From a7d83f19b08eb4c6f79a82fe60c2b86db13f4420 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sat, 24 Nov 2018 13:44:03 +0100 Subject: Squashed 'waflib/' changes from 6e726eb1..5ea8f99f 5ea8f99f Improve test output spacing 0e23b29f Raise exception when test suite fails to ensure non-zero exit status d6de073b Show run time of unit tests 5b655541 Add short configure option for ultra-strict flags 4687ba6d Use gtest-like test output 258903d9 Fix failure count in test group summaries da07e738 Fix verbose tests with Python 3 git-subtree-dir: waflib git-subtree-split: 5ea8f99f6e1246079c1fe6bb590c38a53aadd40d --- src/server/internals/Note.cpp | 420 ------------------------------------------ 1 file changed, 420 deletions(-) delete mode 100644 src/server/internals/Note.cpp (limited to 'src/server/internals/Note.cpp') 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 - - 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 "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(_polyphony)) - , _sustain(false) -{ - const Ingen::URIs& uris = bufs.uris(); - _ports = bufs.maid().make_managed(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( - 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_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 -- cgit v1.2.1