Skip to content

Commit

Permalink
Merge pull request #745 from jpcima/filter
Browse files Browse the repository at this point in the history
Compact multi-mode filter with union
  • Loading branch information
jpcima authored Mar 25, 2021
2 parents 9386ed2 + 2c0250d commit 257ed12
Show file tree
Hide file tree
Showing 6 changed files with 131 additions and 130 deletions.
2 changes: 1 addition & 1 deletion src/sfizz/Defaults.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<SelfMask> selfMask { SelfMask::mask, {SelfMask::mask, SelfMask::dontMask}, 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 sfz
4 changes: 2 additions & 2 deletions src/sfizz/Opcode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -392,8 +392,8 @@ absl::optional<EqType> Opcode::readOptional(OpcodeSpec<EqType>) const
{
switch (hash(value)) {
case hash("peak"): return kEqPeak;
case hash("lshelf"): return kEqLowShelf;
case hash("hshelf"): return kEqHighShelf;
case hash("lshelf"): return kEqLshelf;
case hash("hshelf"): return kEqHshelf;
}

DBG("Unknown EQ type: " << value);
Expand Down
217 changes: 94 additions & 123 deletions src/sfizz/SfzFilter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,59 +18,24 @@ namespace sfz {
// SFZ v2 multi-mode filter

struct Filter::Impl {
double fSampleRate = sfz::config::defaultSampleRate;
FilterType fType = kFilterNone;
unsigned fChannels = 1;
enum { maxChannels = 2 };

sfzLpf1p fDspLpf1p;
sfzLpf2p fDspLpf2p;
sfzLpf4p fDspLpf4p;
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;
sfz2chLpf2p fDsp2chLpf2p;
sfz2chLpf4p fDsp2chLpf4p;
sfz2chLpf6p fDsp2chLpf6p;
sfz2chHpf1p fDsp2chHpf1p;
sfz2chHpf2p fDsp2chHpf2p;
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;
union U {
U() {}
~U() {}

#define DECLARE_MEMBER(type) \
sfz##type fDsp##type; \
sfz2ch##type fDsp2ch##type;
SFZ_EACH_FILTER(DECLARE_MEMBER)
#undef DECLARE_MEMBER
} u;

sfzFilterDsp *getDsp(unsigned channels, FilterType type);
sfzFilterDsp *newDsp(unsigned channels, FilterType type);

static constexpr uint32_t idDsp(unsigned channels, FilterType type)
{
Expand All @@ -85,17 +50,20 @@ Filter::Filter()

Filter::~Filter()
{
sfzFilterDsp *dsp = P->getDsp(P->fChannels, P->fType);

if (dsp)
dsp->~sfzFilterDsp();
}

void Filter::init(double sampleRate)
{
for (unsigned channels = 1; channels <= Impl::maxChannels; ++channels) {
FilterType ftype = static_cast<FilterType>(1);
while (sfzFilterDsp *dsp = P->getDsp(channels, ftype)) {
dsp->init(sampleRate);
ftype = static_cast<FilterType>(static_cast<int>(ftype) + 1);
}
}
sfzFilterDsp *dsp = P->getDsp(P->fChannels, P->fType);

if (dsp)
dsp->init(sampleRate);

P->fSampleRate = sampleRate;
}

void Filter::clear()
Expand Down Expand Up @@ -199,8 +167,15 @@ FilterType Filter::type() const
void Filter::setType(FilterType type)
{
if (P->fType != type) {
sfzFilterDsp *dsp = P->getDsp(P->fChannels, P->fType);
if (dsp)
dsp->~sfzFilterDsp();

P->fType = type;
clear();

dsp = P->newDsp(P->fChannels, type);
if (dsp)
dsp->init(P->fSampleRate);
}
}

Expand All @@ -209,74 +184,49 @@ sfzFilterDsp *Filter::Impl::getDsp(unsigned channels, FilterType type)
switch (idDsp(channels, type)) {
default: return nullptr;

case idDsp(1, kFilterApf1p): return &fDspApf1p;
case idDsp(1, kFilterBpf1p): return &fDspBpf1p;
case idDsp(1, kFilterBpf2p): return &fDspBpf2p;
case idDsp(1, kFilterBpf4p): return &fDspBpf4p;
case idDsp(1, kFilterBpf6p): return &fDspBpf6p;
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;
case idDsp(2, kFilterBpf1p): return &fDsp2chBpf1p;
case idDsp(2, kFilterBpf2p): return &fDsp2chBpf2p;
case idDsp(2, kFilterBpf4p): return &fDsp2chBpf4p;
case idDsp(2, kFilterBpf6p): return &fDsp2chBpf6p;
case idDsp(2, kFilterBrf1p): return &fDsp2chBrf1p;
case idDsp(2, kFilterBrf2p): return &fDsp2chBrf2p;
case idDsp(2, kFilterHpf1p): return &fDsp2chHpf1p;
case idDsp(2, kFilterHpf2p): return &fDsp2chHpf2p;
case idDsp(2, kFilterHpf4p): return &fDsp2chHpf4p;
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;
#define CASE(type) \
case idDsp(1, kFilter##type): return &u.fDsp##type; \
case idDsp(2, kFilter##type): return &u.fDsp2ch##type;
SFZ_EACH_FILTER(CASE)
#undef CASE
}
}

sfzFilterDsp *Filter::Impl::newDsp(unsigned channels, FilterType type)
{
switch (idDsp(channels, type)) {
default: return nullptr;

#define CASE(type) \
case idDsp(1, kFilter##type): return new(&u.fDsp##type) sfz##type; \
case idDsp(2, kFilter##type): return new(&u.fDsp2ch##type) sfz2ch##type;
SFZ_EACH_FILTER(CASE)
#undef CASE
}
}

//------------------------------------------------------------------------------
// SFZ v1 equalizer filter


struct FilterEq::Impl {
double fSampleRate = sfz::config::defaultSampleRate;
EqType fType = kEqNone;
unsigned fChannels = 1;
enum { maxChannels = 2 };

sfzEqPeak fDspPeak;
sfzEqLshelf fDspLshelf;
sfzEqHshelf fDspHshelf;
union U {
U() {}
~U() {}

sfz2chEqPeak fDsp2chPeak;
sfz2chEqLshelf fDsp2chLshelf;
sfz2chEqHshelf fDsp2chHshelf;
#define DECLARE_MEMBER(type) \
sfzEq##type fDsp##type; \
sfz2chEq##type fDsp2ch##type;
SFZ_EACH_EQ(DECLARE_MEMBER)
#undef DECLARE_MEMBER
} u;

sfzFilterDsp *getDsp(unsigned channels, EqType type);
sfzFilterDsp *newDsp(unsigned channels, EqType type);

static constexpr uint32_t idDsp(unsigned channels, EqType type)
{
Expand All @@ -291,17 +241,20 @@ FilterEq::FilterEq()

FilterEq::~FilterEq()
{
sfzFilterDsp *dsp = P->getDsp(P->fChannels, P->fType);

if (dsp)
dsp->~sfzFilterDsp();
}

void FilterEq::init(double sampleRate)
{
for (unsigned channels = 1; channels <= Impl::maxChannels; ++channels) {
EqType ftype = static_cast<EqType>(1);
while (sfzFilterDsp *dsp = P->getDsp(channels, ftype)) {
dsp->init(sampleRate);
ftype = static_cast<EqType>(static_cast<int>(ftype) + 1);
}
}
sfzFilterDsp *dsp = P->getDsp(P->fChannels, P->fType);

if (dsp)
dsp->init(sampleRate);

P->fSampleRate = sampleRate;
}

void FilterEq::clear()
Expand Down Expand Up @@ -406,8 +359,15 @@ EqType FilterEq::type() const
void FilterEq::setType(EqType type)
{
if (P->fType != type) {
sfzFilterDsp *dsp = P->getDsp(P->fChannels, P->fType);
if (dsp)
dsp->~sfzFilterDsp();

P->fType = type;
clear();

dsp = P->newDsp(P->fChannels, type);
if (dsp)
dsp->init(P->fSampleRate);
}
}

Expand All @@ -416,13 +376,24 @@ sfzFilterDsp *FilterEq::Impl::getDsp(unsigned channels, EqType type)
switch (idDsp(channels, type)) {
default: return nullptr;

case idDsp(1, kEqPeak): return &fDspPeak;
case idDsp(1, kEqLowShelf): return &fDspLshelf;
case idDsp(1, kEqHighShelf): return &fDspHshelf;
#define CASE(type) \
case idDsp(1, kEq##type): return &u.fDsp##type; \
case idDsp(2, kEq##type): return &u.fDsp2ch##type;
SFZ_EACH_EQ(CASE)
#undef CASE
}
}

sfzFilterDsp *FilterEq::Impl::newDsp(unsigned channels, EqType type)
{
switch (idDsp(channels, type)) {
default: return nullptr;

case idDsp(2, kEqPeak): return &fDsp2chPeak;
case idDsp(2, kEqLowShelf): return &fDsp2chLshelf;
case idDsp(2, kEqHighShelf): return &fDsp2chHshelf;
#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
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/sfizz/SfzFilter.h
Original file line number Diff line number Diff line change
Expand Up @@ -197,8 +197,8 @@ class FilterEq {
enum EqType : int {
kEqNone,
kEqPeak,
kEqLowShelf,
kEqHighShelf,
kEqLshelf,
kEqHshelf,
};

} // namespace sfz
30 changes: 30 additions & 0 deletions src/sfizz/SfzFilterImpls.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -216,3 +216,33 @@ struct sfz2chPeq final : public sfzFilterPkSh<faust2chPeq> {};
struct sfz2chEqPeak final : public sfzFilterEq<faust2chEqPeak> {};
struct sfz2chEqLshelf final : public sfzFilterEq<faust2chEqLshelf> {};
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)
4 changes: 2 additions & 2 deletions src/sfizz/SynthMessaging.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1254,8 +1254,8 @@ void sfz::Synth::dispatchMessage(Client& client, int delay, const char* path, co
switch (eq.type) {
case EqType::kEqNone: client.receive<'s'>(delay, path, "none"); break;
case EqType::kEqPeak: client.receive<'s'>(delay, path, "peak"); break;
case EqType::kEqLowShelf: client.receive<'s'>(delay, path, "lshelf"); break;
case EqType::kEqHighShelf: client.receive<'s'>(delay, path, "hshelf"); break;
case EqType::kEqLshelf: client.receive<'s'>(delay, path, "lshelf"); break;
case EqType::kEqHshelf: client.receive<'s'>(delay, path, "hshelf"); break;
}
} break;

Expand Down

0 comments on commit 257ed12

Please sign in to comment.