From 7c15ad099f759f2bfdb2701b96fb5335e916a15b Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Tue, 12 May 2020 00:05:42 +0200 Subject: Dummy Backend: add a MTC generator --- libs/backends/dummy/dummy_audiobackend.cc | 50 +++++++++++++++++++++++++++++++ libs/backends/dummy/dummy_audiobackend.h | 2 +- libs/backends/dummy/dummy_midi_seq.h | 10 +++++-- 3 files changed, 58 insertions(+), 4 deletions(-) diff --git a/libs/backends/dummy/dummy_audiobackend.cc b/libs/backends/dummy/dummy_audiobackend.cc index ca9a93e583..b42f29df84 100644 --- a/libs/backends/dummy/dummy_audiobackend.cc +++ b/libs/backends/dummy/dummy_audiobackend.cc @@ -896,6 +896,7 @@ DummyAudioBackend::get_latency_range (PortEngine::PortHandle port_handle, bool f } r = port->latency_range (for_playback); +#ifndef ZERO_LATENCY if (port->is_physical() && port->is_terminal()) { if (port->is_input() && for_playback) { const size_t l_in = _samples_per_period * .25; @@ -910,6 +911,7 @@ DummyAudioBackend::get_latency_range (PortEngine::PortHandle port_handle, bool f r.max += l_out; } } +#endif return r; } @@ -1695,6 +1697,10 @@ DummyMidiPort::setup_generator (int seq_id, const float sr) _midi_seq_spb = sr * .5f; // 120 BPM, beat_time 1.0 per beat. _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 + } return DummyMidiData::sequence_names[seq_id]; } @@ -1728,6 +1734,50 @@ void DummyMidiPort::midi_generate (const pframes_t n_samples) return; } + if (_midi_seq_dat[0].beat_time < 0) { + /* 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; + + samplepos_t tc_frame = _midi_seq_time / audio_samples_per_video_frame; + samplepos_t tc_sample = tc_frame * audio_samples_per_video_frame; + int qf = (tc_frame & 1) ? 4 : 0; + while (tc_sample < _midi_seq_time + n_samples) { + if (tc_sample >= _midi_seq_time) { + uint8_t buf[2]; + buf[0] = 0xf1; + + int frame = tc_frame % 25; + int second = (tc_frame / 25) % 60; + int minute = ((tc_frame / 25) / 60) % 60; + int hour = (((tc_frame / 25) / 60) / 60); + + switch(qf & 7) { + case 0: buf[1] = 0x00 | (frame & 0x0f); break; + case 1: buf[1] = 0x10 | ((frame & 0xf0) >> 4); break; + case 2: buf[1] = 0x20 | (second & 0x0f); break; + case 3: buf[1] = 0x30 | ((second & 0xf0) >> 4); break; + case 4: buf[1] = 0x40 | (minute & 0x0f); break; + case 5: buf[1] = 0x50 | ((minute & 0xf0) >> 4); break; + case 6: buf[1] = 0x60 | ((/* 25fps*/ 0x20 | hour) & 0x0f); break; + case 7: buf[1] = 0x70 | (((/* 25fps*/ 0x20 | hour) & 0xf0)>>4); break; + } + _buffer.push_back (boost::shared_ptr(new DummyMidiEvent (tc_sample - _midi_seq_time, buf, 2))); + } + tc_sample += audio_samples_per_qf; + if (++qf == 8) { + ++tc_frame; + qf = 0; + } + } + + _midi_seq_time += 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; + } + while (1) { const int32_t ev_beat_time = _midi_seq_dat[_midi_seq_pos].beat_time * _midi_seq_spb - _midi_seq_time; if (ev_beat_time < 0) { diff --git a/libs/backends/dummy/dummy_audiobackend.h b/libs/backends/dummy/dummy_audiobackend.h index 58c0bc593d..2990e6980f 100644 --- a/libs/backends/dummy/dummy_audiobackend.h +++ b/libs/backends/dummy/dummy_audiobackend.h @@ -181,7 +181,7 @@ class DummyMidiPort : public DummyPort { // midi event generator ('fake' physical inputs) void midi_generate (const pframes_t n_samples); float _midi_seq_spb; // samples per beat - int32_t _midi_seq_time; + int64_t _midi_seq_time; uint32_t _midi_seq_pos; DummyMidiData::MIDISequence const * _midi_seq_dat; }; // class DummyMidiPort diff --git a/libs/backends/dummy/dummy_midi_seq.h b/libs/backends/dummy/dummy_midi_seq.h index 293b3c7091..e2b31ba5d7 100644 --- a/libs/backends/dummy/dummy_midi_seq.h +++ b/libs/backends/dummy/dummy_midi_seq.h @@ -1239,11 +1239,14 @@ static const MIDISequence s8[] = { // sysex { 8.98, 2, {0xf1, 0x72} }, /* 1 sec pause */ - {11.00, 3, {0xff, 255, 0xff} }, // sentinel +}; + +static const MIDISequence s9[] = { + {-1.0, 0, {0} }, // MTC 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[] = { @@ -1255,7 +1258,8 @@ static const char *sequence_names[] = { "CCs only", "Aftertouch", "Nonsense, Dups", - "MTC (4sec)" + "MTC (4sec)", + "MTC (gen)" }; }} // namespace -- cgit v1.2.3