aboutsummaryrefslogtreecommitdiffstats
path: root/src/engine/MachineBuilder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/engine/MachineBuilder.cpp')
-rw-r--r--src/engine/MachineBuilder.cpp72
1 files changed, 44 insertions, 28 deletions
diff --git a/src/engine/MachineBuilder.cpp b/src/engine/MachineBuilder.cpp
index d94e2da..566944e 100644
--- a/src/engine/MachineBuilder.cpp
+++ b/src/engine/MachineBuilder.cpp
@@ -37,6 +37,7 @@ MachineBuilder::MachineBuilder(SPtr<Machine> machine, double q, bool step)
, _initial_node(machine->initial_node()) // duration 0
, _connect_node(_initial_node)
, _connect_node_end_time(_time) // = 0
+ , _step_duration(machine->time().unit(), 1, 0)
, _step(step)
{}
@@ -51,7 +52,9 @@ MachineBuilder::reset()
bool
MachineBuilder::is_delay_node(SPtr<Node> node) const
{
- return !node->enter_action() && !node->exit_action();
+ return node != _initial_node &&
+ !node->enter_action() &&
+ !node->exit_action();
}
/** Set the duration of a node, with quantization.
@@ -61,7 +64,7 @@ MachineBuilder::set_node_duration(SPtr<Node> node,
Raul::TimeDuration d) const
{
if (_step) {
- node->set_duration(TimeStamp(d.unit(), 1, 0));
+ node->set_duration(_step_duration);
return;
}
@@ -85,10 +88,10 @@ MachineBuilder::connect_nodes(SPtr<Machine> m,
SPtr<Node> head,
Raul::TimeStamp head_start_time)
{
- assert(tail != head);
- assert(head_start_time >= tail_end_time);
-
SPtr<Node> delay_node;
+ if (tail == head) {
+ return delay_node;
+ }
if (is_delay_node(tail) && tail->edges().empty()) {
// Tail is a delay node, just accumulate the time difference into it
@@ -112,9 +115,22 @@ MachineBuilder::connect_nodes(SPtr<Machine> m,
void
MachineBuilder::note_on(Raul::TimeStamp t, size_t ev_size, uint8_t* buf)
{
- SPtr<Node> node(new Node(TimeStamp(t.unit())));
+ SPtr<Node> node;
+ if (_step && _poly_nodes.empty() && is_delay_node(_connect_node)) {
+ /* Stepping and the connect node is the merge node after a polyphonic
+ group. Re-use it to avoid creating delay nodes in step mode. */
+ node = _connect_node;
+ node->set_duration(_step_duration);
+ } else {
+ node = SPtr<Node>(new Node(default_duration()));
+ }
+
node->set_enter_action(SPtr<Action>(new MidiAction(ev_size, buf)));
+ if (_step && _poly_nodes.empty()) {
+ t = _time = _time + _step_duration; // Advance time one step
+ }
+
SPtr<Node> this_connect_node;
Raul::TimeStamp this_connect_node_end_time(t.unit());
@@ -151,25 +167,27 @@ MachineBuilder::note_on(Raul::TimeStamp t, size_t ev_size, uint8_t* buf)
}
void
-MachineBuilder::resolve_note(Raul::TimeStamp t,
+MachineBuilder::resolve_note(Raul::TimeStamp time,
size_t ev_size,
uint8_t* buf,
SPtr<Node> resolved)
{
- resolved->set_exit_action(
- SPtr<Action>(new MidiAction(ev_size, buf)));
- set_node_duration(resolved, t - resolved->enter_time());
+ resolved->set_exit_action(SPtr<Action>(new MidiAction(ev_size, buf)));
if (_active_nodes.size() == 1) {
+ if (_step) {
+ time = _time = _time + _step_duration;
+ }
+
// Last active note
- _connect_node_end_time = t;
+ _connect_node_end_time = time;
if (!_poly_nodes.empty()) {
// Finish a polyphonic section
- _connect_node = SPtr<Node>(new Node(TimeStamp(t.unit())));
+ _connect_node = SPtr<Node>(new Node(TimeStamp(_time.unit(), 0, 0)));
_machine->add_node(_connect_node);
- connect_nodes(_machine, resolved, t, _connect_node, t);
+ connect_nodes(_machine, resolved, time, _connect_node, time);
for (PolyList::iterator j = _poly_nodes.begin();
j != _poly_nodes.end(); ++j) {
@@ -177,7 +195,7 @@ MachineBuilder::resolve_note(Raul::TimeStamp t,
if (j->second->edges().empty()) {
connect_nodes(_machine, j->second,
j->first + j->second->duration(),
- _connect_node, t);
+ _connect_node, time);
}
}
_poly_nodes.clear();
@@ -193,7 +211,6 @@ MachineBuilder::resolve_note(Raul::TimeStamp t,
// 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(SPtr<Action>());
@@ -209,30 +226,32 @@ MachineBuilder::resolve_note(Raul::TimeStamp t,
}
} else {
- // Polyphonic, add this state to poly list
+ // Polyphonic, add this node to poly list
_poly_nodes.push_back(make_pair(resolved->enter_time(), resolved));
_connect_node = resolved;
- _connect_node_end_time = t;
+ _connect_node_end_time = _time;
}
if (resolved->is_active()) {
- resolved->exit(NULL, t);
+ resolved->exit(NULL, _time);
}
}
void
-MachineBuilder::event(Raul::TimeStamp time_offset,
+MachineBuilder::event(Raul::TimeStamp time,
size_t ev_size,
uint8_t* buf)
{
- Raul::TimeStamp t = _time + time_offset;
-
if (ev_size == 0) {
return;
}
+ if (!_step) {
+ _time = time;
+ }
+
if ((buf[0] & 0xF0) == LV2_MIDI_MSG_NOTE_ON) {
- note_on(t, ev_size, buf);
+ note_on(time, 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) {
@@ -249,7 +268,7 @@ MachineBuilder::event(Raul::TimeStamp time_offset,
(ev[0] & 0x0F) == (buf[0] & 0x0F) &&
ev[1] == buf[1]) {
// Same channel and note as on event
- resolve_note(t, ev_size, buf, *i);
+ resolve_note(time, ev_size, buf, *i);
_active_nodes.erase(i);
break;
}
@@ -277,11 +296,8 @@ MachineBuilder::resolve()
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
- };
+ uint8_t st((LV2_MIDI_MSG_NOTE_OFF & 0xF0) | (ev[0] & 0x0F));
+ const uint8_t note_off[3] = { st, ev[1], 0x40 };
(*i)->set_exit_action(
SPtr<Action>(new MidiAction(3, note_off)));
set_node_duration((*i), _time - (*i)->enter_time());