diff --git a/scripts/generate_filters.sh b/scripts/generate_filters.sh index 305d3973..e519ea32 100755 --- a/scripts/generate_filters.sh +++ b/scripts/generate_filters.sh @@ -21,6 +21,7 @@ faustgen() { local cutoffVar=`echo "$code" | $SED -r 's%.*\("Cutoff", &[ \t]*([a-zA-Z0-9_]+).*%\1%;t;d'` local resoVar=`echo "$code" | $SED -r 's%.*\("Resonance", &[ \t]*([a-zA-Z0-9_]+).*%\1%;t;d'` local pkshVar=`echo "$code" | $SED -r 's%.*\("Peak/shelf gain", &[ \t]*([a-zA-Z0-9_]+).*%\1%;t;d'` + local bwVar=`echo "$code" | $SED -r 's%.*\("Bandwidth", &[ \t]*([a-zA-Z0-9_]+).*%\1%;t;d'` # suppress some faust-specific stuff we don't care echo "$code" \ @@ -47,6 +48,9 @@ faustgen() { if test ! -z "$pkshVar"; then $SED -r -i 's/\b'"$pkshVar"'\b/fPkShGain/' "$outfile" fi + if test ! -z "$bwVar"; then + $SED -r -i 's/\b'"$bwVar"'\b/fBandwidth/' "$outfile" + fi } for f in \ @@ -57,7 +61,8 @@ for f in \ Brf1p Brf2p \ Lsh Hsh Peq \ Pink \ - Lpf2pSv Hpf2pSv Bpf2pSv Brf2pSv + Lpf2pSv Hpf2pSv Bpf2pSv Brf2pSv \ + Eq do faustgen "$f" faustgen "2ch$f" diff --git a/src/sfizz/SfzFilter.cpp b/src/sfizz/SfzFilter.cpp index 3a16bc31..8c023dfc 100644 --- a/src/sfizz/SfzFilter.cpp +++ b/src/sfizz/SfzFilter.cpp @@ -13,6 +13,9 @@ namespace sfz { +//------------------------------------------------------------------------------ +// SFZ v2 multi-mode filter + template struct Filter::Impl { FilterType fType = kFilterNone; @@ -246,4 +249,84 @@ void Filter::setType(FilterType type) template class Filter<1>; template class Filter<2>; +//------------------------------------------------------------------------------ +// SFZ v1 equalizer filter + + +template +struct FilterEq::Impl { + sfzEq fDsp; +}; + +template +FilterEq::FilterEq() + : P{new Impl} +{ +} + +template +FilterEq::~FilterEq() +{ +} + +template +void FilterEq::init(double sampleRate) +{ + sfzEq &filter = P->fDsp; + + filter.init(sampleRate); +} + +template +void FilterEq::clear() +{ + sfzEq &filter = P->fDsp; + + filter.instanceClear(); +} + +template +void FilterEq::process(const float *const in[NCh], float *const out[NCh], float cutoff, float bw, float pksh, unsigned nframes) +{ + sfzEq &filter = P->fDsp; + + filter.setCutoff(cutoff); + filter.setBandwidth(bw); + filter.setPkShGain(pksh); + filter.compute(nframes, const_cast(in), const_cast(out)); +} + +template +void FilterEq::processModulated(const float *const in[NCh], float *const out[NCh], const float *cutoff, const float *bw, const float *pksh, unsigned nframes) +{ + sfzEq &filter = P->fDsp; + + unsigned frame = 0; + + while (frame < nframes) { + unsigned current = nframes - frame; + + if (current > config::filterControlInterval) + current = config::filterControlInterval; + + const float *current_in[NCh]; + float *current_out[NCh]; + + for (unsigned c = 0; c < NCh; ++c) { + current_in[c] = in[c] + frame; + current_out[c] = out[c] + frame; + } + + filter.setCutoff(cutoff[frame]); + filter.setBandwidth(bw[frame]); + filter.setPkShGain(pksh[frame]); + filter.compute(current, const_cast(current_in), const_cast(current_out)); + + frame += current; + } +} + +template class FilterEq<1>; +template class FilterEq<2>; + } // namespace sfz diff --git a/src/sfizz/SfzFilter.h b/src/sfizz/SfzFilter.h index d9c36286..a725062d 100644 --- a/src/sfizz/SfzFilter.h +++ b/src/sfizz/SfzFilter.h @@ -97,4 +97,53 @@ enum FilterType : int { kFilterPeq, }; +/** + Equalizer filter for SFZ v1 + Available for mono and stereo. (NCh=1, NCh=2) + + Parameters: + `cutoff`: it's the opcode `egN_freq` (Hz) + `bw`: it's the opcode `eqN_bw` (octave) + `pksh`: it's the opcode `eqN_gain` (dB) + */ +template +class FilterEq { +public: + FilterEq(); + ~FilterEq(); + + /** + Set up the filter constants. + Run it exactly once after instantiating. + */ + void init(double sampleRate); + + /** + Reinitialize the filter memory to zeros. + */ + void clear(); + + /** + Process one cycle of the filter without modulating cutoff or bandwidth. + `cutoff` is a frequency expressed in Hz. + `bw` is a bandwidth expressed in octaves. + `pksh` is a peak/shelf gain expressed in dB. + `in[i]` and `out[i]` may refer to identical buffers, for in-place processing + */ + void process(const float *const in[NCh], float *const out[NCh], float cutoff, float bw, float pksh, unsigned nframes); + + /** + Process one cycle of the filter with cutoff and bandwidth values varying over time. + `cutoff` is a frequency expressed in Hz. + `bw` is a bandwidth expressed in octaves. + `pksh` is a peak/shelf gain expressed in dB. + `in[i]` and `out[i]` may refer to identical buffers, for in-place processing + */ + void processModulated(const float *const in[NCh], float *const out[NCh], const float *cutoff, const float *bw, const float *pksh, unsigned nframes); + +private: + struct Impl; + std::unique_ptr P; +}; + } // namespace sfz diff --git a/src/sfizz/SfzFilterImpls.cxx b/src/sfizz/SfzFilterImpls.cxx index 59455466..54f529ab 100644 --- a/src/sfizz/SfzFilterImpls.cxx +++ b/src/sfizz/SfzFilterImpls.cxx @@ -36,6 +36,7 @@ struct UI {}; #include "gen/filters/sfzLsh.cxx" #include "gen/filters/sfzHsh.cxx" #include "gen/filters/sfzPeq.cxx" +#include "gen/filters/sfzEq.cxx" #include "gen/filters/sfz2chApf1p.cxx" #include "gen/filters/sfz2chBpf1p.cxx" @@ -60,35 +61,62 @@ struct UI {}; #include "gen/filters/sfz2chLsh.cxx" #include "gen/filters/sfz2chHsh.cxx" #include "gen/filters/sfz2chPeq.cxx" +#include "gen/filters/sfz2chEq.cxx" #if defined(__GNUC__) || defined(__clang__) #pragma GCC diagnostic pop #endif +/** + Wrapper of the most common kind of resonant filter + Parameterized by cutoff and Q + */ template struct sfzFilter : public F { void setCutoff(float v) { F::fCutoff = v; } void setQ(float v) { F::fQ = v; } void setPkShGain(float) {} }; +/** + Wrapper of non resonant filters + Parameterized by cutoff only + */ template struct sfzFilterNoQ : public F { void setCutoff(float v) { F::fCutoff = v; } void setQ(float) {} void setPkShGain(float) {} }; +/** + Wrapper of fixed filters + Not parameterized + */ template struct sfzFilterNoCutoff : public F { void setCutoff(float) {} void setQ(float) {} void setPkShGain(float) {} }; -template struct sfzFilterEq : public F { +/** + Wrapper of resonant filters with a gain control for peak or shelf + Parameterized by cutoff, Q, peak/shelf gain + */ +template struct sfzFilterPkSh : public F { void setCutoff(float v) { F::fCutoff = v; } void setQ(float v) { F::fQ = v; } void setPkShGain(float v) { F::fPkShGain = v; } }; +/** + Wrapper of equalizer filters with a bandwidth control + Parameterized by cutoff, bandwidth, peak/shelf gain + */ +template struct sfzFilterEq : public F { + void setCutoff(float v) { F::fCutoff = v; } + void setBandwidth(float v) { F::fBandwidth = v; } + void setPkShGain(float v) { F::fPkShGain = v; } +}; + template struct sfzLpf1p; template struct sfzLpf2p; template struct sfzLpf4p; @@ -112,6 +140,7 @@ template struct sfzBrf2pSv; template struct sfzLsh; template struct sfzHsh; template struct sfzPeq; +template struct sfzEq; template<> struct sfzLpf1p<1> : public sfzFilterNoQ {}; template<> struct sfzLpf2p<1> : public sfzFilter {}; @@ -133,9 +162,10 @@ template<> struct sfzLpf2pSv<1> : public sfzFilter {}; template<> struct sfzHpf2pSv<1> : public sfzFilter {}; template<> struct sfzBpf2pSv<1> : public sfzFilter {}; template<> struct sfzBrf2pSv<1> : public sfzFilter {}; -template<> struct sfzLsh<1> : public sfzFilterEq {}; -template<> struct sfzHsh<1> : public sfzFilterEq {}; -template<> struct sfzPeq<1> : public sfzFilterEq {}; +template<> struct sfzLsh<1> : public sfzFilterPkSh {}; +template<> struct sfzHsh<1> : public sfzFilterPkSh {}; +template<> struct sfzPeq<1> : public sfzFilterPkSh {}; +template<> struct sfzEq<1> : public sfzFilterEq {}; template<> struct sfzLpf1p<2> : public sfzFilterNoQ {}; template<> struct sfzLpf2p<2> : public sfzFilter {}; @@ -157,6 +187,7 @@ template<> struct sfzLpf2pSv<2> : public sfzFilter {}; template<> struct sfzHpf2pSv<2> : public sfzFilter {}; template<> struct sfzBpf2pSv<2> : public sfzFilter {}; template<> struct sfzBrf2pSv<2> : public sfzFilter {}; -template<> struct sfzLsh<2> : public sfzFilterEq {}; -template<> struct sfzHsh<2> : public sfzFilterEq {}; -template<> struct sfzPeq<2> : public sfzFilterEq {}; +template<> struct sfzLsh<2> : public sfzFilterPkSh {}; +template<> struct sfzHsh<2> : public sfzFilterPkSh {}; +template<> struct sfzPeq<2> : public sfzFilterPkSh {}; +template<> struct sfzEq<2> : public sfzFilterEq {}; diff --git a/src/sfizz/dsp/filters/sfz_filters.dsp b/src/sfizz/dsp/filters/sfz_filters.dsp index 27aa26e3..c3c98567 100644 --- a/src/sfizz/dsp/filters/sfz_filters.dsp +++ b/src/sfizz/dsp/filters/sfz_filters.dsp @@ -11,7 +11,7 @@ sk = library("sallenkey_modulable.dsp"); // Generators // the SFZ *noise generator -sfzNoise = no.noise : *(gate) : *(0.25); +sfzNoise = no.noise : *(0.25); //============================================================================== // Filters @@ -90,6 +90,12 @@ sfzHsh = fm.rbjHighShelfSmooth(smoothCoefs,cutoff,pkShGain,Q); // the SFZ peaking EQ filter sfzPeq = fm.rbjPeakingEqSmooth(smoothCoefs,cutoff,pkShGain,Q); +// the SFZ equalizer band +sfzEq = fm.rbjPeakingEqSmooth(smoothCoefs,cutoff,pkShGain,Q) with { + Q = 1./(2.*ma.sinh(0.5*log(2)*bandwidth*w0/sin(w0))); + w0 = 2*ma.PI*max(0,cutoff)/ma.SR; +}; + //============================================================================== // Filters (stereo) @@ -116,6 +122,7 @@ sfz2chBrf2pSv = par(i,2,sfzBrf2pSv); sfz2chLsh = par(i,2,sfzLsh); sfz2chHsh = par(i,2,sfzHsh); sfz2chPeq = par(i,2,sfzPeq); +sfz2chEq = par(i,2,sfzEq); //============================================================================== // Filter parameters @@ -123,6 +130,7 @@ sfz2chPeq = par(i,2,sfzPeq); cutoff = hslider("[01] Cutoff [unit:Hz] [scale:log]", 440.0, 50.0, 10000.0, 1.0); Q = vslider("[02] Resonance [unit:dB]", 0.0, 0.0, 40.0, 0.1) : ba.db2linear; pkShGain = vslider("[03] Peak/shelf gain [unit:dB]", 0.0, 0.0, 40.0, 0.1); +bandwidth = vslider("[04] Bandwidth [unit:octave]", 1.0, 0.1, 10.0, 0.01); // smoothing function to prevent fast changes of filter coefficients smoothCoefs = si.smoo; // TODO check if this is appropriate otherwise replace diff --git a/src/sfizz/gen/filters/sfz2chEq.cxx b/src/sfizz/gen/filters/sfz2chEq.cxx new file mode 100644 index 00000000..c12d7d56 --- /dev/null +++ b/src/sfizz/gen/filters/sfz2chEq.cxx @@ -0,0 +1,198 @@ +/* ------------------------------------------------------------ +author: "Jean Pierre Cimalando" +license: "BSD-2-Clause" +name: "sfz_filters" +Code generated with Faust 2.20.2 (https://faust.grame.fr) +Compilation options: -lang cpp -inpl -double -ftz 0 +------------------------------------------------------------ */ + +#ifndef __faust2chEq_H__ +#define __faust2chEq_H__ + +#ifndef FAUSTFLOAT +#define FAUSTFLOAT float +#endif + +/* link with : "" */ +#include +#include +#include + + +#ifndef FAUSTCLASS +#define FAUSTCLASS faust2chEq +#endif + +#ifdef __APPLE__ +#define exp10f __exp10f +#define exp10 __exp10 +#endif + +class faust2chEq : public dsp { + + public: + + int fSampleRate; + double fConst0; + double fConst1; + FAUSTFLOAT fCutoff; + double fConst2; + FAUSTFLOAT fBandwidth; + FAUSTFLOAT fPkShGain; + double fRec1[2]; + double fRec2[2]; + double fRec0[3]; + double fRec3[2]; + double fRec4[2]; + double fRec5[3]; + + public: + + void metadata(Meta* m) { + } + + int getNumInputs() { + return 2; + } + int getNumOutputs() { + return 2; + } + int getInputRate(int channel) { + int rate; + switch ((channel)) { + case 0: { + rate = 1; + break; + } + case 1: { + rate = 1; + break; + } + default: { + rate = -1; + break; + } + } + return rate; + } + int getOutputRate(int channel) { + int rate; + switch ((channel)) { + case 0: { + rate = 1; + break; + } + case 1: { + rate = 1; + break; + } + default: { + rate = -1; + break; + } + } + return rate; + } + + static void classInit(int sample_rate) { + } + + void instanceConstants(int sample_rate) { + fSampleRate = sample_rate; + fConst0 = std::min(192000.0, std::max(1.0, double(fSampleRate))); + fConst1 = (6.2831853071795862 / fConst0); + fConst2 = (2.1775860903036022 / fConst0); + } + + void instanceResetUserInterface() { + fCutoff = FAUSTFLOAT(440.0); + fBandwidth = FAUSTFLOAT(1.0); + fPkShGain = FAUSTFLOAT(0.0); + } + + void instanceClear() { + for (int l0 = 0; (l0 < 2); l0 = (l0 + 1)) { + fRec1[l0] = 0.0; + } + for (int l1 = 0; (l1 < 2); l1 = (l1 + 1)) { + fRec2[l1] = 0.0; + } + for (int l2 = 0; (l2 < 3); l2 = (l2 + 1)) { + fRec0[l2] = 0.0; + } + for (int l3 = 0; (l3 < 2); l3 = (l3 + 1)) { + fRec3[l3] = 0.0; + } + for (int l4 = 0; (l4 < 2); l4 = (l4 + 1)) { + fRec4[l4] = 0.0; + } + for (int l5 = 0; (l5 < 3); l5 = (l5 + 1)) { + fRec5[l5] = 0.0; + } + } + + void init(int sample_rate) { + classInit(sample_rate); + instanceInit(sample_rate); + } + void instanceInit(int sample_rate) { + instanceConstants(sample_rate); + instanceResetUserInterface(); + instanceClear(); + } + + faust2chEq* clone() { + return new faust2chEq(); + } + + int getSampleRate() { + return fSampleRate; + } + + void buildUserInterface(UI* ui_interface) { + } + + void compute(int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) { + FAUSTFLOAT* input0 = inputs[0]; + FAUSTFLOAT* input1 = inputs[1]; + FAUSTFLOAT* output0 = outputs[0]; + FAUSTFLOAT* output1 = outputs[1]; + double fSlow0 = std::max(0.0, double(fCutoff)); + double fSlow1 = (fConst1 * fSlow0); + double fSlow2 = std::sin(fSlow1); + double fSlow3 = std::max(0.001, (0.5 / double(sinh(double((fConst2 * ((fSlow0 * double(fBandwidth)) / fSlow2))))))); + double fSlow4 = std::pow(10.0, (0.025000000000000001 * double(fPkShGain))); + double fSlow5 = (0.5 * (fSlow2 / (fSlow3 * fSlow4))); + double fSlow6 = (fSlow5 + 1.0); + double fSlow7 = (0.0010000000000000009 * ((0.0 - (2.0 * std::cos(fSlow1))) / fSlow6)); + double fSlow8 = (0.0010000000000000009 * ((1.0 - fSlow5) / fSlow6)); + double fSlow9 = (0.5 * ((fSlow2 * fSlow4) / fSlow3)); + double fSlow10 = (0.0010000000000000009 * ((fSlow9 + 1.0) / fSlow6)); + double fSlow11 = (0.0010000000000000009 * ((1.0 - fSlow9) / fSlow6)); + for (int i = 0; (i < count); i = (i + 1)) { + double fTemp0 = double(input0[i]); + double fTemp1 = double(input1[i]); + fRec1[0] = (fSlow7 + (0.999 * fRec1[1])); + double fTemp2 = (fRec1[0] * fRec0[1]); + fRec2[0] = (fSlow8 + (0.999 * fRec2[1])); + fRec0[0] = (fTemp0 - (fTemp2 + (fRec2[0] * fRec0[2]))); + fRec3[0] = (fSlow10 + (0.999 * fRec3[1])); + fRec4[0] = (fSlow11 + (0.999 * fRec4[1])); + output0[i] = FAUSTFLOAT((((fRec0[0] * fRec3[0]) + fTemp2) + (fRec4[0] * fRec0[2]))); + double fTemp3 = (fRec1[0] * fRec5[1]); + fRec5[0] = (fTemp1 - (fTemp3 + (fRec2[0] * fRec5[2]))); + output1[i] = FAUSTFLOAT(((fTemp3 + (fRec3[0] * fRec5[0])) + (fRec4[0] * fRec5[2]))); + fRec1[1] = fRec1[0]; + fRec2[1] = fRec2[0]; + fRec0[2] = fRec0[1]; + fRec0[1] = fRec0[0]; + fRec3[1] = fRec3[0]; + fRec4[1] = fRec4[0]; + fRec5[2] = fRec5[1]; + fRec5[1] = fRec5[0]; + } + } + +}; + +#endif diff --git a/src/sfizz/gen/filters/sfz2chPeq.cxx b/src/sfizz/gen/filters/sfz2chPeq.cxx index 60af24c2..8db81037 100644 --- a/src/sfizz/gen/filters/sfz2chPeq.cxx +++ b/src/sfizz/gen/filters/sfz2chPeq.cxx @@ -175,7 +175,7 @@ class faust2chPeq : public dsp { output0[i] = FAUSTFLOAT((((fRec0[0] * fRec3[0]) + fTemp2) + (fRec4[0] * fRec0[2]))); double fTemp3 = (fRec1[0] * fRec5[1]); fRec5[0] = (fTemp1 - (fTemp3 + (fRec2[0] * fRec5[2]))); - output1[i] = FAUSTFLOAT(((fRec3[0] * fRec5[0]) + (fTemp3 + (fRec4[0] * fRec5[2])))); + output1[i] = FAUSTFLOAT(((fTemp3 + (fRec3[0] * fRec5[0])) + (fRec4[0] * fRec5[2]))); fRec1[1] = fRec1[0]; fRec2[1] = fRec2[0]; fRec0[2] = fRec0[1]; diff --git a/src/sfizz/gen/filters/sfzEq.cxx b/src/sfizz/gen/filters/sfzEq.cxx new file mode 100644 index 00000000..c674caa4 --- /dev/null +++ b/src/sfizz/gen/filters/sfzEq.cxx @@ -0,0 +1,178 @@ +/* ------------------------------------------------------------ +author: "Jean Pierre Cimalando" +license: "BSD-2-Clause" +name: "sfz_filters" +Code generated with Faust 2.20.2 (https://faust.grame.fr) +Compilation options: -lang cpp -inpl -double -ftz 0 +------------------------------------------------------------ */ + +#ifndef __faustEq_H__ +#define __faustEq_H__ + +#ifndef FAUSTFLOAT +#define FAUSTFLOAT float +#endif + +/* link with : "" */ +#include +#include +#include + + +#ifndef FAUSTCLASS +#define FAUSTCLASS faustEq +#endif + +#ifdef __APPLE__ +#define exp10f __exp10f +#define exp10 __exp10 +#endif + +class faustEq : public dsp { + + public: + + int fSampleRate; + double fConst0; + double fConst1; + FAUSTFLOAT fCutoff; + double fConst2; + FAUSTFLOAT fBandwidth; + FAUSTFLOAT fPkShGain; + double fRec1[2]; + double fRec2[2]; + double fRec0[3]; + double fRec3[2]; + double fRec4[2]; + + public: + + void metadata(Meta* m) { + } + + int getNumInputs() { + return 1; + } + int getNumOutputs() { + return 1; + } + int getInputRate(int channel) { + int rate; + switch ((channel)) { + case 0: { + rate = 1; + break; + } + default: { + rate = -1; + break; + } + } + return rate; + } + int getOutputRate(int channel) { + int rate; + switch ((channel)) { + case 0: { + rate = 1; + break; + } + default: { + rate = -1; + break; + } + } + return rate; + } + + static void classInit(int sample_rate) { + } + + void instanceConstants(int sample_rate) { + fSampleRate = sample_rate; + fConst0 = std::min(192000.0, std::max(1.0, double(fSampleRate))); + fConst1 = (6.2831853071795862 / fConst0); + fConst2 = (2.1775860903036022 / fConst0); + } + + void instanceResetUserInterface() { + fCutoff = FAUSTFLOAT(440.0); + fBandwidth = FAUSTFLOAT(1.0); + fPkShGain = FAUSTFLOAT(0.0); + } + + void instanceClear() { + for (int l0 = 0; (l0 < 2); l0 = (l0 + 1)) { + fRec1[l0] = 0.0; + } + for (int l1 = 0; (l1 < 2); l1 = (l1 + 1)) { + fRec2[l1] = 0.0; + } + for (int l2 = 0; (l2 < 3); l2 = (l2 + 1)) { + fRec0[l2] = 0.0; + } + for (int l3 = 0; (l3 < 2); l3 = (l3 + 1)) { + fRec3[l3] = 0.0; + } + for (int l4 = 0; (l4 < 2); l4 = (l4 + 1)) { + fRec4[l4] = 0.0; + } + } + + void init(int sample_rate) { + classInit(sample_rate); + instanceInit(sample_rate); + } + void instanceInit(int sample_rate) { + instanceConstants(sample_rate); + instanceResetUserInterface(); + instanceClear(); + } + + faustEq* clone() { + return new faustEq(); + } + + int getSampleRate() { + return fSampleRate; + } + + void buildUserInterface(UI* ui_interface) { + } + + void compute(int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) { + FAUSTFLOAT* input0 = inputs[0]; + FAUSTFLOAT* output0 = outputs[0]; + double fSlow0 = std::max(0.0, double(fCutoff)); + double fSlow1 = (fConst1 * fSlow0); + double fSlow2 = std::sin(fSlow1); + double fSlow3 = std::max(0.001, (0.5 / double(sinh(double((fConst2 * ((fSlow0 * double(fBandwidth)) / fSlow2))))))); + double fSlow4 = std::pow(10.0, (0.025000000000000001 * double(fPkShGain))); + double fSlow5 = (0.5 * (fSlow2 / (fSlow3 * fSlow4))); + double fSlow6 = (fSlow5 + 1.0); + double fSlow7 = (0.0010000000000000009 * ((0.0 - (2.0 * std::cos(fSlow1))) / fSlow6)); + double fSlow8 = (0.0010000000000000009 * ((1.0 - fSlow5) / fSlow6)); + double fSlow9 = (0.5 * ((fSlow2 * fSlow4) / fSlow3)); + double fSlow10 = (0.0010000000000000009 * ((fSlow9 + 1.0) / fSlow6)); + double fSlow11 = (0.0010000000000000009 * ((1.0 - fSlow9) / fSlow6)); + for (int i = 0; (i < count); i = (i + 1)) { + double fTemp0 = double(input0[i]); + fRec1[0] = (fSlow7 + (0.999 * fRec1[1])); + double fTemp1 = (fRec1[0] * fRec0[1]); + fRec2[0] = (fSlow8 + (0.999 * fRec2[1])); + fRec0[0] = (fTemp0 - (fTemp1 + (fRec2[0] * fRec0[2]))); + fRec3[0] = (fSlow10 + (0.999 * fRec3[1])); + fRec4[0] = (fSlow11 + (0.999 * fRec4[1])); + output0[i] = FAUSTFLOAT((((fRec0[0] * fRec3[0]) + fTemp1) + (fRec4[0] * fRec0[2]))); + fRec1[1] = fRec1[0]; + fRec2[1] = fRec2[0]; + fRec0[2] = fRec0[1]; + fRec0[1] = fRec0[0]; + fRec3[1] = fRec3[0]; + fRec4[1] = fRec4[0]; + } + } + +}; + +#endif