diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2009-01-30 07:40:13 +0000 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2009-01-30 07:40:13 +0000 |
commit | 70b939da4f9d4097160e32f2373a7a5ff8f4957f (patch) | |
tree | 5917e5847c75e441c9df550d5101352d18e8286f /libs/ardour/audio_port.cc | |
parent | ee62ee07d39f51ba1b70f390dc2158c57f54a572 (diff) |
first pass at internal sends. this is a very tentative work in progress, and it is possible that major changes may follow in the near future. it is certainly not complete, but the fundamental changes to Port/Buffer operation merit a commit at this point
git-svn-id: svn://localhost/ardour2/branches/3.0@4464 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs/ardour/audio_port.cc')
-rw-r--r-- | libs/ardour/audio_port.cc | 126 |
1 files changed, 84 insertions, 42 deletions
diff --git a/libs/ardour/audio_port.cc b/libs/ardour/audio_port.cc index 55d65d850d..0e48c2a699 100644 --- a/libs/ardour/audio_port.cc +++ b/libs/ardour/audio_port.cc @@ -29,9 +29,10 @@ AudioPort::AudioPort (const std::string& name, Flags flags, bool ext, nframes_t : Port (name, DataType::AUDIO, flags, ext) , _has_been_mixed_down (false) , _buffer (0) + , _internal_buffer (false) { assert (name.find_first_of (':') == string::npos); - + if (external ()) { /* external ports use the external port buffer */ @@ -41,8 +42,9 @@ AudioPort::AudioPort (const std::string& name, Flags flags, bool ext, nframes_t /* internal ports need their own buffers */ _buffer = new AudioBuffer (capacity); - } + + check_buffer_status (); } @@ -56,11 +58,22 @@ AudioPort::cycle_start (nframes_t nframes, nframes_t offset) { /* caller must hold process lock */ - _has_been_mixed_down = false; + /* For external (JACK) ports, get_buffer() must only be run + on outputs here in cycle_start(). - if (external ()) { - /* external ports use JACK's memory */ - _buffer->set_data ((Sample *) jack_port_get_buffer (_jack_port, nframes), nframes + offset); + Inputs must be done in the correct processing order, which + requires interleaving with route processing. that will + happen when Port::get_buffer() is called. + */ + + if (!receives_input() && external ()) { + _buffer->set_data ((Sample *) jack_port_get_buffer (_jack_port, nframes) + offset, nframes); + } + + if (receives_input()) { + _has_been_mixed_down = false; + } else { + _buffer->silence (nframes, offset); } } @@ -69,36 +82,21 @@ AudioPort::get_audio_buffer (nframes_t nframes, nframes_t offset) { /* caller must hold process lock */ - if (_has_been_mixed_down) { - return *_buffer; - } - - if (receives_input ()) { - - /* INPUT */ + if (receives_input () && !_has_been_mixed_down) { - /* If we're external (), we have some data in our buffer set up by JACK; - otherwise, we have an undefined buffer. In either case we mix down - our non-JACK inputs; either accumulating into the JACK data or - overwriting the undefined data */ - - mixdown (nframes, offset, !external ()); + /* external ports use JACK's memory unless otherwise noted */ - } else { - - /* OUTPUT */ - - if (!external ()) { - /* start internal output buffers with silence */ - _buffer->silence (nframes, offset); + if (external()) { + if (!using_internal_data()) { + _buffer->set_data ((Sample *) jack_port_get_buffer (_jack_port, nframes) + offset, nframes); + } else { + _buffer->silence (nframes, offset); + } } - - } - - if (nframes) { - _has_been_mixed_down = true; - } + mixdown (nframes, offset, !external ()); + } + return *_buffer; } @@ -111,22 +109,46 @@ AudioPort::cycle_end (nframes_t nframes, nframes_t offset) void AudioPort::mixdown (nframes_t cnt, nframes_t offset, bool first_overwrite) { + /* note: this is only called for input ports */ + if (_connections.empty()) { - if (first_overwrite) { + + /* no internal mixing to do, so for internal ports + just make sure the buffer is silent. + */ + + if (!external()) { _buffer->silence (cnt, offset); + } + + } else { + + set<Port*>::const_iterator p = _connections.begin(); + + /* mix in internally-connected ports. if this is an external port + then it may already have data present from JACK. in that case, we + do not want to overwrite that data, so we skip the initial ::read_from() + call and do everything with accumulate_from() + */ + + if (!external()) { + _buffer->read_from (dynamic_cast<AudioPort*>(*p)->get_audio_buffer (cnt, offset), cnt, offset); + ++p; + } - return; - } - - set<Port*>::const_iterator p = _connections.begin(); - if (first_overwrite) { - _buffer->read_from (dynamic_cast<AudioPort*>(*p)->get_audio_buffer (cnt, offset), cnt, offset); - ++p; + for (; p != _connections.end (); ++p) { + _buffer->accumulate_from (dynamic_cast<AudioPort*>(*p)->get_audio_buffer (cnt, offset), cnt, offset); + + } } - for (; p != _connections.end (); ++p) { - _buffer->accumulate_from (dynamic_cast<AudioPort*>(*p)->get_audio_buffer (cnt, offset), cnt, offset); + /* XXX horrible heuristic designed to check that we worked the whole buffer. + Needs fixing but its a hard problem. + */ + + if (cnt && offset == 0) { + _has_been_mixed_down = true; } } @@ -140,3 +162,23 @@ AudioPort::reset () _buffer->clear (); } } + +bool +AudioPort::using_internal_data () const +{ + return _internal_buffer; +} + +void +AudioPort::use_internal_data () +{ + _buffer->replace_data (_buffer->capacity()); + _internal_buffer = true; +} + +void +AudioPort::use_external_data () +{ + _internal_buffer = false; + _buffer->drop_data (); +} |