Fixes for IO port adding/removing
authorDavid Robillard <d@drobilla.net>
Fri, 1 Sep 2006 07:38:55 +0000 (07:38 +0000)
committerDavid Robillard <d@drobilla.net>
Fri, 1 Sep 2006 07:38:55 +0000 (07:38 +0000)
Working audio sends/port inserts
Send gain, panning
MIDI sends working (maybe port inserts too?)
Buffer/Port fixes (related to silence)
Metering bug fixes

git-svn-id: svn://localhost/ardour2/branches/midi@883 d708f5d6-7413-0410-9779-e7cbd77b26cf

17 files changed:
libs/ardour/amp.cc
libs/ardour/ardour/audio_port.h
libs/ardour/ardour/buffer.h
libs/ardour/ardour/buffer_set.h
libs/ardour/ardour/midi_port.h
libs/ardour/ardour/port.h
libs/ardour/audio_port.cc
libs/ardour/audioengine.cc
libs/ardour/buffer.cc
libs/ardour/buffer_set.cc
libs/ardour/insert.cc
libs/ardour/io.cc
libs/ardour/midi_track.cc
libs/ardour/panner.cc
libs/ardour/port.cc
libs/ardour/route.cc
libs/ardour/send.cc

index cfa20afe3b0d0dd9601f55f9bcd25fdf4bdbd577..8a73e5708e844c57c1a381134e38c89b5247d011 100644 (file)
@@ -37,7 +37,7 @@ Amp::run (BufferSet& bufs, jack_nframes_t nframes, gain_t initial, gain_t target
 
        // if we don't need to declick, defer to apply_simple_gain
        if (initial == target) {
-               apply_simple_gain(bufs, nframes, invert_polarity ? target : -target);
+               apply_simple_gain(bufs, nframes, invert_polarity ? -target : target);
        }
 
        const jack_nframes_t declick = std::min ((jack_nframes_t)128, nframes);
index 45949dc59ec46ae06da1ef9435d5a76977ceb441..07dc8da4424efc9ecbe7af5b2a079fbcb32461b1 100644 (file)
@@ -75,16 +75,6 @@ class AudioPort : public Port {
        static void set_short_over_length (jack_nframes_t);
        static void set_long_over_length (jack_nframes_t);
 
-       /** Assumes that the port is an audio output port */
-       void silence (jack_nframes_t nframes, jack_nframes_t offset) {
-               if (!_silent) {
-                       _buffer.silence(nframes, offset);
-                       if (offset == 0 && nframes == _buffer.capacity()) {
-                               _silent = true;
-                       }
-               }
-       }
-       
   protected:
        friend class AudioEngine;
 
index 896d6e7616d2732d29912ea149d50a9ec6b1896c..828eac4d64304320bf8778834cec96ee3177ffe7 100644 (file)
@@ -56,6 +56,8 @@ public:
         * Based on this you can static cast a Buffer* to the desired type. */
        DataType type() const { return _type; }
 
+       bool silent() const { return _silent; }
+
        /** Clear (eg zero, or empty) buffer starting at TIME @a offset */
        virtual void silence(jack_nframes_t len, jack_nframes_t offset=0) = 0;
        
@@ -66,12 +68,13 @@ public:
 
 protected:
        Buffer(DataType type, size_t capacity)
-       : _type(type), _capacity(capacity), _size(0) 
+       : _type(type), _capacity(capacity), _size(0), _silent(true)
        {}
 
        DataType _type;
        size_t   _capacity;
        size_t   _size;
+       bool     _silent;
 
 private:
        // Prevent copies (undefined)
@@ -93,9 +96,14 @@ public:
 
        void silence(jack_nframes_t len, jack_nframes_t offset=0)
        {
-               assert(_capacity > 0);
-               assert(offset + len <= _capacity);
-               memset(_data + offset, 0, sizeof (Sample) * len);
+               if (!_silent) {
+                       assert(_capacity > 0);
+                       assert(offset + len <= _capacity);
+                       memset(_data + offset, 0, sizeof (Sample) * len);
+                       if (offset == 0 && len == _capacity) {
+                               _silent = true;
+                       }
+               }
        }
        
        /** Read @a len frames FROM THE START OF @a src into self at @a offset */
@@ -105,6 +113,7 @@ public:
                assert(src.type() == _type == DataType::AUDIO);
                assert(offset + len <= _capacity);
                memcpy(_data + offset, ((AudioBuffer&)src).data(len), sizeof(Sample) * len);
+               _silent = src.silent();
        }
        
        /** Accumulate (add)@a len frames FROM THE START OF @a src into self at @a offset */
@@ -119,6 +128,8 @@ public:
                for (jack_nframes_t n = 0; n < len; ++n) {
                        dst_raw[n] += src_raw[n];
                }
+
+               _silent = (src.silent() && _silent);
        }
        
        /** Accumulate (add) @a len frames FROM THE START OF @a src into self at @a offset
@@ -134,6 +145,8 @@ public:
                for (jack_nframes_t n = 0; n < len; ++n) {
                        dst_raw[n] += src_raw[n] * gain_coeff;
                }
+               
+               _silent = ( (src.silent() && _silent) || (_silent && gain_coeff == 0) );
        }
        
        void apply_gain(gain_t gain, jack_nframes_t len, jack_nframes_t offset=0) {
@@ -142,6 +155,8 @@ public:
                for (jack_nframes_t n = 0; n < len; ++n) {
                        buf[n] *= gain;
                }
+
+               _silent = (_silent || gain == 0);
        }
 
        /** Set the data contained by this buffer manually (for setting directly to jack buffer).
@@ -154,6 +169,7 @@ public:
                _capacity = size;
                _size = size;
                _data = data;
+               _silent = false;
        }
 
        const Sample* data(jack_nframes_t nframes, jack_nframes_t offset=0) const
index 43df729e05d3a3662e10c8ddbd2e290a81322867..03b0b193d47118c3fd7bb645a3374f83d0526123 100644 (file)
@@ -84,10 +84,7 @@ public:
                return (MidiBuffer&)get(DataType::MIDI, i);
        }
 
-       void read_from(BufferSet& in, jack_nframes_t nframes, jack_nframes_t offset=0)
-       {
-               throw; // FIXME: implement this with spiffy DataType iterator etc.
-       }
+       void read_from(BufferSet& in, jack_nframes_t nframes, jack_nframes_t offset=0);
 
        // ITERATORS
        
index f6eafe11bd10b0d5a00147b1351166aee76d938b..1abfd809321a9423eb6389cbb2cb087e7181ff5a 100644 (file)
@@ -52,11 +52,6 @@ class MidiPort : public Port {
 
        size_t capacity() { return _buffer.capacity(); }
        size_t size()     { return _buffer.size(); }
-       
-       /** Assumes that the port is an output port */
-       void silence (jack_nframes_t nframes, jack_nframes_t offset) {
-               _buffer.silence(nframes, offset);
-       }
 
   protected:
        friend class AudioEngine;
