From: Paul Davis Date: Fri, 18 Aug 2017 16:17:46 +0000 (-0400) Subject: tweaks to the beatbox toy to properly track and connect note on/off X-Git-Tag: 6.0-pre0~16 X-Git-Url: https://main.carlh.net/gitweb/?p=ardour.git;a=commitdiff_plain;h=6176d937a99012e60233a4a6d82f2503c83b0080 tweaks to the beatbox toy to properly track and connect note on/off --- diff --git a/tools/bb/bb.cc b/tools/bb/bb.cc index 644538b49c..eb31fc0868 100644 --- a/tools/bb/bb.cc +++ b/tools/bb/bb.cc @@ -19,7 +19,7 @@ using std::cerr; using std::endl; - +using namespace ARDOUR; BeatBox::BeatBox (int sr) : _start_requested (false) @@ -174,16 +174,21 @@ BeatBox::process (int nsamples) event_pool.push_back (*ee); } _current_events.clear (); + _incomplete_notes.clear (); clear_pending = false; } + framepos_t last_output_time = 0; + for (Events::iterator ee = _current_events.begin(); ee != _current_events.end(); ++ee) { Event* e = (*ee); if (e->size && (e->time >= process_start && e->time < process_end)) { - if ((buffer = jack_midi_event_reserve (out_buf, superclock_to_samples (offset + e->time - process_start, _sample_rate), e->size)) != 0) { + framepos_t sample_offset_in_buffer = superclock_to_samples (offset + e->time - process_start, _sample_rate); + if ((buffer = jack_midi_event_reserve (out_buf, sample_offset_in_buffer, e->size)) != 0) { memcpy (buffer, e->buf, e->size); outbound_tracker.track (e->buf); + last_output_time = sample_offset_in_buffer; } else { cerr << "Could not reserve space for output event @ " << e << " of size " << e->size << " @ " << offset + e->time - process_start << " (samples: " << superclock_to_samples (offset + e->time - process_start, _sample_rate) << ") offset is " << offset @@ -201,6 +206,8 @@ BeatBox::process (int nsamples) in_buf = jack_port_get_buffer (_input, nsamples); event_index = 0; + Events::iterator loop_iterator; + while (jack_midi_event_get (&in_event, in_buf, event_index++) == 0) { superclock_t event_time = superclock_cnt + samples_to_superclock (in_event.time, _sample_rate); @@ -211,7 +218,7 @@ BeatBox::process (int nsamples) if (_quantize_divisor != 0) { const superclock_t time_per_grid_unit = whole_note_superclocks / _quantize_divisor; - if (in_event.buffer[0] == MIDI_CMD_NOTE_OFF) { + if ((in_event.buffer[0] & 0xf) == MIDI_CMD_NOTE_OFF) { /* note off is special - it must be quantized * to at least 1 quantization "spacing" after @@ -224,18 +231,22 @@ BeatBox::process (int nsamples) /* look for the note on */ - for (Events::iterator ee = _current_events.begin(); ee != _current_events.end(); ++ee) { - /* is it a note-on? same note? same channel? */ - if ((*ee)->time > quantized_time) { - cerr << "Note off seen without corresponding note on!\n"; - /* leave quantized_time alone ... should probably dump the whole event */ - break; - } + IncompleteNotes::iterator ee; - if (((*ee)->buf[0] == MIDI_CMD_NOTE_ON) && ((*ee)->buf[1] == in_event.buffer[1]) && ((*ee)->buf[0] & 0xf) == (in_event.buffer[0] & 0xf)) { + for (ee = _incomplete_notes.begin(); ee != _incomplete_notes.end(); ++ee) { + /* check for same note and channel */ + if (((*ee)->buf[1] == in_event.buffer[1]) && ((*ee)->buf[0] & 0xf) == (in_event.buffer[0] & 0xf)) { quantized_time = (*ee)->time + time_per_grid_unit; + _incomplete_notes.erase (ee); + break; } } + + if (ee == _incomplete_notes.end()) { + cerr << "Note off for " << (int) (*ee)->buf[1] << " seen without corresponding note on among " << _incomplete_notes.size() << endl; + continue; + } + } else { quantized_time = (in_loop_time / time_per_grid_unit) * time_per_grid_unit; } @@ -265,6 +276,17 @@ BeatBox::process (int nsamples) inbound_tracker.track (e->buf); _current_events.insert (e); + + if ((e->buf[0] & 0xf) == MIDI_CMD_NOTE_ON) { + _incomplete_notes.push_back (e); + } + + /* play it to out outputs so that we can hear it immediately */ + /* XXX this smooshes together all inbound notes ... tricky */ + if ((buffer = jack_midi_event_reserve (out_buf, last_output_time++, e->size)) != 0) { + memcpy (buffer, e->buf, e->size); + outbound_tracker.track (e->buf); + } } superclock_cnt += superclocks; diff --git a/tools/bb/bb.h b/tools/bb/bb.h index 4fcf477140..07175b6664 100644 --- a/tools/bb/bb.h +++ b/tools/bb/bb.h @@ -18,6 +18,10 @@ static const superclock_t superclock_ticks_per_second = 508032000; // 2^10 * 3^4 inline superclock_t superclock_to_samples (superclock_t s, int sr) { return (s * sr) / superclock_ticks_per_second; } inline superclock_t samples_to_superclock (int samples, int sr) { return (samples * superclock_ticks_per_second) / sr; } +namespace ARDOUR { +class Session; +} + class BeatBox { public: BeatBox (int sample_rate); @@ -78,6 +82,9 @@ class BeatBox { bool operator () (Event const * a, Event const * b) const; }; + typedef std::vector IncompleteNotes; + IncompleteNotes _incomplete_notes; + typedef std::set Events; Events _current_events;