prepare trim automation
authorRobin Gareus <robin@gareus.org>
Sat, 25 Apr 2015 19:24:58 +0000 (21:24 +0200)
committerRobin Gareus <robin@gareus.org>
Sat, 25 Apr 2015 19:24:58 +0000 (21:24 +0200)
12 files changed:
libs/ardour/amp.cc
libs/ardour/ardour/process_thread.h
libs/ardour/ardour/route.h
libs/ardour/ardour/session.h
libs/ardour/ardour/thread_buffers.h
libs/ardour/automatable.cc
libs/ardour/automation_list.cc
libs/ardour/event_type_map.cc
libs/ardour/process_thread.cc
libs/ardour/route.cc
libs/ardour/session.cc
libs/ardour/thread_buffers.cc

index f2381cdefb5c631f15fb48316e6a537810b65fbc..9430585b6101e9ca058d439e61efa5c016b67bb9 100644 (file)
@@ -46,7 +46,7 @@ Amp::Amp (Session& s, std::string type)
 {
        Evoral::Parameter p (_type == "trim" ? TrimAutomation : GainAutomation);
        boost::shared_ptr<AutomationList> gl (new AutomationList (p));
-       _gain_control = boost::shared_ptr<GainControl> (new GainControl (X_("gaincontrol"), s, this, p, gl));
+       _gain_control = boost::shared_ptr<GainControl> (new GainControl ((_type == "trim") ? X_("trimcontrol") : X_("gaincontrol"), s, this, p, gl));
        _gain_control->set_flags (Controllable::GainLike);
 
        add_control(_gain_control);
index 779fdaea2d50384f8660745b87bf1ef5170cbff8..67bd07dbfe6dced3045cccc968c9db7cecde6588 100644 (file)
@@ -50,6 +50,7 @@ public:
        static BufferSet& get_route_buffers (ChanCount count = ChanCount::ZERO, bool silence = false);
        static BufferSet& get_mix_buffers (ChanCount count = ChanCount::ZERO);
        static gain_t* gain_automation_buffer ();
+       static gain_t* trim_automation_buffer ();
        static gain_t* send_gain_automation_buffer ();
        static pan_t** pan_automation_buffer ();
 
index 99d3421491fb7b9ac5f1b7a78233a5c52974e927..5a459e7ce5acbe6b240b8df7836e2e212bb38ab1 100644 (file)
@@ -508,6 +508,7 @@ class LIBARDOUR_API Route : public SessionObject, public Automatable, public Rou
        bool           _active;
        framecnt_t     _signal_latency;
        framecnt_t     _signal_latency_at_amp_position;
+       framecnt_t     _signal_latency_at_trim_position;
        framecnt_t     _initial_delay;
        framecnt_t     _roll_delay;
 
index 30afd00fdb5489f16a896d7d70279c8e7d7f59e2..3da040af0d931d68a2049aac8a516867f1df557d 100644 (file)
@@ -817,6 +817,7 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
        /* buffers for gain and pan */
 
        gain_t* gain_automation_buffer () const;
+       gain_t* trim_automation_buffer () const;
        gain_t* send_gain_automation_buffer () const;
        pan_t** pan_automation_buffer () const;
 
index bf686fd57ee1e0053f21eb29314138335a5c90a8..5ea352f2efd7163ca14915c9e7b2ae172c87cd70 100644 (file)
@@ -42,6 +42,7 @@ public:
        BufferSet* route_buffers;
        BufferSet* mix_buffers;
        gain_t*    gain_automation_buffer;
+       gain_t*    trim_automation_buffer;
        gain_t*    send_gain_automation_buffer;
        pan_t**    pan_automation_buffer;
        uint32_t   npan_buffers;
index 310592ae4babfccf982872186eb754eb3692b025..9a37b1d590cd190304e16a89d20fa2fdc8ff7a51 100644 (file)
@@ -163,6 +163,8 @@ Automatable::describe_parameter (Evoral::Parameter param)
 
        if (param == Evoral::Parameter(GainAutomation)) {
                return _("Fader");
+       } else if (param.type() == TrimAutomation) {
+               return _("Trim");
        } else if (param.type() == MuteAutomation) {
                return _("Mute");
        } else if (param.type() == MidiCCAutomation) {
@@ -441,6 +443,13 @@ Automatable::control_factory(const Evoral::Parameter& param)
                } else {
                        warning << "GainAutomation for non-Amp" << endl;
                }
+       } else if (param.type() == TrimAutomation) {
+               Amp* amp = dynamic_cast<Amp*>(this);
+               if (amp) {
+                       control = new Amp::GainControl(X_("trimcontrol"), _a_session, amp, param);
+               } else {
+                       warning << "TrimAutomation for non-Amp" << endl;
+               }
        } else if (param.type() == PanAzimuthAutomation || param.type() == PanWidthAutomation || param.type() == PanElevationAutomation) {
                Pannable* pannable = dynamic_cast<Pannable*>(this);
                if (pannable) {
index 941178a698520b622fb0fdc6620e9228cc101f90..7f7599f8ca4abc8025ec62c78f337c735386ffd6 100644 (file)
@@ -139,6 +139,7 @@ AutomationList::create_curve_if_necessary()
 {
        switch (_parameter.type()) {
        case GainAutomation:
+       case TrimAutomation:
        case PanAzimuthAutomation:
        case PanElevationAutomation:
        case PanWidthAutomation:
index cd3aeacebd9f02a87160bf80be3035afb055468a..8782162304a0d9155ee23ab37cb5c5c65bb3b102 100644 (file)
@@ -130,6 +130,8 @@ EventTypeMap::from_symbol(const string& str) const
 
        if (str == "gain") {
                p_type = GainAutomation;
+       } else if (str == "trim") {
+               p_type = TrimAutomation;
        } else if (str == "solo") {
                p_type = SoloAutomation;
        } else if (str == "mute") {
@@ -207,6 +209,8 @@ EventTypeMap::to_symbol(const Evoral::Parameter& param) const
 
        if (t == GainAutomation) {
                return "gain";
+       } else if (t == TrimAutomation) {
+                return "trim";
        } else if (t == PanAzimuthAutomation) {
                 return "pan-azimuth";
        } else if (t == PanElevationAutomation) {
index d4a3d2f3908e3b89adabcf9e8a0d7683769be01f..cf48c50c70e7c73796196a5ef619056e4d22f1d6 100644 (file)
@@ -168,6 +168,17 @@ ProcessThread::gain_automation_buffer()
         return g;
 }
 
+gain_t*
+ProcessThread::trim_automation_buffer()
+{
+        ThreadBuffers* tb = _private_thread_buffers.get();
+        assert (tb);
+
+        gain_t *g =  tb->trim_automation_buffer;
+        assert (g);
+        return g;
+}
+
 gain_t*
 ProcessThread::send_gain_automation_buffer()
 {
index 3d9785b2fbfcb97e98220fe6428a0fe8fdbeb2d3..76006ec186b53f0377501479c92c9c74a5ba2fd6 100644 (file)
@@ -82,6 +82,7 @@ Route::Route (Session& sess, string name, Flag flg, DataType default_type)
        , _active (true)
        , _signal_latency (0)
        , _signal_latency_at_amp_position (0)
+       , _signal_latency_at_trim_position (0)
        , _initial_delay (0)
        , _roll_delay (0)
        , _flags (flg)
@@ -360,7 +361,6 @@ Route::ensure_track_or_route_name(string name, Session &session)
        return newname;
 }
 
-
 void
 Route::inc_gain (gain_t fraction, void *src)
 {
@@ -474,8 +474,15 @@ Route::process_output_buffers (BufferSet& bufs,
                                start_frame + _signal_latency_at_amp_position,
                                end_frame + _signal_latency_at_amp_position,
                                nframes);
+
+               _trim->set_gain_automation_buffer (_session.trim_automation_buffer ());
+               _trim->setup_gain_automation (
+                               start_frame + _signal_latency_at_trim_position,
+                               end_frame + _signal_latency_at_trim_position,
+                               nframes);
        } else {
                _amp->apply_gain_automation (false);
+               _trim->apply_gain_automation (false);
        }
 
        /* Tell main outs what to do about monitoring.  We do this so that
@@ -610,6 +617,10 @@ Route::bounce_process (BufferSet& buffers, framepos_t start, framecnt_t nframes,
        _amp->set_gain_automation_buffer (_session.gain_automation_buffer ());
        _amp->setup_gain_automation (start - latency, start - latency + nframes, nframes);
 
+       /* trim is always at the top, for bounce no latency compensation is needed */
+       _trim->set_gain_automation_buffer (_session.trim_automation_buffer ());
+       _trim->setup_gain_automation (start, start + nframes, nframes);
+
        latency = 0;
        for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
 
@@ -1509,7 +1520,7 @@ Route::clear_processors (Placement p)
                                seen_amp = true;
                        }
 
-                       if ((*i) == _amp || (*i) == _meter || (*i) == _main_outs || (*i) == _delayline) {
+                       if ((*i) == _amp || (*i) == _meter || (*i) == _main_outs || (*i) == _delayline || (*i) == _trim) {
 
                                /* you can't remove these */
 
@@ -1576,7 +1587,7 @@ Route::remove_processor (boost::shared_ptr<Processor> processor, ProcessorStream
 
        /* these can never be removed */
 
-       if (processor == _amp || processor == _meter || processor == _main_outs || processor == _delayline) {
+       if (processor == _amp || processor == _meter || processor == _main_outs || processor == _delayline || processor == _trim) {
                return 0;
        }
 
@@ -3209,6 +3220,7 @@ Route::no_roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame,
        }
 
        _amp->apply_gain_automation (false);
+       _trim->apply_gain_automation (false);
        passthru (bufs, start_frame, end_frame, nframes, 0);
 
        return 0;
@@ -3391,6 +3403,8 @@ Route::update_signal_latency ()
        framecnt_t l = _output->user_latency();
        framecnt_t lamp = 0;
        bool before_amp = true;
+       framecnt_t ltrim = 0;
+       bool before_trim = true;
 
        for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
                if ((*i)->active ()) {
@@ -3399,14 +3413,23 @@ Route::update_signal_latency ()
                if ((*i) == _amp) {
                        before_amp = false;
                }
+               if ((*i) == _trim) {
+                       before_amp = false;
+               }
                if (before_amp) {
                        lamp = l;
                }
+               if (before_trim) {
+                       lamp = l;
+               }
        }
 
        DEBUG_TRACE (DEBUG::Latency, string_compose ("%1: internal signal latency = %2\n", _name, l));
 
+       // TODO: (lamp - _signal_latency) to sync to output (read-ahed),  currently _roll_delay shifts this around
        _signal_latency_at_amp_position = lamp;
+       _signal_latency_at_trim_position = ltrim;
+
        if (_signal_latency != l) {
                _signal_latency = l;
                signal_latency_changed (); /* EMIT SIGNAL */
@@ -3609,6 +3632,18 @@ Route::shift (framepos_t pos, framecnt_t frames)
                _session.add_command (new MementoCommand<AutomationList> (*gc->alist().get(), &before, &after));
        }
 
+       /* gain automation */
+       {
+               boost::shared_ptr<AutomationControl> gc = _trim->gain_control();
+
+               XMLNode &before = gc->alist()->get_state ();
+               gc->alist()->shift (pos, frames);
+               XMLNode &after = gc->alist()->get_state ();
+               _session.add_command (new MementoCommand<AutomationList> (*gc->alist().get(), &before, &after));
+       }
+
+       // TODO mute automation ??
+
        /* pan automation */
        if (_pannable) {
                ControlSet::Controls& c (_pannable->controls());
index b69b0bce611602daf29353a39b249ba172e20313..100c124d72f98613bab451713496f79df9ac230c 100644 (file)
@@ -4810,6 +4810,12 @@ Session::gain_automation_buffer() const
        return ProcessThread::gain_automation_buffer ();
 }
 
+gain_t*
+Session::trim_automation_buffer() const
+{
+       return ProcessThread::trim_automation_buffer ();
+}
+
 gain_t*
 Session::send_gain_automation_buffer() const
 {
index b51576bfc920e1e46a5b908f38b5fe58dd106182..2336ee50bc866327ce802a8323788e59d2a0092d 100644 (file)
@@ -33,6 +33,7 @@ ThreadBuffers::ThreadBuffers ()
        , route_buffers (new BufferSet)
        , mix_buffers (new BufferSet)
        , gain_automation_buffer (0)
+       , trim_automation_buffer (0)
        , send_gain_automation_buffer (0)
        , pan_automation_buffer (0)
        , npan_buffers (0)
@@ -79,6 +80,8 @@ ThreadBuffers::ensure_buffers (ChanCount howmany, size_t custom)
 
        delete [] gain_automation_buffer;
        gain_automation_buffer = new gain_t[audio_buffer_size];
+       delete [] trim_automation_buffer;
+       trim_automation_buffer = new gain_t[audio_buffer_size];
        delete [] send_gain_automation_buffer;
        send_gain_automation_buffer = new gain_t[audio_buffer_size];