index a436722cb04cf6d11d23f55b2e691e4964a3bdec..2a99bdcc16370c5829a2a5a54e0bd0cdaaca12d4 100644 (file)
@@ -47,10 +47,6 @@ class Port : public sigc::trackable {
 
        virtual Buffer& get_buffer() = 0;
        
-       /** Silence/Empty the port, output ports only */
-       virtual void silence (jack_nframes_t nframes, jack_nframes_t offset) = 0;
-
-
        std::string name() const { 
                return _name;
        }
@@ -128,12 +124,6 @@ class Port : public sigc::trackable {
                jack_port_set_latency (_port, nframes);
        }
 
-       bool is_silent() const { return _silent; }
-
-       void mark_silence (bool yn) {
-               _silent = yn;
-       }
-       
        sigc::signal<void,bool> MonitorInputChanged;
        sigc::signal<void,bool> ClockSyncChanged;
 
@@ -156,7 +146,6 @@ class Port : public sigc::trackable {
        unsigned short _metering;
 
        bool          _last_monitor : 1;
-       bool          _silent : 1;
 };
  
 } // namespace ARDOUR
index 99f2b7ecae17993e11674f568a0ca0484595c192..2250c7f2a7376224cc1e76f5acf19704664575b1 100644 (file)
@@ -44,7 +44,7 @@ AudioPort::reset()
                if (_buffer.capacity() > 0) {
                        _buffer.clear();
                }
-               _silent = true;
+               assert(_buffer.silent());
        }
        
        _metering = 0;
@@ -55,8 +55,12 @@ void
 AudioPort::cycle_start (jack_nframes_t nframes)
 {
        if (_flags & JackPortIsOutput) {
-               // FIXME: do nothing, we can cache the value (but capacity needs to be set)
+               const bool silent = _buffer.silent();
+               // FIXME: do nothing, we can cache the value (but capacity needs to be set for MIDI)
                _buffer.set_data((Sample*)jack_port_get_buffer (_port, nframes), nframes);
+               if (silent) {
+                       _buffer.silence(nframes);
+               }
        } else {
                _buffer.set_data((Sample*)jack_port_get_buffer (_port, nframes), nframes);
        }
index 027a6233017b215ac376d57cc878de91b281c35b..ddb835c78f9539cc5480a91f354ecab5a08899e4 100644 (file)
@@ -1066,7 +1066,7 @@ AudioEngine::reconnect_to_jack ()
                (*i)->reset ();
 
                if ((*i)->flags() & JackPortIsOutput) {
-                       (*i)->silence (jack_get_buffer_size (_jack), 0);
+                       (*i)->get_buffer().silence (jack_get_buffer_size (_jack), 0);
                }
        }
 
