diff options
Diffstat (limited to 'src/server/internals')
-rw-r--r-- | src/server/internals/BlockDelay.cpp | 89 | ||||
-rw-r--r-- | src/server/internals/BlockDelay.hpp | 62 | ||||
-rw-r--r-- | src/server/internals/Controller.cpp | 174 | ||||
-rw-r--r-- | src/server/internals/Controller.hpp | 71 | ||||
-rw-r--r-- | src/server/internals/Note.cpp | 420 | ||||
-rw-r--r-- | src/server/internals/Note.hpp | 109 | ||||
-rw-r--r-- | src/server/internals/Time.cpp | 78 | ||||
-rw-r--r-- | src/server/internals/Time.hpp | 59 | ||||
-rw-r--r-- | src/server/internals/Trigger.cpp | 187 | ||||
-rw-r--r-- | src/server/internals/Trigger.hpp | 75 |
10 files changed, 0 insertions, 1324 deletions
diff --git a/src/server/internals/BlockDelay.cpp b/src/server/internals/BlockDelay.cpp deleted file mode 100644 index 6b27ed83..00000000 --- a/src/server/internals/BlockDelay.cpp +++ /dev/null @@ -1,89 +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 <climits> - -#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 "RunContext.hpp" -#include "internals/BlockDelay.hpp" - -namespace Ingen { -namespace Server { -namespace Internals { - -InternalPlugin* BlockDelayNode::internal_plugin(URIs& uris) { - return new InternalPlugin( - uris, 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 = bufs.maid().make_managed<Ports>(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.create( - bufs.uris().atom_Sound, 0, bufs.audio_buffer_size()); - - BlockImpl::activate(bufs); -} - -void -BlockDelayNode::run(RunContext& 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 deleted file mode 100644 index e1ef5311..00000000 --- a/src/server/internals/BlockDelay.hpp +++ /dev/null @@ -1,62 +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/>. -*/ - -#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/Controller.cpp b/src/server/internals/Controller.cpp deleted file mode 100644 index 4c1cf45a..00000000 --- a/src/server/internals/Controller.cpp +++ /dev/null @@ -1,174 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2016 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 <cmath> - -#include "ingen/URIs.hpp" -#include "internals/Controller.hpp" -#include "lv2/lv2plug.in/ns/ext/atom/util.h" -#include "lv2/lv2plug.in/ns/ext/midi/midi.h" - -#include "Buffer.hpp" -#include "Engine.hpp" -#include "InputPort.hpp" -#include "InternalPlugin.hpp" -#include "OutputPort.hpp" -#include "PostProcessor.hpp" -#include "RunContext.hpp" -#include "util.hpp" - -namespace Ingen { -namespace Server { -namespace Internals { - -InternalPlugin* ControllerNode::internal_plugin(URIs& uris) { - return new InternalPlugin( - uris, URI(NS_INTERNALS "Controller"), Raul::Symbol("controller")); -} - -ControllerNode::ControllerNode(InternalPlugin* plugin, - BufferFactory& bufs, - const Raul::Symbol& symbol, - bool polyphonic, - GraphImpl* parent, - SampleRate srate) - : InternalBlock(plugin, symbol, false, parent, srate) - , _learning(false) -{ - const Ingen::URIs& uris = bufs.uris(); - _ports = bufs.maid().make_managed<Ports>(7); - - const Atom zero = bufs.forge().make(0.0f); - const Atom one = bufs.forge().make(1.0f); - const Atom atom_Float = bufs.forge().make_urid(URI(LV2_ATOM__Float)); - - _midi_in_port = new InputPort(bufs, this, Raul::Symbol("input"), 0, 1, - PortType::ATOM, uris.atom_Sequence, Atom()); - _midi_in_port->set_property(uris.lv2_name, bufs.forge().alloc("Input")); - _midi_in_port->set_property(uris.atom_supports, - bufs.forge().make_urid(uris.midi_MidiEvent)); - _ports->at(0) = _midi_in_port; - - _midi_out_port = new OutputPort(bufs, this, Raul::Symbol("event"), 1, 1, - PortType::ATOM, uris.atom_Sequence, Atom()); - _midi_out_port->set_property(uris.lv2_name, bufs.forge().alloc("Event")); - _midi_out_port->set_property(uris.atom_supports, - bufs.forge().make_urid(uris.midi_MidiEvent)); - _ports->at(1) = _midi_out_port; - - _param_port = new InputPort(bufs, this, Raul::Symbol("controller"), 2, 1, - PortType::ATOM, uris.atom_Sequence, zero); - _param_port->set_property(uris.atom_supports, atom_Float); - _param_port->set_property(uris.lv2_minimum, zero); - _param_port->set_property(uris.lv2_maximum, bufs.forge().make(127.0f)); - _param_port->set_property(uris.lv2_portProperty, uris.lv2_integer); - _param_port->set_property(uris.lv2_name, bufs.forge().alloc("Controller")); - _ports->at(2) = _param_port; - - _log_port = new InputPort(bufs, this, Raul::Symbol("logarithmic"), 3, 1, - PortType::ATOM, uris.atom_Sequence, zero); - _log_port->set_property(uris.atom_supports, atom_Float); - _log_port->set_property(uris.lv2_portProperty, uris.lv2_toggled); - _log_port->set_property(uris.lv2_name, bufs.forge().alloc("Logarithmic")); - _ports->at(3) = _log_port; - - _min_port = new InputPort(bufs, this, Raul::Symbol("minimum"), 4, 1, - PortType::ATOM, uris.atom_Sequence, zero); - _min_port->set_property(uris.atom_supports, atom_Float); - _min_port->set_property(uris.lv2_name, bufs.forge().alloc("Minimum")); - _ports->at(4) = _min_port; - - _max_port = new InputPort(bufs, this, Raul::Symbol("maximum"), 5, 1, - PortType::ATOM, uris.atom_Sequence, one); - _max_port->set_property(uris.atom_supports, atom_Float); - _max_port->set_property(uris.lv2_name, bufs.forge().alloc("Maximum")); - _ports->at(5) = _max_port; - - _audio_port = new OutputPort(bufs, this, Raul::Symbol("output"), 6, 1, - PortType::ATOM, uris.atom_Sequence, zero); - _audio_port->set_property(uris.atom_supports, atom_Float); - _audio_port->set_property(uris.lv2_name, bufs.forge().alloc("Output")); - _ports->at(6) = _audio_port; -} - -void -ControllerNode::run(RunContext& context) -{ - const BufferRef midi_in = _midi_in_port->buffer(0); - LV2_Atom_Sequence* seq = midi_in->get<LV2_Atom_Sequence>(); - const BufferRef midi_out = _midi_out_port->buffer(0); - LV2_ATOM_SEQUENCE_FOREACH(seq, ev) { - const uint8_t* buf = (const uint8_t*)LV2_ATOM_BODY(&ev->body); - if (ev->body.type == _midi_in_port->bufs().uris().midi_MidiEvent && - ev->body.size >= 3 && - lv2_midi_message_type(buf) == LV2_MIDI_MSG_CONTROLLER) { - if (control(context, buf[1], buf[2], ev->time.frames + context.start())) { - midi_out->append_event(ev->time.frames, &ev->body); - } - } - } -} - -bool -ControllerNode::control(RunContext& context, uint8_t control_num, uint8_t val, FrameTime time) -{ - assert(time >= context.start() && time <= context.end()); - const uint32_t offset = time - context.start(); - - const Sample nval = (val / 127.0f); // normalized [0, 1] - - if (_learning) { - _param_port->set_control_value(context, time, control_num); - _param_port->force_monitor_update(); - _learning = false; - } else { - _param_port->update_values(offset, 0); - } - - if (control_num != _param_port->buffer(0)->value_at(offset)) { - return false; - } - - for (const auto& port : { _min_port, _max_port, _log_port }) { - port->update_values(offset, 0); - } - - const Sample min_port_val = _min_port->buffer(0)->value_at(offset); - const Sample max_port_val = _max_port->buffer(0)->value_at(offset); - const Sample log_port_val = _log_port->buffer(0)->value_at(offset); - - Sample scaled_value; - if (log_port_val > 0.0f) { - // haaaaack, stupid negatives and logarithms - Sample log_offset = 0; - if (min_port_val < 0) { - log_offset = fabs(min_port_val); - } - const Sample min = log(min_port_val + 1 + log_offset); - const Sample max = log(max_port_val + 1 + log_offset); - scaled_value = expf(nval * (max - min) + min) - 1 - log_offset; - } else { - scaled_value = ((nval) * (max_port_val - min_port_val)) + min_port_val; - } - - _audio_port->set_control_value(context, time, scaled_value); - - return true; -} - -} // namespace Internals -} // namespace Server -} // namespace Ingen diff --git a/src/server/internals/Controller.hpp b/src/server/internals/Controller.hpp deleted file mode 100644 index 720f78c0..00000000 --- a/src/server/internals/Controller.hpp +++ /dev/null @@ -1,71 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2016 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/>. -*/ - -#ifndef INGEN_INTERNALS_CONTROLLER_HPP -#define INGEN_INTERNALS_CONTROLLER_HPP - -#include "InternalBlock.hpp" - -namespace Ingen { -namespace Server { - -class InputPort; -class OutputPort; -class InternalPlugin; - -namespace Internals { - -/** MIDI control input block. - * - * Creating one of these nodes is how a user makes "MIDI Bindings". Note that - * this node will always be monophonic, the poly parameter is ignored. - * - * \ingroup engine - */ -class ControllerNode : public InternalBlock -{ -public: - ControllerNode(InternalPlugin* plugin, - BufferFactory& bufs, - const Raul::Symbol& symbol, - bool polyphonic, - GraphImpl* parent, - SampleRate srate); - - void run(RunContext& context); - - bool control(RunContext& context, uint8_t control_num, uint8_t val, FrameTime time); - - void learn() { _learning = true; } - - static InternalPlugin* internal_plugin(URIs& uris); - -private: - InputPort* _midi_in_port; - OutputPort* _midi_out_port; - InputPort* _param_port; - InputPort* _log_port; - InputPort* _min_port; - InputPort* _max_port; - OutputPort* _audio_port; - bool _learning; -}; - -} // namespace Server -} // namespace Ingen -} // namespace Internals - -#endif // INGEN_INTERNALS_CONTROLLER_HPP diff --git a/src/server/internals/Note.cpp b/src/server/internals/Note.cpp deleted file mode 100644 index b39dd1d4..00000000 --- a/src/server/internals/Note.cpp +++ /dev/null @@ -1,420 +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 <cmath> - -#include "ingen/URIs.hpp" -#include "lv2/lv2plug.in/ns/ext/atom/util.h" -#include "lv2/lv2plug.in/ns/ext/midi/midi.h" -#include "raul/Array.hpp" -#include "raul/Maid.hpp" - -#include "Buffer.hpp" -#include "GraphImpl.hpp" -#include "InputPort.hpp" -#include "InternalPlugin.hpp" -#include "OutputPort.hpp" -#include "RunContext.hpp" -#include "ingen_config.h" -#include "internals/Note.hpp" -#include "util.hpp" - -// #define NOTE_DEBUG 1 - -namespace Ingen { -namespace Server { -namespace Internals { - -InternalPlugin* NoteNode::internal_plugin(URIs& uris) { - return new InternalPlugin( - uris, URI(NS_INTERNALS "Note"), Raul::Symbol("note")); -} - -NoteNode::NoteNode(InternalPlugin* plugin, - BufferFactory& bufs, - const Raul::Symbol& symbol, - bool polyphonic, - GraphImpl* parent, - SampleRate srate) - : InternalBlock(plugin, symbol, polyphonic, parent, srate) - , _voices(bufs.maid().make_managed<Voices>(_polyphony)) - , _sustain(false) -{ - const Ingen::URIs& uris = bufs.uris(); - _ports = bufs.maid().make_managed<Ports>(8); - - const Atom zero = bufs.forge().make(0.0f); - const Atom one = bufs.forge().make(1.0f); - - _midi_in_port = new InputPort(bufs, this, Raul::Symbol("input"), 0, 1, - PortType::ATOM, uris.atom_Sequence, Atom()); - _midi_in_port->set_property(uris.lv2_name, bufs.forge().alloc("Input")); - _midi_in_port->set_property(uris.atom_supports, - bufs.forge().make_urid(uris.midi_MidiEvent)); - _ports->at(0) = _midi_in_port; - - _freq_port = new OutputPort(bufs, this, Raul::Symbol("frequency"), 1, _polyphony, - PortType::ATOM, uris.atom_Sequence, - bufs.forge().make(440.0f)); - _freq_port->set_property(uris.atom_supports, bufs.uris().atom_Float); - _freq_port->set_property(uris.lv2_name, bufs.forge().alloc("Frequency")); - _freq_port->set_property(uris.lv2_minimum, bufs.forge().make(16.0f)); - _freq_port->set_property(uris.lv2_maximum, bufs.forge().make(25088.0f)); - _ports->at(1) = _freq_port; - - _num_port = new OutputPort(bufs, this, Raul::Symbol("number"), 1, _polyphony, - PortType::ATOM, uris.atom_Sequence, zero); - _num_port->set_property(uris.atom_supports, bufs.uris().atom_Float); - _num_port->set_property(uris.lv2_minimum, zero); - _num_port->set_property(uris.lv2_maximum, bufs.forge().make(127.0f)); - _num_port->set_property(uris.lv2_portProperty, uris.lv2_integer); - _num_port->set_property(uris.lv2_name, bufs.forge().alloc("Number")); - _ports->at(2) = _num_port; - - _vel_port = new OutputPort(bufs, this, Raul::Symbol("velocity"), 2, _polyphony, - PortType::ATOM, uris.atom_Sequence, zero); - _vel_port->set_property(uris.atom_supports, bufs.uris().atom_Float); - _vel_port->set_property(uris.lv2_minimum, zero); - _vel_port->set_property(uris.lv2_maximum, one); - _vel_port->set_property(uris.lv2_name, bufs.forge().alloc("Velocity")); - _ports->at(3) = _vel_port; - - _gate_port = new OutputPort(bufs, this, Raul::Symbol("gate"), 3, _polyphony, - PortType::ATOM, uris.atom_Sequence, zero); - _gate_port->set_property(uris.atom_supports, bufs.uris().atom_Float); - _gate_port->set_property(uris.lv2_portProperty, uris.lv2_toggled); - _gate_port->set_property(uris.lv2_name, bufs.forge().alloc("Gate")); - _ports->at(4) = _gate_port; - - _trig_port = new OutputPort(bufs, this, Raul::Symbol("trigger"), 4, _polyphony, - PortType::ATOM, uris.atom_Sequence, zero); - _trig_port->set_property(uris.atom_supports, bufs.uris().atom_Float); - _trig_port->set_property(uris.lv2_portProperty, uris.lv2_toggled); - _trig_port->set_property(uris.lv2_name, bufs.forge().alloc("Trigger")); - _ports->at(5) = _trig_port; - - _bend_port = new OutputPort(bufs, this, Raul::Symbol("bend"), 5, _polyphony, - PortType::ATOM, uris.atom_Sequence, zero); - _bend_port->set_property(uris.atom_supports, bufs.uris().atom_Float); - _bend_port->set_property(uris.lv2_name, bufs.forge().alloc("Bender")); - _bend_port->set_property(uris.lv2_default, zero); - _bend_port->set_property(uris.lv2_minimum, bufs.forge().make(-1.0f)); - _bend_port->set_property(uris.lv2_maximum, one); - _ports->at(6) = _bend_port; - - _pressure_port = new OutputPort(bufs, this, Raul::Symbol("pressure"), 6, _polyphony, - PortType::ATOM, uris.atom_Sequence, zero); - _pressure_port->set_property(uris.atom_supports, bufs.uris().atom_Float); - _pressure_port->set_property(uris.lv2_name, bufs.forge().alloc("Pressure")); - _pressure_port->set_property(uris.lv2_default, zero); - _pressure_port->set_property(uris.lv2_minimum, zero); - _pressure_port->set_property(uris.lv2_maximum, one); - _ports->at(7) = _pressure_port; -} - -bool -NoteNode::prepare_poly(BufferFactory& bufs, uint32_t poly) -{ - if (!_polyphonic) { - return true; - } - - BlockImpl::prepare_poly(bufs, poly); - - if (_prepared_voices && poly <= _prepared_voices->size()) { - return true; - } - - _prepared_voices = bufs.maid().make_managed<Voices>( - poly, *_voices, Voice()); - - return true; -} - -bool -NoteNode::apply_poly(RunContext& context, uint32_t poly) -{ - if (!BlockImpl::apply_poly(context, poly)) { - return false; - } - - if (_prepared_voices) { - assert(_polyphony <= _prepared_voices->size()); - _voices = std::move(_prepared_voices); - } - assert(_polyphony <= _voices->size()); - - return true; -} - -void -NoteNode::run(RunContext& context) -{ - Buffer* const midi_in = _midi_in_port->buffer(0).get(); - LV2_Atom_Sequence* seq = midi_in->get<LV2_Atom_Sequence>(); - LV2_ATOM_SEQUENCE_FOREACH(seq, ev) { - const uint8_t* buf = (const uint8_t*)LV2_ATOM_BODY_CONST(&ev->body); - const FrameTime time = context.start() + (FrameTime)ev->time.frames; - if (ev->body.type == _midi_in_port->bufs().uris().midi_MidiEvent && - ev->body.size >= 3) { - switch (lv2_midi_message_type(buf)) { - case LV2_MIDI_MSG_NOTE_ON: - if (buf[2] == 0) { - note_off(context, buf[1], time); - } else { - note_on(context, buf[1], buf[2], time); - } - break; - case LV2_MIDI_MSG_NOTE_OFF: - note_off(context, buf[1], time); - break; - case LV2_MIDI_MSG_CONTROLLER: - switch (buf[1]) { - case LV2_MIDI_CTL_ALL_NOTES_OFF: - case LV2_MIDI_CTL_ALL_SOUNDS_OFF: - all_notes_off(context, time); - break; - case LV2_MIDI_CTL_SUSTAIN: - if (buf[2] > 63) { - sustain_on(context, time); - } else { - sustain_off(context, time); - } - break; - } - break; - case LV2_MIDI_MSG_BENDER: - bend(context, time, (((((uint16_t)buf[2] << 7) | buf[1]) - 8192.0f) - / 8192.0f)); - break; - case LV2_MIDI_MSG_CHANNEL_PRESSURE: - channel_pressure(context, time, buf[1] / 127.0f); - break; - case LV2_MIDI_MSG_NOTE_PRESSURE: - note_pressure(context, time, buf[1], buf[2] / 127.0f); - break; - default: - break; - } - } - } -} - -static inline float -note_to_freq(uint8_t num) -{ - static const float A4 = 440.0f; - return A4 * powf(2.0f, (float)(num - 57.0f) / 12.0f); -} - -void -NoteNode::note_on(RunContext& context, uint8_t note_num, uint8_t velocity, FrameTime time) -{ - assert(time >= context.start() && time <= context.end()); - assert(note_num <= 127); - - Key* key = &_keys[note_num]; - Voice* voice = nullptr; - uint32_t voice_num = 0; - - if (key->state != Key::State::OFF) { - return; - } - - // Look for free voices - for (uint32_t i=0; i < _polyphony; ++i) { - if ((*_voices)[i].state == Voice::State::FREE) { - voice = &(*_voices)[i]; - voice_num = i; - break; - } - } - - // If we didn't find a free one, steal the oldest - if (voice == nullptr) { - voice_num = 0; - voice = &(*_voices)[0]; - FrameTime oldest_time = (*_voices)[0].time; - for (uint32_t i=1; i < _polyphony; ++i) { - if ((*_voices)[i].time < oldest_time) { - voice = &(*_voices)[i]; - voice_num = i; - oldest_time = voice->time; - } - } - } - assert(voice != nullptr); - assert(voice == &(*_voices)[voice_num]); - - // Update stolen key, if applicable - if (voice->state == Voice::State::ACTIVE) { - assert(_keys[voice->note].state == Key::State::ON_ASSIGNED); - assert(_keys[voice->note].voice == voice_num); - _keys[voice->note].state = Key::State::ON_UNASSIGNED; - } - - // Store key information for later reallocation on note off - key->state = Key::State::ON_ASSIGNED; - key->voice = voice_num; - key->time = time; - - // Check if we just triggered this voice at the same time - // (Double note-on at the same sample on the same voice) - const bool double_trigger = (voice->state == Voice::State::ACTIVE && - voice->time == time); - - // Trigger voice - voice->state = Voice::State::ACTIVE; - voice->note = note_num; - voice->time = time; - - assert(_keys[voice->note].state == Key::State::ON_ASSIGNED); - assert(_keys[voice->note].voice == voice_num); - - _freq_port->set_voice_value(context, voice_num, time, note_to_freq(note_num)); - _num_port->set_voice_value(context, voice_num, time, (float)note_num); - _vel_port->set_voice_value(context, voice_num, time, velocity / 127.0f); - _gate_port->set_voice_value(context, voice_num, time, 1.0f); - if (!double_trigger) { - _trig_port->set_voice_value(context, voice_num, time, 1.0f); - _trig_port->set_voice_value(context, voice_num, time + 1, 0.0f); - } - - assert(key->state == Key::State::ON_ASSIGNED); - assert(voice->state == Voice::State::ACTIVE); - assert(key->voice == voice_num); - assert((*_voices)[key->voice].note == note_num); -} - -void -NoteNode::note_off(RunContext& context, uint8_t note_num, FrameTime time) -{ - assert(time >= context.start() && time <= context.end()); - - Key* key = &_keys[note_num]; - - if (key->state == Key::State::ON_ASSIGNED) { - // Assigned key, turn off voice and key - if ((*_voices)[key->voice].state == Voice::State::ACTIVE) { - assert((*_voices)[key->voice].note == note_num); - if ( ! _sustain) { - free_voice(context, key->voice, time); - } else { - (*_voices)[key->voice].state = Voice::State::HOLDING; - } - } - } - - key->state = Key::State::OFF; -} - -void -NoteNode::free_voice(RunContext& context, uint32_t voice, FrameTime time) -{ - assert(time >= context.start() && time <= context.end()); - - // Find a key to reassign to the freed voice (the newest, if there is one) - Key* replace_key = nullptr; - uint8_t replace_key_num = 0; - - for (uint8_t i = 0; i <= 127; ++i) { - if (_keys[i].state == Key::State::ON_UNASSIGNED) { - if (replace_key == nullptr || _keys[i].time > replace_key->time) { - replace_key = &_keys[i]; - replace_key_num = i; - } - } - } - - if (replace_key != nullptr) { // Found a key to assign to freed voice - assert(&_keys[replace_key_num] == replace_key); - assert(replace_key->state == Key::State::ON_UNASSIGNED); - - // Change the freq but leave the gate high and don't retrigger - _freq_port->set_voice_value(context, voice, time, note_to_freq(replace_key_num)); - _num_port->set_voice_value(context, voice, time, replace_key_num); - - replace_key->state = Key::State::ON_ASSIGNED; - replace_key->voice = voice; - _keys[(*_voices)[voice].note].state = Key::State::ON_UNASSIGNED; - (*_voices)[voice].note = replace_key_num; - (*_voices)[voice].state = Voice::State::ACTIVE; - } else { - // No new note for voice, deactivate (set gate low) - _gate_port->set_voice_value(context, voice, time, 0.0f); - (*_voices)[voice].state = Voice::State::FREE; - } -} - -void -NoteNode::all_notes_off(RunContext& context, FrameTime time) -{ - assert(time >= context.start() && time <= context.end()); - - // FIXME: set all keys to Key::OFF? - - for (uint32_t i = 0; i < _polyphony; ++i) { - _gate_port->set_voice_value(context, i, time, 0.0f); - (*_voices)[i].state = Voice::State::FREE; - } -} - -void -NoteNode::sustain_on(RunContext& context, FrameTime time) -{ - _sustain = true; -} - -void -NoteNode::sustain_off(RunContext& context, FrameTime time) -{ - assert(time >= context.start() && time <= context.end()); - - _sustain = false; - - for (uint32_t i=0; i < _polyphony; ++i) { - if ((*_voices)[i].state == Voice::State::HOLDING) { - free_voice(context, i, time); - } - } -} - -void -NoteNode::bend(RunContext& context, FrameTime time, float amount) -{ - _bend_port->set_control_value(context, time, amount); -} - -void -NoteNode::note_pressure(RunContext& context, FrameTime time, uint8_t note_num, float amount) -{ - for (uint32_t i=0; i < _polyphony; ++i) { - if ((*_voices)[i].state != Voice::State::FREE && (*_voices)[i].note == note_num) { - _pressure_port->set_voice_value(context, i, time, amount); - return; - } - } -} - -void -NoteNode::channel_pressure(RunContext& context, FrameTime time, float amount) -{ - _pressure_port->set_control_value(context, time, amount); -} - -} // namespace Internals -} // namespace Server -} // namespace Ingen diff --git a/src/server/internals/Note.hpp b/src/server/internals/Note.hpp deleted file mode 100644 index 1e60c130..00000000 --- a/src/server/internals/Note.hpp +++ /dev/null @@ -1,109 +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/>. -*/ - -#ifndef INGEN_INTERNALS_NOTE_HPP -#define INGEN_INTERNALS_NOTE_HPP - -#include "InternalBlock.hpp" -#include "types.hpp" - -namespace Ingen { -namespace Server { - -class InputPort; -class OutputPort; -class InternalPlugin; - -namespace Internals { - -/** MIDI note input block. - * - * For pitched instruments like keyboard, etc. - * - * \ingroup engine - */ -class NoteNode : public InternalBlock -{ -public: - NoteNode(InternalPlugin* plugin, - BufferFactory& bufs, - const Raul::Symbol& symbol, - bool polyphonic, - GraphImpl* parent, - SampleRate srate); - - bool prepare_poly(BufferFactory& bufs, uint32_t poly); - bool apply_poly(RunContext& context, uint32_t poly); - - void run(RunContext& context); - - void note_on(RunContext& context, uint8_t note_num, uint8_t velocity, FrameTime time); - void note_off(RunContext& context, uint8_t note_num, FrameTime time); - void all_notes_off(RunContext& context, FrameTime time); - - void sustain_on(RunContext& context, FrameTime time); - void sustain_off(RunContext& context, FrameTime time); - - void bend(RunContext& context, FrameTime time, float amount); - void note_pressure(RunContext& context, FrameTime time, uint8_t note_num, float amount); - void channel_pressure(RunContext& context, FrameTime time, float amount); - - static InternalPlugin* internal_plugin(URIs& uris); - -private: - /** Key, one for each key on the keyboard */ - struct Key { - enum class State { OFF, ON_ASSIGNED, ON_UNASSIGNED }; - Key() : state(State::OFF), voice(0), time(0) {} - State state; - uint32_t voice; - SampleCount time; - }; - - /** Voice, one of these always exists for each voice */ - struct Voice { - enum class State { FREE, ACTIVE, HOLDING }; - Voice() : state(State::FREE), note(0), time(0) {} - State state; - uint8_t note; - SampleCount time; - }; - - typedef Raul::Array<Voice> Voices; - - void free_voice(RunContext& context, uint32_t voice, FrameTime time); - - MPtr<Voices> _voices; - MPtr<Voices> _prepared_voices; - - Key _keys[128]; - bool _sustain; ///< Whether or not hold pedal is depressed - - InputPort* _midi_in_port; - OutputPort* _freq_port; - OutputPort* _num_port; - OutputPort* _vel_port; - OutputPort* _gate_port; - OutputPort* _trig_port; - OutputPort* _bend_port; - OutputPort* _pressure_port; -}; - -} // namespace Server -} // namespace Ingen -} // namespace Internals - -#endif // INGEN_INTERNALS_NOTE_HPP diff --git a/src/server/internals/Time.cpp b/src/server/internals/Time.cpp deleted file mode 100644 index 5474bf21..00000000 --- a/src/server/internals/Time.cpp +++ /dev/null @@ -1,78 +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 "ingen/URIs.hpp" -#include "lv2/lv2plug.in/ns/ext/atom/util.h" -#include "lv2/lv2plug.in/ns/ext/midi/midi.h" - -#include "Buffer.hpp" -#include "Driver.hpp" -#include "Engine.hpp" -#include "InternalPlugin.hpp" -#include "OutputPort.hpp" -#include "RunContext.hpp" -#include "internals/Time.hpp" -#include "util.hpp" - -namespace Ingen { -namespace Server { -namespace Internals { - -InternalPlugin* TimeNode::internal_plugin(URIs& uris) { - return new InternalPlugin( - uris, URI(NS_INTERNALS "Time"), Raul::Symbol("time")); -} - -TimeNode::TimeNode(InternalPlugin* plugin, - BufferFactory& bufs, - const Raul::Symbol& symbol, - bool polyphonic, - GraphImpl* parent, - SampleRate srate) - : InternalBlock(plugin, symbol, false, parent, srate) -{ - const Ingen::URIs& uris = bufs.uris(); - _ports = bufs.maid().make_managed<Ports>(1); - - _notify_port = new OutputPort( - bufs, this, Raul::Symbol("notify"), 0, 1, - PortType::ATOM, uris.atom_Sequence, Atom(), 1024); - _notify_port->set_property(uris.lv2_name, bufs.forge().alloc("Notify")); - _notify_port->set_property(uris.atom_supports, - bufs.forge().make_urid(uris.time_Position)); - _ports->at(0) = _notify_port; -} - -void -TimeNode::run(RunContext& context) -{ - BufferRef buf = _notify_port->buffer(0); - LV2_Atom_Sequence* seq = buf->get<LV2_Atom_Sequence>(); - - // Initialise output to the empty sequence - seq->atom.type = _notify_port->bufs().uris().atom_Sequence; - seq->atom.size = sizeof(LV2_Atom_Sequence_Body); - seq->body.unit = 0; - seq->body.pad = 0; - - // Ask the driver to append any time events for this cycle - context.engine().driver()->append_time_events( - context, *_notify_port->buffer(0)); -} - -} // namespace Internals -} // namespace Server -} // namespace Ingen diff --git a/src/server/internals/Time.hpp b/src/server/internals/Time.hpp deleted file mode 100644 index 1a063f8d..00000000 --- a/src/server/internals/Time.hpp +++ /dev/null @@ -1,59 +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/>. -*/ - -#ifndef INGEN_INTERNALS_TIME_HPP -#define INGEN_INTERNALS_TIME_HPP - -#include "InternalBlock.hpp" - -namespace Ingen { -namespace Server { - -class InputPort; -class OutputPort; -class InternalPlugin; - -namespace Internals { - -/** Time information block. - * - * This sends messages whenever the transport speed or tempo changes. - * - * \ingroup engine - */ -class TimeNode : public InternalBlock -{ -public: - TimeNode(InternalPlugin* plugin, - BufferFactory& bufs, - const Raul::Symbol& symbol, - bool polyphonic, - GraphImpl* parent, - SampleRate srate); - - void run(RunContext& context); - - static InternalPlugin* internal_plugin(URIs& uris); - -private: - OutputPort* _notify_port; -}; - -} // namespace Server -} // namespace Ingen -} // namespace Internals - -#endif // INGEN_INTERNALS_TIME_HPP diff --git a/src/server/internals/Trigger.cpp b/src/server/internals/Trigger.cpp deleted file mode 100644 index 69967877..00000000 --- a/src/server/internals/Trigger.cpp +++ /dev/null @@ -1,187 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2016 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 <cmath> - -#include "ingen/URIs.hpp" -#include "lv2/lv2plug.in/ns/ext/atom/util.h" -#include "lv2/lv2plug.in/ns/ext/midi/midi.h" - -#include "Buffer.hpp" -#include "Engine.hpp" -#include "InputPort.hpp" -#include "InternalPlugin.hpp" -#include "OutputPort.hpp" -#include "RunContext.hpp" -#include "ingen_config.h" -#include "internals/Trigger.hpp" -#include "util.hpp" - -namespace Ingen { -namespace Server { -namespace Internals { - -InternalPlugin* TriggerNode::internal_plugin(URIs& uris) { - return new InternalPlugin( - uris, URI(NS_INTERNALS "Trigger"), Raul::Symbol("trigger")); -} - -TriggerNode::TriggerNode(InternalPlugin* plugin, - BufferFactory& bufs, - const Raul::Symbol& symbol, - bool polyphonic, - GraphImpl* parent, - SampleRate srate) - : InternalBlock(plugin, symbol, false, parent, srate) - , _learning(false) -{ - const Ingen::URIs& uris = bufs.uris(); - _ports = bufs.maid().make_managed<Ports>(6); - - const Atom zero = bufs.forge().make(0.0f); - - _midi_in_port = new InputPort(bufs, this, Raul::Symbol("input"), 0, 1, - PortType::ATOM, uris.atom_Sequence, Atom()); - _midi_in_port->set_property(uris.lv2_name, bufs.forge().alloc("Input")); - _midi_in_port->set_property(uris.atom_supports, - bufs.forge().make_urid(uris.midi_MidiEvent)); - _ports->at(0) = _midi_in_port; - - _midi_out_port = new OutputPort(bufs, this, Raul::Symbol("event"), 1, 1, - PortType::ATOM, uris.atom_Sequence, Atom()); - _midi_out_port->set_property(uris.lv2_name, bufs.forge().alloc("Event")); - _midi_out_port->set_property(uris.atom_supports, - bufs.forge().make_urid(uris.midi_MidiEvent)); - _ports->at(1) = _midi_out_port; - - _note_port = new InputPort(bufs, this, Raul::Symbol("note"), 2, 1, - PortType::ATOM, uris.atom_Sequence, - bufs.forge().make(60.0f)); - _note_port->set_property(uris.atom_supports, bufs.uris().atom_Float); - _note_port->set_property(uris.lv2_minimum, zero); - _note_port->set_property(uris.lv2_maximum, bufs.forge().make(127.0f)); - _note_port->set_property(uris.lv2_portProperty, uris.lv2_integer); - _note_port->set_property(uris.lv2_name, bufs.forge().alloc("Note")); - _ports->at(2) = _note_port; - - _gate_port = new OutputPort(bufs, this, Raul::Symbol("gate"), 3, 1, - PortType::ATOM, uris.atom_Sequence, zero); - _gate_port->set_property(uris.atom_supports, bufs.uris().atom_Float); - _gate_port->set_property(uris.lv2_portProperty, uris.lv2_toggled); - _gate_port->set_property(uris.lv2_name, bufs.forge().alloc("Gate")); - _ports->at(3) = _gate_port; - - _trig_port = new OutputPort(bufs, this, Raul::Symbol("trigger"), 4, 1, - PortType::ATOM, uris.atom_Sequence, zero); - _trig_port->set_property(uris.atom_supports, bufs.uris().atom_Float); - _trig_port->set_property(uris.lv2_portProperty, uris.lv2_toggled); - _trig_port->set_property(uris.lv2_name, bufs.forge().alloc("Trigger")); - _ports->at(4) = _trig_port; - - _vel_port = new OutputPort(bufs, this, Raul::Symbol("velocity"), 5, 1, - PortType::ATOM, uris.atom_Sequence, zero); - _vel_port->set_property(uris.atom_supports, bufs.uris().atom_Float); - _vel_port->set_property(uris.lv2_minimum, zero); - _vel_port->set_property(uris.lv2_maximum, bufs.forge().make(1.0f)); - _vel_port->set_property(uris.lv2_name, bufs.forge().alloc("Velocity")); - _ports->at(5) = _vel_port; -} - -void -TriggerNode::run(RunContext& context) -{ - const BufferRef midi_in = _midi_in_port->buffer(0); - LV2_Atom_Sequence* const seq = midi_in->get<LV2_Atom_Sequence>(); - const BufferRef midi_out = _midi_out_port->buffer(0); - - // Initialise output to the empty sequence - midi_out->prepare_write(context); - - LV2_ATOM_SEQUENCE_FOREACH(seq, ev) { - const int64_t t = ev->time.frames; - const uint8_t* buf = (const uint8_t*)LV2_ATOM_BODY(&ev->body); - bool emit = false; - if (ev->body.type == _midi_in_port->bufs().uris().midi_MidiEvent && - ev->body.size >= 3) { - const FrameTime time = context.start() + t; - switch (lv2_midi_message_type(buf)) { - case LV2_MIDI_MSG_NOTE_ON: - if (buf[2] == 0) { - emit = note_off(context, buf[1], time); - } else { - emit = note_on(context, buf[1], buf[2], time); - } - break; - case LV2_MIDI_MSG_NOTE_OFF: - emit = note_off(context, buf[1], time); - break; - case LV2_MIDI_MSG_CONTROLLER: - switch (buf[1]) { - case LV2_MIDI_CTL_ALL_NOTES_OFF: - case LV2_MIDI_CTL_ALL_SOUNDS_OFF: - _gate_port->set_control_value(context, time, 0.0f); - emit = true; - } - default: - break; - } - } - - if (emit) { - midi_out->append_event(t, &ev->body); - } - } -} - -bool -TriggerNode::note_on(RunContext& context, uint8_t note_num, uint8_t velocity, FrameTime time) -{ - assert(time >= context.start() && time <= context.end()); - const uint32_t offset = time - context.start(); - - if (_learning) { - _note_port->set_control_value(context, time, (float)note_num); - _note_port->force_monitor_update(); - _learning = false; - } - - if (note_num == lrintf(_note_port->buffer(0)->value_at(offset))) { - _gate_port->set_control_value(context, time, 1.0f); - _trig_port->set_control_value(context, time, 1.0f); - _trig_port->set_control_value(context, time + 1, 0.0f); - _vel_port->set_control_value(context, time, velocity / 127.0f); - return true; - } - return false; -} - -bool -TriggerNode::note_off(RunContext& context, uint8_t note_num, FrameTime time) -{ - assert(time >= context.start() && time <= context.end()); - const uint32_t offset = time - context.start(); - - if (note_num == lrintf(_note_port->buffer(0)->value_at(offset))) { - _gate_port->set_control_value(context, time, 0.0f); - return true; - } - - return false; -} - -} // namespace Internals -} // namespace Server -} // namespace Ingen diff --git a/src/server/internals/Trigger.hpp b/src/server/internals/Trigger.hpp deleted file mode 100644 index 4d67395a..00000000 --- a/src/server/internals/Trigger.hpp +++ /dev/null @@ -1,75 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2016 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/>. -*/ - -#ifndef INGEN_INTERNALS_TRIGGER_HPP -#define INGEN_INTERNALS_TRIGGER_HPP - -#include "InternalBlock.hpp" - -namespace Ingen { -namespace Server { - -class InputPort; -class OutputPort; -class InternalPlugin; - -namespace Internals { - -/** MIDI trigger input block. - * - * Just has a gate, for drums etc. A control port is used to select - * which note number is responded to. - * - * Note that this block is always monophonic, the poly parameter is ignored. - * (Should that change?) - * - * \ingroup engine - */ -class TriggerNode : public InternalBlock -{ -public: - TriggerNode(InternalPlugin* plugin, - BufferFactory& bufs, - const Raul::Symbol& symbol, - bool polyphonic, - GraphImpl* parent, - SampleRate srate); - - void run(RunContext& context); - - bool note_on(RunContext& context, uint8_t note_num, uint8_t velocity, FrameTime time); - bool note_off(RunContext& context, uint8_t note_num, FrameTime time); - - void learn() { _learning = true; } - - static InternalPlugin* internal_plugin(URIs& uris); - -private: - bool _learning; - - InputPort* _midi_in_port; - OutputPort* _midi_out_port; - InputPort* _note_port; - OutputPort* _gate_port; - OutputPort* _trig_port; - OutputPort* _vel_port; -}; - -} // namespace Server -} // namespace Ingen -} // namespace Internals - -#endif // INGEN_INTERNALS_TRIGGER_HPP |