Skip to content

Commit

Permalink
Temposync voice processors
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
baconpaul committed Jun 30, 2024
1 parent c8c5826 commit a072123
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 42 deletions.
64 changes: 47 additions & 17 deletions include/sst/voice-effects/VoiceEffectCore.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,13 @@ template <typename VFXConfig> 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<decltype(VFXConfig::getSampleRate(
Expand Down Expand Up @@ -173,30 +179,54 @@ template <typename VFXConfig> struct VoiceEffectTemplateBase : public VFXConfig:
}
}

template <typename T, typename = void> struct has_oversampling : std::false_type
{
#define HASMEM(M, GetSig, DVAL, PARENS) \
template <typename T, typename = void> struct has_##M : std::false_type \
{ \
}; \
template <typename T> struct has_##M<T, std::void_t<decltype(&T::M)>> : std::true_type \
{ \
}; \
GetSig \
{ \
if constexpr (has_##M<VFXConfig>::value) \
{ \
return VFXConfig::M PARENS; \
} \
else \
{ \
return DVAL; \
} \
};

template <typename T>
struct has_oversampling<T, std::void_t<decltype(&T::oversamplingRatio)>> : 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<VoiceEffectTemplateBase<VFXConfig>, VFXConfig::blockSize,
VoiceEffectTemplateBase<VFXConfig>>;

constexpr int16_t getOversamplingRatio()
void updateTempo()
{
if constexpr (has_oversampling<VFXConfig>::value)
{
return VFXConfig::oversamplingRatio;
}
else
auto tempoPointer = getBaseTempoPointer();
assert(tempoPointer);
if (tempo != *tempoPointer)
{
return 1;
std::cout << "Updating tempo " << *tempoPointer << " " << __FILE__ << std::endl;
tempo = *tempoPointer;
temposyncratio = tempo / 120.0;
temposyncratioinv = 1.0 / temposyncratio;
}
}

using BiquadFilterType =
sst::filters::Biquad::BiquadFilter<VoiceEffectTemplateBase<VFXConfig>, VFXConfig::blockSize,
VoiceEffectTemplateBase<VFXConfig>>;
private:
double defaultTempo{120.0};

protected:
double tempo{defaultTempo}, temposyncratio{defaultTempo / 120.0},
temposyncratioinv{120.0 / defaultTempo};
};
} // namespace sst::voice_effects::core

Expand Down
9 changes: 1 addition & 8 deletions include/sst/voice-effects/delay/Chorus.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,14 +104,7 @@ template <typename VFXConfig> struct Chorus : core::VoiceEffectTemplateBase<VFXC
case fpFeedback:
return pmd().asPercent().withDefault(0.f).withName("Feedback");
case fpRate:
return pmd()
.asFloat()
.withRange(-3, 4)
.withPolarity(pmd::ParamMetaData::Polarity::UNIPOLAR_POSITIVE)
// .temposyncable()
// .withTemposyncMultiplier(-1)
.withATwoToTheBFormatting(1, 1, "Hz")
.withName("Rate");
return pmd().asLfoRate(-3, 4).withName("Rate");
case fpDepth:
return pmd()
.asFloat()
Expand Down
9 changes: 1 addition & 8 deletions include/sst/voice-effects/modulation/Phaser.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,14 +80,7 @@ template <typename VFXConfig> struct Phaser : core::VoiceEffectTemplateBase<VFXC
case fpResonance:
return pmd().asPercent().withDefault(0.707).withName("Resonance");
case fpRate:
return pmd()
.asFloat()
.withRange(-3, 4)
.withPolarity(pmd::ParamMetaData::Polarity::UNIPOLAR_POSITIVE)
// .temposyncable()
// .withTemposyncMultiplier(-1)
.withATwoToTheBFormatting(1, 1, "Hz")
.withName("Rate");
return pmd().asLfoRate(-3, 4).withName("Rate");
case fpDepth:
return pmd()
.asFloat()
Expand Down
11 changes: 2 additions & 9 deletions include/sst/voice-effects/modulation/Tremolo.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,7 @@ template <typename VFXConfig> struct Tremolo : core::VoiceEffectTemplateBase<VFX
case fpVolume:
return pmd().asLinearDecibel(-60.f, 12.f).withName("Volume");
case fpRate:
return pmd()
.asFloat()
.withRange(-3, 4)
.withPolarity(pmd::ParamMetaData::Polarity::UNIPOLAR_POSITIVE)
// .temposyncable()
// .withTemposyncMultiplier(-1)
.withATwoToTheBFormatting(1, 1, "Hz")
.withName("Rate");
return pmd().asLfoRate(-3, 4).withName("Rate");
case fpDepth:
return pmd()
.asFloat()
Expand Down Expand Up @@ -444,7 +437,7 @@ template <typename VFXConfig> struct Tremolo : core::VoiceEffectTemplateBase<VFX

// How does it know which MonoTo... function to choose? By first calling this.
bool getMonoToStereoSetting() const { return this->getIntParam(ipStereo) > 0; }

bool enableKeytrack(bool b)
{
auto res = (b != keytrackOn);
Expand Down

0 comments on commit a072123

Please sign in to comment.