summaryrefslogtreecommitdiff
path: root/libs/ardour/amp.cc
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2009-06-09 20:21:19 +0000
committerPaul Davis <paul@linuxaudiosystems.com>2009-06-09 20:21:19 +0000
commite6eb059576eefd9a26c177627ae7dd3ba2feb727 (patch)
tree536ce6ee456f2306bb0346a51ede0a4aa64a8e63 /libs/ardour/amp.cc
parent9bd274bfdee62c9cc0e5752d2a72027d2c732cd0 (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.cc211
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;
+ }
+}