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>
40 #include <glib/gstdio.h>
42 #include <boost/scoped_ptr.hpp>
44 #include <glibmm/fileutils.h>
45 #include <glibmm/miscutils.h>
47 #include "pbd/scoped_file_descriptor.h"
48 #include "pbd/xml++.h"
50 #include "ardour/audiosource.h"
51 #include "ardour/rc_configuration.h"
52 #include "ardour/runtime_functions.h"
56 #include "ardour/debug.h"
59 using namespace ARDOUR;
62 Glib::Threads::Mutex AudioSource::_level_buffer_lock;
63 vector<boost::shared_array<Sample> > AudioSource::_mixdown_buffers;
64 vector<boost::shared_array<gain_t> > AudioSource::_gain_buffers;
65 size_t AudioSource::_working_buffers_size = 0;
66 bool AudioSource::_build_missing_peakfiles = false;
68 /** true if we want peakfiles (e.g. if we are displaying a GUI) */
69 bool AudioSource::_build_peakfiles = false;
73 AudioSource::AudioSource (Session& s, string name)
74 : Source (s, DataType::AUDIO, name)
77 , _peaks_built (false)
79 , peak_leftover_cnt (0)
80 , peak_leftover_size (0)
85 , _last_raw_map_length (0)
89 AudioSource::AudioSource (Session& s, const XMLNode& node)
93 , _peaks_built (false)
95 , peak_leftover_cnt (0)
96 , peak_leftover_size (0)
101 , _last_raw_map_length (0)
103 if (set_state (node, Stateful::loading_state_version)) {
104 throw failed_constructor();
108 AudioSource::~AudioSource ()
110 /* shouldn't happen but make sure we don't leak file descriptors anyway */
112 if (peak_leftover_cnt) {
113 cerr << "AudioSource destroyed with leftover peak data pending" << endl;
116 if ((-1) != _peakfile_fd) {
117 close (_peakfile_fd);
121 delete [] peak_leftovers;
125 AudioSource::get_state ()
127 XMLNode& node (Source::get_state());
129 if (_captured_for.length()) {
130 node.add_property ("captured-for", _captured_for);
137 AudioSource::set_state (const XMLNode& node, int /*version*/)
139 const XMLProperty* prop;
141 if ((prop = node.property ("captured-for")) != 0) {
142 _captured_for = prop->value();
149 AudioSource::empty () const
155 AudioSource::length (framepos_t /*pos*/) const
161 AudioSource::update_length (framecnt_t len)
169 /***********************************************************************
171 ***********************************************************************/
173 /** Checks to see if peaks are ready. If so, we return true. If not, we return false, and
174 * things are set up so that doThisWhenReady is called when the peaks are ready.
175 * A new PBD::ScopedConnection is created for the associated connection and written to
176 * *connect_here_if_not.
178 * @param doThisWhenReady Function to call when peaks are ready (if they are not already).
179 * @param connect_here_if_not Address to write new ScopedConnection to.
180 * @param event_loop Event loop for doThisWhenReady to be called in.
183 AudioSource::peaks_ready (boost::function<void()> doThisWhenReady, ScopedConnection** connect_here_if_not, EventLoop* event_loop) const
186 Glib::Threads::Mutex::Lock lm (_peaks_ready_lock);
188 if (!(ret = _peaks_built)) {
189 *connect_here_if_not = new ScopedConnection;
190 PeaksReady.connect (**connect_here_if_not, MISSING_INVALIDATOR, doThisWhenReady, event_loop);
197 AudioSource::touch_peakfile ()
201 if (g_stat (peakpath.c_str(), &statbuf) != 0 || statbuf.st_size == 0) {
207 tbuf.actime = statbuf.st_atime;
208 tbuf.modtime = time ((time_t*) 0);
210 g_utime (peakpath.c_str(), &tbuf);
214 AudioSource::rename_peakfile (string newpath)
216 /* caller must hold _lock */
218 string oldpath = peakpath;
220 if (Glib::file_test (oldpath, Glib::FILE_TEST_EXISTS)) {
221 if (g_rename (oldpath.c_str(), newpath.c_str()) != 0) {
222 error << string_compose (_("cannot rename peakfile for %1 from %2 to %3 (%4)"), _name, oldpath, newpath, strerror (errno)) << endmsg;
233 AudioSource::initialize_peakfile (string audio_path)
237 peakpath = peak_path (audio_path);
239 DEBUG_TRACE(DEBUG::Peaks, string_compose ("Initialize Peakfile %1 for Audio file %2\n", peakpath, audio_path));
241 /* if the peak file should be there, but isn't .... */
243 if (!empty() && !Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
244 peakpath = find_broken_peakfile (peakpath, audio_path);
247 if (g_stat (peakpath.c_str(), &statbuf)) {
248 if (errno != ENOENT) {
249 /* it exists in the peaks dir, but there is some kind of error */
251 error << string_compose(_("AudioSource: cannot stat peakfile \"%1\""), peakpath) << endmsg;
255 DEBUG_TRACE(DEBUG::Peaks, string_compose("Peakfile %1 does not exist\n", peakpath));
257 _peaks_built = false;
261 /* we found it in the peaks dir, so check it out */
263 if (statbuf.st_size == 0 || (statbuf.st_size < (off_t) ((length(_timeline_position) / _FPP) * sizeof (PeakData)))) {
264 DEBUG_TRACE(DEBUG::Peaks, string_compose("Peakfile %1 is empty\n", peakpath));
265 _peaks_built = false;
267 // Check if the audio file has changed since the peakfile was built.
268 struct stat stat_file;
269 int err = stat (audio_path.c_str(), &stat_file);
273 /* no audio path - nested source or we can't
274 read it or ... whatever, use the peakfile as-is.
276 DEBUG_TRACE(DEBUG::Peaks, string_compose("Error when calling stat on Peakfile %1\n", peakpath));
279 _peak_byte_max = statbuf.st_size;
283 /* allow 6 seconds slop on checking peak vs. file times because of various
287 if (stat_file.st_mtime > statbuf.st_mtime && (stat_file.st_mtime - statbuf.st_mtime > 6)) {
288 _peaks_built = false;
292 _peak_byte_max = statbuf.st_size;
298 if (!empty() && !_peaks_built && _build_missing_peakfiles && _build_peakfiles) {
299 build_peaks_from_scratch ();
306 AudioSource::read (Sample *dst, framepos_t start, framecnt_t cnt, int /*channel*/) const
310 Glib::Threads::Mutex::Lock lm (_lock);
311 return read_unlocked (dst, start, cnt);
315 AudioSource::write (Sample *dst, framecnt_t cnt)
317 Glib::Threads::Mutex::Lock lm (_lock);
318 /* any write makes the file not removable */
319 _flags = Flag (_flags & ~Removable);
320 return write_unlocked (dst, cnt);
324 AudioSource::read_peaks (PeakData *peaks, framecnt_t npeaks, framepos_t start, framecnt_t cnt, double samples_per_visual_peak) const
326 return read_peaks_with_fpp (peaks, npeaks, start, cnt, samples_per_visual_peak, _FPP);
329 /** @param peaks Buffer to write peak data.
330 * @param npeaks Number of peaks to write.
334 AudioSource::read_peaks_with_fpp (PeakData *peaks, framecnt_t npeaks, framepos_t start, framecnt_t cnt,
335 double samples_per_visual_peak, framecnt_t samples_per_file_peak) const
337 Glib::Threads::Mutex::Lock lm (_lock);
339 double expected_peaks;
340 PeakData::PeakDatum xmax;
341 PeakData::PeakDatum xmin;
343 const int bufsize = sysconf(_SC_PAGESIZE);
344 framecnt_t zero_fill = 0;
346 #if defined (PLATFORM_WINDOWS) || defined ( __APPLE__)
347 ScopedFileDescriptor sfd (::open (peakpath.c_str(), O_RDONLY | O_NONBLOCK));
349 ScopedFileDescriptor sfd (::open (peakpath.c_str(), O_RDONLY | O_NOATIME | O_NONBLOCK));
353 error << string_compose (_("Cannot open peakfile @ %1 for reading (%2)"), peakpath, strerror (errno)) << endmsg;
357 expected_peaks = (cnt / (double) samples_per_file_peak);
358 scale = npeaks/expected_peaks;
360 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"
361 , npeaks, start, cnt, _length, samples_per_visual_peak, expected_peaks, scale, peaks));
363 /* fix for near-end-of-file conditions */
365 if (cnt > _length - start) {
366 // cerr << "too close to end @ " << _length << " given " << start << " + " << cnt << " (" << _length - start << ")" << endl;
367 cnt = _length - start;
368 framecnt_t old = npeaks;
369 npeaks = min ((framecnt_t) floor (cnt / samples_per_visual_peak), npeaks);
370 zero_fill = old - npeaks;
373 // cerr << "actual npeaks = " << npeaks << " zf = " << zero_fill << endl;
377 DEBUG_TRACE (DEBUG::Peaks, "RAW DATA\n");
379 /* no scaling at all, just get the sample data and duplicate it for
380 both max and min peak values.
383 boost::scoped_array<Sample> raw_staging(new Sample[cnt]);
385 if (read_unlocked (raw_staging.get(), start, cnt) != cnt) {
386 error << _("cannot read sample data for unscaled peak computation") << endmsg;
390 for (framecnt_t i = 0; i < npeaks; ++i) {
391 peaks[i].max = raw_staging[i];
392 peaks[i].min = raw_staging[i];
399 off_t first_peak_byte = (start / samples_per_file_peak) * sizeof (PeakData);
400 size_t bytes_to_read = sizeof (PeakData)* npeaks;
401 /* open, read, close */
403 DEBUG_TRACE (DEBUG::Peaks, "DIRECT PEAKS\n");
405 off_t map_off = first_peak_byte;
406 off_t read_map_off = map_off & ~(bufsize - 1);
407 off_t map_delta = map_off - read_map_off;
408 size_t map_length = bytes_to_read + map_delta;
410 if (_first_run || (_last_scale != samples_per_visual_peak) || (_last_map_off != map_off) || (_last_raw_map_length < bytes_to_read)) {
411 peak_cache.reset (new PeakData[npeaks]);
412 boost::scoped_array<PeakData> staging (new PeakData[npeaks]);
414 char* addr = (char*) mmap (0, map_length, PROT_READ, MAP_PRIVATE, sfd, read_map_off);
415 if (addr == MAP_FAILED) {
416 error << string_compose (_("map failed - could not mmap peakfile %1."), peakpath) << endmsg;
420 memcpy ((void*)peak_cache.get(), (void*)(addr + map_delta), bytes_to_read);
421 munmap (addr, map_length);
424 memset (&peak_cache[npeaks], 0, sizeof (PeakData) * zero_fill);
428 _last_scale = samples_per_visual_peak;
429 _last_map_off = map_off;
430 _last_raw_map_length = bytes_to_read;
433 memcpy ((void*)peaks, (void*)peak_cache.get(), npeaks * sizeof(PeakData));
440 DEBUG_TRACE (DEBUG::Peaks, "DOWNSAMPLE\n");
444 - more frames-per-peak (lower resolution) than the peakfile, or to put it another way,
445 - less peaks than the peakfile holds for the same range
447 So, read a block into a staging area, and then downsample from there.
449 to avoid confusion, I'll refer to the requested peaks as visual_peaks and the peakfile peaks as stored_peaks
452 const framecnt_t chunksize = (framecnt_t) expected_peaks; // we read all the peaks we need in one hit.
454 /* compute the rounded up frame position */
456 framepos_t current_stored_peak = (framepos_t) ceil (start / (double) samples_per_file_peak);
457 framepos_t next_visual_peak = (framepos_t) ceil (start / samples_per_visual_peak);
458 double next_visual_peak_frame = next_visual_peak * samples_per_visual_peak;
459 framepos_t stored_peak_before_next_visual_peak = (framepos_t) next_visual_peak_frame / samples_per_file_peak;
460 framecnt_t nvisual_peaks = 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 off_t map_off = (uint32_t) (ceil (start / (double) samples_per_file_peak)) * sizeof(PeakData);
470 off_t read_map_off = map_off & ~(bufsize - 1);
471 off_t map_delta = map_off - read_map_off;
472 size_t raw_map_length = chunksize * sizeof(PeakData);
473 size_t map_length = (chunksize * sizeof(PeakData)) + map_delta;
475 if (_first_run || (_last_scale != samples_per_visual_peak) || (_last_map_off != map_off) || (_last_raw_map_length < raw_map_length)) {
476 peak_cache.reset (new PeakData[npeaks]);
477 boost::scoped_array<PeakData> staging (new PeakData[chunksize]);
480 addr = (char*) mmap (0, map_length, PROT_READ, MAP_PRIVATE, sfd, read_map_off);
481 if (addr == MAP_FAILED) {
482 error << string_compose (_("map failed - could not mmap peakfile %1."), peakpath) << endmsg;
486 memcpy ((void*)staging.get(), (void*)(addr + map_delta), raw_map_length);
487 munmap (addr, map_length);
489 while (nvisual_peaks < npeaks) {
494 while ((current_stored_peak <= stored_peak_before_next_visual_peak) && (i < raw_map_length)) {
496 xmax = max (xmax, staging[i].max);
497 xmin = min (xmin, staging[i].min);
499 ++current_stored_peak;
502 peak_cache[nvisual_peaks].max = xmax;
503 peak_cache[nvisual_peaks].min = xmin;
505 next_visual_peak_frame = min ((double) start + cnt, (next_visual_peak_frame + samples_per_visual_peak));
506 stored_peak_before_next_visual_peak = (uint32_t) next_visual_peak_frame / samples_per_file_peak;
510 cerr << "Zero fill end of peaks (@ " << npeaks << " with " << zero_fill << endl;
511 memset (&peak_cache[npeaks], 0, sizeof (PeakData) * zero_fill);
515 _last_scale = samples_per_visual_peak;
516 _last_map_off = map_off;
517 _last_raw_map_length = raw_map_length;
520 memcpy ((void*)peaks, (void*)peak_cache.get(), npeaks * sizeof(PeakData));
523 DEBUG_TRACE (DEBUG::Peaks, "UPSAMPLE\n");
527 - less frames-per-peak (more resolution)
528 - more peaks than stored in the Peakfile
530 So, fetch data from the raw source, and generate peak
534 framecnt_t frames_read = 0;
535 framepos_t current_frame = start;
537 framecnt_t nvisual_peaks = 0;
538 framecnt_t chunksize = (framecnt_t) min (cnt, (framecnt_t) 4096);
539 boost::scoped_array<Sample> raw_staging(new Sample[chunksize]);
541 framepos_t frame_pos = start;
542 double pixel_pos = floor (frame_pos / samples_per_visual_peak);
543 double next_pixel_pos = ceil (frame_pos / samples_per_visual_peak);
544 double pixels_per_frame = 1.0 / samples_per_visual_peak;
549 while (nvisual_peaks < npeaks) {
551 if (i == frames_read) {
553 to_read = min (chunksize, (framecnt_t)(_length - current_frame));
555 if (current_frame >= _length) {
557 /* hmm, error condition - we've reached the end of the file
558 without generating all the peak data. cook up a zero-filled
559 data buffer and then use it. this is simpler than
560 adjusting zero_fill and npeaks and then breaking out of
564 memset (raw_staging.get(), 0, sizeof (Sample) * chunksize);
568 to_read = min (chunksize, (_length - current_frame));
571 if ((frames_read = read_unlocked (raw_staging.get(), current_frame, to_read)) == 0) {
572 error << string_compose(_("AudioSource[%1]: peak read - cannot read %2 samples at offset %3 of %4 (%5)"),
573 _name, to_read, current_frame, _length, strerror (errno))
582 xmax = max (xmax, raw_staging[i]);
583 xmin = min (xmin, raw_staging[i]);
586 pixel_pos += pixels_per_frame;
588 if (pixel_pos >= next_pixel_pos) {
590 peaks[nvisual_peaks].max = xmax;
591 peaks[nvisual_peaks].min = xmin;
596 next_pixel_pos = ceil (pixel_pos + 0.5);
601 memset (&peaks[npeaks], 0, sizeof (PeakData) * zero_fill);
605 DEBUG_TRACE (DEBUG::Peaks, "READPEAKS DONE\n");
610 AudioSource::build_peaks_from_scratch ()
612 const framecnt_t bufsize = 65536; // 256kB per disk read for mono data is about ideal
614 DEBUG_TRACE (DEBUG::Peaks, "Building peaks from scratch\n");
619 /* hold lock while building peaks */
621 Glib::Threads::Mutex::Lock lp (_lock);
623 if (prepare_for_peakfile_writes ()) {
627 framecnt_t current_frame = 0;
628 framecnt_t cnt = _length;
630 _peaks_built = false;
631 boost::scoped_array<Sample> buf(new Sample[bufsize]);
635 framecnt_t frames_to_read = min (bufsize, cnt);
636 framecnt_t frames_read;
638 if ((frames_read = read_unlocked (buf.get(), current_frame, frames_to_read)) != frames_to_read) {
639 error << string_compose(_("%1: could not write read raw data for peak computation (%2)"), _name, strerror (errno)) << endmsg;
640 done_with_peakfile_writes (false);
644 if (compute_and_write_peaks (buf.get(), current_frame, frames_read, true, false, _FPP)) {
648 current_frame += frames_read;
657 done_with_peakfile_writes ((cnt == 0));
665 DEBUG_TRACE (DEBUG::Peaks, string_compose("Could not write peak data, attempting to remove peakfile %1\n", peakpath));
666 ::g_unlink (peakpath.c_str());
673 AudioSource::prepare_for_peakfile_writes ()
675 if ((_peakfile_fd = open (peakpath.c_str(), O_CREAT|O_RDWR, 0664)) < 0) {
676 error << string_compose(_("AudioSource: cannot open peakpath (c) \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
683 AudioSource::done_with_peakfile_writes (bool done)
685 if (peak_leftover_cnt) {
686 compute_and_write_peaks (0, 0, 0, true, false, _FPP);
690 Glib::Threads::Mutex::Lock lm (_peaks_ready_lock);
692 PeaksReady (); /* EMIT SIGNAL */
695 close (_peakfile_fd);
699 /** @param first_frame Offset from the source start of the first frame to process */
701 AudioSource::compute_and_write_peaks (Sample* buf, framecnt_t first_frame, framecnt_t cnt,
702 bool force, bool intermediate_peaks_ready)
704 return compute_and_write_peaks (buf, first_frame, cnt, force, intermediate_peaks_ready, _FPP);
708 AudioSource::compute_and_write_peaks (Sample* buf, framecnt_t first_frame, framecnt_t cnt,
709 bool force, bool intermediate_peaks_ready, framecnt_t fpp)
712 uint32_t peaks_computed;
713 framepos_t current_frame;
714 framecnt_t frames_done;
715 const size_t blocksize = (128 * 1024);
716 off_t first_peak_byte;
717 boost::scoped_array<Sample> buf2;
719 if (_peakfile_fd < 0) {
720 if (prepare_for_peakfile_writes ()) {
726 if (peak_leftover_cnt) {
728 if (first_frame != peak_leftover_frame + peak_leftover_cnt) {
730 /* uh-oh, ::seek() since the last ::compute_and_write_peaks(),
731 and we have leftovers. flush a single peak (since the leftovers
732 never represent more than that, and restart.
737 x.min = peak_leftovers[0];
738 x.max = peak_leftovers[0];
740 off_t byte = (peak_leftover_frame / fpp) * sizeof (PeakData);
742 off_t offset = lseek (_peakfile_fd, byte, SEEK_SET);
744 if (offset != byte) {
745 error << string_compose(_("%1: could not seek in peak file data (%2)"), _name, strerror (errno)) << endmsg;
749 if (::write (_peakfile_fd, &x, sizeof (PeakData)) != sizeof (PeakData)) {
750 error << string_compose(_("%1: could not write peak file data (%2)"), _name, strerror (errno)) << endmsg;
754 _peak_byte_max = max (_peak_byte_max, (off_t) (byte + sizeof(PeakData)));
757 Glib::Threads::Mutex::Lock lm (_peaks_ready_lock);
758 PeakRangeReady (peak_leftover_frame, peak_leftover_cnt); /* EMIT SIGNAL */
759 if (intermediate_peaks_ready) {
760 PeaksReady (); /* EMIT SIGNAL */
764 /* left overs are done */
766 peak_leftover_cnt = 0;
770 /* else ... had leftovers, but they immediately preceed the new data, so just
771 merge them and compute.
774 /* make a new contiguous buffer containing leftovers and the new stuff */
776 to_do = cnt + peak_leftover_cnt;
777 buf2.reset(new Sample[to_do]);
780 memcpy (buf2.get(), peak_leftovers, peak_leftover_cnt * sizeof (Sample));
783 memcpy (buf2.get()+peak_leftover_cnt, buf, cnt * sizeof (Sample));
785 /* no more leftovers */
786 peak_leftover_cnt = 0;
788 /* use the temporary buffer */
791 /* make sure that when we write into the peakfile, we startup where we left off */
793 first_frame = peak_leftover_frame;
799 boost::scoped_array<PeakData> peakbuf(new PeakData[(to_do/fpp)+1]);
801 current_frame = first_frame;
806 /* if some frames were passed in (i.e. we're not flushing leftovers)
807 and there are less than fpp to do, save them till
811 if (force && (to_do < fpp)) {
812 /* keep the left overs around for next time */
814 if (peak_leftover_size < to_do) {
815 delete [] peak_leftovers;
816 peak_leftovers = new Sample[to_do];
817 peak_leftover_size = to_do;
819 memcpy (peak_leftovers, buf, to_do * sizeof (Sample));
820 peak_leftover_cnt = to_do;
821 peak_leftover_frame = current_frame;
828 framecnt_t this_time = min (fpp, to_do);
830 peakbuf[peaks_computed].max = buf[0];
831 peakbuf[peaks_computed].min = buf[0];
833 ARDOUR::find_peaks (buf+1, this_time-1, &peakbuf[peaks_computed].min, &peakbuf[peaks_computed].max);
838 frames_done += this_time;
839 current_frame += this_time;
842 first_peak_byte = (first_frame / fpp) * sizeof (PeakData);
844 if (can_truncate_peaks()) {
846 /* on some filesystems (ext3, at least) this helps to reduce fragmentation of
847 the peakfiles. its not guaranteed to do so, and even on ext3 (as of december 2006)
848 it does not cause single-extent allocation even for peakfiles of
849 less than BLOCKSIZE bytes. only call ftruncate if we'll make the file larger.
852 off_t endpos = lseek (_peakfile_fd, 0, SEEK_END);
853 off_t target_length = blocksize * ((first_peak_byte + blocksize + 1) / blocksize);
855 if (endpos < target_length) {
856 DEBUG_TRACE(DEBUG::Peaks, string_compose ("Truncating Peakfile %1\n", peakpath));
857 if (ftruncate (_peakfile_fd, target_length)) {
858 /* error doesn't actually matter so continue on without testing */
864 off_t offset = lseek(_peakfile_fd, first_peak_byte, SEEK_SET);
866 if (offset != first_peak_byte) {
867 error << string_compose(_("%1: could not seek in peak file data (%2)"), _name, strerror (errno)) << endmsg;
871 ssize_t bytes_to_write = sizeof (PeakData) * peaks_computed;
873 ssize_t bytes_written = ::write (_peakfile_fd, peakbuf.get(), bytes_to_write);
875 if (bytes_written != bytes_to_write) {
876 error << string_compose(_("%1: could not write peak file data (%2)"), _name, strerror (errno)) << endmsg;
880 _peak_byte_max = max (_peak_byte_max, (off_t) (first_peak_byte + bytes_to_write));
883 Glib::Threads::Mutex::Lock lm (_peaks_ready_lock);
884 PeakRangeReady (first_frame, frames_done); /* EMIT SIGNAL */
885 if (intermediate_peaks_ready) {
886 PeaksReady (); /* EMIT SIGNAL */
894 AudioSource::truncate_peakfile ()
896 if (_peakfile_fd < 0) {
897 error << string_compose (_("programming error: %1"), "AudioSource::truncate_peakfile() called without open peakfile descriptor")
902 /* truncate the peakfile down to its natural length if necessary */
904 off_t end = lseek (_peakfile_fd, 0, SEEK_END);
906 if (end > _peak_byte_max) {
907 DEBUG_TRACE(DEBUG::Peaks, string_compose ("Truncating Peakfile %1\n", peakpath));
908 if (ftruncate (_peakfile_fd, _peak_byte_max)) {
909 error << string_compose (_("could not truncate peakfile %1 to %2 (error: %3)"),
910 peakpath, _peak_byte_max, errno) << endmsg;
916 AudioSource::available_peaks (double zoom_factor) const
918 if (zoom_factor < _FPP) {
919 return length(_timeline_position); // peak data will come from the audio file
922 /* peak data comes from peakfile, but the filesize might not represent
923 the valid data due to ftruncate optimizations, so use _peak_byte_max state.
924 XXX - there might be some atomicity issues here, we should probably add a lock,
925 but _peak_byte_max only monotonically increases after initialization.
928 off_t end = _peak_byte_max;
930 return (end/sizeof(PeakData)) * _FPP;
934 AudioSource::mark_streaming_write_completed (const Lock& lock)
936 Glib::Threads::Mutex::Lock lm (_peaks_ready_lock);
939 PeaksReady (); /* EMIT SIGNAL */
944 AudioSource::allocate_working_buffers (framecnt_t framerate)
946 Glib::Threads::Mutex::Lock lm (_level_buffer_lock);
949 /* Note: we don't need any buffers allocated until
950 a level 1 audiosource is created, at which
951 time we'll call ::ensure_buffers_for_level()
952 with the right value and do the right thing.
955 if (!_mixdown_buffers.empty()) {
956 ensure_buffers_for_level_locked ( _mixdown_buffers.size(), framerate);
961 AudioSource::ensure_buffers_for_level (uint32_t level, framecnt_t frame_rate)
963 Glib::Threads::Mutex::Lock lm (_level_buffer_lock);
964 ensure_buffers_for_level_locked (level, frame_rate);
968 AudioSource::ensure_buffers_for_level_locked (uint32_t level, framecnt_t frame_rate)
970 framecnt_t nframes = (framecnt_t) floor (Config->get_audio_playback_buffer_seconds() * frame_rate);
972 /* this may be called because either "level" or "frame_rate" have
973 * changed. and it may be called with "level" smaller than the current
974 * number of buffers, because a new compound region has been created at
975 * a more shallow level than the deepest one we currently have.
978 uint32_t limit = max ((size_t) level, _mixdown_buffers.size());
980 _mixdown_buffers.clear ();
981 _gain_buffers.clear ();
983 for (uint32_t n = 0; n < limit; ++n) {
984 _mixdown_buffers.push_back (boost::shared_array<Sample> (new Sample[nframes]));
985 _gain_buffers.push_back (boost::shared_array<gain_t> (new gain_t[nframes]));