tweaks to the beatbox toy to properly track and connect note on/off

This commit is contained in:
Paul Davis 2017-08-18 12:17:46 -04:00
parent f4f0e70320
commit 6176d937a9
2 changed files with 41 additions and 12 deletions

View File

@ -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 */
IncompleteNotes::iterator ee;
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)->buf[0] == MIDI_CMD_NOTE_ON) && ((*ee)->buf[1] == in_event.buffer[1]) && ((*ee)->buf[0] & 0xf) == (in_event.buffer[0] & 0xf)) {
quantized_time = (*ee)->time + time_per_grid_unit;
}
}
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;

View File

@ -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<Event*> IncompleteNotes;
IncompleteNotes _incomplete_notes;
typedef std::set<Event*,EventComparator> Events;
Events _current_events;