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)
75 , _peaks_built (false)
77 , peak_leftover_cnt (0)
78 , peak_leftover_size (0)
83 AudioSource::AudioSource (Session& s, const XMLNode& node)
87 , _peaks_built (false)
89 , peak_leftover_cnt (0)
90 , peak_leftover_size (0)
93 if (set_state (node, Stateful::loading_state_version)) {
94 throw failed_constructor();
98 AudioSource::~AudioSource ()
100 /* shouldn't happen but make sure we don't leak file descriptors anyway */
102 if (peak_leftover_cnt) {
103 cerr << "AudioSource destroyed with leftover peak data pending" << endl;
106 if ((-1) != _peakfile_fd) {
107 close (_peakfile_fd);
111 delete [] peak_leftovers;
115 AudioSource::get_state ()
117 XMLNode& node (Source::get_state());
119 if (_captured_for.length()) {
120 node.add_property ("captured-for", _captured_for);
127 AudioSource::set_state (const XMLNode& node, int /*version*/)
129 const XMLProperty* prop;
131 if ((prop = node.property ("captured-for")) != 0) {
132 _captured_for = prop->value();
139 AudioSource::empty () const
145 AudioSource::length (framepos_t /*pos*/) const
151 AudioSource::update_length (framecnt_t len)
159 /***********************************************************************
161 ***********************************************************************/
163 /** Checks to see if peaks are ready. If so, we return true. If not, we return false, and
164 * things are set up so that doThisWhenReady is called when the peaks are ready.
165 * A new PBD::ScopedConnection is created for the associated connection and written to
166 * *connect_here_if_not.
168 * @param doThisWhenReady Function to call when peaks are ready (if they are not already).
169 * @param connect_here_if_not Address to write new ScopedConnection to.
170 * @param event_loop Event loop for doThisWhenReady to be called in.
173 AudioSource::peaks_ready (boost::function<void()> doThisWhenReady, ScopedConnection** connect_here_if_not, EventLoop* event_loop) const
176 Glib::Threads::Mutex::Lock lm (_peaks_ready_lock);
178 if (!(ret = _peaks_built)) {
179 *connect_here_if_not = new ScopedConnection;
180 PeaksReady.connect (**connect_here_if_not, MISSING_INVALIDATOR, doThisWhenReady, event_loop);
187 AudioSource::touch_peakfile ()
191 if (g_stat (peakpath.c_str(), &statbuf) != 0 || statbuf.st_size == 0) {
197 tbuf.actime = statbuf.st_atime;
198 tbuf.modtime = time ((time_t*) 0);
200 g_utime (peakpath.c_str(), &tbuf);
204 AudioSource::rename_peakfile (string newpath)
206 /* caller must hold _lock */
208 string oldpath = peakpath;
210 if (Glib::file_test (oldpath, Glib::FILE_TEST_EXISTS)) {
211 if (g_rename (oldpath.c_str(), newpath.c_str()) != 0) {
212 error << string_compose (_("cannot rename peakfile for %1 from %2 to %3 (%4)"), _name, oldpath, newpath, strerror (errno)) << endmsg;
223 AudioSource::initialize_peakfile (string audio_path)
227 peakpath = peak_path (audio_path);
229 DEBUG_TRACE(DEBUG::Peaks, string_compose ("Initialize Peakfile %1 for Audio file %2\n", peakpath, audio_path));
231 /* if the peak file should be there, but isn't .... */
233 if (!empty() && !Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
234 peakpath = find_broken_peakfile (peakpath, audio_path);
237 if (g_stat (peakpath.c_str(), &statbuf)) {
238 if (errno != ENOENT) {
239 /* it exists in the peaks dir, but there is some kind of error */
241 error << string_compose(_("AudioSource: cannot stat peakfile \"%1\""), peakpath) << endmsg;
245 DEBUG_TRACE(DEBUG::Peaks, string_compose("Peakfile %1 does not exist\n", peakpath));
247 _peaks_built = false;
251 /* we found it in the peaks dir, so check it out */
253 if (statbuf.st_size == 0 || (statbuf.st_size < (off_t) ((length(_timeline_position) / _FPP) * sizeof (PeakData)))) {
254 DEBUG_TRACE(DEBUG::Peaks, string_compose("Peakfile %1 is empty\n", peakpath));
255 _peaks_built = false;
257 // Check if the audio file has changed since the peakfile was built.
258 struct stat stat_file;
259 int err = stat (audio_path.c_str(), &stat_file);
263 /* no audio path - nested source or we can't
264 read it or ... whatever, use the peakfile as-is.
266 DEBUG_TRACE(DEBUG::Peaks, string_compose("Error when calling stat on Peakfile %1\n", peakpath));
269 _peak_byte_max = statbuf.st_size;
273 /* allow 6 seconds slop on checking peak vs. file times because of various
277 if (stat_file.st_mtime > statbuf.st_mtime && (stat_file.st_mtime - statbuf.st_mtime > 6)) {
278 _peaks_built = false;
282 _peak_byte_max = statbuf.st_size;
288 if (!empty() && !_peaks_built && _build_missing_peakfiles && _build_peakfiles) {
289 build_peaks_from_scratch ();
296 AudioSource::read (Sample *dst, framepos_t start, framecnt_t cnt, int /*channel*/) const
300 Glib::Threads::Mutex::Lock lm (_lock);
301 return read_unlocked (dst, start, cnt);
305 AudioSource::write (Sample *dst, framecnt_t cnt)
307 Glib::Threads::Mutex::Lock lm (_lock);
308 /* any write makes the file not removable */
309 _flags = Flag (_flags & ~Removable);
310 return write_unlocked (dst, cnt);
314 AudioSource::read_peaks (PeakData *peaks, framecnt_t npeaks, framepos_t start, framecnt_t cnt, double samples_per_visual_peak) const
316 return read_peaks_with_fpp (peaks, npeaks, start, cnt, samples_per_visual_peak, _FPP);
319 /** @param peaks Buffer to write peak data.
320 * @param npeaks Number of peaks to write.
323 struct ScopedFileDescriptor {
324 ScopedFileDescriptor (int fd) : _fd (fd) {}
325 ~ScopedFileDescriptor() { close (_fd); }
326 operator int() { return _fd; }
331 AudioSource::read_peaks_with_fpp (PeakData *peaks, framecnt_t npeaks, framepos_t start, framecnt_t cnt,
332 double samples_per_visual_peak, framecnt_t samples_per_file_peak) const
334 Glib::Threads::Mutex::Lock lm (_lock);
336 double expected_peaks;
337 PeakData::PeakDatum xmax;
338 PeakData::PeakDatum xmin;
341 framecnt_t zero_fill = 0;
343 ScopedFileDescriptor sfd (::open (peakpath.c_str(), O_RDONLY));
346 error << string_compose (_("Cannot open peakfile @ %1 for reading (%2)"), peakpath, strerror (errno)) << endmsg;
350 expected_peaks = (cnt / (double) samples_per_file_peak);
351 scale = npeaks/expected_peaks;
353 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"
354 , npeaks, start, cnt, _length, samples_per_visual_peak, expected_peaks, scale, peaks));
356 /* fix for near-end-of-file conditions */
358 if (cnt > _length - start) {
359 // cerr << "too close to end @ " << _length << " given " << start << " + " << cnt << " (" << _length - start << ")" << endl;
360 cnt = _length - start;
361 framecnt_t old = npeaks;
362 npeaks = min ((framecnt_t) floor (cnt / samples_per_visual_peak), npeaks);
363 zero_fill = old - npeaks;
366 // cerr << "actual npeaks = " << npeaks << " zf = " << zero_fill << endl;
370 DEBUG_TRACE (DEBUG::Peaks, "RAW DATA\n");
372 /* no scaling at all, just get the sample data and duplicate it for
373 both max and min peak values.
376 boost::scoped_array<Sample> raw_staging(new Sample[cnt]);
378 if (read_unlocked (raw_staging.get(), start, cnt) != cnt) {
379 error << _("cannot read sample data for unscaled peak computation") << endmsg;
383 for (framecnt_t i = 0; i < npeaks; ++i) {
384 peaks[i].max = raw_staging[i];
385 peaks[i].min = raw_staging[i];
394 off_t first_peak_byte = (start / samples_per_file_peak) * sizeof (PeakData);
395 ssize_t bytes_to_read = sizeof (PeakData)* npeaks;
396 /* open, read, close */
398 DEBUG_TRACE (DEBUG::Peaks, "DIRECT PEAKS\n");
400 offset = lseek (sfd, first_peak_byte, SEEK_SET);
402 if (offset != first_peak_byte) {
403 error << string_compose(_("AudioSource: could not seek to correct location in peak file \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
407 nread = ::read (sfd, peaks, bytes_to_read);
409 if (nread != bytes_to_read) {
410 DEBUG_TRACE (DEBUG::Peaks, string_compose ("[%1]: Cannot read peaks from peakfile! (read only %2 not %3 at sample %4 = byte %5 )\n"
411 , _name, nread, npeaks, start, first_peak_byte));
416 memset (&peaks[npeaks], 0, sizeof (PeakData) * zero_fill);
427 DEBUG_TRACE (DEBUG::Peaks, "DOWNSAMPLE\n");
431 - more frames-per-peak (lower resolution) than the peakfile, or to put it another way,
432 - less peaks than the peakfile holds for the same range
434 So, read a block into a staging area, and then downsample from there.
436 to avoid confusion, I'll refer to the requested peaks as visual_peaks and the peakfile peaks as stored_peaks
439 const framecnt_t chunksize = (framecnt_t) min (expected_peaks, 65536.0);
441 boost::scoped_array<PeakData> staging(new PeakData[chunksize]);
443 /* compute the rounded up frame position */
445 framepos_t current_frame = start;
446 framepos_t current_stored_peak = (framepos_t) ceil (current_frame / (double) samples_per_file_peak);
447 framepos_t next_visual_peak = (framepos_t) ceil (current_frame / samples_per_visual_peak);
448 double next_visual_peak_frame = next_visual_peak * samples_per_visual_peak;
449 framepos_t stored_peak_before_next_visual_peak = (framepos_t) next_visual_peak_frame / samples_per_file_peak;
450 framecnt_t nvisual_peaks = 0;
451 framecnt_t stored_peaks_read = 0;
454 /* handle the case where the initial visual peak is on a pixel boundary */
456 current_stored_peak = min (current_stored_peak, stored_peak_before_next_visual_peak);
458 /* open ... close during out: handling */
460 while (nvisual_peaks < npeaks) {
462 if (i == stored_peaks_read) {
464 uint32_t start_byte = current_stored_peak * sizeof(PeakData);
465 tnp = min ((framecnt_t)(_length/samples_per_file_peak - current_stored_peak), (framecnt_t) expected_peaks);
466 to_read = min (chunksize, tnp);
467 ssize_t bytes_to_read = sizeof (PeakData) * to_read;
469 DEBUG_TRACE (DEBUG::Peaks, string_compose ("reading %1 bytes from peakfile @ %2\n"
470 , bytes_to_read, start_byte));
473 off_t offset = lseek (sfd, start_byte, SEEK_SET);
475 if (offset != start_byte) {
476 error << string_compose(_("AudioSource: could not seek to correct location in peak file \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
480 if ((nread = ::read (sfd, staging.get(), bytes_to_read)) != bytes_to_read) {
482 off_t fend = lseek (sfd, 0, SEEK_END);
484 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"
485 , _name, (nread / sizeof(PeakData)), to_read, g_strerror (errno), start_byte, _length, fend, ((_length - current_frame)/samples_per_file_peak), npeaks));
489 stored_peaks_read = nread / sizeof(PeakData);
495 while ((i < stored_peaks_read) && (current_stored_peak <= stored_peak_before_next_visual_peak)) {
497 xmax = max (xmax, staging[i].max);
498 xmin = min (xmin, staging[i].min);
500 ++current_stored_peak;
504 peaks[nvisual_peaks].max = xmax;
505 peaks[nvisual_peaks].min = xmin;
509 //next_visual_peak_frame = min ((next_visual_peak * samples_per_visual_peak), (next_visual_peak_frame+samples_per_visual_peak) );
510 next_visual_peak_frame = min ((double) start+cnt, (next_visual_peak_frame+samples_per_visual_peak) );
511 stored_peak_before_next_visual_peak = (uint32_t) next_visual_peak_frame / samples_per_file_peak;
515 cerr << "Zero fill end of peaks (@ " << npeaks << " with " << zero_fill << endl;
516 memset (&peaks[npeaks], 0, sizeof (PeakData) * zero_fill);
521 DEBUG_TRACE (DEBUG::Peaks, "UPSAMPLE\n");
525 - less frames-per-peak (more resolution)
526 - more peaks than stored in the Peakfile
528 So, fetch data from the raw source, and generate peak
532 framecnt_t frames_read = 0;
533 framepos_t current_frame = start;
535 framecnt_t nvisual_peaks = 0;
536 framecnt_t chunksize = (framecnt_t) min (cnt, (framecnt_t) 4096);
537 boost::scoped_array<Sample> raw_staging(new Sample[chunksize]);
539 framepos_t frame_pos = start;
540 double pixel_pos = floor (frame_pos / samples_per_visual_peak);
541 double next_pixel_pos = ceil (frame_pos / samples_per_visual_peak);
542 double pixels_per_frame = 1.0 / samples_per_visual_peak;
547 while (nvisual_peaks < npeaks) {
549 if (i == frames_read) {
551 to_read = min (chunksize, (framecnt_t)(_length - current_frame));
553 if (current_frame >= _length) {
555 /* hmm, error condition - we've reached the end of the file
556 without generating all the peak data. cook up a zero-filled
557 data buffer and then use it. this is simpler than
558 adjusting zero_fill and npeaks and then breaking out of
562 memset (raw_staging.get(), 0, sizeof (Sample) * chunksize);
566 to_read = min (chunksize, (_length - current_frame));
569 if ((frames_read = read_unlocked (raw_staging.get(), current_frame, to_read)) == 0) {
570 error << string_compose(_("AudioSource[%1]: peak read - cannot read %2 samples at offset %3 of %4 (%5)"),
571 _name, to_read, current_frame, _length, strerror (errno))
580 xmax = max (xmax, raw_staging[i]);
581 xmin = min (xmin, raw_staging[i]);
584 pixel_pos += pixels_per_frame;
586 if (pixel_pos >= next_pixel_pos) {
588 peaks[nvisual_peaks].max = xmax;
589 peaks[nvisual_peaks].min = xmin;
594 next_pixel_pos = ceil (pixel_pos + 0.5);
599 memset (&peaks[npeaks], 0, sizeof (PeakData) * zero_fill);
603 DEBUG_TRACE (DEBUG::Peaks, "READPEAKS DONE\n");
608 AudioSource::build_peaks_from_scratch ()
610 const framecnt_t bufsize = 65536; // 256kB per disk read for mono data is about ideal
612 DEBUG_TRACE (DEBUG::Peaks, "Building peaks from scratch\n");
617 /* hold lock while building peaks */
619 Glib::Threads::Mutex::Lock lp (_lock);
621 if (prepare_for_peakfile_writes ()) {
625 framecnt_t current_frame = 0;
626 framecnt_t cnt = _length;
628 _peaks_built = false;
629 boost::scoped_array<Sample> buf(new Sample[bufsize]);
633 framecnt_t frames_to_read = min (bufsize, cnt);
634 framecnt_t frames_read;
636 if ((frames_read = read_unlocked (buf.get(), current_frame, frames_to_read)) != frames_to_read) {
637 error << string_compose(_("%1: could not write read raw data for peak computation (%2)"), _name, strerror (errno)) << endmsg;
638 done_with_peakfile_writes (false);
642 if (compute_and_write_peaks (buf.get(), current_frame, frames_read, true, false, _FPP)) {
646 current_frame += frames_read;
655 done_with_peakfile_writes ((cnt == 0));
663 DEBUG_TRACE (DEBUG::Peaks, string_compose("Could not write peak data, attempting to remove peakfile %1\n", peakpath));
664 ::g_unlink (peakpath.c_str());
671 AudioSource::prepare_for_peakfile_writes ()
673 if ((_peakfile_fd = open (peakpath.c_str(), O_CREAT|O_RDWR, 0664)) < 0) {
674 error << string_compose(_("AudioSource: cannot open peakpath (c) \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
681 AudioSource::done_with_peakfile_writes (bool done)
683 if (peak_leftover_cnt) {
684 compute_and_write_peaks (0, 0, 0, true, false, _FPP);
688 Glib::Threads::Mutex::Lock lm (_peaks_ready_lock);
690 PeaksReady (); /* EMIT SIGNAL */
693 close (_peakfile_fd);
697 /** @param first_frame Offset from the source start of the first frame to process */
699 AudioSource::compute_and_write_peaks (Sample* buf, framecnt_t first_frame, framecnt_t cnt,
700 bool force, bool intermediate_peaks_ready)
702 return compute_and_write_peaks (buf, first_frame, cnt, force, intermediate_peaks_ready, _FPP);
706 AudioSource::compute_and_write_peaks (Sample* buf, framecnt_t first_frame, framecnt_t cnt,
707 bool force, bool intermediate_peaks_ready, framecnt_t fpp)
710 uint32_t peaks_computed;
711 framepos_t current_frame;
712 framecnt_t frames_done;
713 const size_t blocksize = (128 * 1024);
714 off_t first_peak_byte;
715 boost::scoped_array<Sample> buf2;
717 if (_peakfile_fd < 0) {
718 if (prepare_for_peakfile_writes ()) {
724 if (peak_leftover_cnt) {
726 if (first_frame != peak_leftover_frame + peak_leftover_cnt) {
728 /* uh-oh, ::seek() since the last ::compute_and_write_peaks(),
729 and we have leftovers. flush a single peak (since the leftovers
730 never represent more than that, and restart.
735 x.min = peak_leftovers[0];
736 x.max = peak_leftovers[0];
738 off_t byte = (peak_leftover_frame / fpp) * sizeof (PeakData);
740 off_t offset = lseek (_peakfile_fd, byte, SEEK_SET);
742 if (offset != byte) {
743 error << string_compose(_("%1: could not seek in peak file data (%2)"), _name, strerror (errno)) << endmsg;
747 if (::write (_peakfile_fd, &x, sizeof (PeakData)) != sizeof (PeakData)) {
748 error << string_compose(_("%1: could not write peak file data (%2)"), _name, strerror (errno)) << endmsg;
752 _peak_byte_max = max (_peak_byte_max, (off_t) (byte + sizeof(PeakData)));
755 Glib::Threads::Mutex::Lock lm (_peaks_ready_lock);
756 PeakRangeReady (peak_leftover_frame, peak_leftover_cnt); /* EMIT SIGNAL */
757 if (intermediate_peaks_ready) {
758 PeaksReady (); /* EMIT SIGNAL */
762 /* left overs are done */
764 peak_leftover_cnt = 0;
768 /* else ... had leftovers, but they immediately preceed the new data, so just
769 merge them and compute.
772 /* make a new contiguous buffer containing leftovers and the new stuff */
774 to_do = cnt + peak_leftover_cnt;
775 buf2.reset(new Sample[to_do]);
778 memcpy (buf2.get(), peak_leftovers, peak_leftover_cnt * sizeof (Sample));
781 memcpy (buf2.get()+peak_leftover_cnt, buf, cnt * sizeof (Sample));
783 /* no more leftovers */
784 peak_leftover_cnt = 0;
786 /* use the temporary buffer */
789 /* make sure that when we write into the peakfile, we startup where we left off */
791 first_frame = peak_leftover_frame;
797 boost::scoped_array<PeakData> peakbuf(new PeakData[(to_do/fpp)+1]);
799 current_frame = first_frame;
804 /* if some frames were passed in (i.e. we're not flushing leftovers)
805 and there are less than fpp to do, save them till
809 if (force && (to_do < fpp)) {
810 /* keep the left overs around for next time */
812 if (peak_leftover_size < to_do) {
813 delete [] peak_leftovers;
814 peak_leftovers = new Sample[to_do];
815 peak_leftover_size = to_do;
817 memcpy (peak_leftovers, buf, to_do * sizeof (Sample));
818 peak_leftover_cnt = to_do;
819 peak_leftover_frame = current_frame;
826 framecnt_t this_time = min (fpp, to_do);
828 peakbuf[peaks_computed].max = buf[0];
829 peakbuf[peaks_computed].min = buf[0];
831 ARDOUR::find_peaks (buf+1, this_time-1, &peakbuf[peaks_computed].min, &peakbuf[peaks_computed].max);
836 frames_done += this_time;
837 current_frame += this_time;
840 first_peak_byte = (first_frame / fpp) * sizeof (PeakData);
842 if (can_truncate_peaks()) {
844 /* on some filesystems (ext3, at least) this helps to reduce fragmentation of
845 the peakfiles. its not guaranteed to do so, and even on ext3 (as of december 2006)
846 it does not cause single-extent allocation even for peakfiles of
847 less than BLOCKSIZE bytes. only call ftruncate if we'll make the file larger.
850 off_t endpos = lseek (_peakfile_fd, 0, SEEK_END);
851 off_t target_length = blocksize * ((first_peak_byte + blocksize + 1) / blocksize);
853 if (endpos < target_length) {
854 DEBUG_TRACE(DEBUG::Peaks, string_compose ("Truncating Peakfile %1\n", peakpath));
855 if (ftruncate (_peakfile_fd, target_length)) {
856 /* error doesn't actually matter so continue on without testing */
862 off_t offset = lseek(_peakfile_fd, first_peak_byte, SEEK_SET);
864 if (offset != first_peak_byte) {
865 error << string_compose(_("%1: could not seek in peak file data (%2)"), _name, strerror (errno)) << endmsg;
869 ssize_t bytes_to_write = sizeof (PeakData) * peaks_computed;
871 ssize_t bytes_written = ::write (_peakfile_fd, peakbuf.get(), bytes_to_write);
873 if (bytes_written != bytes_to_write) {
874 error << string_compose(_("%1: could not write peak file data (%2)"), _name, strerror (errno)) << endmsg;
878 _peak_byte_max = max (_peak_byte_max, (off_t) (first_peak_byte + bytes_to_write));
881 Glib::Threads::Mutex::Lock lm (_peaks_ready_lock);
882 PeakRangeReady (first_frame, frames_done); /* EMIT SIGNAL */
883 if (intermediate_peaks_ready) {
884 PeaksReady (); /* EMIT SIGNAL */
892 AudioSource::truncate_peakfile ()
894 if (_peakfile_fd < 0) {
895 error << string_compose (_("programming error: %1"), "AudioSource::truncate_peakfile() called without open peakfile descriptor")
900 /* truncate the peakfile down to its natural length if necessary */
902 off_t end = lseek (_peakfile_fd, 0, SEEK_END);
904 if (end > _peak_byte_max) {
905 DEBUG_TRACE(DEBUG::Peaks, string_compose ("Truncating Peakfile %1\n", peakpath));
906 if (ftruncate (_peakfile_fd, _peak_byte_max)) {
907 error << string_compose (_("could not truncate peakfile %1 to %2 (error: %3)"),
908 peakpath, _peak_byte_max, errno) << endmsg;
914 AudioSource::available_peaks (double zoom_factor) const
916 if (zoom_factor < _FPP) {
917 return length(_timeline_position); // peak data will come from the audio file
920 /* peak data comes from peakfile, but the filesize might not represent
921 the valid data due to ftruncate optimizations, so use _peak_byte_max state.
922 XXX - there might be some atomicity issues here, we should probably add a lock,
923 but _peak_byte_max only monotonically increases after initialization.
926 off_t end = _peak_byte_max;
928 return (end/sizeof(PeakData)) * _FPP;
932 AudioSource::mark_streaming_write_completed ()
934 Glib::Threads::Mutex::Lock lm (_peaks_ready_lock);
937 PeaksReady (); /* EMIT SIGNAL */
942 AudioSource::allocate_working_buffers (framecnt_t framerate)
944 Glib::Threads::Mutex::Lock lm (_level_buffer_lock);
947 /* Note: we don't need any buffers allocated until
948 a level 1 audiosource is created, at which
949 time we'll call ::ensure_buffers_for_level()
950 with the right value and do the right thing.
953 if (!_mixdown_buffers.empty()) {
954 ensure_buffers_for_level_locked ( _mixdown_buffers.size(), framerate);
959 AudioSource::ensure_buffers_for_level (uint32_t level, framecnt_t frame_rate)
961 Glib::Threads::Mutex::Lock lm (_level_buffer_lock);
962 ensure_buffers_for_level_locked (level, frame_rate);
966 AudioSource::ensure_buffers_for_level_locked (uint32_t level, framecnt_t frame_rate)
968 framecnt_t nframes = (framecnt_t) floor (Config->get_audio_playback_buffer_seconds() * frame_rate);
970 /* this may be called because either "level" or "frame_rate" have
971 * changed. and it may be called with "level" smaller than the current
972 * number of buffers, because a new compound region has been created at
973 * a more shallow level than the deepest one we currently have.
976 uint32_t limit = max ((size_t) level, _mixdown_buffers.size());
978 _mixdown_buffers.clear ();
979 _gain_buffers.clear ();
981 for (uint32_t n = 0; n < limit; ++n) {
982 _mixdown_buffers.push_back (boost::shared_array<Sample> (new Sample[nframes]));
983 _gain_buffers.push_back (boost::shared_array<gain_t> (new gain_t[nframes]));