gearmulator

Emulation of classic VA synths of the late 90s/2000s that are based on Motorola 56300 family DSPs
Log | Files | Refs | Submodules | README | LICENSE

commit e294741eaf26e1b1d9c1fdd281c8cf1e1954d2d5
parent 6a1fb2627d05b77f2536b9dd6132d924c6f80bde
Author: dsp56300 <dsp56300@users.noreply.github.com>
Date:   Thu,  5 Sep 2024 19:51:52 +0200

move midi clock processing to a separate file

Diffstat:
Msource/synthLib/CMakeLists.txt | 1+
Asource/synthLib/midiClock.cpp | 84+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asource/synthLib/midiClock.h | 27+++++++++++++++++++++++++++
Msource/synthLib/plugin.cpp | 70+++-------------------------------------------------------------------
Msource/synthLib/plugin.h | 8++++----
5 files changed, 119 insertions(+), 71 deletions(-)

diff --git a/source/synthLib/CMakeLists.txt b/source/synthLib/CMakeLists.txt @@ -16,6 +16,7 @@ set(SOURCES deviceTypes.h dspMemoryPatch.cpp dspMemoryPatch.h midiBufferParser.cpp midiBufferParser.h + midiClock.cpp midiClock.h midiToSysex.cpp midiToSysex.h midiTypes.h os.cpp os.h diff --git a/source/synthLib/midiClock.cpp b/source/synthLib/midiClock.cpp @@ -0,0 +1,84 @@ +#include "midiClock.h" + +#include "midiTypes.h" + +#include <cmath> + +#include "plugin.h" + +#if 0 +#define LOGMC(S) LOG(S) +#else +#define LOGMC(S) do{}while(false) +#endif + +namespace synthLib +{ + static constexpr double ClockTicksPerQuarter = 24.0; + + void MidiClock::process(const float _bpm, const float _ppqPos, const bool _isPlaying, const size_t _sampleCount) + { + if(_bpm < 1.0f) + return; + + if(_isPlaying && !m_isPlaying) + { + const double ppqPos = _ppqPos; + m_clockTickPos = (ppqPos - std::floor(ppqPos + 1.0)) * ClockTicksPerQuarter; + LOGMC("Start at ppqPos=" << ppqPos << ", clock tick offset " << m_clockTickPos); + m_isPlaying = true; + m_needsStart = true; + } + else if(m_isPlaying && !_isPlaying) + { + LOGMC("Stop at ppqPos=" << ppqPos); + + m_isPlaying = false; + + SMidiEvent evStop(MidiEventSource::Internal); + evStop.a = M_STOP; + m_plugin.insertMidiEvent(evStop); + m_clockTickPos = 0.0; + } + + if(!m_isPlaying) + return; + + const double quartersPerSecond = _bpm / 60.0; + const double clockTicksPerSecond = ClockTicksPerQuarter * quartersPerSecond; + + const double clocksPerSample = clockTicksPerSecond * m_plugin.getHostSamplerateInv(); + + for(uint32_t i=0; i<static_cast<uint32_t>(_sampleCount); ++i) + { + m_clockTickPos += clocksPerSample; + + if (m_clockTickPos < 0.0f) + continue; + + m_clockTickPos -= 1.0; + + LOGMC("insert tick at " << i); + + SMidiEvent evClock(MidiEventSource::Internal); + evClock.a = M_TIMINGCLOCK; + evClock.offset = i; + + if(m_needsStart) + { + evClock.a = M_START; + m_plugin.insertMidiEvent(evClock); + evClock.a = M_TIMINGCLOCK; + + m_needsStart = false; + } + + m_plugin.insertMidiEvent(evClock); + } + } + + void MidiClock::restart() + { + m_needsStart = true; + } +} diff --git a/source/synthLib/midiClock.h b/source/synthLib/midiClock.h @@ -0,0 +1,26 @@ +#pragma once + +#include <cstddef> + +namespace synthLib +{ + class Plugin; + + class MidiClock + { + public: + MidiClock(Plugin& _plugin) : m_plugin(_plugin) + { + } + + void process(float _bpm, float _ppqPos, bool _isPlaying, size_t _sampleCount); + void restart(); + + private: + Plugin& m_plugin; + + bool m_isPlaying = false; + bool m_needsStart = false; + double m_clockTickPos = 0.0; + }; +} +\ No newline at end of file diff --git a/source/synthLib/plugin.cpp b/source/synthLib/plugin.cpp @@ -5,12 +5,6 @@ #include "os.h" -#if 0 -#define LOGMC(S) LOG(S) -#else -#define LOGMC(S) do{}while(false) -#endif - using namespace synthLib; namespace synthLib @@ -21,6 +15,7 @@ namespace synthLib : m_resampler(_device->getChannelCountIn(), _device->getChannelCountOut()) , m_device(_device) , m_deviceSamplerate(_device->getSamplerate()) + , m_midiClock(*this) { } @@ -128,7 +123,7 @@ namespace synthLib setState(deviceState); // MIDI clock has to send the start event again, some device find it confusing and do strange things if there isn't any - m_needsStart = true; + m_midiClock.restart(); updateDeviceLatency(); } @@ -203,66 +198,7 @@ namespace synthLib void Plugin::processMidiClock(float _bpm, float _ppqPos, bool _isPlaying, size_t _sampleCount) { - if(_bpm < 1.0f) - return; - - const double ppqPos = _ppqPos; - - constexpr double clockTicksPerQuarter = 24.0; - - if(_isPlaying && !m_isPlaying) - { - m_clockTickPos = (ppqPos - std::floor(ppqPos + 1.0)) * clockTicksPerQuarter; - LOGMC("Start at ppqPos=" << ppqPos << ", clock tick offset " << m_clockTickPos); - m_isPlaying = true; - m_needsStart = true; - } - else if(m_isPlaying && !_isPlaying) - { - LOGMC("Stop at ppqPos=" << ppqPos); - - m_isPlaying = false; - - SMidiEvent evStop(MidiEventSource::Internal); - evStop.a = M_STOP; - m_midiIn.insert(m_midiIn.begin(), evStop); - m_clockTickPos = 0.0; - } - - if(!m_isPlaying) - return; - - const double quartersPerSecond = _bpm / 60.0; - const double clockTicksPerSecond = clockTicksPerQuarter * quartersPerSecond; - - const double clocksPerSample = clockTicksPerSecond * m_hostSamplerateInv; - - for(uint32_t i=0; i<static_cast<uint32_t>(_sampleCount); ++i) - { - m_clockTickPos += clocksPerSample; - - if (m_clockTickPos < 0.0f) - continue; - - m_clockTickPos -= 1.0; - - LOGMC("insert tick at " << i); - - SMidiEvent evClock(MidiEventSource::Internal); - evClock.a = M_TIMINGCLOCK; - evClock.offset = i; - - if(m_needsStart) - { - evClock.a = M_START; - insertMidiEvent(evClock); - evClock.a = M_TIMINGCLOCK; - - m_needsStart = false; - } - - insertMidiEvent(evClock); - } + m_midiClock.process(_bpm, _ppqPos, _isPlaying, _sampleCount); } float* Plugin::getDummyBuffer(size_t _minimumSize) diff --git a/source/synthLib/plugin.h b/source/synthLib/plugin.h @@ -9,6 +9,7 @@ #include "dsp56kEmu/ringbuffer.h" #include "deviceTypes.h" +#include "midiClock.h" namespace synthLib { @@ -25,6 +26,7 @@ namespace synthLib void setHostSamplerate(float _hostSamplerate, float _preferredDeviceSamplerate); float getHostSamplerate() const { return m_hostSamplerate; } + float getHostSamplerateInv() const { return m_hostSamplerateInv; } void setBlockSize(uint32_t _blockSize); @@ -77,10 +79,8 @@ namespace synthLib uint32_t m_deviceLatencyMidiToOutput = 0; uint32_t m_deviceLatencyInputToOutput = 0; - // MIDI Clock - bool m_isPlaying = false; - bool m_needsStart = false; - double m_clockTickPos = 0.0; + MidiClock m_midiClock; + uint32_t m_extraLatencyBlocks = 1; float m_deviceSamplerate = 0.0f;