index 7b99f2a900d60688860edef2c7f91241782d1fdf..d4a370685c1a536dd0ccab0e0c9ee59d941bf91c 100644 (file)
@@ -39,6 +39,7 @@ Buffer::create(DataType type, size_t capacity)
 
 AudioBuffer::AudioBuffer(size_t capacity)
        : Buffer(DataType::AUDIO, capacity)
+       , _owns_data(false)
        , _data(NULL)
 {
        _size = capacity; // For audio buffers, size = capacity (always)
@@ -49,10 +50,8 @@ AudioBuffer::AudioBuffer(size_t capacity)
                posix_memalign((void**)&_data, 16, sizeof(Sample) * capacity);
 #endif 
                assert(_data);
-               clear();
                _owns_data = true;
-       } else {
-               _owns_data = false;
+               clear();
        }
 }
 
@@ -108,13 +107,15 @@ MidiBuffer::read_from(const Buffer& src, jack_nframes_t nframes, jack_nframes_t
        clear();
        assert(_size == 0);
 
-       // FIXME: This is embarrassingly slow.  branch branch branch
+       // FIXME: slow
        for (size_t i=0; i < src.size(); ++i) {
                const MidiEvent& ev = msrc[i];
                if (ev.time >= offset && ev.time < offset+nframes) {
                        push_back(ev);
                }
        }
+
+       _silent = src.silent();
 }
 
 
@@ -140,6 +141,8 @@ MidiBuffer::push_back(const MidiEvent& ev)
 
        //cerr << "MidiBuffer: pushed, size = " << _size << endl;
 
+       _silent = false;
+
        return true;
 }
 
@@ -154,6 +157,7 @@ MidiBuffer::silence(jack_nframes_t dur, jack_nframes_t offset)
        memset(_events, 0, sizeof(MidiEvent) * _capacity);
        memset(_data, 0, sizeof(RawMidi) * _capacity * MAX_EVENT_SIZE);
        _size = 0;
+       _silent = true;
 }
 
 
index 3989df2ad21c1b1a3626c5e14073a46fe9d46b4e..bbbf7e3b8612e19486e7d962e084659810f417e3 100644 (file)
@@ -149,6 +149,22 @@ BufferSet::buffer_capacity(DataType type) const
        return _buffers[type.to_index()][0]->capacity();
 }
 
+// FIXME: make 'in' const
+void
+BufferSet::read_from(BufferSet& in, jack_nframes_t nframes, jack_nframes_t offset)
+{
+       assert(available() >= in.count());
+
+       // Copy all buffers 1:1
+       for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
+               BufferSet::iterator o = begin(*t);
+               for (BufferSet::iterator i = in.begin(*t); i != in.end(*t); ++i, ++o) {
+                       o->read_from(*i, nframes, offset);
+               }
+       }
+
+       set_count(in.count());
+}
 
 } // namespace ARDOUR
 
index c74c81f7e39d90939feb6926cb1a6f2f4403721b..e72c1d535ad4817643ab746a5e3b43b6f6ff3f0c 100644 (file)
@@ -1045,7 +1045,7 @@ PortInsert::configure_io (int32_t ignored_magic, int32_t in, int32_t out)
        }
 
        // FIXME
-       return ensure_io (ChanCount(_default_type, out), ChanCount(_default_type, in), false, this);
+       return ensure_io (ChanCount(_default_type, in), ChanCount(_default_type, out), false, this);
 }
 
 int32_t
index 00c0f4e168ebc1580ab5fb8dc9ec8c131866dd92..a30881b4dab25b4c09e58d1f0618f86c6c88b261 100644 (file)
@@ -181,7 +181,7 @@ IO::silence (jack_nframes_t nframes, jack_nframes_t offset)
        /* io_lock, not taken: function must be called from Session::process() calltree */
 
        for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
-               i->silence (nframes, offset);
+               i->get_buffer().silence (nframes, offset);
        }
 }
 
