From a077166ec6c31ad4aaab738b9dffc139bf3a4d50 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sat, 14 Nov 2015 18:47:19 -0500 Subject: Replace Delay internal with simpler BlockDelay --- src/server/BlockFactory.cpp | 8 +- src/server/BufferFactory.cpp | 6 ++ src/server/BufferFactory.hpp | 4 +- src/server/InternalPlugin.cpp | 8 +- src/server/internals/BlockDelay.cpp | 89 ++++++++++++++++ src/server/internals/BlockDelay.hpp | 62 +++++++++++ src/server/internals/Delay.cpp | 205 ------------------------------------ src/server/internals/Delay.hpp | 73 ------------- src/server/wscript | 2 +- 9 files changed, 169 insertions(+), 288 deletions(-) create mode 100644 src/server/internals/BlockDelay.cpp create mode 100644 src/server/internals/BlockDelay.hpp delete mode 100644 src/server/internals/Delay.cpp delete mode 100644 src/server/internals/Delay.hpp (limited to 'src/server') diff --git a/src/server/BlockFactory.cpp b/src/server/BlockFactory.cpp index b715ecb7..de7c2de2 100644 --- a/src/server/BlockFactory.cpp +++ b/src/server/BlockFactory.cpp @@ -21,8 +21,8 @@ #include "ingen/LV2Features.hpp" #include "ingen/Log.hpp" #include "ingen/World.hpp" +#include "internals/BlockDelay.hpp" #include "internals/Controller.hpp" -#include "internals/Delay.hpp" #include "internals/Note.hpp" #include "internals/Time.hpp" #include "internals/Trigger.hpp" @@ -111,12 +111,12 @@ void BlockFactory::load_internal_plugins() { Ingen::URIs& uris = _world->uris(); + InternalPlugin* block_delay_plug = BlockDelayNode::internal_plugin(uris); + _plugins.insert(make_pair(block_delay_plug->uri(), block_delay_plug)); + InternalPlugin* controller_plug = ControllerNode::internal_plugin(uris); _plugins.insert(make_pair(controller_plug->uri(), controller_plug)); - InternalPlugin* delay_plug = DelayNode::internal_plugin(uris); - _plugins.insert(make_pair(delay_plug->uri(), delay_plug)); - InternalPlugin* note_plug = NoteNode::internal_plugin(uris); _plugins.insert(make_pair(note_plug->uri(), note_plug)); diff --git a/src/server/BufferFactory.cpp b/src/server/BufferFactory.cpp index aeaa0d44..749e83d0 100644 --- a/src/server/BufferFactory.cpp +++ b/src/server/BufferFactory.cpp @@ -74,6 +74,12 @@ BufferFactory::audio_buffer_size(SampleCount nframes) return nframes * sizeof(Sample); } +uint32_t +BufferFactory::audio_buffer_size() const +{ + return _engine.driver()->block_length() * sizeof(Sample); +} + uint32_t BufferFactory::default_size(LV2_URID type) const { diff --git a/src/server/BufferFactory.hpp b/src/server/BufferFactory.hpp index 2fae3244..ccb01899 100644 --- a/src/server/BufferFactory.hpp +++ b/src/server/BufferFactory.hpp @@ -46,7 +46,9 @@ public: ~BufferFactory(); static uint32_t audio_buffer_size(SampleCount nframes); - uint32_t default_size(LV2_URID type) const; + + uint32_t audio_buffer_size() const; + uint32_t default_size(LV2_URID type) const; BufferRef get_buffer(LV2_URID type, LV2_URID value_type, diff --git a/src/server/InternalPlugin.cpp b/src/server/InternalPlugin.cpp index 075bc67d..3d065fe3 100644 --- a/src/server/InternalPlugin.cpp +++ b/src/server/InternalPlugin.cpp @@ -16,7 +16,7 @@ #include "ingen/URIs.hpp" #include "internals/Controller.hpp" -#include "internals/Delay.hpp" +#include "internals/BlockDelay.hpp" #include "internals/Note.hpp" #include "internals/Time.hpp" #include "internals/Trigger.hpp" @@ -50,10 +50,10 @@ InternalPlugin::instantiate(BufferFactory& bufs, { const SampleCount srate = engine.driver()->sample_rate(); - if (uri() == NS_INTERNALS "Controller") { + if (uri() == NS_INTERNALS "BlockDelay") { + return new BlockDelayNode(this, bufs, symbol, polyphonic, parent, srate); + } else if (uri() == NS_INTERNALS "Controller") { return new ControllerNode(this, bufs, symbol, polyphonic, parent, srate); - } else if (uri() == NS_INTERNALS "Delay") { - return new DelayNode(this, bufs, symbol, polyphonic, parent, srate); } else if (uri() == NS_INTERNALS "Note") { return new NoteNode(this, bufs, symbol, polyphonic, parent, srate); } else if (uri() == NS_INTERNALS "Time") { diff --git a/src/server/internals/BlockDelay.cpp b/src/server/internals/BlockDelay.cpp new file mode 100644 index 00000000..39bd09b9 --- /dev/null +++ b/src/server/internals/BlockDelay.cpp @@ -0,0 +1,89 @@ +/* + This file is part of Ingen. + Copyright 2007-2015 David Robillard + + Ingen is free software: you can redistribute it and/or modify it under the + terms of the GNU Affero General Public License as published by the Free + Software Foundation, either version 3 of the License, or any later version. + + Ingen is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU Affero General Public License for details. + + You should have received a copy of the GNU Affero General Public License + along with Ingen. If not, see . +*/ + +#include + +#include + +#include "ingen/URIs.hpp" +#include "raul/Array.hpp" +#include "raul/Maid.hpp" + +#include "Buffer.hpp" +#include "InputPort.hpp" +#include "InternalPlugin.hpp" +#include "OutputPort.hpp" +#include "ProcessContext.hpp" +#include "internals/BlockDelay.hpp" + +namespace Ingen { +namespace Server { +namespace Internals { + +InternalPlugin* BlockDelayNode::internal_plugin(URIs& uris) { + return new InternalPlugin( + uris, Raul::URI(NS_INTERNALS "BlockDelay"), Raul::Symbol("blockDelay")); +} + +BlockDelayNode::BlockDelayNode(InternalPlugin* plugin, + BufferFactory& bufs, + const Raul::Symbol& symbol, + bool polyphonic, + GraphImpl* parent, + SampleRate srate) + : InternalBlock(plugin, symbol, polyphonic, parent, srate) +{ + const Ingen::URIs& uris = bufs.uris(); + _ports = new Raul::Array(2); + + _in_port = new InputPort(bufs, this, Raul::Symbol("in"), 0, 1, + PortType::AUDIO, 0, bufs.forge().make(0.0f)); + _in_port->set_property(uris.lv2_name, bufs.forge().alloc("In")); + _ports->at(0) = _in_port; + + _out_port = new OutputPort(bufs, this, Raul::Symbol("out"), 0, 1, + PortType::AUDIO, 0, bufs.forge().make(0.0f)); + _out_port->set_property(uris.lv2_name, bufs.forge().alloc("Out")); + _ports->at(1) = _out_port; +} + +BlockDelayNode::~BlockDelayNode() +{ + _buffer.reset(); +} + +void +BlockDelayNode::activate(BufferFactory& bufs) +{ + _buffer = bufs.get_buffer( + bufs.uris().atom_Sound, 0, bufs.audio_buffer_size(), false, true); + + BlockImpl::activate(bufs); +} + +void +BlockDelayNode::run(ProcessContext& context) +{ + // Copy buffer from last cycle to output + _out_port->buffer(0)->copy(context, _buffer.get()); + + // Copy input from this cycle to buffer + _buffer->copy(context, _in_port->buffer(0).get()); +} + +} // namespace Internals +} // namespace Server +} // namespace Ingen diff --git a/src/server/internals/BlockDelay.hpp b/src/server/internals/BlockDelay.hpp new file mode 100644 index 00000000..e1ef5311 --- /dev/null +++ b/src/server/internals/BlockDelay.hpp @@ -0,0 +1,62 @@ +/* + This file is part of Ingen. + Copyright 2007-2015 David Robillard + + Ingen is free software: you can redistribute it and/or modify it under the + terms of the GNU Affero General Public License as published by the Free + Software Foundation, either version 3 of the License, or any later version. + + Ingen is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU Affero General Public License for details. + + You should have received a copy of the GNU Affero General Public License + along with Ingen. If not, see . +*/ + +#ifndef INGEN_INTERNALS_BLOCKDELAY_HPP +#define INGEN_INTERNALS_BLOCKDELAY_HPP + +#include "BufferRef.hpp" +#include "InternalBlock.hpp" +#include "types.hpp" + +namespace Ingen { +namespace Server { + +class InputPort; +class OutputPort; +class InternalPlugin; +class BufferFactory; + +namespace Internals { + +class BlockDelayNode : public InternalBlock +{ +public: + BlockDelayNode(InternalPlugin* plugin, + BufferFactory& bufs, + const Raul::Symbol& symbol, + bool polyphonic, + GraphImpl* parent, + SampleRate srate); + + ~BlockDelayNode(); + + void activate(BufferFactory& bufs); + + void run(RunContext& context); + + static InternalPlugin* internal_plugin(URIs& uris); + +private: + InputPort* _in_port; + OutputPort* _out_port; + BufferRef _buffer; +}; + +} // namespace Server +} // namespace Ingen +} // namespace Internals + +#endif // INGEN_INTERNALS_BLOCKDELAY_HPP diff --git a/src/server/internals/Delay.cpp b/src/server/internals/Delay.cpp deleted file mode 100644 index 6ac97008..00000000 --- a/src/server/internals/Delay.cpp +++ /dev/null @@ -1,205 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2015 David Robillard - - Ingen is free software: you can redistribute it and/or modify it under the - terms of the GNU Affero General Public License as published by the Free - Software Foundation, either version 3 of the License, or any later version. - - Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#include - -#include - -#include "ingen/URIs.hpp" -#include "raul/Array.hpp" -#include "raul/Maid.hpp" - -#include "Buffer.hpp" -#include "Driver.hpp" -#include "Engine.hpp" -#include "GraphImpl.hpp" -#include "InputPort.hpp" -#include "InternalPlugin.hpp" -#include "OutputPort.hpp" -#include "RunContext.hpp" -#include "internals/Delay.hpp" -#include "util.hpp" - -#define CALC_DELAY(delaytime) \ - (f_clamp (delaytime * (float)sample_rate, 1.0f, (float)(buffer_mask + 1))) - -using namespace std; - -namespace Ingen { -namespace Server { -namespace Internals { - -static const float MAX_DELAY_SECONDS = 8.0f; - -InternalPlugin* DelayNode::internal_plugin(URIs& uris) { - return new InternalPlugin( - uris, Raul::URI(NS_INTERNALS "Delay"), Raul::Symbol("delay")); -} - -DelayNode::DelayNode(InternalPlugin* plugin, - BufferFactory& bufs, - const Raul::Symbol& symbol, - bool polyphonic, - GraphImpl* parent, - SampleRate srate) - : InternalBlock(plugin, symbol, polyphonic, parent, srate) - , _buffer(0) - , _buffer_length(0) - , _buffer_mask(0) - , _write_phase(0) -{ - const Ingen::URIs& uris = bufs.uris(); - _ports = new Raul::Array(3); - - const float default_delay = 1.0f; - _last_delay_time = default_delay; - _delay_samples = default_delay; - - _delay_port = new InputPort(bufs, this, Raul::Symbol("delay"), 1, _polyphony, - PortType::CONTROL, 0, bufs.forge().make(default_delay)); - _delay_port->set_property(uris.lv2_name, bufs.forge().alloc("Delay")); - _delay_port->set_property(uris.lv2_default, bufs.forge().make(default_delay)); - _delay_port->set_property(uris.lv2_minimum, bufs.forge().make((float)(1.0/(double)srate))); - _delay_port->set_property(uris.lv2_maximum, bufs.forge().make(MAX_DELAY_SECONDS)); - _ports->at(0) = _delay_port; - - _in_port = new InputPort(bufs, this, Raul::Symbol("in"), 0, 1, - PortType::AUDIO, 0, bufs.forge().make(0.0f)); - _in_port->set_property(uris.lv2_name, bufs.forge().alloc("Input")); - _ports->at(1) = _in_port; - - _out_port = new OutputPort(bufs, this, Raul::Symbol("out"), 0, 1, - PortType::AUDIO, 0, bufs.forge().make(0.0f)); - _out_port->set_property(uris.lv2_name, - bufs.forge().alloc("Output")); - _ports->at(2) = _out_port; - - //_buffer = bufs.get(PortType::AUDIO, bufs.audio_buffer_size(buffer_length_frames), true); - -} - -DelayNode::~DelayNode() -{ - //_buffer.reset(); - free(_buffer); -} - -void -DelayNode::activate(BufferFactory& bufs) -{ - BlockImpl::activate(bufs); - const SampleRate rate = bufs.engine().driver()->sample_rate(); - const SampleCount min_size = MAX_DELAY_SECONDS * rate; - - // Smallest power of two larger than min_size - SampleCount size = 1; - while (size < min_size) - size <<= 1; - - _buffer = (float*)calloc(size, sizeof(float)); - _buffer_mask = size - 1; - _buffer_length = size; - //_buffer->clear(); - _write_phase = 0; -} - -static inline float f_clamp(float x, float a, float b) -{ - const float x1 = fabs(x - a); - const float x2 = fabs(x - b); - - x = x1 + a + b; - x -= x2; - x *= 0.5; - - return x; -} - -static inline float cube_interp(const float fr, const float inm1, const float - in, const float inp1, const float inp2) -{ - return in + 0.5f * fr * ( - inp1 - inm1 + fr * ( - 4.0f * inp1 + 2.0f * inm1 - 5.0f * in - inp2 + fr * ( - 3.0f * (in - inp1) - inm1 + inp2))); -} - -void -DelayNode::run(RunContext& context) -{ - Buffer* const delay_buf = _delay_port->buffer(0).get(); - Buffer* const in_buf = _in_port->buffer(0).get(); - Buffer* const out_buf = _out_port->buffer(0).get(); - - DelayNode* plugin_data = this; - - const float* const in = in_buf->samples(); - float* const out = out_buf->samples(); - const float delay_time = delay_buf->samples()[0]; - const uint32_t buffer_mask = plugin_data->_buffer_mask; - const SampleRate sample_rate = context.engine().driver()->sample_rate(); - float delay_samples = plugin_data->_delay_samples; - int64_t write_phase = plugin_data->_write_phase; - const uint32_t sample_count = context.nframes(); - - if (write_phase == 0) { - _last_delay_time = delay_time; - _delay_samples = delay_samples = CALC_DELAY(delay_time); - } - - if (delay_time == _last_delay_time) { - const int64_t idelay_samples = (int64_t)delay_samples; - const float frac = delay_samples - idelay_samples; - - for (uint32_t i = 0; i < sample_count; i++) { - int64_t read_phase = write_phase - (int64_t)delay_samples; - const float read = cube_interp(frac, - buffer_at(read_phase - 1), - buffer_at(read_phase), - buffer_at(read_phase + 1), - buffer_at(read_phase + 2)); - buffer_at(write_phase++) = in[i]; - out[i] = read; - } - } else { - const float next_delay_samples = CALC_DELAY(delay_time); - const float delay_samples_slope = (next_delay_samples - delay_samples) / sample_count; - - for (uint32_t i = 0; i < sample_count; i++) { - delay_samples += delay_samples_slope; - write_phase++; - const int64_t read_phase = write_phase - (int64_t)delay_samples; - const int64_t idelay_samples = (int64_t)delay_samples; - const float frac = delay_samples - idelay_samples; - const float read = cube_interp(frac, - buffer_at(read_phase - 1), - buffer_at(read_phase), - buffer_at(read_phase + 1), - buffer_at(read_phase + 2)); - buffer_at(write_phase) = in[i]; - out[i] = read; - } - - _last_delay_time = delay_time; - _delay_samples = delay_samples; - } - - _write_phase = write_phase; -} - -} // namespace Internals -} // namespace Server -} // namespace Ingen diff --git a/src/server/internals/Delay.hpp b/src/server/internals/Delay.hpp deleted file mode 100644 index 0dc5da30..00000000 --- a/src/server/internals/Delay.hpp +++ /dev/null @@ -1,73 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2015 David Robillard - - Ingen is free software: you can redistribute it and/or modify it under the - terms of the GNU Affero General Public License as published by the Free - Software Foundation, either version 3 of the License, or any later version. - - Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#ifndef INGEN_INTERNALS_DELAY_HPP -#define INGEN_INTERNALS_DELAY_HPP - -#include - -#include "InternalBlock.hpp" -#include "types.hpp" - -namespace Ingen { -namespace Server { - -class InputPort; -class OutputPort; -class InternalPlugin; -class BufferFactory; - -namespace Internals { - -class DelayNode : public InternalBlock -{ -public: - DelayNode(InternalPlugin* plugin, - BufferFactory& bufs, - const Raul::Symbol& symbol, - bool polyphonic, - GraphImpl* parent, - SampleRate srate); - - ~DelayNode(); - - void activate(BufferFactory& bufs); - - void run(RunContext& context); - - static InternalPlugin* internal_plugin(URIs& uris); - - float delay_samples() const { return _delay_samples; } - -private: - inline float& buffer_at(int64_t phase) const { return _buffer[phase & _buffer_mask]; } - - InputPort* _delay_port; - InputPort* _in_port; - OutputPort* _out_port; - float* _buffer; - uint32_t _buffer_length; - uint32_t _buffer_mask; - uint64_t _write_phase; - float _last_delay_time; - float _delay_samples; -}; - -} // namespace Server -} // namespace Ingen -} // namespace Internals - -#endif // INGEN_INTERNALS_DELAY_HPP diff --git a/src/server/wscript b/src/server/wscript index 6f5ffb86..8fda0b2a 100644 --- a/src/server/wscript +++ b/src/server/wscript @@ -44,8 +44,8 @@ def build(bld): events/SetPortValue.cpp events/Undo.cpp ingen_engine.cpp + internals/BlockDelay.cpp internals/Controller.cpp - internals/Delay.cpp internals/Note.cpp internals/Time.cpp internals/Trigger.cpp -- cgit v1.2.1