diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2009-06-09 20:21:19 +0000 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2009-06-09 20:21:19 +0000 |
commit | e6eb059576eefd9a26c177627ae7dd3ba2feb727 (patch) | |
tree | 536ce6ee456f2306bb0346a51ede0a4aa64a8e63 /libs/ardour/amp.cc | |
parent | 9bd274bfdee62c9cc0e5752d2a72027d2c732cd0 (diff) |
the big Route structure refactor. !!!! THIS WILL ***NOT LOAD*** PRIOR 3.0 or 2.X SESSIONS !!!! BREAKAGE IS EXPECTED !!!! IF YOU HAVE AND NEED A WORKING 3.0 DO **NOT** UPDATE. !!!! otherwise, update and enjoy the steadily emerging joys of this major reworking of ardour internals
git-svn-id: svn://localhost/ardour2/branches/3.0@5137 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs/ardour/amp.cc')
-rw-r--r-- | libs/ardour/amp.cc | 211 |
1 files changed, 158 insertions, 53 deletions
diff --git a/libs/ardour/amp.cc b/libs/ardour/amp.cc index 591fcd8569..755dc8b821 100644 --- a/libs/ardour/amp.cc +++ b/libs/ardour/amp.cc @@ -19,24 +19,31 @@ #include <cstring> #include <cmath> #include <algorithm> + +#include "evoral/Curve.hpp" + #include "ardour/amp.h" #include "ardour/audio_buffer.h" #include "ardour/buffer_set.h" #include "ardour/configuration.h" #include "ardour/io.h" +#include "ardour/mute_master.h" #include "ardour/session.h" -namespace ARDOUR { +#include "i18n.h" + +using namespace ARDOUR; -Amp::Amp(Session& s, IO& io) +Amp::Amp(Session& s, boost::shared_ptr<MuteMaster> mm) : Processor(s, "Amp") - , _io(io) - , _mute(false) , _apply_gain(true) , _apply_gain_automation(false) , _current_gain(1.0) - , _desired_gain(1.0) + , _mute_master (mm) { + boost::shared_ptr<AutomationList> gl(new AutomationList(Evoral::Parameter(GainAutomation))); + _gain_control = boost::shared_ptr<GainControl>( new GainControl(X_("gaincontrol"), s, this, Evoral::Parameter(GainAutomation), gl )); + add_control(_gain_control); } bool @@ -59,64 +66,92 @@ Amp::configure_io (ChanCount in, ChanCount out) void Amp::run_in_place (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes) { - gain_t* gab = _session.gain_automation_buffer(); + gain_t mute_gain; - if (_mute && !bufs.is_silent()) { - Amp::apply_gain (bufs, nframes, _current_mute_gain, _desired_mute_gain, false); - if (_desired_mute_gain == 0.0f) { - bufs.is_silent(true); - } + if (_mute_master) { + mute_gain = _mute_master->mute_gain_at (MuteMaster::PreFader); + } else { + mute_gain = 1.0; } if (_apply_gain) { if (_apply_gain_automation) { - if (_io.phase_invert()) { + gain_t* gab = _session.gain_automation_buffer (); + + if (mute_gain == 0.0) { + + /* absolute mute */ + + if (_current_gain == 0.0) { + + /* already silent */ + + for (BufferSet::audio_iterator i = bufs.audio_begin(); i != bufs.audio_end(); ++i) { + i->clear (); + } + } else { + + /* cut to silence */ + + Amp::apply_gain (bufs, nframes, _current_gain, 0.0); + _current_gain = 0.0; + } + + + } else if (mute_gain != 1.0) { + + /* mute dimming */ + 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]; + sp[nx] *= gab[nx] * mute_gain; } } + + _current_gain = gab[nframes-1] * mute_gain; + } else { + + /* no mute */ + 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]; } } + + _current_gain = gab[nframes-1]; } + } else { /* manual (scalar) gain */ + + gain_t dg = _gain_control->user_float() * mute_gain; - if (_current_gain != _desired_gain) { + if (_current_gain != dg) { - Amp::apply_gain (bufs, nframes, _current_gain, _desired_gain, _io.phase_invert()); - _current_gain = _desired_gain; + Amp::apply_gain (bufs, nframes, _current_gain, dg); + _current_gain = dg; - } else if (_current_gain != 0.0f && (_io.phase_invert() || _current_gain != 1.0f)) { + } else if ((_current_gain != 0.0f) && (_current_gain != 1.0f)) { - /* 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 has not changed, but its non-unity, so apply it unless + its zero. */ - gain_t this_gain; - - if (_io.phase_invert()) { - this_gain = -_current_gain; - } else { - this_gain = _current_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); + apply_gain_to_buffer(sp, nframes, _current_gain); } } else if (_current_gain == 0.0f) { + + /* silence! */ + for (BufferSet::audio_iterator i = bufs.audio_begin(); i != bufs.audio_end(); ++i) { i->clear(); } @@ -125,30 +160,19 @@ Amp::run_in_place (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, } } -/** Apply a declicked gain to the audio buffers of @a bufs */ void -Amp::apply_gain (BufferSet& bufs, nframes_t nframes, - gain_t initial, gain_t target, bool invert_polarity) +Amp::apply_gain (BufferSet& bufs, nframes_t nframes, gain_t initial, gain_t target) { - if (nframes == 0) { - return; - } - - if (bufs.count().n_audio() == 0) { + /** Apply a (potentially) declicked gain to the audio buffers of @a bufs + */ + + if (nframes == 0 || bufs.count().n_audio() == 0) { return; } // if we don't need to declick, defer to apply_simple_gain if (initial == target) { - if (target == 0.0) { - for (BufferSet::audio_iterator i = bufs.audio_begin(); i != bufs.audio_end(); ++i) { - memset (i->data(), 0, sizeof (Sample) * nframes); - } - } else if (target != 1.0) { - for (BufferSet::audio_iterator i = bufs.audio_begin(); i != bufs.audio_end(); ++i) { - apply_gain_to_buffer (i->data(), nframes, target); - } - } + apply_simple_gain (bufs, nframes, target); return; } @@ -156,7 +180,7 @@ Amp::apply_gain (BufferSet& bufs, nframes_t nframes, gain_t delta; double fractional_shift = -1.0/declick; double fractional_pos; - gain_t polscale = invert_polarity ? -1.0f : 1.0f; + gain_t polscale = 1.0f; if (target < initial) { /* fade out: remove more and more of delta from initial */ @@ -180,10 +204,6 @@ Amp::apply_gain (BufferSet& bufs, nframes_t nframes, if (declick != nframes) { - if (invert_polarity) { - target = -target; - } - if (target == 0.0) { memset (&buffer[declick], 0, sizeof (Sample) * (nframes - declick)); } else if (target != 1.0) { @@ -196,6 +216,62 @@ Amp::apply_gain (BufferSet& bufs, nframes_t nframes, void Amp::apply_simple_gain (BufferSet& bufs, nframes_t nframes, gain_t target) { + if (target == 0.0) { + for (BufferSet::audio_iterator i = bufs.audio_begin(); i != bufs.audio_end(); ++i) { + memset (i->data(), 0, sizeof (Sample) * nframes); + } + } else if (target != 1.0) { + for (BufferSet::audio_iterator i = bufs.audio_begin(); i != bufs.audio_end(); ++i) { + apply_gain_to_buffer (i->data(), nframes, target); + } + } +} + +void +Amp::inc_gain (gain_t factor, void *src) +{ + float desired_gain = _gain_control->user_float(); + if (desired_gain == 0.0f) { + set_gain (0.000001f + (0.000001f * factor), src); + } else { + set_gain (desired_gain + (desired_gain * factor), src); + } +} + +void +Amp::set_gain (gain_t val, void *src) +{ + // max gain at about +6dB (10.0 ^ ( 6 dB * 0.05)) + if (val > 1.99526231f) { + val = 1.99526231f; + } + + //cerr << "set desired gain to " << val << " when curgain = " << _gain_control->get_value () << endl; + + if (src != _gain_control.get()) { + _gain_control->set_value(val); + // bit twisty, this will come back and call us again + // (this keeps control in sync with reality) + return; + } + + { + // Glib::Mutex::Lock dm (declick_lock); + _gain_control->set_float(val, false); + } + + if (_session.transport_stopped()) { + // _gain = val; + } + + /* + if (_session.transport_stopped() && src != 0 && src != this && _gain_control->automation_write()) { + _gain_control->list()->add (_session.transport_frame(), val); + + } + */ + + _session.set_dirty(); } XMLNode& @@ -206,4 +282,33 @@ Amp::state (bool full_state) return node; } -} // namespace ARDOUR +void +Amp::GainControl::set_value (float val) +{ + // max gain at about +6dB (10.0 ^ ( 6 dB * 0.05)) + if (val > 1.99526231f) + val = 1.99526231f; + + _amp->set_gain (val, this); + + AutomationControl::set_value(val); +} + +float +Amp::GainControl::get_value (void) const +{ + return AutomationControl::get_value(); +} + +void +Amp::setup_gain_automation (sframes_t start_frame, sframes_t end_frame, nframes_t nframes) +{ + Glib::Mutex::Lock am (data().control_lock(), Glib::TRY_LOCK); + + if (am.locked() && _session.transport_rolling() && _gain_control->automation_playback()) { + _apply_gain_automation = _gain_control->list()->curve().rt_safe_get_vector ( + start_frame, end_frame, _session.gain_automation_buffer(), nframes); + } else { + _apply_gain_automation = false; + } +} |