From 08406e9865906cb21f9eb32853d6c257b64ce6c9 Mon Sep 17 00:00:00 2001 From: Paul Date: Sun, 30 Jun 2024 14:10:10 -0400 Subject: [PATCH] Temposync voice processors (#104) * Temposync voice processors Add temposync communication to the voice processors. Turns out the SimpleLFO has a bit of drift due to float vs double which we need to clean up, but the basic idea is right, so merge this then open a followup issue. --- include/sst/voice-effects/VoiceEffectCore.h | 63 ++++++++++++++----- include/sst/voice-effects/delay/Chorus.h | 9 +-- include/sst/voice-effects/modulation/Phaser.h | 9 +-- .../sst/voice-effects/modulation/Tremolo.h | 11 +--- 4 files changed, 50 insertions(+), 42 deletions(-) diff --git a/include/sst/voice-effects/VoiceEffectCore.h b/include/sst/voice-effects/VoiceEffectCore.h index ded6161..5b9d7ae 100644 --- a/include/sst/voice-effects/VoiceEffectCore.h +++ b/include/sst/voice-effects/VoiceEffectCore.h @@ -119,7 +119,13 @@ template struct VoiceEffectTemplateBase : public VFXConfig: float envelope_rate_linear_nowrap(float f) { - return VFXConfig::blockSize * VFXConfig::getSampleRateInv(this) * std::pow(2, -f); + auto res = VFXConfig::blockSize * VFXConfig::getSampleRateInv(this) * std::pow(2, -f); + if (getIsTemposync()) + { + updateTempo(); + res = res * temposyncratio; + } + return res; } static_assert(std::is_same struct VoiceEffectTemplateBase : public VFXConfig: } } - template struct has_oversampling : std::false_type - { +#define HASMEM(M, GetSig, DVAL, PARENS) \ + template struct has_##M : std::false_type \ + { \ + }; \ + template struct has_##M> : std::true_type \ + { \ + }; \ + GetSig \ + { \ + if constexpr (has_##M::value) \ + { \ + return VFXConfig::M PARENS; \ + } \ + else \ + { \ + return DVAL; \ + } \ }; - template - struct has_oversampling> : std::true_type - { - }; + HASMEM(oversamplingRatio, constexpr int16_t getOversamplingRatio(), 1, ); + HASMEM(getTempoPointer, double *getBaseTempoPointer(), &defaultTempo, (asBase())); + HASMEM(isTemposync, bool getIsTemposync(), false, (asBase())); + +#undef HASMEM + + using BiquadFilterType = + sst::filters::Biquad::BiquadFilter, VFXConfig::blockSize, + VoiceEffectTemplateBase>; - constexpr int16_t getOversamplingRatio() + void updateTempo() { - if constexpr (has_oversampling::value) - { - return VFXConfig::oversamplingRatio; - } - else + auto tempoPointer = getBaseTempoPointer(); + assert(tempoPointer); + if (tempo != *tempoPointer) { - return 1; + tempo = *tempoPointer; + temposyncratio = tempo / 120.0; + temposyncratioinv = 1.0 / temposyncratio; } } - using BiquadFilterType = - sst::filters::Biquad::BiquadFilter, VFXConfig::blockSize, - VoiceEffectTemplateBase>; + private: + double defaultTempo{120.0}; + + protected: + double tempo{defaultTempo}, temposyncratio{defaultTempo / 120.0}, + temposyncratioinv{120.0 / defaultTempo}; }; } // namespace sst::voice_effects::core diff --git a/include/sst/voice-effects/delay/Chorus.h b/include/sst/voice-effects/delay/Chorus.h index 8f8624c..61ac779 100644 --- a/include/sst/voice-effects/delay/Chorus.h +++ b/include/sst/voice-effects/delay/Chorus.h @@ -104,14 +104,7 @@ template struct Chorus : core::VoiceEffectTemplateBase struct Phaser : core::VoiceEffectTemplateBase struct Tremolo : core::VoiceEffectTemplateBase struct Tremolo : core::VoiceEffectTemplateBasegetIntParam(ipStereo) > 0; } - + bool enableKeytrack(bool b) { auto res = (b != keytrackOn);