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 read_npeaks = npeaks;
357 framecnt_t zero_fill = 0;
361 expected_peaks = (cnt / (double) samples_per_file_peak);
362 if (g_stat (peakpath.c_str(), &statbuf) != 0) {
363 error << string_compose (_("Cannot open peakfile @ %1 for size check (%2)"), peakpath, strerror (errno)) << endmsg;
367 /* check actual size of the peakfile is at least large enough for all
368 * the data in the audio file. if it is too short, assume that a crash
369 * or other error truncated it, and rebuild it from scratch.
372 const off_t expected_file_size = (_length / (double) samples_per_file_peak) * sizeof (PeakData);
374 if (statbuf.st_size < expected_file_size) {
375 warning << string_compose (_("peak file %1 is truncated from %2 to %3"), peakpath, expected_file_size, statbuf.st_size) << endmsg;
376 const_cast<AudioSource*>(this)->build_peaks_from_scratch ();
377 if (g_stat (peakpath.c_str(), &statbuf) != 0) {
378 error << string_compose (_("Cannot open peakfile @ %1 for size check (%2) after rebuild"), peakpath, strerror (errno)) << endmsg;
380 if (statbuf.st_size < expected_file_size) {
381 fatal << "peak file is still truncated after rebuild" << endmsg;
386 ScopedFileDescriptor sfd (::open (peakpath.c_str(), O_RDONLY));
389 error << string_compose (_("Cannot open peakfile @ %1 for reading (%2)"), peakpath, strerror (errno)) << endmsg;
393 scale = npeaks/expected_peaks;
396 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"
397 , npeaks, start, cnt, _length, samples_per_visual_peak, expected_peaks, scale, peaks));
399 /* fix for near-end-of-file conditions */
401 if (cnt > _length - start) {
402 // cerr << "too close to end @ " << _length << " given " << start << " + " << cnt << " (" << _length - start << ")" << endl;
403 cnt = _length - start;
404 read_npeaks = min ((framecnt_t) floor (cnt / samples_per_visual_peak), npeaks);
405 zero_fill = npeaks - read_npeaks;
406 expected_peaks = (cnt / (double) samples_per_file_peak);
407 scale = npeaks/expected_peaks;
410 // cerr << "actual npeaks = " << read_npeaks << " zf = " << zero_fill << endl;
414 DEBUG_TRACE (DEBUG::Peaks, "RAW DATA\n");
416 /* no scaling at all, just get the sample data and duplicate it for
417 both max and min peak values.
420 boost::scoped_array<Sample> raw_staging(new Sample[cnt]);
422 if (read_unlocked (raw_staging.get(), start, cnt) != cnt) {
423 error << _("cannot read sample data for unscaled peak computation") << endmsg;
427 for (framecnt_t i = 0; i < npeaks; ++i) {
428 peaks[i].max = raw_staging[i];
429 peaks[i].min = raw_staging[i];
436 off_t first_peak_byte = (start / samples_per_file_peak) * sizeof (PeakData);
437 size_t bytes_to_read = sizeof (PeakData) * read_npeaks;
438 /* open, read, close */
440 DEBUG_TRACE (DEBUG::Peaks, "DIRECT PEAKS\n");
442 off_t map_off = first_peak_byte;
443 off_t read_map_off = map_off & ~(bufsize - 1);
444 off_t map_delta = map_off - read_map_off;
445 size_t map_length = bytes_to_read + map_delta;
447 if (_first_run || (_last_scale != samples_per_visual_peak) || (_last_map_off != map_off) || (_last_raw_map_length < bytes_to_read)) {
448 peak_cache.reset (new PeakData[npeaks]);
450 #ifdef PLATFORM_WINDOWS
451 HANDLE file_handle = (HANDLE) _get_osfhandle(int(sfd));
456 map_handle = CreateFileMapping(file_handle, NULL, PAGE_READONLY, 0, 0, NULL);
457 if (map_handle == NULL) {
458 error << string_compose (_("map failed - could not create file mapping for peakfile %1."), peakpath) << endmsg;
462 view_handle = MapViewOfFile(map_handle, FILE_MAP_READ, 0, read_map_off, map_length);
463 if (view_handle == NULL) {
464 error << string_compose (_("map failed - could not map peakfile %1."), peakpath) << endmsg;
468 addr = (char*) view_handle;
470 memcpy ((void*)peak_cache.get(), (void*)(addr + map_delta), bytes_to_read);
472 err_flag = UnmapViewOfFile (view_handle);
473 err_flag = CloseHandle(map_handle);
475 error << string_compose (_("unmap failed - could not unmap peakfile %1."), peakpath) << endmsg;
479 addr = (char*) mmap (0, map_length, PROT_READ, MAP_PRIVATE, sfd, read_map_off);
480 if (addr == MAP_FAILED) {
481 error << string_compose (_("map failed - could not mmap peakfile %1."), peakpath) << endmsg;
485 memcpy ((void*)peak_cache.get(), (void*)(addr + map_delta), bytes_to_read);
486 munmap (addr, map_length);
489 memset (&peak_cache[read_npeaks], 0, sizeof (PeakData) * zero_fill);
493 _last_scale = samples_per_visual_peak;
494 _last_map_off = map_off;
495 _last_raw_map_length = bytes_to_read;
498 memcpy ((void*)peaks, (void*)peak_cache.get(), npeaks * sizeof(PeakData));
505 DEBUG_TRACE (DEBUG::Peaks, "DOWNSAMPLE\n");
509 - more frames-per-peak (lower resolution) than the peakfile, or to put it another way,
510 - less peaks than the peakfile holds for the same range
512 So, read a block into a staging area, and then downsample from there.
514 to avoid confusion, I'll refer to the requested peaks as visual_peaks and the peakfile peaks as stored_peaks
517 const framecnt_t chunksize = (framecnt_t) expected_peaks; // we read all the peaks we need in one hit.
519 /* compute the rounded up frame position */
521 framepos_t current_stored_peak = (framepos_t) ceil (start / (double) samples_per_file_peak);
522 framepos_t next_visual_peak = (framepos_t) ceil (start / samples_per_visual_peak);
523 double next_visual_peak_frame = next_visual_peak * samples_per_visual_peak;
524 framepos_t stored_peak_before_next_visual_peak = (framepos_t) next_visual_peak_frame / samples_per_file_peak;
525 framecnt_t nvisual_peaks = 0;
528 /* handle the case where the initial visual peak is on a pixel boundary */
530 current_stored_peak = min (current_stored_peak, stored_peak_before_next_visual_peak);
532 /* open ... close during out: handling */
534 off_t map_off = (uint32_t) (ceil (start / (double) samples_per_file_peak)) * sizeof(PeakData);
535 off_t read_map_off = map_off & ~(bufsize - 1);
536 off_t map_delta = map_off - read_map_off;
537 size_t raw_map_length = chunksize * sizeof(PeakData);
538 size_t map_length = (chunksize * sizeof(PeakData)) + map_delta;
540 if (_first_run || (_last_scale != samples_per_visual_peak) || (_last_map_off != map_off) || (_last_raw_map_length < raw_map_length)) {
541 peak_cache.reset (new PeakData[npeaks]);
542 boost::scoped_array<PeakData> staging (new PeakData[chunksize]);
545 #ifdef PLATFORM_WINDOWS
546 HANDLE file_handle = (HANDLE) _get_osfhandle(int(sfd));
551 map_handle = CreateFileMapping(file_handle, NULL, PAGE_READONLY, 0, 0, NULL);
552 if (map_handle == NULL) {
553 error << string_compose (_("map failed - could not create file mapping for peakfile %1."), peakpath) << endmsg;
557 view_handle = MapViewOfFile(map_handle, FILE_MAP_READ, 0, read_map_off, map_length);
558 if (view_handle == NULL) {
559 error << string_compose (_("map failed - could not map peakfile %1."), peakpath) << endmsg;
563 addr = (char *) view_handle;
565 memcpy ((void*)staging.get(), (void*)(addr + map_delta), raw_map_length);
567 err_flag = UnmapViewOfFile (view_handle);
568 err_flag = CloseHandle(map_handle);
570 error << string_compose (_("unmap failed - could not unmap peakfile %1."), peakpath) << endmsg;
574 addr = (char*) mmap (0, map_length, PROT_READ, MAP_PRIVATE, sfd, read_map_off);
575 if (addr == MAP_FAILED) {
576 error << string_compose (_("map failed - could not mmap peakfile %1."), peakpath) << endmsg;
580 memcpy ((void*)staging.get(), (void*)(addr + map_delta), raw_map_length);
581 munmap (addr, map_length);
583 while (nvisual_peaks < read_npeaks) {
588 while ((current_stored_peak <= stored_peak_before_next_visual_peak) && (i < chunksize)) {
590 xmax = max (xmax, staging[i].max);
591 xmin = min (xmin, staging[i].min);
593 ++current_stored_peak;
596 peak_cache[nvisual_peaks].max = xmax;
597 peak_cache[nvisual_peaks].min = xmin;
599 next_visual_peak_frame = min ((double) start + cnt, (next_visual_peak_frame + samples_per_visual_peak));
600 stored_peak_before_next_visual_peak = (uint32_t) next_visual_peak_frame / samples_per_file_peak;
604 cerr << "Zero fill end of peaks (@ " << read_npeaks << " with " << zero_fill << ")" << endl;
605 memset (&peak_cache[read_npeaks], 0, sizeof (PeakData) * zero_fill);
609 _last_scale = samples_per_visual_peak;
610 _last_map_off = map_off;
611 _last_raw_map_length = raw_map_length;
614 memcpy ((void*)peaks, (void*)peak_cache.get(), npeaks * sizeof(PeakData));
617 DEBUG_TRACE (DEBUG::Peaks, "UPSAMPLE\n");
621 - less frames-per-peak (more resolution)
622 - more peaks than stored in the Peakfile
624 So, fetch data from the raw source, and generate peak
628 framecnt_t frames_read = 0;
629 framepos_t current_frame = start;
631 framecnt_t nvisual_peaks = 0;
632 framecnt_t chunksize = (framecnt_t) min (cnt, (framecnt_t) 4096);
633 boost::scoped_array<Sample> raw_staging(new Sample[chunksize]);
635 framepos_t frame_pos = start;
636 double pixel_pos = floor (frame_pos / samples_per_visual_peak);
637 double next_pixel_pos = ceil (frame_pos / samples_per_visual_peak);
638 double pixels_per_frame = 1.0 / samples_per_visual_peak;
643 while (nvisual_peaks < read_npeaks) {
645 if (i == frames_read) {
647 to_read = min (chunksize, (framecnt_t)(_length - current_frame));
649 if (current_frame >= _length) {
651 /* hmm, error condition - we've reached the end of the file
652 without generating all the peak data. cook up a zero-filled
653 data buffer and then use it. this is simpler than
654 adjusting zero_fill and read_npeaks and then breaking out of
658 memset (raw_staging.get(), 0, sizeof (Sample) * chunksize);
662 to_read = min (chunksize, (_length - current_frame));
665 if ((frames_read = read_unlocked (raw_staging.get(), current_frame, to_read)) == 0) {
666 error << string_compose(_("AudioSource[%1]: peak read - cannot read %2 samples at offset %3 of %4 (%5)"),
667 _name, to_read, current_frame, _length, strerror (errno))
676 xmax = max (xmax, raw_staging[i]);
677 xmin = min (xmin, raw_staging[i]);
680 pixel_pos += pixels_per_frame;
682 if (pixel_pos >= next_pixel_pos) {
684 peaks[nvisual_peaks].max = xmax;
685 peaks[nvisual_peaks].min = xmin;
690 next_pixel_pos = ceil (pixel_pos + 0.5);
695 memset (&peaks[read_npeaks], 0, sizeof (PeakData) * zero_fill);
699 DEBUG_TRACE (DEBUG::Peaks, "READPEAKS DONE\n");
704 AudioSource::build_peaks_from_scratch ()
706 const framecnt_t bufsize = 65536; // 256kB per disk read for mono data is about ideal
708 DEBUG_TRACE (DEBUG::Peaks, "Building peaks from scratch\n");
713 /* hold lock while building peaks */
715 Glib::Threads::Mutex::Lock lp (_lock);
717 if (prepare_for_peakfile_writes ()) {
721 framecnt_t current_frame = 0;
722 framecnt_t cnt = _length;
724 _peaks_built = false;
725 boost::scoped_array<Sample> buf(new Sample[bufsize]);
729 framecnt_t frames_to_read = min (bufsize, cnt);
730 framecnt_t frames_read;
732 if ((frames_read = read_unlocked (buf.get(), current_frame, frames_to_read)) != frames_to_read) {
733 error << string_compose(_("%1: could not write read raw data for peak computation (%2)"), _name, strerror (errno)) << endmsg;
734 done_with_peakfile_writes (false);
738 if (compute_and_write_peaks (buf.get(), current_frame, frames_read, true, false, _FPP)) {
742 current_frame += frames_read;
751 done_with_peakfile_writes ((cnt == 0));
759 DEBUG_TRACE (DEBUG::Peaks, string_compose("Could not write peak data, attempting to remove peakfile %1\n", peakpath));
760 ::g_unlink (peakpath.c_str());
767 AudioSource::prepare_for_peakfile_writes ()
769 if ((_peakfile_fd = open (peakpath.c_str(), O_CREAT|O_RDWR, 0664)) < 0) {
770 error << string_compose(_("AudioSource: cannot open peakpath (c) \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
777 AudioSource::done_with_peakfile_writes (bool done)
779 if (peak_leftover_cnt) {
780 compute_and_write_peaks (0, 0, 0, true, false, _FPP);
784 Glib::Threads::Mutex::Lock lm (_peaks_ready_lock);
786 PeaksReady (); /* EMIT SIGNAL */
789 close (_peakfile_fd);
793 /** @param first_frame Offset from the source start of the first frame to
794 * process. _lock MUST be held by caller.
797 AudioSource::compute_and_write_peaks (Sample* buf, framecnt_t first_frame, framecnt_t cnt,
798 bool force, bool intermediate_peaks_ready)
800 return compute_and_write_peaks (buf, first_frame, cnt, force, intermediate_peaks_ready, _FPP);
804 AudioSource::compute_and_write_peaks (Sample* buf, framecnt_t first_frame, framecnt_t cnt,
805 bool force, bool intermediate_peaks_ready, framecnt_t fpp)
808 uint32_t peaks_computed;
809 framepos_t current_frame;
810 framecnt_t frames_done;
811 const size_t blocksize = (128 * 1024);
812 off_t first_peak_byte;
813 boost::scoped_array<Sample> buf2;
815 if (_peakfile_fd < 0) {
816 if (prepare_for_peakfile_writes ()) {
822 if (peak_leftover_cnt) {
824 if (first_frame != peak_leftover_frame + peak_leftover_cnt) {
826 /* uh-oh, ::seek() since the last ::compute_and_write_peaks(),
827 and we have leftovers. flush a single peak (since the leftovers
828 never represent more than that, and restart.
833 x.min = peak_leftovers[0];
834 x.max = peak_leftovers[0];
836 off_t byte = (peak_leftover_frame / fpp) * sizeof (PeakData);
838 off_t offset = lseek (_peakfile_fd, byte, SEEK_SET);
840 if (offset != byte) {
841 error << string_compose(_("%1: could not seek in peak file data (%2)"), _name, strerror (errno)) << endmsg;
845 if (::write (_peakfile_fd, &x, sizeof (PeakData)) != sizeof (PeakData)) {
846 error << string_compose(_("%1: could not write peak file data (%2)"), _name, strerror (errno)) << endmsg;
850 _peak_byte_max = max (_peak_byte_max, (off_t) (byte + sizeof(PeakData)));
853 Glib::Threads::Mutex::Lock lm (_peaks_ready_lock);
854 PeakRangeReady (peak_leftover_frame, peak_leftover_cnt); /* EMIT SIGNAL */
855 if (intermediate_peaks_ready) {
856 PeaksReady (); /* EMIT SIGNAL */
860 /* left overs are done */
862 peak_leftover_cnt = 0;
866 /* else ... had leftovers, but they immediately preceed the new data, so just
867 merge them and compute.
870 /* make a new contiguous buffer containing leftovers and the new stuff */
872 to_do = cnt + peak_leftover_cnt;
873 buf2.reset(new Sample[to_do]);
876 memcpy (buf2.get(), peak_leftovers, peak_leftover_cnt * sizeof (Sample));
879 memcpy (buf2.get()+peak_leftover_cnt, buf, cnt * sizeof (Sample));
881 /* no more leftovers */
882 peak_leftover_cnt = 0;
884 /* use the temporary buffer */
887 /* make sure that when we write into the peakfile, we startup where we left off */
889 first_frame = peak_leftover_frame;
895 boost::scoped_array<PeakData> peakbuf(new PeakData[(to_do/fpp)+1]);
897 current_frame = first_frame;
902 /* if some frames were passed in (i.e. we're not flushing leftovers)
903 and there are less than fpp to do, save them till
907 if (force && (to_do < fpp)) {
908 /* keep the left overs around for next time */
910 if (peak_leftover_size < to_do) {
911 delete [] peak_leftovers;
912 peak_leftovers = new Sample[to_do];
913 peak_leftover_size = to_do;
915 memcpy (peak_leftovers, buf, to_do * sizeof (Sample));
916 peak_leftover_cnt = to_do;
917 peak_leftover_frame = current_frame;
924 framecnt_t this_time = min (fpp, to_do);
926 peakbuf[peaks_computed].max = buf[0];
927 peakbuf[peaks_computed].min = buf[0];
929 ARDOUR::find_peaks (buf+1, this_time-1, &peakbuf[peaks_computed].min, &peakbuf[peaks_computed].max);
934 frames_done += this_time;
935 current_frame += this_time;
938 first_peak_byte = (first_frame / fpp) * sizeof (PeakData);
940 if (can_truncate_peaks()) {
942 /* on some filesystems (ext3, at least) this helps to reduce fragmentation of
943 the peakfiles. its not guaranteed to do so, and even on ext3 (as of december 2006)
944 it does not cause single-extent allocation even for peakfiles of
945 less than BLOCKSIZE bytes. only call ftruncate if we'll make the file larger.
948 off_t endpos = lseek (_peakfile_fd, 0, SEEK_END);
949 off_t target_length = blocksize * ((first_peak_byte + blocksize + 1) / blocksize);
951 if (endpos < target_length) {
952 DEBUG_TRACE(DEBUG::Peaks, string_compose ("Truncating Peakfile %1\n", peakpath));
953 if (ftruncate (_peakfile_fd, target_length)) {
954 /* error doesn't actually matter so continue on without testing */
960 off_t offset = lseek(_peakfile_fd, first_peak_byte, SEEK_SET);
962 if (offset != first_peak_byte) {
963 error << string_compose(_("%1: could not seek in peak file data (%2)"), _name, strerror (errno)) << endmsg;
967 ssize_t bytes_to_write = sizeof (PeakData) * peaks_computed;
969 ssize_t bytes_written = ::write (_peakfile_fd, peakbuf.get(), bytes_to_write);
971 if (bytes_written != bytes_to_write) {
972 error << string_compose(_("%1: could not write peak file data (%2)"), _name, strerror (errno)) << endmsg;
976 _peak_byte_max = max (_peak_byte_max, (off_t) (first_peak_byte + bytes_to_write));
979 Glib::Threads::Mutex::Lock lm (_peaks_ready_lock);
980 PeakRangeReady (first_frame, frames_done); /* EMIT SIGNAL */
981 if (intermediate_peaks_ready) {
982 PeaksReady (); /* EMIT SIGNAL */
990 AudioSource::truncate_peakfile ()
992 if (_peakfile_fd < 0) {
993 error << string_compose (_("programming error: %1"), "AudioSource::truncate_peakfile() called without open peakfile descriptor")
998 /* truncate the peakfile down to its natural length if necessary */
1000 off_t end = lseek (_peakfile_fd, 0, SEEK_END);
1002 if (end > _peak_byte_max) {
1003 DEBUG_TRACE(DEBUG::Peaks, string_compose ("Truncating Peakfile %1\n", peakpath));
1004 if (ftruncate (_peakfile_fd, _peak_byte_max)) {
1005 error << string_compose (_("could not truncate peakfile %1 to %2 (error: %3)"),
1006 peakpath, _peak_byte_max, errno) << endmsg;
1012 AudioSource::available_peaks (double zoom_factor) const
1014 if (zoom_factor < _FPP) {
1015 return length(_timeline_position); // peak data will come from the audio file
1018 /* peak data comes from peakfile, but the filesize might not represent
1019 the valid data due to ftruncate optimizations, so use _peak_byte_max state.
1020 XXX - there might be some atomicity issues here, we should probably add a lock,
1021 but _peak_byte_max only monotonically increases after initialization.
1024 off_t end = _peak_byte_max;
1026 return (end/sizeof(PeakData)) * _FPP;
1030 AudioSource::mark_streaming_write_completed (const Lock& lock)
1032 Glib::Threads::Mutex::Lock lm (_peaks_ready_lock);
1035 PeaksReady (); /* EMIT SIGNAL */
1040 AudioSource::allocate_working_buffers (framecnt_t framerate)
1042 Glib::Threads::Mutex::Lock lm (_level_buffer_lock);
1045 /* Note: we don't need any buffers allocated until
1046 a level 1 audiosource is created, at which
1047 time we'll call ::ensure_buffers_for_level()
1048 with the right value and do the right thing.
1051 if (!_mixdown_buffers.empty()) {
1052 ensure_buffers_for_level_locked ( _mixdown_buffers.size(), framerate);
1057 AudioSource::ensure_buffers_for_level (uint32_t level, framecnt_t frame_rate)
1059 Glib::Threads::Mutex::Lock lm (_level_buffer_lock);
1060 ensure_buffers_for_level_locked (level, frame_rate);
1064 AudioSource::ensure_buffers_for_level_locked (uint32_t level, framecnt_t frame_rate)
1066 framecnt_t nframes = (framecnt_t) floor (Config->get_audio_playback_buffer_seconds() * frame_rate);
1068 /* this may be called because either "level" or "frame_rate" have
1069 * changed. and it may be called with "level" smaller than the current
1070 * number of buffers, because a new compound region has been created at
1071 * a more shallow level than the deepest one we currently have.
1074 uint32_t limit = max ((size_t) level, _mixdown_buffers.size());
1076 _mixdown_buffers.clear ();
1077 _gain_buffers.clear ();
1079 for (uint32_t n = 0; n < limit; ++n) {
1080 _mixdown_buffers.push_back (boost::shared_array<Sample> (new Sample[nframes]));
1081 _gain_buffers.push_back (boost::shared_array<gain_t> (new gain_t[nframes]));