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.
34 #include <glibmm/fileutils.h>
35 #include <glibmm/miscutils.h>
37 #include "pbd/xml++.h"
38 #include "pbd/pthread_utils.h"
40 #include "ardour/audiosource.h"
41 #include "ardour/audio_diskstream.h"
42 #include "ardour/cycle_timer.h"
43 #include "ardour/session.h"
44 #include "ardour/transient_detector.h"
45 #include "ardour/runtime_functions.h"
50 using namespace ARDOUR;
53 Glib::StaticMutex AudioSource::_level_buffer_lock = GLIBMM_STATIC_MUTEX_INIT;
54 vector<boost::shared_ptr<Sample> > AudioSource::_mixdown_buffers;
55 vector<boost::shared_ptr<gain_t> > AudioSource::_gain_buffers;
56 size_t AudioSource::_working_buffers_size = 0;
57 bool AudioSource::_build_missing_peakfiles = false;
59 /** true if we want peakfiles (e.g. if we are displaying a GUI) */
60 bool AudioSource::_build_peakfiles = false;
64 AudioSource::AudioSource (Session& s, string name)
65 : Source (s, DataType::AUDIO, name)
70 _peakfile_descriptor = 0;
71 peak_leftover_cnt = 0;
72 peak_leftover_size = 0;
76 AudioSource::AudioSource (Session& s, const XMLNode& node)
83 _peakfile_descriptor = 0;
84 peak_leftover_cnt = 0;
85 peak_leftover_size = 0;
88 if (set_state (node, Stateful::loading_state_version)) {
89 throw failed_constructor();
93 AudioSource::~AudioSource ()
95 /* shouldn't happen but make sure we don't leak file descriptors anyway */
97 if (peak_leftover_cnt) {
98 cerr << "AudioSource destroyed with leftover peak data pending" << endl;
101 delete _peakfile_descriptor;
102 delete [] peak_leftovers;
106 AudioSource::get_state ()
108 XMLNode& node (Source::get_state());
110 if (_captured_for.length()) {
111 node.add_property ("captured-for", _captured_for);
118 AudioSource::set_state (const XMLNode& node, int /*version*/)
120 const XMLProperty* prop;
122 if ((prop = node.property ("captured-for")) != 0) {
123 _captured_for = prop->value();
130 AudioSource::empty () const
136 AudioSource::length (framepos_t /*pos*/) const
142 AudioSource::update_length (framepos_t pos, framecnt_t cnt)
144 if (pos + cnt > _length) {
150 /***********************************************************************
152 ***********************************************************************/
154 /** Checks to see if peaks are ready. If so, we return true. If not, we return false, and
155 * things are set up so that doThisWhenReady is called when the peaks are ready.
156 * A new PBD::ScopedConnection is created for the associated connection and written to
157 * *connect_here_if_not.
159 * @param doThisWhenReady Function to call when peaks are ready (if they are not already).
160 * @param connect_here_if_not Address to write new ScopedConnection to.
161 * @param event_loop Event loop for doThisWhenReady to be called in.
164 AudioSource::peaks_ready (boost::function<void()> doThisWhenReady, ScopedConnection** connect_here_if_not, EventLoop* event_loop) const
167 Glib::Mutex::Lock lm (_peaks_ready_lock);
169 if (!(ret = _peaks_built)) {
170 *connect_here_if_not = new ScopedConnection;
171 PeaksReady.connect (**connect_here_if_not, MISSING_INVALIDATOR, doThisWhenReady, event_loop);
178 AudioSource::touch_peakfile ()
182 if (stat (peakpath.c_str(), &statbuf) != 0 || statbuf.st_size == 0) {
188 tbuf.actime = statbuf.st_atime;
189 tbuf.modtime = time ((time_t) 0);
191 utime (peakpath.c_str(), &tbuf);
195 AudioSource::rename_peakfile (string newpath)
197 /* caller must hold _lock */
199 string oldpath = peakpath;
201 if (Glib::file_test (oldpath, Glib::FILE_TEST_EXISTS)) {
202 if (rename (oldpath.c_str(), newpath.c_str()) != 0) {
203 error << string_compose (_("cannot rename peakfile for %1 from %2 to %3 (%4)"), _name, oldpath, newpath, strerror (errno)) << endmsg;
214 AudioSource::initialize_peakfile (bool newfile, string audio_path)
218 peakpath = peak_path (audio_path);
220 /* if the peak file should be there, but isn't .... */
222 if (!newfile && !Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
223 peakpath = find_broken_peakfile (peakpath, audio_path);
226 if (stat (peakpath.c_str(), &statbuf)) {
227 if (errno != ENOENT) {
228 /* it exists in the peaks dir, but there is some kind of error */
230 error << string_compose(_("AudioSource: cannot stat peakfile \"%1\""), peakpath) << endmsg;
234 /* peakfile does not exist */
236 _peaks_built = false;
240 /* we found it in the peaks dir, so check it out */
242 if (statbuf.st_size == 0 || (statbuf.st_size < (off_t) ((length(_timeline_position) / _FPP) * sizeof (PeakData)))) {
244 _peaks_built = false;
246 // Check if the audio file has changed since the peakfile was built.
247 struct stat stat_file;
248 int err = stat (audio_path.c_str(), &stat_file);
252 /* no audio path - nested source or we can't
253 read it or ... whatever, use the peakfile as-is.
257 _peak_byte_max = statbuf.st_size;
261 /* allow 6 seconds slop on checking peak vs. file times because of various
265 if (stat_file.st_mtime > statbuf.st_mtime && (stat_file.st_mtime - statbuf.st_mtime > 6)) {
266 _peaks_built = false;
270 _peak_byte_max = statbuf.st_size;
276 if (!newfile && !_peaks_built && _build_missing_peakfiles && _build_peakfiles) {
277 build_peaks_from_scratch ();
284 AudioSource::read (Sample *dst, framepos_t start, framecnt_t cnt, int /*channel*/) const
288 Glib::Mutex::Lock lm (_lock);
289 return read_unlocked (dst, start, cnt);
293 AudioSource::write (Sample *dst, framecnt_t cnt)
295 Glib::Mutex::Lock lm (_lock);
296 /* any write makes the fill not removable */
297 _flags = Flag (_flags & ~Removable);
298 return write_unlocked (dst, cnt);
302 AudioSource::read_peaks (PeakData *peaks, framecnt_t npeaks, framepos_t start, framecnt_t cnt, double samples_per_visual_peak) const
304 return read_peaks_with_fpp (peaks, npeaks, start, cnt, samples_per_visual_peak, _FPP);
307 /** @param peaks Buffer to write peak data.
308 * @param npeaks Number of peaks to write.
312 AudioSource::read_peaks_with_fpp (PeakData *peaks, framecnt_t npeaks, framepos_t start, framecnt_t cnt,
313 double samples_per_visual_peak, framecnt_t samples_per_file_peak) const
315 Glib::Mutex::Lock lm (_lock);
317 double expected_peaks;
318 PeakData::PeakDatum xmax;
319 PeakData::PeakDatum xmin;
322 framecnt_t zero_fill = 0;
324 PeakData* staging = 0;
325 Sample* raw_staging = 0;
327 FdFileDescriptor* peakfile_descriptor = new FdFileDescriptor (peakpath, false, 0664);
328 int peakfile_fd = -1;
330 expected_peaks = (cnt / (double) samples_per_file_peak);
331 scale = npeaks/expected_peaks;
333 #undef DEBUG_READ_PEAKS
334 #ifdef DEBUG_READ_PEAKS
335 cerr << "======>RP: npeaks = " << npeaks
336 << " start = " << start
338 << " len = " << _length
339 << " samples_per_visual_peak =" << samples_per_visual_peak
340 << " expected was " << expected_peaks << " ... scale = " << scale
341 << " PD ptr = " << peaks
346 /* fix for near-end-of-file conditions */
348 if (cnt > _length - start) {
349 // cerr << "too close to end @ " << _length << " given " << start << " + " << cnt << endl;
350 cnt = _length - start;
351 framecnt_t old = npeaks;
352 npeaks = min ((framecnt_t) floor (cnt / samples_per_visual_peak), npeaks);
353 zero_fill = old - npeaks;
356 // cerr << "actual npeaks = " << npeaks << " zf = " << zero_fill << endl;
360 #ifdef DEBUG_READ_PEAKS
361 cerr << "RAW DATA\n";
363 /* no scaling at all, just get the sample data and duplicate it for
364 both max and min peak values.
367 Sample* raw_staging = new Sample[cnt];
369 if (read_unlocked (raw_staging, start, cnt) != cnt) {
370 error << _("cannot read sample data for unscaled peak computation") << endmsg;
374 for (framecnt_t i = 0; i < npeaks; ++i) {
375 peaks[i].max = raw_staging[i];
376 peaks[i].min = raw_staging[i];
379 delete peakfile_descriptor;
380 delete [] raw_staging;
386 off_t first_peak_byte = (start / samples_per_file_peak) * sizeof (PeakData);
388 /* open, read, close */
390 if ((peakfile_fd = peakfile_descriptor->allocate ()) < 0) {
391 error << string_compose(_("AudioSource: cannot open peakpath (a) \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
392 delete peakfile_descriptor;
396 #ifdef DEBUG_READ_PEAKS
397 cerr << "DIRECT PEAKS\n";
400 nread = ::pread (peakfile_fd, peaks, sizeof (PeakData)* npeaks, first_peak_byte);
402 if (nread != sizeof (PeakData) * npeaks) {
403 cerr << "AudioSource["
405 << "]: cannot read peaks from peakfile! (read only "
415 delete peakfile_descriptor;
420 memset (&peaks[npeaks], 0, sizeof (PeakData) * zero_fill);
423 delete peakfile_descriptor;
432 #ifdef DEBUG_READ_PEAKS
433 cerr << "DOWNSAMPLE\n";
437 - more frames-per-peak (lower resolution) than the peakfile, or to put it another way,
438 - less peaks than the peakfile holds for the same range
440 So, read a block into a staging area, and then downsample from there.
442 to avoid confusion, I'll refer to the requested peaks as visual_peaks and the peakfile peaks as stored_peaks
445 const framecnt_t chunksize = (framecnt_t) min (expected_peaks, 65536.0);
447 staging = new PeakData[chunksize];
449 /* compute the rounded up frame position */
451 framepos_t current_frame = start;
452 framepos_t current_stored_peak = (framepos_t) ceil (current_frame / (double) samples_per_file_peak);
453 framepos_t next_visual_peak = (framepos_t) ceil (current_frame / samples_per_visual_peak);
454 double next_visual_peak_frame = next_visual_peak * samples_per_visual_peak;
455 framepos_t stored_peak_before_next_visual_peak = (framepos_t) next_visual_peak_frame / samples_per_file_peak;
456 framecnt_t nvisual_peaks = 0;
457 framecnt_t stored_peaks_read = 0;
460 /* handle the case where the initial visual peak is on a pixel boundary */
462 current_stored_peak = min (current_stored_peak, stored_peak_before_next_visual_peak);
464 /* open ... close during out: handling */
466 if ((peakfile_fd = peakfile_descriptor->allocate ()) < 0) {
467 error << string_compose(_("AudioSource: cannot open peakpath (b) \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
468 delete peakfile_descriptor;
473 while (nvisual_peaks < npeaks) {
475 if (i == stored_peaks_read) {
477 uint32_t start_byte = current_stored_peak * sizeof(PeakData);
478 tnp = min ((framecnt_t)(_length/samples_per_file_peak - current_stored_peak), (framecnt_t) expected_peaks);
479 to_read = min (chunksize, tnp);
481 #ifdef DEBUG_READ_PEAKS
482 cerr << "read " << sizeof (PeakData) * to_read << " from peakfile @ " << start_byte << endl;
485 if ((nread = ::pread (peakfile_fd, staging, sizeof (PeakData) * to_read, start_byte))
486 != sizeof (PeakData) * to_read) {
488 off_t fend = lseek (peakfile_fd, 0, SEEK_END);
490 cerr << "AudioSource["
492 << "]: cannot read peak data from peakfile ("
493 << (nread / sizeof(PeakData))
494 << " peaks instead of "
499 << " at start_byte = " << start_byte
500 << " _length = " << _length << " versus len = " << fend
501 << " expected maxpeaks = " << (_length - current_frame)/samples_per_file_peak
502 << " npeaks was " << npeaks
508 stored_peaks_read = nread / sizeof(PeakData);
514 while ((i < stored_peaks_read) && (current_stored_peak <= stored_peak_before_next_visual_peak)) {
516 xmax = max (xmax, staging[i].max);
517 xmin = min (xmin, staging[i].min);
519 ++current_stored_peak;
523 peaks[nvisual_peaks].max = xmax;
524 peaks[nvisual_peaks].min = xmin;
528 //next_visual_peak_frame = min ((next_visual_peak * samples_per_visual_peak), (next_visual_peak_frame+samples_per_visual_peak) );
529 next_visual_peak_frame = min ((double) start+cnt, (next_visual_peak_frame+samples_per_visual_peak) );
530 stored_peak_before_next_visual_peak = (uint32_t) next_visual_peak_frame / samples_per_file_peak;
534 memset (&peaks[npeaks], 0, sizeof (PeakData) * zero_fill);
541 #ifdef DEBUG_READ_PEAKS
542 cerr << "UPSAMPLE\n";
546 - less frames-per-peak (more resolution)
547 - more peaks than stored in the Peakfile
549 So, fetch data from the raw source, and generate peak
553 framecnt_t frames_read = 0;
554 framepos_t current_frame = start;
556 framecnt_t nvisual_peaks = 0;
557 framecnt_t chunksize = (framecnt_t) min (cnt, (framecnt_t) 4096);
558 raw_staging = new Sample[chunksize];
560 framepos_t frame_pos = start;
561 double pixel_pos = floor (frame_pos / samples_per_visual_peak);
562 double next_pixel_pos = ceil (frame_pos / samples_per_visual_peak);
563 double pixels_per_frame = 1.0 / samples_per_visual_peak;
568 while (nvisual_peaks < npeaks) {
570 if (i == frames_read) {
572 to_read = min (chunksize, (framecnt_t)(_length - current_frame));
574 if (current_frame >= _length) {
576 /* hmm, error condition - we've reached the end of the file
577 without generating all the peak data. cook up a zero-filled
578 data buffer and then use it. this is simpler than
579 adjusting zero_fill and npeaks and then breaking out of
583 memset (raw_staging, 0, sizeof (Sample) * chunksize);
587 to_read = min (chunksize, (_length - current_frame));
590 if ((frames_read = read_unlocked (raw_staging, current_frame, to_read)) == 0) {
591 error << string_compose(_("AudioSource[%1]: peak read - cannot read %2 samples at offset %3 of %4 (%5)"),
592 _name, to_read, current_frame, _length, strerror (errno))
601 xmax = max (xmax, raw_staging[i]);
602 xmin = min (xmin, raw_staging[i]);
605 pixel_pos += pixels_per_frame;
607 if (pixel_pos >= next_pixel_pos) {
609 peaks[nvisual_peaks].max = xmax;
610 peaks[nvisual_peaks].min = xmin;
615 next_pixel_pos = ceil (pixel_pos + 0.5);
620 memset (&peaks[npeaks], 0, sizeof (PeakData) * zero_fill);
627 delete peakfile_descriptor;
630 delete [] raw_staging;
632 #ifdef DEBUG_READ_PEAKS
639 #undef DEBUG_PEAK_BUILD
642 AudioSource::build_peaks_from_scratch ()
646 const framecnt_t bufsize = 65536; // 256kB per disk read for mono data is about ideal
651 /* hold lock while building peaks */
653 Glib::Mutex::Lock lp (_lock);
655 if (prepare_for_peakfile_writes ()) {
659 framecnt_t current_frame = 0;
660 framecnt_t cnt = _length;
662 _peaks_built = false;
663 buf = new Sample[bufsize];
667 framecnt_t frames_to_read = min (bufsize, cnt);
668 framecnt_t frames_read;
670 if ((frames_read = read_unlocked (buf, current_frame, frames_to_read)) != frames_to_read) {
671 error << string_compose(_("%1: could not write read raw data for peak computation (%2)"), _name, strerror (errno)) << endmsg;
672 done_with_peakfile_writes (false);
676 if (compute_and_write_peaks (buf, current_frame, frames_read, true, false, _FPP)) {
680 current_frame += frames_read;
689 done_with_peakfile_writes ((cnt == 0));
697 unlink (peakpath.c_str());
706 AudioSource::prepare_for_peakfile_writes ()
708 _peakfile_descriptor = new FdFileDescriptor (peakpath, true, 0664);
709 if ((_peakfile_fd = _peakfile_descriptor->allocate()) < 0) {
710 error << string_compose(_("AudioSource: cannot open peakpath (c) \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
717 AudioSource::done_with_peakfile_writes (bool done)
719 if (peak_leftover_cnt) {
720 compute_and_write_peaks (0, 0, 0, true, false, _FPP);
724 Glib::Mutex::Lock lm (_peaks_ready_lock);
726 PeaksReady (); /* EMIT SIGNAL */
729 delete _peakfile_descriptor;
730 _peakfile_descriptor = 0;
733 /** @param first_frame Offset from the source start of the first frame to process */
735 AudioSource::compute_and_write_peaks (Sample* buf, framecnt_t first_frame, framecnt_t cnt,
736 bool force, bool intermediate_peaks_ready)
738 return compute_and_write_peaks (buf, first_frame, cnt, force, intermediate_peaks_ready, _FPP);
742 AudioSource::compute_and_write_peaks (Sample* buf, framecnt_t first_frame, framecnt_t cnt,
743 bool force, bool intermediate_peaks_ready, framecnt_t fpp)
747 uint32_t peaks_computed;
748 PeakData* peakbuf = 0;
750 framepos_t current_frame;
751 framecnt_t frames_done;
752 const size_t blocksize = (128 * 1024);
753 off_t first_peak_byte;
755 if (_peakfile_descriptor == 0) {
756 prepare_for_peakfile_writes ();
760 if (peak_leftover_cnt) {
762 if (first_frame != peak_leftover_frame + peak_leftover_cnt) {
764 /* uh-oh, ::seek() since the last ::compute_and_write_peaks(),
765 and we have leftovers. flush a single peak (since the leftovers
766 never represent more than that, and restart.
771 x.min = peak_leftovers[0];
772 x.max = peak_leftovers[0];
774 off_t byte = (peak_leftover_frame / fpp) * sizeof (PeakData);
776 if (::pwrite (_peakfile_fd, &x, sizeof (PeakData), byte) != sizeof (PeakData)) {
777 error << string_compose(_("%1: could not write peak file data (%2)"), _name, strerror (errno)) << endmsg;
781 _peak_byte_max = max (_peak_byte_max, (off_t) (byte + sizeof(PeakData)));
784 Glib::Mutex::Lock lm (_peaks_ready_lock);
785 PeakRangeReady (peak_leftover_frame, peak_leftover_cnt); /* EMIT SIGNAL */
786 if (intermediate_peaks_ready) {
787 PeaksReady (); /* EMIT SIGNAL */
791 /* left overs are done */
793 peak_leftover_cnt = 0;
797 /* else ... had leftovers, but they immediately preceed the new data, so just
798 merge them and compute.
801 /* make a new contiguous buffer containing leftovers and the new stuff */
803 to_do = cnt + peak_leftover_cnt;
804 buf2 = new Sample[to_do];
807 memcpy (buf2, peak_leftovers, peak_leftover_cnt * sizeof (Sample));
810 memcpy (buf2+peak_leftover_cnt, buf, cnt * sizeof (Sample));
812 /* no more leftovers */
813 peak_leftover_cnt = 0;
815 /* use the temporary buffer */
818 /* make sure that when we write into the peakfile, we startup where we left off */
820 first_frame = peak_leftover_frame;
826 peakbuf = new PeakData[(to_do/fpp)+1];
828 current_frame = first_frame;
833 /* if some frames were passed in (i.e. we're not flushing leftovers)
834 and there are less than fpp to do, save them till
838 if (force && (to_do < fpp)) {
839 /* keep the left overs around for next time */
841 if (peak_leftover_size < to_do) {
842 delete [] peak_leftovers;
843 peak_leftovers = new Sample[to_do];
844 peak_leftover_size = to_do;
846 memcpy (peak_leftovers, buf, to_do * sizeof (Sample));
847 peak_leftover_cnt = to_do;
848 peak_leftover_frame = current_frame;
855 framecnt_t this_time = min (fpp, to_do);
857 peakbuf[peaks_computed].max = buf[0];
858 peakbuf[peaks_computed].min = buf[0];
860 ARDOUR::find_peaks (buf+1, this_time-1, &peakbuf[peaks_computed].min, &peakbuf[peaks_computed].max);
865 frames_done += this_time;
866 current_frame += this_time;
869 first_peak_byte = (first_frame / fpp) * sizeof (PeakData);
871 if (can_truncate_peaks()) {
873 /* on some filesystems (ext3, at least) this helps to reduce fragmentation of
874 the peakfiles. its not guaranteed to do so, and even on ext3 (as of december 2006)
875 it does not cause single-extent allocation even for peakfiles of
876 less than BLOCKSIZE bytes. only call ftruncate if we'll make the file larger.
879 off_t endpos = lseek (_peakfile_fd, 0, SEEK_END);
880 off_t target_length = blocksize * ((first_peak_byte + blocksize + 1) / blocksize);
882 if (endpos < target_length) {
883 if (ftruncate (_peakfile_fd, target_length)) {
884 /* error doesn't actually matter so continue on without testing */
889 if (::pwrite (_peakfile_fd, peakbuf, sizeof (PeakData) * peaks_computed, first_peak_byte) != (ssize_t) (sizeof (PeakData) * peaks_computed)) {
890 error << string_compose(_("%1: could not write peak file data (%2)"), _name, strerror (errno)) << endmsg;
894 _peak_byte_max = max (_peak_byte_max, (off_t) (first_peak_byte + sizeof(PeakData)*peaks_computed));
897 Glib::Mutex::Lock lm (_peaks_ready_lock);
898 PeakRangeReady (first_frame, frames_done); /* EMIT SIGNAL */
899 if (intermediate_peaks_ready) {
900 PeaksReady (); /* EMIT SIGNAL */
914 AudioSource::truncate_peakfile ()
916 if (_peakfile_descriptor == 0) {
917 error << string_compose (_("programming error: %1"), "AudioSource::truncate_peakfile() called without open peakfile descriptor")
922 /* truncate the peakfile down to its natural length if necessary */
924 off_t end = lseek (_peakfile_fd, 0, SEEK_END);
926 if (end > _peak_byte_max) {
927 if (ftruncate (_peakfile_fd, _peak_byte_max)) {
928 error << string_compose (_("could not truncate peakfile %1 to %2 (error: %3)"),
929 peakpath, _peak_byte_max, errno) << endmsg;
935 AudioSource::available_peaks (double zoom_factor) const
937 if (zoom_factor < _FPP) {
938 return length(_timeline_position); // peak data will come from the audio file
941 /* peak data comes from peakfile, but the filesize might not represent
942 the valid data due to ftruncate optimizations, so use _peak_byte_max state.
943 XXX - there might be some atomicity issues here, we should probably add a lock,
944 but _peak_byte_max only monotonically increases after initialization.
947 off_t end = _peak_byte_max;
949 return (end/sizeof(PeakData)) * _FPP;
953 AudioSource::mark_streaming_write_completed ()
955 Glib::Mutex::Lock lm (_peaks_ready_lock);
958 PeaksReady (); /* EMIT SIGNAL */
963 AudioSource::allocate_working_buffers (framecnt_t framerate)
965 Glib::Mutex::Lock lm (_level_buffer_lock);
968 /* Note: we don't need any buffers allocated until
969 a level 1 audiosource is created, at which
970 time we'll call ::ensure_buffers_for_level()
971 with the right value and do the right thing.
974 if (!_mixdown_buffers.empty()) {
975 ensure_buffers_for_level_locked ( _mixdown_buffers.size(), framerate);
980 AudioSource::ensure_buffers_for_level (uint32_t level, framecnt_t frame_rate)
982 Glib::Mutex::Lock lm (_level_buffer_lock);
983 ensure_buffers_for_level_locked (level, frame_rate);
987 AudioSource::ensure_buffers_for_level_locked (uint32_t level, framecnt_t frame_rate)
989 framecnt_t nframes = (framecnt_t) floor (Config->get_audio_playback_buffer_seconds() * frame_rate);
991 _mixdown_buffers.clear ();
992 _gain_buffers.clear ();
994 while (_mixdown_buffers.size() < level) {
995 _mixdown_buffers.push_back (boost::shared_ptr<Sample> (new Sample[nframes]));
996 _gain_buffers.push_back (boost::shared_ptr<gain_t> (new gain_t[nframes]));