@@ -217,6 +217,15 @@ IO::deliver_output (BufferSet& bufs, jack_nframes_t start_frame, jack_nframes_t
        // Use the panner to distribute audio to output port buffers
        if (_panner && !_panner->empty() && !_panner->bypassed()) {
                _panner->distribute(bufs, output_buffers(), start_frame, end_frame, nframes, offset);
+       } else {
+               const DataType type = DataType::AUDIO;
+
+               // Copy any audio 1:1 to outputs
+               assert(bufs.count().get(DataType::AUDIO) == output_buffers().count().get(DataType::AUDIO));
+               BufferSet::iterator o = output_buffers().begin(type);
+               for (BufferSet::iterator i = bufs.begin(type); i != bufs.end(type); ++i, ++o) {
+                       o->read_from(*i, nframes, offset);
+               }
        }
 
 
@@ -228,8 +237,9 @@ IO::deliver_output (BufferSet& bufs, jack_nframes_t start_frame, jack_nframes_t
        }
 
        const DataType type = DataType::MIDI;
-       
-       // Just dump any MIDI 1-to-1, we're not at all clever with MIDI routing yet
+
+       // Copy any MIDI 1:1 to outputs
+       assert(bufs.count().get(DataType::MIDI) == output_buffers().count().get(DataType::MIDI));
        BufferSet::iterator o = output_buffers().begin(type);
        for (BufferSet::iterator i = bufs.begin(type); i != bufs.end(type); ++i, ++o) {
                o->read_from(*i, nframes, offset);
index 2336baac75965f7443287adef6fd0a7271084f72..900a4f3191f9034e44ad66afaea2b7919eae40f3 100644 (file)
@@ -542,22 +542,26 @@ MidiTrack::process_output_buffers (BufferSet& bufs,
                               jack_nframes_t nframes, jack_nframes_t offset, bool with_redirects, int declick,
                               bool meter)
 {
-       // There's no such thing as a MIDI bus for the time being, to avoid diverging from trunk
-       // too much until the SoC settles down.  We'll do all the MIDI route work here for now
+       /* There's no such thing as a MIDI bus for the time being, to avoid diverging from trunk
+        * too much until the SoC settles down.  We'll do all the MIDI route work here for now,
+        * but the long-term goal is to have Route::process_output_buffers handle everything */
        
-       // Main output stage is the only stage we've got.
-       // I think it's a pretty good stage though, wouldn't you say?
+       // Run all redirects
+       if (with_redirects) {
+               Glib::RWLock::ReaderLock rm (redirect_lock, Glib::TRY_LOCK);
+               if (rm.locked()) {
+                       for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
+                               (*i)->run (bufs, start_frame, end_frame, nframes, offset);
+                       }
+               } 
+       }
        
+       // Main output stage
        if (muted()) {
-
                IO::silence(nframes, offset);
-
        } else {
-
                deliver_output(bufs, start_frame, end_frame, nframes, offset);
-
        }
-
 }
 
 int
index 3e8329cc9db58c593da506ea19e25764b1c0327b..1ced0faf89d5c2896b430d0fd408e96e56250186 100644 (file)
@@ -1525,8 +1525,6 @@ Panner::distribute_no_automation (BufferSet& inbufs, BufferSet& outbufs, jack_nf
                                dst.accumulate_from(*i, nframes, offset);
                        }
 
-                       //audio_output(0)->mark_silence (false); // FIXME
-
                } else {
 
                        /* mix all buffers into the output, scaling them all by the gain */
@@ -1540,7 +1538,6 @@ Panner::distribute_no_automation (BufferSet& inbufs, BufferSet& outbufs, jack_nf
                                dst.accumulate_with_gain_from(*i, nframes, offset, gain_coeff);
                        }
 
-                       //audio_output(0)->mark_silence (false); // FIXME
                }
 
                return;
@@ -1604,8 +1601,6 @@ Panner::distribute (BufferSet& inbufs, BufferSet& outbufs, jack_nframes_t start_
                        dst.accumulate_from(*i, nframes, offset);
                }
 
-               //audio_output(0)->mark_silence (false); // FIXME
-
                return;
        }
 
index 5f8b454f0fb6eb0d83bf6484b933799bc494f81a..9e77128e4ca8f57aecb0c22ba854b897c79a78a3 100644 (file)
@@ -27,7 +27,6 @@ Port::Port (jack_port_t *p)
        : _port (p)
        , _metering(0)
        , _last_monitor(false)
