second half of "bomb out if playlist construction from XML fails"
[ardour2.git] / libs / ardour / audiosource.cc
blobe674ea0723279c2f5aff2ba5639bc075e8c9e830
1 /*
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.
20 #include <sys/stat.h>
21 #include <unistd.h>
22 #include <fcntl.h>
23 #include <poll.h>
24 #include <float.h>
25 #include <utime.h>
26 #include <cerrno>
27 #include <ctime>
28 #include <cmath>
29 #include <iomanip>
30 #include <fstream>
31 #include <algorithm>
32 #include <vector>
34 #include <glibmm/fileutils.h>
35 #include <glibmm/miscutils.h>
37 #include "pbd/xml++.h"
38 #include "pbd/pthread_utils.h"
40 #include "ardour/audiosource.h"
41 #include "ardour/audio_diskstream.h"
42 #include "ardour/cycle_timer.h"
43 #include "ardour/session.h"
44 #include "ardour/transient_detector.h"
45 #include "ardour/runtime_functions.h"
47 #include "i18n.h"
49 using namespace std;
50 using namespace ARDOUR;
51 using namespace PBD;
53 Glib::StaticMutex AudioSource::_level_buffer_lock = GLIBMM_STATIC_MUTEX_INIT;
54 vector<boost::shared_ptr<Sample> > AudioSource::_mixdown_buffers;
55 vector<boost::shared_ptr<gain_t> > AudioSource::_gain_buffers;
56 size_t AudioSource::_working_buffers_size = 0;
57 bool AudioSource::_build_missing_peakfiles = false;
59 /** true if we want peakfiles (e.g. if we are displaying a GUI) */
60 bool AudioSource::_build_peakfiles = false;
62 #define _FPP 256
64 AudioSource::AudioSource (Session& s, string name)
65 : Source (s, DataType::AUDIO, name)
66 , _length (0)
68 _peaks_built = false;
69 _peak_byte_max = 0;
70 _peakfile_descriptor = 0;
71 _read_data_count = 0;
72 _write_data_count = 0;
73 peak_leftover_cnt = 0;
74 peak_leftover_size = 0;
75 peak_leftovers = 0;
78 AudioSource::AudioSource (Session& s, const XMLNode& node)
79 : Source (s, node)
80 , _length (0)
83 _peaks_built = false;
84 _peak_byte_max = 0;
85 _peakfile_descriptor = 0;
86 _read_data_count = 0;
87 _write_data_count = 0;
88 peak_leftover_cnt = 0;
89 peak_leftover_size = 0;
90 peak_leftovers = 0;
92 if (set_state (node, Stateful::loading_state_version)) {
93 throw failed_constructor();
97 AudioSource::~AudioSource ()
99 /* shouldn't happen but make sure we don't leak file descriptors anyway */
101 if (peak_leftover_cnt) {
102 cerr << "AudioSource destroyed with leftover peak data pending" << endl;
105 delete _peakfile_descriptor;
106 delete [] peak_leftovers;
109 XMLNode&
110 AudioSource::get_state ()
112 XMLNode& node (Source::get_state());
114 if (_captured_for.length()) {
115 node.add_property ("captured-for", _captured_for);
118 return node;
122 AudioSource::set_state (const XMLNode& node, int /*version*/)
124 const XMLProperty* prop;
126 if ((prop = node.property ("captured-for")) != 0) {
127 _captured_for = prop->value();
130 return 0;
133 bool
134 AudioSource::empty () const
136 return _length == 0;
139 framecnt_t
140 AudioSource::length (framepos_t /*pos*/) const
142 return _length;
145 void
146 AudioSource::update_length (framepos_t pos, framecnt_t cnt)
148 if (pos + cnt > _length) {
149 _length = pos + cnt;
154 /***********************************************************************
155 PEAK FILE STUFF
156 ***********************************************************************/
158 /** Checks to see if peaks are ready. If so, we return true. If not, we return false, and
159 * things are set up so that doThisWhenReady is called when the peaks are ready.
160 * A new PBD::ScopedConnection is created for the associated connection and written to
161 * *connect_here_if_not.
163 * @param doThisWhenReady Function to call when peaks are ready (if they are not already).
164 * @param connect_here_if_not Address to write new ScopedConnection to.
165 * @param event_loop Event loop for doThisWhenReady to be called in.
167 bool
168 AudioSource::peaks_ready (boost::function<void()> doThisWhenReady, ScopedConnection** connect_here_if_not, EventLoop* event_loop) const
170 bool ret;
171 Glib::Mutex::Lock lm (_peaks_ready_lock);
173 if (!(ret = _peaks_built)) {
174 *connect_here_if_not = new ScopedConnection;
175 PeaksReady.connect (**connect_here_if_not, MISSING_INVALIDATOR, doThisWhenReady, event_loop);
178 return ret;
181 void
182 AudioSource::touch_peakfile ()
184 struct stat statbuf;
186 if (stat (peakpath.c_str(), &statbuf) != 0 || statbuf.st_size == 0) {
187 return;
190 struct utimbuf tbuf;
192 tbuf.actime = statbuf.st_atime;
193 tbuf.modtime = time ((time_t) 0);
195 utime (peakpath.c_str(), &tbuf);
199 AudioSource::rename_peakfile (string newpath)
201 /* caller must hold _lock */
203 string oldpath = peakpath;
205 if (Glib::file_test (oldpath, Glib::FILE_TEST_EXISTS)) {
206 if (rename (oldpath.c_str(), newpath.c_str()) != 0) {
207 error << string_compose (_("cannot rename peakfile for %1 from %2 to %3 (%4)"), _name, oldpath, newpath, strerror (errno)) << endmsg;
208 return -1;
212 peakpath = newpath;
214 return 0;
218 AudioSource::initialize_peakfile (bool newfile, string audio_path)
220 struct stat statbuf;
222 peakpath = peak_path (audio_path);
224 /* if the peak file should be there, but isn't .... */
226 if (!newfile && !Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
227 peakpath = find_broken_peakfile (peakpath, audio_path);
230 if (stat (peakpath.c_str(), &statbuf)) {
231 if (errno != ENOENT) {
232 /* it exists in the peaks dir, but there is some kind of error */
234 error << string_compose(_("AudioSource: cannot stat peakfile \"%1\""), peakpath) << endmsg;
235 return -1;
238 /* peakfile does not exist */
240 _peaks_built = false;
242 } else {
244 /* we found it in the peaks dir, so check it out */
246 if (statbuf.st_size == 0 || (statbuf.st_size < (off_t) ((length(_timeline_position) / _FPP) * sizeof (PeakData)))) {
247 // empty
248 _peaks_built = false;
249 } else {
250 // Check if the audio file has changed since the peakfile was built.
251 struct stat stat_file;
252 int err = stat (audio_path.c_str(), &stat_file);
254 if (err) {
256 /* no audio path - nested source or we can't
257 read it or ... whatever, use the peakfile as-is.
260 _peaks_built = true;
261 _peak_byte_max = statbuf.st_size;
263 } else {
265 /* allow 6 seconds slop on checking peak vs. file times because of various
266 disk action "races"
269 if (stat_file.st_mtime > statbuf.st_mtime && (stat_file.st_mtime - statbuf.st_mtime > 6)) {
270 _peaks_built = false;
271 _peak_byte_max = 0;
272 } else {
273 _peaks_built = true;
274 _peak_byte_max = statbuf.st_size;
280 if (!newfile && !_peaks_built && _build_missing_peakfiles && _build_peakfiles) {
281 build_peaks_from_scratch ();
284 return 0;
287 framecnt_t
288 AudioSource::read (Sample *dst, framepos_t start, framecnt_t cnt, int /*channel*/) const
290 Glib::Mutex::Lock lm (_lock);
291 return read_unlocked (dst, start, cnt);
294 framecnt_t
295 AudioSource::write (Sample *dst, framecnt_t cnt)
297 Glib::Mutex::Lock lm (_lock);
298 /* any write makes the fill not removable */
299 _flags = Flag (_flags & ~Removable);
300 return write_unlocked (dst, cnt);
304 AudioSource::read_peaks (PeakData *peaks, framecnt_t npeaks, framepos_t start, framecnt_t cnt, double samples_per_visual_peak) const
306 return read_peaks_with_fpp (peaks, npeaks, start, cnt, samples_per_visual_peak, _FPP);
309 /** @param peaks Buffer to write peak data.
310 * @param npeaks Number of peaks to write.
314 AudioSource::read_peaks_with_fpp (PeakData *peaks, framecnt_t npeaks, framepos_t start, framecnt_t cnt,
315 double samples_per_visual_peak, framecnt_t samples_per_file_peak) const
317 Glib::Mutex::Lock lm (_lock);
318 double scale;
319 double expected_peaks;
320 PeakData::PeakDatum xmax;
321 PeakData::PeakDatum xmin;
322 int32_t to_read;
323 uint32_t nread;
324 framecnt_t zero_fill = 0;
325 int ret = -1;
326 PeakData* staging = 0;
327 Sample* raw_staging = 0;
329 FdFileDescriptor* peakfile_descriptor = new FdFileDescriptor (peakpath, false, 0664);
330 int peakfile_fd = -1;
332 expected_peaks = (cnt / (double) samples_per_file_peak);
333 scale = npeaks/expected_peaks;
335 #undef DEBUG_READ_PEAKS
336 #ifdef DEBUG_READ_PEAKS
337 cerr << "======>RP: npeaks = " << npeaks
338 << " start = " << start
339 << " cnt = " << cnt
340 << " len = " << _length
341 << " samples_per_visual_peak =" << samples_per_visual_peak
342 << " expected was " << expected_peaks << " ... scale = " << scale
343 << " PD ptr = " << peaks
344 <<endl;
346 #endif
348 /* fix for near-end-of-file conditions */
350 if (cnt > _length - start) {
351 // cerr << "too close to end @ " << _length << " given " << start << " + " << cnt << endl;
352 cnt = _length - start;
353 framecnt_t old = npeaks;
354 npeaks = min ((framecnt_t) floor (cnt / samples_per_visual_peak), npeaks);
355 zero_fill = old - npeaks;
358 // cerr << "actual npeaks = " << npeaks << " zf = " << zero_fill << endl;
360 if (npeaks == cnt) {
362 #ifdef DEBUG_READ_PEAKS
363 cerr << "RAW DATA\n";
364 #endif
365 /* no scaling at all, just get the sample data and duplicate it for
366 both max and min peak values.
369 Sample* raw_staging = new Sample[cnt];
371 if (read_unlocked (raw_staging, start, cnt) != cnt) {
372 error << _("cannot read sample data for unscaled peak computation") << endmsg;
373 return -1;
376 for (framecnt_t i = 0; i < npeaks; ++i) {
377 peaks[i].max = raw_staging[i];
378 peaks[i].min = raw_staging[i];
381 delete peakfile_descriptor;
382 delete [] raw_staging;
383 return 0;
386 if (scale == 1.0) {
388 off_t first_peak_byte = (start / samples_per_file_peak) * sizeof (PeakData);
390 /* open, read, close */
392 if ((peakfile_fd = peakfile_descriptor->allocate ()) < 0) {
393 error << string_compose(_("AudioSource: cannot open peakpath (a) \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
394 delete peakfile_descriptor;
395 return -1;
398 #ifdef DEBUG_READ_PEAKS
399 cerr << "DIRECT PEAKS\n";
400 #endif
402 nread = ::pread (peakfile_fd, peaks, sizeof (PeakData)* npeaks, first_peak_byte);
403 delete peakfile_descriptor;
405 if (nread != sizeof (PeakData) * npeaks) {
406 cerr << "AudioSource["
407 << _name
408 << "]: cannot read peaks from peakfile! (read only "
409 << nread
410 << " not "
411 << npeaks
412 << "at sample "
413 << start
414 << " = byte "
415 << first_peak_byte
416 << ')'
417 << endl;
418 delete peakfile_descriptor;
419 return -1;
422 if (zero_fill) {
423 memset (&peaks[npeaks], 0, sizeof (PeakData) * zero_fill);
426 delete peakfile_descriptor;
427 return 0;
431 framecnt_t tnp;
433 if (scale < 1.0) {
435 #ifdef DEBUG_READ_PEAKS
436 cerr << "DOWNSAMPLE\n";
437 #endif
438 /* the caller wants:
440 - more frames-per-peak (lower resolution) than the peakfile, or to put it another way,
441 - less peaks than the peakfile holds for the same range
443 So, read a block into a staging area, and then downsample from there.
445 to avoid confusion, I'll refer to the requested peaks as visual_peaks and the peakfile peaks as stored_peaks
448 const framecnt_t chunksize = (framecnt_t) min (expected_peaks, 65536.0);
450 staging = new PeakData[chunksize];
452 /* compute the rounded up frame position */
454 framepos_t current_frame = start;
455 framepos_t current_stored_peak = (framepos_t) ceil (current_frame / (double) samples_per_file_peak);
456 framepos_t next_visual_peak = (framepos_t) ceil (current_frame / samples_per_visual_peak);
457 double next_visual_peak_frame = next_visual_peak * samples_per_visual_peak;
458 framepos_t stored_peak_before_next_visual_peak = (framepos_t) next_visual_peak_frame / samples_per_file_peak;
459 framecnt_t nvisual_peaks = 0;
460 framecnt_t stored_peaks_read = 0;
461 framecnt_t i = 0;
463 /* handle the case where the initial visual peak is on a pixel boundary */
465 current_stored_peak = min (current_stored_peak, stored_peak_before_next_visual_peak);
467 /* open ... close during out: handling */
469 if ((peakfile_fd = peakfile_descriptor->allocate ()) < 0) {
470 error << string_compose(_("AudioSource: cannot open peakpath (b) \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
471 delete peakfile_descriptor;
472 delete [] staging;
473 return 0;
476 while (nvisual_peaks < npeaks) {
478 if (i == stored_peaks_read) {
480 uint32_t start_byte = current_stored_peak * sizeof(PeakData);
481 tnp = min ((framecnt_t)(_length/samples_per_file_peak - current_stored_peak), (framecnt_t) expected_peaks);
482 to_read = min (chunksize, tnp);
484 #ifdef DEBUG_READ_PEAKS
485 cerr << "read " << sizeof (PeakData) * to_read << " from peakfile @ " << start_byte << endl;
486 #endif
488 if ((nread = ::pread (peakfile_fd, staging, sizeof (PeakData) * to_read, start_byte))
489 != sizeof (PeakData) * to_read) {
491 off_t fend = lseek (peakfile_fd, 0, SEEK_END);
493 cerr << "AudioSource["
494 << _name
495 << "]: cannot read peak data from peakfile ("
496 << (nread / sizeof(PeakData))
497 << " peaks instead of "
498 << to_read
499 << ") ("
500 << strerror (errno)
501 << ')'
502 << " at start_byte = " << start_byte
503 << " _length = " << _length << " versus len = " << fend
504 << " expected maxpeaks = " << (_length - current_frame)/samples_per_file_peak
505 << " npeaks was " << npeaks
506 << endl;
507 goto out;
510 i = 0;
511 stored_peaks_read = nread / sizeof(PeakData);
514 xmax = -1.0;
515 xmin = 1.0;
517 while ((i < stored_peaks_read) && (current_stored_peak <= stored_peak_before_next_visual_peak)) {
519 xmax = max (xmax, staging[i].max);
520 xmin = min (xmin, staging[i].min);
521 ++i;
522 ++current_stored_peak;
523 --expected_peaks;
526 peaks[nvisual_peaks].max = xmax;
527 peaks[nvisual_peaks].min = xmin;
528 ++nvisual_peaks;
529 ++next_visual_peak;
531 //next_visual_peak_frame = min ((next_visual_peak * samples_per_visual_peak), (next_visual_peak_frame+samples_per_visual_peak) );
532 next_visual_peak_frame = min ((double) start+cnt, (next_visual_peak_frame+samples_per_visual_peak) );
533 stored_peak_before_next_visual_peak = (uint32_t) next_visual_peak_frame / samples_per_file_peak;
536 if (zero_fill) {
537 memset (&peaks[npeaks], 0, sizeof (PeakData) * zero_fill);
540 ret = 0;
542 } else {
544 #ifdef DEBUG_READ_PEAKS
545 cerr << "UPSAMPLE\n";
546 #endif
547 /* the caller wants
549 - less frames-per-peak (more resolution)
550 - more peaks than stored in the Peakfile
552 So, fetch data from the raw source, and generate peak
553 data on the fly.
556 framecnt_t frames_read = 0;
557 framepos_t current_frame = start;
558 framecnt_t i = 0;
559 framecnt_t nvisual_peaks = 0;
560 framecnt_t chunksize = (framecnt_t) min (cnt, (framecnt_t) 4096);
561 raw_staging = new Sample[chunksize];
563 framepos_t frame_pos = start;
564 double pixel_pos = floor (frame_pos / samples_per_visual_peak);
565 double next_pixel_pos = ceil (frame_pos / samples_per_visual_peak);
566 double pixels_per_frame = 1.0 / samples_per_visual_peak;
568 xmin = 1.0;
569 xmax = -1.0;
571 while (nvisual_peaks < npeaks) {
573 if (i == frames_read) {
575 to_read = min (chunksize, (framecnt_t)(_length - current_frame));
577 if (current_frame >= _length) {
579 /* hmm, error condition - we've reached the end of the file
580 without generating all the peak data. cook up a zero-filled
581 data buffer and then use it. this is simpler than
582 adjusting zero_fill and npeaks and then breaking out of
583 this loop early
586 memset (raw_staging, 0, sizeof (Sample) * chunksize);
588 } else {
590 to_read = min (chunksize, (_length - current_frame));
593 if ((frames_read = read_unlocked (raw_staging, current_frame, to_read)) == 0) {
594 error << string_compose(_("AudioSource[%1]: peak read - cannot read %2 samples at offset %3 of %4 (%5)"),
595 _name, to_read, current_frame, _length, strerror (errno))
596 << endmsg;
597 goto out;
601 i = 0;
604 xmax = max (xmax, raw_staging[i]);
605 xmin = min (xmin, raw_staging[i]);
606 ++i;
607 ++current_frame;
608 pixel_pos += pixels_per_frame;
610 if (pixel_pos >= next_pixel_pos) {
612 peaks[nvisual_peaks].max = xmax;
613 peaks[nvisual_peaks].min = xmin;
614 ++nvisual_peaks;
615 xmin = 1.0;
616 xmax = -1.0;
618 next_pixel_pos = ceil (pixel_pos + 0.5);
622 if (zero_fill) {
623 memset (&peaks[npeaks], 0, sizeof (PeakData) * zero_fill);
626 ret = 0;
629 out:
630 delete peakfile_descriptor;
632 delete [] staging;
633 delete [] raw_staging;
635 #ifdef DEBUG_READ_PEAKS
636 cerr << "RP DONE\n";
637 #endif
639 return ret;
642 #undef DEBUG_PEAK_BUILD
645 AudioSource::build_peaks_from_scratch ()
647 Sample* buf = 0;
649 const framecnt_t bufsize = 65536; // 256kB per disk read for mono data is about ideal
651 int ret = -1;
654 /* hold lock while building peaks */
656 Glib::Mutex::Lock lp (_lock);
658 if (prepare_for_peakfile_writes ()) {
659 goto out;
662 framecnt_t current_frame = 0;
663 framecnt_t cnt = _length;
665 _peaks_built = false;
666 buf = new Sample[bufsize];
668 while (cnt) {
670 framecnt_t frames_to_read = min (bufsize, cnt);
671 framecnt_t frames_read;
673 if ((frames_read = read_unlocked (buf, current_frame, frames_to_read)) != frames_to_read) {
674 error << string_compose(_("%1: could not write read raw data for peak computation (%2)"), _name, strerror (errno)) << endmsg;
675 done_with_peakfile_writes (false);
676 goto out;
679 if (compute_and_write_peaks (buf, current_frame, frames_read, true, false, _FPP)) {
680 break;
683 current_frame += frames_read;
684 cnt -= frames_read;
687 if (cnt == 0) {
688 /* success */
689 truncate_peakfile();
692 done_with_peakfile_writes ((cnt == 0));
693 if (cnt == 0) {
694 ret = 0;
698 out:
699 if (ret) {
700 unlink (peakpath.c_str());
703 delete [] buf;
705 return ret;
709 AudioSource::prepare_for_peakfile_writes ()
711 _peakfile_descriptor = new FdFileDescriptor (peakpath, true, 0664);
712 if ((_peakfile_fd = _peakfile_descriptor->allocate()) < 0) {
713 error << string_compose(_("AudioSource: cannot open peakpath (c) \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
714 return -1;
716 return 0;
719 void
720 AudioSource::done_with_peakfile_writes (bool done)
722 if (peak_leftover_cnt) {
723 compute_and_write_peaks (0, 0, 0, true, false, _FPP);
726 if (done) {
727 Glib::Mutex::Lock lm (_peaks_ready_lock);
728 _peaks_built = true;
729 PeaksReady (); /* EMIT SIGNAL */
732 delete _peakfile_descriptor;
733 _peakfile_descriptor = 0;
736 /** @param first_frame Offset from the source start of the first frame to process */
738 AudioSource::compute_and_write_peaks (Sample* buf, framecnt_t first_frame, framecnt_t cnt,
739 bool force, bool intermediate_peaks_ready)
741 return compute_and_write_peaks (buf, first_frame, cnt, force, intermediate_peaks_ready, _FPP);
745 AudioSource::compute_and_write_peaks (Sample* buf, framecnt_t first_frame, framecnt_t cnt,
746 bool force, bool intermediate_peaks_ready, framecnt_t fpp)
748 Sample* buf2 = 0;
749 framecnt_t to_do;
750 uint32_t peaks_computed;
751 PeakData* peakbuf = 0;
752 int ret = -1;
753 framepos_t current_frame;
754 framecnt_t frames_done;
755 const size_t blocksize = (128 * 1024);
756 off_t first_peak_byte;
758 if (_peakfile_descriptor == 0) {
759 prepare_for_peakfile_writes ();
762 restart:
763 if (peak_leftover_cnt) {
765 if (first_frame != peak_leftover_frame + peak_leftover_cnt) {
767 /* uh-oh, ::seek() since the last ::compute_and_write_peaks(),
768 and we have leftovers. flush a single peak (since the leftovers
769 never represent more than that, and restart.
772 PeakData x;
774 x.min = peak_leftovers[0];
775 x.max = peak_leftovers[0];
777 off_t byte = (peak_leftover_frame / fpp) * sizeof (PeakData);
779 if (::pwrite (_peakfile_fd, &x, sizeof (PeakData), byte) != sizeof (PeakData)) {
780 error << string_compose(_("%1: could not write peak file data (%2)"), _name, strerror (errno)) << endmsg;
781 goto out;
784 _peak_byte_max = max (_peak_byte_max, (off_t) (byte + sizeof(PeakData)));
787 Glib::Mutex::Lock lm (_peaks_ready_lock);
788 PeakRangeReady (peak_leftover_frame, peak_leftover_cnt); /* EMIT SIGNAL */
789 if (intermediate_peaks_ready) {
790 PeaksReady (); /* EMIT SIGNAL */
794 /* left overs are done */
796 peak_leftover_cnt = 0;
797 goto restart;
800 /* else ... had leftovers, but they immediately preceed the new data, so just
801 merge them and compute.
804 /* make a new contiguous buffer containing leftovers and the new stuff */
806 to_do = cnt + peak_leftover_cnt;
807 buf2 = new Sample[to_do];
809 /* the remnants */
810 memcpy (buf2, peak_leftovers, peak_leftover_cnt * sizeof (Sample));
812 /* the new stuff */
813 memcpy (buf2+peak_leftover_cnt, buf, cnt * sizeof (Sample));
815 /* no more leftovers */
816 peak_leftover_cnt = 0;
818 /* use the temporary buffer */
819 buf = buf2;
821 /* make sure that when we write into the peakfile, we startup where we left off */
823 first_frame = peak_leftover_frame;
825 } else {
826 to_do = cnt;
829 peakbuf = new PeakData[(to_do/fpp)+1];
830 peaks_computed = 0;
831 current_frame = first_frame;
832 frames_done = 0;
834 while (to_do) {
836 /* if some frames were passed in (i.e. we're not flushing leftovers)
837 and there are less than fpp to do, save them till
838 next time
841 if (force && (to_do < fpp)) {
842 /* keep the left overs around for next time */
844 if (peak_leftover_size < to_do) {
845 delete [] peak_leftovers;
846 peak_leftovers = new Sample[to_do];
847 peak_leftover_size = to_do;
849 memcpy (peak_leftovers, buf, to_do * sizeof (Sample));
850 peak_leftover_cnt = to_do;
851 peak_leftover_frame = current_frame;
853 /* done for now */
855 break;
858 framecnt_t this_time = min (fpp, to_do);
860 peakbuf[peaks_computed].max = buf[0];
861 peakbuf[peaks_computed].min = buf[0];
863 ARDOUR::find_peaks (buf+1, this_time-1, &peakbuf[peaks_computed].min, &peakbuf[peaks_computed].max);
865 peaks_computed++;
866 buf += this_time;
867 to_do -= this_time;
868 frames_done += this_time;
869 current_frame += this_time;
872 first_peak_byte = (first_frame / fpp) * sizeof (PeakData);
874 if (can_truncate_peaks()) {
876 /* on some filesystems (ext3, at least) this helps to reduce fragmentation of
877 the peakfiles. its not guaranteed to do so, and even on ext3 (as of december 2006)
878 it does not cause single-extent allocation even for peakfiles of
879 less than BLOCKSIZE bytes. only call ftruncate if we'll make the file larger.
882 off_t endpos = lseek (_peakfile_fd, 0, SEEK_END);
883 off_t target_length = blocksize * ((first_peak_byte + blocksize + 1) / blocksize);
885 if (endpos < target_length) {
886 (void) ftruncate (_peakfile_fd, target_length);
887 /* error doesn't actually matter though, so continue on without testing */
891 if (::pwrite (_peakfile_fd, peakbuf, sizeof (PeakData) * peaks_computed, first_peak_byte) != (ssize_t) (sizeof (PeakData) * peaks_computed)) {
892 error << string_compose(_("%1: could not write peak file data (%2)"), _name, strerror (errno)) << endmsg;
893 goto out;
896 _peak_byte_max = max (_peak_byte_max, (off_t) (first_peak_byte + sizeof(PeakData)*peaks_computed));
898 if (frames_done) {
899 Glib::Mutex::Lock lm (_peaks_ready_lock);
900 PeakRangeReady (first_frame, frames_done); /* EMIT SIGNAL */
901 if (intermediate_peaks_ready) {
902 PeaksReady (); /* EMIT SIGNAL */
906 ret = 0;
908 out:
909 delete [] peakbuf;
910 delete [] buf2;
912 return ret;
915 void
916 AudioSource::truncate_peakfile ()
918 if (_peakfile_descriptor == 0) {
919 error << string_compose (_("programming error: %1"), "AudioSource::truncate_peakfile() called without open peakfile descriptor")
920 << endmsg;
921 return;
924 /* truncate the peakfile down to its natural length if necessary */
926 off_t end = lseek (_peakfile_fd, 0, SEEK_END);
928 if (end > _peak_byte_max) {
929 (void) ftruncate (_peakfile_fd, _peak_byte_max);
933 framecnt_t
934 AudioSource::available_peaks (double zoom_factor) const
936 if (zoom_factor < _FPP) {
937 return length(_timeline_position); // peak data will come from the audio file
940 /* peak data comes from peakfile, but the filesize might not represent
941 the valid data due to ftruncate optimizations, so use _peak_byte_max state.
942 XXX - there might be some atomicity issues here, we should probably add a lock,
943 but _peak_byte_max only monotonically increases after initialization.
946 off_t end = _peak_byte_max;
948 return (end/sizeof(PeakData)) * _FPP;
951 void
952 AudioSource::dec_read_data_count (framecnt_t cnt)
954 uint32_t val = cnt * sizeof (Sample);
956 if (val < _read_data_count) {
957 _read_data_count -= val;
958 } else {
959 _read_data_count = 0;
963 void
964 AudioSource::mark_streaming_write_completed ()
966 Glib::Mutex::Lock lm (_peaks_ready_lock);
968 if (_peaks_built) {
969 PeaksReady (); /* EMIT SIGNAL */
973 void
974 AudioSource::allocate_working_buffers (framecnt_t framerate)
976 Glib::Mutex::Lock lm (_level_buffer_lock);
979 /* Note: we don't need any buffers allocated until
980 a level 1 audiosource is created, at which
981 time we'll call ::ensure_buffers_for_level()
982 with the right value and do the right thing.
985 if (!_mixdown_buffers.empty()) {
986 ensure_buffers_for_level_locked ( _mixdown_buffers.size(), framerate);
990 void
991 AudioSource::ensure_buffers_for_level (uint32_t level, framecnt_t frame_rate)
993 Glib::Mutex::Lock lm (_level_buffer_lock);
994 ensure_buffers_for_level_locked (level, frame_rate);
997 void
998 AudioSource::ensure_buffers_for_level_locked (uint32_t level, framecnt_t frame_rate)
1000 framecnt_t nframes = (framecnt_t) floor (Config->get_audio_playback_buffer_seconds() * frame_rate);
1002 _mixdown_buffers.clear ();
1003 _gain_buffers.clear ();
1005 while (_mixdown_buffers.size() < level) {
1006 _mixdown_buffers.push_back (boost::shared_ptr<Sample> (new Sample[nframes]));
1007 _gain_buffers.push_back (boost::shared_ptr<gain_t> (new gain_t[nframes]));