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.
21 #include <sys/utime.h>
38 #include <glib/gstdio.h>
40 #include <boost/scoped_array.hpp>
41 #include <boost/scoped_ptr.hpp>
43 #include <glibmm/fileutils.h>
44 #include <glibmm/miscutils.h>
46 #include "pbd/xml++.h"
48 #include "ardour/audiosource.h"
49 #include "ardour/rc_configuration.h"
50 #include "ardour/runtime_functions.h"
54 #include "ardour/debug.h"
57 using namespace ARDOUR;
60 Glib::Threads::Mutex AudioSource::_level_buffer_lock;
61 vector<boost::shared_array<Sample> > AudioSource::_mixdown_buffers;
62 vector<boost::shared_array<gain_t> > AudioSource::_gain_buffers;
63 size_t AudioSource::_working_buffers_size = 0;
64 bool AudioSource::_build_missing_peakfiles = false;
66 /** true if we want peakfiles (e.g. if we are displaying a GUI) */
67 bool AudioSource::_build_peakfiles = false;
71 AudioSource::AudioSource (Session& s, string name)
72 : Source (s, DataType::AUDIO, name)
77 _peakfile_descriptor = 0;
78 peak_leftover_cnt = 0;
79 peak_leftover_size = 0;
83 AudioSource::AudioSource (Session& s, const XMLNode& node)
90 _peakfile_descriptor = 0;
91 peak_leftover_cnt = 0;
92 peak_leftover_size = 0;
95 if (set_state (node, Stateful::loading_state_version)) {
96 throw failed_constructor();
100 AudioSource::~AudioSource ()
102 /* shouldn't happen but make sure we don't leak file descriptors anyway */
104 if (peak_leftover_cnt) {
105 cerr << "AudioSource destroyed with leftover peak data pending" << endl;
108 delete _peakfile_descriptor;
109 delete [] peak_leftovers;
113 AudioSource::get_state ()
115 XMLNode& node (Source::get_state());
117 if (_captured_for.length()) {
118 node.add_property ("captured-for", _captured_for);
125 AudioSource::set_state (const XMLNode& node, int /*version*/)
127 const XMLProperty* prop;
129 if ((prop = node.property ("captured-for")) != 0) {
130 _captured_for = prop->value();
137 AudioSource::empty () const
143 AudioSource::length (framepos_t /*pos*/) const
149 AudioSource::update_length (framecnt_t len)
157 /***********************************************************************
159 ***********************************************************************/
161 /** Checks to see if peaks are ready. If so, we return true. If not, we return false, and
162 * things are set up so that doThisWhenReady is called when the peaks are ready.
163 * A new PBD::ScopedConnection is created for the associated connection and written to
164 * *connect_here_if_not.
166 * @param doThisWhenReady Function to call when peaks are ready (if they are not already).
167 * @param connect_here_if_not Address to write new ScopedConnection to.
168 * @param event_loop Event loop for doThisWhenReady to be called in.
171 AudioSource::peaks_ready (boost::function<void()> doThisWhenReady, ScopedConnection** connect_here_if_not, EventLoop* event_loop) const
174 Glib::Threads::Mutex::Lock lm (_peaks_ready_lock);
176 if (!(ret = _peaks_built)) {
177 *connect_here_if_not = new ScopedConnection;
178 PeaksReady.connect (**connect_here_if_not, MISSING_INVALIDATOR, doThisWhenReady, event_loop);
185 AudioSource::touch_peakfile ()
189 if (g_stat (peakpath.c_str(), &statbuf) != 0 || statbuf.st_size == 0) {
195 tbuf.actime = statbuf.st_atime;
196 tbuf.modtime = time ((time_t*) 0);
198 g_utime (peakpath.c_str(), &tbuf);
202 AudioSource::rename_peakfile (string newpath)
204 /* caller must hold _lock */
206 string oldpath = peakpath;
208 if (Glib::file_test (oldpath, Glib::FILE_TEST_EXISTS)) {
209 if (g_rename (oldpath.c_str(), newpath.c_str()) != 0) {
210 error << string_compose (_("cannot rename peakfile for %1 from %2 to %3 (%4)"), _name, oldpath, newpath, strerror (errno)) << endmsg;
221 AudioSource::initialize_peakfile (string audio_path)
225 peakpath = peak_path (audio_path);
227 DEBUG_TRACE(DEBUG::Peaks, string_compose ("Initialize Peakfile %1 for Audio file %2\n", peakpath, audio_path));
229 /* if the peak file should be there, but isn't .... */
231 if (!empty() && !Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
232 peakpath = find_broken_peakfile (peakpath, audio_path);
235 if (g_stat (peakpath.c_str(), &statbuf)) {
236 if (errno != ENOENT) {
237 /* it exists in the peaks dir, but there is some kind of error */
239 error << string_compose(_("AudioSource: cannot stat peakfile \"%1\""), peakpath) << endmsg;
243 DEBUG_TRACE(DEBUG::Peaks, string_compose("Peakfile %1 does not exist\n", peakpath));
245 _peaks_built = false;
249 /* we found it in the peaks dir, so check it out */
251 if (statbuf.st_size == 0 || (statbuf.st_size < (off_t) ((length(_timeline_position) / _FPP) * sizeof (PeakData)))) {
252 DEBUG_TRACE(DEBUG::Peaks, string_compose("Peakfile %1 is empty\n", peakpath));
253 _peaks_built = false;
255 // Check if the audio file has changed since the peakfile was built.
256 struct stat stat_file;
257 int err = stat (audio_path.c_str(), &stat_file);
261 /* no audio path - nested source or we can't
262 read it or ... whatever, use the peakfile as-is.
264 DEBUG_TRACE(DEBUG::Peaks, string_compose("Error when calling stat on Peakfile %1\n", peakpath));
267 _peak_byte_max = statbuf.st_size;
271 /* allow 6 seconds slop on checking peak vs. file times because of various
275 if (stat_file.st_mtime > statbuf.st_mtime && (stat_file.st_mtime - statbuf.st_mtime > 6)) {
276 _peaks_built = false;
280 _peak_byte_max = statbuf.st_size;
286 if (!empty() && !_peaks_built && _build_missing_peakfiles && _build_peakfiles) {
287 build_peaks_from_scratch ();
294 AudioSource::read (Sample *dst, framepos_t start, framecnt_t cnt, int /*channel*/) const
298 Glib::Threads::Mutex::Lock lm (_lock);
299 return read_unlocked (dst, start, cnt);
303 AudioSource::write (Sample *dst, framecnt_t cnt)
305 Glib::Threads::Mutex::Lock lm (_lock);
306 /* any write makes the file not removable */
307 _flags = Flag (_flags & ~Removable);
308 return write_unlocked (dst, cnt);
312 AudioSource::read_peaks (PeakData *peaks, framecnt_t npeaks, framepos_t start, framecnt_t cnt, double samples_per_visual_peak) const
314 return read_peaks_with_fpp (peaks, npeaks, start, cnt, samples_per_visual_peak, _FPP);
317 /** @param peaks Buffer to write peak data.
318 * @param npeaks Number of peaks to write.
322 AudioSource::read_peaks_with_fpp (PeakData *peaks, framecnt_t npeaks, framepos_t start, framecnt_t cnt,
323 double samples_per_visual_peak, framecnt_t samples_per_file_peak) const
325 Glib::Threads::Mutex::Lock lm (_lock);
327 double expected_peaks;
328 PeakData::PeakDatum xmax;
329 PeakData::PeakDatum xmin;
332 framecnt_t zero_fill = 0;
334 boost::scoped_ptr<FdFileDescriptor> peakfile_descriptor(new FdFileDescriptor (peakpath, false, 0664));
335 int peakfile_fd = -1;
337 expected_peaks = (cnt / (double) samples_per_file_peak);
338 scale = npeaks/expected_peaks;
340 DEBUG_TRACE (DEBUG::Peaks, string_compose (" ======>RP: npeaks = %1 start = %2 cnt = %3 len = %4 samples_per_visual_peak = %5 expected was %6 ... scale = %7 PD ptr = %8\n"
341 , npeaks, start, cnt, _length, samples_per_visual_peak, expected_peaks, scale, peaks));
343 /* fix for near-end-of-file conditions */
345 if (cnt > _length - start) {
346 // cerr << "too close to end @ " << _length << " given " << start << " + " << cnt << " (" << _length - start << ")" << endl;
347 cnt = _length - start;
348 framecnt_t old = npeaks;
349 npeaks = min ((framecnt_t) floor (cnt / samples_per_visual_peak), npeaks);
350 zero_fill = old - npeaks;
353 // cerr << "actual npeaks = " << npeaks << " zf = " << zero_fill << endl;
357 DEBUG_TRACE (DEBUG::Peaks, "RAW DATA\n");
359 /* no scaling at all, just get the sample data and duplicate it for
360 both max and min peak values.
363 boost::scoped_array<Sample> raw_staging(new Sample[cnt]);
365 if (read_unlocked (raw_staging.get(), start, cnt) != cnt) {
366 error << _("cannot read sample data for unscaled peak computation") << endmsg;
370 for (framecnt_t i = 0; i < npeaks; ++i) {
371 peaks[i].max = raw_staging[i];
372 peaks[i].min = raw_staging[i];
381 off_t first_peak_byte = (start / samples_per_file_peak) * sizeof (PeakData);
382 ssize_t bytes_to_read = sizeof (PeakData)* npeaks;
383 /* open, read, close */
385 if ((peakfile_fd = peakfile_descriptor->allocate ()) < 0) {
386 error << string_compose(_("AudioSource: cannot open peakpath (a) \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
390 DEBUG_TRACE (DEBUG::Peaks, "DIRECT PEAKS\n");
392 offset = lseek (peakfile_fd, first_peak_byte, SEEK_SET);
394 if (offset != first_peak_byte) {
395 error << string_compose(_("AudioSource: could not seek to correct location in peak file \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
399 nread = ::read (peakfile_fd, peaks, bytes_to_read);
401 if (nread != bytes_to_read) {
402 DEBUG_TRACE (DEBUG::Peaks, string_compose ("[%1]: Cannot read peaks from peakfile! (read only %2 not %3 at sample %4 = byte %5 )\n"
403 , _name, nread, npeaks, start, first_peak_byte));
408 memset (&peaks[npeaks], 0, sizeof (PeakData) * zero_fill);
419 DEBUG_TRACE (DEBUG::Peaks, "DOWNSAMPLE\n");
423 - more frames-per-peak (lower resolution) than the peakfile, or to put it another way,
424 - less peaks than the peakfile holds for the same range
426 So, read a block into a staging area, and then downsample from there.
428 to avoid confusion, I'll refer to the requested peaks as visual_peaks and the peakfile peaks as stored_peaks
431 const framecnt_t chunksize = (framecnt_t) min (expected_peaks, 65536.0);
433 boost::scoped_array<PeakData> staging(new PeakData[chunksize]);
435 /* compute the rounded up frame position */
437 framepos_t current_frame = start;
438 framepos_t current_stored_peak = (framepos_t) ceil (current_frame / (double) samples_per_file_peak);
439 framepos_t next_visual_peak = (framepos_t) ceil (current_frame / samples_per_visual_peak);
440 double next_visual_peak_frame = next_visual_peak * samples_per_visual_peak;
441 framepos_t stored_peak_before_next_visual_peak = (framepos_t) next_visual_peak_frame / samples_per_file_peak;
442 framecnt_t nvisual_peaks = 0;
443 framecnt_t stored_peaks_read = 0;
446 /* handle the case where the initial visual peak is on a pixel boundary */
448 current_stored_peak = min (current_stored_peak, stored_peak_before_next_visual_peak);
450 /* open ... close during out: handling */
452 if ((peakfile_fd = peakfile_descriptor->allocate ()) < 0) {
453 error << string_compose(_("AudioSource: cannot open peakpath (b) \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
457 while (nvisual_peaks < npeaks) {
459 if (i == stored_peaks_read) {
461 uint32_t start_byte = current_stored_peak * sizeof(PeakData);
462 tnp = min ((framecnt_t)(_length/samples_per_file_peak - current_stored_peak), (framecnt_t) expected_peaks);
463 to_read = min (chunksize, tnp);
464 ssize_t bytes_to_read = sizeof (PeakData) * to_read;
466 DEBUG_TRACE (DEBUG::Peaks, string_compose ("reading %1 bytes from peakfile @ %2\n"
467 , bytes_to_read, start_byte));
470 off_t offset = lseek (peakfile_fd, start_byte, SEEK_SET);
472 if (offset != start_byte) {
473 error << string_compose(_("AudioSource: could not seek to correct location in peak file \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
477 if ((nread = ::read (peakfile_fd, staging.get(), bytes_to_read)) != bytes_to_read) {
479 off_t fend = lseek (peakfile_fd, 0, SEEK_END);
481 DEBUG_TRACE (DEBUG::Peaks, string_compose ("[%1]: cannot read peak data from peakfile (%2 peaks instead of %3) (%4) at start_byte = %5 _length = %6 versus len = %7 expected maxpeaks = %8 npeaks was %9"
482 , _name, (nread / sizeof(PeakData)), to_read, g_strerror (errno), start_byte, _length, fend, ((_length - current_frame)/samples_per_file_peak), npeaks));
486 stored_peaks_read = nread / sizeof(PeakData);
492 while ((i < stored_peaks_read) && (current_stored_peak <= stored_peak_before_next_visual_peak)) {
494 xmax = max (xmax, staging[i].max);
495 xmin = min (xmin, staging[i].min);
497 ++current_stored_peak;
501 peaks[nvisual_peaks].max = xmax;
502 peaks[nvisual_peaks].min = xmin;
506 //next_visual_peak_frame = min ((next_visual_peak * samples_per_visual_peak), (next_visual_peak_frame+samples_per_visual_peak) );
507 next_visual_peak_frame = min ((double) start+cnt, (next_visual_peak_frame+samples_per_visual_peak) );
508 stored_peak_before_next_visual_peak = (uint32_t) next_visual_peak_frame / samples_per_file_peak;
512 cerr << "Zero fill end of peaks (@ " << npeaks << " with " << zero_fill << endl;
513 memset (&peaks[npeaks], 0, sizeof (PeakData) * zero_fill);
518 DEBUG_TRACE (DEBUG::Peaks, "UPSAMPLE\n");
522 - less frames-per-peak (more resolution)
523 - more peaks than stored in the Peakfile
525 So, fetch data from the raw source, and generate peak
529 framecnt_t frames_read = 0;
530 framepos_t current_frame = start;
532 framecnt_t nvisual_peaks = 0;
533 framecnt_t chunksize = (framecnt_t) min (cnt, (framecnt_t) 4096);
534 boost::scoped_array<Sample> raw_staging(new Sample[chunksize]);
536 framepos_t frame_pos = start;
537 double pixel_pos = floor (frame_pos / samples_per_visual_peak);
538 double next_pixel_pos = ceil (frame_pos / samples_per_visual_peak);
539 double pixels_per_frame = 1.0 / samples_per_visual_peak;
544 while (nvisual_peaks < npeaks) {
546 if (i == frames_read) {
548 to_read = min (chunksize, (framecnt_t)(_length - current_frame));
550 if (current_frame >= _length) {
552 /* hmm, error condition - we've reached the end of the file
553 without generating all the peak data. cook up a zero-filled
554 data buffer and then use it. this is simpler than
555 adjusting zero_fill and npeaks and then breaking out of
559 memset (raw_staging.get(), 0, sizeof (Sample) * chunksize);
563 to_read = min (chunksize, (_length - current_frame));
566 if ((frames_read = read_unlocked (raw_staging.get(), current_frame, to_read)) == 0) {
567 error << string_compose(_("AudioSource[%1]: peak read - cannot read %2 samples at offset %3 of %4 (%5)"),
568 _name, to_read, current_frame, _length, strerror (errno))
577 xmax = max (xmax, raw_staging[i]);
578 xmin = min (xmin, raw_staging[i]);
581 pixel_pos += pixels_per_frame;
583 if (pixel_pos >= next_pixel_pos) {
585 peaks[nvisual_peaks].max = xmax;
586 peaks[nvisual_peaks].min = xmin;
591 next_pixel_pos = ceil (pixel_pos + 0.5);
596 memset (&peaks[npeaks], 0, sizeof (PeakData) * zero_fill);
600 DEBUG_TRACE (DEBUG::Peaks, "READPEAKS DONE\n");
605 AudioSource::build_peaks_from_scratch ()
607 const framecnt_t bufsize = 65536; // 256kB per disk read for mono data is about ideal
609 DEBUG_TRACE (DEBUG::Peaks, "Building peaks from scratch\n");
614 /* hold lock while building peaks */
616 Glib::Threads::Mutex::Lock lp (_lock);
618 if (prepare_for_peakfile_writes ()) {
622 framecnt_t current_frame = 0;
623 framecnt_t cnt = _length;
625 _peaks_built = false;
626 boost::scoped_array<Sample> buf(new Sample[bufsize]);
630 framecnt_t frames_to_read = min (bufsize, cnt);
631 framecnt_t frames_read;
633 if ((frames_read = read_unlocked (buf.get(), current_frame, frames_to_read)) != frames_to_read) {
634 error << string_compose(_("%1: could not write read raw data for peak computation (%2)"), _name, strerror (errno)) << endmsg;
635 done_with_peakfile_writes (false);
639 if (compute_and_write_peaks (buf.get(), current_frame, frames_read, true, false, _FPP)) {
643 current_frame += frames_read;
652 done_with_peakfile_writes ((cnt == 0));
660 DEBUG_TRACE (DEBUG::Peaks, string_compose("Could not write peak data, attempting to remove peakfile %1\n", peakpath));
661 ::g_unlink (peakpath.c_str());
668 AudioSource::prepare_for_peakfile_writes ()
670 _peakfile_descriptor = new FdFileDescriptor (peakpath, true, 0664);
671 if ((_peakfile_fd = _peakfile_descriptor->allocate()) < 0) {
672 error << string_compose(_("AudioSource: cannot open peakpath (c) \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
679 AudioSource::done_with_peakfile_writes (bool done)
681 if (peak_leftover_cnt) {
682 compute_and_write_peaks (0, 0, 0, true, false, _FPP);
686 Glib::Threads::Mutex::Lock lm (_peaks_ready_lock);
688 PeaksReady (); /* EMIT SIGNAL */
691 delete _peakfile_descriptor;
692 _peakfile_descriptor = 0;
695 /** @param first_frame Offset from the source start of the first frame to process */
697 AudioSource::compute_and_write_peaks (Sample* buf, framecnt_t first_frame, framecnt_t cnt,
698 bool force, bool intermediate_peaks_ready)
700 return compute_and_write_peaks (buf, first_frame, cnt, force, intermediate_peaks_ready, _FPP);
704 AudioSource::compute_and_write_peaks (Sample* buf, framecnt_t first_frame, framecnt_t cnt,
705 bool force, bool intermediate_peaks_ready, framecnt_t fpp)
708 uint32_t peaks_computed;
709 framepos_t current_frame;
710 framecnt_t frames_done;
711 const size_t blocksize = (128 * 1024);
712 off_t first_peak_byte;
713 boost::scoped_array<Sample> buf2;
715 if (_peakfile_descriptor == 0) {
716 prepare_for_peakfile_writes ();
720 if (peak_leftover_cnt) {
722 if (first_frame != peak_leftover_frame + peak_leftover_cnt) {
724 /* uh-oh, ::seek() since the last ::compute_and_write_peaks(),
725 and we have leftovers. flush a single peak (since the leftovers
726 never represent more than that, and restart.
731 x.min = peak_leftovers[0];
732 x.max = peak_leftovers[0];
734 off_t byte = (peak_leftover_frame / fpp) * sizeof (PeakData);
736 off_t offset = lseek (_peakfile_fd, byte, SEEK_SET);
738 if (offset != byte) {
739 error << string_compose(_("%1: could not seek in peak file data (%2)"), _name, strerror (errno)) << endmsg;
743 if (::write (_peakfile_fd, &x, sizeof (PeakData)) != sizeof (PeakData)) {
744 error << string_compose(_("%1: could not write peak file data (%2)"), _name, strerror (errno)) << endmsg;
748 _peak_byte_max = max (_peak_byte_max, (off_t) (byte + sizeof(PeakData)));
751 Glib::Threads::Mutex::Lock lm (_peaks_ready_lock);
752 PeakRangeReady (peak_leftover_frame, peak_leftover_cnt); /* EMIT SIGNAL */
753 if (intermediate_peaks_ready) {
754 PeaksReady (); /* EMIT SIGNAL */
758 /* left overs are done */
760 peak_leftover_cnt = 0;
764 /* else ... had leftovers, but they immediately preceed the new data, so just
765 merge them and compute.
768 /* make a new contiguous buffer containing leftovers and the new stuff */
770 to_do = cnt + peak_leftover_cnt;
771 buf2.reset(new Sample[to_do]);
774 memcpy (buf2.get(), peak_leftovers, peak_leftover_cnt * sizeof (Sample));
777 memcpy (buf2.get()+peak_leftover_cnt, buf, cnt * sizeof (Sample));
779 /* no more leftovers */
780 peak_leftover_cnt = 0;
782 /* use the temporary buffer */
785 /* make sure that when we write into the peakfile, we startup where we left off */
787 first_frame = peak_leftover_frame;
793 boost::scoped_array<PeakData> peakbuf(new PeakData[(to_do/fpp)+1]);
795 current_frame = first_frame;
800 /* if some frames were passed in (i.e. we're not flushing leftovers)
801 and there are less than fpp to do, save them till
805 if (force && (to_do < fpp)) {
806 /* keep the left overs around for next time */
808 if (peak_leftover_size < to_do) {
809 delete [] peak_leftovers;
810 peak_leftovers = new Sample[to_do];
811 peak_leftover_size = to_do;
813 memcpy (peak_leftovers, buf, to_do * sizeof (Sample));
814 peak_leftover_cnt = to_do;
815 peak_leftover_frame = current_frame;
822 framecnt_t this_time = min (fpp, to_do);
824 peakbuf[peaks_computed].max = buf[0];
825 peakbuf[peaks_computed].min = buf[0];
827 ARDOUR::find_peaks (buf+1, this_time-1, &peakbuf[peaks_computed].min, &peakbuf[peaks_computed].max);
832 frames_done += this_time;
833 current_frame += this_time;
836 first_peak_byte = (first_frame / fpp) * sizeof (PeakData);
838 if (can_truncate_peaks()) {
840 /* on some filesystems (ext3, at least) this helps to reduce fragmentation of
841 the peakfiles. its not guaranteed to do so, and even on ext3 (as of december 2006)
842 it does not cause single-extent allocation even for peakfiles of
843 less than BLOCKSIZE bytes. only call ftruncate if we'll make the file larger.
846 off_t endpos = lseek (_peakfile_fd, 0, SEEK_END);
847 off_t target_length = blocksize * ((first_peak_byte + blocksize + 1) / blocksize);
849 if (endpos < target_length) {
850 DEBUG_TRACE(DEBUG::Peaks, string_compose ("Truncating Peakfile %1\n", peakpath));
851 if (ftruncate (_peakfile_fd, target_length)) {
852 /* error doesn't actually matter so continue on without testing */
858 off_t offset = lseek(_peakfile_fd, first_peak_byte, SEEK_SET);
860 if (offset != first_peak_byte) {
861 error << string_compose(_("%1: could not seek in peak file data (%2)"), _name, strerror (errno)) << endmsg;
865 ssize_t bytes_to_write = sizeof (PeakData) * peaks_computed;
867 ssize_t bytes_written = ::write (_peakfile_fd, peakbuf.get(), bytes_to_write);
869 if (bytes_written != bytes_to_write) {
870 error << string_compose(_("%1: could not write peak file data (%2)"), _name, strerror (errno)) << endmsg;
874 _peak_byte_max = max (_peak_byte_max, (off_t) (first_peak_byte + bytes_to_write));
877 Glib::Threads::Mutex::Lock lm (_peaks_ready_lock);
878 PeakRangeReady (first_frame, frames_done); /* EMIT SIGNAL */
879 if (intermediate_peaks_ready) {
880 PeaksReady (); /* EMIT SIGNAL */
888 AudioSource::truncate_peakfile ()
890 if (_peakfile_descriptor == 0) {
891 error << string_compose (_("programming error: %1"), "AudioSource::truncate_peakfile() called without open peakfile descriptor")
896 /* truncate the peakfile down to its natural length if necessary */
898 off_t end = lseek (_peakfile_fd, 0, SEEK_END);
900 if (end > _peak_byte_max) {
901 DEBUG_TRACE(DEBUG::Peaks, string_compose ("Truncating Peakfile %1\n", peakpath));
902 if (ftruncate (_peakfile_fd, _peak_byte_max)) {
903 error << string_compose (_("could not truncate peakfile %1 to %2 (error: %3)"),
904 peakpath, _peak_byte_max, errno) << endmsg;
910 AudioSource::available_peaks (double zoom_factor) const
912 if (zoom_factor < _FPP) {
913 return length(_timeline_position); // peak data will come from the audio file
916 /* peak data comes from peakfile, but the filesize might not represent
917 the valid data due to ftruncate optimizations, so use _peak_byte_max state.
918 XXX - there might be some atomicity issues here, we should probably add a lock,
919 but _peak_byte_max only monotonically increases after initialization.
922 off_t end = _peak_byte_max;
924 return (end/sizeof(PeakData)) * _FPP;
928 AudioSource::mark_streaming_write_completed ()
930 Glib::Threads::Mutex::Lock lm (_peaks_ready_lock);
933 PeaksReady (); /* EMIT SIGNAL */
938 AudioSource::allocate_working_buffers (framecnt_t framerate)
940 Glib::Threads::Mutex::Lock lm (_level_buffer_lock);
943 /* Note: we don't need any buffers allocated until
944 a level 1 audiosource is created, at which
945 time we'll call ::ensure_buffers_for_level()
946 with the right value and do the right thing.
949 if (!_mixdown_buffers.empty()) {
950 ensure_buffers_for_level_locked ( _mixdown_buffers.size(), framerate);
955 AudioSource::ensure_buffers_for_level (uint32_t level, framecnt_t frame_rate)
957 Glib::Threads::Mutex::Lock lm (_level_buffer_lock);
958 ensure_buffers_for_level_locked (level, frame_rate);
962 AudioSource::ensure_buffers_for_level_locked (uint32_t level, framecnt_t frame_rate)
964 framecnt_t nframes = (framecnt_t) floor (Config->get_audio_playback_buffer_seconds() * frame_rate);
966 /* this may be called because either "level" or "frame_rate" have
967 * changed. and it may be called with "level" smaller than the current
968 * number of buffers, because a new compound region has been created at
969 * a more shallow level than the deepest one we currently have.
972 uint32_t limit = max ((size_t) level, _mixdown_buffers.size());
974 _mixdown_buffers.clear ();
975 _gain_buffers.clear ();
977 for (uint32_t n = 0; n < limit; ++n) {
978 _mixdown_buffers.push_back (boost::shared_array<Sample> (new Sample[nframes]));
979 _gain_buffers.push_back (boost::shared_array<gain_t> (new gain_t[nframes]));