summaryrefslogtreecommitdiff
path: root/libs/ardour/audio_port.cc
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2009-01-30 07:40:13 +0000
committerPaul Davis <paul@linuxaudiosystems.com>2009-01-30 07:40:13 +0000
commit70b939da4f9d4097160e32f2373a7a5ff8f4957f (patch)
tree5917e5847c75e441c9df550d5101352d18e8286f /libs/ardour/audio_port.cc
parentee62ee07d39f51ba1b70f390dc2158c57f54a572 (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.cc126
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 ();
+}