diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2008-09-28 20:40:53 +0000 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2008-09-28 20:40:53 +0000 |
commit | 43b17b5df1927a6c08a382c420c49d7ac1014852 (patch) | |
tree | 090359c64ff468e1a7a8ffe19093b04ce33b4c29 /libs/ardour | |
parent | e11b3f90c2d02735a071d526d67cfd0de90cbac3 (diff) |
changes from torben for processor/plugin count determination and other fixes; rework cycle_start() mess, first pass
git-svn-id: svn://localhost/ardour2/branches/3.0@3821 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs/ardour')
-rw-r--r-- | libs/ardour/ardour/buffer.h | 2 | ||||
-rw-r--r-- | libs/ardour/ardour/io.h | 2 | ||||
-rw-r--r-- | libs/ardour/audioengine.cc | 5 | ||||
-rw-r--r-- | libs/ardour/audioregion.cc | 2 | ||||
-rw-r--r-- | libs/ardour/io.cc | 9 | ||||
-rw-r--r-- | libs/ardour/route.cc | 323 | ||||
-rw-r--r-- | libs/ardour/session_process.cc | 4 |
7 files changed, 328 insertions, 19 deletions
diff --git a/libs/ardour/ardour/buffer.h b/libs/ardour/ardour/buffer.h index 72df6c7fd6..e03489568c 100644 --- a/libs/ardour/ardour/buffer.h +++ b/libs/ardour/ardour/buffer.h @@ -74,7 +74,7 @@ public: /** Clear the entire buffer */ virtual void clear() { silence(_capacity, 0); } - + virtual void read_from(const Buffer& src, nframes_t offset, nframes_t len) = 0; protected: diff --git a/libs/ardour/ardour/io.h b/libs/ardour/ardour/io.h index 08c8a1b211..521efbafb4 100644 --- a/libs/ardour/ardour/io.h +++ b/libs/ardour/ardour/io.h @@ -287,6 +287,8 @@ class IO : public SessionObject, public AutomatableControls, public Latent DataType _default_type; bool _public_ports; + virtual void prepare_inputs (nframes_t nframes, nframes_t offset); + virtual void set_deferred_state() {} void reset_panner (); diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc index 956b956020..8629a5c0df 100644 --- a/libs/ardour/audioengine.cc +++ b/libs/ardour/audioengine.cc @@ -342,11 +342,6 @@ AudioEngine::process_callback (nframes_t nframes) boost::shared_ptr<Ports> p = ports.reader(); - // Prepare ports (ie read data if necessary) - for (Ports::iterator i = p->begin(); i != p->end(); ++i) { - (*i)->cycle_start (nframes, 0); - } - if (_freewheeling) { /* emit the Freewheel signal and stop freewheeling in the event of trouble */ if (Freewheel (nframes)) { diff --git a/libs/ardour/audioregion.cc b/libs/ardour/audioregion.cc index 477c479de8..f74fb83735 100644 --- a/libs/ardour/audioregion.cc +++ b/libs/ardour/audioregion.cc @@ -473,7 +473,7 @@ AudioRegion::_read_at (const SourceList& srcs, nframes_t limit, } } } else if (_scale_amplitude != 1.0f) { - ARDOUR::apply_gain_to_buffer (mixdown_buffer, to_read, _scale_amplitude); + apply_gain_to_buffer (mixdown_buffer, to_read, _scale_amplitude); } merge: diff --git a/libs/ardour/io.cc b/libs/ardour/io.cc index 7db2493c76..c51920cd0d 100644 --- a/libs/ardour/io.cc +++ b/libs/ardour/io.cc @@ -2744,3 +2744,12 @@ IO::UserBundleInfo::UserBundleInfo (IO* io, boost::shared_ptr<UserBundle> b) ); } +void +IO::prepare_inputs (nframes_t nframes, nframes_t offset) +{ + /* io_lock, not taken: function must be called from Session::process() calltree */ + + for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) { + (*i).cycle_start (nframes, offset); + } +} diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index 7cf6c4ef36..a90a730ea6 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -722,6 +722,312 @@ Route::process_output_buffers (BufferSet& bufs, } } +#ifdef NEW_POB +/** Process this route for one (sub) cycle (process thread) + * + * @param bufs Scratch buffers to use for the signal path + * @param start_frame Initial transport frame + * @param end_frame Final transport frame + * @param nframes Number of frames to output (to ports) + * @param offset Output offset (of port buffers, for split cycles) + * + * Note that (end_frame - start_frame) may not be equal to nframes when the + * transport speed isn't 1.0 (eg varispeed). + */ +void +Route::process_output_buffers (BufferSet& bufs, + nframes_t start_frame, nframes_t end_frame, + nframes_t nframes, nframes_t offset, bool with_processors, int declick, + bool meter) +{ + // This is definitely very audio-only for now + assert(_default_type == DataType::AUDIO); + + ProcessorList::iterator i; + bool post_fader_work = false; + bool mute_declick_applied = false; + gain_t dmg, dsg, dg; + IO *co; + bool mute_audible; + bool solo_audible; + bool no_monitor; + gain_t* gab = _session.gain_automation_buffer(); + + switch (Config->get_monitoring_model()) { + case HardwareMonitoring: + case ExternalMonitoring: + no_monitor = true; + break; + default: + no_monitor = false; + } + + declick = _pending_declick; + + { + Glib::Mutex::Lock cm (_control_outs_lock, Glib::TRY_LOCK); + + if (cm.locked()) { + co = _control_outs; + } else { + co = 0; + } + } + + { + Glib::Mutex::Lock dm (declick_lock, Glib::TRY_LOCK); + + if (dm.locked()) { + dmg = desired_mute_gain; + dsg = desired_solo_gain; + dg = _desired_gain; + } else { + dmg = mute_gain; + dsg = solo_gain; + dg = _gain; + } + } + + /* ---------------------------------------------------------------------------------------------------- + GLOBAL DECLICK (for transport changes etc.) + input metering & monitoring (control outs) + denormal control + pre-fader redirects + pre-fader metering & monitoring (control outs) + gain stage + post-fader redirects + global mute + main output + post-fader metering & monitoring (control outs) + */ + + { + Glib::RWLock::ReaderLock rm (_processor_lock, Glib::TRY_LOCK); + for (i = processors.begin(); i != processors.end(); ++i) { + (*i)->run_in_place (bufs, start_frame, end_frame, nframes, offset); + } + } + + /* ---------------------------------------------------------------------------------------------------- + INPUT METERING & MONITORING + -------------------------------------------------------------------------------------------------- */ + + if (meter && (_meter_point == MeterInput)) { + _meter->run_in_place(bufs, start_frame, end_frame, nframes, offset); + } + + if (!_soloed && _mute_affects_pre_fader && (mute_gain != dmg)) { + Amp::run_in_place (bufs, nframes, mute_gain, dmg, false); + mute_gain = dmg; + mute_declick_applied = true; + } + + /* ---------------------------------------------------------------------------------------------------- + PRE-FADER REDIRECTS + -------------------------------------------------------------------------------------------------- */ + + // This really should already be true... + bufs.set_count(pre_fader_streams()); + + + if ((_meter_point == MeterPreFader) && co) { + + solo_audible = dsg > 0; + mute_audible = dmg > 0 || !_mute_affects_pre_fader; + + if ( // muted by solo of another track + + !solo_audible || + + // muted by mute of this track + + !mute_audible || + + // rec-enabled but not s/w monitoring + + (no_monitor && record_enabled() && (!Config->get_auto_input() || _session.actively_recording())) + + ) { + + co->silence (nframes, offset); + + } else { + + co->deliver_output (bufs, start_frame, end_frame, nframes, offset); + } + } + + /* ---------------------------------------------------------------------------------------------------- + GAIN STAGE + -------------------------------------------------------------------------------------------------- */ + + /* if not recording or recording and requiring any monitor signal, then apply gain */ + + if ( // not recording + + !(record_enabled() && _session.actively_recording()) || + + // OR recording + + // AND software monitoring required + + Config->get_monitoring_model() == SoftwareMonitoring) { + + if (apply_gain_automation) { + + if (_phase_invert) { + for (BufferSet::audio_iterator i = bufs.audio_begin(); i != bufs.audio_end(); ++i) { + Sample* const sp = i->data(); + + for (nframes_t nx = 0; nx < nframes; ++nx) { + sp[nx] *= -gab[nx]; + } + } + } else { + for (BufferSet::audio_iterator i = bufs.audio_begin(); i != bufs.audio_end(); ++i) { + Sample* const sp = i->data(); + + for (nframes_t nx = 0; nx < nframes; ++nx) { + sp[nx] *= gab[nx]; + } + } + } + + if (apply_gain_automation && _session.transport_rolling() && nframes > 0) { + _effective_gain = gab[nframes-1]; + } + + } else { + + /* manual (scalar) gain */ + + if (_gain != dg) { + + Amp::run_in_place (bufs, nframes, _gain, dg, _phase_invert); + _gain = dg; + + } else if (_gain != 0 && (_phase_invert || _gain != 1.0)) { + + /* no need to interpolate current gain value, + but its non-unity, so apply it. if the gain + is zero, do nothing because we'll ship silence + below. + */ + + gain_t this_gain; + + if (_phase_invert) { + this_gain = -_gain; + } else { + this_gain = _gain; + } + + for (BufferSet::audio_iterator i = bufs.audio_begin(); i != bufs.audio_end(); ++i) { + Sample* const sp = i->data(); + apply_gain_to_buffer(sp,nframes,this_gain); + } + + } else if (_gain == 0) { + for (BufferSet::audio_iterator i = bufs.audio_begin(); i != bufs.audio_end(); ++i) { + i->clear(); + } + } + } + + } else { + + /* actively recording, no monitoring required; leave buffers as-is to save CPU cycles */ + + } + + + /* ---------------------------------------------------------------------------------------------------- + CONTROL OUTPUT STAGE + -------------------------------------------------------------------------------------------------- */ + + if ((_meter_point == MeterPostFader) && co) { + + solo_audible = solo_gain > 0; + mute_audible = dmg > 0 || !_mute_affects_control_outs; + + if ( // silent anyway + + (_gain == 0 && !apply_gain_automation) || + + // muted by solo of another track + + !solo_audible || + + // muted by mute of this track + + !mute_audible || + + // recording but not s/w monitoring + + (no_monitor && record_enabled() && (!Config->get_auto_input() || _session.actively_recording())) + + ) { + + co->silence (nframes, offset); + + } else { + + co->deliver_output (bufs, start_frame, end_frame, nframes, offset); + } + } + + /* ---------------------------------------------------------------------------------------------------- + MAIN OUTPUT STAGE + -------------------------------------------------------------------------------------------------- */ + + solo_audible = dsg > 0; + mute_audible = dmg > 0 || !_mute_affects_main_outs; + + if (n_outputs().get(_default_type) == 0) { + + /* relax */ + + } else if (no_monitor && record_enabled() && (!Config->get_auto_input() || _session.actively_recording())) { + + IO::silence (nframes, offset); + + } else { + + if ( // silent anyway + + (_gain == 0 && !apply_gain_automation) || + + // muted by solo of another track, but not using control outs for solo + + (!solo_audible && (Config->get_solo_model() != SoloBus)) || + + // muted by mute of this track + + !mute_audible + + ) { + + /* don't use Route::silence() here, because that causes + all outputs (sends, port processors, etc. to be silent). + */ + + if (_meter_point == MeterPostFader) { + peak_meter().reset(); + } + + IO::silence (nframes, offset); + + } else { + + deliver_output(bufs, start_frame, end_frame, nframes, offset); + + } + + } +} + +#endif /* NEW_POB */ + ChanCount Route::n_process_buffers () { @@ -829,6 +1135,8 @@ Route::add_processor (boost::shared_ptr<Processor> processor, ProcessorStreams* _processors.push_back (processor); + // Set up processor list channels. This will set processor->[input|output]_streams(), + // configure redirect ports properly, etc. if (_reset_processor_counts (err)) { _processors.pop_back (); _reset_processor_counts (0); // it worked before we tried to add it ... @@ -844,16 +1152,6 @@ Route::add_processor (boost::shared_ptr<Processor> processor, ProcessorStreams* } - _processors.push_back (processor); - - // Set up processor list channels. This will set processor->[input|output]_streams(), - // configure redirect ports properly, etc. - if (_reset_processor_counts (err)) { - _processors.pop_back (); - _reset_processor_counts (0); // it worked before we tried to add it ... - return -1; - } - // Ensure peak vector sizes before the plugin is activated ChanCount potential_max_streams; @@ -1404,14 +1702,14 @@ Route::check_some_processor_counts (list<ProcessorCount>& iclist, ChanCount requ err->index = index; err->count = required_inputs; } - return false; + return true; } (*i).in = required_inputs; required_inputs = (*i).out; } - return true; + return false; } int @@ -2774,3 +3072,4 @@ Route::set_pending_declick (int declick) } } + diff --git a/libs/ardour/session_process.cc b/libs/ardour/session_process.cc index abe802548a..e4025ca6de 100644 --- a/libs/ardour/session_process.cc +++ b/libs/ardour/session_process.cc @@ -103,6 +103,8 @@ Session::no_roll (nframes_t nframes, nframes_t offset) for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { + (*i)->prepare_inputs (nframes, offset); + if ((*i)->is_hidden()) { continue; } @@ -142,6 +144,8 @@ Session::process_routes (nframes_t nframes, nframes_t offset) int ret; + (*i)->prepare_inputs (nframes, offset); + if ((*i)->is_hidden()) { continue; } |