From c43fb4ca41013811be4493dba1d8cf36b86a3f14 Mon Sep 17 00:00:00 2001 From: Andreya-Autumn Date: Thu, 12 Sep 2024 14:54:31 +0200 Subject: [PATCH] fixes --- include/sst/voice-effects/delay/Chorus.h | 7 +- include/sst/voice-effects/dynamics/AutoWah.h | 2 - include/sst/voice-effects/filter/CytomicSVF.h | 16 +- include/sst/voice-effects/modulation/Phaser.h | 2 - .../sst/voice-effects/modulation/RingMod.h | 8 +- .../voice-effects/modulation/ShepardPhaser.h | 185 +++++++++++++----- 6 files changed, 141 insertions(+), 79 deletions(-) diff --git a/include/sst/voice-effects/delay/Chorus.h b/include/sst/voice-effects/delay/Chorus.h index 03aeaf5..00c3bf5 100644 --- a/include/sst/voice-effects/delay/Chorus.h +++ b/include/sst/voice-effects/delay/Chorus.h @@ -71,10 +71,7 @@ template struct Chorus : core::VoiceEffectTemplateBase() - { - std::fill(mLastParam.begin(), mLastParam.end(), -188888.f); - } + Chorus(const SincTable &st) : sSincTable(st), core::VoiceEffectTemplateBase() {} ~Chorus() { @@ -394,8 +391,6 @@ template struct Chorus : core::VoiceEffectTemplateBase lineSupport; bool isShort{true}; - std::array mLastParam{}; - sst::basic_blocks::dsp::lipol_sse feedbackLerp, timeLerp[2]; }; diff --git a/include/sst/voice-effects/dynamics/AutoWah.h b/include/sst/voice-effects/dynamics/AutoWah.h index ac293db..326b208 100644 --- a/include/sst/voice-effects/dynamics/AutoWah.h +++ b/include/sst/voice-effects/dynamics/AutoWah.h @@ -237,8 +237,6 @@ template struct AutoWah : core::VoiceEffectTemplateBase mLastParam{}; - std::array mLastIParam{}; bool first = true; bool keytrackOn = false; sst::basic_blocks::dsp::SlewLimiter speedLimiter; diff --git a/include/sst/voice-effects/filter/CytomicSVF.h b/include/sst/voice-effects/filter/CytomicSVF.h index 7a8d98c..9680bd5 100644 --- a/include/sst/voice-effects/filter/CytomicSVF.h +++ b/include/sst/voice-effects/filter/CytomicSVF.h @@ -164,7 +164,11 @@ template struct CytomicSVF : core::VoiceEffectTemplateBase< return pmd().withName("error"); } - void initVoiceEffect() {} + void initVoiceEffect() + { + cySvf[0].init(); + cySvf[1].init(); + } void initVoiceEffectParams() { this->initToParamMetadataDefault(this); } void calc_coeffs(float pitch = 0.f) @@ -191,20 +195,12 @@ template struct CytomicSVF : core::VoiceEffectTemplateBase< if (diff || idiff) { - if (idiff) - { - cySvf[0].init(); - if (iparam[2]) - { - cySvf[1].init(); - } - } auto mode = (sst::filters::CytomicSVF::Mode)(iparam[0]); auto res = std::clamp(param[2], 0.f, 1.f); if (iparam[2] == true) { - res *= .885f; // I just checked on a specrum analyzer. + res *= .885f; // I just checked peak heights on a spectrum analyzer. } auto shelf = this->dbToLinear(param[3]); diff --git a/include/sst/voice-effects/modulation/Phaser.h b/include/sst/voice-effects/modulation/Phaser.h index 1b9779a..1779113 100644 --- a/include/sst/voice-effects/modulation/Phaser.h +++ b/include/sst/voice-effects/modulation/Phaser.h @@ -340,8 +340,6 @@ template struct Phaser : core::VoiceEffectTemplateBase mLastParam{}; - std::array mLastIParam{}; std::array filters; float fbAmt[2]{0.f, 0.f}; sst::basic_blocks::dsp::lipol_sse feedbackLerp; diff --git a/include/sst/voice-effects/modulation/RingMod.h b/include/sst/voice-effects/modulation/RingMod.h index 1c4c910..fdedafe 100644 --- a/include/sst/voice-effects/modulation/RingMod.h +++ b/include/sst/voice-effects/modulation/RingMod.h @@ -51,11 +51,7 @@ template struct RingMod : core::VoiceEffectTemplateBase() - { - std::fill(mLastIParam.begin(), mLastIParam.end(), -1); - std::fill(mLastParam.begin(), mLastParam.end(), -188888.f); - } + RingMod() : core::VoiceEffectTemplateBase() {} ~RingMod() {} @@ -159,8 +155,6 @@ template struct RingMod : core::VoiceEffectTemplateBase mLastParam{}; - std::array mLastIParam{}; sst::basic_blocks::dsp::QuadratureOscillator qosc; int priorNum = -1; int priorDenom = -1; diff --git a/include/sst/voice-effects/modulation/ShepardPhaser.h b/include/sst/voice-effects/modulation/ShepardPhaser.h index bf280ea..c0bc14b 100644 --- a/include/sst/voice-effects/modulation/ShepardPhaser.h +++ b/include/sst/voice-effects/modulation/ShepardPhaser.h @@ -92,7 +92,18 @@ template struct ShepardPhaser : core::VoiceEffectTemplateBa return pmd().asInt().withName("Error"); } - void initVoiceEffect() {} + void initVoiceEffect() + { + for (int i = 0; i < 24; ++i) + { + filters[i].init(); + if (i < 12) + { + priorLevelL[i] = -12345.f; + priorLevelR[i] = -12345.f; + } + } + } void initVoiceEffectParams() { this->initToParamMetadataDefault(this); } @@ -124,6 +135,7 @@ template struct ShepardPhaser : core::VoiceEffectTemplateBa if (peaks != priorPeaks) { logOfPeaks = std::log2f(peaks); + gainScale = 1 / logOfPeaks; priorPeaks = peaks; } auto lfoRate = this->getFloatParam(fpRate) - logOfPeaks; @@ -140,50 +152,107 @@ template struct ShepardPhaser : core::VoiceEffectTemplateBa mech::clear_block(dataoutL); mech::clear_block(dataoutR); - for (int i = 0; i < peaks; ++i) + if (stereo) { - auto offset = static_cast(i) / static_cast(peaks); - auto halfway = 0.5 / static_cast(peaks); - auto iPhaseL = std::fmod(phasorValue + offset, 1.0); - auto iPhaseR = !stereo ? iPhaseL : std::fmod(phasorValue + offset + halfway, 1.0); - - auto iTriL = triangle(iPhaseL); - auto iTriR = triangle(iPhaseR); - - auto freqL = 440.f * this->note_to_pitch_ignoring_tuning( - this->getFloatParam(fpStartFreq) + (range * iPhaseL)); - auto freqR = 440.f * this->note_to_pitch_ignoring_tuning( - this->getFloatParam(fpStartFreq) + (range * iPhaseR)); - - filters[i].template setCoeffForBlock( - sst::filters::CytomicSVF::Mode::BP, freqL, freqR, res, res, - this->getSampleRateInv(), 1.f, 1.f); - - float tmpL alignas(16)[VFXConfig::blockSize]; - float tmpR alignas(16)[VFXConfig::blockSize]; - mech::copy_from_to(datainL, tmpL); - mech::copy_from_to(datainR, tmpR); - - for (int k = 0; k < VFXConfig::blockSize; ++k) + for (int i = 0; i < peaks; ++i) { - filters[i].processBlockStep(tmpL[k], tmpR[k]); + auto offset = static_cast(i) / static_cast(peaks); + auto halfway = 0.5 / static_cast(peaks); + + // ramp for frequency + auto iPhaseL = std::fmod(phasorValue + offset, 1.0); + auto iPhaseR = std::fmod(phasorValue + offset + halfway, 1.0); + + // triangle for amplitude + auto iTriL = triangle(iPhaseL); + auto iTriR = triangle(iPhaseR); + iTriL = iTriL * iTriL * iTriL; + iTriR = iTriR * iTriR * iTriR; + if (priorLevelL[i] < 0) // true on first block + { + priorLevelL[i] = iTriL; // start from the first value + } + if (priorLevelR[i] < 0) // same for the right side + { + priorLevelR[i] = iTriR; + } + // set the smoothers to start on the prior value + levelLerpL.set_target_instant(priorLevelL[i]); + levelLerpR.set_target_instant(priorLevelR[i]); + // and aim for the current value + levelLerpL.set_target(iTriL); + levelLerpR.set_target(iTriR); + // and save the index's value to start from on the next block + priorLevelL[i] = iTriL; + priorLevelR[i] = iTriR; + // A float per filter is a lot less memory than a lipol_sse per filter + + auto freqL = 440.f * this->note_to_pitch_ignoring_tuning( + this->getFloatParam(fpStartFreq) + (range * iPhaseL)); + auto freqR = 440.f * this->note_to_pitch_ignoring_tuning( + this->getFloatParam(fpStartFreq) + (range * iPhaseR)); + + filters[i].template setCoeffForBlock( + sst::filters::CytomicSVF::Mode::BP, freqL, freqR, res, res, + this->getSampleRateInv(), 1.f, 1.f); + + float tmpL alignas(16)[VFXConfig::blockSize]; + float tmpR alignas(16)[VFXConfig::blockSize]; + mech::copy_from_to(datainL, tmpL); + mech::copy_from_to(datainR, tmpR); + + for (int k = 0; k < VFXConfig::blockSize; ++k) + { + filters[i].processBlockStep(tmpL[k], tmpR[k]); + } + + levelLerpL.multiply_block(tmpL); + levelLerpR.multiply_block(tmpR); + + mech::scale_accumulate_from_to(tmpL, tmpR, gainScale, + dataoutL, dataoutR); } - - if (!stereo) - { - lipolLevel[i].set_target(iTriL * iTriL * iTriL); - lipolLevel[i].multiply_2_blocks(tmpL, tmpR); - } - else + } + else + { + for (int i = 0; i < peaks; ++i) { - lipolLevel[i].set_target(iTriL * iTriL * iTriL); - lipolLevel[i].multiply_block(tmpL); - lipolLevel[i + 12].set_target(iTriR * iTriR * iTriR); - lipolLevel[i + 12].multiply_block(tmpR); + auto offset = static_cast(i) / static_cast(peaks); + auto halfway = 0.5 / static_cast(peaks); + auto iPhase = std::fmod(phasorValue + offset, 1.0); + + auto iTri = triangle(iPhase); + iTri = iTri * iTri * iTri; + if (priorLevelL[i] < 0) + { + priorLevelL[i] = iTri; + } + levelLerpL.set_target_instant(priorLevelL[i]); + levelLerpL.set_target(iTri); + priorLevelL[i] = iTri; + + auto freq = 440.f * this->note_to_pitch_ignoring_tuning( + this->getFloatParam(fpStartFreq) + (range * iPhase)); + + filters[i].template setCoeffForBlock( + sst::filters::CytomicSVF::Mode::BP, freq, freq, res, res, + this->getSampleRateInv(), 1.f, 1.f); + + float tmpL alignas(16)[VFXConfig::blockSize]; + float tmpR alignas(16)[VFXConfig::blockSize]; + mech::copy_from_to(datainL, tmpL); + mech::copy_from_to(datainR, tmpR); + + for (int k = 0; k < VFXConfig::blockSize; ++k) + { + filters[i].processBlockStep(tmpL[k], tmpR[k]); + } + + levelLerpL.multiply_2_blocks(tmpL, tmpR); + + mech::scale_accumulate_from_to(tmpL, tmpR, gainScale, + dataoutL, dataoutR); } - - mech::scale_accumulate_from_to(tmpL, tmpR, 0.5f, dataoutL, - dataoutR); } } @@ -196,6 +265,7 @@ template struct ShepardPhaser : core::VoiceEffectTemplateBa if (peaks != priorPeaks) { logOfPeaks = std::log2f(peaks); + gainScale = 1 / logOfPeaks; priorPeaks = peaks; } auto lfoRate = this->getFloatParam(fpRate) - logOfPeaks; @@ -213,13 +283,23 @@ template struct ShepardPhaser : core::VoiceEffectTemplateBa for (int i = 0; i < peaks; ++i) { + auto offset = static_cast(i) / static_cast(peaks); + auto iPhase = std::fmod(phasorValue + offset, 1.0); - float iPhase = phasorValue + (i / static_cast(peaks)); - if (iPhase > 1) + float iTri = triangle(iPhase); + iTri = iTri * iTri * iTri; + + if (isFirst) { - iPhase -= 1; + priorLevelL[i] = iTri; + if (i == peaks - 1) + { + isFirst = false; + } } - float iTri = triangle(iPhase); + levelLerpL.set_target_instant(priorLevelL[i]); + levelLerpL.set_target(iTri); + priorLevelL[i] = iTri; auto freqMod = this->getFloatParam(fpStartFreq) + (range * iPhase); auto freq = 440.f * this->note_to_pitch_ignoring_tuning(freqMod); @@ -234,10 +314,9 @@ template struct ShepardPhaser : core::VoiceEffectTemplateBa filters[i].processBlockStep(tmp[k]); } - lipolLevel[i].set_target(iTri * iTri * iTri); - lipolLevel[i].multiply_block(tmp); + levelLerpL.multiply_block(tmp); - mech::scale_accumulate_from_to(tmp, 0.5f, dataoutL); + mech::scale_accumulate_from_to(tmp, gainScale, dataoutL); } } @@ -249,14 +328,16 @@ template struct ShepardPhaser : core::VoiceEffectTemplateBa bool getMonoToStereoSetting() const { return this->getIntParam(ipStereo) > 0; } protected: - std::array mLastParam{}; - std::array mLastIParam{}; - std::array filters; - sst::basic_blocks::dsp::lipol_sse lipolLevel[24]; - float logOfPeaks{0.f}; + sst::basic_blocks::dsp::lipol_sse levelLerpL, levelLerpR; + float priorLevelL[12]; + float priorLevelR[12]; + int priorPeaks{0}; + float logOfPeaks{0.f}; + float gainScale{1.f}; + bool isFirst{true}; }; } // namespace sst::voice_effects::modulation