From 5c5c4342970cb3a3179fec307ac170931215d9fa Mon Sep 17 00:00:00 2001 From: Jean Pierre Cimalando Date: Thu, 25 Feb 2021 00:16:24 +0100 Subject: [PATCH] Update fx with faust helpers, change oversampling strategy --- src/CMakeLists.txt | 38 +++++++++++++++++++++++++++ src/sfizz/effects/Compressor.cpp | 29 ++++++++------------ src/sfizz/effects/Disto.cpp | 17 ++++-------- src/sfizz/effects/Fverb.cpp | 30 +++++++++------------ src/sfizz/effects/Gate.cpp | 29 ++++++++------------ src/sfizz/effects/Limiter.cpp | 6 ++--- src/sfizz/effects/dsp/compressor.dsp | 5 ++-- src/sfizz/effects/dsp/disto_stage.dsp | 4 +-- src/sfizz/effects/dsp/gate.dsp | 7 +++-- src/sfizz/effects/dsp/limiter.dsp | 5 ++-- 10 files changed, 88 insertions(+), 82 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cc19c67f..7be3fd64 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -340,6 +340,44 @@ foreach(filter_type "sfizz/gen/filters/sfz2ch${filter_type}.hxx") endforeach() +# Faust effects +add_faust_command( + "sfizz/effects/dsp/compressor.dsp" + "sfizz/effects/gen/compressor.hxx" + IN_PLACE + CLASS_NAME "faustCompressor" + IMPORT_DIRS "sfizz/dsp") +add_faust_command( + "sfizz/effects/dsp/disto_stage.dsp" + "sfizz/effects/gen/disto_stage.hxx" + IN_PLACE + CLASS_NAME "faustDisto" + IMPORT_DIRS "sfizz/dsp") +add_faust_command( + "sfizz/effects/dsp/fverb.dsp" + "sfizz/effects/gen/fverb.hxx" + IN_PLACE + CLASS_NAME "faustFverb" + IMPORT_DIRS "sfizz/dsp") +add_faust_command( + "sfizz/effects/dsp/gate.dsp" + "sfizz/effects/gen/gate.hxx" + IN_PLACE + CLASS_NAME "faustGate" + IMPORT_DIRS "sfizz/dsp") +add_faust_command( + "sfizz/effects/dsp/limiter.dsp" + "sfizz/effects/gen/limiter.hxx" + IN_PLACE + CLASS_NAME "faustLimiter" + IMPORT_DIRS "sfizz/dsp") +target_sources(sfizz_internal PRIVATE + "sfizz/effects/gen/compressor.hxx" + "sfizz/effects/gen/disto_stage.hxx" + "sfizz/effects/gen/fverb.hxx" + "sfizz/effects/gen/gate.hxx" + "sfizz/effects/gen/limiter.hxx") + # Windows installer if(WIN32) include(VSTConfig) diff --git a/src/sfizz/effects/Compressor.cpp b/src/sfizz/effects/Compressor.cpp index f2608531..0cd528dc 100644 --- a/src/sfizz/effects/Compressor.cpp +++ b/src/sfizz/effects/Compressor.cpp @@ -17,6 +17,7 @@ */ #include "Compressor.h" +#include "gen/compressor.hxx" #include "Opcode.h" #include "AudioSpan.h" #include "MathHelpers.h" @@ -24,8 +25,6 @@ #include "absl/memory/memory.h" static constexpr int _oversampling = 2; -#define FAUST_UIMACROS 1 -#include "gen/compressor.hxx" namespace sfz { namespace fx { @@ -38,12 +37,6 @@ namespace fx { AudioBuffer _gain2x { 2, _oversampling * config::defaultSamplesPerBlock }; hiir::Downsampler2x<12> _downsampler2x[EffectChannels]; hiir::Upsampler2x<12> _upsampler2x[EffectChannels]; - - #define DEFINE_SET_GET(type, ident, name, var, def, min, max, step) \ - float get_##ident(size_t i) const noexcept { return _compressor[i].var; } \ - void set_##ident(size_t i, float value) noexcept { _compressor[i].var = value; } - FAUST_LIST_ACTIVES(DEFINE_SET_GET); - #undef DEFINE_SET_GET }; Compressor::Compressor() @@ -62,8 +55,8 @@ namespace fx { { Impl& impl = *_impl; for (faustCompressor& comp : impl._compressor) { - comp.classInit(sampleRate); - comp.instanceConstants(sampleRate); + comp.classInit(_oversampling * sampleRate); + comp.instanceConstants(_oversampling * sampleRate); } for (unsigned c = 0; c < EffectChannels; ++c) { @@ -164,29 +157,29 @@ namespace fx { case hash("comp_attack"): { auto value = opc.read(Default::compAttack); - for (size_t c = 0; c < 2; ++c) - impl.set_Attack(c, value); + for (faustCompressor& comp : impl._compressor) + comp.setAttack(value); } break; case hash("comp_release"): { auto value = opc.read(Default::compRelease); - for (size_t c = 0; c < 2; ++c) - impl.set_Release(c, value); + for (faustCompressor& comp : impl._compressor) + comp.setRelease(value); } break; case hash("comp_threshold"): { auto value = opc.read(Default::compThreshold); - for (size_t c = 0; c < 2; ++c) - impl.set_Threshold(c, value); + for (faustCompressor& comp : impl._compressor) + comp.setThreshold(value); } break; case hash("comp_ratio"): { auto value = opc.read(Default::compRatio); - for (size_t c = 0; c < 2; ++c) - impl.set_Ratio(c, value); + for (faustCompressor& comp : impl._compressor) + comp.setRatio(value); } break; case hash("comp_gain"): diff --git a/src/sfizz/effects/Disto.cpp b/src/sfizz/effects/Disto.cpp index ed9d3487..05ba158c 100644 --- a/src/sfizz/effects/Disto.cpp +++ b/src/sfizz/effects/Disto.cpp @@ -19,6 +19,7 @@ */ #include "Disto.h" +#include "gen/disto_stage.hxx" #include "Opcode.h" #include "Config.h" #include "MathHelpers.h" @@ -27,8 +28,6 @@ #include static constexpr int _oversampling = 8; -#define FAUST_UIMACROS 1 -#include "gen/disto_stage.hxx" namespace sfz { namespace fx { @@ -56,12 +55,6 @@ struct Disto::Impl { float mk = 21.0f + _tone * 1.08f; return 440.0f * std::exp2((mk - 69.0f) * (1.0f / 12.0f)); } - - #define DEFINE_SET_GET(type, ident, name, var, def, min, max, step) \ - float get_##ident(size_t c, size_t s) const noexcept { return _stages[c][s].var; } \ - void set_##ident(size_t c, size_t s, float value) noexcept { _stages[c][s].var = value; } - FAUST_LIST_ACTIVES(DEFINE_SET_GET); - #undef DEFINE_SET_GET }; Disto::Disto() @@ -71,7 +64,7 @@ Disto::Disto() for (unsigned c = 0; c < EffectChannels; ++c) { for (faustDisto& stage : impl._stages[c]) - stage.init(config::defaultSampleRate); + stage.init(_oversampling * config::defaultSampleRate); } } @@ -86,8 +79,8 @@ void Disto::setSampleRate(double sampleRate) for (unsigned c = 0; c < EffectChannels; ++c) { for (faustDisto& stage : impl._stages[c]) { - stage.classInit(sampleRate); - stage.instanceConstants(sampleRate); + stage.classInit(_oversampling * sampleRate); + stage.instanceConstants(_oversampling * sampleRate); } } } @@ -150,7 +143,7 @@ void Disto::process(const float* const inputs[], float* const outputs[], unsigne absl::Span stageInOut = upsamplerOut; for (unsigned s = 0, numStages = impl._numStages; s < numStages; ++s) { // set depth parameter (TODO modulation) - impl.set_Depth(c, s, depth); + impl._stages[c][s].setDepth(depth); // float *faustIn[] = { stageInOut.data() }; float *faustOut[] = { stageInOut.data() }; diff --git a/src/sfizz/effects/Fverb.cpp b/src/sfizz/effects/Fverb.cpp index f5161533..804e12a3 100644 --- a/src/sfizz/effects/Fverb.cpp +++ b/src/sfizz/effects/Fverb.cpp @@ -5,14 +5,13 @@ // If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz #include "Fverb.h" +#include "gen/fverb.hxx" #include "Opcode.h" #include "Config.h" #include "MathHelpers.h" #include #include #include -#define FAUST_UIMACROS 1 -#include "gen/fverb.hxx" /** Note(jpc): implementation status @@ -40,12 +39,6 @@ namespace fx { struct Fverb::Impl { faustFverb dsp; - #define DEFINE_SET_GET(type, ident, name, var, def, min, max, step) \ - float get_##ident() const noexcept { return dsp.var; } \ - void set_##ident(float value) noexcept { dsp.var = value; } - FAUST_LIST_ACTIVES(DEFINE_SET_GET); - #undef DEFINE_SET_GET - struct Profile { float tailDensity; // % float decayAtMaxSize; // % @@ -240,17 +233,18 @@ namespace fx { const float decayMin = decayMax * 0.5f; Impl& impl = *reverb->impl_; - impl.set_Predelay(predelay * 1e3); - impl.set_Tail_density(profile->tailDensity); - impl.set_Decay(decayMax * size * 0.01f + decayMin * (1.0f - size * 0.01f)); - impl.set_Modulator_frequency(profile->modulationFrequency); - impl.set_Modulator_depth(profile->modulationDepth); - impl.set_Dry(profile->dry * dry * 0.01f); - impl.set_Wet(profile->wet * wet * 0.01f); - impl.set_Input_amount(input); - impl.set_Input_low_pass_cutoff(Impl::lpfCutoff(tone)); + faustFverb& dsp = impl.dsp; + dsp.setPredelay(predelay * 1e3); + dsp.setTailDensity(profile->tailDensity); + dsp.setDecay(decayMax * size * 0.01f + decayMin * (1.0f - size * 0.01f)); + dsp.setModulatorFrequency(profile->modulationFrequency); + dsp.setModulatorDepth(profile->modulationDepth); + dsp.setDry(profile->dry * dry * 0.01f); + dsp.setWet(profile->wet * wet * 0.01f); + dsp.setInputAmount(input); + dsp.setInputLowPassCutoff(Impl::lpfCutoff(tone)); // NOTE(jpc): damp formula not well calibrated, but sounds ok-ish - impl.set_Damping(Impl::lpfCutoff(100 - 0.5 * damp)); + dsp.setDamping(Impl::lpfCutoff(100 - 0.5 * damp)); return fx; } diff --git a/src/sfizz/effects/Gate.cpp b/src/sfizz/effects/Gate.cpp index bfe8fdfc..e8852dfb 100644 --- a/src/sfizz/effects/Gate.cpp +++ b/src/sfizz/effects/Gate.cpp @@ -20,6 +20,7 @@ */ #include "Gate.h" +#include "gen/gate.hxx" #include "Opcode.h" #include "AudioSpan.h" #include "MathHelpers.h" @@ -27,8 +28,6 @@ #include "absl/memory/memory.h" static constexpr int _oversampling = 2; -#define FAUST_UIMACROS 1 -#include "gen/gate.hxx" namespace sfz { namespace fx { @@ -41,12 +40,6 @@ namespace fx { AudioBuffer _gain2x { 2, _oversampling * config::defaultSamplesPerBlock }; hiir::Downsampler2x<12> _downsampler2x[EffectChannels]; hiir::Upsampler2x<12> _upsampler2x[EffectChannels]; - - #define DEFINE_SET_GET(type, ident, name, var, def, min, max, step) \ - float get_##ident(size_t i) const noexcept { return _gate[i].var; } \ - void set_##ident(size_t i, float value) noexcept { _gate[i].var = value; } - FAUST_LIST_ACTIVES(DEFINE_SET_GET); - #undef DEFINE_SET_GET }; Gate::Gate() @@ -65,8 +58,8 @@ namespace fx { { Impl& impl = *_impl; for (faustGate& gate : impl._gate) { - gate.classInit(sampleRate); - gate.instanceConstants(sampleRate); + gate.classInit(_oversampling * sampleRate); + gate.instanceConstants(_oversampling * sampleRate); } for (unsigned c = 0; c < EffectChannels; ++c) { @@ -167,29 +160,29 @@ namespace fx { case hash("gate_attack"): { auto value = opc.read(Default::gateAttack); - for (size_t c = 0; c < 2; ++c) - impl.set_Attack(c, value); + for (faustGate& gate : impl._gate) + gate.setAttack(value); } break; case hash("gate_hold"): { auto value = opc.read(Default::gateHold); - for (size_t c = 0; c < 2; ++c) - impl.set_Hold(c, value); + for (faustGate& gate : impl._gate) + gate.setHold(value); } break; case hash("gate_release"): { auto value = opc.read(Default::gateRelease); - for (size_t c = 0; c < 2; ++c) - impl.set_Release(c, value); + for (faustGate& gate : impl._gate) + gate.setRelease(value); } break; case hash("gate_threshold"): { auto value = opc.read(Default::gateThreshold); - for (size_t c = 0; c < 2; ++c) - impl.set_Threshold(c, value); + for (faustGate& gate : impl._gate) + gate.setThreshold(value); } break; case hash("gate_stlink"): diff --git a/src/sfizz/effects/Limiter.cpp b/src/sfizz/effects/Limiter.cpp index eb5f1c3c..8c13ca62 100644 --- a/src/sfizz/effects/Limiter.cpp +++ b/src/sfizz/effects/Limiter.cpp @@ -11,12 +11,12 @@ */ #include "Limiter.h" +#include "gen/limiter.hxx" #include "Opcode.h" #include "AudioSpan.h" #include "absl/memory/memory.h" static constexpr int _oversampling = 2; -#include "gen/limiter.hxx" namespace sfz { namespace fx { @@ -33,8 +33,8 @@ namespace fx { void Limiter::setSampleRate(double sampleRate) { - _limiter->classInit(sampleRate); - _limiter->instanceConstants(sampleRate); + _limiter->classInit(_oversampling * sampleRate); + _limiter->instanceConstants(_oversampling * sampleRate); for (unsigned c = 0; c < EffectChannels; ++c) { _downsampler2x[c].set_coefs(OSCoeffs2x); diff --git a/src/sfizz/effects/dsp/compressor.dsp b/src/sfizz/effects/dsp/compressor.dsp index 6675e7c1..acec90dd 100644 --- a/src/sfizz/effects/dsp/compressor.dsp +++ b/src/sfizz/effects/dsp/compressor.dsp @@ -3,9 +3,8 @@ import("stdfaust.lib"); cgain = co.compression_gain_mono(ratio, thresh, att, rel) with { ratio = hslider("[1] Ratio", 1.0, 1.0, 20.0, 0.01); thresh = hslider("[2] Threshold [unit:dB]", 0.0, -60.0, 0.0, 0.01); - over = fconstant(int _oversampling, ); - att = hslider("[3] Attack [unit:s]", 0.0, 0.0, 0.5, 1e-3) : *(over); - rel = hslider("[4] Release [unit:s]", 0.0, 0.0, 5.0, 1e-3) : *(over); + att = hslider("[3] Attack [unit:s]", 0.0, 0.0, 0.5, 1e-3); + rel = hslider("[4] Release [unit:s]", 0.0, 0.0, 5.0, 1e-3); }; process = cgain; diff --git a/src/sfizz/effects/dsp/disto_stage.dsp b/src/sfizz/effects/dsp/disto_stage.dsp index f05a54fa..f2494745 100644 --- a/src/sfizz/effects/dsp/disto_stage.dsp +++ b/src/sfizz/effects/dsp/disto_stage.dsp @@ -1,14 +1,12 @@ import("stdfaust.lib"); disto_stage(depth, x) = shs*hh(x)+(1.0-shs)*lh(x) : fi.dcblockerat(5.0) with { - over = fconstant(int _oversampling, ); - // sigmoid parameters a = depth*0.2+2.0; b = 2.0; // smooth hysteresis transition - shs = hs : si.smooth(ba.tau2pole(10e-3*over)); + shs = hs : si.smooth(ba.tau2pole(10e-3)); // the low and high hysteresis lh(x) = sig(a*x)*b; diff --git a/src/sfizz/effects/dsp/gate.dsp b/src/sfizz/effects/dsp/gate.dsp index 7bac7f27..bbb303f3 100644 --- a/src/sfizz/effects/dsp/gate.dsp +++ b/src/sfizz/effects/dsp/gate.dsp @@ -2,10 +2,9 @@ import("stdfaust.lib"); ggain = ef.gate_gain_mono(thresh, att, hold, rel) with { thresh = hslider("[1] Threshold [unit:dB]", 0.0, -60.0, 0.0, 0.01); - over = fconstant(int _oversampling, ); - att = hslider("[2] Attack [unit:s]", 0.0, 0.0, 10.0, 1e-3) : *(over); - hold = hslider("[3] Hold [unit:s]", 0.0, 0.0, 10.0, 1e-3) : *(over); - rel = hslider("[4] Release [unit:s]", 0.0, 0.0, 5.0, 1e-3) : *(over); + att = hslider("[2] Attack [unit:s]", 0.0, 0.0, 10.0, 1e-3); + hold = hslider("[3] Hold [unit:s]", 0.0, 0.0, 10.0, 1e-3); + rel = hslider("[4] Release [unit:s]", 0.0, 0.0, 5.0, 1e-3); }; process = ggain; diff --git a/src/sfizz/effects/dsp/limiter.dsp b/src/sfizz/effects/dsp/limiter.dsp index cbb14b26..e8ed03d9 100644 --- a/src/sfizz/effects/dsp/limiter.dsp +++ b/src/sfizz/effects/dsp/limiter.dsp @@ -1,9 +1,8 @@ import("stdfaust.lib"); limiter(x) = gain*x with { - att = 0.0008 * over; - rel = 0.5 * over; - over = fconstant(int _oversampling, ); + att = 0.0008; + rel = 0.5; peak = x : an.amp_follower_ud(att, rel); gain = ba.if(peak>1.0, 1.0/peak, 1.0) : si.smooth(ba.tau2pole(0.5*att)); };