From 52e49500bb78974d43bdfd30b2ec9b2a4522dd25 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Fri, 26 Feb 2010 01:39:16 +0000 Subject: Perform all mixing for an audio input in a single mix operation (instead of a two step polyphony mixdown (by connections) and connections mixdown (by ports)). Speed up and inline AudioBuffer::accumulate, to speed up mix(). Remove local buffer from Connection (always mix into destination InputPort's buffers). git-svn-id: http://svn.drobilla.net/lad/trunk/ingen@2494 a436a847-0d15-0410-975c-d299462d15a1 --- src/engine/InputPort.cpp | 81 ++++++++++++++++++++++++------------------------ 1 file changed, 40 insertions(+), 41 deletions(-) (limited to 'src/engine/InputPort.cpp') diff --git a/src/engine/InputPort.cpp b/src/engine/InputPort.cpp index d5051865..4c5b56e2 100644 --- a/src/engine/InputPort.cpp +++ b/src/engine/InputPort.cpp @@ -75,19 +75,10 @@ InputPort::apply_poly(Maid& maid, uint32_t poly) } -void -InputPort::set_buffer_size(Context& context, BufferFactory& bufs, size_t size) -{ - PortImpl::set_buffer_size(context, bufs, size); - - for (Connections::iterator c = _connections.begin(); c != _connections.end(); ++c) - (*c)->update_buffer_size(context, bufs); -} - - /** Set \a buffers appropriately if this port has \a num_connections connections. + * \return true iff buffers are locally owned by the port */ -void +bool InputPort::get_buffers(BufferFactory& bufs, Raul::Array* buffers, uint32_t poly) { size_t num_connections = (ThreadManager::current_thread_id() == THREAD_PROCESS) @@ -97,26 +88,25 @@ InputPort::get_buffers(BufferFactory& bufs, Raul::Array* buf // Audio input with no connections, use shared zero buffer for (uint32_t v = 0; v < poly; ++v) buffers->at(v) = bufs.silent_buffer(); + return false; } else if (num_connections == 1) { if (ThreadManager::current_thread_id() == THREAD_PROCESS) { - // Single connection, use it directly - for (uint32_t v = 0; v < poly; ++v) - buffers->at(v) = _connections.front()->buffer(v); - } else { - // Not in the process thread, will be set later - for (uint32_t v = 0; v < poly; ++v) - buffers->at(v) = NULL; + if (!_connections.front()->must_mix()) { + // Single non-mixing conneciton, use buffers directly + for (uint32_t v = 0; v < poly; ++v) + buffers->at(v) = _connections.front()->buffer(v); + return false; + } } + } - } else { - // Use local buffers - for (uint32_t v = 0; v < poly; ++v) { - buffers->at(v) = NULL; // Release first (potential immediate recycling) - buffers->at(v) = _bufs.get(buffer_type(), _buffer_size); - buffers->at(v)->clear(); - } + // Otherwise, allocate local buffers + for (uint32_t v = 0; v < poly; ++v) { + buffers->at(v) = _bufs.get(buffer_type(), _buffer_size); + buffers->at(v)->clear(); } + return true; } @@ -186,31 +176,32 @@ InputPort::pre_process(Context& context) if (_set_by_user) return; - // Process connections (mix down polyphony, if necessary) + uint32_t max_num_srcs = 0; for (Connections::iterator c = _connections.begin(); c != _connections.end(); ++c) - (*c)->process(context); + max_num_srcs += (*c)->src_port()->poly(); - // Multiple connections, mix them all into our local buffers - if (_connections.size() > 1) { - for (uint32_t v = 0; v < _poly; ++v) - buffer(v)->prepare_write(context); + Buffer* srcs[max_num_srcs]; + if (_connections.empty()) { for (uint32_t v = 0; v < _poly; ++v) { - const uint32_t num_srcs = _connections.size(); - Connections::iterator c = _connections.begin(); - Buffer* srcs[num_srcs]; - for (uint32_t i = 0; c != _connections.end(); ++c) { - assert(i < num_srcs); - srcs[i++] = (*c)->buffer(v).get(); - } + buffer(v)->prepare_read(context); + } + } else if (direct_connect()) { + for (uint32_t v = 0; v < _poly; ++v) { + _buffers->at(v) = _connections.front()->buffer(v); + _buffers->at(v)->prepare_read(context); + } + } else { + for (uint32_t v = 0; v < _poly; ++v) { + uint32_t num_srcs = 0; + for (Connections::iterator c = _connections.begin(); c != _connections.end(); ++c) + (*c)->get_sources(context, v, srcs, max_num_srcs, num_srcs); mix(context, buffer(v).get(), srcs, num_srcs); + buffer(v)->prepare_read(context); } } - for (uint32_t v = 0; v < _poly; ++v) - buffer(v)->prepare_read(context); - if (_broadcast) broadcast_value(context, false); } @@ -223,5 +214,13 @@ InputPort::post_process(Context& context) } +bool +InputPort::direct_connect() const +{ + ThreadManager::assert_thread(THREAD_PROCESS); + return _connections.size() == 1 && !_connections.front()->must_mix(); +} + + } // namespace Ingen -- cgit v1.2.1