From a513af4218d0a62a45960d04ff6ddeecb8d3d4f5 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sun, 2 Oct 2016 23:56:47 -0400 Subject: Add event outputs to Trigger and Controller --- src/server/internals/Trigger.cpp | 72 ++++++++++++++++++++++++++++------------ 1 file changed, 50 insertions(+), 22 deletions(-) (limited to 'src/server/internals/Trigger.cpp') diff --git a/src/server/internals/Trigger.cpp b/src/server/internals/Trigger.cpp index 49a3a2ed..dc703271 100644 --- a/src/server/internals/Trigger.cpp +++ b/src/server/internals/Trigger.cpp @@ -1,6 +1,6 @@ /* This file is part of Ingen. - Copyright 2007-2015 David Robillard + Copyright 2007-2016 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 @@ -51,7 +51,7 @@ TriggerNode::TriggerNode(InternalPlugin* plugin, , _learning(false) { const Ingen::URIs& uris = bufs.uris(); - _ports = new Raul::Array(5); + _ports = new Raul::Array(6); const Atom zero = bufs.forge().make(0.0f); @@ -62,7 +62,14 @@ TriggerNode::TriggerNode(InternalPlugin* plugin, bufs.forge().make_urid(uris.midi_MidiEvent)); _ports->at(0) = _midi_in_port; - _note_port = new InputPort(bufs, this, Raul::Symbol("note"), 1, 1, + _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); @@ -70,69 +77,82 @@ TriggerNode::TriggerNode(InternalPlugin* plugin, _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(1) = _note_port; + _ports->at(2) = _note_port; - _gate_port = new OutputPort(bufs, this, Raul::Symbol("gate"), 2, 1, + _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(2) = _gate_port; + _ports->at(3) = _gate_port; - _trig_port = new OutputPort(bufs, this, Raul::Symbol("trigger"), 3, 1, + _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(3) = _trig_port; + _ports->at(4) = _trig_port; - _vel_port = new OutputPort(bufs, this, Raul::Symbol("velocity"), 4, 1, + _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(4) = _vel_port; + _ports->at(5) = _vel_port; } void TriggerNode::run(RunContext& context) { - Buffer* const midi_in = _midi_in_port->buffer(0).get(); - LV2_Atom_Sequence* seq = midi_in->get(); + const BufferRef midi_in = _midi_in_port->buffer(0); + LV2_Atom_Sequence* const seq = midi_in->get(); + 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 uint8_t* buf = (const uint8_t*)LV2_ATOM_BODY(&ev->body); + 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() + ev->time.frames; + const FrameTime time = context.start() + t; switch (lv2_midi_message_type(buf)) { case LV2_MIDI_MSG_NOTE_ON: if (buf[2] == 0) { - note_off(context, buf[1], time); + emit = note_off(context, buf[1], time); } else { - note_on(context, buf[1], buf[2], time); + emit = note_on(context, buf[1], buf[2], time); } break; case LV2_MIDI_MSG_NOTE_OFF: - note_off(context, buf[1], time); + 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); + } } } -void +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); @@ -140,22 +160,30 @@ TriggerNode::note_on(RunContext& context, uint8_t note_num, uint8_t velocity, Fr _learning = false; } - const Sample filter_note = _note_port->buffer(0)->value_at(0); - if (filter_note >= 0.0 && filter_note < 127.0 && (note_num == (uint8_t)filter_note)) { + _note_port->update_values(offset, 0); + 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; } -void +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(0))) + _note_port->update_values(offset, 0); + 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 -- cgit v1.2.1