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:
parent
017e16c530
commit
bd1220a46d
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user