Fixes for IO port adding/removing

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
This commit is contained in:
David Robillard 2006-09-01 07:38:55 +00:00
parent 017e16c530
commit bd1220a46d
17 changed files with 99 additions and 80 deletions

View 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);

View 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;

View 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

View 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

View 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;

View 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

View 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);
}

View 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);
}
}

View 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;
}

View 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

View 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

View 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);

View 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?
if (muted()) {
IO::silence(nframes, offset);
} else {
deliver_output(bufs, start_frame, end_frame, nframes, offset);
// 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

View 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;
}

View 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

View 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);

View 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);