2 Copyright (C) 2000 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 $Id: source.cc 404 2006-03-17 17:39:21Z pauld $
33 #include <pbd/xml++.h>
34 #include <pbd/pthread_utils.h>
36 #include <ardour/audiosource.h>
41 using namespace ARDOUR;
44 pthread_t AudioSource::peak_thread;
45 bool AudioSource::have_peak_thread = false;
46 vector<AudioSource*> AudioSource::pending_peak_sources;
47 Glib::Mutex* AudioSource::pending_peak_sources_lock = 0;
48 int AudioSource::peak_request_pipe[2];
50 bool AudioSource::_build_missing_peakfiles = false;
51 bool AudioSource::_build_peakfiles = false;
53 AudioSource::AudioSource (Session& s, string name)
54 : Source (s, name, DataType::AUDIO)
56 if (pending_peak_sources_lock == 0) {
57 pending_peak_sources_lock = new Glib::Mutex;
61 next_peak_clear_should_notify = true;
63 _write_data_count = 0;
66 AudioSource::AudioSource (Session& s, const XMLNode& node)
69 if (pending_peak_sources_lock == 0) {
70 pending_peak_sources_lock = new Glib::Mutex;
74 next_peak_clear_should_notify = true;
76 _write_data_count = 0;
78 if (set_state (node)) {
79 throw failed_constructor();
83 AudioSource::~AudioSource ()
88 AudioSource::get_state ()
90 XMLNode& node (Source::get_state());
92 if (_captured_for.length()) {
93 node.add_property ("captured-for", _captured_for);
100 AudioSource::set_state (const XMLNode& node)
102 const XMLProperty* prop;
104 Source::set_state (node);
106 if ((prop = node.property ("captured-for")) != 0) {
107 _captured_for = prop->value();
113 /***********************************************************************
115 ***********************************************************************/
118 AudioSource::peak_thread_work (void* arg)
120 PBD::ThreadCreated (pthread_self(), X_("Peak"));
121 struct pollfd pfd[1];
123 if (pending_peak_sources_lock == 0) {
124 pending_peak_sources_lock = new Glib::Mutex;
127 Glib::Mutex::Lock lm (*pending_peak_sources_lock);
131 pfd[0].fd = peak_request_pipe[0];
132 pfd[0].events = POLLIN|POLLERR|POLLHUP;
134 pending_peak_sources_lock->unlock ();
136 if (poll (pfd, 1, -1) < 0) {
138 if (errno == EINTR) {
139 pending_peak_sources_lock->lock ();
143 error << string_compose (_("poll on peak request pipe failed (%1)"),
149 if (pfd[0].revents & ~POLLIN) {
150 error << _("Error on peak thread request pipe") << endmsg;
154 if (pfd[0].revents & POLLIN) {
158 /* empty the pipe of all current requests */
161 size_t nread = ::read (peak_request_pipe[0], &req, sizeof (req));
164 switch ((PeakRequest::Type) req) {
166 case PeakRequest::Build:
169 case PeakRequest::Quit:
170 pthread_exit_pbd (0);
178 } else if (nread == 0) {
180 } else if (errno == EAGAIN) {
183 fatal << _("Error reading from peak request pipe") << endmsg;
189 pending_peak_sources_lock->lock ();
191 while (!pending_peak_sources.empty()) {
193 AudioSource* s = pending_peak_sources.front();
194 pending_peak_sources.erase (pending_peak_sources.begin());
196 pending_peak_sources_lock->unlock ();
198 pending_peak_sources_lock->lock ();
202 pthread_exit_pbd (0);
208 AudioSource::start_peak_thread ()
210 if (!_build_peakfiles) {
214 if (pipe (peak_request_pipe)) {
215 error << string_compose(_("Cannot create transport request signal pipe (%1)"), strerror (errno)) << endmsg;
219 if (fcntl (peak_request_pipe[0], F_SETFL, O_NONBLOCK)) {
220 error << string_compose(_("UI: cannot set O_NONBLOCK on peak request pipe (%1)"), strerror (errno)) << endmsg;
224 if (fcntl (peak_request_pipe[1], F_SETFL, O_NONBLOCK)) {
225 error << string_compose(_("UI: cannot set O_NONBLOCK on peak request pipe (%1)"), strerror (errno)) << endmsg;
229 if (pthread_create_and_store ("peak file builder", &peak_thread, 0, peak_thread_work, 0)) {
230 error << _("AudioSource: could not create peak thread") << endmsg;
234 have_peak_thread = true;
239 AudioSource::stop_peak_thread ()
241 if (!have_peak_thread) {
247 char c = (char) PeakRequest::Quit;
248 ::write (peak_request_pipe[1], &c, 1);
249 pthread_join (peak_thread, &status);
253 AudioSource::queue_for_peaks (AudioSource* source)
255 if (have_peak_thread) {
257 Glib::Mutex::Lock lm (*pending_peak_sources_lock);
259 source->next_peak_clear_should_notify = true;
261 if (find (pending_peak_sources.begin(),
262 pending_peak_sources.end(),
263 source) == pending_peak_sources.end()) {
264 pending_peak_sources.push_back (source);
267 char c = (char) PeakRequest::Build;
268 ::write (peak_request_pipe[1], &c, 1);
272 void AudioSource::clear_queue_for_peaks ()
274 /* this is done to cancel a group of running peak builds */
275 if (have_peak_thread) {
276 Glib::Mutex::Lock lm (*pending_peak_sources_lock);
277 pending_peak_sources.clear ();
283 AudioSource::peaks_ready (sigc::slot<void> the_slot, sigc::connection& conn) const
286 Glib::Mutex::Lock lm (_lock);
288 /* check to see if the peak data is ready. if not
289 connect the slot while still holding the lock.
292 if (!(ret = _peaks_built)) {
293 conn = PeaksReady.connect (the_slot);
300 AudioSource::rename_peakfile (string newpath)
302 /* caller must hold _lock */
304 string oldpath = peakpath;
306 if (access (oldpath.c_str(), F_OK) == 0) {
307 if (rename (oldpath.c_str(), newpath.c_str()) != 0) {
308 error << string_compose (_("cannot rename peakfile for %1 from %2 to %3 (%4)"), _name, oldpath, newpath, strerror (errno)) << endmsg;
319 AudioSource::initialize_peakfile (bool newfile, string audio_path)
323 peakpath = peak_path (audio_path);
325 /* Nasty band-aid for older sessions that were created before we
326 used libsndfile for all audio files.
329 if (!newfile && access (peakpath.c_str(), R_OK) != 0) {
330 string str = old_peak_path (audio_path);
331 if (access (str.c_str(), R_OK) == 0) {
338 if (!_build_peakfiles) {
342 _peaks_built = false;
346 if (stat (peakpath.c_str(), &statbuf)) {
347 if (errno != ENOENT) {
348 /* it exists in the peaks dir, but there is some kind of error */
350 error << string_compose(_("AudioSource: cannot stat peakfile \"%1\""), peakpath) << endmsg;
356 /* we found it in the peaks dir */
359 if (statbuf.st_size == 0) {
360 _peaks_built = false;
362 // Check if the audio file has changed since the peakfile was built.
363 struct stat stat_file;
364 int err = stat (audio_path.c_str(), &stat_file);
366 if (!err && stat_file.st_mtime > statbuf.st_mtime){
367 _peaks_built = false;
374 if (!newfile && !_peaks_built && _build_missing_peakfiles && _build_peakfiles) {
375 build_peaks_from_scratch ();
382 AudioSource::read (Sample *dst, jack_nframes_t start, jack_nframes_t cnt) const
384 Glib::Mutex::Lock lm (_lock);
385 return read_unlocked (dst, start, cnt);
389 AudioSource::write (Sample *dst, jack_nframes_t cnt)
391 Glib::Mutex::Lock lm (_lock);
392 return write_unlocked (dst, cnt);
396 AudioSource::read_peaks (PeakData *peaks, jack_nframes_t npeaks, jack_nframes_t start, jack_nframes_t cnt, double samples_per_visual_peak) const
398 Glib::Mutex::Lock lm (_lock);
400 double expected_peaks;
401 PeakData::PeakDatum xmax;
402 PeakData::PeakDatum xmin;
405 jack_nframes_t zero_fill = 0;
407 PeakData* staging = 0;
408 Sample* raw_staging = 0;
411 expected_peaks = (cnt / (double) frames_per_peak);
412 scale = npeaks/expected_peaks;
415 cerr << "======>RP: npeaks = " << npeaks
416 << " start = " << start
418 << " len = " << _length
419 << " samples_per_visual_peak =" << samples_per_visual_peak
420 << " expected was " << expected_peaks << " ... scale = " << scale
421 << " PD ptr = " << peaks
426 /* fix for near-end-of-file conditions */
428 if (cnt > _length - start) {
429 // cerr << "too close to end @ " << _length << " given " << start << " + " << cnt << endl;
430 cnt = _length - start;
431 jack_nframes_t old = npeaks;
432 npeaks = min ((jack_nframes_t) floor (cnt / samples_per_visual_peak), npeaks);
433 zero_fill = old - npeaks;
436 // cerr << "actual npeaks = " << npeaks << " zf = " << zero_fill << endl;
440 // cerr << "RAW DATA\n";
442 /* no scaling at all, just get the sample data and duplicate it for
443 both max and min peak values.
446 Sample* raw_staging = new Sample[cnt];
448 if (read_unlocked (raw_staging, start, cnt) != cnt) {
449 error << _("cannot read sample data for unscaled peak computation") << endmsg;
453 for (jack_nframes_t i = 0; i < npeaks; ++i) {
454 peaks[i].max = raw_staging[i];
455 peaks[i].min = raw_staging[i];
458 delete [] raw_staging;
464 off_t first_peak_byte = (start / frames_per_peak) * sizeof (PeakData);
466 /* open, read, close */
468 if ((peakfile = ::open (peakpath.c_str(), O_RDWR|O_CREAT, 0664)) < 0) {
469 error << string_compose(_("AudioSource: cannot open peakpath \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
473 // cerr << "DIRECT PEAKS\n";
475 nread = ::pread (peakfile, peaks, sizeof (PeakData)* npeaks, first_peak_byte);
478 if (nread != sizeof (PeakData) * npeaks) {
479 cerr << "AudioSource["
481 << "]: cannot read peaks from peakfile! (read only "
495 memset (&peaks[npeaks], 0, sizeof (PeakData) * zero_fill);
506 // cerr << "DOWNSAMPLE\n";
510 - more frames-per-peak (lower resolution) than the peakfile, or to put it another way,
511 - less peaks than the peakfile holds for the same range
513 So, read a block into a staging area, and then downsample from there.
515 to avoid confusion, I'll refer to the requested peaks as visual_peaks and the peakfile peaks as stored_peaks
518 const uint32_t chunksize = (uint32_t) min (expected_peaks, 4096.0);
520 staging = new PeakData[chunksize];
522 /* compute the rounded up frame position */
524 jack_nframes_t current_frame = start;
525 jack_nframes_t current_stored_peak = (jack_nframes_t) ceil (current_frame / (double) frames_per_peak);
526 uint32_t next_visual_peak = (uint32_t) ceil (current_frame / samples_per_visual_peak);
527 double next_visual_peak_frame = next_visual_peak * samples_per_visual_peak;
528 uint32_t stored_peak_before_next_visual_peak = (jack_nframes_t) next_visual_peak_frame / frames_per_peak;
529 uint32_t nvisual_peaks = 0;
530 uint32_t stored_peaks_read = 0;
533 /* handle the case where the initial visual peak is on a pixel boundary */
535 current_stored_peak = min (current_stored_peak, stored_peak_before_next_visual_peak);
537 /* open ... close during out: handling */
539 if ((peakfile = ::open (peakpath.c_str(), O_RDWR|O_CREAT, 0664)) < 0) {
540 error << string_compose(_("AudioSource: cannot open peakpath \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
544 while (nvisual_peaks < npeaks) {
546 if (i == stored_peaks_read) {
548 uint32_t start_byte = current_stored_peak * sizeof(PeakData);
549 tnp = min ((_length/frames_per_peak - current_stored_peak), (jack_nframes_t) expected_peaks);
550 to_read = min (chunksize, tnp);
552 off_t fend = lseek (peakfile, 0, SEEK_END);
554 if ((nread = ::pread (peakfile, staging, sizeof (PeakData) * to_read, start_byte))
555 != sizeof (PeakData) * to_read) {
556 cerr << "AudioSource["
558 << "]: cannot read peak data from peakfile ("
559 << (nread / sizeof(PeakData))
560 << " peaks instead of "
565 << " at start_byte = " << start_byte
566 << " _length = " << _length << " versus len = " << fend
567 << " expected maxpeaks = " << (_length - current_frame)/frames_per_peak
568 << " npeaks was " << npeaks
574 stored_peaks_read = nread / sizeof(PeakData);
580 while ((i < stored_peaks_read) && (current_stored_peak <= stored_peak_before_next_visual_peak)) {
582 xmax = max (xmax, staging[i].max);
583 xmin = min (xmin, staging[i].min);
585 ++current_stored_peak;
589 peaks[nvisual_peaks].max = xmax;
590 peaks[nvisual_peaks].min = xmin;
594 //next_visual_peak_frame = min ((next_visual_peak * samples_per_visual_peak), (next_visual_peak_frame+samples_per_visual_peak) );
595 next_visual_peak_frame = min ((double) start+cnt, (next_visual_peak_frame+samples_per_visual_peak) );
596 stored_peak_before_next_visual_peak = (uint32_t) next_visual_peak_frame / frames_per_peak;
600 memset (&peaks[npeaks], 0, sizeof (PeakData) * zero_fill);
607 // cerr << "UPSAMPLE\n";
611 - less frames-per-peak (more resolution)
612 - more peaks than stored in the Peakfile
614 So, fetch data from the raw source, and generate peak
618 jack_nframes_t frames_read = 0;
619 jack_nframes_t current_frame = start;
620 jack_nframes_t i = 0;
621 jack_nframes_t nvisual_peaks = 0;
622 jack_nframes_t chunksize = (jack_nframes_t) min (cnt, (jack_nframes_t) 4096);
623 raw_staging = new Sample[chunksize];
625 jack_nframes_t frame_pos = start;
626 double pixel_pos = floor (frame_pos / samples_per_visual_peak);
627 double next_pixel_pos = ceil (frame_pos / samples_per_visual_peak);
628 double pixels_per_frame = 1.0 / samples_per_visual_peak;
633 while (nvisual_peaks < npeaks) {
635 if (i == frames_read) {
637 to_read = min (chunksize, (_length - current_frame));
639 if ((frames_read = read_unlocked (raw_staging, current_frame, to_read)) == 0) {
640 error << string_compose(_("AudioSource[%1]: peak read - cannot read %2 samples at offset %3")
641 , _name, to_read, current_frame)
649 xmax = max (xmax, raw_staging[i]);
650 xmin = min (xmin, raw_staging[i]);
653 pixel_pos += pixels_per_frame;
655 if (pixel_pos >= next_pixel_pos) {
657 peaks[nvisual_peaks].max = xmax;
658 peaks[nvisual_peaks].min = xmin;
663 next_pixel_pos = ceil (pixel_pos + 0.5);
668 memset (&peaks[npeaks], 0, sizeof (PeakData) * zero_fill);
684 delete [] raw_staging;
690 #undef DEBUG_PEAK_BUILD
693 AudioSource::build_peaks ()
695 vector<PeakBuildRecord*> built;
697 bool pr_signal = false;
698 list<PeakBuildRecord*> copy;
701 Glib::Mutex::Lock lm (_lock);
702 copy = pending_peak_builds;
703 pending_peak_builds.clear ();
706 #ifdef DEBUG_PEAK_BUILD
707 cerr << "build peaks with " << copy.size() << " requests pending\n";
710 for (list<PeakBuildRecord *>::iterator i = copy.begin(); i != copy.end(); ++i) {
712 if ((status = do_build_peak ((*i)->frame, (*i)->cnt)) != 0) {
713 unlink (peakpath.c_str());
716 built.push_back (new PeakBuildRecord (*(*i)));
721 Glib::Mutex::Lock lm (_lock);
726 if (next_peak_clear_should_notify) {
727 next_peak_clear_should_notify = false;
734 for (vector<PeakBuildRecord *>::iterator i = built.begin(); i != built.end(); ++i) {
735 PeakRangeReady ((*i)->frame, (*i)->cnt); /* EMIT SIGNAL */
740 PeaksReady (); /* EMIT SIGNAL */
748 AudioSource::do_build_peak (jack_nframes_t first_frame, jack_nframes_t cnt)
750 jack_nframes_t current_frame;
751 Sample buf[frames_per_peak];
755 jack_nframes_t frames_read;
756 jack_nframes_t frames_to_read;
757 off_t first_peak_byte;
761 #ifdef DEBUG_PEAK_BUILD
762 cerr << pthread_self() << ": " << _name << ": building peaks for " << first_frame << " to " << first_frame + cnt - 1 << endl;
765 first_peak_byte = (first_frame / frames_per_peak) * sizeof (PeakData);
767 #ifdef DEBUG_PEAK_BUILD
768 cerr << "seeking to " << first_peak_byte << " before writing new peak data\n";
771 current_frame = first_frame;
772 peakbuf = new PeakData[(cnt/frames_per_peak)+1];
775 if ((peakfile = ::open (peakpath.c_str(), O_RDWR|O_CREAT, 0664)) < 0) {
776 error << string_compose(_("AudioSource: cannot open peakpath \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
782 frames_to_read = min (frames_per_peak, cnt);
784 /* lock for every read */
786 if ((frames_read = read (buf, current_frame, frames_to_read)) != frames_to_read) {
787 error << string_compose(_("%1: could not write read raw data for peak computation (%2)"), _name, strerror (errno)) << endmsg;
794 for (jack_nframes_t n = 1; n < frames_read; ++n) {
795 xmax = max (xmax, buf[n]);
796 xmin = min (xmin, buf[n]);
798 // if (current_frame < frames_read) {
799 // cerr << "sample = " << buf[n] << " max = " << xmax << " min = " << xmin << " max of 2 = " << max (xmax, buf[n]) << endl;
803 peakbuf[peaki].max = xmax;
804 peakbuf[peaki].min = xmin;
807 current_frame += frames_read;
811 if (::pwrite (peakfile, peakbuf, sizeof (PeakData) * peaki, first_peak_byte) != (ssize_t) (sizeof (PeakData) * peaki)) {
812 error << string_compose(_("%1: could not write peak file data (%2)"), _name, strerror (errno)) << endmsg;
827 AudioSource::build_peaks_from_scratch ()
829 Glib::Mutex::Lock lp (_lock);
831 next_peak_clear_should_notify = true;
832 pending_peak_builds.push_back (new PeakBuildRecord (0, _length));
833 queue_for_peaks (this);
837 AudioSource::file_changed (string path)
839 struct stat stat_file;
840 struct stat stat_peak;
842 int e1 = stat (path.c_str(), &stat_file);
843 int e2 = stat (peak_path(path).c_str(), &stat_peak);
845 if (!e1 && !e2 && stat_file.st_mtime > stat_peak.st_mtime){
853 AudioSource::available_peaks (double zoom_factor) const
858 if (zoom_factor < frames_per_peak) {
859 return length(); // peak data will come from the audio file
862 /* peak data comes from peakfile */
864 if ((peakfile = ::open (peakpath.c_str(), O_RDONLY)) < 0) {
865 error << string_compose(_("AudioSource: cannot open peakpath \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
870 Glib::Mutex::Lock lm (_lock);
871 end = lseek (peakfile, 0, SEEK_END);
876 return (end/sizeof(PeakData)) * frames_per_peak;