From ac297f95f4b553df04754e4a3d3ea8ddef36c877 Mon Sep 17 00:00:00 2001 From: falkTX Date: Tue, 8 Feb 2022 04:07:12 +0000 Subject: [PATCH] Fix host time sometimes skipping beats Closes #104 Turns out that the tick can be just at the end of the audio block (ie, frame 511 of 512) and we will just barely miss it. Because the tick is reset from host info on every audio block (to always keep things in sync), we would miss the event because of just 1 sample. So give a little hand to make sure new beat is always triggered. Signed-off-by: falkTX --- plugins/Cardinal/src/HostAudio.cpp | 6 +++--- plugins/Cardinal/src/HostTime.cpp | 32 ++++++++++++++++++++++-------- src/override/Window.cpp | 2 +- 3 files changed, 28 insertions(+), 12 deletions(-) diff --git a/plugins/Cardinal/src/HostAudio.cpp b/plugins/Cardinal/src/HostAudio.cpp index 14a9a4c..6bf4f71 100644 --- a/plugins/Cardinal/src/HostAudio.cpp +++ b/plugins/Cardinal/src/HostAudio.cpp @@ -105,19 +105,19 @@ struct HostAudio : TerminalModule { void processTerminalOutput(const ProcessArgs&) override { - float** const dataOuts = pcontext->dataOuts; - const int blockFrames = pcontext->engine->getBlockFrames(); // only incremented on output const int k = dataFrame++; DISTRHO_SAFE_ASSERT_INT2_RETURN(k < blockFrames, k, blockFrames,); - const float gain = numParams != 0 ? std::pow(params[0].getValue(), 2.f) : 1.0f; + float** const dataOuts = pcontext->dataOuts; // from cardinal into host, shows as input plug if (! isBypassed()) { + const float gain = numParams != 0 ? std::pow(params[0].getValue(), 2.f) : 1.0f; + for (int i=0; iengine->getBlockFrame(); + // local variables for faster access + double tick, tickClock; + // Update time position if running a new audio block if (lastBlockFrame != blockFrame) { @@ -70,9 +73,14 @@ struct HostTime : TerminalModule { timeInfo.reset = pcontext->reset; timeInfo.bar = pcontext->bar; timeInfo.beat = pcontext->beat; - timeInfo.tick = pcontext->tick; - timeInfo.tickClock = pcontext->tickClock; timeInfo.seconds = pcontext->frame / pcontext->sampleRate; + tick = pcontext->tick; + tickClock = pcontext->tickClock; + } + else + { + tick = timeInfo.tick; + tickClock = timeInfo.tickClock; } const bool playing = pcontext->playing; @@ -80,7 +88,7 @@ struct HostTime : TerminalModule { if (playingWithBBT) { - if (timeInfo.tick == 0.0) + if (d_isZero(tick)) { pulseReset.trigger(); pulseClock.trigger(); @@ -95,9 +103,13 @@ struct HostTime : TerminalModule { pulseReset.trigger(); } - if ((timeInfo.tick += pcontext->ticksPerFrame) >= pcontext->ticksPerBeat) + tick += pcontext->ticksPerFrame; + + // give a little help to keep tick active, + // as otherwise we might miss it if located at the very end of the audio block + if (tick + 0.0001 >= pcontext->ticksPerBeat) { - timeInfo.tick -= pcontext->ticksPerBeat; + tick -= pcontext->ticksPerBeat; pulseBeat.trigger(); if (++timeInfo.beat > pcontext->beatsPerBar) @@ -108,9 +120,9 @@ struct HostTime : TerminalModule { } } - if ((timeInfo.tickClock += pcontext->ticksPerFrame) >= pcontext->ticksPerClock) + if ((tickClock += pcontext->ticksPerFrame) >= pcontext->ticksPerClock) { - timeInfo.tickClock -= pcontext->ticksPerClock; + tickClock -= pcontext->ticksPerClock; pulseClock.trigger(); } } @@ -120,12 +132,16 @@ struct HostTime : TerminalModule { const bool hasBeat = pulseBeat.process(args.sampleTime); const bool hasClock = pulseClock.process(args.sampleTime); const float beatPhase = playingWithBBT && pcontext->ticksPerBeat > 0.0 - ? timeInfo.tick / pcontext->ticksPerBeat + ? tick / pcontext->ticksPerBeat : 0.0f; const float barPhase = playingWithBBT && pcontext->beatsPerBar > 0 ? ((float) (timeInfo.beat - 1) + beatPhase) / pcontext->beatsPerBar : 0.0f; + // store back the local values + timeInfo.tick = tick; + timeInfo.tickClock = tickClock; + if (isBypassed()) return; diff --git a/src/override/Window.cpp b/src/override/Window.cpp index 6cb8fc0..87c0502 100644 --- a/src/override/Window.cpp +++ b/src/override/Window.cpp @@ -359,7 +359,7 @@ void Window::step() { bndSetFont(uiFont->handle); // Set window title - std::string windowTitle = APP_NAME + " " + APP_EDITION_NAME + " " + APP_VERSION; + std::string windowTitle = "Cardinal"; if (APP->patch->path != "") { windowTitle += " - "; if (!APP->history->isSaved())