Compact multi-mode filter with union

This commit is contained in:
Jean Pierre Cimalando 2021-03-25 01:02:00 +01:00
parent 9386ed2f09
commit 2c0250d620
6 changed files with 129 additions and 128 deletions

View file

@ -180,7 +180,7 @@ ESpec<LoopMode> loopMode { LoopMode::no_loop, {LoopMode::no_loop, LoopMode::loop
ESpec<VelocityOverride> velocityOverride { VelocityOverride::current, {VelocityOverride::current, VelocityOverride::previous}, 0}; ESpec<VelocityOverride> velocityOverride { VelocityOverride::current, {VelocityOverride::current, VelocityOverride::previous}, 0};
ESpec<SelfMask> selfMask { SelfMask::mask, {SelfMask::mask, SelfMask::dontMask}, 0}; ESpec<SelfMask> selfMask { SelfMask::mask, {SelfMask::mask, SelfMask::dontMask}, 0};
ESpec<FilterType> filter { FilterType::kFilterNone, {FilterType::kFilterNone, FilterType::kFilterPeq}, 0}; ESpec<FilterType> filter { FilterType::kFilterNone, {FilterType::kFilterNone, FilterType::kFilterPeq}, 0};
ESpec<EqType> eq { EqType::kEqNone, {EqType::kEqNone, EqType::kEqHighShelf}, 0}; ESpec<EqType> eq { EqType::kEqNone, {EqType::kEqNone, EqType::kEqHshelf}, 0};
} // namespace Default } // namespace Default
} // namespace sfz } // namespace sfz

View file

