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);
401 delete peakfile_descriptor;
403 if (nread != sizeof (PeakData) * npeaks) {
404 cerr << "AudioSource["
406 << "]: cannot read peaks from peakfile! (read only "
416 delete peakfile_descriptor;
421 memset (&peaks[npeaks], 0, sizeof (PeakData) * zero_fill);
424 delete peakfile_descriptor;
433 #ifdef DEBUG_READ_PEAKS
434 cerr << "DOWNSAMPLE\n";
438 - more frames-per-peak (lower resolution) than the peakfile, or to put it another way,
439 - less peaks than the peakfile holds for the same range
441 So, read a block into a staging area, and then downsample from there.
443 to avoid confusion, I'll refer to the requested peaks as visual_peaks and the peakfile peaks as stored_peaks
446 const framecnt_t chunksize = (framecnt_t) min (expected_peaks, 65536.0);
448 staging = new PeakData[chunksize];
450 /* compute the rounded up frame position */
452 framepos_t current_frame = start;
453 framepos_t current_stored_peak = (framepos_t) ceil (current_frame / (double) samples_per_file_peak);
454 framepos_t next_visual_peak = (framepos_t) ceil (current_frame / samples_per_visual_peak);
455 double next_visual_peak_frame = next_visual_peak * samples_per_visual_peak;
456 framepos_t stored_peak_before_next_visual_peak = (framepos_t) next_visual_peak_frame / samples_per_file_peak;
457 framecnt_t nvisual_peaks = 0;
458 framecnt_t stored_peaks_read = 0;
461 /* handle the case where the initial visual peak is on a pixel boundary */
463 current_stored_peak = min (current_stored_peak, stored_peak_before_next_visual_peak);
465 /* open ... close during out: handling */
467 if ((peakfile_fd = peakfile_descriptor->allocate ()) < 0) {
468 error << string_compose(_("AudioSource: cannot open peakpath (b) \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
469 delete peakfile_descriptor;
474 while (nvisual_peaks < npeaks) {
476 if (i == stored_peaks_read) {
478 uint32_t start_byte = current_stored_peak * sizeof(PeakData);
479 tnp = min ((framecnt_t)(_length/samples_per_file_peak - current_stored_peak), (framecnt_t) expected_peaks);
480 to_read = min (chunksize, tnp);
482 #ifdef DEBUG_READ_PEAKS
483 cerr << "read " << sizeof (PeakData) * to_read << " from peakfile @ " << start_byte << endl;
486 if ((nread = ::pread (peakfile_fd, staging, sizeof (PeakData) * to_read, start_byte))
487 != sizeof (PeakData) * to_read) {
489 off_t fend = lseek (peakfile_fd, 0, SEEK_END);
491 cerr << "AudioSource["
493 << "]: cannot read peak data from peakfile ("
494 << (nread / sizeof(PeakData))
495 << " peaks instead of "
500 << " at start_byte = " << start_byte
501 << " _length = " << _length << " versus len = " << fend
502 << " expected maxpeaks = " << (_length - current_frame)/samples_per_file_peak
503 << " npeaks was " << npeaks
509 stored_peaks_read = nread / sizeof(PeakData);
515 while ((i < stored_peaks_read) && (current_stored_peak <= stored_peak_before_next_visual_peak)) {
517 xmax = max (xmax, staging[i].max);
518 xmin = min (xmin, staging[i].min);
520 ++current_stored_peak;
524 peaks[nvisual_peaks].max = xmax;
525 peaks[nvisual_peaks].min = xmin;
529 //next_visual_peak_frame = min ((next_visual_peak * samples_per_visual_peak), (next_visual_peak_frame+samples_per_visual_peak) );
530 next_visual_peak_frame = min ((double) start+cnt, (next_visual_peak_frame+samples_per_visual_peak) );
531 stored_peak_before_next_visual_peak = (uint32_t) next_visual_peak_frame / samples_per_file_peak;
535 memset (&peaks[npeaks], 0, sizeof (PeakData) * zero_fill);
542 #ifdef DEBUG_READ_PEAKS
543 cerr << "UPSAMPLE\n";
547 - less frames-per-peak (more resolution)
548 - more peaks than stored in the Peakfile
550 So, fetch data from the raw source, and generate peak
554 framecnt_t frames_read = 0;
555 framepos_t current_frame = start;
557 framecnt_t nvisual_peaks = 0;
558 framecnt_t chunksize = (framecnt_t) min (cnt, (framecnt_t) 4096);
559 raw_staging = new Sample[chunksize];
561 framepos_t frame_pos = start;
562 double pixel_pos = floor (frame_pos / samples_per_visual_peak);
563 double next_pixel_pos = ceil (frame_pos / samples_per_visual_peak);
564 double pixels_per_frame = 1.0 / samples_per_visual_peak;
569 while (nvisual_peaks < npeaks) {
571 if (i == frames_read) {
573 to_read = min (chunksize, (framecnt_t)(_length - current_frame));
575 if (current_frame >= _length) {
577 /* hmm, error condition - we've reached the end of the file
578 without generating all the peak data. cook up a zero-filled
579 data buffer and then use it. this is simpler than
580 adjusting zero_fill and npeaks and then breaking out of
584 memset (raw_staging, 0, sizeof (Sample) * chunksize);
588 to_read = min (chunksize, (_length - current_frame));
591 if ((frames_read = read_unlocked (raw_staging, current_frame, to_read)) == 0) {
592 error << string_compose(_("AudioSource[%1]: peak read - cannot read %2 samples at offset %3 of %4 (%5)"),
593 _name, to_read, current_frame, _length, strerror (errno))
602 xmax = max (xmax, raw_staging[i]);
603 xmin = min (xmin, raw_staging[i]);
606 pixel_pos += pixels_per_frame;
608 if (pixel_pos >= next_pixel_pos) {
610 peaks[nvisual_peaks].max = xmax;
611 peaks[nvisual_peaks].min = xmin;
616 next_pixel_pos = ceil (pixel_pos + 0.5);
621 memset (&peaks[npeaks], 0, sizeof (PeakData) * zero_fill);
628 delete peakfile_descriptor;
631 delete [] raw_staging;
633 #ifdef DEBUG_READ_PEAKS
640 #undef DEBUG_PEAK_BUILD
643 AudioSource::build_peaks_from_scratch ()
647 const framecnt_t bufsize = 65536; // 256kB per disk read for mono data is about ideal
652 /* hold lock while building peaks */
654 Glib::Mutex::Lock lp (_lock);
656 if (prepare_for_peakfile_writes ()) {
660 framecnt_t current_frame = 0;
661 framecnt_t cnt = _length;
663 _peaks_built = false;
664 buf = new Sample[bufsize];
668 framecnt_t frames_to_read = min (bufsize, cnt);
669 framecnt_t frames_read;
671 if ((frames_read = read_unlocked (buf, current_frame, frames_to_read)) != frames_to_read) {
672 error << string_compose(_("%1: could not write read raw data for peak computation (%2)"), _name, strerror (errno)) << endmsg;
673 done_with_peakfile_writes (false);
677 if (compute_and_write_peaks (buf, current_frame, frames_read, true, false, _FPP)) {
681 current_frame += frames_read;
690 done_with_peakfile_writes ((cnt == 0));
698 unlink (peakpath.c_str());
707 AudioSource::prepare_for_peakfile_writes ()
709 _peakfile_descriptor = new FdFileDescriptor (peakpath, true, 0664);
710 if ((_peakfile_fd = _peakfile_descriptor->allocate()) < 0) {
711 error << string_compose(_("AudioSource: cannot open peakpath (c) \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
718 AudioSource::done_with_peakfile_writes (bool done)
720 if (peak_leftover_cnt) {
721 compute_and_write_peaks (0, 0, 0, true, false, _FPP);
725 Glib::Mutex::Lock lm (_peaks_ready_lock);
727 PeaksReady (); /* EMIT SIGNAL */
730 delete _peakfile_descriptor;
731 _peakfile_descriptor = 0;
734 /** @param first_frame Offset from the source start of the first frame to process */
736 AudioSource::compute_and_write_peaks (Sample* buf, framecnt_t first_frame, framecnt_t cnt,
737 bool force, bool intermediate_peaks_ready)
739 return compute_and_write_peaks (buf, first_frame, cnt, force, intermediate_peaks_ready, _FPP);
743 AudioSource::compute_and_write_peaks (Sample* buf, framecnt_t first_frame, framecnt_t cnt,
744 bool force, bool intermediate_peaks_ready, framecnt_t fpp)
748 uint32_t peaks_computed;
749 PeakData* peakbuf = 0;
751 framepos_t current_frame;
752 framecnt_t frames_done;
753 const size_t blocksize = (128 * 1024);
754 off_t first_peak_byte;
756 if (_peakfile_descriptor == 0) {
757 prepare_for_peakfile_writes ();
761 if (peak_leftover_cnt) {
763 if (first_frame != peak_leftover_frame + peak_leftover_cnt) {
765 /* uh-oh, ::seek() since the last ::compute_and_write_peaks(),
766 and we have leftovers. flush a single peak (since the leftovers
767 never represent more than that, and restart.
772 x.min = peak_leftovers[0];
773 x.max = peak_leftovers[0];
775 off_t byte = (peak_leftover_frame / fpp) * sizeof (PeakData);
777 if (::pwrite (_peakfile_fd, &x, sizeof (PeakData), byte) != sizeof (PeakData)) {
778 error << string_compose(_("%1: could not write peak file data (%2)"), _name, strerror (errno)) << endmsg;
782 _peak_byte_max = max (_peak_byte_max, (off_t) (byte + sizeof(PeakData)));
785 Glib::Mutex::Lock lm (_peaks_ready_lock);
786 PeakRangeReady (peak_leftover_frame, peak_leftover_cnt); /* EMIT SIGNAL */
787 if (intermediate_peaks_ready) {
788 PeaksReady (); /* EMIT SIGNAL */
792 /* left overs are done */
794 peak_leftover_cnt = 0;
798 /* else ... had leftovers, but they immediately preceed the new data, so just
799 merge them and compute.
802 /* make a new contiguous buffer containing leftovers and the new stuff */
804 to_do = cnt + peak_leftover_cnt;
805 buf2 = new Sample[to_do];
808 memcpy (buf2, peak_leftovers, peak_leftover_cnt * sizeof (Sample));
811 memcpy (buf2+peak_leftover_cnt, buf, cnt * sizeof (Sample));
813 /* no more leftovers */
814 peak_leftover_cnt = 0;
816 /* use the temporary buffer */
819 /* make sure that when we write into the peakfile, we startup where we left off */
821 first_frame = peak_leftover_frame;
827 peakbuf = new PeakData[(to_do/fpp)+1];
829 current_frame = first_frame;
834 /* if some frames were passed in (i.e. we're not flushing leftovers)
835 and there are less than fpp to do, save them till
839 if (force && (to_do < fpp)) {
840 /* keep the left overs around for next time */
842 if (peak_leftover_size < to_do) {
843 delete [] peak_leftovers;
844 peak_leftovers = new Sample[to_do];
845 peak_leftover_size = to_do;
847 memcpy (peak_leftovers, buf, to_do * sizeof (Sample));
848 peak_leftover_cnt = to_do;
849 peak_leftover_frame = current_frame;
856 framecnt_t this_time = min (fpp, to_do);
858 peakbuf[peaks_computed].max = buf[0];
859 peakbuf[peaks_computed].min = buf[0];
861 ARDOUR::find_peaks (buf+1, this_time-1, &peakbuf[peaks_computed].min, &peakbuf[peaks_computed].max);
866 frames_done += this_time;
867 current_frame += this_time;
870 first_peak_byte = (first_frame / fpp) * sizeof (PeakData);
872 if (can_truncate_peaks()) {
874 /* on some filesystems (ext3, at least) this helps to reduce fragmentation of
875 the peakfiles. its not guaranteed to do so, and even on ext3 (as of december 2006)
876 it does not cause single-extent allocation even for peakfiles of
877 less than BLOCKSIZE bytes. only call ftruncate if we'll make the file larger.
880 off_t endpos = lseek (_peakfile_fd, 0, SEEK_END);
881 off_t target_length = blocksize * ((first_peak_byte + blocksize + 1) / blocksize);
883 if (endpos < target_length) {
884 (void) ftruncate (_peakfile_fd, target_length);
885 /* error doesn't actually matter though, 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 (void) ftruncate (_peakfile_fd, _peak_byte_max);
932 AudioSource::available_peaks (double zoom_factor) const
934 if (zoom_factor < _FPP) {
935 return length(_timeline_position); // peak data will come from the audio file
938 /* peak data comes from peakfile, but the filesize might not represent
939 the valid data due to ftruncate optimizations, so use _peak_byte_max state.
940 XXX - there might be some atomicity issues here, we should probably add a lock,
941 but _peak_byte_max only monotonically increases after initialization.
944 off_t end = _peak_byte_max;
946 return (end/sizeof(PeakData)) * _FPP;
950 AudioSource::mark_streaming_write_completed ()
952 Glib::Mutex::Lock lm (_peaks_ready_lock);
955 PeaksReady (); /* EMIT SIGNAL */
960 AudioSource::allocate_working_buffers (framecnt_t framerate)
962 Glib::Mutex::Lock lm (_level_buffer_lock);
965 /* Note: we don't need any buffers allocated until
966 a level 1 audiosource is created, at which
967 time we'll call ::ensure_buffers_for_level()
968 with the right value and do the right thing.
971 if (!_mixdown_buffers.empty()) {
972 ensure_buffers_for_level_locked ( _mixdown_buffers.size(), framerate);
977 AudioSource::ensure_buffers_for_level (uint32_t level, framecnt_t frame_rate)
979 Glib::Mutex::Lock lm (_level_buffer_lock);
980 ensure_buffers_for_level_locked (level, frame_rate);
984 AudioSource::ensure_buffers_for_level_locked (uint32_t level, framecnt_t frame_rate)
986 framecnt_t nframes = (framecnt_t) floor (Config->get_audio_playback_buffer_seconds() * frame_rate);
988 _mixdown_buffers.clear ();
989 _gain_buffers.clear ();
991 while (_mixdown_buffers.size() < level) {
992 _mixdown_buffers.push_back (boost::shared_ptr<Sample> (new Sample[nframes]));
993 _gain_buffers.push_back (boost::shared_ptr<gain_t> (new gain_t[nframes]));