Skip to content

Commit

Permalink
More waveshaper shapes and infrastructure (surge-synthesizer#4788)
Browse files Browse the repository at this point in the history
1. Fix a register bug in dcBlocker which only came into effect
   if you use R1/R2 != 0,1
2. Add a 'soft rectified' which is SOFT(2|x|-1) using ADAA,
   TANH and dcBlock in combination

Addresses surge-synthesizer#1964
  • Loading branch information
baconpaul authored Jul 29, 2021
1 parent dd49e03 commit a3b1018
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 35 deletions.
44 changes: 13 additions & 31 deletions src/common/FilterConfiguration.h
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,7 @@ enum ws_type
wst_fwrectify,
wst_poswav,
wst_negwav,
wst_softrect,

wst_singlefold,
wst_dualfold,
Expand All @@ -487,41 +488,21 @@ enum ws_type
n_ws_types,
};

const char wst_names[n_ws_types][16] = {"Off",
"Soft",
"Hard",
"Asymmetric",
"Sine",
"Digital",
"Soft Harm 2",
"Soft Harm 3",
"Soft Harm 4",
"Soft Harm 5",
"Abs Full Wave",
"Positive Wave",
"Negative Wave",
"Single Fold",
"Double Fold",
"WestCoast Fold",
"Additive 1+2",
"Additive 1+3",
"Additive 1+4",
"Additive 1+5",
"Additive 1234",
"Additive Saw 3",
"Additive Sqr 3",

"Fuzz",
"Fuzz SoftClip",
"Heavy Fuzz",
"Fuzz Center"
const char wst_names[n_ws_types][16] = {
"Off", "Soft", "Hard", "Asymmetric", "Sine",
"Digital", "Soft Harm 2", "Soft Harm 3", "Soft Harm 4", "Soft Harm 5",
"Abs Full Wave", "Positive Wave", "Negative Wave", "Soft Rectified", "Single Fold",
"Double Fold", "WestCoast Fold", "Additive 1+2", "Additive 1+3", "Additive 1+4",
"Additive 1+5", "Additive 1234", "Additive Saw 3", "Additive Sqr 3",

"Fuzz", "Fuzz SoftClip", "Heavy Fuzz", "Fuzz Center"

};

const char wst_ui_names[n_ws_types][16] = {
"Off", "Soft", "Hard", "Asym", "Sine", "Digi", "Harm 2", "Harm 3", "Harm 4",
"Harm 5", "Abs", "Pos", "Neg", "1Fold", "2Fold", "WstFold", "+12", "+13",
"+14", "+15", "+12345", "+Saw3", "+Sqr3", "Fuzz", "FzSft", "FzHvy", "FzCtr"};
"Off", "Soft", "Hard", "Asym", "Sine", "Digi", "Harm 2", "Harm 3", "Harm 4", "Harm 5",
"Abs", "Pos", "Neg", "SRect", "1Fold", "2Fold", "WstFold", "+12", "+13", "+14",
"+15", "+12345", "+Saw3", "+Sqr3", "Fuzz", "FzSft", "FzHvy", "FzCtr"};

struct WaveShaperSelectorMapper : public ParameterDiscreteIndexRemapper
{
Expand Down Expand Up @@ -556,6 +537,7 @@ struct WaveShaperSelectorMapper : public ParameterDiscreteIndexRemapper
p(wst_fwrectify, "Rectify");
p(wst_poswav, "Rectify");
p(wst_negwav, "Rectify");
p(wst_softrect, "Rectify");

p(wst_singlefold, "Folders");
p(wst_dualfold, "Folders");
Expand Down
36 changes: 32 additions & 4 deletions src/common/dsp/QuadFilterWaveshapers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -198,8 +198,8 @@ template <int R1, int R2> inline __m128 dcBlock(QuadFilterWaveshaperState *__res
// https://www.dsprelated.com/freebooks/filters/DC_Blocker.html
// y_n = x_n - x_n-1 + R y_n-1
const auto fac = _mm_set1_ps(0.9999);
auto dx = _mm_sub_ps(x, s->R[0]);
auto filtval = _mm_add_ps(dx, _mm_mul_ps(fac, s->R[1]));
auto dx = _mm_sub_ps(x, s->R[R1]);
auto filtval = _mm_add_ps(dx, _mm_mul_ps(fac, s->R[R2]));
s->R[R1] = x;
s->R[R2] = filtval;
s->init = _mm_setzero_ps();
Expand Down Expand Up @@ -436,8 +436,10 @@ __m128 PlusSqr3(QuadFilterWaveshaperState *__restrict s, __m128 in, __m128 drive

/*
* Given a function which is from x -> (F, adF) and two registers, do the ADAA
* Set updateInit to false if you are going to wrap this in a dcBlocker (which
* resets init itself) or other init adjusting function.
*/
template <void FandADF(__m128, __m128 &, __m128 &), int xR, int aR>
template <void FandADF(__m128, __m128 &, __m128 &), int xR, int aR, bool updateInit = true>
__m128 ADAA(QuadFilterWaveshaperState *__restrict s, __m128 x)
{
auto xPrior = s->R[xR];
Expand All @@ -460,7 +462,10 @@ __m128 ADAA(QuadFilterWaveshaperState *__restrict s, __m128 x)

s->R[xR] = x;
s->R[aR] = ad;
s->init = _mm_setzero_ps();
if (updateInit)
{
s->init = _mm_setzero_ps();
}

return r;
}
Expand Down Expand Up @@ -528,6 +533,27 @@ __m128 ADAA_FULL_WAVE(QuadFilterWaveshaperState *__restrict s, __m128 x, __m128
return ADAA<fwrect_kernel, 0, 1>(s, x);
}

void softrect_kernel(__m128 x, __m128 &F, __m128 &adF)
{
/*
* F : x > 0 ? 2x-1 : -2x - 1 = 2 * ( sgn(x) * x ) - 1
* adF : x > 0 ? x^2-x : -x^2 - x = sgn(x) * x^2 - x
*/
static const auto p2 = _mm_set1_ps(2.f);
static const auto p1 = _mm_set1_ps(1.f);
static const auto p05 = _mm_set1_ps(0.5f);
auto gz = _mm_cmpge_ps(x, _mm_setzero_ps());
auto sgn = _mm_sub_ps(_mm_and_ps(gz, p1), _mm_andnot_ps(gz, p1));

F = _mm_sub_ps(_mm_mul_ps(p2, _mm_mul_ps(sgn, x)), p1);
adF = _mm_sub_ps(_mm_mul_ps(sgn, _mm_mul_ps(x, x)), x);
}

__m128 ADAA_SOFTRECT_WAVE(QuadFilterWaveshaperState *__restrict s, __m128 x, __m128 drive)
{
return TANH(s, dcBlock<2, 3>(s, ADAA<softrect_kernel, 0, 1, false>(s, x)), drive);
}

template <int pts> struct FolderADAA
{
FolderADAA(std::initializer_list<float> xi, std::initializer_list<float> yi)
Expand Down Expand Up @@ -661,6 +687,8 @@ WaveshaperQFPtr GetQFPtrWaveshaper(int type)
return CHEBY_CORE<cheb5_kernel, false>;
case wst_fwrectify:
return ADAA_FULL_WAVE;
case wst_softrect:
return ADAA_SOFTRECT_WAVE;
case wst_poswav:
return ADAA_POS_WAVE<0, 1>;
case wst_negwav:
Expand Down

0 comments on commit a3b1018

Please sign in to comment.