Add the multi-mode filter, mono and stereo
This commit is contained in:
parent
b6130ccf02
commit
ac4dfff729
10 changed files with 1145 additions and 0 deletions
64
scripts/generate_filters.sh
Executable file
64
scripts/generate_filters.sh
Executable file
|
|
@ -0,0 +1,64 @@
|
||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
|
||||||
|
if ! test -d "src"; then
|
||||||
|
echo "Please run this in the project root directory."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
FAUSTARGS="-double -inpl"
|
||||||
|
|
||||||
|
# support GNU sed only, use gsed on a Mac
|
||||||
|
test -z "$SED" && SED=sed
|
||||||
|
|
||||||
|
faustgen() {
|
||||||
|
mkdir -p src/sfizz/gen/filters
|
||||||
|
local outfile=src/sfizz/gen/filters/sfz"$1".cxx
|
||||||
|
|
||||||
|
local code=`faust $FAUSTARGS -pn sfz"$1" -cn faust"$1" src/sfizz/dsp/filters/sfz_filters.dsp`
|
||||||
|
|
||||||
|
# find variable names of our controls
|
||||||
|
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'`
|
||||||
|
|
||||||
|
# suppress some faust-specific stuff we don't care
|
||||||
|
echo "$code" \
|
||||||
|
| fgrep -v -- '->declare(' \
|
||||||
|
| fgrep -v -- '->openHorizontalBox(' \
|
||||||
|
| fgrep -v -- '->openVerticalBox(' \
|
||||||
|
| fgrep -v -- '->closeBox(' \
|
||||||
|
| fgrep -v -- '->addHorizontalSlider(' \
|
||||||
|
| fgrep -v -- '->addVerticalSlider(' \
|
||||||
|
> "$outfile"
|
||||||
|
|
||||||
|
# direct access to parameter variables
|
||||||
|
$SED -r -i 's/\bprivate:/public:/' "$outfile"
|
||||||
|
# no virtuals please
|
||||||
|
$SED -r -i 's/\bvirtual\b//' "$outfile"
|
||||||
|
|
||||||
|
# rename the variables for us to access more easily
|
||||||
|
if test ! -z "$cutoffVar"; then
|
||||||
|
$SED -r -i 's/\b'"$cutoffVar"'\b/fCutoff/' "$outfile"
|
||||||
|
fi
|
||||||
|
if test ! -z "$resoVar"; then
|
||||||
|
$SED -r -i 's/\b'"$resoVar"'\b/fQ/' "$outfile"
|
||||||
|
fi
|
||||||
|
if test ! -z "$pkshVar"; then
|
||||||
|
$SED -r -i 's/\b'"$pkshVar"'\b/fPkShGain/' "$outfile"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
for f in \
|
||||||
|
Lpf1p Lpf2p Lpf4p Lpf6p \
|
||||||
|
Hpf1p Hpf2p Hpf4p Hpf6p \
|
||||||
|
Bpf1p Bpf2p Bpf4p Bpf6p \
|
||||||
|
Apf1p \
|
||||||
|
Brf1p Brf2p \
|
||||||
|
Lsh Hsh Peq \
|
||||||
|
Pink \
|
||||||
|
Lpf2pSv Hpf2pSv Bpf2pSv Brf2pSv
|
||||||
|
do
|
||||||
|
faustgen "$f"
|
||||||
|
faustgen "2ch$f"
|
||||||
|
done
|
||||||
|
|
@ -9,6 +9,7 @@ set (SFIZZ_SOURCES
|
||||||
sfizz/Oversampler.cpp
|
sfizz/Oversampler.cpp
|
||||||
sfizz/FloatEnvelopes.cpp
|
sfizz/FloatEnvelopes.cpp
|
||||||
sfizz/Logger.cpp
|
sfizz/Logger.cpp
|
||||||
|
sfizz/SfzFilter.cpp
|
||||||
)
|
)
|
||||||
include (SfizzSIMDSourceFilesCheck)
|
include (SfizzSIMDSourceFilesCheck)
|
||||||
|
|
||||||
|
|
|
||||||
256
src/sfizz/SfzFilter.cpp
Normal file
256
src/sfizz/SfzFilter.cpp
Normal file
|
|
@ -0,0 +1,256 @@
|
||||||
|
// SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
|
||||||
|
// This code is part of the sfizz library and is licensed under a BSD 2-clause
|
||||||
|
// license. You should have receive a LICENSE.md file along with the code.
|
||||||
|
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
|
||||||
|
|
||||||
|
#include "SfzFilter.h"
|
||||||
|
#include "SfzFilterDefs.h"
|
||||||
|
#include "SfzFilterImpls.cxx"
|
||||||
|
#include <cstring>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
namespace sfz {
|
||||||
|
|
||||||
|
template <unsigned NCh>
|
||||||
|
struct Filter<NCh>::Impl {
|
||||||
|
FilterType fType = kFilterNone;
|
||||||
|
|
||||||
|
sfzLpf1p<NCh> fDspLpf1p;
|
||||||
|
sfzLpf2p<NCh> fDspLpf2p;
|
||||||
|
sfzLpf4p<NCh> fDspLpf4p;
|
||||||
|
sfzLpf6p<NCh> fDspLpf6p;
|
||||||
|
sfzHpf1p<NCh> fDspHpf1p;
|
||||||
|
sfzHpf2p<NCh> fDspHpf2p;
|
||||||
|
sfzHpf4p<NCh> fDspHpf4p;
|
||||||
|
sfzHpf6p<NCh> fDspHpf6p;
|
||||||
|
sfzBpf1p<NCh> fDspBpf1p;
|
||||||
|
sfzBpf2p<NCh> fDspBpf2p;
|
||||||
|
sfzBpf4p<NCh> fDspBpf4p;
|
||||||
|
sfzBpf6p<NCh> fDspBpf6p;
|
||||||
|
sfzApf1p<NCh> fDspApf1p;
|
||||||
|
sfzBrf1p<NCh> fDspBrf1p;
|
||||||
|
sfzBrf2p<NCh> fDspBrf2p;
|
||||||
|
sfzPink<NCh> fDspPink;
|
||||||
|
sfzLpf2pSv<NCh> fDspLpf2pSv;
|
||||||
|
sfzHpf2pSv<NCh> fDspHpf2pSv;
|
||||||
|
sfzBpf2pSv<NCh> fDspBpf2pSv;
|
||||||
|
sfzBrf2pSv<NCh> fDspBrf2pSv;
|
||||||
|
sfzLsh<NCh> fDspLsh;
|
||||||
|
sfzHsh<NCh> fDspHsh;
|
||||||
|
sfzPeq<NCh> fDspPeq;
|
||||||
|
|
||||||
|
template <class F> static void process(F &filter, const float *const in[NCh], float *const out[NCh], float cutoff, float q, float pksh, unsigned nframes);
|
||||||
|
template <class F> static void processModulated(F &filter, const float *const in[NCh], float *const out[NCh], const float *cutoff, const float *q, const float *pksh, unsigned nframes);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <unsigned NCh>
|
||||||
|
Filter<NCh>::Filter()
|
||||||
|
: P{new Impl}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template <unsigned NCh>
|
||||||
|
Filter<NCh>::~Filter()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template <unsigned NCh>
|
||||||
|
void Filter<NCh>::init(double sampleRate)
|
||||||
|
{
|
||||||
|
P->fDspLpf1p.init(sampleRate);
|
||||||
|
P->fDspLpf2p.init(sampleRate);
|
||||||
|
P->fDspLpf4p.init(sampleRate);
|
||||||
|
P->fDspLpf6p.init(sampleRate);
|
||||||
|
P->fDspHpf1p.init(sampleRate);
|
||||||
|
P->fDspHpf2p.init(sampleRate);
|
||||||
|
P->fDspHpf4p.init(sampleRate);
|
||||||
|
P->fDspHpf6p.init(sampleRate);
|
||||||
|
P->fDspBpf1p.init(sampleRate);
|
||||||
|
P->fDspBpf2p.init(sampleRate);
|
||||||
|
P->fDspBpf4p.init(sampleRate);
|
||||||
|
P->fDspBpf6p.init(sampleRate);
|
||||||
|
P->fDspApf1p.init(sampleRate);
|
||||||
|
P->fDspBrf1p.init(sampleRate);
|
||||||
|
P->fDspBrf2p.init(sampleRate);
|
||||||
|
P->fDspPink.init(sampleRate);
|
||||||
|
P->fDspLpf2pSv.init(sampleRate);
|
||||||
|
P->fDspHpf2pSv.init(sampleRate);
|
||||||
|
P->fDspBpf2pSv.init(sampleRate);
|
||||||
|
P->fDspBrf2pSv.init(sampleRate);
|
||||||
|
P->fDspLsh.init(sampleRate);
|
||||||
|
P->fDspHsh.init(sampleRate);
|
||||||
|
P->fDspPeq.init(sampleRate);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <unsigned NCh>
|
||||||
|
void Filter<NCh>::clear()
|
||||||
|
{
|
||||||
|
switch (P->fType) {
|
||||||
|
case kFilterNone: break;
|
||||||
|
case kFilterApf1p: P->fDspApf1p.instanceClear(); break;
|
||||||
|
case kFilterBpf1p: P->fDspBpf1p.instanceClear(); break;
|
||||||
|
case kFilterBpf2p: P->fDspBpf2p.instanceClear(); break;
|
||||||
|
case kFilterBpf4p: P->fDspBpf4p.instanceClear(); break;
|
||||||
|
case kFilterBpf6p: P->fDspBpf6p.instanceClear(); break;
|
||||||
|
case kFilterBrf1p: P->fDspBrf1p.instanceClear(); break;
|
||||||
|
case kFilterBrf2p: P->fDspBrf2p.instanceClear(); break;
|
||||||
|
case kFilterHpf1p: P->fDspHpf1p.instanceClear(); break;
|
||||||
|
case kFilterHpf2p: P->fDspHpf2p.instanceClear(); break;
|
||||||
|
case kFilterHpf4p: P->fDspHpf4p.instanceClear(); break;
|
||||||
|
case kFilterHpf6p: P->fDspHpf6p.instanceClear(); break;
|
||||||
|
case kFilterLpf1p: P->fDspLpf1p.instanceClear(); break;
|
||||||
|
case kFilterLpf2p: P->fDspLpf2p.instanceClear(); break;
|
||||||
|
case kFilterLpf4p: P->fDspLpf4p.instanceClear(); break;
|
||||||
|
case kFilterLpf6p: P->fDspLpf6p.instanceClear(); break;
|
||||||
|
case kFilterPink: P->fDspPink.instanceClear(); break;
|
||||||
|
case kFilterLpf2pSv: P->fDspLpf2pSv.instanceClear(); break;
|
||||||
|
case kFilterHpf2pSv: P->fDspHpf2pSv.instanceClear(); break;
|
||||||
|
case kFilterBpf2pSv: P->fDspBpf2pSv.instanceClear(); break;
|
||||||
|
case kFilterBrf2pSv: P->fDspBrf2pSv.instanceClear(); break;
|
||||||
|
case kFilterLsh: P->fDspLsh.instanceClear(); break;
|
||||||
|
case kFilterHsh: P->fDspHsh.instanceClear(); break;
|
||||||
|
case kFilterPeq: P->fDspPeq.instanceClear(); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <unsigned NCh>
|
||||||
|
template <class F>
|
||||||
|
void Filter<NCh>::Impl::process(F &filter, const float *const in[NCh], float *const out[NCh], float cutoff, float q, float pksh, unsigned nframes)
|
||||||
|
{
|
||||||
|
filter.setCutoff(cutoff);
|
||||||
|
filter.setQ(q);
|
||||||
|
filter.setPkShGain(pksh);
|
||||||
|
filter.compute(nframes, const_cast<float **>(in), const_cast<float **>(out));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <unsigned NCh>
|
||||||
|
void Filter<NCh>::process(const float *const in[NCh], float *const out[NCh], float cutoff, float q, float pksh, unsigned nframes)
|
||||||
|
{
|
||||||
|
if (P->fType == kFilterNone) {
|
||||||
|
for (unsigned c = 0; c < NCh; ++c) {
|
||||||
|
const float *ch_in = in[c];
|
||||||
|
float *ch_out = out[c];
|
||||||
|
if (ch_in != ch_out)
|
||||||
|
std::memcpy(ch_out, ch_in, nframes * sizeof(float));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (P->fType) {
|
||||||
|
case kFilterApf1p: P->process(P->fDspApf1p, in, out, cutoff, q, pksh, nframes); break;
|
||||||
|
case kFilterBpf1p: P->process(P->fDspBpf1p, in, out, cutoff, q, pksh, nframes); break;
|
||||||
|
case kFilterBpf2p: P->process(P->fDspBpf2p, in, out, cutoff, q, pksh, nframes); break;
|
||||||
|
case kFilterBpf4p: P->process(P->fDspBpf4p, in, out, cutoff, q, pksh, nframes); break;
|
||||||
|
case kFilterBpf6p: P->process(P->fDspBpf6p, in, out, cutoff, q, pksh, nframes); break;
|
||||||
|
case kFilterBrf1p: P->process(P->fDspBrf1p, in, out, cutoff, q, pksh, nframes); break;
|
||||||
|
case kFilterBrf2p: P->process(P->fDspBrf2p, in, out, cutoff, q, pksh, nframes); break;
|
||||||
|
case kFilterHpf1p: P->process(P->fDspHpf1p, in, out, cutoff, q, pksh, nframes); break;
|
||||||
|
case kFilterHpf2p: P->process(P->fDspHpf2p, in, out, cutoff, q, pksh, nframes); break;
|
||||||
|
case kFilterHpf4p: P->process(P->fDspHpf4p, in, out, cutoff, q, pksh, nframes); break;
|
||||||
|
case kFilterHpf6p: P->process(P->fDspHpf6p, in, out, cutoff, q, pksh, nframes); break;
|
||||||
|
case kFilterLpf1p: P->process(P->fDspLpf1p, in, out, cutoff, q, pksh, nframes); break;
|
||||||
|
case kFilterLpf2p: P->process(P->fDspLpf2p, in, out, cutoff, q, pksh, nframes); break;
|
||||||
|
case kFilterLpf4p: P->process(P->fDspLpf4p, in, out, cutoff, q, pksh, nframes); break;
|
||||||
|
case kFilterLpf6p: P->process(P->fDspLpf6p, in, out, cutoff, q, pksh, nframes); break;
|
||||||
|
case kFilterPink: P->process(P->fDspPink, in, out, cutoff, q, pksh, nframes); break;
|
||||||
|
case kFilterLpf2pSv: P->process(P->fDspLpf2pSv, in, out, cutoff, q, pksh, nframes); break;
|
||||||
|
case kFilterHpf2pSv: P->process(P->fDspHpf2pSv, in, out, cutoff, q, pksh, nframes); break;
|
||||||
|
case kFilterBpf2pSv: P->process(P->fDspBpf2pSv, in, out, cutoff, q, pksh, nframes); break;
|
||||||
|
case kFilterBrf2pSv: P->process(P->fDspBrf2pSv, in, out, cutoff, q, pksh, nframes); break;
|
||||||
|
case kFilterLsh: P->process(P->fDspLsh, in, out, cutoff, q, pksh, nframes); break;
|
||||||
|
case kFilterHsh: P->process(P->fDspHsh, in, out, cutoff, q, pksh, nframes); break;
|
||||||
|
case kFilterPeq: P->process(P->fDspPeq, in, out, cutoff, q, pksh, nframes); break;
|
||||||
|
default: assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <unsigned NCh>
|
||||||
|
template <class F>
|
||||||
|
void Filter<NCh>::Impl::processModulated(F &filter, const float *const in[NCh], float *const out[NCh], const float *cutoff, const float *q, const float *pksh, unsigned nframes)
|
||||||
|
{
|
||||||
|
unsigned frame = 0;
|
||||||
|
|
||||||
|
while (frame < nframes) {
|
||||||
|
unsigned current = nframes - frame;
|
||||||
|
|
||||||
|
if (current > kFilterControlInterval)
|
||||||
|
current = kFilterControlInterval;
|
||||||
|
|
||||||
|
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.setQ(q[frame]);
|
||||||
|
filter.setPkShGain(pksh[frame]);
|
||||||
|
filter.compute(current, const_cast<float **>(current_in), const_cast<float **>(current_out));
|
||||||
|
|
||||||
|
frame += current;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <unsigned NCh>
|
||||||
|
void Filter<NCh>::processModulated(const float *const in[NCh], float *const out[NCh], const float *cutoff, const float *q, const float *pksh, unsigned nframes)
|
||||||
|
{
|
||||||
|
if (P->fType == kFilterNone) {
|
||||||
|
for (unsigned c = 0; c < NCh; ++c) {
|
||||||
|
const float *ch_in = in[c];
|
||||||
|
float *ch_out = out[c];
|
||||||
|
if (ch_in != ch_out)
|
||||||
|
std::memcpy(ch_out, ch_in, nframes * sizeof(float));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (P->fType) {
|
||||||
|
case kFilterApf1p: P->processModulated(P->fDspApf1p, in, out, cutoff, q, pksh, nframes); break;
|
||||||
|
case kFilterBpf1p: P->processModulated(P->fDspBpf1p, in, out, cutoff, q, pksh, nframes); break;
|
||||||
|
case kFilterBpf2p: P->processModulated(P->fDspBpf2p, in, out, cutoff, q, pksh, nframes); break;
|
||||||
|
case kFilterBpf4p: P->processModulated(P->fDspBpf4p, in, out, cutoff, q, pksh, nframes); break;
|
||||||
|
case kFilterBpf6p: P->processModulated(P->fDspBpf6p, in, out, cutoff, q, pksh, nframes); break;
|
||||||
|
case kFilterBrf1p: P->processModulated(P->fDspBrf1p, in, out, cutoff, q, pksh, nframes); break;
|
||||||
|
case kFilterBrf2p: P->processModulated(P->fDspBrf2p, in, out, cutoff, q, pksh, nframes); break;
|
||||||
|
case kFilterHpf1p: P->processModulated(P->fDspHpf1p, in, out, cutoff, q, pksh, nframes); break;
|
||||||
|
case kFilterHpf2p: P->processModulated(P->fDspHpf2p, in, out, cutoff, q, pksh, nframes); break;
|
||||||
|
case kFilterHpf4p: P->processModulated(P->fDspHpf4p, in, out, cutoff, q, pksh, nframes); break;
|
||||||
|
case kFilterHpf6p: P->processModulated(P->fDspHpf6p, in, out, cutoff, q, pksh, nframes); break;
|
||||||
|
case kFilterLpf1p: P->processModulated(P->fDspLpf1p, in, out, cutoff, q, pksh, nframes); break;
|
||||||
|
case kFilterLpf2p: P->processModulated(P->fDspLpf2p, in, out, cutoff, q, pksh, nframes); break;
|
||||||
|
case kFilterLpf4p: P->processModulated(P->fDspLpf4p, in, out, cutoff, q, pksh, nframes); break;
|
||||||
|
case kFilterLpf6p: P->processModulated(P->fDspLpf6p, in, out, cutoff, q, pksh, nframes); break;
|
||||||
|
case kFilterPink: P->processModulated(P->fDspPink, in, out, cutoff, q, pksh, nframes); break;
|
||||||
|
case kFilterLpf2pSv: P->processModulated(P->fDspLpf2pSv, in, out, cutoff, q, pksh, nframes); break;
|
||||||
|
case kFilterHpf2pSv: P->processModulated(P->fDspHpf2pSv, in, out, cutoff, q, pksh, nframes); break;
|
||||||
|
case kFilterBpf2pSv: P->processModulated(P->fDspBpf2pSv, in, out, cutoff, q, pksh, nframes); break;
|
||||||
|
case kFilterBrf2pSv: P->processModulated(P->fDspBrf2pSv, in, out, cutoff, q, pksh, nframes); break;
|
||||||
|
case kFilterLsh: P->processModulated(P->fDspLsh, in, out, cutoff, q, pksh, nframes); break;
|
||||||
|
case kFilterHsh: P->processModulated(P->fDspHsh, in, out, cutoff, q, pksh, nframes); break;
|
||||||
|
case kFilterPeq: P->processModulated(P->fDspPeq, in, out, cutoff, q, pksh, nframes); break;
|
||||||
|
default: assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <unsigned NCh>
|
||||||
|
FilterType Filter<NCh>::type() const
|
||||||
|
{
|
||||||
|
return P->fType;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <unsigned NCh>
|
||||||
|
void Filter<NCh>::setType(FilterType type)
|
||||||
|
{
|
||||||
|
if (P->fType != type) {
|
||||||
|
P->fType = type;
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template class Filter<1>;
|
||||||
|
template class Filter<2>;
|
||||||
|
|
||||||
|
} // namespace sfz
|
||||||
100
src/sfizz/SfzFilter.h
Normal file
100
src/sfizz/SfzFilter.h
Normal file
|
|
@ -0,0 +1,100 @@
|
||||||
|
// SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
|
||||||
|
// This code is part of the sfizz library and is licensed under a BSD 2-clause
|
||||||
|
// license. You should have receive a LICENSE.md file along with the code.
|
||||||
|
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace sfz {
|
||||||
|
|
||||||
|
enum FilterType : int;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Multi-mode filter for SFZ v2
|
||||||
|
Available for mono and stereo. (NCh=1, NCh=2)
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
`cutoff`: it's the opcode `filN_cutoff` (Hz)
|
||||||
|
`q`: it's the opcode `filN_resonance` (dB)
|
||||||
|
`pksh`: it's the opcode `filN_gain` (dB)
|
||||||
|
*/
|
||||||
|
template <unsigned NCh>
|
||||||
|
class Filter {
|
||||||
|
public:
|
||||||
|
Filter();
|
||||||
|
~Filter();
|
||||||
|
|
||||||
|
/**
|
||||||
|
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 Q.
|
||||||
|
`cutoff` is a frequency expressed in Hz.
|
||||||
|
`q` is a resonance expressed in dB.
|
||||||
|
`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 q, float pksh, unsigned nframes);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Process one cycle of the filter with cutoff and Q values varying over time.
|
||||||
|
`cutoff` is a frequency expressed in Hz.
|
||||||
|
`q` is a resonance expressed in dB.
|
||||||
|
`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 *q, const float *pksh, unsigned nframes);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get the type of filter.
|
||||||
|
*/
|
||||||
|
FilterType type() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Set the type of filter.
|
||||||
|
*/
|
||||||
|
void setType(FilterType type);
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct Impl;
|
||||||
|
std::unique_ptr<Impl> P;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum FilterType : int {
|
||||||
|
kFilterNone,
|
||||||
|
kFilterApf1p,
|
||||||
|
kFilterBpf1p,
|
||||||
|
kFilterBpf2p,
|
||||||
|
kFilterBpf4p,
|
||||||
|
kFilterBpf6p,
|
||||||
|
kFilterBrf1p,
|
||||||
|
kFilterBrf2p,
|
||||||
|
kFilterHpf1p,
|
||||||
|
kFilterHpf2p,
|
||||||
|
kFilterHpf4p,
|
||||||
|
kFilterHpf6p,
|
||||||
|
kFilterLpf1p,
|
||||||
|
kFilterLpf2p,
|
||||||
|
kFilterLpf4p,
|
||||||
|
kFilterLpf6p,
|
||||||
|
kFilterPink,
|
||||||
|
kFilterLpf2pSv,
|
||||||
|
kFilterHpf2pSv,
|
||||||
|
kFilterBpf2pSv,
|
||||||
|
kFilterBrf2pSv,
|
||||||
|
kFilterLsh,
|
||||||
|
kFilterHsh,
|
||||||
|
kFilterPeq,
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace sfz
|
||||||
19
src/sfizz/SfzFilterDefs.h
Normal file
19
src/sfizz/SfzFilterDefs.h
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
// SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
|
||||||
|
// This code is part of the sfizz library and is licensed under a BSD 2-clause
|
||||||
|
// license. You should have receive a LICENSE.md file along with the code.
|
||||||
|
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace sfz {
|
||||||
|
|
||||||
|
enum {
|
||||||
|
/**
|
||||||
|
Minimum interval in frames between recomputations of coefficients of the
|
||||||
|
modulated filter. The lower, the more CPU resources are consumed.
|
||||||
|
*/
|
||||||
|
kFilterControlInterval = 16,
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace sfz
|
||||||
153
src/sfizz/SfzFilterImpls.cxx
Normal file
153
src/sfizz/SfzFilterImpls.cxx
Normal file
|
|
@ -0,0 +1,153 @@
|
||||||
|
// SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
|
||||||
|
// This code is part of the sfizz library and is licensed under a BSD 2-clause
|
||||||
|
// license. You should have receive a LICENSE.md file along with the code.
|
||||||
|
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
|
||||||
|
|
||||||
|
struct dsp {};
|
||||||
|
struct Meta {};
|
||||||
|
struct UI {};
|
||||||
|
|
||||||
|
#include "gen/filters/sfzApf1p.cxx"
|
||||||
|
#include "gen/filters/sfzBpf1p.cxx"
|
||||||
|
#include "gen/filters/sfzBpf2p.cxx"
|
||||||
|
#include "gen/filters/sfzBpf4p.cxx"
|
||||||
|
#include "gen/filters/sfzBpf6p.cxx"
|
||||||
|
#include "gen/filters/sfzBrf1p.cxx"
|
||||||
|
#include "gen/filters/sfzBrf2p.cxx"
|
||||||
|
#include "gen/filters/sfzHpf1p.cxx"
|
||||||
|
#include "gen/filters/sfzHpf2p.cxx"
|
||||||
|
#include "gen/filters/sfzHpf4p.cxx"
|
||||||
|
#include "gen/filters/sfzHpf6p.cxx"
|
||||||
|
#include "gen/filters/sfzLpf1p.cxx"
|
||||||
|
#include "gen/filters/sfzLpf2p.cxx"
|
||||||
|
#include "gen/filters/sfzLpf4p.cxx"
|
||||||
|
#include "gen/filters/sfzLpf6p.cxx"
|
||||||
|
#include "gen/filters/sfzPink.cxx"
|
||||||
|
#include "gen/filters/sfzLpf2pSv.cxx"
|
||||||
|
#include "gen/filters/sfzHpf2pSv.cxx"
|
||||||
|
#include "gen/filters/sfzBpf2pSv.cxx"
|
||||||
|
#include "gen/filters/sfzBrf2pSv.cxx"
|
||||||
|
#include "gen/filters/sfzLsh.cxx"
|
||||||
|
#include "gen/filters/sfzHsh.cxx"
|
||||||
|
#include "gen/filters/sfzPeq.cxx"
|
||||||
|
|
||||||
|
#include "gen/filters/sfz2chApf1p.cxx"
|
||||||
|
#include "gen/filters/sfz2chBpf1p.cxx"
|
||||||
|
#include "gen/filters/sfz2chBpf2p.cxx"
|
||||||
|
#include "gen/filters/sfz2chBpf4p.cxx"
|
||||||
|
#include "gen/filters/sfz2chBpf6p.cxx"
|
||||||
|
#include "gen/filters/sfz2chBrf1p.cxx"
|
||||||
|
#include "gen/filters/sfz2chBrf2p.cxx"
|
||||||
|
#include "gen/filters/sfz2chHpf1p.cxx"
|
||||||
|
#include "gen/filters/sfz2chHpf2p.cxx"
|
||||||
|
#include "gen/filters/sfz2chHpf4p.cxx"
|
||||||
|
#include "gen/filters/sfz2chHpf6p.cxx"
|
||||||
|
#include "gen/filters/sfz2chLpf1p.cxx"
|
||||||
|
#include "gen/filters/sfz2chLpf2p.cxx"
|
||||||
|
#include "gen/filters/sfz2chLpf4p.cxx"
|
||||||
|
#include "gen/filters/sfz2chLpf6p.cxx"
|
||||||
|
#include "gen/filters/sfz2chPink.cxx"
|
||||||
|
#include "gen/filters/sfz2chLpf2pSv.cxx"
|
||||||
|
#include "gen/filters/sfz2chHpf2pSv.cxx"
|
||||||
|
#include "gen/filters/sfz2chBpf2pSv.cxx"
|
||||||
|
#include "gen/filters/sfz2chBrf2pSv.cxx"
|
||||||
|
#include "gen/filters/sfz2chLsh.cxx"
|
||||||
|
#include "gen/filters/sfz2chHsh.cxx"
|
||||||
|
#include "gen/filters/sfz2chPeq.cxx"
|
||||||
|
|
||||||
|
template <class F> struct sfzFilter : public F {
|
||||||
|
void setCutoff(float v) { F::fCutoff = v; }
|
||||||
|
void setQ(float v) { F::fQ = v; }
|
||||||
|
void setPkShGain(float) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class F> struct sfzFilterNoQ : public F {
|
||||||
|
void setCutoff(float v) { F::fCutoff = v; }
|
||||||
|
void setQ(float) {}
|
||||||
|
void setPkShGain(float) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class F> struct sfzFilterNoCutoff : public F {
|
||||||
|
void setCutoff(float) {}
|
||||||
|
void setQ(float) {}
|
||||||
|
void setPkShGain(float) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class F> struct sfzFilterEq : public F {
|
||||||
|
void setCutoff(float v) { F::fCutoff = v; }
|
||||||
|
void setQ(float v) { F::fQ = v; }
|
||||||
|
void setPkShGain(float v) { F::fPkShGain = v; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <unsigned NCh> struct sfzLpf1p;
|
||||||
|
template <unsigned NCh> struct sfzLpf2p;
|
||||||
|
template <unsigned NCh> struct sfzLpf4p;
|
||||||
|
template <unsigned NCh> struct sfzLpf6p;
|
||||||
|
template <unsigned NCh> struct sfzHpf1p;
|
||||||
|
template <unsigned NCh> struct sfzHpf2p;
|
||||||
|
template <unsigned NCh> struct sfzHpf4p;
|
||||||
|
template <unsigned NCh> struct sfzHpf6p;
|
||||||
|
template <unsigned NCh> struct sfzBpf1p;
|
||||||
|
template <unsigned NCh> struct sfzBpf2p;
|
||||||
|
template <unsigned NCh> struct sfzBpf4p;
|
||||||
|
template <unsigned NCh> struct sfzBpf6p;
|
||||||
|
template <unsigned NCh> struct sfzApf1p;
|
||||||
|
template <unsigned NCh> struct sfzBrf1p;
|
||||||
|
template <unsigned NCh> struct sfzBrf2p;
|
||||||
|
template <unsigned NCh> struct sfzPink;
|
||||||
|
template <unsigned NCh> struct sfzLpf2pSv;
|
||||||
|
template <unsigned NCh> struct sfzHpf2pSv;
|
||||||
|
template <unsigned NCh> struct sfzBpf2pSv;
|
||||||
|
template <unsigned NCh> struct sfzBrf2pSv;
|
||||||
|
template <unsigned NCh> struct sfzLsh;
|
||||||
|
template <unsigned NCh> struct sfzHsh;
|
||||||
|
template <unsigned NCh> struct sfzPeq;
|
||||||
|
|
||||||
|
template<> struct sfzLpf1p<1> : public sfzFilterNoQ<faustLpf1p> {};
|
||||||
|
template<> struct sfzLpf2p<1> : public sfzFilter<faustLpf2p> {};
|
||||||
|
template<> struct sfzLpf4p<1> : public sfzFilter<faustLpf4p> {};
|
||||||
|
template<> struct sfzLpf6p<1> : public sfzFilter<faustLpf6p> {};
|
||||||
|
template<> struct sfzHpf1p<1> : public sfzFilterNoQ<faustHpf1p> {};
|
||||||
|
template<> struct sfzHpf2p<1> : public sfzFilter<faustHpf2p> {};
|
||||||
|
template<> struct sfzHpf4p<1> : public sfzFilter<faustHpf4p> {};
|
||||||
|
template<> struct sfzHpf6p<1> : public sfzFilter<faustHpf6p> {};
|
||||||
|
template<> struct sfzBpf1p<1> : public sfzFilterNoQ<faustBpf1p> {};
|
||||||
|
template<> struct sfzBpf2p<1> : public sfzFilter<faustBpf2p> {};
|
||||||
|
template<> struct sfzBpf4p<1> : public sfzFilter<faustBpf4p> {};
|
||||||
|
template<> struct sfzBpf6p<1> : public sfzFilter<faustBpf6p> {};
|
||||||
|
template<> struct sfzApf1p<1> : public sfzFilterNoQ<faustApf1p> {};
|
||||||
|
template<> struct sfzBrf1p<1> : public sfzFilterNoQ<faustBrf1p> {};
|
||||||
|
template<> struct sfzBrf2p<1> : public sfzFilter<faustBrf2p> {};
|
||||||
|
template<> struct sfzPink<1> : public sfzFilterNoCutoff<faustPink> {};
|
||||||
|
template<> struct sfzLpf2pSv<1> : public sfzFilter<faustLpf2pSv> {};
|
||||||
|
template<> struct sfzHpf2pSv<1> : public sfzFilter<faustHpf2pSv> {};
|
||||||
|
template<> struct sfzBpf2pSv<1> : public sfzFilter<faustBpf2pSv> {};
|
||||||
|
template<> struct sfzBrf2pSv<1> : public sfzFilter<faustBrf2pSv> {};
|
||||||
|
template<> struct sfzLsh<1> : public sfzFilterEq<faustLsh> {};
|
||||||
|
template<> struct sfzHsh<1> : public sfzFilterEq<faustHsh> {};
|
||||||
|
template<> struct sfzPeq<1> : public sfzFilterEq<faustPeq> {};
|
||||||
|
|
||||||
|
template<> struct sfzLpf1p<2> : public sfzFilterNoQ<faust2chLpf1p> {};
|
||||||
|
template<> struct sfzLpf2p<2> : public sfzFilter<faust2chLpf2p> {};
|
||||||
|
template<> struct sfzLpf4p<2> : public sfzFilter<faust2chLpf4p> {};
|
||||||
|
template<> struct sfzLpf6p<2> : public sfzFilter<faust2chLpf6p> {};
|
||||||
|
template<> struct sfzHpf1p<2> : public sfzFilterNoQ<faust2chHpf1p> {};
|
||||||
|
template<> struct sfzHpf2p<2> : public sfzFilter<faust2chHpf2p> {};
|
||||||
|
template<> struct sfzHpf4p<2> : public sfzFilter<faust2chHpf4p> {};
|
||||||
|
template<> struct sfzHpf6p<2> : public sfzFilter<faust2chHpf6p> {};
|
||||||
|
template<> struct sfzBpf1p<2> : public sfzFilterNoQ<faust2chBpf1p> {};
|
||||||
|
template<> struct sfzBpf2p<2> : public sfzFilter<faust2chBpf2p> {};
|
||||||
|
template<> struct sfzBpf4p<2> : public sfzFilter<faust2chBpf4p> {};
|
||||||
|
template<> struct sfzBpf6p<2> : public sfzFilter<faust2chBpf6p> {};
|
||||||
|
template<> struct sfzApf1p<2> : public sfzFilterNoQ<faust2chApf1p> {};
|
||||||
|
template<> struct sfzBrf1p<2> : public sfzFilterNoQ<faust2chBrf1p> {};
|
||||||
|
template<> struct sfzBrf2p<2> : public sfzFilter<faust2chBrf2p> {};
|
||||||
|
template<> struct sfzPink<2> : public sfzFilterNoCutoff<faust2chPink> {};
|
||||||
|
template<> struct sfzLpf2pSv<2> : public sfzFilter<faust2chLpf2pSv> {};
|
||||||
|
template<> struct sfzHpf2pSv<2> : public sfzFilter<faust2chHpf2pSv> {};
|
||||||
|
template<> struct sfzBpf2pSv<2> : public sfzFilter<faust2chBpf2pSv> {};
|
||||||
|
template<> struct sfzBrf2pSv<2> : public sfzFilter<faust2chBrf2pSv> {};
|
||||||
|
template<> struct sfzLsh<2> : public sfzFilterEq<faust2chLsh> {};
|
||||||
|
template<> struct sfzHsh<2> : public sfzFilterEq<faust2chHsh> {};
|
||||||
|
template<> struct sfzPeq<2> : public sfzFilterEq<faust2chPeq> {};
|
||||||
72
src/sfizz/dsp/filters/filters_modulable.dsp
Normal file
72
src/sfizz/dsp/filters/filters_modulable.dsp
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
// -*- mode: faust; -*-
|
||||||
|
|
||||||
|
declare author "Jean Pierre Cimalando";
|
||||||
|
declare license "BSD-2-Clause";
|
||||||
|
|
||||||
|
import("stdfaust.lib");
|
||||||
|
rbj = library("rbj_filters.dsp");
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
// Biquad filter from normalized coefficients
|
||||||
|
// b0,b1,b2,a1,a2 : normalized coefficients
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
biquad(b0,b1,b2,a1,a2) = fi.iir((b0,b1,b2),(a1,a2));
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
// Biquad filter using smoothed coefficients
|
||||||
|
// s : a smoothing function applied to each coefficient
|
||||||
|
// b0,b1,b2,a1,a2 : normalized coefficients
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
smoothBiquad(s,b0,b1,b2,a1,a2) = biquad(b0:s,b1:s,b2:s,a1:s,a2:s);
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
// RBJ filter of a specific type using smoothed coefficients
|
||||||
|
// s : a smoothing function applied to each coefficient
|
||||||
|
// f : cutoff frequency
|
||||||
|
// g : gain in decibel, for peaking and shelving types only
|
||||||
|
// q : height of the resonant peak in linear units
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
rbjLpfSmooth(s,f,g,q,x) = (rbj.filtercoeff(f,g,q).LPF,x) : smoothBiquad(s);
|
||||||
|
rbjHpfSmooth(s,f,g,q,x) = (rbj.filtercoeff(f,g,q).HPF,x) : smoothBiquad(s);
|
||||||
|
rbjBpfSmooth(s,f,g,q,x) = (rbj.filtercoeff(f,g,q).BPF,x) : smoothBiquad(s);
|
||||||
|
rbjNotchSmooth(s,f,g,q,x) = (rbj.filtercoeff(f,g,q).notch,x) : smoothBiquad(s);
|
||||||
|
rbjApfSmooth(s,f,g,q,x) = (rbj.filtercoeff(f,g,q).APF,x) : smoothBiquad(s);
|
||||||
|
rbjPeakingEqSmooth(s,f,g,q,x) = (rbj.filtercoeff(f,g,q).peakingEQ,x) : smoothBiquad(s);
|
||||||
|
rbjPeakingNotchSmooth(s,f,g,q,x) = (rbj.filtercoeff(f,g,q).peakNotch,x) : smoothBiquad(s);
|
||||||
|
rbjLowShelfSmooth(s,f,g,q,x) = (rbj.filtercoeff(f,g,q).lowShelf,x) : smoothBiquad(s);
|
||||||
|
rbjHighShelfSmooth(s,f,g,q,x) = (rbj.filtercoeff(f,g,q).highShelf,x) : smoothBiquad(s);
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
// 1-pole low-pass filter
|
||||||
|
// s : a smoothing function applied to each coefficient
|
||||||
|
// f : cutoff frequency
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
lp1Smooth(s,f) = fi.iir((1-p),(0-p)) with {
|
||||||
|
p = exp(-2.*ma.PI*f/ma.SR) : s;
|
||||||
|
};
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
// 1-pole high-pass filter
|
||||||
|
// s : a smoothing function applied to each coefficient
|
||||||
|
// f : cutoff frequency
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
hp1Smooth(s,f) = fi.iir((0.5*(1.+p),-0.5*(1+p)),(0.-p)) with {
|
||||||
|
p = exp(-2.*ma.PI*f/ma.SR) : s;
|
||||||
|
};
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
// 1-pole all-pass filter
|
||||||
|
// s : a smoothing function applied to each coefficient
|
||||||
|
// f : cutoff frequency
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
ap1Smooth(s,f) = fi.iir((a,1.),(a)) with {
|
||||||
|
a = (-1.+2.*ma.PI*f/ma.SR) : s;
|
||||||
|
};
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Example
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// process = rbjLpfSmooth(si.smoo, cutoff, 0.0, resonance : ba.db2linear) with {
|
||||||
|
// cutoff = hslider("[1] Cutoff [unit:Hz] [scale:log]", 440.0, 50.0, 10000.0, 1.0);
|
||||||
|
// resonance = hslider("[2] Resonance [unit:dB]", 0.0, 0.0, 40.0, 0.1);
|
||||||
|
// };
|
||||||
212
src/sfizz/dsp/filters/rbj_filters.dsp
Normal file
212
src/sfizz/dsp/filters/rbj_filters.dsp
Normal file
|
|
@ -0,0 +1,212 @@
|
||||||
|
/**
|
||||||
|
Note(jpc): This is RBJ filter extracted from faustlibraries master branch.
|
||||||
|
Unlike some prior versions found in faust 2.x, this one has been
|
||||||
|
permissively relicensed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
************************************************************************
|
||||||
|
FAUST library file
|
||||||
|
Copyright (C) 2019-2020 GRAME, Centre National de Creation Musicale
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2.1 of the
|
||||||
|
License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with the GNU C Library; if not, write to the Free
|
||||||
|
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
|
02111-1307 USA.
|
||||||
|
|
||||||
|
EXCEPTION TO THE LGPL LICENSE : As a special exception, you may create a
|
||||||
|
larger FAUST program which directly or indirectly imports this library
|
||||||
|
file and still distribute the compiled code generated by the FAUST
|
||||||
|
compiler, or a modified version of this compiled code, under your own
|
||||||
|
copyright and license. This EXCEPTION TO THE LGPL LICENSE explicitly
|
||||||
|
grants you the right to freely choose the license for the resulting
|
||||||
|
compiled code. In particular the resulting compiled code has no obligation
|
||||||
|
to be LGPL or GPL. For example you are free to choose a commerci
|
||||||
|
************************************************************************
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
declare name "MaxMSP compatibility Library";
|
||||||
|
declare author "GRAME";
|
||||||
|
declare copyright "GRAME";
|
||||||
|
declare version "1.1";
|
||||||
|
declare license "LGPL with exception";
|
||||||
|
|
||||||
|
ba = library("basics.lib");
|
||||||
|
ma = library("maths.lib");
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Implementation of MaxMSP filtercoeff
|
||||||
|
//
|
||||||
|
// from : Cookbook formulae for audio EQ biquad filter coefficients
|
||||||
|
// by : Robert Bristow-Johnson <rbj@audioimagination.com>
|
||||||
|
// URL : http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt
|
||||||
|
//
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
|
||||||
|
filtercoeff(f0, dBgain, Q) = environment
|
||||||
|
{
|
||||||
|
//----------------------------------------
|
||||||
|
// biquad coeffs for various filters
|
||||||
|
// usage : filtercoeff(f0, dBgain, Q).LPF
|
||||||
|
//----------------------------------------
|
||||||
|
|
||||||
|
LPF = rbjcoef(a0, a1, a2, b0, b1, b2)
|
||||||
|
with {
|
||||||
|
b0 = (1 - cos(w0))/2;
|
||||||
|
b1 = 1 - cos(w0);
|
||||||
|
b2 = (1 - cos(w0))/2;
|
||||||
|
a0 = 1 + alpha;
|
||||||
|
a1 = -2*cos(w0);
|
||||||
|
a2 = 1 - alpha;
|
||||||
|
};
|
||||||
|
|
||||||
|
HPF = rbjcoef(a0, a1, a2, b0, b1, b2)
|
||||||
|
with {
|
||||||
|
b0 = (1 + cos(w0))/2;
|
||||||
|
b1 = -1 - cos(w0);
|
||||||
|
b2 = (1 + cos(w0))/2;
|
||||||
|
a0 = 1 + alpha;
|
||||||
|
a1 = -2*cos(w0);
|
||||||
|
a2 = 1 - alpha;
|
||||||
|
};
|
||||||
|
|
||||||
|
BPF = rbjcoef(a0, a1, a2, b0, b1, b2) // constant 0 dB peak gain
|
||||||
|
with {
|
||||||
|
b0 = alpha;
|
||||||
|
b1 = 0;
|
||||||
|
b2 = -alpha;
|
||||||
|
a0 = 1 + alpha;
|
||||||
|
a1 = -2*cos(w0);
|
||||||
|
a2 = 1 - alpha;
|
||||||
|
};
|
||||||
|
|
||||||
|
notch = rbjcoef(a0, a1, a2, b0, b1, b2)
|
||||||
|
with {
|
||||||
|
b0 = 1;
|
||||||
|
b1 = -2*cos(w0);
|
||||||
|
b2 = 1;
|
||||||
|
a0 = 1 + alpha;
|
||||||
|
a1 = -2*cos(w0);
|
||||||
|
a2 = 1 - alpha;
|
||||||
|
};
|
||||||
|
|
||||||
|
APF = rbjcoef(a0, a1, a2, b0, b1, b2)
|
||||||
|
with {
|
||||||
|
b0 = 1 - alpha;
|
||||||
|
b1 = -2*cos(w0);
|
||||||
|
b2 = 1 + alpha;
|
||||||
|
a0 = 1 + alpha;
|
||||||
|
a1 = -2*cos(w0);
|
||||||
|
a2 = 1 - alpha;
|
||||||
|
};
|
||||||
|
|
||||||
|
peakingEQ = rbjcoef(a0, a1, a2, b0, b1, b2)
|
||||||
|
with {
|
||||||
|
b0 = 1 + alpha*A;
|
||||||
|
b1 = -2*cos(w0);
|
||||||
|
b2 = 1 - alpha*A;
|
||||||
|
a0 = 1 + alpha/A;
|
||||||
|
a1 = -2*cos(w0);
|
||||||
|
a2 = 1 - alpha/A;
|
||||||
|
};
|
||||||
|
|
||||||
|
peakNotch = rbjcoef(a0, a1, a2, b0, b1, b2)
|
||||||
|
with {
|
||||||
|
b0 = 1 + alpha*G;
|
||||||
|
b1 = -2*cos(w0);
|
||||||
|
b2 = 1 - alpha*G;
|
||||||
|
a0 = 1 + alpha/G;
|
||||||
|
a1 = -2*cos(w0);
|
||||||
|
a2 = 1 - alpha/G;
|
||||||
|
};
|
||||||
|
|
||||||
|
lowShelf = rbjcoef(a0, a1, a2, b0, b1, b2)
|
||||||
|
with {
|
||||||
|
b0 = A*((A+1) - (A-1)*cos(w0) + 2*sqrt(A)*alpha);
|
||||||
|
b1 = 2*A*((A-1) - (A+1)*cos(w0));
|
||||||
|
b2 = A*((A+1) - (A-1)*cos(w0) - 2*sqrt(A)*alpha);
|
||||||
|
a0 = (A+1) + (A-1)*cos(w0) + 2*sqrt(A)*alpha;
|
||||||
|
a1 = -2*((A-1) + (A+1)*cos(w0));
|
||||||
|
a2 = (A+1) + (A-1)*cos(w0) - 2*sqrt(A)*alpha;
|
||||||
|
};
|
||||||
|
|
||||||
|
highShelf = rbjcoef(a0, a1, a2, b0, b1, b2)
|
||||||
|
with {
|
||||||
|
b0 = A*((A+1) + (A-1)*cos(w0) + 2*sqrt(A)*alpha);
|
||||||
|
b1 = -2*A*((A-1) + (A+1)*cos(w0));
|
||||||
|
b2 = A*((A+1) + (A-1)*cos(w0) - 2*sqrt(A)*alpha);
|
||||||
|
a0 = (A+1) - (A-1)*cos(w0) + 2*sqrt(A)*alpha;
|
||||||
|
a1 = 2*((A-1) - (A+1)*cos(w0));
|
||||||
|
a2 = (A+1) - (A-1)*cos(w0) - 2*sqrt(A)*alpha;
|
||||||
|
};
|
||||||
|
|
||||||
|
// --------------------- implementation ------------------------------
|
||||||
|
|
||||||
|
// convert rbj coeffs to biquad coeffs
|
||||||
|
rbjcoef(a0,a1,a2,b0,b1,b2) = (b0/a0, b1/a0, b2/a0, a1/a0, a2/a0);
|
||||||
|
|
||||||
|
// common values
|
||||||
|
// alpha = sin(w0)/(2*Q);
|
||||||
|
// w0 = 2*ma.PI*f0/Fs;
|
||||||
|
alpha = sin(w0)/(2*max(0.001,Q));
|
||||||
|
w0 = 2*ma.PI*max(0,f0)/Fs;
|
||||||
|
Fs = ma.SR;
|
||||||
|
A = 10^(dBgain/40); // (for peaking and shelving EQ filters only)
|
||||||
|
G = sqrt(max(0.00001, dBgain)); // When gain is a linear values (i.e. not in dB)
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
// Implementation of MaxMSP biquad~
|
||||||
|
// y[n] = a0 * x[n] + a1 * x[n-1] + a2 * x[n-2] - b1 * y[n-1] - b2 * y[n-2]
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
|
||||||
|
biquad(x,a0,a1,a2,b1,b2) = x : + ~ ((-1)*conv2(b1, b2)) : conv3(a0, a1, a2)
|
||||||
|
with {
|
||||||
|
conv2(c0,c1,x) = c0*x+c1*x';
|
||||||
|
conv3(c0,c1,c2,x) = c0*x+c1*x'+c2*x'';
|
||||||
|
};
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Filters using filtercoeff and biquad
|
||||||
|
//
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Low Pass Filter
|
||||||
|
LPF(x, f0, gain, Q) = x , filtercoeff(f0,gain,Q).LPF : biquad;
|
||||||
|
|
||||||
|
// High Pass Filter
|
||||||
|
HPF(x, f0, gain, Q) = x , filtercoeff(f0,gain,Q).HPF : biquad;
|
||||||
|
|
||||||
|
// Band Pass Filter
|
||||||
|
BPF(x, f0, gain, Q) = x , filtercoeff(f0,gain,Q).BPF : biquad;
|
||||||
|
|
||||||
|
// notch Filter
|
||||||
|
notch(x, f0, gain, Q) = x , filtercoeff(f0,gain,Q).notch : biquad;
|
||||||
|
|
||||||
|
// All Pass Filter
|
||||||
|
APF(x, f0, gain, Q) = x , filtercoeff(f0,gain,Q).APF : biquad;
|
||||||
|
|
||||||
|
// ????
|
||||||
|
peakingEQ(x, f0, gain, Q) = x , filtercoeff(f0,gain,Q).peakingEQ : biquad;
|
||||||
|
|
||||||
|
// Max peakNotch is like peakingEQ but with a linear gain
|
||||||
|
peakNotch(x, f0, gain, Q) = x , filtercoeff(f0,gain,Q).peakNotch : biquad;
|
||||||
|
|
||||||
|
// ????
|
||||||
|
lowShelf(x, f0, gain, Q) = x , filtercoeff(f0,gain,Q).lowShelf : biquad;
|
||||||
|
|
||||||
|
// ????
|
||||||
|
highShelf(x, f0, gain, Q) = x , filtercoeff(f0,gain,Q).highShelf : biquad;
|
||||||
140
src/sfizz/dsp/filters/sallenkey_modulable.dsp
Normal file
140
src/sfizz/dsp/filters/sallenkey_modulable.dsp
Normal file
|
|
@ -0,0 +1,140 @@
|
||||||
|
/**
|
||||||
|
Note(jpc): this is a personal edit of the Sallen-Key state-variable filter
|
||||||
|
from `vaeffects.lib`. This changes:
|
||||||
|
- the frequency control, now in Hz instead of 0-1
|
||||||
|
- the smooth parameter, allowing for slower parameter transitions
|
||||||
|
while keeping some expensive computation out of the frame loop
|
||||||
|
*/
|
||||||
|
|
||||||
|
import("stdfaust.lib");
|
||||||
|
|
||||||
|
declare author "Eric Tarr";
|
||||||
|
declare license "MIT-style STK-4.3 license";
|
||||||
|
|
||||||
|
//================================Sallen Key Filters======================================
|
||||||
|
// The following filters were implemented based on VA models of synthesizer
|
||||||
|
// filters.
|
||||||
|
//
|
||||||
|
// The modeling approach is based on a Topology Preserving Transform (TPT) to
|
||||||
|
// resolve the delay-free feedback loop in the corresponding analog filters.
|
||||||
|
//
|
||||||
|
// The primary processing block used to build other filters (Moog, Korg, etc.) is
|
||||||
|
// based on a 1st-order Sallen-Key filter.
|
||||||
|
//
|
||||||
|
// The filters included in this script are 1st-order LPF/HPF and 2nd-order
|
||||||
|
// state-variable filters capable of LPF, HPF, and BPF.
|
||||||
|
//
|
||||||
|
// #### Resources:
|
||||||
|
//
|
||||||
|
// * Vadim Zavalishin (2018) "The Art of VA Filter Design", v2.1.0
|
||||||
|
// <https://www.native-instruments.com/fileadmin/ni_media/downloads/pdf/VAFilterDesign_2.1.0.pdf>
|
||||||
|
// * Will Pirkle (2014) "Resolving Delay-Free Loops in Recursive Filters Using
|
||||||
|
// the Modified Härmä Method", AES 137 <http://www.aes.org/e-lib/browse.cfm?elib=17517>
|
||||||
|
// * Description and diagrams of 1st- and 2nd-order TPT filters:
|
||||||
|
// <https://www.willpirkle.com/706-2/>
|
||||||
|
//========================================================================================
|
||||||
|
|
||||||
|
//------------------`(fi.)sallenKey2ndOrder`-----------------
|
||||||
|
// Sallen-Key generic multi-outputs 2nd order filter.
|
||||||
|
//
|
||||||
|
// This is a 2nd-order Sallen-Key state-variable filter. The idea is that by
|
||||||
|
// "tapping" into different points in the circuit, different filters
|
||||||
|
// (LPF,BPF,HPF) can be achieved. See Figure 4.6 of
|
||||||
|
// <https://www.willpirkle.com/706-2/>
|
||||||
|
//
|
||||||
|
// This is also a good example of the next step for generalizing the Faust
|
||||||
|
// programming approach used for all these VA filters. In this case, there are
|
||||||
|
// three things to calculate each recursive step (y,s1,s2). For each thing, the
|
||||||
|
// circuit is only calculated up to that point.
|
||||||
|
//
|
||||||
|
// Comparing the LPF to BPF, the output signal (y) is calculated similarly.
|
||||||
|
// Except, the output of the BPF stops earlier in the circuit. Similarly, the
|
||||||
|
// states (s1 and s2) only differ in that s2 includes a couple more terms
|
||||||
|
// beyond what is used for s1.
|
||||||
|
//
|
||||||
|
// #### Usage
|
||||||
|
//
|
||||||
|
// ```
|
||||||
|
// _ : sallenKey2ndOrder(smooth,freq,Q) : _,_,_
|
||||||
|
// ```
|
||||||
|
//
|
||||||
|
// Where:
|
||||||
|
//
|
||||||
|
// * `freq`: cutoff frequency
|
||||||
|
// * `Q`: q
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
sallenKey2ndOrder(smooth,freq,Q) = _<:(s1,s2,ylpf,ybpf,yhpf) : !,!,_,_,_
|
||||||
|
letrec{
|
||||||
|
's1 = -(s2):-(s1*FBs1):*(alpha0):*(g*2):+(s1);
|
||||||
|
's2 = -(s2):-(s1*FBs1):*(alpha0):*(g):+(s1):*(g*2):+(s2);
|
||||||
|
// Compute the LPF, BPF, HPF outputs
|
||||||
|
'ylpf = -(s2):-(s1*FBs1):*(alpha0):*(g*2):+(s1):*(g):+(s2);
|
||||||
|
'ybpf = -(s2):-(s1*FBs1):*(alpha0):*(g):+(s1);
|
||||||
|
'yhpf = -(s2):-(s1*FBs1):*(alpha0);
|
||||||
|
}
|
||||||
|
with{
|
||||||
|
wd = 2*ma.PI*freq;
|
||||||
|
T = 1/ma.SR;
|
||||||
|
wa = (2/T)*tan(wd*T/2);
|
||||||
|
g = (wa*T/2):smooth;
|
||||||
|
G = g/(1.0 + g);
|
||||||
|
R = 1/(2*Q);
|
||||||
|
FBs1 = (2*R+g):smooth;
|
||||||
|
alpha0 = (1/(1 + 2*R*g + g*g)):smooth;
|
||||||
|
};
|
||||||
|
|
||||||
|
//------------------`(fi.)sallenKey2ndOrderLPF`-----------------
|
||||||
|
// Sallen-Key 2nd order lowpass filter (see description above).
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// #### Usage
|
||||||
|
//
|
||||||
|
// ```
|
||||||
|
// _ : sallenKey2ndOrderLPF(smooth,freq,Q) : _
|
||||||
|
// ```
|
||||||
|
//
|
||||||
|
// Where:
|
||||||
|
//
|
||||||
|
// * `freq`: cutoff frequency
|
||||||
|
// * `Q`: q
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
// Specialize the generic implementation: keep the first LPF output, the compiler will only generate the needed code
|
||||||
|
sallenKey2ndOrderLPF(smooth,freq,Q) = sallenKey2ndOrder(smooth,freq,Q) : _,!,!;
|
||||||
|
|
||||||
|
|
||||||
|
//------------------`(fi.)sallenKey2ndOrderBPF`-----------------
|
||||||
|
// Sallen-Key 2nd order bandpass filter (see description above).
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// #### Usage
|
||||||
|
//
|
||||||
|
// ```
|
||||||
|
// _ : sallenKey2ndOrderBPF(smooth,freq,Q) : _
|
||||||
|
// ```
|
||||||
|
//
|
||||||
|
// Where:
|
||||||
|
//
|
||||||
|
// * `freq`: cutoff frequency
|
||||||
|
// * `Q`: q
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
// Specialize the generic implementation: keep the second BPF output, the compiler will only generate the needed code
|
||||||
|
sallenKey2ndOrderBPF(smooth,freq,Q) = sallenKey2ndOrder(smooth,freq,Q) : !,_,!;
|
||||||
|
|
||||||
|
|
||||||
|
//------------------`(fi.)sallenKey2ndOrderHPF`-----------------
|
||||||
|
// Sallen-Key 2nd order highpass filter (see description above).
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// #### Usage
|
||||||
|
//
|
||||||
|
// ```
|
||||||
|
// _ : sallenKey2ndOrderHPF(smooth,freq,Q) : _
|
||||||
|
// ```
|
||||||
|
//
|
||||||
|
// Where:
|
||||||
|
//
|
||||||
|
// * `freq`: cutoff frequency
|
||||||
|
// * `Q`: q
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
// Specialize the generic implementation: keep the third HPF output, the compiler will only generate the needed code
|
||||||
|
sallenKey2ndOrderHPF(smooth,freq,Q) = sallenKey2ndOrder(smooth,freq,Q) : !,!,_;
|
||||||
128
src/sfizz/dsp/filters/sfz_filters.dsp
Normal file
128
src/sfizz/dsp/filters/sfz_filters.dsp
Normal file
|
|
@ -0,0 +1,128 @@
|
||||||
|
// -*- mode: faust; -*-
|
||||||
|
|
||||||
|
declare author "Jean Pierre Cimalando";
|
||||||
|
declare license "BSD-2-Clause";
|
||||||
|
|
||||||
|
import("stdfaust.lib");
|
||||||
|
fm = library("filters_modulable.dsp");
|
||||||
|
sk = library("sallenkey_modulable.dsp");
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Generators
|
||||||
|
|
||||||
|
// the SFZ *noise generator
|
||||||
|
sfzNoise = no.noise : *(gate) : *(0.25);
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Filters
|
||||||
|
|
||||||
|
// the SFZ lowpass 1-pole filter
|
||||||
|
sfzLpf1p = fm.lp1Smooth(smoothCoefs,cutoff);
|
||||||
|
|
||||||
|
// the SFZ lowpass 2-pole filter
|
||||||
|
sfzLpf2p = fm.rbjLpfSmooth(smoothCoefs,cutoff,0.,Q);
|
||||||
|
|
||||||
|
// the SFZ lowpass 4-pole filter
|
||||||
|
sfzLpf4p = sfzLpf2p : sfzLpf2p;
|
||||||
|
|
||||||
|
// the SFZ lowpass 6-pole filter
|
||||||
|
sfzLpf6p = sfzLpf2p : sfzLpf2p : sfzLpf2p;
|
||||||
|
|
||||||
|
// the SFZ highpass 1-pole filter
|
||||||
|
sfzHpf1p = fm.hp1Smooth(smoothCoefs,cutoff);
|
||||||
|
|
||||||
|
// the SFZ highpass 2-pole filter
|
||||||
|
sfzHpf2p = fm.rbjHpfSmooth(smoothCoefs,cutoff,0.,Q);
|
||||||
|
|
||||||
|
// the SFZ highpass 4-pole filter
|
||||||
|
sfzHpf4p = sfzHpf2p : sfzHpf2p;
|
||||||
|
|
||||||
|
// the SFZ highpass 6-pole filter
|
||||||
|
sfzHpf6p = sfzHpf2p : sfzHpf2p : sfzHpf2p;
|
||||||
|
|
||||||
|
// the SFZ bandpass 1-pole filter
|
||||||
|
sfzBpf1p = sfzLpf1p : sfzHpf1p;
|
||||||
|
|
||||||
|
// the SFZ bandpass 2-pole filter
|
||||||
|
sfzBpf2p = fm.rbjBpfSmooth(smoothCoefs,cutoff,0.,Q);
|
||||||
|
|
||||||
|
// the SFZ bandpass 4-pole filter
|
||||||
|
// Note: bpf_4p not in specification but here anyway
|
||||||
|
sfzBpf4p = sfzBpf2p : sfzBpf2p;
|
||||||
|
|
||||||
|
// the SFZ bandpass 6-pole filter
|
||||||
|
// Note: bpf_6p not in specification but here anyway
|
||||||
|
sfzBpf6p = sfzBpf2p : sfzBpf2p : sfzBpf2p;
|
||||||
|
|
||||||
|
// the SFZ allpass 1-pole filter
|
||||||
|
sfzApf1p = fm.ap1Smooth(smoothCoefs,cutoff);
|
||||||
|
|
||||||
|
// the SFZ notch 1-pole filter
|
||||||
|
// Note: this thing is my invention, may not be correct.
|
||||||
|
// in Sforzando, 1p seems implemented the same as 2p.
|
||||||
|
sfzBrf1p = _ <: (_, (sfzApf1p : sfzApf1p)) :> +;
|
||||||
|
|
||||||
|
// the SFZ notch 2-pole filter
|
||||||
|
sfzBrf2p = fm.rbjNotchSmooth(smoothCoefs,cutoff,0.,Q);
|
||||||
|
|
||||||
|
// the SFZ pink filter
|
||||||
|
sfzPink = no.pink_filter;
|
||||||
|
|
||||||
|
// the SFZ 2-pole state-variable lowpass filter
|
||||||
|
sfzLpf2pSv = sk.sallenKey2ndOrderLPF(smoothCoefs,cutoff,Q);
|
||||||
|
|
||||||
|
// the SFZ 2-pole state-variable highpass filter
|
||||||
|
sfzHpf2pSv = sk.sallenKey2ndOrderHPF(smoothCoefs,cutoff,Q);
|
||||||
|
|
||||||
|
// the SFZ 2-pole state-variable bandpass filter
|
||||||
|
// Note: attenuate in order to have the resonant peak at 0 dB (same as sfzBpf2p)
|
||||||
|
sfzBpf2pSv = sk.sallenKey2ndOrderBPF(smoothCoefs,cutoff,Q) : *((1./Q):smoothCoefs);
|
||||||
|
|
||||||
|
// the SFZ 2-pole state-variable notch filter
|
||||||
|
sfzBrf2pSv = _ <: (sfzLpf2pSv, sfzHpf2pSv) :> +;
|
||||||
|
|
||||||
|
// the SFZ low-shelf filter
|
||||||
|
sfzLsh = fm.rbjLowShelfSmooth(smoothCoefs,cutoff,pkShGain,Q);
|
||||||
|
|
||||||
|
// the SFZ high-shelf filter
|
||||||
|
sfzHsh = fm.rbjHighShelfSmooth(smoothCoefs,cutoff,pkShGain,Q);
|
||||||
|
|
||||||
|
// the SFZ peaking EQ filter
|
||||||
|
sfzPeq = fm.rbjPeakingEqSmooth(smoothCoefs,cutoff,pkShGain,Q);
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Filters (stereo)
|
||||||
|
|
||||||
|
sfz2chLpf1p = par(i,2,sfzLpf1p);
|
||||||
|
sfz2chLpf2p = par(i,2,sfzLpf2p);
|
||||||
|
sfz2chLpf4p = par(i,2,sfzLpf4p);
|
||||||
|
sfz2chLpf6p = par(i,2,sfzLpf6p);
|
||||||
|
sfz2chHpf1p = par(i,2,sfzHpf1p);
|
||||||
|
sfz2chHpf2p = par(i,2,sfzHpf2p);
|
||||||
|
sfz2chHpf4p = par(i,2,sfzHpf4p);
|
||||||
|
sfz2chHpf6p = par(i,2,sfzHpf6p);
|
||||||
|
sfz2chBpf1p = par(i,2,sfzBpf1p);
|
||||||
|
sfz2chBpf2p = par(i,2,sfzBpf2p);
|
||||||
|
sfz2chBpf4p = par(i,2,sfzBpf4p);
|
||||||
|
sfz2chBpf6p = par(i,2,sfzBpf6p);
|
||||||
|
sfz2chApf1p = par(i,2,sfzApf1p);
|
||||||
|
sfz2chBrf1p = par(i,2,sfzBrf1p);
|
||||||
|
sfz2chBrf2p = par(i,2,sfzBrf2p);
|
||||||
|
sfz2chPink = par(i,2,sfzPink);
|
||||||
|
sfz2chLpf2pSv = par(i,2,sfzLpf2pSv);
|
||||||
|
sfz2chHpf2pSv = par(i,2,sfzHpf2pSv);
|
||||||
|
sfz2chBpf2pSv = par(i,2,sfzBpf2pSv);
|
||||||
|
sfz2chBrf2pSv = par(i,2,sfzBrf2pSv);
|
||||||
|
sfz2chLsh = par(i,2,sfzLsh);
|
||||||
|
sfz2chHsh = par(i,2,sfzHsh);
|
||||||
|
sfz2chPeq = par(i,2,sfzPeq);
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Filter parameters
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
// smoothing function to prevent fast changes of filter coefficients
|
||||||
|
smoothCoefs = si.smoo; // TODO check if this is appropriate otherwise replace
|
||||||
Loading…
Add table
Reference in a new issue