summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2007-09-21 00:46:21 +0000
committerDavid Robillard <d@drobilla.net>2007-09-21 00:46:21 +0000
commit2fd281a285e4b0bc31e0a0dc6f970359440612c8 (patch)
treeb4537d5196d13608cacb32f4c96bdb24ff180b3d
parentc4faafc0d3b9c68d41706ad40edde1ecfb7f4338 (diff)
downloadingen-2fd281a285e4b0bc31e0a0dc6f970359440612c8.tar.gz
ingen-2fd281a285e4b0bc31e0a0dc6f970359440612c8.tar.bz2
ingen-2fd281a285e4b0bc31e0a0dc6f970359440612c8.zip
Somewhat functional dynamic polyphony (LV2 and internal nodes only).
git-svn-id: http://svn.drobilla.net/lad/ingen@744 a436a847-0d15-0410-975c-d299462d15a1
-rw-r--r--src/libs/engine/Buffer.hpp5
-rw-r--r--src/libs/engine/Connection.cpp37
-rw-r--r--src/libs/engine/Connection.hpp9
-rw-r--r--src/libs/engine/InputPort.cpp53
-rw-r--r--src/libs/engine/JackAudioDriver.cpp18
-rw-r--r--src/libs/engine/LV2Node.cpp24
-rw-r--r--src/libs/engine/MidiNoteNode.cpp12
-rw-r--r--src/libs/engine/MidiNoteNode.hpp4
-rw-r--r--src/libs/engine/NodeBase.cpp2
-rw-r--r--src/libs/engine/NodeFactory.cpp2
-rw-r--r--src/libs/engine/Patch.cpp6
-rw-r--r--src/libs/engine/Port.cpp13
12 files changed, 92 insertions, 93 deletions
diff --git a/src/libs/engine/Buffer.hpp b/src/libs/engine/Buffer.hpp
index 4a79c482..44b69cbe 100644
--- a/src/libs/engine/Buffer.hpp
+++ b/src/libs/engine/Buffer.hpp
@@ -21,13 +21,14 @@
#include <cstddef>
#include <cassert>
#include <boost/utility.hpp>
+#include <raul/Deletable.hpp>
#include "types.hpp"
#include "DataType.hpp"
namespace Ingen {
-class Buffer : public boost::noncopyable
+class Buffer : public boost::noncopyable, public Raul::Deletable
{
public:
Buffer(DataType type, size_t size)
@@ -35,8 +36,6 @@ public:
, _size(size)
{}
- virtual ~Buffer() {}
-
/** Clear contents and reset state */
virtual void clear() = 0;
diff --git a/src/libs/engine/Connection.cpp b/src/libs/engine/Connection.cpp
index bae72412..c2ecb2ec 100644
--- a/src/libs/engine/Connection.cpp
+++ b/src/libs/engine/Connection.cpp
@@ -16,6 +16,7 @@
*/
#include <algorithm>
+#include <raul/Maid.hpp>
#include "util.hpp"
#include "Connection.hpp"
#include "Node.hpp"
@@ -36,7 +37,10 @@ Connection::Connection(Port* src_port, Port* dst_port)
, _dst_port(dst_port)
, _local_buffer(NULL)
, _buffer_size(dst_port->buffer_size())
- , _must_mix( (src_port->poly() != dst_port->poly())
+ /*, _must_mix( (src_port->poly() != dst_port->poly())
+ || (src_port->buffer(0)->size() < dst_port->buffer(0)->size()) )*/
+ , _must_mix( (src_port->polyphonic() && (! dst_port->polyphonic()))
+ || (src_port->poly() != dst_port->poly() )
|| (src_port->buffer(0)->size() < dst_port->buffer(0)->size()) )
, _pending_disconnection(false)
{
@@ -75,6 +79,33 @@ Connection::set_buffer_size(size_t size)
void
+Connection::prepare_poly(uint32_t poly)
+{
+ _must_mix = (type() == DataType::FLOAT) && (poly > 1) && (
+ (_src_port->poly() != _dst_port->poly())
+ || (_src_port->polyphonic() && !_dst_port->polyphonic())
+ || (_src_port->parent()->polyphonic() && !_dst_port->parent()->polyphonic()) );
+
+ /*cerr << src_port()->path() << " * " << src_port()->poly()
+ << " -> " << dst_port()->path() << " * " << dst_port()->poly()
+ << "\t\tmust mix: " << _must_mix << " at poly " << poly << endl;*/
+
+ if (_must_mix && ! _local_buffer)
+ _local_buffer = BufferFactory::create(_dst_port->type(), _dst_port->buffer(0)->size());
+}
+
+
+void
+Connection::apply_poly(Raul::Maid& maid, uint32_t poly)
+{
+ if (poly == 1 && _local_buffer && !_must_mix) {
+ maid.push(_local_buffer);
+ _local_buffer = NULL;
+ }
+}
+
+
+void
Connection::process(SampleCount nframes, FrameTime start, FrameTime end)
{
// FIXME: nframes parameter not used
@@ -97,8 +128,8 @@ Connection::process(SampleCount nframes, FrameTime start, FrameTime end)
const size_t copy_size = std::min(src_buffer->size(), mix_buf->size());
- //cerr << "Mixing " << src_port()->buffer(0)->data()
- // << " -> " << _local_buffer->data() << endl;
+ /*cerr << "[Connection] Mixing " << src_port()->path() << " * " << src_port()->poly()
+ << " -> " << dst_port()->path() << " * " << dst_port()->poly() << endl;*/
// Copy src buffer to start of mix buffer
mix_buf->copy((AudioBuffer*)src_port()->buffer(0), 0, copy_size-1);
diff --git a/src/libs/engine/Connection.hpp b/src/libs/engine/Connection.hpp
index 816efe6c..44cbcccb 100644
--- a/src/libs/engine/Connection.hpp
+++ b/src/libs/engine/Connection.hpp
@@ -64,6 +64,8 @@ public:
inline Buffer* buffer(size_t voice) const;
void set_buffer_size(size_t size);
+ void prepare_poly(uint32_t poly);
+ void apply_poly(Raul::Maid& maid, uint32_t poly);
DataType type() const { return _src_port->type(); }
@@ -80,12 +82,13 @@ protected:
inline Buffer*
Connection::buffer(size_t voice) const
{
- if (_must_mix)
+ if (_must_mix) {
return _local_buffer;
- else if (_src_port->poly() == 1)
+ } else if ( ! _src_port->polyphonic()) {
return _src_port->buffer(0);
- else
+ } else {
return _src_port->buffer(voice);
+ }
}
diff --git a/src/libs/engine/InputPort.cpp b/src/libs/engine/InputPort.cpp
index 2d76210b..1adb53a0 100644
--- a/src/libs/engine/InputPort.cpp
+++ b/src/libs/engine/InputPort.cpp
@@ -48,32 +48,22 @@ InputPort::add_connection(Raul::ListNode<Connection*>* const c)
_connections.push_back(c);
bool modify_buffers = !_fixed_buffers;
- //if (modify_buffers && _is_tied)
- // modify_buffers = !_tied_port->fixed_buffers();
if (modify_buffers) {
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));
- //if (_is_tied)
- // _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();
- //if (_is_tied)
- // _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());
}
@@ -83,8 +73,6 @@ Raul::ListNode<Connection*>*
InputPort::remove_connection(const OutputPort* src_port)
{
bool modify_buffers = !_fixed_buffers;
- //if (modify_buffers && _is_tied)
- // modify_buffers = !_tied_port->fixed_buffers();
bool found = false;
Raul::ListNode<Connection*>* connection = NULL;
@@ -105,15 +93,11 @@ InputPort::remove_connection(const OutputPort* src_port)
if (modify_buffers)
_buffers->at(i)->unjoin();
_buffers->at(i)->clear(); // Write silence
- //if (_is_tied)
- //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));
- //if (_is_tied)
- // _tied_port->buffer(i)->join(_buffers->at(i));
}
}
}
@@ -121,9 +105,6 @@ InputPort::remove_connection(const OutputPort* src_port)
if (modify_buffers)
Port::connect_buffers();
- //assert( ! _is_tied || _tied_port != NULL);
- //assert( ! _is_tied || _buffers->at(0)->data() == _tied_port->buffer(0)->data());
-
return connection;
}
@@ -147,8 +128,6 @@ InputPort::is_connected_to(const OutputPort* port) const
void
InputPort::pre_process(SampleCount nframes, FrameTime start, FrameTime end)
{
- //assert(!_is_tied || _tied_port != NULL);
-
bool do_mixdown = true;
if (_connections.size() == 0) {
@@ -160,39 +139,31 @@ InputPort::pre_process(SampleCount nframes, FrameTime start, FrameTime end)
for (Connections::iterator c = _connections.begin(); c != _connections.end(); ++c)
(*c)->process(nframes, start, 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 (_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));
- do_mixdown = false;
- }
- connect_buffers();
- } else {
+ if ( ! _fixed_buffers) {
+ // If only one connection, try to use buffer directly (zero copy)
+ if (_connections.size() == 1) {
+ for (uint32_t i=0; i < _poly; ++i)
+ _buffers->at(i)->join((*_connections.begin())->buffer(i));
do_mixdown = false;
}
+ connect_buffers();
+ } else {
+ do_mixdown = true;
}
- //cerr << path() << " mixing: " << do_mixdown << endl;
-
for (uint32_t i=0; i < _poly; ++i)
_buffers->at(i)->prepare_read(nframes);
//cerr << path() << " poly = " << _poly << ", mixdown: " << do_mixdown << endl;
if (!do_mixdown) {
- assert(_buffers->at(0)->is_joined_to((*_connections.begin())->buffer(0)));
+#ifndef NDEBUG
+ for (uint32_t i=0; i < _poly; ++i)
+ assert(_buffers->at(i)->is_joined_to((*_connections.begin())->buffer(i)));
+#endif
return;
}
- /*assert(!_is_tied || _tied_port != NULL);
- 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
diff --git a/src/libs/engine/JackAudioDriver.cpp b/src/libs/engine/JackAudioDriver.cpp
index b9e89189..b9cbdb60 100644
--- a/src/libs/engine/JackAudioDriver.cpp
+++ b/src/libs/engine/JackAudioDriver.cpp
@@ -75,33 +75,15 @@ JackAudioPort::~JackAudioPort()
void
JackAudioPort::prepare_buffer(jack_nframes_t nframes)
{
- // FIXME: Technically this doesn't need to be done every time for output ports
- /*_jack_buffer->set_data((jack_default_audio_sample_t*)
- jack_port_get_buffer(_jack_port, nframes));
-
- _patch_port->buffer(0)->join(_jack_buffer);
-*/
jack_sample_t* jack_buf = (jack_sample_t*)jack_port_get_buffer(_jack_port, nframes);
AudioBuffer* patch_buf = (AudioBuffer*)_patch_port->buffer(0);
if (jack_buf != _jack_buffer) {
- //cerr << "Jack buffer: " << jack_buf << endl;
patch_buf->set_data(jack_buf);
_jack_buffer = jack_buf;
}
- //assert(_patch_port->tied_port() != NULL);
-
- // FIXME: fixed_buffers switch on/off thing can be removed once this
- // gets figured out and assertions can go away
- //m_patch_port->fixed_buffers(false);
- //m_patch_port->buffer(0)->join(_jack_buffer);
- //m_patch_port->tied_port()->buffer(0)->join(_jack_buffer);
-
- //m_patch_port->fixed_buffers(true);
-
- //assert(_patch_port->buffer(0)->data() == _patch_port->tied_port()->buffer(0)->data());
assert(patch_buf->data() == jack_buf);
}
diff --git a/src/libs/engine/LV2Node.cpp b/src/libs/engine/LV2Node.cpp
index 6d66f332..f1b61997 100644
--- a/src/libs/engine/LV2Node.cpp
+++ b/src/libs/engine/LV2Node.cpp
@@ -60,7 +60,7 @@ LV2Node::prepare_poly(uint32_t poly)
NodeBase::prepare_poly(poly);
- if (poly <= _prepared_instances->size())
+ if (_prepared_instances && poly <= _prepared_instances->size())
return true;
_prepared_instances = new Raul::Array<SLV2Instance>(poly, *_instances);
@@ -70,11 +70,11 @@ LV2Node::prepare_poly(uint32_t poly)
cerr << "Failed to instantiate plugin!" << endl;
return false;
}
+
+ if (_activated)
+ slv2_instance_activate((*_prepared_instances)[i]);
}
- for (uint32_t j=0; j < num_ports(); ++j)
- _ports->at(j)->prepare_poly(poly);
-
return true;
}
@@ -86,23 +86,25 @@ LV2Node::apply_poly(Raul::Maid& maid, uint32_t poly)
return true;
assert(poly <= _prepared_instances->size());
-
- NodeBase::apply_poly(maid, poly);
if (_prepared_instances) {
maid.push(_instances);
_instances = _prepared_instances;
+#if 0
for (uint32_t port=0; port < num_ports(); ++port)
- for (uint32_t voice = _polyphony; voice < _prepared_instances->size(); ++voice)
+ for (uint32_t voice = /*_polyphony*/0; voice < _prepared_instances->size(); ++voice)
slv2_instance_connect_port((*_instances)[voice], port,
_ports->at(port)->buffer(voice)->raw_data());
+#endif
_prepared_instances = NULL;
}
_polyphony = poly;
+ NodeBase::apply_poly(maid, poly);
+
return true;
}
@@ -255,13 +257,7 @@ LV2Node::set_port_buffer(uint32_t voice, uint32_t port_num, Buffer* buf)
{
assert(voice < _polyphony);
- if (buf->type() == DataType::FLOAT) {
- slv2_instance_connect_port((*_instances)[voice], port_num, ((AudioBuffer*)buf)->data());
- } else if (buf->type() == DataType::MIDI) {
- slv2_instance_connect_port((*_instances)[voice], port_num, ((MidiBuffer*)buf)->data());
- } else if (buf->type() == DataType::OSC) {
- slv2_instance_connect_port((*_instances)[voice], port_num, ((OSCBuffer*)buf)->data());
- }
+ slv2_instance_connect_port((*_instances)[voice], port_num, buf->raw_data());
}
diff --git a/src/libs/engine/MidiNoteNode.cpp b/src/libs/engine/MidiNoteNode.cpp
index 3ac33a68..a5b29f85 100644
--- a/src/libs/engine/MidiNoteNode.cpp
+++ b/src/libs/engine/MidiNoteNode.cpp
@@ -87,9 +87,10 @@ MidiNoteNode::prepare_poly(uint32_t poly)
NodeBase::prepare_poly(poly);
+ if (_prepared_voices && poly <= _prepared_voices->size())
+ return true;
+
_prepared_voices = new Raul::Array<Voice>(poly, *_voices);
-
- cerr << path() << " prepared poly " << poly << endl;
return true;
}
@@ -113,8 +114,6 @@ MidiNoteNode::apply_poly(Raul::Maid& maid, uint32_t poly)
_polyphony = poly;
assert(_voices->size() >= _polyphony);
- cerr << path() << " applied poly " << poly << endl;
-
return true;
}
@@ -219,7 +218,8 @@ MidiNoteNode::note_on(uchar note_num, uchar velocity, FrameTime time, SampleCoun
assert(voice != NULL);
assert(voice == &(*_voices)[voice_num]);
- //cerr << "[MidiNoteNode] Note on @ " << time << ". Key " << (int)note_num << ", Voice " << voice_num << endl;
+ //cerr << "[MidiNoteNode] Note " << (int)note_num << " on @ " << time
+ // << ". Voice " << voice_num << " / " << _polyphony << endl;
// Update stolen key, if applicable
if (voice->state == Voice::Voice::ACTIVE) {
@@ -300,7 +300,7 @@ MidiNoteNode::note_off(uchar note_num, FrameTime time, SampleCount nframes, Fram
void
-MidiNoteNode::free_voice(size_t voice, FrameTime time, SampleCount nframes, FrameTime start, FrameTime end)
+MidiNoteNode::free_voice(uint32_t voice, FrameTime time, SampleCount nframes, FrameTime start, FrameTime end)
{
assert(time >= start && time <= end);
assert(time - start < _buffer_size);
diff --git a/src/libs/engine/MidiNoteNode.hpp b/src/libs/engine/MidiNoteNode.hpp
index 34a926ff..f2fbbf5d 100644
--- a/src/libs/engine/MidiNoteNode.hpp
+++ b/src/libs/engine/MidiNoteNode.hpp
@@ -59,7 +59,7 @@ private:
struct Key {
enum State { OFF, ON_ASSIGNED, ON_UNASSIGNED };
Key() : state(OFF), voice(0), time(0) {}
- State state; size_t voice; SampleCount time;
+ State state; uint32_t voice; SampleCount time;
};
/** Voice, one of these always exists for each voice */
@@ -70,7 +70,7 @@ private:
};
float note_to_freq(int num);
- void free_voice(size_t voice, FrameTime time, SampleCount nframes, FrameTime start, FrameTime end);
+ void free_voice(uint32_t voice, FrameTime time, SampleCount nframes, FrameTime start, FrameTime end);
Raul::Array<Voice>* _voices;
Raul::Array<Voice>* _prepared_voices;
diff --git a/src/libs/engine/NodeBase.cpp b/src/libs/engine/NodeBase.cpp
index 90d5864f..4f3d37b2 100644
--- a/src/libs/engine/NodeBase.cpp
+++ b/src/libs/engine/NodeBase.cpp
@@ -28,7 +28,7 @@
#include "Patch.hpp"
#include "ObjectStore.hpp"
-using std::cout; using std::cerr; using std::endl;
+using namespace std;
namespace Ingen {
diff --git a/src/libs/engine/NodeFactory.cpp b/src/libs/engine/NodeFactory.cpp
index ea670ab0..fe8cf626 100644
--- a/src/libs/engine/NodeFactory.cpp
+++ b/src/libs/engine/NodeFactory.cpp
@@ -608,7 +608,7 @@ NodeFactory::load_ladspa_plugins()
for (list<Plugin*>::const_iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
if ((*i)->uri() == plugin->uri()) {
cerr << "Warning: Duplicate LADSPA plugin " << plugin->uri()
- << " found.\nChoosing " << (*i)->lib_path()
+ << " found.\n Choosing " << (*i)->lib_path()
<< " over " << plugin->lib_path() << endl;
found = true;
break;
diff --git a/src/libs/engine/Patch.cpp b/src/libs/engine/Patch.cpp
index 3d8e7756..2705db36 100644
--- a/src/libs/engine/Patch.cpp
+++ b/src/libs/engine/Patch.cpp
@@ -115,6 +115,9 @@ Patch::prepare_internal_poly(uint32_t poly)
for (Raul::List<Node*>::iterator i = _nodes.begin(); i != _nodes.end(); ++i)
(*i)->prepare_poly(poly);
+
+ for (Raul::List<Connection*>::iterator i = _connections.begin(); i != _connections.end(); ++i)
+ (*i)->prepare_poly(poly);
/* FIXME: Deal with failure */
@@ -129,6 +132,9 @@ Patch::apply_internal_poly(Raul::Maid& maid, uint32_t poly)
for (Raul::List<Node*>::iterator i = _nodes.begin(); i != _nodes.end(); ++i)
(*i)->apply_poly(maid, poly);
+
+ for (Raul::List<Connection*>::iterator i = _connections.begin(); i != _connections.end(); ++i)
+ (*i)->apply_poly(maid, poly);
_internal_poly = poly;
diff --git a/src/libs/engine/Port.cpp b/src/libs/engine/Port.cpp
index bcf47e90..30ee73f2 100644
--- a/src/libs/engine/Port.cpp
+++ b/src/libs/engine/Port.cpp
@@ -31,7 +31,7 @@ const char* const DataType::type_uris[4] = { "UNKNOWN", "FLOAT", "MIDI", "OSC" }
Port::Port(Node* const node, const string& name, uint32_t index, uint32_t poly, DataType type, size_t buffer_size)
- : GraphObject(node, name)
+ : GraphObject(node, name, true)
, _index(index)
, _poly(poly)
, _type(type)
@@ -45,6 +45,9 @@ Port::Port(Node* const node, const string& name, uint32_t index, uint32_t poly,
allocate_buffers();
clear_buffers();
+ if (node->parent() == NULL)
+ _polyphonic = false;
+
assert(_buffers->size() > 0);
}
@@ -61,6 +64,9 @@ Port::~Port()
bool
Port::prepare_poly(uint32_t poly)
{
+ if (!_polyphonic || !_parent->polyphonic())
+ return true;
+
/* FIXME: poly never goes down, harsh on memory.. */
if (poly > _poly) {
_prepared_buffers = new Raul::Array<Buffer*>(poly, *_buffers);
@@ -76,6 +82,9 @@ Port::prepare_poly(uint32_t poly)
bool
Port::apply_poly(Raul::Maid& maid, uint32_t poly)
{
+ if (!_polyphonic || !_parent->polyphonic())
+ return true;
+
assert(poly <= _prepared_poly);
// Apply a new set of buffers from a preceding call to prepare_poly
@@ -86,6 +95,8 @@ Port::apply_poly(Raul::Maid& maid, uint32_t poly)
_poly = poly;
+ connect_buffers();
+
return true;
}