diff options
author | David Robillard <d@drobilla.net> | 2015-11-14 18:47:19 -0500 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2016-10-02 12:24:56 -0400 |
commit | a077166ec6c31ad4aaab738b9dffc139bf3a4d50 (patch) | |
tree | 8e32e8003bebe0d879b1f9879f3e88c90b9d1b26 /src/server/internals | |
parent | c73c877f8bd09e0d5a6663ea5ba32a54465f5376 (diff) | |
download | ingen-a077166ec6c31ad4aaab738b9dffc139bf3a4d50.tar.gz ingen-a077166ec6c31ad4aaab738b9dffc139bf3a4d50.tar.bz2 ingen-a077166ec6c31ad4aaab738b9dffc139bf3a4d50.zip |
Replace Delay internal with simpler BlockDelay
Diffstat (limited to 'src/server/internals')
-rw-r--r-- | src/server/internals/BlockDelay.cpp | 89 | ||||
-rw-r--r-- | src/server/internals/BlockDelay.hpp (renamed from src/server/internals/Delay.hpp) | 37 | ||||
-rw-r--r-- | src/server/internals/Delay.cpp | 205 |
3 files changed, 102 insertions, 229 deletions
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 <http://drobilla.net/> + + 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 <http://www.gnu.org/licenses/>. +*/ + +#include <limits.h> + +#include <cmath> + +#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<PortImpl*>(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/Delay.hpp b/src/server/internals/BlockDelay.hpp index 0dc5da30..e1ef5311 100644 --- a/src/server/internals/Delay.hpp +++ b/src/server/internals/BlockDelay.hpp @@ -14,11 +14,10 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef INGEN_INTERNALS_DELAY_HPP -#define INGEN_INTERNALS_DELAY_HPP - -#include <math.h> +#ifndef INGEN_INTERNALS_BLOCKDELAY_HPP +#define INGEN_INTERNALS_BLOCKDELAY_HPP +#include "BufferRef.hpp" #include "InternalBlock.hpp" #include "types.hpp" @@ -32,17 +31,17 @@ class BufferFactory; namespace Internals { -class DelayNode : public InternalBlock +class BlockDelayNode : public InternalBlock { public: - DelayNode(InternalPlugin* plugin, - BufferFactory& bufs, - const Raul::Symbol& symbol, - bool polyphonic, - GraphImpl* parent, - SampleRate srate); + BlockDelayNode(InternalPlugin* plugin, + BufferFactory& bufs, + const Raul::Symbol& symbol, + bool polyphonic, + GraphImpl* parent, + SampleRate srate); - ~DelayNode(); + ~BlockDelayNode(); void activate(BufferFactory& bufs); @@ -50,24 +49,14 @@ public: 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; + BufferRef _buffer; }; } // namespace Server } // namespace Ingen } // namespace Internals -#endif // INGEN_INTERNALS_DELAY_HPP +#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 <http://drobilla.net/> - - 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 <http://www.gnu.org/licenses/>. -*/ - -#include <limits.h> - -#include <cmath> - -#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<PortImpl*>(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 |