diff options
Diffstat (limited to 'src/engine/MachineBuilder.cpp')
-rw-r--r-- | src/engine/MachineBuilder.cpp | 72 |
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()); |