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>
37 #ifdef PLATFORM_WINDOWS
46 #include <glib/gstdio.h>
48 #include <boost/scoped_ptr.hpp>
50 #include <glibmm/fileutils.h>
51 #include <glibmm/miscutils.h>
53 #include "pbd/scoped_file_descriptor.h"
54 #include "pbd/xml++.h"
56 #include "ardour/audiosource.h"
57 #include "ardour/rc_configuration.h"
58 #include "ardour/runtime_functions.h"
62 #include "ardour/debug.h"
65 using namespace ARDOUR;
68 Glib::Threads::Mutex AudioSource::_level_buffer_lock;
69 vector<boost::shared_array<Sample> > AudioSource::_mixdown_buffers;
70 vector<boost::shared_array<gain_t> > AudioSource::_gain_buffers;
71 size_t AudioSource::_working_buffers_size = 0;
72 bool AudioSource::_build_missing_peakfiles = false;
74 /** true if we want peakfiles (e.g. if we are displaying a GUI) */
75 bool AudioSource::_build_peakfiles = false;
79 AudioSource::AudioSource (Session& s, string name)
80 : Source (s, DataType::AUDIO, name)
83 , _peaks_built (false)
85 , peak_leftover_cnt (0)
86 , peak_leftover_size (0)
91 , _last_raw_map_length (0)
95 AudioSource::AudioSource (Session& s, const XMLNode& node)
99 , _peaks_built (false)
101 , peak_leftover_cnt (0)
102 , peak_leftover_size (0)
107 , _last_raw_map_length (0)
109 if (set_state (node, Stateful::loading_state_version)) {
110 throw failed_constructor();
114 AudioSource::~AudioSource ()
116 /* shouldn't happen but make sure we don't leak file descriptors anyway */
118 if (peak_leftover_cnt) {
119 cerr << "AudioSource destroyed with leftover peak data pending" << endl;
122 if ((-1) != _peakfile_fd) {
123 close (_peakfile_fd);
127 delete [] peak_leftovers;
131 AudioSource::get_state ()
133 XMLNode& node (Source::get_state());
135 if (_captured_for.length()) {
136 node.add_property ("captured-for", _captured_for);
143 AudioSource::set_state (const XMLNode& node, int /*version*/)
145 const XMLProperty* prop;
147 if ((prop = node.property ("captured-for")) != 0) {
148 _captured_for = prop->value();
155 AudioSource::empty () const
161 AudioSource::length (framepos_t /*pos*/) const
167 AudioSource::update_length (framecnt_t len)
175 /***********************************************************************
177 ***********************************************************************/
179 /** Checks to see if peaks are ready. If so, we return true. If not, we return false, and
180 * things are set up so that doThisWhenReady is called when the peaks are ready.
181 * A new PBD::ScopedConnection is created for the associated connection and written to
182 * *connect_here_if_not.
184 * @param doThisWhenReady Function to call when peaks are ready (if they are not already).
185 * @param connect_here_if_not Address to write new ScopedConnection to.
186 * @param event_loop Event loop for doThisWhenReady to be called in.
189 AudioSource::peaks_ready (boost::function<void()> doThisWhenReady, ScopedConnection** connect_here_if_not, EventLoop* event_loop) const
192 Glib::Threads::Mutex::Lock lm (_peaks_ready_lock);
194 if (!(ret = _peaks_built)) {
195 *connect_here_if_not = new ScopedConnection;
196 PeaksReady.connect (**connect_here_if_not, MISSING_INVALIDATOR, doThisWhenReady, event_loop);
203 AudioSource::touch_peakfile ()
207 if (g_stat (peakpath.c_str(), &statbuf) != 0 || statbuf.st_size == 0) {
213 tbuf.actime = statbuf.st_atime;
214 tbuf.modtime = time ((time_t*) 0);
216 g_utime (peakpath.c_str(), &tbuf);
220 AudioSource::rename_peakfile (string newpath)
222 /* caller must hold _lock */
224 string oldpath = peakpath;
226 if (Glib::file_test (oldpath, Glib::FILE_TEST_EXISTS)) {
227 if (g_rename (oldpath.c_str(), newpath.c_str()) != 0) {
228 error << string_compose (_("cannot rename peakfile for %1 from %2 to %3 (%4)"), _name, oldpath, newpath, strerror (errno)) << endmsg;
239 AudioSource::initialize_peakfile (string audio_path)
243 peakpath = peak_path (audio_path);
245 DEBUG_TRACE(DEBUG::Peaks, string_compose ("Initialize Peakfile %1 for Audio file %2\n", peakpath, audio_path));
247 /* if the peak file should be there, but isn't .... */
249 if (!empty() && !Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
250 peakpath = find_broken_peakfile (peakpath, audio_path);
253 if (g_stat (peakpath.c_str(), &statbuf)) {
254 if (errno != ENOENT) {
255 /* it exists in the peaks dir, but there is some kind of error */
257 error << string_compose(_("AudioSource: cannot stat peakfile \"%1\""), peakpath) << endmsg;
261 DEBUG_TRACE(DEBUG::Peaks, string_compose("Peakfile %1 does not exist\n", peakpath));
263 _peaks_built = false;
267 /* we found it in the peaks dir, so check it out */
269 if (statbuf.st_size == 0 || (statbuf.st_size < (off_t) ((length(_timeline_position) / _FPP) * sizeof (PeakData)))) {
270 DEBUG_TRACE(DEBUG::Peaks, string_compose("Peakfile %1 is empty\n", peakpath));
271 _peaks_built = false;
273 // Check if the audio file has changed since the peakfile was built.
274 struct stat stat_file;
275 int err = stat (audio_path.c_str(), &stat_file);
279 /* no audio path - nested source or we can't
280 read it or ... whatever, use the peakfile as-is.
282 DEBUG_TRACE(DEBUG::Peaks, string_compose("Error when calling stat on Peakfile %1\n", peakpath));
285 _peak_byte_max = statbuf.st_size;
289 /* allow 6 seconds slop on checking peak vs. file times because of various
293 if (stat_file.st_mtime > statbuf.st_mtime && (stat_file.st_mtime - statbuf.st_mtime > 6)) {
294 _peaks_built = false;
298 _peak_byte_max = statbuf.st_size;
304 if (!empty() && !_peaks_built && _build_missing_peakfiles && _build_peakfiles) {
305 build_peaks_from_scratch ();
312 AudioSource::read (Sample *dst, framepos_t start, framecnt_t cnt, int /*channel*/) const
316 Glib::Threads::Mutex::Lock lm (_lock);
317 return read_unlocked (dst, start, cnt);
321 AudioSource::write (Sample *dst, framecnt_t cnt)
323 Glib::Threads::Mutex::Lock lm (_lock);
324 /* any write makes the file not removable */
325 _flags = Flag (_flags & ~Removable);
326 return write_unlocked (dst, cnt);
330 AudioSource::read_peaks (PeakData *peaks, framecnt_t npeaks, framepos_t start, framecnt_t cnt, double samples_per_visual_peak) const
332 return read_peaks_with_fpp (peaks, npeaks, start, cnt, samples_per_visual_peak, _FPP);
335 /** @param peaks Buffer to write peak data.
336 * @param npeaks Number of peaks to write.
340 AudioSource::read_peaks_with_fpp (PeakData *peaks, framecnt_t npeaks, framepos_t start, framecnt_t cnt,
341 double samples_per_visual_peak, framecnt_t samples_per_file_peak) const
343 Glib::Threads::Mutex::Lock lm (_lock);
345 double expected_peaks;
346 PeakData::PeakDatum xmax;
347 PeakData::PeakDatum xmin;
349 #ifdef PLATFORM_WINDOWS
350 SYSTEM_INFO system_info;
351 GetSystemInfo (&system_info);
352 const int bufsize = system_info.dwAllocationGranularity;;
354 const int bufsize = sysconf(_SC_PAGESIZE);
356 framecnt_t zero_fill = 0;
358 #ifdef PLATFORM_WINDOWS
359 ScopedFileDescriptor sfd (::open (peakpath.c_str(), O_RDONLY));
360 #elif defined (__APPLE__)
361 ScopedFileDescriptor sfd (::open (peakpath.c_str(), O_RDONLY | O_NONBLOCK));
363 ScopedFileDescriptor sfd (::open (peakpath.c_str(), O_RDONLY | O_NOATIME | O_NONBLOCK));
367 error << string_compose (_("Cannot open peakfile @ %1 for reading (%2)"), peakpath, strerror (errno)) << endmsg;
371 expected_peaks = (cnt / (double) samples_per_file_peak);
372 scale = npeaks/expected_peaks;
374 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"
375 , npeaks, start, cnt, _length, samples_per_visual_peak, expected_peaks, scale, peaks));
377 /* fix for near-end-of-file conditions */
379 if (cnt > _length - start) {
380 // cerr << "too close to end @ " << _length << " given " << start << " + " << cnt << " (" << _length - start << ")" << endl;
381 cnt = _length - start;
382 framecnt_t old = npeaks;
383 npeaks = min ((framecnt_t) floor (cnt / samples_per_visual_peak), npeaks);
384 zero_fill = old - npeaks;
387 // cerr << "actual npeaks = " << npeaks << " zf = " << zero_fill << endl;
391 DEBUG_TRACE (DEBUG::Peaks, "RAW DATA\n");
393 /* no scaling at all, just get the sample data and duplicate it for
394 both max and min peak values.
397 boost::scoped_array<Sample> raw_staging(new Sample[cnt]);
399 if (read_unlocked (raw_staging.get(), start, cnt) != cnt) {
400 error << _("cannot read sample data for unscaled peak computation") << endmsg;
404 for (framecnt_t i = 0; i < npeaks; ++i) {
405 peaks[i].max = raw_staging[i];
406 peaks[i].min = raw_staging[i];
413 off_t first_peak_byte = (start / samples_per_file_peak) * sizeof (PeakData);
414 size_t bytes_to_read = sizeof (PeakData)* npeaks;
415 /* open, read, close */
417 DEBUG_TRACE (DEBUG::Peaks, "DIRECT PEAKS\n");
419 off_t map_off = first_peak_byte;
420 off_t read_map_off = map_off & ~(bufsize - 1);
421 off_t map_delta = map_off - read_map_off;
422 size_t map_length = bytes_to_read + map_delta;
424 if (_first_run || (_last_scale != samples_per_visual_peak) || (_last_map_off != map_off) || (_last_raw_map_length < bytes_to_read)) {
425 peak_cache.reset (new PeakData[npeaks]);
426 boost::scoped_array<PeakData> staging (new PeakData[npeaks]);
428 #ifdef PLATFORM_WINDOWS
429 HANDLE file_handle = (HANDLE) _get_osfhandle(int(sfd));
434 map_handle = CreateFileMapping(file_handle, NULL, PAGE_READONLY, 0, 0, NULL);
435 if (map_handle == NULL) {
436 error << string_compose (_("map failed - could not create file mapping for peakfile %1."), peakpath) << endmsg;
440 view_handle = MapViewOfFile(map_handle, FILE_MAP_READ, 0, read_map_off, map_length);
441 if (view_handle == NULL) {
442 error << string_compose (_("map failed - could not map peakfile %1."), peakpath) << endmsg;
446 addr = (char*) view_handle;
448 memcpy ((void*)peak_cache.get(), (void*)(addr + map_delta), bytes_to_read);
450 err_flag = UnmapViewOfFile (view_handle);
451 err_flag = CloseHandle(map_handle);
453 error << string_compose (_("unmap failed - could not unmap peakfile %1."), peakpath) << endmsg;
457 addr = (char*) mmap (0, map_length, PROT_READ, MAP_PRIVATE, sfd, read_map_off);
458 if (addr == MAP_FAILED) {
459 error << string_compose (_("map failed - could not mmap peakfile %1."), peakpath) << endmsg;
463 memcpy ((void*)peak_cache.get(), (void*)(addr + map_delta), bytes_to_read);
464 munmap (addr, map_length);
467 memset (&peak_cache[npeaks], 0, sizeof (PeakData) * zero_fill);
471 _last_scale = samples_per_visual_peak;
472 _last_map_off = map_off;
473 _last_raw_map_length = bytes_to_read;
476 memcpy ((void*)peaks, (void*)peak_cache.get(), npeaks * sizeof(PeakData));
483 DEBUG_TRACE (DEBUG::Peaks, "DOWNSAMPLE\n");
487 - more frames-per-peak (lower resolution) than the peakfile, or to put it another way,
488 - less peaks than the peakfile holds for the same range
490 So, read a block into a staging area, and then downsample from there.
492 to avoid confusion, I'll refer to the requested peaks as visual_peaks and the peakfile peaks as stored_peaks
495 const framecnt_t chunksize = (framecnt_t) expected_peaks; // we read all the peaks we need in one hit.
497 /* compute the rounded up frame position */
499 framepos_t current_stored_peak = (framepos_t) ceil (start / (double) samples_per_file_peak);
500 framepos_t next_visual_peak = (framepos_t) ceil (start / samples_per_visual_peak);
501 double next_visual_peak_frame = next_visual_peak * samples_per_visual_peak;
502 framepos_t stored_peak_before_next_visual_peak = (framepos_t) next_visual_peak_frame / samples_per_file_peak;
503 framecnt_t nvisual_peaks = 0;
506 /* handle the case where the initial visual peak is on a pixel boundary */
508 current_stored_peak = min (current_stored_peak, stored_peak_before_next_visual_peak);
510 /* open ... close during out: handling */
512 off_t map_off = (uint32_t) (ceil (start / (double) samples_per_file_peak)) * sizeof(PeakData);
513 off_t read_map_off = map_off & ~(bufsize - 1);
514 off_t map_delta = map_off - read_map_off;
515 size_t raw_map_length = chunksize * sizeof(PeakData);
516 size_t map_length = (chunksize * sizeof(PeakData)) + map_delta;
518 if (_first_run || (_last_scale != samples_per_visual_peak) || (_last_map_off != map_off) || (_last_raw_map_length < raw_map_length)) {
519 peak_cache.reset (new PeakData[npeaks]);
520 boost::scoped_array<PeakData> staging (new PeakData[chunksize]);
523 #ifdef PLATFORM_WINDOWS
524 HANDLE file_handle = (HANDLE) _get_osfhandle(int(sfd));
529 map_handle = CreateFileMapping(file_handle, NULL, PAGE_READONLY, 0, 0, NULL);
530 if (map_handle == NULL) {
531 error << string_compose (_("map failed - could not create file mapping for peakfile %1."), peakpath) << endmsg;
535 view_handle = MapViewOfFile(map_handle, FILE_MAP_READ, 0, read_map_off, map_length);
536 if (view_handle == NULL) {
537 error << string_compose (_("map failed - could not map peakfile %1."), peakpath) << endmsg;
541 addr = (char *) view_handle;
543 memcpy ((void*)staging.get(), (void*)(addr + map_delta), raw_map_length);
545 err_flag = UnmapViewOfFile (view_handle);
546 err_flag = CloseHandle(map_handle);
548 error << string_compose (_("unmap failed - could not unmap peakfile %1."), peakpath) << endmsg;
552 addr = (char*) mmap (0, map_length, PROT_READ, MAP_PRIVATE, sfd, read_map_off);
553 if (addr == MAP_FAILED) {
554 error << string_compose (_("map failed - could not mmap peakfile %1."), peakpath) << endmsg;
558 memcpy ((void*)staging.get(), (void*)(addr + map_delta), raw_map_length);
559 munmap (addr, map_length);
561 while (nvisual_peaks < npeaks) {
566 while ((current_stored_peak <= stored_peak_before_next_visual_peak) && (i < raw_map_length)) {
568 xmax = max (xmax, staging[i].max);
569 xmin = min (xmin, staging[i].min);
571 ++current_stored_peak;
574 peak_cache[nvisual_peaks].max = xmax;
575 peak_cache[nvisual_peaks].min = xmin;
577 next_visual_peak_frame = min ((double) start + cnt, (next_visual_peak_frame + samples_per_visual_peak));
578 stored_peak_before_next_visual_peak = (uint32_t) next_visual_peak_frame / samples_per_file_peak;
582 cerr << "Zero fill end of peaks (@ " << npeaks << " with " << zero_fill << endl;
583 memset (&peak_cache[npeaks], 0, sizeof (PeakData) * zero_fill);
587 _last_scale = samples_per_visual_peak;
588 _last_map_off = map_off;
589 _last_raw_map_length = raw_map_length;
592 memcpy ((void*)peaks, (void*)peak_cache.get(), npeaks * sizeof(PeakData));
595 DEBUG_TRACE (DEBUG::Peaks, "UPSAMPLE\n");
599 - less frames-per-peak (more resolution)
600 - more peaks than stored in the Peakfile
602 So, fetch data from the raw source, and generate peak
606 framecnt_t frames_read = 0;
607 framepos_t current_frame = start;
609 framecnt_t nvisual_peaks = 0;
610 framecnt_t chunksize = (framecnt_t) min (cnt, (framecnt_t) 4096);
611 boost::scoped_array<Sample> raw_staging(new Sample[chunksize]);
613 framepos_t frame_pos = start;
614 double pixel_pos = floor (frame_pos / samples_per_visual_peak);
615 double next_pixel_pos = ceil (frame_pos / samples_per_visual_peak);
616 double pixels_per_frame = 1.0 / samples_per_visual_peak;
621 while (nvisual_peaks < npeaks) {
623 if (i == frames_read) {
625 to_read = min (chunksize, (framecnt_t)(_length - current_frame));
627 if (current_frame >= _length) {
629 /* hmm, error condition - we've reached the end of the file
630 without generating all the peak data. cook up a zero-filled
631 data buffer and then use it. this is simpler than
632 adjusting zero_fill and npeaks and then breaking out of
636 memset (raw_staging.get(), 0, sizeof (Sample) * chunksize);
640 to_read = min (chunksize, (_length - current_frame));
643 if ((frames_read = read_unlocked (raw_staging.get(), current_frame, to_read)) == 0) {
644 error << string_compose(_("AudioSource[%1]: peak read - cannot read %2 samples at offset %3 of %4 (%5)"),
645 _name, to_read, current_frame, _length, strerror (errno))
654 xmax = max (xmax, raw_staging[i]);
655 xmin = min (xmin, raw_staging[i]);
658 pixel_pos += pixels_per_frame;
660 if (pixel_pos >= next_pixel_pos) {
662 peaks[nvisual_peaks].max = xmax;
663 peaks[nvisual_peaks].min = xmin;
668 next_pixel_pos = ceil (pixel_pos + 0.5);
673 memset (&peaks[npeaks], 0, sizeof (PeakData) * zero_fill);
677 DEBUG_TRACE (DEBUG::Peaks, "READPEAKS DONE\n");
682 AudioSource::build_peaks_from_scratch ()
684 const framecnt_t bufsize = 65536; // 256kB per disk read for mono data is about ideal
686 DEBUG_TRACE (DEBUG::Peaks, "Building peaks from scratch\n");
691 /* hold lock while building peaks */
693 Glib::Threads::Mutex::Lock lp (_lock);
695 if (prepare_for_peakfile_writes ()) {
699 framecnt_t current_frame = 0;
700 framecnt_t cnt = _length;
702 _peaks_built = false;
703 boost::scoped_array<Sample> buf(new Sample[bufsize]);
707 framecnt_t frames_to_read = min (bufsize, cnt);
708 framecnt_t frames_read;
710 if ((frames_read = read_unlocked (buf.get(), current_frame, frames_to_read)) != frames_to_read) {
711 error << string_compose(_("%1: could not write read raw data for peak computation (%2)"), _name, strerror (errno)) << endmsg;
712 done_with_peakfile_writes (false);
716 if (compute_and_write_peaks (buf.get(), current_frame, frames_read, true, false, _FPP)) {
720 current_frame += frames_read;
729 done_with_peakfile_writes ((cnt == 0));
737 DEBUG_TRACE (DEBUG::Peaks, string_compose("Could not write peak data, attempting to remove peakfile %1\n", peakpath));
738 ::g_unlink (peakpath.c_str());
745 AudioSource::prepare_for_peakfile_writes ()
747 if ((_peakfile_fd = open (peakpath.c_str(), O_CREAT|O_RDWR, 0664)) < 0) {
748 error << string_compose(_("AudioSource: cannot open peakpath (c) \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
755 AudioSource::done_with_peakfile_writes (bool done)
757 if (peak_leftover_cnt) {
758 compute_and_write_peaks (0, 0, 0, true, false, _FPP);
762 Glib::Threads::Mutex::Lock lm (_peaks_ready_lock);
764 PeaksReady (); /* EMIT SIGNAL */
767 close (_peakfile_fd);
771 /** @param first_frame Offset from the source start of the first frame to process */
773 AudioSource::compute_and_write_peaks (Sample* buf, framecnt_t first_frame, framecnt_t cnt,
774 bool force, bool intermediate_peaks_ready)
776 return compute_and_write_peaks (buf, first_frame, cnt, force, intermediate_peaks_ready, _FPP);
780 AudioSource::compute_and_write_peaks (Sample* buf, framecnt_t first_frame, framecnt_t cnt,
781 bool force, bool intermediate_peaks_ready, framecnt_t fpp)
784 uint32_t peaks_computed;
785 framepos_t current_frame;
786 framecnt_t frames_done;
787 const size_t blocksize = (128 * 1024);
788 off_t first_peak_byte;
789 boost::scoped_array<Sample> buf2;
791 if (_peakfile_fd < 0) {
792 if (prepare_for_peakfile_writes ()) {
798 if (peak_leftover_cnt) {
800 if (first_frame != peak_leftover_frame + peak_leftover_cnt) {
802 /* uh-oh, ::seek() since the last ::compute_and_write_peaks(),
803 and we have leftovers. flush a single peak (since the leftovers
804 never represent more than that, and restart.
809 x.min = peak_leftovers[0];
810 x.max = peak_leftovers[0];
812 off_t byte = (peak_leftover_frame / fpp) * sizeof (PeakData);
814 off_t offset = lseek (_peakfile_fd, byte, SEEK_SET);
816 if (offset != byte) {
817 error << string_compose(_("%1: could not seek in peak file data (%2)"), _name, strerror (errno)) << endmsg;
821 if (::write (_peakfile_fd, &x, sizeof (PeakData)) != sizeof (PeakData)) {
822 error << string_compose(_("%1: could not write peak file data (%2)"), _name, strerror (errno)) << endmsg;
826 _peak_byte_max = max (_peak_byte_max, (off_t) (byte + sizeof(PeakData)));
829 Glib::Threads::Mutex::Lock lm (_peaks_ready_lock);
830 PeakRangeReady (peak_leftover_frame, peak_leftover_cnt); /* EMIT SIGNAL */
831 if (intermediate_peaks_ready) {
832 PeaksReady (); /* EMIT SIGNAL */
836 /* left overs are done */
838 peak_leftover_cnt = 0;
842 /* else ... had leftovers, but they immediately preceed the new data, so just
843 merge them and compute.
846 /* make a new contiguous buffer containing leftovers and the new stuff */
848 to_do = cnt + peak_leftover_cnt;
849 buf2.reset(new Sample[to_do]);
852 memcpy (buf2.get(), peak_leftovers, peak_leftover_cnt * sizeof (Sample));
855 memcpy (buf2.get()+peak_leftover_cnt, buf, cnt * sizeof (Sample));
857 /* no more leftovers */
858 peak_leftover_cnt = 0;
860 /* use the temporary buffer */
863 /* make sure that when we write into the peakfile, we startup where we left off */
865 first_frame = peak_leftover_frame;
871 boost::scoped_array<PeakData> peakbuf(new PeakData[(to_do/fpp)+1]);
873 current_frame = first_frame;
878 /* if some frames were passed in (i.e. we're not flushing leftovers)
879 and there are less than fpp to do, save them till
883 if (force && (to_do < fpp)) {
884 /* keep the left overs around for next time */
886 if (peak_leftover_size < to_do) {
887 delete [] peak_leftovers;
888 peak_leftovers = new Sample[to_do];
889 peak_leftover_size = to_do;
891 memcpy (peak_leftovers, buf, to_do * sizeof (Sample));
892 peak_leftover_cnt = to_do;
893 peak_leftover_frame = current_frame;
900 framecnt_t this_time = min (fpp, to_do);
902 peakbuf[peaks_computed].max = buf[0];
903 peakbuf[peaks_computed].min = buf[0];
905 ARDOUR::find_peaks (buf+1, this_time-1, &peakbuf[peaks_computed].min, &peakbuf[peaks_computed].max);
910 frames_done += this_time;
911 current_frame += this_time;
914 first_peak_byte = (first_frame / fpp) * sizeof (PeakData);
916 if (can_truncate_peaks()) {
918 /* on some filesystems (ext3, at least) this helps to reduce fragmentation of
919 the peakfiles. its not guaranteed to do so, and even on ext3 (as of december 2006)
920 it does not cause single-extent allocation even for peakfiles of
921 less than BLOCKSIZE bytes. only call ftruncate if we'll make the file larger.
924 off_t endpos = lseek (_peakfile_fd, 0, SEEK_END);
925 off_t target_length = blocksize * ((first_peak_byte + blocksize + 1) / blocksize);
927 if (endpos < target_length) {
928 DEBUG_TRACE(DEBUG::Peaks, string_compose ("Truncating Peakfile %1\n", peakpath));
929 if (ftruncate (_peakfile_fd, target_length)) {
930 /* error doesn't actually matter so continue on without testing */
936 off_t offset = lseek(_peakfile_fd, first_peak_byte, SEEK_SET);
938 if (offset != first_peak_byte) {
939 error << string_compose(_("%1: could not seek in peak file data (%2)"), _name, strerror (errno)) << endmsg;
943 ssize_t bytes_to_write = sizeof (PeakData) * peaks_computed;
945 ssize_t bytes_written = ::write (_peakfile_fd, peakbuf.get(), bytes_to_write);
947 if (bytes_written != bytes_to_write) {
948 error << string_compose(_("%1: could not write peak file data (%2)"), _name, strerror (errno)) << endmsg;
952 _peak_byte_max = max (_peak_byte_max, (off_t) (first_peak_byte + bytes_to_write));
955 Glib::Threads::Mutex::Lock lm (_peaks_ready_lock);
956 PeakRangeReady (first_frame, frames_done); /* EMIT SIGNAL */
957 if (intermediate_peaks_ready) {
958 PeaksReady (); /* EMIT SIGNAL */
966 AudioSource::truncate_peakfile ()
968 if (_peakfile_fd < 0) {
969 error << string_compose (_("programming error: %1"), "AudioSource::truncate_peakfile() called without open peakfile descriptor")
974 /* truncate the peakfile down to its natural length if necessary */
976 off_t end = lseek (_peakfile_fd, 0, SEEK_END);
978 if (end > _peak_byte_max) {
979 DEBUG_TRACE(DEBUG::Peaks, string_compose ("Truncating Peakfile %1\n", peakpath));
980 if (ftruncate (_peakfile_fd, _peak_byte_max)) {
981 error << string_compose (_("could not truncate peakfile %1 to %2 (error: %3)"),
982 peakpath, _peak_byte_max, errno) << endmsg;
988 AudioSource::available_peaks (double zoom_factor) const
990 if (zoom_factor < _FPP) {
991 return length(_timeline_position); // peak data will come from the audio file
994 /* peak data comes from peakfile, but the filesize might not represent
995 the valid data due to ftruncate optimizations, so use _peak_byte_max state.
996 XXX - there might be some atomicity issues here, we should probably add a lock,
997 but _peak_byte_max only monotonically increases after initialization.
1000 off_t end = _peak_byte_max;
1002 return (end/sizeof(PeakData)) * _FPP;
1006 AudioSource::mark_streaming_write_completed (const Lock& lock)
1008 Glib::Threads::Mutex::Lock lm (_peaks_ready_lock);
1011 PeaksReady (); /* EMIT SIGNAL */
1016 AudioSource::allocate_working_buffers (framecnt_t framerate)
1018 Glib::Threads::Mutex::Lock lm (_level_buffer_lock);
1021 /* Note: we don't need any buffers allocated until
1022 a level 1 audiosource is created, at which
1023 time we'll call ::ensure_buffers_for_level()
1024 with the right value and do the right thing.
1027 if (!_mixdown_buffers.empty()) {
1028 ensure_buffers_for_level_locked ( _mixdown_buffers.size(), framerate);
1033 AudioSource::ensure_buffers_for_level (uint32_t level, framecnt_t frame_rate)
1035 Glib::Threads::Mutex::Lock lm (_level_buffer_lock);
1036 ensure_buffers_for_level_locked (level, frame_rate);
1040 AudioSource::ensure_buffers_for_level_locked (uint32_t level, framecnt_t frame_rate)
1042 framecnt_t nframes = (framecnt_t) floor (Config->get_audio_playback_buffer_seconds() * frame_rate);
1044 /* this may be called because either "level" or "frame_rate" have
1045 * changed. and it may be called with "level" smaller than the current
1046 * number of buffers, because a new compound region has been created at
1047 * a more shallow level than the deepest one we currently have.
1050 uint32_t limit = max ((size_t) level, _mixdown_buffers.size());
1052 _mixdown_buffers.clear ();
1053 _gain_buffers.clear ();
1055 for (uint32_t n = 0; n < limit; ++n) {
1056 _mixdown_buffers.push_back (boost::shared_array<Sample> (new Sample[nframes]));
1057 _gain_buffers.push_back (boost::shared_array<gain_t> (new gain_t[nframes]));