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 bool AudioSource::_build_missing_peakfiles = false;
73 /** true if we want peakfiles (e.g. if we are displaying a GUI) */
74 bool AudioSource::_build_peakfiles = false;
78 AudioSource::AudioSource (Session& s, string name)
79 : Source (s, DataType::AUDIO, name)
82 , _peaks_built (false)
84 , peak_leftover_cnt (0)
85 , peak_leftover_size (0)
90 , _last_raw_map_length (0)
94 AudioSource::AudioSource (Session& s, const XMLNode& node)
98 , _peaks_built (false)
100 , peak_leftover_cnt (0)
101 , peak_leftover_size (0)
106 , _last_raw_map_length (0)
108 if (set_state (node, Stateful::loading_state_version)) {
109 throw failed_constructor();
113 AudioSource::~AudioSource ()
115 /* shouldn't happen but make sure we don't leak file descriptors anyway */
117 if (peak_leftover_cnt) {
118 cerr << "AudioSource destroyed with leftover peak data pending" << endl;
121 if ((-1) != _peakfile_fd) {
122 close (_peakfile_fd);
126 delete [] peak_leftovers;
130 AudioSource::get_state ()
132 XMLNode& node (Source::get_state());
134 if (_captured_for.length()) {
135 node.add_property ("captured-for", _captured_for);
142 AudioSource::set_state (const XMLNode& node, int /*version*/)
144 const XMLProperty* prop;
146 if ((prop = node.property ("captured-for")) != 0) {
147 _captured_for = prop->value();
154 AudioSource::empty () const
160 AudioSource::length (framepos_t /*pos*/) const
166 AudioSource::update_length (framecnt_t len)
174 /***********************************************************************
176 ***********************************************************************/
178 /** Checks to see if peaks are ready. If so, we return true. If not, we return false, and
179 * things are set up so that doThisWhenReady is called when the peaks are ready.
180 * A new PBD::ScopedConnection is created for the associated connection and written to
181 * *connect_here_if_not.
183 * @param doThisWhenReady Function to call when peaks are ready (if they are not already).
184 * @param connect_here_if_not Address to write new ScopedConnection to.
185 * @param event_loop Event loop for doThisWhenReady to be called in.
188 AudioSource::peaks_ready (boost::function<void()> doThisWhenReady, ScopedConnection** connect_here_if_not, EventLoop* event_loop) const
191 Glib::Threads::Mutex::Lock lm (_peaks_ready_lock);
193 if (!(ret = _peaks_built)) {
194 *connect_here_if_not = new ScopedConnection;
195 PeaksReady.connect (**connect_here_if_not, MISSING_INVALIDATOR, doThisWhenReady, event_loop);
202 AudioSource::touch_peakfile ()
206 if (g_stat (peakpath.c_str(), &statbuf) != 0 || statbuf.st_size == 0) {
212 tbuf.actime = statbuf.st_atime;
213 tbuf.modtime = time ((time_t*) 0);
215 g_utime (peakpath.c_str(), &tbuf);
219 AudioSource::rename_peakfile (string newpath)
221 /* caller must hold _lock */
223 string oldpath = peakpath;
225 if (Glib::file_test (oldpath, Glib::FILE_TEST_EXISTS)) {
226 if (g_rename (oldpath.c_str(), newpath.c_str()) != 0) {
227 error << string_compose (_("cannot rename peakfile for %1 from %2 to %3 (%4)"), _name, oldpath, newpath, strerror (errno)) << endmsg;
238 AudioSource::initialize_peakfile (string audio_path)
242 peakpath = peak_path (audio_path);
244 DEBUG_TRACE(DEBUG::Peaks, string_compose ("Initialize Peakfile %1 for Audio file %2\n", peakpath, audio_path));
246 /* if the peak file should be there, but isn't .... */
248 if (!empty() && !Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
249 peakpath = find_broken_peakfile (peakpath, audio_path);
252 if (g_stat (peakpath.c_str(), &statbuf)) {
253 if (errno != ENOENT) {
254 /* it exists in the peaks dir, but there is some kind of error */
256 error << string_compose(_("AudioSource: cannot stat peakfile \"%1\""), peakpath) << endmsg;
260 DEBUG_TRACE(DEBUG::Peaks, string_compose("Peakfile %1 does not exist\n", peakpath));
262 _peaks_built = false;
266 /* we found it in the peaks dir, so check it out */
268 if (statbuf.st_size == 0 || (statbuf.st_size < (off_t) ((length(_timeline_position) / _FPP) * sizeof (PeakData)))) {
269 DEBUG_TRACE(DEBUG::Peaks, string_compose("Peakfile %1 is empty\n", peakpath));
270 _peaks_built = false;
272 // Check if the audio file has changed since the peakfile was built.
273 struct stat stat_file;
274 int err = stat (audio_path.c_str(), &stat_file);
278 /* no audio path - nested source or we can't
279 read it or ... whatever, use the peakfile as-is.
281 DEBUG_TRACE(DEBUG::Peaks, string_compose("Error when calling stat on Peakfile %1\n", peakpath));
284 _peak_byte_max = statbuf.st_size;
288 /* allow 6 seconds slop on checking peak vs. file times because of various
292 if (stat_file.st_mtime > statbuf.st_mtime && (stat_file.st_mtime - statbuf.st_mtime > 6)) {
293 _peaks_built = false;
297 _peak_byte_max = statbuf.st_size;
303 if (!empty() && !_peaks_built && _build_missing_peakfiles && _build_peakfiles) {
304 build_peaks_from_scratch ();
311 AudioSource::read (Sample *dst, framepos_t start, framecnt_t cnt, int /*channel*/) const
315 Glib::Threads::Mutex::Lock lm (_lock);
316 return read_unlocked (dst, start, cnt);
320 AudioSource::write (Sample *dst, framecnt_t cnt)
322 Glib::Threads::Mutex::Lock lm (_lock);
323 /* any write makes the file not removable */
324 _flags = Flag (_flags & ~Removable);
325 return write_unlocked (dst, cnt);
329 AudioSource::read_peaks (PeakData *peaks, framecnt_t npeaks, framepos_t start, framecnt_t cnt, double samples_per_visual_peak) const
331 return read_peaks_with_fpp (peaks, npeaks, start, cnt, samples_per_visual_peak, _FPP);
334 /** @param peaks Buffer to write peak data.
335 * @param npeaks Number of peaks to write.
339 AudioSource::read_peaks_with_fpp (PeakData *peaks, framecnt_t npeaks, framepos_t start, framecnt_t cnt,
340 double samples_per_visual_peak, framecnt_t samples_per_file_peak) const
342 Glib::Threads::Mutex::Lock lm (_lock);
344 double expected_peaks;
345 PeakData::PeakDatum xmax;
346 PeakData::PeakDatum xmin;
348 #ifdef PLATFORM_WINDOWS
349 SYSTEM_INFO system_info;
350 GetSystemInfo (&system_info);
351 const int bufsize = system_info.dwAllocationGranularity;;
353 const int bufsize = sysconf(_SC_PAGESIZE);
355 framecnt_t read_npeaks = npeaks;
356 framecnt_t zero_fill = 0;
360 expected_peaks = (cnt / (double) samples_per_file_peak);
361 if (g_stat (peakpath.c_str(), &statbuf) != 0) {
362 error << string_compose (_("Cannot open peakfile @ %1 for size check (%2)"), peakpath, strerror (errno)) << endmsg;
366 /* check actual size of the peakfile is at least large enough for all
367 * the data in the audio file. if it is too short, assume that a crash
368 * or other error truncated it, and rebuild it from scratch.
371 const off_t expected_file_size = (_length / (double) samples_per_file_peak) * sizeof (PeakData);
373 if (statbuf.st_size < expected_file_size) {
374 warning << string_compose (_("peak file %1 is truncated from %2 to %3"), peakpath, expected_file_size, statbuf.st_size) << endmsg;
375 const_cast<AudioSource*>(this)->build_peaks_from_scratch ();
376 if (g_stat (peakpath.c_str(), &statbuf) != 0) {
377 error << string_compose (_("Cannot open peakfile @ %1 for size check (%2) after rebuild"), peakpath, strerror (errno)) << endmsg;
379 if (statbuf.st_size < expected_file_size) {
380 fatal << "peak file is still truncated after rebuild" << endmsg;
385 ScopedFileDescriptor sfd (::open (peakpath.c_str(), O_RDONLY));
388 error << string_compose (_("Cannot open peakfile @ %1 for reading (%2)"), peakpath, strerror (errno)) << endmsg;
392 scale = npeaks/expected_peaks;
395 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"
396 , npeaks, start, cnt, _length, samples_per_visual_peak, expected_peaks, scale, peaks));
398 /* fix for near-end-of-file conditions */
400 if (cnt > _length - start) {
401 // cerr << "too close to end @ " << _length << " given " << start << " + " << cnt << " (" << _length - start << ")" << endl;
402 cnt = _length - start;
403 read_npeaks = min ((framecnt_t) floor (cnt / samples_per_visual_peak), npeaks);
404 zero_fill = npeaks - read_npeaks;
405 expected_peaks = (cnt / (double) samples_per_file_peak);
406 scale = npeaks/expected_peaks;
409 // cerr << "actual npeaks = " << read_npeaks << " zf = " << zero_fill << endl;
413 DEBUG_TRACE (DEBUG::Peaks, "RAW DATA\n");
415 /* no scaling at all, just get the sample data and duplicate it for
416 both max and min peak values.
419 boost::scoped_array<Sample> raw_staging(new Sample[cnt]);
421 if (read_unlocked (raw_staging.get(), start, cnt) != cnt) {
422 error << _("cannot read sample data for unscaled peak computation") << endmsg;
426 for (framecnt_t i = 0; i < npeaks; ++i) {
427 peaks[i].max = raw_staging[i];
428 peaks[i].min = raw_staging[i];
435 off_t first_peak_byte = (start / samples_per_file_peak) * sizeof (PeakData);
436 size_t bytes_to_read = sizeof (PeakData) * read_npeaks;
437 /* open, read, close */
439 DEBUG_TRACE (DEBUG::Peaks, "DIRECT PEAKS\n");
441 off_t map_off = first_peak_byte;
442 off_t read_map_off = map_off & ~(bufsize - 1);
443 off_t map_delta = map_off - read_map_off;
444 size_t map_length = bytes_to_read + map_delta;
446 if (_first_run || (_last_scale != samples_per_visual_peak) || (_last_map_off != map_off) || (_last_raw_map_length < bytes_to_read)) {
447 peak_cache.reset (new PeakData[npeaks]);
449 #ifdef PLATFORM_WINDOWS
450 HANDLE file_handle = (HANDLE) _get_osfhandle(int(sfd));
455 map_handle = CreateFileMapping(file_handle, NULL, PAGE_READONLY, 0, 0, NULL);
456 if (map_handle == NULL) {
457 error << string_compose (_("map failed - could not create file mapping for peakfile %1."), peakpath) << endmsg;
461 view_handle = MapViewOfFile(map_handle, FILE_MAP_READ, 0, read_map_off, map_length);
462 if (view_handle == NULL) {
463 error << string_compose (_("map failed - could not map peakfile %1."), peakpath) << endmsg;
467 addr = (char*) view_handle;
469 memcpy ((void*)peak_cache.get(), (void*)(addr + map_delta), bytes_to_read);
471 err_flag = UnmapViewOfFile (view_handle);
472 err_flag = CloseHandle(map_handle);
474 error << string_compose (_("unmap failed - could not unmap peakfile %1."), peakpath) << endmsg;
478 addr = (char*) mmap (0, map_length, PROT_READ, MAP_PRIVATE, sfd, read_map_off);
479 if (addr == MAP_FAILED) {
480 error << string_compose (_("map failed - could not mmap peakfile %1."), peakpath) << endmsg;
484 memcpy ((void*)peak_cache.get(), (void*)(addr + map_delta), bytes_to_read);
485 munmap (addr, map_length);
488 memset (&peak_cache[read_npeaks], 0, sizeof (PeakData) * zero_fill);
492 _last_scale = samples_per_visual_peak;
493 _last_map_off = map_off;
494 _last_raw_map_length = bytes_to_read;
497 memcpy ((void*)peaks, (void*)peak_cache.get(), npeaks * sizeof(PeakData));
504 DEBUG_TRACE (DEBUG::Peaks, "DOWNSAMPLE\n");
508 - more frames-per-peak (lower resolution) than the peakfile, or to put it another way,
509 - less peaks than the peakfile holds for the same range
511 So, read a block into a staging area, and then downsample from there.
513 to avoid confusion, I'll refer to the requested peaks as visual_peaks and the peakfile peaks as stored_peaks
516 const framecnt_t chunksize = (framecnt_t) expected_peaks; // we read all the peaks we need in one hit.
518 /* compute the rounded up frame position */
520 framepos_t current_stored_peak = (framepos_t) ceil (start / (double) samples_per_file_peak);
521 framepos_t next_visual_peak = (framepos_t) ceil (start / samples_per_visual_peak);
522 double next_visual_peak_frame = next_visual_peak * samples_per_visual_peak;
523 framepos_t stored_peak_before_next_visual_peak = (framepos_t) next_visual_peak_frame / samples_per_file_peak;
524 framecnt_t nvisual_peaks = 0;
527 /* handle the case where the initial visual peak is on a pixel boundary */
529 current_stored_peak = min (current_stored_peak, stored_peak_before_next_visual_peak);
531 /* open ... close during out: handling */
533 off_t map_off = (uint32_t) (ceil (start / (double) samples_per_file_peak)) * sizeof(PeakData);
534 off_t read_map_off = map_off & ~(bufsize - 1);
535 off_t map_delta = map_off - read_map_off;
536 size_t raw_map_length = chunksize * sizeof(PeakData);
537 size_t map_length = (chunksize * sizeof(PeakData)) + map_delta;
539 if (_first_run || (_last_scale != samples_per_visual_peak) || (_last_map_off != map_off) || (_last_raw_map_length < raw_map_length)) {
540 peak_cache.reset (new PeakData[npeaks]);
541 boost::scoped_array<PeakData> staging (new PeakData[chunksize]);
544 #ifdef PLATFORM_WINDOWS
545 HANDLE file_handle = (HANDLE) _get_osfhandle(int(sfd));
550 map_handle = CreateFileMapping(file_handle, NULL, PAGE_READONLY, 0, 0, NULL);
551 if (map_handle == NULL) {
552 error << string_compose (_("map failed - could not create file mapping for peakfile %1."), peakpath) << endmsg;
556 view_handle = MapViewOfFile(map_handle, FILE_MAP_READ, 0, read_map_off, map_length);
557 if (view_handle == NULL) {
558 error << string_compose (_("map failed - could not map peakfile %1."), peakpath) << endmsg;
562 addr = (char *) view_handle;
564 memcpy ((void*)staging.get(), (void*)(addr + map_delta), raw_map_length);
566 err_flag = UnmapViewOfFile (view_handle);
567 err_flag = CloseHandle(map_handle);
569 error << string_compose (_("unmap failed - could not unmap peakfile %1."), peakpath) << endmsg;
573 addr = (char*) mmap (0, map_length, PROT_READ, MAP_PRIVATE, sfd, read_map_off);
574 if (addr == MAP_FAILED) {
575 error << string_compose (_("map failed - could not mmap peakfile %1."), peakpath) << endmsg;
579 memcpy ((void*)staging.get(), (void*)(addr + map_delta), raw_map_length);
580 munmap (addr, map_length);
582 while (nvisual_peaks < read_npeaks) {
587 while ((current_stored_peak <= stored_peak_before_next_visual_peak) && (i < chunksize)) {
589 xmax = max (xmax, staging[i].max);
590 xmin = min (xmin, staging[i].min);
592 ++current_stored_peak;
595 peak_cache[nvisual_peaks].max = xmax;
596 peak_cache[nvisual_peaks].min = xmin;
598 next_visual_peak_frame = min ((double) start + cnt, (next_visual_peak_frame + samples_per_visual_peak));
599 stored_peak_before_next_visual_peak = (uint32_t) next_visual_peak_frame / samples_per_file_peak;
603 cerr << "Zero fill end of peaks (@ " << read_npeaks << " with " << zero_fill << ")" << endl;
604 memset (&peak_cache[read_npeaks], 0, sizeof (PeakData) * zero_fill);
608 _last_scale = samples_per_visual_peak;
609 _last_map_off = map_off;
610 _last_raw_map_length = raw_map_length;
613 memcpy ((void*)peaks, (void*)peak_cache.get(), npeaks * sizeof(PeakData));
616 DEBUG_TRACE (DEBUG::Peaks, "UPSAMPLE\n");
620 - less frames-per-peak (more resolution)
621 - more peaks than stored in the Peakfile
623 So, fetch data from the raw source, and generate peak
627 framecnt_t frames_read = 0;
628 framepos_t current_frame = start;
630 framecnt_t nvisual_peaks = 0;
631 framecnt_t chunksize = (framecnt_t) min (cnt, (framecnt_t) 4096);
632 boost::scoped_array<Sample> raw_staging(new Sample[chunksize]);
634 framepos_t frame_pos = start;
635 double pixel_pos = floor (frame_pos / samples_per_visual_peak);
636 double next_pixel_pos = ceil (frame_pos / samples_per_visual_peak);
637 double pixels_per_frame = 1.0 / samples_per_visual_peak;
642 while (nvisual_peaks < read_npeaks) {
644 if (i == frames_read) {
646 to_read = min (chunksize, (framecnt_t)(_length - current_frame));
648 if (current_frame >= _length) {
650 /* hmm, error condition - we've reached the end of the file
651 without generating all the peak data. cook up a zero-filled
652 data buffer and then use it. this is simpler than
653 adjusting zero_fill and read_npeaks and then breaking out of
657 memset (raw_staging.get(), 0, sizeof (Sample) * chunksize);
661 to_read = min (chunksize, (_length - current_frame));
664 if ((frames_read = read_unlocked (raw_staging.get(), current_frame, to_read)) == 0) {
665 error << string_compose(_("AudioSource[%1]: peak read - cannot read %2 samples at offset %3 of %4 (%5)"),
666 _name, to_read, current_frame, _length, strerror (errno))
675 xmax = max (xmax, raw_staging[i]);
676 xmin = min (xmin, raw_staging[i]);
679 pixel_pos += pixels_per_frame;
681 if (pixel_pos >= next_pixel_pos) {
683 peaks[nvisual_peaks].max = xmax;
684 peaks[nvisual_peaks].min = xmin;
689 next_pixel_pos = ceil (pixel_pos + 0.5);
694 memset (&peaks[read_npeaks], 0, sizeof (PeakData) * zero_fill);
698 DEBUG_TRACE (DEBUG::Peaks, "READPEAKS DONE\n");
703 AudioSource::build_peaks_from_scratch ()
705 const framecnt_t bufsize = 65536; // 256kB per disk read for mono data is about ideal
707 DEBUG_TRACE (DEBUG::Peaks, "Building peaks from scratch\n");
712 /* hold lock while building peaks */
714 Glib::Threads::Mutex::Lock lp (_lock);
716 if (prepare_for_peakfile_writes ()) {
720 framecnt_t current_frame = 0;
721 framecnt_t cnt = _length;
723 _peaks_built = false;
724 boost::scoped_array<Sample> buf(new Sample[bufsize]);
728 framecnt_t frames_to_read = min (bufsize, cnt);
729 framecnt_t frames_read;
731 if ((frames_read = read_unlocked (buf.get(), current_frame, frames_to_read)) != frames_to_read) {
732 error << string_compose(_("%1: could not write read raw data for peak computation (%2)"), _name, strerror (errno)) << endmsg;
733 done_with_peakfile_writes (false);
737 if (compute_and_write_peaks (buf.get(), current_frame, frames_read, true, false, _FPP)) {
741 current_frame += frames_read;
750 done_with_peakfile_writes ((cnt == 0));
758 DEBUG_TRACE (DEBUG::Peaks, string_compose("Could not write peak data, attempting to remove peakfile %1\n", peakpath));
759 ::g_unlink (peakpath.c_str());
766 AudioSource::prepare_for_peakfile_writes ()
768 if ((_peakfile_fd = open (peakpath.c_str(), O_CREAT|O_RDWR, 0664)) < 0) {
769 error << string_compose(_("AudioSource: cannot open peakpath (c) \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
776 AudioSource::done_with_peakfile_writes (bool done)
778 if (peak_leftover_cnt) {
779 compute_and_write_peaks (0, 0, 0, true, false, _FPP);
783 Glib::Threads::Mutex::Lock lm (_peaks_ready_lock);
785 PeaksReady (); /* EMIT SIGNAL */
788 close (_peakfile_fd);
792 /** @param first_frame Offset from the source start of the first frame to
793 * process. _lock MUST be held by caller.
796 AudioSource::compute_and_write_peaks (Sample* buf, framecnt_t first_frame, framecnt_t cnt,
797 bool force, bool intermediate_peaks_ready)
799 return compute_and_write_peaks (buf, first_frame, cnt, force, intermediate_peaks_ready, _FPP);
803 AudioSource::compute_and_write_peaks (Sample* buf, framecnt_t first_frame, framecnt_t cnt,
804 bool force, bool intermediate_peaks_ready, framecnt_t fpp)
807 uint32_t peaks_computed;
808 framepos_t current_frame;
809 framecnt_t frames_done;
810 const size_t blocksize = (128 * 1024);
811 off_t first_peak_byte;
812 boost::scoped_array<Sample> buf2;
814 if (_peakfile_fd < 0) {
815 if (prepare_for_peakfile_writes ()) {
821 if (peak_leftover_cnt) {
823 if (first_frame != peak_leftover_frame + peak_leftover_cnt) {
825 /* uh-oh, ::seek() since the last ::compute_and_write_peaks(),
826 and we have leftovers. flush a single peak (since the leftovers
827 never represent more than that, and restart.
832 x.min = peak_leftovers[0];
833 x.max = peak_leftovers[0];
835 off_t byte = (peak_leftover_frame / fpp) * sizeof (PeakData);
837 off_t offset = lseek (_peakfile_fd, byte, SEEK_SET);
839 if (offset != byte) {
840 error << string_compose(_("%1: could not seek in peak file data (%2)"), _name, strerror (errno)) << endmsg;
844 if (::write (_peakfile_fd, &x, sizeof (PeakData)) != sizeof (PeakData)) {
845 error << string_compose(_("%1: could not write peak file data (%2)"), _name, strerror (errno)) << endmsg;
849 _peak_byte_max = max (_peak_byte_max, (off_t) (byte + sizeof(PeakData)));
852 Glib::Threads::Mutex::Lock lm (_peaks_ready_lock);
853 PeakRangeReady (peak_leftover_frame, peak_leftover_cnt); /* EMIT SIGNAL */
854 if (intermediate_peaks_ready) {
855 PeaksReady (); /* EMIT SIGNAL */
859 /* left overs are done */
861 peak_leftover_cnt = 0;
865 /* else ... had leftovers, but they immediately preceed the new data, so just
866 merge them and compute.
869 /* make a new contiguous buffer containing leftovers and the new stuff */
871 to_do = cnt + peak_leftover_cnt;
872 buf2.reset(new Sample[to_do]);
875 memcpy (buf2.get(), peak_leftovers, peak_leftover_cnt * sizeof (Sample));
878 memcpy (buf2.get()+peak_leftover_cnt, buf, cnt * sizeof (Sample));
880 /* no more leftovers */
881 peak_leftover_cnt = 0;
883 /* use the temporary buffer */
886 /* make sure that when we write into the peakfile, we startup where we left off */
888 first_frame = peak_leftover_frame;
894 boost::scoped_array<PeakData> peakbuf(new PeakData[(to_do/fpp)+1]);
896 current_frame = first_frame;
901 /* if some frames were passed in (i.e. we're not flushing leftovers)
902 and there are less than fpp to do, save them till
906 if (force && (to_do < fpp)) {
907 /* keep the left overs around for next time */
909 if (peak_leftover_size < to_do) {
910 delete [] peak_leftovers;
911 peak_leftovers = new Sample[to_do];
912 peak_leftover_size = to_do;
914 memcpy (peak_leftovers, buf, to_do * sizeof (Sample));
915 peak_leftover_cnt = to_do;
916 peak_leftover_frame = current_frame;
923 framecnt_t this_time = min (fpp, to_do);
925 peakbuf[peaks_computed].max = buf[0];
926 peakbuf[peaks_computed].min = buf[0];
928 ARDOUR::find_peaks (buf+1, this_time-1, &peakbuf[peaks_computed].min, &peakbuf[peaks_computed].max);
933 frames_done += this_time;
934 current_frame += this_time;
937 first_peak_byte = (first_frame / fpp) * sizeof (PeakData);
939 if (can_truncate_peaks()) {
941 /* on some filesystems (ext3, at least) this helps to reduce fragmentation of
942 the peakfiles. its not guaranteed to do so, and even on ext3 (as of december 2006)
943 it does not cause single-extent allocation even for peakfiles of
944 less than BLOCKSIZE bytes. only call ftruncate if we'll make the file larger.
947 off_t endpos = lseek (_peakfile_fd, 0, SEEK_END);
948 off_t target_length = blocksize * ((first_peak_byte + blocksize + 1) / blocksize);
950 if (endpos < target_length) {
951 DEBUG_TRACE(DEBUG::Peaks, string_compose ("Truncating Peakfile %1\n", peakpath));
952 if (ftruncate (_peakfile_fd, target_length)) {
953 /* error doesn't actually matter so continue on without testing */
959 off_t offset = lseek(_peakfile_fd, first_peak_byte, SEEK_SET);
961 if (offset != first_peak_byte) {
962 error << string_compose(_("%1: could not seek in peak file data (%2)"), _name, strerror (errno)) << endmsg;
966 ssize_t bytes_to_write = sizeof (PeakData) * peaks_computed;
968 ssize_t bytes_written = ::write (_peakfile_fd, peakbuf.get(), bytes_to_write);
970 if (bytes_written != bytes_to_write) {
971 error << string_compose(_("%1: could not write peak file data (%2)"), _name, strerror (errno)) << endmsg;
975 _peak_byte_max = max (_peak_byte_max, (off_t) (first_peak_byte + bytes_to_write));
978 Glib::Threads::Mutex::Lock lm (_peaks_ready_lock);
979 PeakRangeReady (first_frame, frames_done); /* EMIT SIGNAL */
980 if (intermediate_peaks_ready) {
981 PeaksReady (); /* EMIT SIGNAL */
989 AudioSource::truncate_peakfile ()
991 if (_peakfile_fd < 0) {
992 error << string_compose (_("programming error: %1"), "AudioSource::truncate_peakfile() called without open peakfile descriptor")
997 /* truncate the peakfile down to its natural length if necessary */
999 off_t end = lseek (_peakfile_fd, 0, SEEK_END);
1001 if (end > _peak_byte_max) {
1002 DEBUG_TRACE(DEBUG::Peaks, string_compose ("Truncating Peakfile %1\n", peakpath));
1003 if (ftruncate (_peakfile_fd, _peak_byte_max)) {
1004 error << string_compose (_("could not truncate peakfile %1 to %2 (error: %3)"),
1005 peakpath, _peak_byte_max, errno) << endmsg;
1011 AudioSource::available_peaks (double zoom_factor) const
1013 if (zoom_factor < _FPP) {
1014 return length(_timeline_position); // peak data will come from the audio file
1017 /* peak data comes from peakfile, but the filesize might not represent
1018 the valid data due to ftruncate optimizations, so use _peak_byte_max state.
1019 XXX - there might be some atomicity issues here, we should probably add a lock,
1020 but _peak_byte_max only monotonically increases after initialization.
1023 off_t end = _peak_byte_max;
1025 return (end/sizeof(PeakData)) * _FPP;
1029 AudioSource::mark_streaming_write_completed (const Lock& lock)
1031 Glib::Threads::Mutex::Lock lm (_peaks_ready_lock);
1034 PeaksReady (); /* EMIT SIGNAL */
1039 AudioSource::allocate_working_buffers (framecnt_t framerate)
1041 Glib::Threads::Mutex::Lock lm (_level_buffer_lock);
1044 /* Note: we don't need any buffers allocated until
1045 a level 1 audiosource is created, at which
1046 time we'll call ::ensure_buffers_for_level()
1047 with the right value and do the right thing.
1050 if (!_mixdown_buffers.empty()) {
1051 ensure_buffers_for_level_locked ( _mixdown_buffers.size(), framerate);
1056 AudioSource::ensure_buffers_for_level (uint32_t level, framecnt_t frame_rate)
1058 Glib::Threads::Mutex::Lock lm (_level_buffer_lock);
1059 ensure_buffers_for_level_locked (level, frame_rate);
1063 AudioSource::ensure_buffers_for_level_locked (uint32_t level, framecnt_t frame_rate)
1065 framecnt_t nframes = (framecnt_t) floor (Config->get_audio_playback_buffer_seconds() * frame_rate);
1067 /* this may be called because either "level" or "frame_rate" have
1068 * changed. and it may be called with "level" smaller than the current
1069 * number of buffers, because a new compound region has been created at
1070 * a more shallow level than the deepest one we currently have.
1073 uint32_t limit = max ((size_t) level, _mixdown_buffers.size());
1075 _mixdown_buffers.clear ();
1076 _gain_buffers.clear ();
1078 for (uint32_t n = 0; n < limit; ++n) {
1079 _mixdown_buffers.push_back (boost::shared_array<Sample> (new Sample[nframes]));
1080 _gain_buffers.push_back (boost::shared_array<gain_t> (new gain_t[nframes]));