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"
39
#include "ardour/audiosource.h"
40
#include "ardour/rc_configuration.h"
41
#include "ardour/runtime_functions.h"
46
using namespace ARDOUR;
49
Glib::Threads::Mutex AudioSource::_level_buffer_lock;
50
vector<boost::shared_array<Sample> > AudioSource::_mixdown_buffers;
51
vector<boost::shared_array<gain_t> > AudioSource::_gain_buffers;
52
size_t AudioSource::_working_buffers_size = 0;
53
bool AudioSource::_build_missing_peakfiles = false;
55
/** true if we want peakfiles (e.g. if we are displaying a GUI) */
56
bool AudioSource::_build_peakfiles = false;
60
AudioSource::AudioSource (Session& s, string name)
61
: Source (s, DataType::AUDIO, name)
66
_peakfile_descriptor = 0;
67
peak_leftover_cnt = 0;
68
peak_leftover_size = 0;
72
AudioSource::AudioSource (Session& s, const XMLNode& node)
79
_peakfile_descriptor = 0;
80
peak_leftover_cnt = 0;
81
peak_leftover_size = 0;
84
if (set_state (node, Stateful::loading_state_version)) {
85
throw failed_constructor();
89
AudioSource::~AudioSource ()
91
/* shouldn't happen but make sure we don't leak file descriptors anyway */
93
if (peak_leftover_cnt) {
94
cerr << "AudioSource destroyed with leftover peak data pending" << endl;
97
delete _peakfile_descriptor;
98
delete [] peak_leftovers;
102
AudioSource::get_state ()
104
XMLNode& node (Source::get_state());
106
if (_captured_for.length()) {
107
node.add_property ("captured-for", _captured_for);
114
AudioSource::set_state (const XMLNode& node, int /*version*/)
116
const XMLProperty* prop;
118
if ((prop = node.property ("captured-for")) != 0) {
119
_captured_for = prop->value();
126
AudioSource::empty () const
132
AudioSource::length (framepos_t /*pos*/) const
138
AudioSource::update_length (framecnt_t len)
146
/***********************************************************************
148
***********************************************************************/
150
/** Checks to see if peaks are ready. If so, we return true. If not, we return false, and
151
* things are set up so that doThisWhenReady is called when the peaks are ready.
152
* A new PBD::ScopedConnection is created for the associated connection and written to
153
* *connect_here_if_not.
155
* @param doThisWhenReady Function to call when peaks are ready (if they are not already).
156
* @param connect_here_if_not Address to write new ScopedConnection to.
157
* @param event_loop Event loop for doThisWhenReady to be called in.
160
AudioSource::peaks_ready (boost::function<void()> doThisWhenReady, ScopedConnection** connect_here_if_not, EventLoop* event_loop) const
163
Glib::Threads::Mutex::Lock lm (_peaks_ready_lock);
165
if (!(ret = _peaks_built)) {
166
*connect_here_if_not = new ScopedConnection;
167
PeaksReady.connect (**connect_here_if_not, MISSING_INVALIDATOR, doThisWhenReady, event_loop);
174
AudioSource::touch_peakfile ()
178
if (stat (peakpath.c_str(), &statbuf) != 0 || statbuf.st_size == 0) {
184
tbuf.actime = statbuf.st_atime;
185
tbuf.modtime = time ((time_t*) 0);
187
utime (peakpath.c_str(), &tbuf);
191
AudioSource::rename_peakfile (string newpath)
193
/* caller must hold _lock */
195
string oldpath = peakpath;
197
if (Glib::file_test (oldpath, Glib::FILE_TEST_EXISTS)) {
198
if (rename (oldpath.c_str(), newpath.c_str()) != 0) {
199
error << string_compose (_("cannot rename peakfile for %1 from %2 to %3 (%4)"), _name, oldpath, newpath, strerror (errno)) << endmsg;
210
AudioSource::initialize_peakfile (string audio_path)
214
peakpath = peak_path (audio_path);
216
/* if the peak file should be there, but isn't .... */
218
if (!empty() && !Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
219
peakpath = find_broken_peakfile (peakpath, audio_path);
222
if (stat (peakpath.c_str(), &statbuf)) {
223
if (errno != ENOENT) {
224
/* it exists in the peaks dir, but there is some kind of error */
226
error << string_compose(_("AudioSource: cannot stat peakfile \"%1\""), peakpath) << endmsg;
230
/* peakfile does not exist */
232
_peaks_built = false;
236
/* we found it in the peaks dir, so check it out */
238
if (statbuf.st_size == 0 || (statbuf.st_size < (off_t) ((length(_timeline_position) / _FPP) * sizeof (PeakData)))) {
240
_peaks_built = false;
242
// Check if the audio file has changed since the peakfile was built.
243
struct stat stat_file;
244
int err = stat (audio_path.c_str(), &stat_file);
248
/* no audio path - nested source or we can't
249
read it or ... whatever, use the peakfile as-is.
253
_peak_byte_max = statbuf.st_size;
257
/* allow 6 seconds slop on checking peak vs. file times because of various
261
if (stat_file.st_mtime > statbuf.st_mtime && (stat_file.st_mtime - statbuf.st_mtime > 6)) {
262
_peaks_built = false;
266
_peak_byte_max = statbuf.st_size;
272
if (!empty() && !_peaks_built && _build_missing_peakfiles && _build_peakfiles) {
273
build_peaks_from_scratch ();
280
AudioSource::read (Sample *dst, framepos_t start, framecnt_t cnt, int /*channel*/) const
284
Glib::Threads::Mutex::Lock lm (_lock);
285
return read_unlocked (dst, start, cnt);
289
AudioSource::write (Sample *dst, framecnt_t cnt)
291
Glib::Threads::Mutex::Lock lm (_lock);
292
/* any write makes the fill not removable */
293
_flags = Flag (_flags & ~Removable);
294
return write_unlocked (dst, cnt);
298
AudioSource::read_peaks (PeakData *peaks, framecnt_t npeaks, framepos_t start, framecnt_t cnt, double samples_per_visual_peak) const
300
return read_peaks_with_fpp (peaks, npeaks, start, cnt, samples_per_visual_peak, _FPP);
303
/** @param peaks Buffer to write peak data.
304
* @param npeaks Number of peaks to write.
308
AudioSource::read_peaks_with_fpp (PeakData *peaks, framecnt_t npeaks, framepos_t start, framecnt_t cnt,
309
double samples_per_visual_peak, framecnt_t samples_per_file_peak) const
311
Glib::Threads::Mutex::Lock lm (_lock);
313
double expected_peaks;
314
PeakData::PeakDatum xmax;
315
PeakData::PeakDatum xmin;
318
framecnt_t zero_fill = 0;
320
PeakData* staging = 0;
321
Sample* raw_staging = 0;
323
FdFileDescriptor* peakfile_descriptor = new FdFileDescriptor (peakpath, false, 0664);
324
int peakfile_fd = -1;
326
expected_peaks = (cnt / (double) samples_per_file_peak);
327
scale = npeaks/expected_peaks;
329
#undef DEBUG_READ_PEAKS
330
#ifdef DEBUG_READ_PEAKS
331
cerr << "======>RP: npeaks = " << npeaks
332
<< " start = " << start
334
<< " len = " << _length
335
<< " samples_per_visual_peak =" << samples_per_visual_peak
336
<< " expected was " << expected_peaks << " ... scale = " << scale
337
<< " PD ptr = " << peaks
342
/* fix for near-end-of-file conditions */
344
if (cnt > _length - start) {
345
// cerr << "too close to end @ " << _length << " given " << start << " + " << cnt << endl;
346
cnt = _length - start;
347
framecnt_t old = npeaks;
348
npeaks = min ((framecnt_t) floor (cnt / samples_per_visual_peak), npeaks);
349
zero_fill = old - npeaks;
352
// cerr << "actual npeaks = " << npeaks << " zf = " << zero_fill << endl;
356
#ifdef DEBUG_READ_PEAKS
357
cerr << "RAW DATA\n";
359
/* no scaling at all, just get the sample data and duplicate it for
360
both max and min peak values.
363
Sample* raw_staging = new Sample[cnt];
365
if (read_unlocked (raw_staging, start, cnt) != cnt) {
366
error << _("cannot read sample data for unscaled peak computation") << endmsg;
370
for (framecnt_t i = 0; i < npeaks; ++i) {
371
peaks[i].max = raw_staging[i];
372
peaks[i].min = raw_staging[i];
375
delete peakfile_descriptor;
376
delete [] raw_staging;
382
off_t first_peak_byte = (start / samples_per_file_peak) * sizeof (PeakData);
384
/* open, read, close */
386
if ((peakfile_fd = peakfile_descriptor->allocate ()) < 0) {
387
error << string_compose(_("AudioSource: cannot open peakpath (a) \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
388
delete peakfile_descriptor;
392
#ifdef DEBUG_READ_PEAKS
393
cerr << "DIRECT PEAKS\n";
396
nread = ::pread (peakfile_fd, peaks, sizeof (PeakData)* npeaks, first_peak_byte);
398
if (nread != sizeof (PeakData) * npeaks) {
399
cerr << "AudioSource["
401
<< "]: cannot read peaks from peakfile! (read only "
411
delete peakfile_descriptor;
416
memset (&peaks[npeaks], 0, sizeof (PeakData) * zero_fill);
419
delete peakfile_descriptor;
428
#ifdef DEBUG_READ_PEAKS
429
cerr << "DOWNSAMPLE\n";
433
- more frames-per-peak (lower resolution) than the peakfile, or to put it another way,
434
- less peaks than the peakfile holds for the same range
436
So, read a block into a staging area, and then downsample from there.
438
to avoid confusion, I'll refer to the requested peaks as visual_peaks and the peakfile peaks as stored_peaks
441
const framecnt_t chunksize = (framecnt_t) min (expected_peaks, 65536.0);
443
staging = new PeakData[chunksize];
445
/* compute the rounded up frame position */
447
framepos_t current_frame = start;
448
framepos_t current_stored_peak = (framepos_t) ceil (current_frame / (double) samples_per_file_peak);
449
framepos_t next_visual_peak = (framepos_t) ceil (current_frame / samples_per_visual_peak);
450
double next_visual_peak_frame = next_visual_peak * samples_per_visual_peak;
451
framepos_t stored_peak_before_next_visual_peak = (framepos_t) next_visual_peak_frame / samples_per_file_peak;
452
framecnt_t nvisual_peaks = 0;
453
framecnt_t stored_peaks_read = 0;
456
/* handle the case where the initial visual peak is on a pixel boundary */
458
current_stored_peak = min (current_stored_peak, stored_peak_before_next_visual_peak);
460
/* open ... close during out: handling */
462
if ((peakfile_fd = peakfile_descriptor->allocate ()) < 0) {
463
error << string_compose(_("AudioSource: cannot open peakpath (b) \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
464
delete peakfile_descriptor;
469
while (nvisual_peaks < npeaks) {
471
if (i == stored_peaks_read) {
473
uint32_t start_byte = current_stored_peak * sizeof(PeakData);
474
tnp = min ((framecnt_t)(_length/samples_per_file_peak - current_stored_peak), (framecnt_t) expected_peaks);
475
to_read = min (chunksize, tnp);
477
#ifdef DEBUG_READ_PEAKS
478
cerr << "read " << sizeof (PeakData) * to_read << " from peakfile @ " << start_byte << endl;
481
if ((nread = ::pread (peakfile_fd, staging, sizeof (PeakData) * to_read, start_byte))
482
!= sizeof (PeakData) * to_read) {
484
off_t fend = lseek (peakfile_fd, 0, SEEK_END);
486
cerr << "AudioSource["
488
<< "]: cannot read peak data from peakfile ("
489
<< (nread / sizeof(PeakData))
490
<< " peaks instead of "
495
<< " at start_byte = " << start_byte
496
<< " _length = " << _length << " versus len = " << fend
497
<< " expected maxpeaks = " << (_length - current_frame)/samples_per_file_peak
498
<< " npeaks was " << npeaks
504
stored_peaks_read = nread / sizeof(PeakData);
510
while ((i < stored_peaks_read) && (current_stored_peak <= stored_peak_before_next_visual_peak)) {
512
xmax = max (xmax, staging[i].max);
513
xmin = min (xmin, staging[i].min);
515
++current_stored_peak;
519
peaks[nvisual_peaks].max = xmax;
520
peaks[nvisual_peaks].min = xmin;
524
//next_visual_peak_frame = min ((next_visual_peak * samples_per_visual_peak), (next_visual_peak_frame+samples_per_visual_peak) );
525
next_visual_peak_frame = min ((double) start+cnt, (next_visual_peak_frame+samples_per_visual_peak) );
526
stored_peak_before_next_visual_peak = (uint32_t) next_visual_peak_frame / samples_per_file_peak;
530
memset (&peaks[npeaks], 0, sizeof (PeakData) * zero_fill);
537
#ifdef DEBUG_READ_PEAKS
538
cerr << "UPSAMPLE\n";
542
- less frames-per-peak (more resolution)
543
- more peaks than stored in the Peakfile
545
So, fetch data from the raw source, and generate peak
549
framecnt_t frames_read = 0;
550
framepos_t current_frame = start;
552
framecnt_t nvisual_peaks = 0;
553
framecnt_t chunksize = (framecnt_t) min (cnt, (framecnt_t) 4096);
554
raw_staging = new Sample[chunksize];
556
framepos_t frame_pos = start;
557
double pixel_pos = floor (frame_pos / samples_per_visual_peak);
558
double next_pixel_pos = ceil (frame_pos / samples_per_visual_peak);
559
double pixels_per_frame = 1.0 / samples_per_visual_peak;
564
while (nvisual_peaks < npeaks) {
566
if (i == frames_read) {
568
to_read = min (chunksize, (framecnt_t)(_length - current_frame));
570
if (current_frame >= _length) {
572
/* hmm, error condition - we've reached the end of the file
573
without generating all the peak data. cook up a zero-filled
574
data buffer and then use it. this is simpler than
575
adjusting zero_fill and npeaks and then breaking out of
579
memset (raw_staging, 0, sizeof (Sample) * chunksize);
583
to_read = min (chunksize, (_length - current_frame));
586
if ((frames_read = read_unlocked (raw_staging, current_frame, to_read)) == 0) {
587
error << string_compose(_("AudioSource[%1]: peak read - cannot read %2 samples at offset %3 of %4 (%5)"),
588
_name, to_read, current_frame, _length, strerror (errno))
597
xmax = max (xmax, raw_staging[i]);
598
xmin = min (xmin, raw_staging[i]);
601
pixel_pos += pixels_per_frame;
603
if (pixel_pos >= next_pixel_pos) {
605
peaks[nvisual_peaks].max = xmax;
606
peaks[nvisual_peaks].min = xmin;
611
next_pixel_pos = ceil (pixel_pos + 0.5);
616
memset (&peaks[npeaks], 0, sizeof (PeakData) * zero_fill);
623
delete peakfile_descriptor;
626
delete [] raw_staging;
628
#ifdef DEBUG_READ_PEAKS
635
#undef DEBUG_PEAK_BUILD
638
AudioSource::build_peaks_from_scratch ()
642
const framecnt_t bufsize = 65536; // 256kB per disk read for mono data is about ideal
647
/* hold lock while building peaks */
649
Glib::Threads::Mutex::Lock lp (_lock);
651
if (prepare_for_peakfile_writes ()) {
655
framecnt_t current_frame = 0;
656
framecnt_t cnt = _length;
658
_peaks_built = false;
659
buf = new Sample[bufsize];
663
framecnt_t frames_to_read = min (bufsize, cnt);
664
framecnt_t frames_read;
666
if ((frames_read = read_unlocked (buf, current_frame, frames_to_read)) != frames_to_read) {
667
error << string_compose(_("%1: could not write read raw data for peak computation (%2)"), _name, strerror (errno)) << endmsg;
668
done_with_peakfile_writes (false);
672
if (compute_and_write_peaks (buf, current_frame, frames_read, true, false, _FPP)) {
676
current_frame += frames_read;
685
done_with_peakfile_writes ((cnt == 0));
693
unlink (peakpath.c_str());
702
AudioSource::prepare_for_peakfile_writes ()
704
_peakfile_descriptor = new FdFileDescriptor (peakpath, true, 0664);
705
if ((_peakfile_fd = _peakfile_descriptor->allocate()) < 0) {
706
error << string_compose(_("AudioSource: cannot open peakpath (c) \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
713
AudioSource::done_with_peakfile_writes (bool done)
715
if (peak_leftover_cnt) {
716
compute_and_write_peaks (0, 0, 0, true, false, _FPP);
720
Glib::Threads::Mutex::Lock lm (_peaks_ready_lock);
722
PeaksReady (); /* EMIT SIGNAL */
725
delete _peakfile_descriptor;
726
_peakfile_descriptor = 0;
729
/** @param first_frame Offset from the source start of the first frame to process */
731
AudioSource::compute_and_write_peaks (Sample* buf, framecnt_t first_frame, framecnt_t cnt,
732
bool force, bool intermediate_peaks_ready)
734
return compute_and_write_peaks (buf, first_frame, cnt, force, intermediate_peaks_ready, _FPP);
738
AudioSource::compute_and_write_peaks (Sample* buf, framecnt_t first_frame, framecnt_t cnt,
739
bool force, bool intermediate_peaks_ready, framecnt_t fpp)
743
uint32_t peaks_computed;
744
PeakData* peakbuf = 0;
746
framepos_t current_frame;
747
framecnt_t frames_done;
748
const size_t blocksize = (128 * 1024);
749
off_t first_peak_byte;
751
if (_peakfile_descriptor == 0) {
752
prepare_for_peakfile_writes ();
756
if (peak_leftover_cnt) {
758
if (first_frame != peak_leftover_frame + peak_leftover_cnt) {
760
/* uh-oh, ::seek() since the last ::compute_and_write_peaks(),
761
and we have leftovers. flush a single peak (since the leftovers
762
never represent more than that, and restart.
767
x.min = peak_leftovers[0];
768
x.max = peak_leftovers[0];
770
off_t byte = (peak_leftover_frame / fpp) * sizeof (PeakData);
772
if (::pwrite (_peakfile_fd, &x, sizeof (PeakData), byte) != sizeof (PeakData)) {
773
error << string_compose(_("%1: could not write peak file data (%2)"), _name, strerror (errno)) << endmsg;
777
_peak_byte_max = max (_peak_byte_max, (off_t) (byte + sizeof(PeakData)));
780
Glib::Threads::Mutex::Lock lm (_peaks_ready_lock);
781
PeakRangeReady (peak_leftover_frame, peak_leftover_cnt); /* EMIT SIGNAL */
782
if (intermediate_peaks_ready) {
783
PeaksReady (); /* EMIT SIGNAL */
787
/* left overs are done */
789
peak_leftover_cnt = 0;
793
/* else ... had leftovers, but they immediately preceed the new data, so just
794
merge them and compute.
797
/* make a new contiguous buffer containing leftovers and the new stuff */
799
to_do = cnt + peak_leftover_cnt;
800
buf2 = new Sample[to_do];
803
memcpy (buf2, peak_leftovers, peak_leftover_cnt * sizeof (Sample));
806
memcpy (buf2+peak_leftover_cnt, buf, cnt * sizeof (Sample));
808
/* no more leftovers */
809
peak_leftover_cnt = 0;
811
/* use the temporary buffer */
814
/* make sure that when we write into the peakfile, we startup where we left off */
816
first_frame = peak_leftover_frame;
822
peakbuf = new PeakData[(to_do/fpp)+1];
824
current_frame = first_frame;
829
/* if some frames were passed in (i.e. we're not flushing leftovers)
830
and there are less than fpp to do, save them till
834
if (force && (to_do < fpp)) {
835
/* keep the left overs around for next time */
837
if (peak_leftover_size < to_do) {
838
delete [] peak_leftovers;
839
peak_leftovers = new Sample[to_do];
840
peak_leftover_size = to_do;
842
memcpy (peak_leftovers, buf, to_do * sizeof (Sample));
843
peak_leftover_cnt = to_do;
844
peak_leftover_frame = current_frame;
851
framecnt_t this_time = min (fpp, to_do);
853
peakbuf[peaks_computed].max = buf[0];
854
peakbuf[peaks_computed].min = buf[0];
856
ARDOUR::find_peaks (buf+1, this_time-1, &peakbuf[peaks_computed].min, &peakbuf[peaks_computed].max);
861
frames_done += this_time;
862
current_frame += this_time;
865
first_peak_byte = (first_frame / fpp) * sizeof (PeakData);
867
if (can_truncate_peaks()) {
869
/* on some filesystems (ext3, at least) this helps to reduce fragmentation of
870
the peakfiles. its not guaranteed to do so, and even on ext3 (as of december 2006)
871
it does not cause single-extent allocation even for peakfiles of
872
less than BLOCKSIZE bytes. only call ftruncate if we'll make the file larger.
875
off_t endpos = lseek (_peakfile_fd, 0, SEEK_END);
876
off_t target_length = blocksize * ((first_peak_byte + blocksize + 1) / blocksize);
878
if (endpos < target_length) {
879
if (ftruncate (_peakfile_fd, target_length)) {
880
/* error doesn't actually matter so continue on without testing */
885
if (::pwrite (_peakfile_fd, peakbuf, sizeof (PeakData) * peaks_computed, first_peak_byte) != (ssize_t) (sizeof (PeakData) * peaks_computed)) {
886
error << string_compose(_("%1: could not write peak file data (%2)"), _name, strerror (errno)) << endmsg;
890
_peak_byte_max = max (_peak_byte_max, (off_t) (first_peak_byte + sizeof(PeakData)*peaks_computed));
893
Glib::Threads::Mutex::Lock lm (_peaks_ready_lock);
894
PeakRangeReady (first_frame, frames_done); /* EMIT SIGNAL */
895
if (intermediate_peaks_ready) {
896
PeaksReady (); /* EMIT SIGNAL */
910
AudioSource::truncate_peakfile ()
912
if (_peakfile_descriptor == 0) {
913
error << string_compose (_("programming error: %1"), "AudioSource::truncate_peakfile() called without open peakfile descriptor")
918
/* truncate the peakfile down to its natural length if necessary */
920
off_t end = lseek (_peakfile_fd, 0, SEEK_END);
922
if (end > _peak_byte_max) {
923
if (ftruncate (_peakfile_fd, _peak_byte_max)) {
924
error << string_compose (_("could not truncate peakfile %1 to %2 (error: %3)"),
925
peakpath, _peak_byte_max, errno) << endmsg;
931
AudioSource::available_peaks (double zoom_factor) const
933
if (zoom_factor < _FPP) {
934
return length(_timeline_position); // peak data will come from the audio file
937
/* peak data comes from peakfile, but the filesize might not represent
938
the valid data due to ftruncate optimizations, so use _peak_byte_max state.
939
XXX - there might be some atomicity issues here, we should probably add a lock,
940
but _peak_byte_max only monotonically increases after initialization.
943
off_t end = _peak_byte_max;
945
return (end/sizeof(PeakData)) * _FPP;
949
AudioSource::mark_streaming_write_completed ()
951
Glib::Threads::Mutex::Lock lm (_peaks_ready_lock);
954
PeaksReady (); /* EMIT SIGNAL */
959
AudioSource::allocate_working_buffers (framecnt_t framerate)
961
Glib::Threads::Mutex::Lock lm (_level_buffer_lock);
964
/* Note: we don't need any buffers allocated until
965
a level 1 audiosource is created, at which
966
time we'll call ::ensure_buffers_for_level()
967
with the right value and do the right thing.
970
if (!_mixdown_buffers.empty()) {
971
ensure_buffers_for_level_locked ( _mixdown_buffers.size(), framerate);
976
AudioSource::ensure_buffers_for_level (uint32_t level, framecnt_t frame_rate)
978
Glib::Threads::Mutex::Lock lm (_level_buffer_lock);
979
ensure_buffers_for_level_locked (level, frame_rate);
983
AudioSource::ensure_buffers_for_level_locked (uint32_t level, framecnt_t frame_rate)
985
framecnt_t nframes = (framecnt_t) floor (Config->get_audio_playback_buffer_seconds() * frame_rate);
987
/* this may be called because either "level" or "frame_rate" have
988
* changed. and it may be called with "level" smaller than the current
989
* number of buffers, because a new compound region has been created at
990
* a more shallow level than the deepest one we currently have.
993
uint32_t limit = max ((size_t) level, _mixdown_buffers.size());
995
_mixdown_buffers.clear ();
996
_gain_buffers.clear ();
998
for (uint32_t n = 0; n < limit; ++n) {
999
_mixdown_buffers.push_back (boost::shared_array<Sample> (new Sample[nframes]));
1000
_gain_buffers.push_back (boost::shared_array<gain_t> (new gain_t[nframes]));