125 lines
3.6 KiB
C++
125 lines
3.6 KiB
C++
/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
|
|
*
|
|
* Om is free software; you can redistribute it and/or modify it under the
|
|
* terms of the GNU General Public License as published by the Free Software
|
|
* Foundation; either version 2 of the License, or (at your option) any later
|
|
* version.
|
|
*
|
|
* Om 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 General Public License for details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
#include "MidiTriggerNode.h"
|
|
#include <cmath>
|
|
#include "InputPort.h"
|
|
#include "OutputPort.h"
|
|
#include "PortInfo.h"
|
|
#include "Plugin.h"
|
|
#include "util.h"
|
|
#include "midi.h"
|
|
|
|
namespace Om {
|
|
|
|
|
|
MidiTriggerNode::MidiTriggerNode(const string& path, size_t poly, Patch* parent, samplerate srate, size_t buffer_size)
|
|
: InternalNode(path, 1, parent, srate, buffer_size)
|
|
{
|
|
m_num_ports = 5;
|
|
m_ports.alloc(m_num_ports);
|
|
|
|
m_midi_in_port = new InputPort<MidiMessage>(this, "MIDI In", 0, 1,
|
|
new PortInfo("MIDI In", MIDI, INPUT), m_buffer_size);
|
|
m_ports.at(0) = m_midi_in_port;
|
|
|
|
m_note_port = new InputPort<sample>(this, "Note Number", 1, 1,
|
|
new PortInfo("Note Number", CONTROL, INPUT, INTEGER, 60, 0, 127), 1);
|
|
m_ports.at(1) = m_note_port;
|
|
|
|
m_gate_port = new OutputPort<sample>(this, "Gate", 2, 1,
|
|
new PortInfo("Gate", AUDIO, OUTPUT, 0, 0, 1), m_buffer_size);
|
|
m_ports.at(2) = m_gate_port;
|
|
|
|
m_trig_port = new OutputPort<sample>(this, "Trigger", 3, 1,
|
|
new PortInfo("Trigger", AUDIO, OUTPUT, 0, 0, 1), m_buffer_size);
|
|
m_ports.at(3) = m_trig_port;
|
|
|
|
m_vel_port = new OutputPort<sample>(this, "Velocity", 4, poly,
|
|
new PortInfo("Velocity", AUDIO, OUTPUT, 0, 0, 1), m_buffer_size);
|
|
m_ports.at(4) = m_vel_port;
|
|
|
|
m_plugin.type(Plugin::Internal);
|
|
m_plugin.plug_label("trigger_in");
|
|
m_plugin.name("Om Trigger Node (MIDI, OSC)");
|
|
}
|
|
|
|
|
|
void
|
|
MidiTriggerNode::run(size_t nframes)
|
|
{
|
|
InternalNode::run(nframes);
|
|
|
|
MidiMessage ev;
|
|
|
|
for (size_t i=0; i < m_midi_in_port->buffer(0)->filled_size(); ++i) {
|
|
ev = m_midi_in_port->buffer(0)->value_at(i);
|
|
|
|
switch (ev.buffer[0] & 0xF0) {
|
|
case MIDI_CMD_NOTE_ON:
|
|
if (ev.buffer[2] == 0)
|
|
note_off(ev.buffer[1], ev.time);
|
|
else
|
|
note_on(ev.buffer[1], ev.buffer[2], ev.time);
|
|
break;
|
|
case MIDI_CMD_NOTE_OFF:
|
|
note_off(ev.buffer[1], ev.time);
|
|
break;
|
|
case MIDI_CMD_CONTROL:
|
|
if (ev.buffer[1] == MIDI_CTL_ALL_NOTES_OFF
|
|
|| ev.buffer[1] == MIDI_CTL_ALL_SOUNDS_OFF)
|
|
m_gate_port->buffer(0)->set(0.0f, ev.time);
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
MidiTriggerNode::note_on(uchar note_num, uchar velocity, samplecount offset)
|
|
{
|
|
//std::cerr << "Note on starting at sample " << offset << std::endl;
|
|
assert(offset < m_buffer_size);
|
|
|
|
const sample filter_note = m_note_port->buffer(0)->value_at(0);
|
|
if (filter_note >= 0.0 && filter_note < 127.0 && (note_num == (uchar)filter_note)){
|
|
|
|
// See comments in MidiNoteNode::note_on (FIXME)
|
|
if (offset == (samplecount)(m_buffer_size-1))
|
|
--offset;
|
|
|
|
m_gate_port->buffer(0)->set(1.0f, offset);
|
|
m_trig_port->buffer(0)->set(1.0f, offset, offset);
|
|
m_trig_port->buffer(0)->set(0.0f, offset+1);
|
|
m_vel_port->buffer(0)->set(velocity/127.0f, offset);
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
MidiTriggerNode::note_off(uchar note_num, samplecount offset)
|
|
{
|
|
assert(offset < m_buffer_size);
|
|
|
|
if (note_num == lrintf(m_note_port->buffer(0)->value_at(0)))
|
|
m_gate_port->buffer(0)->set(0.0f, offset);
|
|
}
|
|
|
|
|
|
} // namespace Om
|
|
|