summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2007-09-18 15:13:05 +0000
committerDavid Robillard <d@drobilla.net>2007-09-18 15:13:05 +0000
commitcbc7847a12e57176c5bafa9baa007de6865745c7 (patch)
tree0ca368a06c025c3898682b1bfa18fbb048e45b9b /src
parent33f66f46c1f1e9774e5b59a9637d2bfabd700394 (diff)
downloadingen-cbc7847a12e57176c5bafa9baa007de6865745c7.tar.gz
ingen-cbc7847a12e57176c5bafa9baa007de6865745c7.tar.bz2
ingen-cbc7847a12e57176c5bafa9baa007de6865745c7.zip
Work on dynamic polyphony.
git-svn-id: http://svn.drobilla.net/lad/ingen@720 a436a847-0d15-0410-975c-d299462d15a1
Diffstat (limited to 'src')
-rw-r--r--src/libs/engine/InputPort.cpp44
-rw-r--r--src/libs/engine/LV2Node.cpp14
-rw-r--r--src/libs/engine/LV2Node.hpp4
-rw-r--r--src/libs/engine/Node.hpp17
-rw-r--r--src/libs/engine/NodeBase.cpp18
-rw-r--r--src/libs/engine/NodeBase.hpp3
-rw-r--r--src/libs/engine/OutputPort.cpp4
-rw-r--r--src/libs/engine/Port.cpp44
-rw-r--r--src/libs/engine/Port.hpp24
9 files changed, 138 insertions, 34 deletions
diff --git a/src/libs/engine/InputPort.cpp b/src/libs/engine/InputPort.cpp
index 5025f6e3..edc89225 100644
--- a/src/libs/engine/InputPort.cpp
+++ b/src/libs/engine/InputPort.cpp
@@ -55,25 +55,25 @@ InputPort::add_connection(Raul::ListNode<Connection*>* const c)
if (_connections.size() == 1) {
// Use buffer directly to avoid copying
for (uint32_t i=0; i < _poly; ++i) {
- _buffers.at(i)->join(c->elem()->buffer(i));
+ _buffers->at(i)->join(c->elem()->buffer(i));
//if (_is_tied)
- // _tied_port->buffer(i)->join(_buffers.at(i));
- //assert(_buffers.at(i)->data() == c->elem()->buffer(i)->data());
+ // _tied_port->buffer(i)->join(_buffers->at(i));
+ //assert(_buffers->at(i)->data() == c->elem()->buffer(i)->data());
}
} else if (_connections.size() == 2) {
// Used to directly use single connection buffer, now there's two
// so have to use local ones again and mix down
for (uint32_t i=0; i < _poly; ++i) {
- _buffers.at(i)->unjoin();
+ _buffers->at(i)->unjoin();
//if (_is_tied)
- // _tied_port->buffer(i)->join(_buffers.at(i));
+ // _tied_port->buffer(i)->join(_buffers->at(i));
}
}
Port::connect_buffers();
}
//assert( ! _is_tied || _tied_port != NULL);
- //assert( ! _is_tied || _buffers.at(0)->data() == _tied_port->buffer(0)->data());
+ //assert( ! _is_tied || _buffers->at(0)->data() == _tied_port->buffer(0)->data());
}
@@ -103,17 +103,17 @@ InputPort::remove_connection(const OutputPort* src_port)
for (uint32_t i=0; i < _poly; ++i) {
// Use a local buffer
if (modify_buffers)
- _buffers.at(i)->unjoin();
- _buffers.at(i)->clear(); // Write silence
+ _buffers->at(i)->unjoin();
+ _buffers->at(i)->clear(); // Write silence
//if (_is_tied)
- //m_tied_port->buffer(i)->join(_buffers.at(i));
+ //m_tied_port->buffer(i)->join(_buffers->at(i));
}
} else if (modify_buffers && _connections.size() == 1) {
// Share a buffer
for (uint32_t i=0; i < _poly; ++i) {
- _buffers.at(i)->join((*_connections.begin())->buffer(i));
+ _buffers->at(i)->join((*_connections.begin())->buffer(i));
//if (_is_tied)
- // _tied_port->buffer(i)->join(_buffers.at(i));
+ // _tied_port->buffer(i)->join(_buffers->at(i));
}
}
}
@@ -122,7 +122,7 @@ InputPort::remove_connection(const OutputPort* src_port)
Port::connect_buffers();
//assert( ! _is_tied || _tied_port != NULL);
- //assert( ! _is_tied || _buffers.at(0)->data() == _tied_port->buffer(0)->data());
+ //assert( ! _is_tied || _buffers->at(0)->data() == _tied_port->buffer(0)->data());
return connection;
}
@@ -153,7 +153,7 @@ InputPort::pre_process(SampleCount nframes, FrameTime start, FrameTime end)
if (_connections.size() == 0) {
for (uint32_t i=0; i < _poly; ++i)
- _buffers.at(i)->prepare_read(nframes);
+ _buffers->at(i)->prepare_read(nframes);
return;
}
@@ -163,13 +163,13 @@ InputPort::pre_process(SampleCount nframes, FrameTime start, FrameTime end)
// If only one connection, buffer is (maybe) used directly (no copying)
if (_connections.size() == 1) {
// Buffer changed since connection
- if (!_buffers.at(0)->is_joined_to((*_connections.begin())->buffer(0))) {
+ if (!_buffers->at(0)->is_joined_to((*_connections.begin())->buffer(0))) {
if (_fixed_buffers) { // || (_is_tied && _tied_port->fixed_buffers())) {
// can't change buffer, must copy
do_mixdown = true;
} else {
// zero-copy
- _buffers.at(0)->join((*_connections.begin())->buffer(0));
+ _buffers->at(0)->join((*_connections.begin())->buffer(0));
do_mixdown = false;
}
connect_buffers();
@@ -181,20 +181,20 @@ InputPort::pre_process(SampleCount nframes, FrameTime start, FrameTime end)
//cerr << path() << " mixing: " << do_mixdown << endl;
for (uint32_t i=0; i < _poly; ++i)
- _buffers.at(i)->prepare_read(nframes);
+ _buffers->at(i)->prepare_read(nframes);
if (!do_mixdown) {
- assert(_buffers.at(0)->is_joined_to((*_connections.begin())->buffer(0)));
+ assert(_buffers->at(0)->is_joined_to((*_connections.begin())->buffer(0)));
return;
}
/*assert(!_is_tied || _tied_port != NULL);
- assert(!_is_tied || _buffers.at(0)->data() == _tied_port->buffer(0)->data());*/
+ assert(!_is_tied || _buffers->at(0)->data() == _tied_port->buffer(0)->data());*/
if (_type == DataType::FLOAT) {
for (uint32_t voice=0; voice < _poly; ++voice) {
// Copy first connection
- _buffers.at(voice)->copy(
+ _buffers->at(voice)->copy(
(*_connections.begin())->buffer(voice), 0, _buffer_size-1);
// Accumulate the rest
@@ -203,7 +203,7 @@ InputPort::pre_process(SampleCount nframes, FrameTime start, FrameTime end)
Connections::iterator c = _connections.begin();
for (++c; c != _connections.end(); ++c)
- ((AudioBuffer*)_buffers.at(voice))->accumulate(
+ ((AudioBuffer*)_buffers->at(voice))->accumulate(
((AudioBuffer*)(*c)->buffer(voice)), 0, _buffer_size-1);
}
}
@@ -215,7 +215,7 @@ InputPort::pre_process(SampleCount nframes, FrameTime start, FrameTime end)
// cerr << "WARNING: MIDI mixing not implemented, only first connection used." << endl;
// Copy first connection
- _buffers.at(0)->copy(
+ _buffers->at(0)->copy(
(*_connections.begin())->buffer(0), 0, _buffer_size-1);
}
}
@@ -237,7 +237,7 @@ InputPort::post_process(SampleCount nframes, FrameTime start, FrameTime end)
{
// Prepare for next cycle
for (uint32_t i=0; i < _poly; ++i)
- _buffers.at(i)->prepare_write(nframes);
+ _buffers->at(i)->prepare_write(nframes);
}
diff --git a/src/libs/engine/LV2Node.cpp b/src/libs/engine/LV2Node.cpp
index ccad761f..36bfd319 100644
--- a/src/libs/engine/LV2Node.cpp
+++ b/src/libs/engine/LV2Node.cpp
@@ -50,6 +50,20 @@ LV2Node::LV2Node(const Plugin* plugin,
}
+void
+LV2Node::prepare_poly(uint32_t poly)
+{
+ NodeBase::prepare_poly(poly);
+}
+
+
+void
+LV2Node::apply_poly(Raul::Maid& maid, uint32_t poly)
+{
+ NodeBase::apply_poly(maid, poly);
+}
+
+
/** Instantiate self from LV2 plugin descriptor.
*
* Implemented as a seperate function (rather than in the constructor) to
diff --git a/src/libs/engine/LV2Node.hpp b/src/libs/engine/LV2Node.hpp
index 8a6847f1..88ae5ffc 100644
--- a/src/libs/engine/LV2Node.hpp
+++ b/src/libs/engine/LV2Node.hpp
@@ -44,6 +44,9 @@ public:
virtual ~LV2Node();
virtual bool instantiate();
+
+ void prepare_poly(uint32_t poly);
+ void apply_poly(Raul::Maid& maid, uint32_t poly);
void activate();
void deactivate();
@@ -57,6 +60,7 @@ protected:
SLV2Plugin _lv2_plugin;
SLV2Instance* _instances;
+ SLV2Instance* _prepared_instances;
};
diff --git a/src/libs/engine/Node.hpp b/src/libs/engine/Node.hpp
index feb9e9ef..ca495904 100644
--- a/src/libs/engine/Node.hpp
+++ b/src/libs/engine/Node.hpp
@@ -23,7 +23,7 @@
#include "types.hpp"
#include "GraphObject.hpp"
-namespace Raul { template <typename T> class List; }
+namespace Raul { template <typename T> class List; class Maid; }
namespace Ingen {
@@ -61,7 +61,22 @@ public:
virtual void activate() = 0;
virtual void deactivate() = 0;
virtual bool activated() = 0;
+
+ /** Prepare for a new (external) polyphony value.
+ *
+ * Preprocessor thread, poly is actually applied by apply_poly.
+ */
+ virtual void prepare_poly(uint32_t poly) = 0;
+ /** Apply a new polyphony value.
+ *
+ * Audio thread.
+ *
+ * \param poly Must be < the most recent value passed to prepare_poly.
+ * \param maid Any objects no longer needed will be pushed to this
+ */
+ virtual void apply_poly(Raul::Maid& maid, uint32_t poly) = 0;
+
/** Parallelism: Reset flags for start of a new cycle.
*/
virtual void reset_input_ready() = 0;
diff --git a/src/libs/engine/NodeBase.cpp b/src/libs/engine/NodeBase.cpp
index b61783b3..32b641e0 100644
--- a/src/libs/engine/NodeBase.cpp
+++ b/src/libs/engine/NodeBase.cpp
@@ -83,6 +83,24 @@ NodeBase::deactivate()
void
+NodeBase::prepare_poly(uint32_t poly)
+{
+ if (_ports)
+ for (size_t i=0; i < _ports->size(); ++i)
+ _ports->at(i)->prepare_poly(poly);
+}
+
+
+void
+NodeBase::apply_poly(Raul::Maid& maid, uint32_t poly)
+{
+ if (_ports)
+ for (size_t i=0; i < _ports->size(); ++i)
+ _ports->at(i)->apply_poly(maid, poly);
+}
+
+
+void
NodeBase::set_buffer_size(size_t size)
{
_buffer_size = size;
diff --git a/src/libs/engine/NodeBase.hpp b/src/libs/engine/NodeBase.hpp
index 668f615c..ed3cd80d 100644
--- a/src/libs/engine/NodeBase.hpp
+++ b/src/libs/engine/NodeBase.hpp
@@ -55,6 +55,9 @@ public:
virtual void deactivate();
bool activated() { return _activated; }
+ virtual void prepare_poly(uint32_t poly);
+ virtual void apply_poly(Raul::Maid& maid, uint32_t poly);
+
virtual void reset_input_ready();
virtual bool process_lock();
virtual void process_unlock();
diff --git a/src/libs/engine/OutputPort.cpp b/src/libs/engine/OutputPort.cpp
index ce945f09..9724c4c7 100644
--- a/src/libs/engine/OutputPort.cpp
+++ b/src/libs/engine/OutputPort.cpp
@@ -25,7 +25,7 @@ void
OutputPort::pre_process(SampleCount nframes, FrameTime start, FrameTime end)
{
for (uint32_t i=0; i < _poly; ++i)
- _buffers.at(i)->prepare_write(nframes);
+ _buffers->at(i)->prepare_write(nframes);
}
@@ -33,7 +33,7 @@ void
OutputPort::post_process(SampleCount nframes, FrameTime start, FrameTime end)
{
for (uint32_t i=0; i < _poly; ++i)
- _buffers.at(i)->prepare_read(nframes);
+ _buffers->at(i)->prepare_read(nframes);
}
diff --git a/src/libs/engine/Port.cpp b/src/libs/engine/Port.cpp
index c104c32a..8f9e9ce7 100644
--- a/src/libs/engine/Port.cpp
+++ b/src/libs/engine/Port.cpp
@@ -15,6 +15,8 @@
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include <raul/Array.hpp>
+#include <raul/Maid.hpp>
#include "Port.hpp"
#include "Node.hpp"
#include "DataType.hpp"
@@ -42,24 +44,52 @@ Port::Port(Node* const node, const string& name, uint32_t index, uint32_t poly,
allocate_buffers();
clear_buffers();
- assert(_buffers.size() > 0);
+ assert(_buffers->size() > 0);
}
Port::~Port()
{
for (uint32_t i=0; i < _poly; ++i)
- delete _buffers.at(i);
+ delete _buffers->at(i);
+}
+
+
+void
+Port::prepare_poly(uint32_t poly)
+{
+ /* FIXME: poly never goes down, harsh on memory.. */
+ if (poly > _poly) {
+ _prepared_buffers = new Raul::Array<Buffer*>(poly, *_buffers);
+ _prepared_poly = poly;
+ for (uint32_t i = _poly; i < _prepared_poly; ++i)
+ _buffers->at(i) = BufferFactory::create(_type, _buffer_size);
+ }
+}
+
+
+void
+Port::apply_poly(Raul::Maid& maid, uint32_t poly)
+{
+ assert(poly <= _prepared_poly);
+
+ // Apply a new set of buffers from a preceding call to prepare_poly
+ if (_prepared_buffers && _buffers != _prepared_buffers) {
+ maid.push(_buffers);
+ _buffers = _prepared_buffers;
+ }
+
+ _poly = poly;
}
void
Port::allocate_buffers()
{
- _buffers.alloc(_poly);
+ _buffers->alloc(_poly);
for (uint32_t i=0; i < _poly; ++i)
- _buffers.at(i) = BufferFactory::create(_type, _buffer_size);
+ _buffers->at(i) = BufferFactory::create(_type, _buffer_size);
}
@@ -69,7 +99,7 @@ Port::set_buffer_size(size_t size)
_buffer_size = size;
for (uint32_t i=0; i < _poly; ++i)
- _buffers.at(i)->resize(size);
+ _buffers->at(i)->resize(size);
connect_buffers();
}
@@ -79,7 +109,7 @@ void
Port::connect_buffers()
{
for (uint32_t i=0; i < _poly; ++i)
- Port::parent_node()->set_port_buffer(i, _index, _buffers.at(i));
+ Port::parent_node()->set_port_buffer(i, _index, _buffers->at(i));
}
@@ -87,7 +117,7 @@ void
Port::clear_buffers()
{
for (uint32_t i=0; i < _poly; ++i)
- _buffers.at(i)->clear();
+ _buffers->at(i)->clear();
}
diff --git a/src/libs/engine/Port.hpp b/src/libs/engine/Port.hpp
index 2899915f..5b1c86b2 100644
--- a/src/libs/engine/Port.hpp
+++ b/src/libs/engine/Port.hpp
@@ -25,6 +25,8 @@
#include "GraphObject.hpp"
#include "DataType.hpp"
+namespace Raul { class Maid; }
+
namespace Ingen {
class Node;
@@ -46,8 +48,22 @@ public:
/** A port's parent is always a node, so static cast should be safe */
Node* parent_node() const { return (Node*)_parent; }
+
+ /** Prepare for a new (external) polyphony value.
+ *
+ * Preprocessor thread, poly is actually applied by apply_poly.
+ */
+ virtual void prepare_poly(uint32_t poly);
+
+ /** Apply a new polyphony value.
+ *
+ * Audio thread.
+ *
+ * \param poly Must be < the most recent value passed to prepare_poly.
+ */
+ virtual void apply_poly(Raul::Maid& maid, uint32_t poly);
- Buffer* buffer(uint32_t voice) const { return _buffers.at(voice); }
+ Buffer* buffer(uint32_t voice) const { return _buffers->at(voice); }
/** Called once per process cycle */
virtual void pre_process(SampleCount nframes, FrameTime start, FrameTime end) = 0;
@@ -82,7 +98,11 @@ protected:
size_t _buffer_size;
bool _fixed_buffers;
- Raul::Array<Buffer*> _buffers;
+ Raul::Array<Buffer*>* _buffers;
+
+ // Dynamic polyphony
+ uint32_t _prepared_poly;
+ Raul::Array<Buffer*>* _prepared_buffers;
};