feat(fx): add effect rack and effect units
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
#include "Reverb.h"
|
||||
|
||||
namespace serum
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
constexpr int combTuning[8] = { 1116, 1188, 1277, 1356, 1422, 1491, 1557, 1617 };
|
||||
constexpr int allpassTuning[4] = { 556, 441, 341, 225 };
|
||||
}
|
||||
|
||||
void ReverbUnit::prepare (double sampleRate, int)
|
||||
{
|
||||
sr = sampleRate;
|
||||
const double scale = sr / 44100.0;
|
||||
|
||||
for (int i = 0; i < 8; ++i)
|
||||
{
|
||||
const int len = (int) (combTuning[i] * scale) + 1;
|
||||
combL[(size_t) i].assign ((size_t) len, 0.0f);
|
||||
combR[(size_t) i].assign ((size_t) len, 0.0f);
|
||||
}
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
const int len = (int) (allpassTuning[i] * scale) + 1;
|
||||
apL[(size_t) i].assign ((size_t) len, 0.0f);
|
||||
apR[(size_t) i].assign ((size_t) len, 0.0f);
|
||||
}
|
||||
|
||||
const int preLen = (int) (sr * 0.2);
|
||||
preL.assign ((size_t) preLen, 0.0f);
|
||||
preR.assign ((size_t) preLen, 0.0f);
|
||||
reset();
|
||||
}
|
||||
|
||||
void ReverbUnit::reset()
|
||||
{
|
||||
for (int i = 0; i < 8; ++i)
|
||||
{
|
||||
std::fill (combL[(size_t) i].begin(), combL[(size_t) i].end(), 0.0f);
|
||||
std::fill (combR[(size_t) i].begin(), combR[(size_t) i].end(), 0.0f);
|
||||
combPosL[(size_t) i] = combPosR[(size_t) i] = 0;
|
||||
combFiltL[(size_t) i] = combFiltR[(size_t) i] = 0.0f;
|
||||
}
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
std::fill (apL[(size_t) i].begin(), apL[(size_t) i].end(), 0.0f);
|
||||
std::fill (apR[(size_t) i].begin(), apR[(size_t) i].end(), 0.0f);
|
||||
apPosL[(size_t) i] = apPosR[(size_t) i] = 0;
|
||||
}
|
||||
std::fill (preL.begin(), preL.end(), 0.0f);
|
||||
std::fill (preR.begin(), preR.end(), 0.0f);
|
||||
prePos = 0;
|
||||
}
|
||||
|
||||
void ReverbUnit::process (float* l, float* r, int numSamples, const float p[4])
|
||||
{
|
||||
const float feedback = maps::sizeToValue (p[0]);
|
||||
const float damping = p[1];
|
||||
const float width = p[2];
|
||||
const int preLen = (int) preL.size();
|
||||
const float preDelay = (preLen > 0) ? p[3] * 0.15f * sr : 0.0f;
|
||||
|
||||
for (int i = 0; i < numSamples; ++i)
|
||||
{
|
||||
// Predelay.
|
||||
float inL = l[i], inR = r[i];
|
||||
if (preLen > 0)
|
||||
{
|
||||
const int read = (prePos - (int) preDelay + preLen) % preLen;
|
||||
preL[(size_t) prePos] = inL;
|
||||
preR[(size_t) prePos] = inR;
|
||||
inL = preL[(size_t) read];
|
||||
inR = preR[(size_t) read];
|
||||
prePos = (prePos + 1) % preLen;
|
||||
}
|
||||
|
||||
// Combs.
|
||||
float sumL = 0.0f, sumR = 0.0f;
|
||||
for (int c = 0; c < 8; ++c)
|
||||
{
|
||||
auto& buf = combL[(size_t) c];
|
||||
const int pos = combPosL[(size_t) c];
|
||||
float out = buf[(size_t) pos];
|
||||
combFiltL[(size_t) c] = out * (1.0f - damping) + combFiltL[(size_t) c] * damping;
|
||||
buf[(size_t) pos] = inL + combFiltL[(size_t) c] * feedback;
|
||||
combPosL[(size_t) c] = (pos + 1) % (int) buf.size();
|
||||
sumL += out;
|
||||
}
|
||||
for (int c = 0; c < 8; ++c)
|
||||
{
|
||||
auto& buf = combR[(size_t) c];
|
||||
const int pos = combPosR[(size_t) c];
|
||||
float out = buf[(size_t) pos];
|
||||
combFiltR[(size_t) c] = out * (1.0f - damping) + combFiltR[(size_t) c] * damping;
|
||||
buf[(size_t) pos] = inR + combFiltR[(size_t) c] * feedback;
|
||||
combPosR[(size_t) c] = (pos + 1) % (int) buf.size();
|
||||
sumR += out;
|
||||
}
|
||||
|
||||
// Allpasses.
|
||||
float aL = sumL, aR = sumR;
|
||||
for (int a = 0; a < 4; ++a)
|
||||
{
|
||||
auto& buf = apL[(size_t) a];
|
||||
const int pos = apPosL[(size_t) a];
|
||||
const float stored = buf[(size_t) pos];
|
||||
buf[(size_t) pos] = aL + stored * 0.5f;
|
||||
aL = stored - aL;
|
||||
apPosL[(size_t) a] = (pos + 1) % (int) buf.size();
|
||||
}
|
||||
for (int a = 0; a < 4; ++a)
|
||||
{
|
||||
auto& buf = apR[(size_t) a];
|
||||
const int pos = apPosR[(size_t) a];
|
||||
const float stored = buf[(size_t) pos];
|
||||
buf[(size_t) pos] = aR + stored * 0.5f;
|
||||
aR = stored - aR;
|
||||
apPosR[(size_t) a] = (pos + 1) % (int) buf.size();
|
||||
}
|
||||
|
||||
// Width (stereo cross-mix).
|
||||
const float w = 1.0f - width * 0.5f;
|
||||
const float outL = aL * w + aR * (1.0f - w);
|
||||
const float outR = aR * w + aL * (1.0f - w);
|
||||
|
||||
l[i] = outL;
|
||||
r[i] = outR;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace serum
|
||||
Reference in New Issue
Block a user