-       , _silent(false)
 {
        if (_port == 0) {
                throw failed_constructor();
@@ -44,7 +43,6 @@ void
 Port::reset ()
 {
        _last_monitor = false;
-       _silent = false;
 }
 
 int 
index e0b890340ac2e6d36ccdaad7cfb8325a5fb9f662..672e0692cbb4f183b00ab6567cb8d9e9f9e44c44 100644 (file)
@@ -240,7 +240,6 @@ Route::process_output_buffers (BufferSet& bufs,
        bool post_fader_work = false;
        bool mute_declick_applied = false;
        gain_t dmg, dsg, dg;
-       vector<Sample*>::iterator bufiter;
        IO *co;
        bool mute_audible;
        bool solo_audible;
@@ -338,10 +337,14 @@ Route::process_output_buffers (BufferSet& bufs,
                } 
        } 
 
-       /* ----------------------------------------------------------------------------------------------------
+       /* ---------------------------------------------------------------------------------------------------
           PRE-FADER REDIRECTS
           -------------------------------------------------------------------------------------------------- */
 
+       /* FIXME: Somewhere in these loops is where bufs.count() should go from n_inputs() to redirect_max_outs()
+        * (if they differ).  Something explicit needs to be done here to make sure the list of redirects will
+        * give us what we need (possibly by inserting transparent 'translators' into the list to make it work) */
+
        if (with_redirects) {
                Glib::RWLock::ReaderLock rm (redirect_lock, Glib::TRY_LOCK);
                if (rm.locked()) {
@@ -371,7 +374,10 @@ Route::process_output_buffers (BufferSet& bufs,
                } 
        }
 
+       // FIXME: for now, just hope the redirects list did what it was supposed to
+       bufs.set_count(n_process_buffers());
 
+       
        if (!_soloed && (mute_gain != dmg) && !mute_declick_applied && _mute_affects_post_fader) {
                Amp::run (bufs, nframes, mute_gain, dmg, _phase_invert);
                mute_gain = dmg;
@@ -652,8 +658,7 @@ Route::process_output_buffers (BufferSet& bufs,
 ChanCount
 Route::n_process_buffers ()
 {
-       //return max (n_inputs(), redirect_max_outs);
-       return n_inputs(); // FIXME?
+       return max (n_inputs(), redirect_max_outs);
 }
 
 void
@@ -761,8 +766,6 @@ Route::add_redirect (boost::shared_ptr<Redirect> redirect, void *src, uint32_t*
 
                redirect->set_default_type(_default_type);
 
-               ChanCount potential_max_streams;
-
                if ((pi = boost::dynamic_pointer_cast<PluginInsert>(redirect)) != 0) {
                        pi->set_count (1);
 
@@ -770,8 +773,6 @@ Route::add_redirect (boost::shared_ptr<Redirect> redirect, void *src, uint32_t*
                                /* generator plugin */
                                _have_internal_generator = true;
                        }
-
-                       potential_max_streams = max(pi->input_streams(), pi->output_streams());
                        
                } else if ((porti = boost::dynamic_pointer_cast<PortInsert>(redirect)) != 0) {
 
@@ -784,13 +785,14 @@ Route::add_redirect (boost::shared_ptr<Redirect> redirect, void *src, uint32_t*
                           the "outputs" of the route should match the inputs of this
                           route. XXX shouldn't they match the number of active signal
                           streams at the point of insertion?
-                          
                        */
+                       // FIXME: (yes, they should)
 
                        porti->ensure_io (n_outputs (), n_inputs(), false, this);
                }
-
+               
                // Ensure peak vector sizes before the plugin is activated
+               ChanCount potential_max_streams = max(redirect->input_streams(), redirect->output_streams());
                _meter->setup(potential_max_streams);
 
                _redirects.push_back (redirect);
index 9161b0492d5078e88c0e3282f35f818fe80068c5..6654f3c75bf90da59e6a540c04438c8db651c028 100644 (file)
@@ -38,7 +38,7 @@ Send::Send (Session& s, Placement p)
 {
        _metering = false;
        save_state (_("initial state"));
-        RedirectCreated (this); /* EMIT SIGNAL */
+       RedirectCreated (this); /* EMIT SIGNAL */
 }
 
 Send::Send (Session& s, const XMLNode& node)
@@ -51,7 +51,7 @@ Send::Send (Session& s, const XMLNode& node)
        }
 
        save_state (_("initial state"));
-        RedirectCreated (this); /* EMIT SIGNAL */
+       RedirectCreated (this); /* EMIT SIGNAL */
 }
 
 Send::Send (const Send& other)
@@ -114,7 +114,6 @@ Send::run (BufferSet& bufs, jack_nframes_t start_frame, jack_nframes_t end_frame
 
                sendbufs.read_from(bufs, nframes);
                assert(sendbufs.count() == bufs.count());
-               assert(sendbufs.count() == _outputs.count());
 
                IO::deliver_output (sendbufs, start_frame, end_frame, nframes, offset);