X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Faudioregion.cc;h=6163897b2015c24ce9434fd23706efc5ff676649;hb=5a3a2fad4fd1c217a5771caa64efe92a0b305275;hp=bcb36ab85a1db8e69ce88d7a72422766cbc914e5;hpb=a1955a82e81816161f5b7dbf460a694e902237b0;p=ardour.git diff --git a/libs/ardour/audioregion.cc b/libs/ardour/audioregion.cc index bcb36ab85a..6163897b20 100644 --- a/libs/ardour/audioregion.cc +++ b/libs/ardour/audioregion.cc @@ -212,7 +212,8 @@ AudioRegion::AudioRegion (boost::shared_ptr other) : Region (other), _fade_in (other->_fade_in), _fade_out (other->_fade_out), - _envelope (other->_envelope) + _envelope (other->_envelope) + { /* Pure copy constructor */ @@ -241,11 +242,42 @@ AudioRegion::AudioRegion (boost::shared_ptr other) } _scale_amplitude = other->_scale_amplitude; - _envelope = other->_envelope; _fade_in_disabled = 0; _fade_out_disabled = 0; - + + listen_to_my_curves (); + listen_to_my_sources (); +} + +AudioRegion::AudioRegion (boost::shared_ptr other, const SourceList& srcs, + nframes_t length, const string& name, layer_t layer, Flag flags) + : Region (other, length, name, layer, flags), + _fade_in (other->_fade_in), + _fade_out (other->_fade_out), + _envelope (other->_envelope) + +{ + /* make-a-sort-of-copy-with-different-sources constructor (used by audio filter) */ + + set > unique_srcs; + + for (SourceList::const_iterator i=srcs.begin(); i != srcs.end(); ++i) { + sources.push_back (*i); + master_sources.push_back (*i); + (*i)->GoingAway.connect (mem_fun (*this, &AudioRegion::source_deleted)); + + boost::shared_ptr afs = boost::dynamic_pointer_cast ((*i)); + if (afs) { + afs->HeaderPositionOffsetChanged.connect (mem_fun (*this, &AudioRegion::source_offset_changed)); + } + } + + _scale_amplitude = other->_scale_amplitude; + + _fade_in_disabled = 0; + _fade_out_disabled = 0; + listen_to_my_curves (); listen_to_my_sources (); } @@ -324,6 +356,9 @@ AudioRegion::~AudioRegion () for (SourceList::const_iterator i = sources.begin(); i != sources.end(); ++i) { (*i)->remove_playlist (pl); } + for (SourceList::const_iterator i = master_sources.begin(); i != master_sources.end(); ++i) { + (*i)->remove_playlist (pl); + } } notify_callbacks (); @@ -385,6 +420,7 @@ AudioRegion::verify_start_and_length (nframes_t new_start, nframes_t& new_length return true; } + bool AudioRegion::verify_start (nframes_t pos) { @@ -455,39 +491,51 @@ AudioRegion::read_peaks (PeakData *buf, nframes_t npeaks, nframes_t offset, nfra } nframes64_t -AudioRegion::read (Sample* buf, nframes64_t position, nframes64_t cnt, int channel) const +AudioRegion::read (Sample* buf, nframes64_t timeline_position, nframes64_t cnt, int channel) const { /* raw read, no fades, no gain, nada */ - return _read_at (sources, buf, 0, 0, _position + position, cnt, channel, 0, 0, true); + return _read_at (sources, _length, buf, 0, 0, _position + timeline_position, cnt, channel, 0, 0, ReadOps (0)); +} + +nframes64_t +AudioRegion::read_with_ops (Sample* buf, nframes64_t file_position, nframes64_t cnt, int channel, ReadOps rops) const +{ + return _read_at (sources, _length, buf, 0, 0, file_position, cnt, channel, 0, 0, rops); } nframes_t -AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, nframes_t position, +AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, nframes_t file_position, nframes_t cnt, uint32_t chan_n, nframes_t read_frames, nframes_t skip_frames) const { /* regular diskstream/butler read complete with fades etc */ - return _read_at (sources, buf, mixdown_buffer, gain_buffer, position, cnt, chan_n, read_frames, skip_frames, false); + return _read_at (sources, _length, buf, mixdown_buffer, gain_buffer, file_position, cnt, + chan_n, read_frames, skip_frames, ReadOps (~0)); } nframes_t AudioRegion::master_read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, nframes_t position, nframes_t cnt, uint32_t chan_n) const { - return _read_at (master_sources, buf, mixdown_buffer, gain_buffer, position, cnt, chan_n, 0, 0); + /* do not read gain/scaling/fades and do not count this disk i/o in statistics */ + + return _read_at (master_sources, master_sources.front()->length(), buf, mixdown_buffer, + gain_buffer, position, cnt, chan_n, 0, 0, ReadOps (0)); } nframes_t -AudioRegion::_read_at (const SourceList& srcs, Sample *buf, Sample *mixdown_buffer, float *gain_buffer, +AudioRegion::_read_at (const SourceList& srcs, nframes_t limit, + Sample *buf, Sample *mixdown_buffer, float *gain_buffer, nframes_t position, nframes_t cnt, uint32_t chan_n, nframes_t read_frames, nframes_t skip_frames, - bool raw) const + ReadOps rops) const { nframes_t internal_offset; nframes_t buf_offset; nframes_t to_read; + bool raw = (rops == ReadOpsNone); if (muted() && !raw) { return 0; /* read nothing */ @@ -504,11 +552,11 @@ AudioRegion::_read_at (const SourceList& srcs, Sample *buf, Sample *mixdown_buff buf_offset = 0; } - if (internal_offset >= _length) { + if (internal_offset >= limit) { return 0; /* read nothing */ } - if ((to_read = min (cnt, _length - internal_offset)) == 0) { + if ((to_read = min (cnt, limit - internal_offset)) == 0) { return 0; /* read nothing */ } @@ -519,18 +567,17 @@ AudioRegion::_read_at (const SourceList& srcs, Sample *buf, Sample *mixdown_buff mixdown_buffer += buf_offset; } - if (!raw) { + if (rops & ReadOpsCount) { _read_data_count = 0; } if (chan_n < n_channels()) { if (srcs[chan_n]->read (mixdown_buffer, _start + internal_offset, to_read) != to_read) { - return 0; /* "read nothing" */ } - if (!raw) { + if (rops & ReadOpsCount) { _read_data_count += srcs[chan_n]->read_data_count(); } @@ -541,19 +588,13 @@ AudioRegion::_read_at (const SourceList& srcs, Sample *buf, Sample *mixdown_buff */ memset (mixdown_buffer, 0, sizeof (Sample) * cnt); - - /* no fades required */ - - if (!raw) { - goto merge; - } } - /* fade in */ - - if (!raw) { + if (rops & ReadOpsFades) { - if (_flags & FadeIn) { + /* fade in */ + + if ((_flags & FadeIn) && Config->get_use_region_fades()) { nframes_t fade_in_length = (nframes_t) _fade_in.back()->when; @@ -561,13 +602,13 @@ AudioRegion::_read_at (const SourceList& srcs, Sample *buf, Sample *mixdown_buff if (internal_offset < fade_in_length) { - nframes_t limit; + nframes_t fi_limit; - limit = min (to_read, fade_in_length - internal_offset); + fi_limit = min (to_read, fade_in_length - internal_offset); - _fade_in.get_vector (internal_offset, internal_offset+limit, gain_buffer, limit); + _fade_in.get_vector (internal_offset, internal_offset+fi_limit, gain_buffer, fi_limit); - for (nframes_t n = 0; n < limit; ++n) { + for (nframes_t n = 0; n < fi_limit; ++n) { mixdown_buffer[n] *= gain_buffer[n]; } } @@ -575,79 +616,77 @@ AudioRegion::_read_at (const SourceList& srcs, Sample *buf, Sample *mixdown_buff /* fade out */ - if (_flags & FadeOut) { - + if ((_flags & FadeOut) && Config->get_use_region_fades()) { + /* see if some part of this read is within the fade out */ /* ................. >| REGION - _length + limit { } FADE fade_out_length ^ - _length - fade_out_length + limit - fade_out_length |--------------| ^internal_offset ^internal_offset + to_read we need the intersection of [internal_offset,internal_offset+to_read] with - [_length - fade_out_length, _length] + [limit - fade_out_length, limit] */ nframes_t fade_out_length = (nframes_t) _fade_out.back()->when; - nframes_t fade_interval_start = max(internal_offset, _length-fade_out_length); - nframes_t fade_interval_end = min(internal_offset + to_read, _length); - + nframes_t fade_interval_start = max(internal_offset, limit-fade_out_length); + nframes_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 limit = fade_interval_end - fade_interval_start; - nframes_t curve_offset = fade_interval_start - (_length-fade_out_length); + + 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; - _fade_out.get_vector (curve_offset,curve_offset+limit, gain_buffer, limit); + _fade_out.get_vector (curve_offset,curve_offset+fo_limit, gain_buffer, fo_limit); - for (nframes_t n = 0, m = fade_offset; n < limit; ++n, ++m) { + for (nframes_t n = 0, m = fade_offset; n < fo_limit; ++n, ++m) { mixdown_buffer[m] *= gain_buffer[n]; } } } + } - /* Regular gain curves */ + /* Regular gain curves and scaling */ + + if ((rops & ReadOpsOwnAutomation) && envelope_active()) { + _envelope.get_vector (internal_offset, internal_offset + to_read, gain_buffer, to_read); - if (envelope_active()) { - _envelope.get_vector (internal_offset, internal_offset + to_read, gain_buffer, to_read); - - if (_scale_amplitude != 1.0f) { - for (nframes_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) { - mixdown_buffer[n] *= gain_buffer[n]; - } + if ((rops & ReadOpsOwnScaling) && _scale_amplitude != 1.0f) { + for (nframes_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) { + mixdown_buffer[n] *= gain_buffer[n]; } - } else if (_scale_amplitude != 1.0f) { - Session::apply_gain_to_buffer (mixdown_buffer, to_read, _scale_amplitude); } + } else if ((rops & ReadOpsOwnScaling) && _scale_amplitude != 1.0f) { + Session::apply_gain_to_buffer (mixdown_buffer, to_read, _scale_amplitude); + } - merge: + if (!opaque()) { - if (!opaque()) { - - /* gack. the things we do for users. - */ - - buf += buf_offset; + /* gack. the things we do for users. + */ + + buf += buf_offset; - for (nframes_t n = 0; n < to_read; ++n) { - buf[n] += mixdown_buffer[n]; - } - } - } + for (nframes_t n = 0; n < to_read; ++n) { + buf[n] += mixdown_buffer[n]; + } + } return to_read; } @@ -808,7 +847,7 @@ AudioRegion::set_live_state (const XMLNode& node, Change& what_changed, bool sen } if ((prop = child->property ("active")) != 0) { - if (prop->value() == "yes") { + if (string_is_affirmative (prop->value())) { set_fade_in_active (true); } else { set_fade_in_active (true); @@ -829,7 +868,7 @@ AudioRegion::set_live_state (const XMLNode& node, Change& what_changed, bool sen } if ((prop = child->property ("active")) != 0) { - if (prop->value() == "yes") { + if (string_is_affirmative (prop->value())) { set_fade_out_active (true); } else { set_fade_out_active (false); @@ -1200,7 +1239,7 @@ AudioRegion::master_source_names () } void -AudioRegion::set_master_sources (SourceList& srcs) +AudioRegion::set_master_sources (const SourceList& srcs) { master_sources = srcs; } @@ -1477,6 +1516,15 @@ AudioRegion::speed_mismatch (float sr) const void AudioRegion::source_offset_changed () { + /* XXX this fixes a crash that should not occur. It does occur + becauses regions are not being deleted when a session + is unloaded. That bug must be fixed. + */ + + if (sources.empty()) { + return; + } + boost::shared_ptr afs = boost::dynamic_pointer_cast(sources.front()); if (afs && afs->destructive()) { @@ -1504,16 +1552,26 @@ AudioRegion::set_playlist (boost::weak_ptr wpl) (*i)->remove_playlist (_playlist); (*i)->add_playlist (pl); } + for (SourceList::const_iterator i = master_sources.begin(); i != master_sources.end(); ++i) { + (*i)->remove_playlist (_playlist); + (*i)->add_playlist (pl); + } } else { for (SourceList::const_iterator i = sources.begin(); i != sources.end(); ++i) { (*i)->add_playlist (pl); } + for (SourceList::const_iterator i = master_sources.begin(); i != master_sources.end(); ++i) { + (*i)->add_playlist (pl); + } } } else { if (old_playlist) { for (SourceList::const_iterator i = sources.begin(); i != sources.end(); ++i) { (*i)->remove_playlist (old_playlist); } + for (SourceList::const_iterator i = master_sources.begin(); i != master_sources.end(); ++i) { + (*i)->remove_playlist (old_playlist); + } } } } @@ -1576,7 +1634,24 @@ AudioRegion::get_transients (AnalysisFeatureList& results, bool force_new) return 0; } - cerr << "startup analysis of " << _name << endl; + /* no existing/complete transient info */ + + static bool analyse_dialog_shown = false; + 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\ +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\ +")); + analyse_dialog_shown = true; //only show this dialog once + } + } TransientDetector t (pl->session().frame_rate()); bool existing_results = !results.empty(); @@ -1590,14 +1665,10 @@ AudioRegion::get_transients (AnalysisFeatureList& results, bool force_new) t.reset (); - cerr << "working on channel " << i << endl; - if (t.run ("", this, i, these_results)) { return -1; } - cerr << "done\n"; - /* translate all transients to give absolute position */ for (AnalysisFeatureList::iterator i = these_results.begin(); i != these_results.end(); ++i) {