Skip to content

Commit

Permalink
Keytrack (#92)
Browse files Browse the repository at this point in the history
* ...and other adventures
* clang-format
  • Loading branch information
Andreya-Autumn authored May 28, 2024
1 parent 0c7b251 commit 3d38bf4
Show file tree
Hide file tree
Showing 8 changed files with 294 additions and 88 deletions.
39 changes: 33 additions & 6 deletions include/sst/voice-effects/delay/StringResonator.h
Original file line number Diff line number Diff line change
Expand Up @@ -245,8 +245,13 @@ template <typename VFXConfig> struct StringResonator : core::VoiceEffectTemplate
panParamTwo = 1.f;
}

auto ptOne = pitch + this->getFloatParam(fpOffsetOne);
auto ptTwo = pitch + this->getFloatParam(fpOffsetTwo);
auto ptOne = this->getFloatParam(fpOffsetOne);
auto ptTwo = this->getFloatParam(fpOffsetTwo);
if (keytrackOn)
{
ptOne += pitch;
ptTwo += pitch;
}
ptOne += pitchAdjustmentForStiffness();
ptTwo += pitchAdjustmentForStiffness();
setupFilters(ptOne);
Expand Down Expand Up @@ -331,7 +336,11 @@ template <typename VFXConfig> struct StringResonator : core::VoiceEffectTemplate
panParam = 0.5f;
}

auto pt = pitch + this->getFloatParam(fpOffsetOne);
auto pt = this->getFloatParam(fpOffsetOne);
if (keytrackOn)
{
pt += pitch;
}
pt += pitchAdjustmentForStiffness();
setupFilters(pt);

Expand Down Expand Up @@ -396,8 +405,13 @@ template <typename VFXConfig> struct StringResonator : core::VoiceEffectTemplate
namespace sdsp = sst::basic_blocks::dsp;
mech::copy_from_to<VFXConfig::blockSize>(datainL, dataoutL);

auto ptOne = pitch + this->getFloatParam(fpOffsetOne);
auto ptTwo = pitch + this->getFloatParam(fpOffsetTwo);
auto ptOne = this->getFloatParam(fpOffsetOne);
auto ptTwo = this->getFloatParam(fpOffsetTwo);
if (keytrackOn)
{
ptOne += pitch;
ptTwo += pitch;
}
ptOne += pitchAdjustmentForStiffness();
ptTwo += pitchAdjustmentForStiffness();
setupFilters(ptOne);
Expand Down Expand Up @@ -464,7 +478,11 @@ template <typename VFXConfig> struct StringResonator : core::VoiceEffectTemplate
namespace sdsp = sst::basic_blocks::dsp;
mech::copy_from_to<VFXConfig::blockSize>(datainL, dataoutL);

auto pt = pitch + this->getFloatParam(fpOffsetOne);
auto pt = this->getFloatParam(fpOffsetOne);
if (keytrackOn)
{
pt += pitch;
}
pt += pitchAdjustmentForStiffness();
setupFilters(pt);

Expand Down Expand Up @@ -652,7 +670,16 @@ template <typename VFXConfig> struct StringResonator : core::VoiceEffectTemplate

bool getMonoToStereoSetting() const { return this->getIntParam(ipStereo) > 0; }

bool enableKeytrack(bool b)
{
auto res = (b != keytrackOn);
keytrackOn = b;
return res;
}
bool getKeytrack() const { return keytrackOn; }

protected:
bool keytrackOn{true};
std::array<details::DelayLineSupport, 2> lineSupport;
bool isShort{true};
bool firstPitch{false};
Expand Down
118 changes: 91 additions & 27 deletions include/sst/voice-effects/distortion/BitCrusher.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,49 +23,72 @@

#include "sst/basic-blocks/params/ParamMetadata.h"
#include "../VoiceEffectCore.h"
#include "sst/filters/CytomicSVF.h"

