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 close (_peakfile_fd);
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.
321 struct ScopedFileDescriptor {
322 ScopedFileDescriptor (int fd) : _fd (fd) {}
323 ~ScopedFileDescriptor() { close (_fd); }
324 operator int() { return _fd; }
329 AudioSource::read_peaks_with_fpp (PeakData *peaks, framecnt_t npeaks, framepos_t start, framecnt_t cnt,
330 double samples_per_visual_peak, framecnt_t samples_per_file_peak) const
332 Glib::Threads::Mutex::Lock lm (_lock);
334 double expected_peaks;
335 PeakData::PeakDatum xmax;
336 PeakData::PeakDatum xmin;
339 framecnt_t zero_fill = 0;
341 ScopedFileDescriptor sfd (::open (peakpath.c_str(), O_RDONLY));
344 error << string_compose (_("Cannot open peakfile @ %1 for reading (%2)"), peakpath, strerror (errno)) << endmsg;
348 expected_peaks = (cnt / (double) samples_per_file_peak);
349 scale = npeaks/expected_peaks;
351 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"
352 , npeaks, start, cnt, _length, samples_per_visual_peak, expected_peaks, scale, peaks));
354 /* fix for near-end-of-file conditions */
356 if (cnt > _length - start) {
357 // cerr << "too close to end @ " << _length << " given " << start << " + " << cnt << " (" << _length - start << ")" << endl;
358 cnt = _length - start;
359 framecnt_t old = npeaks;
360 npeaks = min ((framecnt_t) floor (cnt / samples_per_visual_peak), npeaks);
361 zero_fill = old - npeaks;
364 // cerr << "actual npeaks = " << npeaks << " zf = " << zero_fill << endl;
368 DEBUG_TRACE (DEBUG::Peaks, "RAW DATA\n");
370 /* no scaling at all, just get the sample data and duplicate it for
371 both max and min peak values.
374 boost::scoped_array<Sample> raw_staging(new Sample[cnt]);
376 if (read_unlocked (raw_staging.get(), start, cnt) != cnt) {
377 error << _("cannot read sample data for unscaled peak computation") << endmsg;
381 for (framecnt_t i = 0; i < npeaks; ++i) {
382 peaks[i].max = raw_staging[i];
383 peaks[i].min = raw_staging[i];
392 off_t first_peak_byte = (start / samples_per_file_peak) * sizeof (PeakData);
393 ssize_t bytes_to_read = sizeof (PeakData)* npeaks;
394 /* open, read, close */
396 DEBUG_TRACE (DEBUG::Peaks, "DIRECT PEAKS\n");
398 offset = lseek (sfd, first_peak_byte, SEEK_SET);
400 if (offset != first_peak_byte) {
401 error << string_compose(_("AudioSource: could not seek to correct location in peak file \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
405 nread = ::read (sfd, peaks, bytes_to_read);
407 if (nread != bytes_to_read) {
408 DEBUG_TRACE (DEBUG::Peaks, string_compose ("[%1]: Cannot read peaks from peakfile! (read only %2 not %3 at sample %4 = byte %5 )\n"
409 , _name, nread, npeaks, start, first_peak_byte));
414 memset (&peaks[npeaks], 0, sizeof (PeakData) * zero_fill);
425 DEBUG_TRACE (DEBUG::Peaks, "DOWNSAMPLE\n");
429 - more frames-per-peak (lower resolution) than the peakfile, or to put it another way,
430 - less peaks than the peakfile holds for the same range
432 So, read a block into a staging area, and then downsample from there.
434 to avoid confusion, I'll refer to the requested peaks as visual_peaks and the peakfile peaks as stored_peaks
437 const framecnt_t chunksize = (framecnt_t) min (expected_peaks, 65536.0);
439 boost::scoped_array<PeakData> staging(new PeakData[chunksize]);
441 /* compute the rounded up frame position */
443 framepos_t current_frame = start;
444 framepos_t current_stored_peak = (framepos_t) ceil (current_frame / (double) samples_per_file_peak);
445 framepos_t next_visual_peak = (framepos_t) ceil (current_frame / samples_per_visual_peak);
446 double next_visual_peak_frame = next_visual_peak * samples_per_visual_peak;
447 framepos_t stored_peak_before_next_visual_peak = (framepos_t) next_visual_peak_frame / samples_per_file_peak;
448 framecnt_t nvisual_peaks = 0;
449 framecnt_t stored_peaks_read = 0;
452 /* handle the case where the initial visual peak is on a pixel boundary */
454 current_stored_peak = min (current_stored_peak, stored_peak_before_next_visual_peak);
456 /* open ... close during out: handling */
458 while (nvisual_peaks < npeaks) {
460 if (i == stored_peaks_read) {
462 uint32_t start_byte = current_stored_peak * sizeof(PeakData);
463 tnp = min ((framecnt_t)(_length/samples_per_file_peak - current_stored_peak), (framecnt_t) expected_peaks);
464 to_read = min (chunksize, tnp);
465 ssize_t bytes_to_read = sizeof (PeakData) * to_read;
467 DEBUG_TRACE (DEBUG::Peaks, string_compose ("reading %1 bytes from peakfile @ %2\n"
468 , bytes_to_read, start_byte));
471 off_t offset = lseek (sfd, start_byte, SEEK_SET);
473 if (offset != start_byte) {
474 error << string_compose(_("AudioSource: could not seek to correct location in peak file \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
478 if ((nread = ::read (sfd, staging.get(), bytes_to_read)) != bytes_to_read) {
480 off_t fend = lseek (sfd, 0, SEEK_END);
482 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"
483 , _name, (nread / sizeof(PeakData)), to_read, g_strerror (errno), start_byte, _length, fend, ((_length - current_frame)/samples_per_file_peak), npeaks));
487 stored_peaks_read = nread / sizeof(PeakData);
493 while ((i < stored_peaks_read) && (current_stored_peak <= stored_peak_before_next_visual_peak)) {
495 xmax = max (xmax, staging[i].max);
496 xmin = min (xmin, staging[i].min);
498 ++current_stored_peak;
502 peaks[nvisual_peaks].max = xmax;
503 peaks[nvisual_peaks].min = xmin;
507 //next_visual_peak_frame = min ((next_visual_peak * samples_per_visual_peak), (next_visual_peak_frame+samples_per_visual_peak) );
508 next_visual_peak_frame = min ((double) start+cnt, (next_visual_peak_frame+samples_per_visual_peak) );
509 stored_peak_before_next_visual_peak = (uint32_t) next_visual_peak_frame / samples_per_file_peak;
513 cerr << "Zero fill end of peaks (@ " << npeaks << " with " << zero_fill << endl;
514 memset (&peaks[npeaks], 0, sizeof (PeakData) * zero_fill);
519 DEBUG_TRACE (DEBUG::Peaks, "UPSAMPLE\n");
523 - less frames-per-peak (more resolution)
524 - more peaks than stored in the Peakfile
526 So, fetch data from the raw source, and generate peak
530 framecnt_t frames_read = 0;
531 framepos_t current_frame = start;
533 framecnt_t nvisual_peaks = 0;
534 framecnt_t chunksize = (framecnt_t) min (cnt, (framecnt_t) 4096);
535 boost::scoped_array<Sample> raw_staging(new Sample[chunksize]);
537 framepos_t frame_pos = start;
538 double pixel_pos = floor (frame_pos / samples_per_visual_peak);
539 double next_pixel_pos = ceil (frame_pos / samples_per_visual_peak);
540 double pixels_per_frame = 1.0 / samples_per_visual_peak;
545 while (nvisual_peaks < npeaks) {
547 if (i == frames_read) {
549 to_read = min (chunksize, (framecnt_t)(_length - current_frame));
551 if (current_frame >= _length) {
553 /* hmm, error condition - we've reached the end of the file
554 without generating all the peak data. cook up a zero-filled
555 data buffer and then use it. this is simpler than
556 adjusting zero_fill and npeaks and then breaking out of
560 memset (raw_staging.get(), 0, sizeof (Sample) * chunksize);
564 to_read = min (chunksize, (_length - current_frame));
567 if ((frames_read = read_unlocked (raw_staging.get(), current_frame, to_read)) == 0) {
568 error << string_compose(_("AudioSource[%1]: peak read - cannot read %2 samples at offset %3 of %4 (%5)"),
569 _name, to_read, current_frame, _length, strerror (errno))
578 xmax = max (xmax, raw_staging[i]);
579 xmin = min (xmin, raw_staging[i]);
582 pixel_pos += pixels_per_frame;
584 if (pixel_pos >= next_pixel_pos) {
586 peaks[nvisual_peaks].max = xmax;
587 peaks[nvisual_peaks].min = xmin;
592 next_pixel_pos = ceil (pixel_pos + 0.5);
597 memset (&peaks[npeaks], 0, sizeof (PeakData) * zero_fill);
601 DEBUG_TRACE (DEBUG::Peaks, "READPEAKS DONE\n");
606 AudioSource::build_peaks_from_scratch ()
608 const framecnt_t bufsize = 65536; // 256kB per disk read for mono data is about ideal
610 DEBUG_TRACE (DEBUG::Peaks, "Building peaks from scratch\n");
615 /* hold lock while building peaks */
617 Glib::Threads::Mutex::Lock lp (_lock);
619 if (prepare_for_peakfile_writes ()) {
623 framecnt_t current_frame = 0;
624 framecnt_t cnt = _length;
626 _peaks_built = false;
627 boost::scoped_array<Sample> buf(new Sample[bufsize]);
631 framecnt_t frames_to_read = min (bufsize, cnt);
632 framecnt_t frames_read;
634 if ((frames_read = read_unlocked (buf.get(), current_frame, frames_to_read)) != frames_to_read) {
635 error << string_compose(_("%1: could not write read raw data for peak computation (%2)"), _name, strerror (errno)) << endmsg;
636 done_with_peakfile_writes (false);
640 if (compute_and_write_peaks (buf.get(), current_frame, frames_read, true, false, _FPP)) {
644 current_frame += frames_read;
653 done_with_peakfile_writes ((cnt == 0));
661 DEBUG_TRACE (DEBUG::Peaks, string_compose("Could not write peak data, attempting to remove peakfile %1\n", peakpath));
662 ::g_unlink (peakpath.c_str());
669 AudioSource::prepare_for_peakfile_writes ()
671 if ((_peakfile_fd = open (peakpath.c_str(), O_CREAT|O_RDWR, 0664)) < 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 close (_peakfile_fd);
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_fd < 0) {
716 if (prepare_for_peakfile_writes ()) {
722 if (peak_leftover_cnt) {
724 if (first_frame != peak_leftover_frame + peak_leftover_cnt) {
726 /* uh-oh, ::seek() since the last ::compute_and_write_peaks(),
727 and we have leftovers. flush a single peak (since the leftovers
728 never represent more than that, and restart.
733 x.min = peak_leftovers[0];
734 x.max = peak_leftovers[0];
736 off_t byte = (peak_leftover_frame / fpp) * sizeof (PeakData);
738 off_t offset = lseek (_peakfile_fd, byte, SEEK_SET);
740 if (offset != byte) {
741 error << string_compose(_("%1: could not seek in peak file data (%2)"), _name, strerror (errno)) << endmsg;
745 if (::write (_peakfile_fd, &x, sizeof (PeakData)) != sizeof (PeakData)) {
746 error << string_compose(_("%1: could not write peak file data (%2)"), _name, strerror (errno)) << endmsg;
750 _peak_byte_max = max (_peak_byte_max, (off_t) (byte + sizeof(PeakData)));
753 Glib::Threads::Mutex::Lock lm (_peaks_ready_lock);
754 PeakRangeReady (peak_leftover_frame, peak_leftover_cnt); /* EMIT SIGNAL */
755 if (intermediate_peaks_ready) {
756 PeaksReady (); /* EMIT SIGNAL */
760 /* left overs are done */
762 peak_leftover_cnt = 0;
766 /* else ... had leftovers, but they immediately preceed the new data, so just
767 merge them and compute.
770 /* make a new contiguous buffer containing leftovers and the new stuff */
772 to_do = cnt + peak_leftover_cnt;
773 buf2.reset(new Sample[to_do]);
776 memcpy (buf2.get(), peak_leftovers, peak_leftover_cnt * sizeof (Sample));
779 memcpy (buf2.get()+peak_leftover_cnt, buf, cnt * sizeof (Sample));
781 /* no more leftovers */
782 peak_leftover_cnt = 0;
784 /* use the temporary buffer */
787 /* make sure that when we write into the peakfile, we startup where we left off */
789 first_frame = peak_leftover_frame;
795 boost::scoped_array<PeakData> peakbuf(new PeakData[(to_do/fpp)+1]);
797 current_frame = first_frame;
802 /* if some frames were passed in (i.e. we're not flushing leftovers)
803 and there are less than fpp to do, save them till
807 if (force && (to_do < fpp)) {
808 /* keep the left overs around for next time */
810 if (peak_leftover_size < to_do) {
811 delete [] peak_leftovers;
812 peak_leftovers = new Sample[to_do];
813 peak_leftover_size = to_do;
815 memcpy (peak_leftovers, buf, to_do * sizeof (Sample));
816 peak_leftover_cnt = to_do;
817 peak_leftover_frame = current_frame;
824 framecnt_t this_time = min (fpp, to_do);
826 peakbuf[peaks_computed].max = buf[0];
827 peakbuf[peaks_computed].min = buf[0];
829 ARDOUR::find_peaks (buf+1, this_time-1, &peakbuf[peaks_computed].min, &peakbuf[peaks_computed].max);
834 frames_done += this_time;
835 current_frame += this_time;
838 first_peak_byte = (first_frame / fpp) * sizeof (PeakData);
840 if (can_truncate_peaks()) {
842 /* on some filesystems (ext3, at least) this helps to reduce fragmentation of
843 the peakfiles. its not guaranteed to do so, and even on ext3 (as of december 2006)
844 it does not cause single-extent allocation even for peakfiles of
845 less than BLOCKSIZE bytes. only call ftruncate if we'll make the file larger.
848 off_t endpos = lseek (_peakfile_fd, 0, SEEK_END);
849 off_t target_length = blocksize * ((first_peak_byte + blocksize + 1) / blocksize);
851 if (endpos < target_length) {
852 DEBUG_TRACE(DEBUG::Peaks, string_compose ("Truncating Peakfile %1\n", peakpath));
853 if (ftruncate (_peakfile_fd, target_length)) {
854 /* error doesn't actually matter so continue on without testing */
860 off_t offset = lseek(_peakfile_fd, first_peak_byte, SEEK_SET);
862 if (offset != first_peak_byte) {
863 error << string_compose(_("%1: could not seek in peak file data (%2)"), _name, strerror (errno)) << endmsg;
867 ssize_t bytes_to_write = sizeof (PeakData) * peaks_computed;
869 ssize_t bytes_written = ::write (_peakfile_fd, peakbuf.get(), bytes_to_write);
871 if (bytes_written != bytes_to_write) {
872 error << string_compose(_("%1: could not write peak file data (%2)"), _name, strerror (errno)) << endmsg;
876 _peak_byte_max = max (_peak_byte_max, (off_t) (first_peak_byte + bytes_to_write));
879 Glib::Threads::Mutex::Lock lm (_peaks_ready_lock);
880 PeakRangeReady (first_frame, frames_done); /* EMIT SIGNAL */
881 if (intermediate_peaks_ready) {
882 PeaksReady (); /* EMIT SIGNAL */
890 AudioSource::truncate_peakfile ()
892 if (_peakfile_fd < 0) {
893 error << string_compose (_("programming error: %1"), "AudioSource::truncate_peakfile() called without open peakfile descriptor")
898 /* truncate the peakfile down to its natural length if necessary */
900 off_t end = lseek (_peakfile_fd, 0, SEEK_END);
902 if (end > _peak_byte_max) {
903 DEBUG_TRACE(DEBUG::Peaks, string_compose ("Truncating Peakfile %1\n", peakpath));
904 if (ftruncate (_peakfile_fd, _peak_byte_max)) {
905 error << string_compose (_("could not truncate peakfile %1 to %2 (error: %3)"),
906 peakpath, _peak_byte_max, errno) << endmsg;
912 AudioSource::available_peaks (double zoom_factor) const
914 if (zoom_factor < _FPP) {
915 return length(_timeline_position); // peak data will come from the audio file
918 /* peak data comes from peakfile, but the filesize might not represent
919 the valid data due to ftruncate optimizations, so use _peak_byte_max state.
920 XXX - there might be some atomicity issues here, we should probably add a lock,
921 but _peak_byte_max only monotonically increases after initialization.
924 off_t end = _peak_byte_max;
926 return (end/sizeof(PeakData)) * _FPP;
930 AudioSource::mark_streaming_write_completed ()
932 Glib::Threads::Mutex::Lock lm (_peaks_ready_lock);
935 PeaksReady (); /* EMIT SIGNAL */
940 AudioSource::allocate_working_buffers (framecnt_t framerate)
942 Glib::Threads::Mutex::Lock lm (_level_buffer_lock);
945 /* Note: we don't need any buffers allocated until
946 a level 1 audiosource is created, at which
947 time we'll call ::ensure_buffers_for_level()
948 with the right value and do the right thing.
951 if (!_mixdown_buffers.empty()) {
952 ensure_buffers_for_level_locked ( _mixdown_buffers.size(), framerate);
957 AudioSource::ensure_buffers_for_level (uint32_t level, framecnt_t frame_rate)
959 Glib::Threads::Mutex::Lock lm (_level_buffer_lock);
960 ensure_buffers_for_level_locked (level, frame_rate);
964 AudioSource::ensure_buffers_for_level_locked (uint32_t level, framecnt_t frame_rate)
966 framecnt_t nframes = (framecnt_t) floor (Config->get_audio_playback_buffer_seconds() * frame_rate);
968 /* this may be called because either "level" or "frame_rate" have
969 * changed. and it may be called with "level" smaller than the current
970 * number of buffers, because a new compound region has been created at
971 * a more shallow level than the deepest one we currently have.
974 uint32_t limit = max ((size_t) level, _mixdown_buffers.size());
976 _mixdown_buffers.clear ();
977 _gain_buffers.clear ();
979 for (uint32_t n = 0; n < limit; ++n) {
980 _mixdown_buffers.push_back (boost::shared_array<Sample> (new Sample[nframes]));
981 _gain_buffers.push_back (boost::shared_array<gain_t> (new gain_t[nframes]));