#include "FilterBank.h" namespace serum { void FilterBank::prepare (double sampleRate, int maxBlockSize) { f1L.prepare (sampleRate, maxBlockSize); f1R.prepare (sampleRate, maxBlockSize); f2L.prepare (sampleRate, maxBlockSize); f2R.prepare (sampleRate, maxBlockSize); } void FilterBank::reset() { f1L.reset(); f1R.reset(); f2L.reset(); f2R.reset(); } void FilterBank::applySlot (Filter& f, float* buf, int n, bool on, int type, float cutoff, float res, float drive, float key, int slope, float noteHz) noexcept { if (on) f.process (buf, n, cutoff, res, drive, key, noteHz, type, slope); } void FilterBank::process (float* l, float* r, int numSamples, const FilterBankParams& p, float noteHz) noexcept { const bool anyFilter = p.f1On || p.f2On; if (! anyFilter) return; if (p.route == (int) FilterRoute::Serial) { applySlot (f1L, l, numSamples, p.f1On, p.f1Type, p.f1Cutoff, p.f1Res, p.f1Drive, p.f1Key, p.f1Slope, noteHz); applySlot (f1R, r, numSamples, p.f1On, p.f1Type, p.f1Cutoff, p.f1Res, p.f1Drive, p.f1Key, p.f1Slope, noteHz); applySlot (f2L, l, numSamples, p.f2On, p.f2Type, p.f2Cutoff, p.f2Res, p.f2Drive, p.f2Key, p.f2Slope, noteHz); applySlot (f2R, r, numSamples, p.f2On, p.f2Type, p.f2Cutoff, p.f2Res, p.f2Drive, p.f2Key, p.f2Slope, noteHz); } else if (p.route == (int) FilterRoute::Parallel) { // Run both filters on copies and crossfade. const float cutoff1 = p.f1On ? Filter::getCutoffHz (p.f1Cutoff, p.f1Key, noteHz) : 0.0f; const float cutoff2 = p.f2On ? Filter::getCutoffHz (p.f2Cutoff, p.f2Key, noteHz) : 0.0f; float f1l = 0.0f, f1r = 0.0f, f2l = 0.0f, f2r = 0.0f; for (int i = 0; i < numSamples; ++i) { f1l = l[i]; f1r = r[i]; f2l = l[i]; f2r = r[i]; if (p.f1On) { f1l = f1L.processSample (f1l, cutoff1, p.f1Res, p.f1Drive, p.f1Type, p.f1Slope); f1r = f1R.processSample (f1r, cutoff1, p.f1Res, p.f1Drive, p.f1Type, p.f1Slope); } if (p.f2On) { f2l = f2L.processSample (f2l, cutoff2, p.f2Res, p.f2Drive, p.f2Type, p.f2Slope); f2r = f2R.processSample (f2r, cutoff2, p.f2Res, p.f2Drive, p.f2Type, p.f2Slope); } const float m = p.mix; l[i] = f1l * (1.0f - m) + f2l * m; r[i] = f1r * (1.0f - m) + f2r * m; } } else // Split: filter 1 -> left, filter 2 -> right { applySlot (f1L, l, numSamples, p.f1On, p.f1Type, p.f1Cutoff, p.f1Res, p.f1Drive, p.f1Key, p.f1Slope, noteHz); applySlot (f2R, r, numSamples, p.f2On, p.f2Type, p.f2Cutoff, p.f2Res, p.f2Drive, p.f2Key, p.f2Slope, noteHz); } // Post-filter output level. if (p.out != 1.0f) { for (int i = 0; i < numSamples; ++i) { l[i] *= p.out; r[i] *= p.out; } } } } // namespace serum