@ -392,8 +392,8 @@ absl::optional<EqType> Opcode::readOptional(OpcodeSpec<EqType>) const
{ {
switch (hash(value)) { switch (hash(value)) {
case hash("peak"): return kEqPeak; case hash("peak"): return kEqPeak;
case hash("lshelf"): return kEqLowShelf; case hash("lshelf"): return kEqLshelf;
case hash("hshelf"): return kEqHighShelf; case hash("hshelf"): return kEqHshelf;
} }
DBG("Unknown EQ type: " << value); DBG("Unknown EQ type: " << value);

View file

@ -18,59 +18,24 @@ namespace sfz {
// SFZ v2 multi-mode filter // SFZ v2 multi-mode filter
struct Filter::Impl { struct Filter::Impl {
double fSampleRate = sfz::config::defaultSampleRate;
FilterType fType = kFilterNone; FilterType fType = kFilterNone;
unsigned fChannels = 1; unsigned fChannels = 1;
enum { maxChannels = 2 }; enum { maxChannels = 2 };
sfzLpf1p fDspLpf1p; union U {
sfzLpf2p fDspLpf2p; U() {}
sfzLpf4p fDspLpf4p; ~U() {}
sfzLpf6p fDspLpf6p;
sfzHpf1p fDspHpf1p;
sfzHpf2p fDspHpf2p;
sfzHpf4p fDspHpf4p;
sfzHpf6p fDspHpf6p;
sfzBpf1p fDspBpf1p;
sfzBpf2p fDspBpf2p;
sfzBpf4p fDspBpf4p;
sfzBpf6p fDspBpf6p;
sfzApf1p fDspApf1p;
sfzBrf1p fDspBrf1p;
sfzBrf2p fDspBrf2p;
sfzPink fDspPink;
sfzLpf2pSv fDspLpf2pSv;
sfzHpf2pSv fDspHpf2pSv;
sfzBpf2pSv fDspBpf2pSv;
sfzBrf2pSv fDspBrf2pSv;
sfzLsh fDspLsh;
sfzHsh fDspHsh;
sfzPeq fDspPeq;
sfz2chLpf1p fDsp2chLpf1p; #define DECLARE_MEMBER(type) \
sfz2chLpf2p fDsp2chLpf2p; sfz##type fDsp##type; \
sfz2chLpf4p fDsp2chLpf4p; sfz2ch##type fDsp2ch##type;
sfz2chLpf6p fDsp2chLpf6p; SFZ_EACH_FILTER(DECLARE_MEMBER)
sfz2chHpf1p fDsp2chHpf1p; #undef DECLARE_MEMBER
sfz2chHpf2p fDsp2chHpf2p; } u;
sfz2chHpf4p fDsp2chHpf4p;
sfz2chHpf6p fDsp2chHpf6p;
sfz2chBpf1p fDsp2chBpf1p;
sfz2chBpf2p fDsp2chBpf2p;
sfz2chBpf4p fDsp2chBpf4p;
sfz2chBpf6p fDsp2chBpf6p;
sfz2chApf1p fDsp2chApf1p;
sfz2chBrf1p fDsp2chBrf1p;
sfz2chBrf2p fDsp2chBrf2p;
sfz2chPink fDsp2chPink;
sfz2chLpf2pSv fDsp2chLpf2pSv;
sfz2chHpf2pSv fDsp2chHpf2pSv;
sfz2chBpf2pSv fDsp2chBpf2pSv;
sfz2chBrf2pSv fDsp2chBrf2pSv;
sfz2chLsh fDsp2chLsh;
sfz2chHsh fDsp2chHsh;
sfz2chPeq fDsp2chPeq;
sfzFilterDsp *getDsp(unsigned channels, FilterType type); sfzFilterDsp *getDsp(unsigned channels, FilterType type);
sfzFilterDsp *newDsp(unsigned channels, FilterType type);
static constexpr uint32_t idDsp(unsigned channels, FilterType type) static constexpr uint32_t idDsp(unsigned channels, FilterType type)
{ {
@ -85,17 +50,20 @@ Filter::Filter()
Filter::~Filter() Filter::~Filter()
{ {
sfzFilterDsp *dsp = P->getDsp(P->fChannels, P->fType);
if (dsp)
dsp->~sfzFilterDsp();
} }
void Filter::init(double sampleRate) void Filter::init(double sampleRate)
{ {
for (unsigned channels = 1; channels <= Impl::maxChannels; ++channels) { sfzFilterDsp *dsp = P->getDsp(P->fChannels, P->fType);
FilterType ftype = static_cast<FilterType>(1);
while (sfzFilterDsp *dsp = P->getDsp(channels, ftype)) { if (dsp)
dsp->init(sampleRate); dsp->init(sampleRate);
ftype = static_cast<FilterType>(static_cast<int>(ftype) + 1);
} P->fSampleRate = sampleRate;
}
} }
void Filter::clear() void Filter::clear()
@ -199,8 +167,15 @@ FilterType Filter::type() const
void Filter::setType(FilterType type) void Filter::setType(FilterType type)
{ {
if (P->fType != type) { if (P->fType != type) {
sfzFilterDsp *dsp = P->getDsp(P->fChannels, P->fType);
if (dsp)
dsp->~sfzFilterDsp();
P->fType = type; P->fType = type;
clear();
dsp = P->newDsp(P->fChannels, type);
if (dsp)
dsp->init(P->fSampleRate);
} }
} }
@ -209,74 +184,49 @@ sfzFilterDsp *Filter::Impl::getDsp(unsigned channels, FilterType type)
switch (idDsp(channels, type)) { switch (idDsp(channels, type)) {
default: return nullptr; default: return nullptr;
case idDsp(1, kFilterApf1p): return &fDspApf1p; #define CASE(type) \
case idDsp(1, kFilterBpf1p): return &fDspBpf1p; case idDsp(1, kFilter##type): return &u.fDsp##type; \
case idDsp(1, kFilterBpf2p): return &fDspBpf2p; case idDsp(2, kFilter##type): return &u.fDsp2ch##type;
case idDsp(1, kFilterBpf4p): return &fDspBpf4p; SFZ_EACH_FILTER(CASE)
case idDsp(1, kFilterBpf6p): return &fDspBpf6p; #undef CASE
case idDsp(1, kFilterBrf1p): return &fDspBrf1p; }
case idDsp(1, kFilterBrf2p): return &fDspBrf2p; }
case idDsp(1, kFilterHpf1p): return &fDspHpf1p;
case idDsp(1, kFilterHpf2p): return &fDspHpf2p;
case idDsp(1, kFilterHpf4p): return &fDspHpf4p;
case idDsp(1, kFilterHpf6p): return &fDspHpf6p;
case idDsp(1, kFilterLpf1p): return &fDspLpf1p;
case idDsp(1, kFilterLpf2p): return &fDspLpf2p;
case idDsp(1, kFilterLpf4p): return &fDspLpf4p;
case idDsp(1, kFilterLpf6p): return &fDspLpf6p;
case idDsp(1, kFilterPink): return &fDspPink;
case idDsp(1, kFilterLpf2pSv): return &fDspLpf2pSv;
case idDsp(1, kFilterHpf2pSv): return &fDspHpf2pSv;
case idDsp(1, kFilterBpf2pSv): return &fDspBpf2pSv;
case idDsp(1, kFilterBrf2pSv): return &fDspBrf2pSv;
case idDsp(1, kFilterLsh): return &fDspLsh;
case idDsp(1, kFilterHsh): return &fDspHsh;
case idDsp(1, kFilterPeq): return &fDspPeq;
case idDsp(2, kFilterApf1p): return &fDsp2chApf1p; sfzFilterDsp *Filter::Impl::newDsp(unsigned channels, FilterType type)
case idDsp(2, kFilterBpf1p): return &fDsp2chBpf1p; {
case idDsp(2, kFilterBpf2p): return &fDsp2chBpf2p; switch (idDsp(channels, type)) {
case idDsp(2, kFilterBpf4p): return &fDsp2chBpf4p; default: return nullptr;
case idDsp(2, kFilterBpf6p): return &fDsp2chBpf6p;
case idDsp(2, kFilterBrf1p): return &fDsp2chBrf1p; #define CASE(type) \
case idDsp(2, kFilterBrf2p): return &fDsp2chBrf2p; case idDsp(1, kFilter##type): return new(&u.fDsp##type) sfz##type; \
case idDsp(2, kFilterHpf1p): return &fDsp2chHpf1p; case idDsp(2, kFilter##type): return new(&u.fDsp2ch##type) sfz2ch##type;
case idDsp(2, kFilterHpf2p): return &fDsp2chHpf2p; SFZ_EACH_FILTER(CASE)
case idDsp(2, kFilterHpf4p): return &fDsp2chHpf4p; #undef CASE
case idDsp(2, kFilterHpf6p): return &fDsp2chHpf6p;
case idDsp(2, kFilterLpf1p): return &fDsp2chLpf1p;
case idDsp(2, kFilterLpf2p): return &fDsp2chLpf2p;
case idDsp(2, kFilterLpf4p): return &fDsp2chLpf4p;
case idDsp(2, kFilterLpf6p): return &fDsp2chLpf6p;
case idDsp(2, kFilterPink): return &fDsp2chPink;
case idDsp(2, kFilterLpf2pSv): return &fDsp2chLpf2pSv;
case idDsp(2, kFilterHpf2pSv): return &fDsp2chHpf2pSv;
case idDsp(2, kFilterBpf2pSv): return &fDsp2chBpf2pSv;
case idDsp(2, kFilterBrf2pSv): return &fDsp2chBrf2pSv;
case idDsp(2, kFilterLsh): return &fDsp2chLsh;
case idDsp(2, kFilterHsh): return &fDsp2chHsh;
case idDsp(2, kFilterPeq): return &fDsp2chPeq;
} }
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// SFZ v1 equalizer filter // SFZ v1 equalizer filter
struct FilterEq::Impl { struct FilterEq::Impl {
double fSampleRate = sfz::config::defaultSampleRate;
EqType fType = kEqNone; EqType fType = kEqNone;
unsigned fChannels = 1; unsigned fChannels = 1;
enum { maxChannels = 2 }; enum { maxChannels = 2 };
sfzEqPeak fDspPeak; union U {
sfzEqLshelf fDspLshelf; U() {}
sfzEqHshelf fDspHshelf; ~U() {}
sfz2chEqPeak fDsp2chPeak; #define DECLARE_MEMBER(type) \
sfz2chEqLshelf fDsp2chLshelf; sfzEq##type fDsp##type; \
sfz2chEqHshelf fDsp2chHshelf; sfz2chEq##type fDsp2ch##type;
SFZ_EACH_EQ(DECLARE_MEMBER)
#undef DECLARE_MEMBER
} u;
sfzFilterDsp *getDsp(unsigned channels, EqType type); sfzFilterDsp *getDsp(unsigned channels, EqType type);
sfzFilterDsp *newDsp(unsigned channels, EqType type);
static constexpr uint32_t idDsp(unsigned channels, EqType type) static constexpr uint32_t idDsp(unsigned channels, EqType type)
{ {
@ -291,17 +241,20 @@ FilterEq::FilterEq()
FilterEq::~FilterEq() FilterEq::~FilterEq()
{ {
sfzFilterDsp *dsp = P->getDsp(P->fChannels, P->fType);
if (dsp)
dsp->~sfzFilterDsp();
} }
void FilterEq::init(double sampleRate) void FilterEq::init(double sampleRate)
{ {
for (unsigned channels = 1; channels <= Impl::maxChannels; ++channels) { sfzFilterDsp *dsp = P->getDsp(P->fChannels, P->fType);
EqType ftype = static_cast<EqType>(1);
while (sfzFilterDsp *dsp = P->getDsp(channels, ftype)) { if (dsp)
dsp->init(sampleRate); dsp->init(sampleRate);
ftype = static_cast<EqType>(static_cast<int>(ftype) + 1);
} P->fSampleRate = sampleRate;
}
} }
void FilterEq::clear() void FilterEq::clear()
@ -406,8 +359,15 @@ EqType FilterEq::type() const
void FilterEq::setType(EqType type) void FilterEq::setType(EqType type)
{ {
if (P->fType != type) { if (P->fType != type) {
sfzFilterDsp *dsp = P->getDsp(P->fChannels, P->fType);
if (dsp)
dsp->~sfzFilterDsp();
P->fType = type; P->fType = type;
clear();
dsp = P->newDsp(P->fChannels, type);
if (dsp)
dsp->init(P->fSampleRate);
} }
} }
@ -416,13 +376,24 @@ sfzFilterDsp *FilterEq::Impl::getDsp(unsigned channels, EqType type)
switch (idDsp(channels, type)) { switch (idDsp(channels, type)) {
default: return nullptr; default: return nullptr;
case idDsp(1, kEqPeak): return &fDspPeak; #define CASE(type) \
case idDsp(1, kEqLowShelf): return &fDspLshelf; case idDsp(1, kEq##type): return &u.fDsp##type; \
case idDsp(1, kEqHighShelf): return &fDspHshelf; case idDsp(2, kEq##type): return &u.fDsp2ch##type;
SFZ_EACH_EQ(CASE)
#undef CASE
}
}
case idDsp(2, kEqPeak): return &fDsp2chPeak; sfzFilterDsp *FilterEq::Impl::newDsp(unsigned channels, EqType type)
case idDsp(2, kEqLowShelf): return &fDsp2chLshelf; {
case idDsp(2, kEqHighShelf): return &fDsp2chHshelf; switch (idDsp(channels, type)) {
default: return nullptr;
#define CASE(type) \
case idDsp(1, kEq##type): return new (&u.fDsp##type) sfzEq##type; \
case idDsp(2, kEq##type): return new (&u.fDsp2ch##type) sfz2chEq##type;
SFZ_EACH_EQ(CASE)
#undef CASE
} }
} }

View file

@ -197,8 +197,8 @@ private:
enum EqType : int { enum EqType : int {
kEqNone, kEqNone,
kEqPeak, kEqPeak,
kEqLowShelf, kEqLshelf,
kEqHighShelf, kEqHshelf,
}; };
} // namespace sfz } // namespace sfz

View file

@ -216,3 +216,33 @@ struct sfz2chPeq final : public sfzFilterPkSh<faust2chPeq> {};
struct sfz2chEqPeak final : public sfzFilterEq<faust2chEqPeak> {}; struct sfz2chEqPeak final : public sfzFilterEq<faust2chEqPeak> {};
struct sfz2chEqLshelf final : public sfzFilterEq<faust2chEqLshelf> {}; struct sfz2chEqLshelf final : public sfzFilterEq<faust2chEqLshelf> {};
struct sfz2chEqHshelf final : public sfzFilterEq<faust2chEqHshelf> {}; struct sfz2chEqHshelf final : public sfzFilterEq<faust2chEqHshelf> {};
#define SFZ_EACH_FILTER(F) \
F(Apf1p) \
F(Bpf1p) \
F(Bpf2p) \
F(Bpf4p) \
F(Bpf6p) \
F(Brf1p) \
F(Brf2p) \
F(Hpf1p) \
F(Hpf2p) \
F(Hpf4p) \
F(Hpf6p) \
F(Lpf1p) \
F(Lpf2p) \
F(Lpf4p) \
F(Lpf6p) \
F(Pink) \
F(Lpf2pSv) \
F(Hpf2pSv) \
F(Bpf2pSv) \
F(Brf2pSv) \
F(Lsh) \
F(Hsh) \
F(Peq)
#define SFZ_EACH_EQ(F) \
F(Peak) \
F(Lshelf) \
F(Hshelf)

View file

@ -1254,8 +1254,8 @@ void sfz::Synth::dispatchMessage(Client& client, int delay, const char* path, co
switch (eq.type) { switch (eq.type) {
case EqType::kEqNone: client.receive<'s'>(delay, path, "none"); break; case EqType::kEqNone: client.receive<'s'>(delay, path, "none"); break;
case EqType::kEqPeak: client.receive<'s'>(delay, path, "peak"); break; case EqType::kEqPeak: client.receive<'s'>(delay, path, "peak"); break;
case EqType::kEqLowShelf: client.receive<'s'>(delay, path, "lshelf"); break; case EqType::kEqLshelf: client.receive<'s'>(delay, path, "lshelf"); break;
case EqType::kEqHighShelf: client.receive<'s'>(delay, path, "hshelf"); break; case EqType::kEqHshelf: client.receive<'s'>(delay, path, "hshelf"); break;
} }
} break; } break;