Compact multi-mode filter with union
This commit is contained in:
parent
9386ed2f09
commit
2c0250d620
6 changed files with 129 additions and 128 deletions
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -197,8 +197,8 @@ private:
|
||||||
enum EqType : int {
|
enum EqType : int {
|
||||||
kEqNone,
|
kEqNone,
|
||||||
kEqPeak,
|
kEqPeak,
|
||||||
kEqLowShelf,
|
kEqLshelf,
|
||||||
kEqHighShelf,
|
kEqHshelf,
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace sfz
|
} // namespace sfz
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue