Dummy Backend: add a MIDI Clock generator

This commit is contained in:
Robin Gareus 2020-05-27 18:08:56 +02:00
parent 974ae5100f
commit b46a7d43c2
Signed by: rgareus
GPG Key ID: A090BCE02CF57F04
2 changed files with 67 additions and 6 deletions

View File

@ -1698,9 +1698,20 @@ DummyMidiPort::setup_generator (int seq_id, const float sr)
_midi_seq_pos = 0;
_midi_seq_time = 0;
if (_midi_seq_dat && _midi_seq_dat[0].beat_time < 0) {
_midi_seq_spb = sr / 25; // 25fps MTC
if (_midi_seq_dat && _midi_seq_dat[0].beat_time < -1) {
_midi_seq_spb = sr / 25; // 25fps MTC
} else if (_midi_seq_dat && _midi_seq_dat[0].beat_time < 0) {
/* MIDI Clock 120 BPM */
const double bpm = 120;
double quarter_notes_per_beat = 1.0;
const double samples_per_beat = sr * 60.0 / bpm;
const double samples_per_quarter_note = samples_per_beat / quarter_notes_per_beat;
const double clock_tick_interval = samples_per_quarter_note / 24.0;
_midi_seq_spb = clock_tick_interval;
}
return DummyMidiData::sequence_names[seq_id];
}
@ -1734,7 +1745,7 @@ void DummyMidiPort::midi_generate (const pframes_t n_samples)
return;
}
if (_midi_seq_dat[0].beat_time < 0) {
if (_midi_seq_dat[0].beat_time < -1) {
/* MTC generator */
const int audio_samples_per_video_frame = _midi_seq_spb; // sample-rate / 25
const int audio_samples_per_qf = audio_samples_per_video_frame / 4;
@ -1775,6 +1786,51 @@ void DummyMidiPort::midi_generate (const pframes_t n_samples)
if (_midi_seq_time >= /* 24 * 3600 * 25 */ 2160000LL * audio_samples_per_video_frame) {
_midi_seq_time -= 2160000LL * audio_samples_per_video_frame; // 24h @ 25fps
}
return;
} else if (_midi_seq_dat[0].beat_time < 0) {
/* MClk generator */
uint8_t buf[3];
if (_midi_seq_time == 0) {
/* Position Message */
int64_t bcnt = 0; // beat count
buf[0] = 0xf2;
buf[1] = bcnt & 0x7f; // LSB
buf[2] = (bcnt >> 7) & 0x7f; // MSB
_buffer.push_back (boost::shared_ptr<DummyMidiEvent>(new DummyMidiEvent (0, buf, 3)));
}
/* MIDI System Real-Time Messages */
#define MIDI_RT_CLOCK (0xF8)
#define MIDI_RT_START (0xFA)
#define MIDI_RT_CONTINUE (0xFB)
#define MIDI_RT_STOP (0xFC)
if (_midi_seq_time == 0) {
/* start */
buf[0] = MIDI_RT_START;
_buffer.push_back (boost::shared_ptr<DummyMidiEvent>(new DummyMidiEvent (0, buf, 1)));
}
const int clock_tick_interval = _midi_seq_spb; // samples per clock-tick
samplepos_t clk_tick = _midi_seq_time / clock_tick_interval;
samplepos_t clk_sample = clk_tick * clock_tick_interval;
while (clk_sample < _midi_seq_time + n_samples) {
if (clk_sample >= _midi_seq_time) {
buf[0] = MIDI_RT_CLOCK;
_buffer.push_back (boost::shared_ptr<DummyMidiEvent>(new DummyMidiEvent (clk_sample - _midi_seq_time, buf, 1)));
}
clk_sample += clock_tick_interval;
}
_midi_seq_time += n_samples;
if (_midi_seq_time >= 16384 * 24 * clock_tick_interval) {
_midi_seq_time -= 16384 * 24 * clock_tick_interval;
}
return;
}

View File

@ -780,11 +780,15 @@ static const MIDISequence s7[] = { // channel1, nonsense
};
static const MIDISequence s8[] = {
{-1.0, 0, {0} }, // MTC Generator
{-2.0, 0, {0} }, // MTC Generator
};
static const MIDISequence s9[] = {
{-1.0, 0, {0} }, // MClk Generator
};
static const MIDISequence *sequences[] = {
s0, s1, s2, s3, s4, s5, s6, s7, s8
s0, s1, s2, s3, s4, s5, s6, s7, s8, s9
};
static const char *sequence_names[] = {
@ -796,7 +800,8 @@ static const char *sequence_names[] = {
"CCs only",
"Aftertouch",
"Nonsense, Dups",
"MTC 25fps"
"MTC 25fps",
"MClk 120 BPM"
};
}} // namespace