namespace sst::voice_effects::distortion
{
template <typename VFXConfig> struct BitCrusher : core::VoiceEffectTemplateBase<VFXConfig>
{
static constexpr const char *effectName{"BitCrusher"};

enum bc_fparams
static constexpr int numFloatParams{5};
static constexpr int numIntParams{1};

enum FloatParams
{
bc_samplerate,
bc_bitdepth,
bc_zeropoint,
bc_cutoff,
bc_resonance,
bc_num_params
fpSamplerate,
fpBitdepth,
fpZeropoint,
fpCutoff,
fpResonance,
};

static constexpr int numFloatParams{bc_num_params};
static constexpr int numIntParams{0};
enum IntParams
{
ipFilterSwitch
};

BitCrusher() : core::VoiceEffectTemplateBase<VFXConfig>(), lp(this) {}
BitCrusher() : core::VoiceEffectTemplateBase<VFXConfig>() {}

~BitCrusher() {}

basic_blocks::params::ParamMetaData paramAt(int idx) const
{
using pmd = basic_blocks::params::ParamMetaData;

switch ((bc_fparams)idx)
switch (idx)
{
case bc_samplerate:
case fpSamplerate:
if (keytrackOn)
{
return pmd()
.asFloat()
.withRange(0, 96)
.withName("Samplerate Ratio")
.withDefault(96)
.withLinearScaleFormatting("semitones");
}
return pmd()
.asAudibleFrequency()
.withRange(-12, 80)
.withName("sampleRate")
.withDefault(7.5);
case bc_bitdepth:
.withName("Samplerate")
.withDefault(80);
case fpBitdepth:
return pmd().asPercent().withName("bitdepth").withDefault(1.f);
case bc_zeropoint:
case fpZeropoint:
return pmd().asPercent().withName("zeropoint").withDefault(0.f);
case bc_cutoff:
return pmd().asAudibleFrequency().withName("cutoff");
case bc_resonance:
case fpCutoff:
if (keytrackOn)
{
return pmd()
.asFloat()
.withRange(0, 96)
.withName("Cutoff Offset")
.withDefault(96)
.withLinearScaleFormatting("semitones");
}
return pmd().asAudibleFrequency().withName("Cutoff");
case fpResonance:
return pmd().asPercent().withName("resonance").withDefault(0.707f);
default:
break;
Expand All @@ -74,18 +97,49 @@ template <typename VFXConfig> struct BitCrusher : core::VoiceEffectTemplateBase<
return pmd().withName("Unknown " + std::to_string(idx));
}

basic_blocks::params::ParamMetaData intParamAt(int idx) const
{
using pmd = basic_blocks::params::ParamMetaData;
switch (idx)
{
case ipFilterSwitch:
return pmd().asBool().withName("Filter Engage");
break;
}
return pmd().withName("oops");
}

void initVoiceEffectParams() { this->initToParamMetadataDefault(this); }

void processStereo(float *datainL, float *datainR, float *dataoutL, float *dataoutR,
float pitch)
{
float t = this->getSampleRateInv() * 440 *
this->equalNoteToPitch(this->getFloatParam(bc_samplerate));
float bd = 16.f * std::min(1.f, std::max(0.f, this->getFloatParam(bc_bitdepth)));
bool filterSwitch = this->getIntParam(ipFilterSwitch);
float sRate = this->getFloatParam(fpSamplerate);
if (keytrackOn)
{
sRate += pitch;
}
float t = this->getSampleRateInv() * 440 * this->equalNoteToPitch(sRate);
float bd = 16.f * std::min(1.f, std::max(0.f, this->getFloatParam(fpBitdepth)));
float b = powf(2, bd), b_inv = 1.f / b;

auto reso = std::clamp(this->getFloatParam(fpResonance), 0.f, 1.f);
auto cutoff = this->getFloatParam(fpCutoff);
if (keytrackOn)
{
cutoff += pitch;
}
auto filterFreq = 440 * this->note_to_pitch_ignoring_tuning(cutoff);

if (priorFreq != filterFreq && filterSwitch == true)
{
filter.template setCoeffForBlock<VFXConfig::blockSize>(
filters::CytomicSVF::LP, filterFreq, reso, this->getSampleRateInv(), 0.f);
}

int k;
float dVal = this->getFloatParam(bc_zeropoint);
float dVal = this->getFloatParam(fpZeropoint);
for (k = 0; k < VFXConfig::blockSize; k++)
{
float inputL = datainL[k];
Expand All @@ -111,15 +165,25 @@ template <typename VFXConfig> struct BitCrusher : core::VoiceEffectTemplateBase<
dataoutL[k] = level[0];
dataoutR[k] = level[1];
}
if (filterSwitch == true)
{
filter.processBlock<VFXConfig::blockSize>(dataoutL, dataoutR, dataoutL, dataoutR);
}
}

lp.coeff_LP2B(lp.calc_omega(this->getFloatParam(bc_cutoff) / 12.f),
std::clamp(this->getFloatParam(bc_resonance), 0.001f, 0.999f));
lp.process_block(dataoutL, dataoutR);
bool enableKeytrack(bool b)
{
auto res = (b != keytrackOn);
keytrackOn = b;
return res;
}
bool getKeytrack() const { return keytrackOn; }

protected:
float time[2]{0.f, 0.f}, level[2]{0.f, 0.f};
typename core::VoiceEffectTemplateBase<VFXConfig>::BiquadFilterType lp;
bool keytrackOn{false};
float priorFreq = -1.f;
sst::filters::CytomicSVF filter;
};
} // namespace sst::voice_effects::distortion

Expand Down
33 changes: 33 additions & 0 deletions include/sst/voice-effects/filter/StaticPhaser.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,27 @@ template <typename VFXConfig> struct StaticPhaser : core::VoiceEffectTemplateBas
switch (idx)
{
case fpCenterFrequency:
if (keytrackOn)
{
return pmd()
.asFloat()
.withRange(-48, 48)
.withName("Offset")
.withDefault(0)
.withLinearScaleFormatting("semitones");
}
return pmd().asAudibleFrequency().withName(std::string("Freq (L)")).withDefault(0);

case fpCenterFrequencyR:
if (keytrackOn)
{
return pmd()
.asFloat()
.withRange(-48, 48)
.withName("Offset")
.withDefault(0)
.withLinearScaleFormatting("semitones");
}
return pmd().asAudibleFrequency().withName("Freq R").withDefault(0);

break;
Expand Down Expand Up @@ -197,6 +215,10 @@ template <typename VFXConfig> struct StaticPhaser : core::VoiceEffectTemplateBas
for (int i = 0; i < numFloatParams; i++)
{
param[i] = this->getFloatParam(i);
if (i < 2 && keytrackOn)
{
param[i] += pitch;
}
diff = diff || (mLastParam[i] != param[i]);
}
for (int i = 0; i < numIntParams; ++i)
Expand All @@ -205,6 +227,9 @@ template <typename VFXConfig> struct StaticPhaser : core::VoiceEffectTemplateBas
idiff = idiff || (mLastIParam[i] != iparam[i]);
}

idiff |= (wasKeytrackOn != keytrackOn);
wasKeytrackOn = keytrackOn;

if (diff || idiff)
{
if (idiff)
Expand Down Expand Up @@ -257,8 +282,16 @@ template <typename VFXConfig> struct StaticPhaser : core::VoiceEffectTemplateBas
apfs[i].template retainCoeffForBlock<VFXConfig::blockSize>();
}
}
bool enableKeytrack(bool b)
{
auto res = (b != keytrackOn);
keytrackOn = b;
return res;
}
bool getKeytrack() const { return keytrackOn; }

protected:
bool keytrackOn{false}, wasKeytrackOn{false};
float fbAmt[2]{0.f, 0.f};
std::array<float, numFloatParams> mLastParam{};
std::array<int, numIntParams> mLastIParam{};
Expand Down
Loading

0 comments on commit 3d38bf4

Please sign in to comment.