13
0

add basics of a method to flush MidiStateTracker state to a MidiBuffer

When the buffer is delivered to a receiver, the receiver should (theoretically) end up
the same state as the MidiStateTracker
This commit is contained in:
Paul Davis 2022-02-01 17:51:34 -07:00
parent 04004d2178
commit 885d2feb6a
2 changed files with 36 additions and 11 deletions

View File

@ -54,6 +54,8 @@ public:
void resolve_notes (Evoral::EventSink<samplepos_t>& buffer, samplepos_t time); void resolve_notes (Evoral::EventSink<samplepos_t>& buffer, samplepos_t time);
void resolve_notes (MidiSource& src, const Glib::Threads::Mutex::Lock& lock, Temporal::Beats time); void resolve_notes (MidiSource& src, const Glib::Threads::Mutex::Lock& lock, Temporal::Beats time);
void flush_notes (MidiBuffer&, samplepos_t);
bool empty() const { return _on == 0; } bool empty() const { return _on == 0; }
uint16_t on() const { return _on; } uint16_t on() const { return _on; }
bool active (uint8_t note, uint8_t channel) { bool active (uint8_t note, uint8_t channel) {
@ -80,7 +82,7 @@ class LIBARDOUR_API MidiStateTracker : public MidiNoteTracker
void dump (std::ostream&); void dump (std::ostream&);
void reset (); void reset ();
void resolve (MidiBuffer&, samplepos_t); void flush (MidiBuffer&, samplepos_t);
private: private:
uint8_t have_program[16]; uint8_t have_program[16];

View File

@ -228,10 +228,6 @@ MidiStateTracker::reset ()
MidiNoteTracker::reset (); MidiNoteTracker::reset ();
for (size_t n = 0; n < n_channels; ++n) {
have_program[n] = 0;
}
for (size_t n = 0; n < n_channels; ++n) { for (size_t n = 0; n < n_channels; ++n) {
program[n] = 0; program[n] = 0;
} }
@ -259,6 +255,7 @@ MidiStateTracker::track (const uint8_t* evbuf)
case MIDI_CTL_ALL_NOTES_OFF: case MIDI_CTL_ALL_NOTES_OFF:
MidiNoteTracker::reset(); MidiNoteTracker::reset();
break; break;
case MIDI_CMD_NOTE_ON: case MIDI_CMD_NOTE_ON:
add (evbuf[1], chan); add (evbuf[1], chan);
break; break;
@ -267,16 +264,15 @@ MidiStateTracker::track (const uint8_t* evbuf)
break; break;
case MIDI_CMD_CONTROL: case MIDI_CMD_CONTROL:
control[chan][evbuf[1]] = evbuf[2]; control[chan][evbuf[1]] = 0xf|evbuf[2];
break; break;
case MIDI_CMD_PGM_CHANGE: case MIDI_CMD_PGM_CHANGE:
program[chan] = evbuf[1]; program[chan] = 0xf|evbuf[1];
have_program[chan] = 1;
break; break;
case MIDI_CMD_CHANNEL_PRESSURE: case MIDI_CMD_CHANNEL_PRESSURE:
pressure[chan] = evbuf[1]; pressure[chan] = 0xf|evbuf[1];
break; break;
case MIDI_CMD_NOTE_PRESSURE: case MIDI_CMD_NOTE_PRESSURE:
@ -290,12 +286,39 @@ MidiStateTracker::track (const uint8_t* evbuf)
break; break;
default: default:
break; break;
} }
} }
void void
MidiStateTracker::resolve (MidiBuffer& buffer, samplepos_t time) MidiStateTracker::flush (MidiBuffer& dst, samplepos_t time)
{ {
/* XXX implement me */ /* XXX implement me */
uint8_t buf[3];
const size_t n_channels = 16;
const size_t n_controls = 127;
/* XXX need MidiNoteTracker::flush() method that will emit NoteOn for
* all currently-on notes.
*/
for (int chn = 0; chn < n_channels; ++chn) {
if (program[chn] & 0xf) {
buf[0] = MIDI_CMD_PGM_CHANGE|chn;
buf[1] = program[chn] & 0x7f;
dst.write (time, Evoral::MIDI_EVENT, 2, buf);
}
}
for (int chn = 0; chn < 16; ++chn) {
for (int ctl = 0; ctl < n_controls; ++ctl) {
if (control[chn][ctl] & 0xf) {
buf[0] = MIDI_CMD_CONTROL|chn;
buf[1] = ctl;
buf[2] = control[chn][ctl] & 0x7f;
dst.write (time, Evoral::MIDI_EVENT, 3, buf);
}
}
}
} }