Update fx with faust helpers, change oversampling strategy

This commit is contained in:
Jean Pierre Cimalando 2021-02-25 00:16:24 +01:00
parent cd43cac59b
commit 5c5c434297
10 changed files with 88 additions and 82 deletions

View file

@ -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)

View file

@ -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<float, 2> _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"):

View file

@ -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 <cmath>
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<float> 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() };

View file

@ -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 <absl/memory/memory.h>
#include <absl/strings/ascii.h>
#include <cmath>
#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;
}

View file

@ -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<float, 2> _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"):

View file

@ -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);

View file

@ -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, <math.h>);
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;

View file

@ -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, <math.h>);
// 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;

View file

@ -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, <math.h>);
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;

View file

@ -1,9 +1,8 @@
import("stdfaust.lib");
limiter(x) = gain*x with {
att = 0.0008 * over;
rel = 0.5 * over;
over = fconstant(int _oversampling, <math.h>);
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));
};