aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/engine/MachineBuilder.cpp254
-rw-r--r--src/engine/MachineBuilder.hpp9
2 files changed, 134 insertions, 129 deletions
diff --git a/src/engine/MachineBuilder.cpp b/src/engine/MachineBuilder.cpp
index bb8f7c2..0a6dbfc 100644
--- a/src/engine/MachineBuilder.cpp
+++ b/src/engine/MachineBuilder.cpp
@@ -115,61 +115,135 @@ MachineBuilder::connect_nodes(SharedPtr<Machine> m,
}
void
-MachineBuilder::event(Raul::TimeStamp time_offset,
- size_t ev_size,
- unsigned char* buf)
+MachineBuilder::note_on(Raul::TimeStamp t, size_t ev_size, uint8_t* buf)
{
- const Raul::TimeUnit unit = time_offset.unit();
- Raul::TimeStamp t = _time + time_offset;
+ SharedPtr<Node> node(new Node(TimeStamp(t.unit())));
+ node->set_enter_action(SharedPtr<Action>(new MidiAction(ev_size, buf)));
+
+ SharedPtr<Node> this_connect_node;
+ Raul::TimeStamp this_connect_node_end_time(t.unit());
+
+ /* If currently polyphonic, use a poly node with no successors as connect
+ node, for more sensible patterns like what a human would build. */
+ if (!_poly_nodes.empty()) {
+ for (PolyList::iterator j = _poly_nodes.begin();
+ j != _poly_nodes.end(); ++j) {
+ if (j->second->edges().empty()) {
+ this_connect_node = j->second;
+ this_connect_node_end_time = j->first + j->second->duration();
+ break;
+ }
+ }
+ }
- if (ev_size == 0) {
- return;
+ /* Currently monophonic, or didn't find a poly node, so use _connect_node
+ which is maintained below on note off events. */
+ if (!this_connect_node) {
+ this_connect_node = _connect_node;
+ this_connect_node_end_time = _connect_node_end_time;
}
- if ((buf[0] & 0xF0) == LV2_MIDI_MSG_NOTE_ON) {
+ SharedPtr<Node> delay_node = connect_nodes(
+ _machine, this_connect_node, this_connect_node_end_time, node, t);
+
+ if (delay_node) {
+ _connect_node = delay_node;
+ _connect_node_end_time = t;
+ }
+
+ node->enter(NULL, t);
+ _active_nodes.push_back(node);
+}
- SharedPtr<Node> node(new Node(TimeStamp(unit)));
- node->set_enter_action(SharedPtr<Action>(new MidiAction(ev_size, buf)));
+void
+MachineBuilder::resolve_note(Raul::TimeStamp t,
+ size_t ev_size,
+ uint8_t* buf,
+ SharedPtr<Node> resolved)
+{
+ resolved->set_exit_action(
+ SharedPtr<Action>(new MidiAction(ev_size, buf)));
+ set_node_duration(resolved, t - resolved->enter_time());
- SharedPtr<Node> this_connect_node;
- Raul::TimeStamp this_connect_node_end_time(unit);
+ if (_active_nodes.size() == 1) {
+ // Last active note
+ _connect_node_end_time = t;
- // If currently polyphonic, use a poly node with no successors as connect node
- // Results in patterns closest to what a human would choose
if (!_poly_nodes.empty()) {
+ // Finish a polyphonic section
+ _connect_node = SharedPtr<Node>(new Node(TimeStamp(t.unit())));
+ _machine->add_node(_connect_node);
+
+ connect_nodes(_machine, resolved, t, _connect_node, t);
+
for (PolyList::iterator j = _poly_nodes.begin();
j != _poly_nodes.end(); ++j) {
- if (j->second->edges().empty()) {
- this_connect_node = j->second;
- this_connect_node_end_time = j->first + j->second->duration();
- break;
+ _machine->add_node(j->second);
+ if (j->second->edges().size() == 0) {
+ connect_nodes(_machine, j->second,
+ j->first + j->second->duration(),
+ _connect_node, t);
}
}
- }
+ _poly_nodes.clear();
+
+ _machine->add_node(resolved);
+
+ } else {
+ // Just monophonic
+ if (is_delay_node(_connect_node)
+ && _connect_node->duration().is_zero()
+ && (_connect_node->edges().size() == 1)
+ && ((*_connect_node->edges().begin())->head() == resolved)) {
+ // Trim useless delay node if possible (after poly sections)
+
+ _connect_node->edges().clear();
+ assert(_connect_node->edges().empty());
+ _connect_node->set_enter_action(resolved->enter_action());
+ _connect_node->set_exit_action(resolved->exit_action());
+ resolved->set_enter_action(SharedPtr<Action>());
+ resolved->set_exit_action(SharedPtr<Action>());
+ set_node_duration(_connect_node, resolved->duration());
+ resolved = _connect_node;
+ if (std::find(_machine->nodes().begin(),
+ _machine->nodes().end(),
+ _connect_node)
+ == _machine->nodes().end()) {
+ _machine->add_node(_connect_node);
+ }
- // Currently monophonic, or didn't find a poly node, so use _connect_node
- // which is maintained below on note off events.
- if (!this_connect_node) {
- this_connect_node = _connect_node;
- this_connect_node_end_time = _connect_node_end_time;
+ } else {
+ _connect_node = resolved;
+ _machine->add_node(resolved);
+ }
}
- SharedPtr<Node> delay_node = connect_nodes(_machine,
- this_connect_node,
- this_connect_node_end_time,
- node,
- t);
+ } else {
+ // Polyphonic, add this state to poly list
+ _poly_nodes.push_back(make_pair(resolved->enter_time(), resolved));
+ _connect_node = resolved;
+ _connect_node_end_time = t;
+ }
- if (delay_node) {
- _connect_node = delay_node;
- _connect_node_end_time = t;
- }
+ if (resolved->is_active()) {
+ resolved->exit(NULL, t);
+ }
+}
- node->enter(NULL, t);
- _active_nodes.push_back(node);
+void
+MachineBuilder::event(Raul::TimeStamp time_offset,
+ size_t ev_size,
+ uint8_t* buf)
+{
+ Raul::TimeStamp t = _time + time_offset;
- } else if ((buf[0] & 0xF0) == LV2_MIDI_MSG_NOTE_OFF) {
+ if (ev_size == 0) {
+ return;
+ }
+ if ((buf[0] & 0xF0) == LV2_MIDI_MSG_NOTE_ON) {
+ note_on(t, ev_size, buf);
+ } else if ((buf[0] & 0xF0) == LV2_MIDI_MSG_NOTE_OFF) {
for (ActiveList::iterator i = _active_nodes.begin();
i != _active_nodes.end(); ++i) {
SharedPtr<MidiAction> action = PtrCast<MidiAction>(
@@ -178,96 +252,18 @@ MachineBuilder::event(Raul::TimeStamp time_offset,
continue;
}
- const size_t ev_size = action->event_size();
- const unsigned char* ev = action->event();
-
- if ((ev_size == 3) && ((ev[0] & 0xF0) == LV2_MIDI_MSG_NOTE_ON)
- && ((ev[0] & 0x0F) == (buf[0] & 0x0F)) // same channel
- && (ev[1] == buf[1])) {
- // same note
- SharedPtr<Node> resolved = *i;
-
- resolved->set_exit_action(
- SharedPtr<Action>(new MidiAction(ev_size, buf)));
- set_node_duration(resolved, t - resolved->enter_time());
-
- // Last active note
- if (_active_nodes.size() == 1) {
-
- _connect_node_end_time = t;
-
- // Finish a polyphonic section
- if (!_poly_nodes.empty()) {
-
- _connect_node = SharedPtr<Node>(new Node(TimeStamp(unit)));
- _machine->add_node(_connect_node);
-
- connect_nodes(_machine, resolved, t, _connect_node, t);
-
- for (PolyList::iterator j = _poly_nodes.begin();
- j != _poly_nodes.end(); ++j) {
- _machine->add_node(j->second);
- if (j->second->edges().size() == 0) {
- connect_nodes(_machine, j->second,
- j->first + j->second->duration(),
- _connect_node, t);
- }
- }
- _poly_nodes.clear();
-
- _machine->add_node(resolved);
-
- // Just monophonic
- } else {
-
- // Trim useless delay node if possible (these appear after poly sections)
- if (is_delay_node(_connect_node)
- && _connect_node->duration().is_zero()
- && (_connect_node->edges().size() == 1)
- && ((*_connect_node->edges().begin())->head() ==
- resolved)) {
-
- _connect_node->edges().clear();
- assert(_connect_node->edges().empty());
- _connect_node->set_enter_action(
- resolved->enter_action());
- _connect_node->set_exit_action(
- resolved->exit_action());
- resolved->set_enter_action(SharedPtr<Action>());
- resolved->set_exit_action(SharedPtr<Action>());
- set_node_duration(_connect_node, resolved->duration());
- resolved = _connect_node;
- if (std::find(_machine->nodes().begin(),
- _machine->nodes().end(),
- _connect_node)
- == _machine->nodes().end()) {
- _machine->add_node(_connect_node);
- }
-
- } else {
- _connect_node = resolved;
- _machine->add_node(resolved);
- }
- }
-
- // Polyphonic, add this state to poly list
- } else {
- _poly_nodes.push_back(make_pair(resolved->enter_time(),
- resolved));
- _connect_node = resolved;
- _connect_node_end_time = t;
- }
-
- if (resolved->is_active()) {
- resolved->exit(NULL, t);
- }
+ const size_t ev_size = action->event_size();
+ const uint8_t* ev = action->event();
+ if ((ev[0] & 0xF0) == LV2_MIDI_MSG_NOTE_ON &&
+ (ev[0] & 0x0F) == (buf[0] & 0x0F) &&
+ ev[1] == buf[1]) {
+ // Same channel and note as on event
+ resolve_note(t, ev_size, buf, *i);
_active_nodes.erase(i);
-
break;
}
}
-
}
}
@@ -288,14 +284,14 @@ MachineBuilder::resolve()
continue;
}
- const size_t ev_size = action->event_size();
- const unsigned char* ev = action->event();
- if (ev_size == 3 &&
- (ev[0] & 0xF0) == LV2_MIDI_MSG_NOTE_ON) {
- unsigned char note_off[3]
- = { ((LV2_MIDI_MSG_NOTE_OFF & 0xF0) | (ev[0] & 0x0F)),
- ev[1],
- 0x40 };
+ const size_t ev_size = action->event_size();
+ const uint8_t* ev = action->event();
+ if (ev_size == 3 && (ev[0] & 0xF0) == LV2_MIDI_MSG_NOTE_ON) {
+ const uint8_t note_off[3] = {
+ ((LV2_MIDI_MSG_NOTE_OFF & 0xF0) | (ev[0] & 0x0F)),
+ ev[1],
+ 0x40
+ };
(*i)->set_exit_action(
SharedPtr<Action>(new MidiAction(3, note_off)));
set_node_duration((*i), _time - (*i)->enter_time());
diff --git a/src/engine/MachineBuilder.hpp b/src/engine/MachineBuilder.hpp
index 7bd865d..cb3ccea 100644
--- a/src/engine/MachineBuilder.hpp
+++ b/src/engine/MachineBuilder.hpp
@@ -18,6 +18,8 @@
#ifndef MACHINA_MACHINEBUILDER_HPP
#define MACHINA_MACHINEBUILDER_HPP
+#include <stdint.h>
+
#include <list>
#include "raul/SharedPtr.hpp"
@@ -48,6 +50,13 @@ private:
bool is_delay_node(SharedPtr<Node> node) const;
void set_node_duration(SharedPtr<Node> node, Raul::TimeDuration d) const;
+ void note_on(Raul::TimeStamp t, size_t ev_size, uint8_t* buf);
+
+ void resolve_note(Raul::TimeStamp t,
+ size_t ev_size,
+ uint8_t* buf,
+ SharedPtr<Node> resolved);
+
SharedPtr<Node>connect_nodes(SharedPtr<Machine> m,
SharedPtr<Node> tail,
Raul::TimeStamp tail_end_time,