X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Faudioregion.cc;h=f3ae05f1b1b8710970d9b8707f40fe5dfddaf9dc;hb=73192bc1a7ea55fa1864dc3826845b15c00dd2ec;hp=8c66591fa771a0730b0e812854ab4351ce3b491a;hpb=eb4d9be40c15dd1fc7069eefef684048b98d2226;p=ardour.git diff --git a/libs/ardour/audioregion.cc b/libs/ardour/audioregion.cc index 8c66591fa7..f3ae05f1b1 100644 --- a/libs/ardour/audioregion.cc +++ b/libs/ardour/audioregion.cc @@ -45,6 +45,7 @@ #include "ardour/region_factory.h" #include "ardour/runtime_functions.h" #include "ardour/transient_detector.h" +#include "ardour/progress.h" #include "i18n.h" #include @@ -103,12 +104,12 @@ AudioRegion::register_properties () , _scale_amplitude (Properties::scale_amplitude, 1.0) #define AUDIOREGION_COPY_STATE(other) \ - _envelope_active (other->_envelope_active) \ - , _default_fade_in (other->_default_fade_in) \ - , _default_fade_out (other->_default_fade_out) \ - , _fade_in_active (other->_fade_in_active) \ - , _fade_out_active (other->_fade_out_active) \ - , _scale_amplitude (other->_scale_amplitude) + _envelope_active (Properties::envelope_active, other->_envelope_active) \ + , _default_fade_in (Properties::default_fade_in, other->_default_fade_in) \ + , _default_fade_out (Properties::default_fade_out, other->_default_fade_out) \ + , _fade_in_active (Properties::fade_in_active, other->_fade_in_active) \ + , _fade_out_active (Properties::fade_out_active, other->_fade_out_active) \ + , _scale_amplitude (Properties::scale_amplitude, other->_scale_amplitude) /* a Session will reset these to its chosen defaults by calling AudioRegion::set_default_fade() */ void @@ -116,8 +117,10 @@ AudioRegion::init () { register_properties (); + suspend_property_changes(); set_default_fades (); set_default_envelope (); + resume_property_changes(); listen_to_my_curves (); connect_to_analysis_changed (); @@ -154,14 +157,16 @@ AudioRegion::AudioRegion (const SourceList& srcs) assert (_sources.size() == _master_sources.size()); } -AudioRegion::AudioRegion (boost::shared_ptr other, nframes64_t offset, bool offset_relative) +AudioRegion::AudioRegion (boost::shared_ptr other, framecnt_t offset, bool offset_relative) : Region (other, offset, offset_relative) , AUDIOREGION_COPY_STATE (other) , _automatable (other->session()) , _fade_in (new AutomationList (*other->_fade_in)) , _fade_out (new AutomationList (*other->_fade_out)) - /* XXX is this guaranteed to work for all values of offset+offset_relative? */ - , _envelope (new AutomationList (*other->_envelope, _start, _start + _length)) + /* As far as I can see, the _envelope's times are relative to region position, and have nothing + to do with sources (and hence _start). So when we copy the envelope, we just use the supplied offset. + */ + , _envelope (new AutomationList (*other->_envelope, offset, other->_length)) , _fade_in_suspended (0) , _fade_out_suspended (0) { @@ -292,8 +297,8 @@ AudioRegion::set_envelope_active (bool yn) } } -ARDOUR::nframes_t -AudioRegion::read_peaks (PeakData *buf, nframes_t npeaks, nframes_t offset, nframes_t cnt, uint32_t chan_n, double samples_per_unit) const +ARDOUR::framecnt_t +AudioRegion::read_peaks (PeakData *buf, framecnt_t npeaks, framecnt_t offset, framecnt_t cnt, uint32_t chan_n, double samples_per_unit) const { if (chan_n >= _sources.size()) { return 0; @@ -303,7 +308,7 @@ AudioRegion::read_peaks (PeakData *buf, nframes_t npeaks, nframes_t offset, nfra return 0; } else { if (_scale_amplitude != 1.0f) { - for (nframes_t n = 0; n < npeaks; ++n) { + for (framecnt_t n = 0; n < npeaks; ++n) { buf[n].max *= _scale_amplitude; buf[n].min *= _scale_amplitude; } @@ -354,6 +359,10 @@ AudioRegion::_read_at (const SourceList& /*srcs*/, framecnt_t limit, framecnt_t to_read; bool raw = (rops == ReadOpsNone); + if (n_channels() == 0) { + return 0; + } + if (muted() && !raw) { return 0; /* read nothing */ } @@ -405,7 +414,22 @@ AudioRegion::_read_at (const SourceList& /*srcs*/, framecnt_t limit, we don't have. */ - memset (mixdown_buffer, 0, sizeof (Sample) * cnt); + if (Config->get_replicate_missing_region_channels()) { + /* track is N-channel, this region has less channels, so use a relevant channel + */ + + uint32_t channel = n_channels() % chan_n; + boost::shared_ptr src = audio_source (channel); + + if (src->read (mixdown_buffer, _start + internal_offset, to_read) != to_read) { + return 0; /* "read nothing" */ + } + + /* adjust read data count appropriately since this was a duplicate read */ + src->dec_read_data_count (to_read); + } else { + memset (mixdown_buffer, 0, sizeof (Sample) * cnt); + } } if (rops & ReadOpsFades) { @@ -414,20 +438,19 @@ AudioRegion::_read_at (const SourceList& /*srcs*/, framecnt_t limit, if (_fade_in_active && _session.config.get_use_region_fades()) { - nframes_t fade_in_length = (nframes_t) _fade_in->back()->when; + framecnt_t fade_in_length = (framecnt_t) _fade_in->back()->when; /* see if this read is within the fade in */ if (internal_offset < fade_in_length) { - nframes_t fi_limit; + framecnt_t fi_limit; fi_limit = min (to_read, fade_in_length - internal_offset); - _fade_in->curve().get_vector (internal_offset, internal_offset+fi_limit, gain_buffer, fi_limit); - for (nframes_t n = 0; n < fi_limit; ++n) { + for (framecnt_t n = 0; n < fi_limit; ++n) { mixdown_buffer[n] *= gain_buffer[n]; } } @@ -456,20 +479,20 @@ AudioRegion::_read_at (const SourceList& /*srcs*/, framecnt_t limit, */ - nframes_t fade_out_length = (nframes_t) _fade_out->back()->when; - nframes_t fade_interval_start = max(internal_offset, limit-fade_out_length); - nframes_t fade_interval_end = min(internal_offset + to_read, limit); + framecnt_t fade_out_length = (framecnt_t) _fade_out->back()->when; + framecnt_t fade_interval_start = max(internal_offset, limit-fade_out_length); + framecnt_t fade_interval_end = min(internal_offset + to_read, limit); if (fade_interval_end > fade_interval_start) { /* (part of the) the fade out is in this buffer */ - nframes_t fo_limit = fade_interval_end - fade_interval_start; - nframes_t curve_offset = fade_interval_start - (limit-fade_out_length); - nframes_t fade_offset = fade_interval_start - internal_offset; + framecnt_t fo_limit = fade_interval_end - fade_interval_start; + framecnt_t curve_offset = fade_interval_start - (limit-fade_out_length); + framecnt_t fade_offset = fade_interval_start - internal_offset; _fade_out->curve().get_vector (curve_offset, curve_offset+fo_limit, gain_buffer, fo_limit); - for (nframes_t n = 0, m = fade_offset; n < fo_limit; ++n, ++m) { + for (framecnt_t n = 0, m = fade_offset; n < fo_limit; ++n, ++m) { mixdown_buffer[m] *= gain_buffer[n]; } } @@ -483,11 +506,11 @@ AudioRegion::_read_at (const SourceList& /*srcs*/, framecnt_t limit, _envelope->curve().get_vector (internal_offset, internal_offset + to_read, gain_buffer, to_read); if ((rops & ReadOpsOwnScaling) && _scale_amplitude != 1.0f) { - for (nframes_t n = 0; n < to_read; ++n) { + for (framecnt_t n = 0; n < to_read; ++n) { mixdown_buffer[n] *= gain_buffer[n] * _scale_amplitude; } } else { - for (nframes_t n = 0; n < to_read; ++n) { + for (framecnt_t n = 0; n < to_read; ++n) { mixdown_buffer[n] *= gain_buffer[n]; } } @@ -496,19 +519,19 @@ AudioRegion::_read_at (const SourceList& /*srcs*/, framecnt_t limit, // XXX this should be using what in 2.0 would have been: // Session::apply_gain_to_buffer (mixdown_buffer, to_read, _scale_amplitude); - for (nframes_t n = 0; n < to_read; ++n) { + for (framecnt_t n = 0; n < to_read; ++n) { mixdown_buffer[n] *= _scale_amplitude; } } - if (!opaque()) { + if (!opaque() && (buf != mixdown_buffer)) { /* gack. the things we do for users. */ buf += buf_offset; - for (nframes_t n = 0; n < to_read; ++n) { + for (framecnt_t n = 0; n < to_read; ++n) { buf[n] += mixdown_buffer[n]; } } @@ -689,13 +712,13 @@ AudioRegion::set_state (const XMLNode& node, int version) void AudioRegion::set_fade_in_shape (FadeShape shape) { - set_fade_in (shape, (nframes_t) _fade_in->back()->when); + set_fade_in (shape, (framecnt_t) _fade_in->back()->when); } void AudioRegion::set_fade_out_shape (FadeShape shape) { - set_fade_out (shape, (nframes_t) _fade_out->back()->when); + set_fade_out (shape, (framecnt_t) _fade_out->back()->when); } void @@ -715,12 +738,12 @@ AudioRegion::set_fade_in (FadeShape shape, framecnt_t len) _fade_in->clear (); switch (shape) { - case Linear: + case FadeLinear: _fade_in->fast_simple_add (0.0, 0.0); _fade_in->fast_simple_add (len, 1.0); break; - case Fast: + case FadeFast: _fade_in->fast_simple_add (0, 0); _fade_in->fast_simple_add (len * 0.389401, 0.0333333); _fade_in->fast_simple_add (len * 0.629032, 0.0861111); @@ -730,7 +753,7 @@ AudioRegion::set_fade_in (FadeShape shape, framecnt_t len) _fade_in->fast_simple_add (len, 1); break; - case Slow: + case FadeSlow: _fade_in->fast_simple_add (0, 0); _fade_in->fast_simple_add (len * 0.0207373, 0.197222); _fade_in->fast_simple_add (len * 0.0645161, 0.525); @@ -741,7 +764,7 @@ AudioRegion::set_fade_in (FadeShape shape, framecnt_t len) _fade_in->fast_simple_add (len, 1); break; - case LogA: + case FadeLogA: _fade_in->fast_simple_add (0, 0); _fade_in->fast_simple_add (len * 0.0737327, 0.308333); _fade_in->fast_simple_add (len * 0.246544, 0.658333); @@ -751,7 +774,7 @@ AudioRegion::set_fade_in (FadeShape shape, framecnt_t len) _fade_in->fast_simple_add (len, 1); break; - case LogB: + case FadeLogB: _fade_in->fast_simple_add (0, 0); _fade_in->fast_simple_add (len * 0.304147, 0.0694444); _fade_in->fast_simple_add (len * 0.529954, 0.152778); @@ -763,6 +786,7 @@ AudioRegion::set_fade_in (FadeShape shape, framecnt_t len) } _fade_in->thaw (); + send_change (PropertyChange (Properties::fade_in)); } void @@ -782,7 +806,7 @@ AudioRegion::set_fade_out (FadeShape shape, framecnt_t len) _fade_out->clear (); switch (shape) { - case Fast: + case FadeFast: _fade_out->fast_simple_add (len * 0, 1); _fade_out->fast_simple_add (len * 0.023041, 0.697222); _fade_out->fast_simple_add (len * 0.0553, 0.483333); @@ -792,7 +816,7 @@ AudioRegion::set_fade_out (FadeShape shape, framecnt_t len) _fade_out->fast_simple_add (len * 1, 0); break; - case LogA: + case FadeLogA: _fade_out->fast_simple_add (len * 0, 1); _fade_out->fast_simple_add (len * 0.228111, 0.988889); _fade_out->fast_simple_add (len * 0.347926, 0.972222); @@ -802,7 +826,7 @@ AudioRegion::set_fade_out (FadeShape shape, framecnt_t len) _fade_out->fast_simple_add (len * 1, 0); break; - case Slow: + case FadeSlow: _fade_out->fast_simple_add (len * 0, 1); _fade_out->fast_simple_add (len * 0.305556, 1); _fade_out->fast_simple_add (len * 0.548611, 0.991736); @@ -812,7 +836,7 @@ AudioRegion::set_fade_out (FadeShape shape, framecnt_t len) _fade_out->fast_simple_add (len * 1, 0); break; - case LogB: + case FadeLogB: _fade_out->fast_simple_add (len * 0, 1); _fade_out->fast_simple_add (len * 0.080645, 0.730556); _fade_out->fast_simple_add (len * 0.277778, 0.289256); @@ -821,13 +845,14 @@ AudioRegion::set_fade_out (FadeShape shape, framecnt_t len) _fade_out->fast_simple_add (len * 1, 0); break; - case Linear: + case FadeLinear: _fade_out->fast_simple_add (len * 0, 1); _fade_out->fast_simple_add (len * 1, 0); break; } _fade_out->thaw (); + send_change (PropertyChange (Properties::fade_in)); } void @@ -897,14 +922,14 @@ void AudioRegion::set_default_fade_in () { _fade_in_suspended = 0; - set_fade_in (Linear, 64); + set_fade_in (FadeLinear, 64); } void AudioRegion::set_default_fade_out () { _fade_out_suspended = 0; - set_fade_out (Linear, 64); + set_fade_out (FadeLinear, 64); } void @@ -935,6 +960,8 @@ AudioRegion::recompute_at_end () _envelope->truncate_end (_length); _envelope->set_max_xval (_length); _envelope->thaw (); + + suspend_property_changes(); if (_left_of_split) { set_default_fade_out (); @@ -948,6 +975,8 @@ AudioRegion::recompute_at_end () _fade_in->extend_to (_length); send_change (PropertyChange (Properties::fade_in)); } + + resume_property_changes(); } void @@ -956,6 +985,8 @@ AudioRegion::recompute_at_start () /* as above, but the shift was from the front */ _envelope->truncate_start (_length); + + suspend_property_changes(); if (_right_of_split) { set_default_fade_in (); @@ -969,6 +1000,8 @@ AudioRegion::recompute_at_start () _fade_out->extend_to (_length); send_change (PropertyChange (Properties::fade_out)); } + + resume_property_changes(); } int @@ -1029,8 +1062,8 @@ int AudioRegion::exportme (Session& /*session*/, ARDOUR::ExportSpecification& /*spec*/) { // TODO EXPORT -// const nframes_t blocksize = 4096; -// nframes_t to_read; +// const framecnt_t blocksize = 4096; +// framecnt_t to_read; // int status = -1; // // spec.channels = _sources.size(); @@ -1065,7 +1098,7 @@ AudioRegion::exportme (Session& /*session*/, ARDOUR::ExportSpecification& /*spec // goto out; // } // -// for (nframes_t x = 0; x < to_read; ++x) { +// for (framecnt_t x = 0; x < to_read; ++x) { // spec.dataF[chan+(x*spec.channels)] = buf[x]; // } // } @@ -1109,74 +1142,74 @@ AudioRegion::set_scale_amplitude (gain_t g) send_change (PropertyChange (Properties::scale_amplitude)); } -void -AudioRegion::normalize_to (float target_dB) +/** @return the maximum (linear) amplitude of the region, or a -ve + * number if the Progress object reports that the process was cancelled. + */ +double +AudioRegion::maximum_amplitude (Progress* p) const { - const framecnt_t blocksize = 64 * 1024; - Sample buf[blocksize]; - framepos_t fpos; - framepos_t fend; - framecnt_t to_read; + framepos_t fpos = _start; + framepos_t const fend = _start + _length; double maxamp = 0; - gain_t target = dB_to_coefficient (target_dB); - - if (target == 1.0f) { - /* do not normalize to precisely 1.0 (0 dBFS), to avoid making it appear - that we may have clipped. - */ - target -= FLT_EPSILON; - } - - fpos = _start; - fend = _start + _length; - - /* first pass: find max amplitude */ + framecnt_t const blocksize = 64 * 1024; + Sample buf[blocksize]; + while (fpos < fend) { uint32_t n; - to_read = min (fend - fpos, blocksize); + framecnt_t const to_read = min (fend - fpos, blocksize); for (n = 0; n < n_channels(); ++n) { /* read it in */ if (read_raw_internal (buf, fpos, to_read, 0) != to_read) { - return; + return 0; } maxamp = compute_peak (buf, to_read, maxamp); } fpos += to_read; - }; + if (p) { + p->set_progress (float (fpos - _start) / _length); + if (p->cancelled ()) { + return -1; + } + } + } + + return maxamp; +} + +/** Normalize using a given maximum amplitude and target, so that region + * _scale_amplitude becomes target / max_amplitude. + */ +void +AudioRegion::normalize (float max_amplitude, float target_dB) +{ + gain_t target = dB_to_coefficient (target_dB); + + if (target == 1.0f) { + /* do not normalize to precisely 1.0 (0 dBFS), to avoid making it appear + that we may have clipped. + */ + target -= FLT_EPSILON; + } - if (maxamp == 0.0f) { + if (max_amplitude == 0.0f) { /* don't even try */ return; } - if (maxamp == target) { + if (max_amplitude == target) { /* we can't do anything useful */ return; } - /* compute scale factor */ - - _scale_amplitude = target/maxamp; - - /* tell the diskstream we're in */ - - boost::shared_ptr pl (playlist()); - - if (pl) { - pl->ContentsChanged(); - } - - /* tell everybody else */ - - send_change (PropertyChange (Properties::scale_amplitude)); + set_scale_amplitude (target / max_amplitude); } void @@ -1274,7 +1307,7 @@ AudioRegion::audio_source (uint32_t n) const } int -AudioRegion::adjust_transients (nframes64_t delta) +AudioRegion::adjust_transients (frameoffset_t delta) { for (AnalysisFeatureList::iterator x = _transients.begin(); x != _transients.end(); ++x) { (*x) = (*x) + delta; @@ -1286,7 +1319,7 @@ AudioRegion::adjust_transients (nframes64_t delta) } int -AudioRegion::update_transient (nframes64_t old_position, nframes64_t new_position) +AudioRegion::update_transient (framepos_t old_position, framepos_t new_position) { for (AnalysisFeatureList::iterator x = _transients.begin(); x != _transients.end(); ++x) { if ((*x) == old_position) { @@ -1301,7 +1334,7 @@ AudioRegion::update_transient (nframes64_t old_position, nframes64_t new_positio } void -AudioRegion::add_transient (nframes64_t where) +AudioRegion::add_transient (framepos_t where) { _transients.push_back(where); _valid_transients = true; @@ -1310,7 +1343,7 @@ AudioRegion::add_transient (nframes64_t where) } void -AudioRegion::remove_transient (nframes64_t where) +AudioRegion::remove_transient (framepos_t where) { _transients.remove(where); _valid_transients = true; @@ -1395,15 +1428,15 @@ AudioRegion::get_transients (AnalysisFeatureList& results, bool force_new) if (!Config->get_auto_analyse_audio()) { if (!analyse_dialog_shown) { pl->session().Dialog (_("\ -You have requested an operation that requires audio analysis.\n\n \ -You currently have \"auto-analyse-audio\" disabled, which means\n\ +You have requested an operation that requires audio analysis.\n\n\ +You currently have \"auto-analyse-audio\" disabled, which means \ that transient data must be generated every time it is required.\n\n\ -If you are doing work that will require transient data on a\n\ -regular basis, you should probably enable \"auto-analyse-audio\"\n\ -+then quit ardour and restart.\n\n\ -+This dialog will not display again. But you may notice a slight delay\n\ -+in this and future transient-detection operations.\n\ -+")); +If you are doing work that will require transient data on a \ +regular basis, you should probably enable \"auto-analyse-audio\" \ +then quit ardour and restart.\n\n\ +This dialog will not display again. But you may notice a slight delay \ +in this and future transient-detection operations.\n\ +")); analyse_dialog_shown = true; } }