From b56821db00dfa0f9dd0875ef77cd617d12a3bdbd Mon Sep 17 00:00:00 2001 From: Jean Pierre Cimalando Date: Thu, 6 Aug 2020 00:53:43 +0200 Subject: [PATCH] Add the distortion --- dpf.mk | 1 + scripts/generate_disto.sh | 54 ++++++ src/CMakeLists.txt | 5 +- src/sfizz/Effects.cpp | 2 + src/sfizz/effects/Disto.cpp | 226 +++++++++++++++++++++++ src/sfizz/effects/Disto.h | 54 ++++++ src/sfizz/effects/dsp/disto_stage.dsp | 40 +++++ src/sfizz/effects/gen/disto_stage.cxx | 248 ++++++++++++++++++++++++++ 8 files changed, 629 insertions(+), 1 deletion(-) create mode 100755 scripts/generate_disto.sh create mode 100644 src/sfizz/effects/Disto.cpp create mode 100644 src/sfizz/effects/Disto.h create mode 100644 src/sfizz/effects/dsp/disto_stage.dsp create mode 100644 src/sfizz/effects/gen/disto_stage.cxx diff --git a/dpf.mk b/dpf.mk index ba675096..f79e7d41 100644 --- a/dpf.mk +++ b/dpf.mk @@ -61,6 +61,7 @@ SFIZZ_SOURCES = \ src/sfizz/effects/Apan.cpp \ src/sfizz/Effects.cpp \ src/sfizz/effects/Compressor.cpp \ + src/sfizz/effects/Disto.cpp \ src/sfizz/effects/Eq.cpp \ src/sfizz/effects/Filter.cpp \ src/sfizz/effects/Gain.cpp \ diff --git a/scripts/generate_disto.sh b/scripts/generate_disto.sh new file mode 100755 index 00000000..095cb147 --- /dev/null +++ b/scripts/generate_disto.sh @@ -0,0 +1,54 @@ +#!/bin/sh +set -e + +if ! test -d "src"; then + echo "Please run this in the project root directory." + exit 1 +fi + +# Note: needs faust >= 2.27.1 for UI macros +FAUSTARGS="-uim -inpl" + +# support GNU sed only, use gsed on a Mac +test -z "$SED" && SED=sed + +faustgen() { + mkdir -p src/sfizz/effects/gen + local outfile=src/sfizz/effects/gen/disto_stage.cxx + + local code=`faust $FAUSTARGS -cn faustDisto src/sfizz/effects/dsp/disto_stage.dsp` + + # suppress some faust-specific stuff we don't care + echo "$code" \ + | fgrep -v -- '->declare(' \ + | fgrep -v -- '->openHorizontalBox(' \ + | fgrep -v -- '->openVerticalBox(' \ + | fgrep -v -- '->closeBox(' \ + | fgrep -v -- '->addHorizontalSlider(' \ + | fgrep -v -- '->addVerticalSlider(' \ + > "$outfile" + + # remove metadata + $SED -r -i 's/void[ \t]+metadata[ \t]*\(Meta[ \t]*\*[ \t]*[a-zA-Z0-9_]+\)/void metadata()/' "$outfile" + + # remove UI + $SED -r -i 's/void[ \t]+buildUserInterface[ \t]*\(UI[ \t]*\*[ \t]*[a-zA-Z0-9_]+\)/void buildUserInterface()/' "$outfile" + + # remove inheritance + $SED -r -i 's/:[ \t]*public[ \t]+dsp\b\s*//' "$outfile" + + # remove virtual + $SED -r -i 's/\bvirtual\b\s*//' "$outfile" + + # remove undesired UIM + $SED -r -i '/^[ \t]*#define[ \t]+FAUST_(FILE_NAME|CLASS_NAME|INPUTS|OUTPUTS|ACTIVES|PASSIVES)/d' "$outfile" + $SED -r -i '/^[ \t]*FAUST_ADD.*/d' "$outfile" + + # direct access to parameter variables + $SED -r -i 's/\bprivate:/public:/' "$outfile" + + # remove trailing whitespace + $SED -r -i 's/[ \t]+$//' "$outfile" +} + +faustgen diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b8ec8e0c..6d0d5c83 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -11,7 +11,8 @@ set (FAUST_FILES sfizz/effects/dsp/limiter.dsp sfizz/effects/dsp/resonant_string.dsp sfizz/effects/dsp/compressor.dsp - sfizz/effects/dsp/gate.dsp) + sfizz/effects/dsp/gate.dsp + sfizz/effects/dsp/disto_stage.dsp) source_group ("Faust Files" FILES ${FAUST_FILES}) set (SFIZZ_HEADERS @@ -35,6 +36,7 @@ set (SFIZZ_HEADERS sfizz/effects/CommonLFO.h sfizz/effects/CommonLFO.hpp sfizz/effects/Compressor.h + sfizz/effects/Disto.h sfizz/effects/Eq.h sfizz/effects/Filter.h sfizz/effects/Gain.h @@ -130,6 +132,7 @@ set (SFIZZ_SOURCES sfizz/effects/Limiter.cpp sfizz/effects/Compressor.cpp sfizz/effects/Gate.cpp + sfizz/effects/Disto.cpp sfizz/effects/Strings.cpp sfizz/effects/Rectify.cpp sfizz/effects/Gain.cpp diff --git a/src/sfizz/Effects.cpp b/src/sfizz/Effects.cpp index f41f29dc..cc9254b1 100644 --- a/src/sfizz/Effects.cpp +++ b/src/sfizz/Effects.cpp @@ -17,6 +17,7 @@ #include "effects/Limiter.h" #include "effects/Compressor.h" #include "effects/Gate.h" +#include "effects/Disto.h" #include "effects/Strings.h" #include "effects/Rectify.h" #include "effects/Gain.h" @@ -35,6 +36,7 @@ void EffectFactory::registerStandardEffectTypes() registerEffectType("limiter", fx::Limiter::makeInstance); registerEffectType("comp", fx::Compressor::makeInstance); registerEffectType("gate", fx::Gate::makeInstance); + registerEffectType("disto", fx::Disto::makeInstance); registerEffectType("strings", fx::Strings::makeInstance); // extensions (book) diff --git a/src/sfizz/effects/Disto.cpp b/src/sfizz/effects/Disto.cpp new file mode 100644 index 00000000..4aea5188 --- /dev/null +++ b/src/sfizz/effects/Disto.cpp @@ -0,0 +1,226 @@ +// SPDX-License-Identifier: BSD-2-Clause + +// This code is part of the sfizz library and is licensed under a BSD 2-clause +// license. You should have receive a LICENSE.md file along with the code. +// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz + +/* + Note(jpc): implementation status + +- [x] disto_tone +- [ ] disto_tone_oncc +- [x] disto_depth +- [ ] disto_depth_oncc +- [x] disto_stages +- [x] disto_dry +- [ ] disto_dry_oncc +- [x] disto_wet +- [ ] disto_wet_oncc +*/ + +#include "Disto.h" +#include "Opcode.h" +#include "Config.h" +#include +#include +#include +#include + +static constexpr int _oversampling = 8; +#define FAUST_UIMACROS 1 +#include "gen/disto_stage.cxx" + +namespace sfz { +namespace fx { + +struct Disto::Impl { + enum { maxStages = 4 }; + + float _samplePeriod = 1.0 / config::defaultSampleRate; + float _tone = 100.0; + float _depth = 0.0; + float _dry = 0.0; + float _wet = 0.0; + unsigned _numStages = 1; + + float _toneLpfMem[EffectChannels] = {}; + faustDisto _stages[EffectChannels][maxStages]; + + hiir::Upsampler2xFpu<12> _up2x[EffectChannels]; + hiir::Upsampler2xFpu<4> _up4x[EffectChannels]; + hiir::Upsampler2xFpu<3> _up8x[EffectChannels]; + + hiir::Downsampler2xFpu<12> _down2x[EffectChannels]; + hiir::Downsampler2xFpu<4> _down4x[EffectChannels]; + hiir::Downsampler2xFpu<3> _down8x[EffectChannels]; + + std::unique_ptr _temp8x[2]; + + // use the same formula as reverb + float toneCutoff() const noexcept { return 21.0f + _tone * 1.08f; } + + #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() + : _impl(new Impl) +{ + Impl& impl = *_impl; + + for (unsigned c = 0; c < EffectChannels; ++c) { + for (faustDisto& stage : impl._stages[c]) + stage.init(config::defaultSampleRate); + } +} + +Disto::~Disto() +{ +} + +void Disto::setSampleRate(double sampleRate) +{ + Impl& impl = *_impl; + impl._samplePeriod = 1.0 / sampleRate; + + for (unsigned c = 0; c < EffectChannels; ++c) { + for (faustDisto& stage : impl._stages[c]) { + stage.classInit(sampleRate); + stage.instanceConstants(sampleRate); + } + } + + static constexpr double coefs2x[12] = { 0.036681502163648017, 0.13654762463195794, 0.27463175937945444, 0.42313861743656711, 0.56109869787919531, 0.67754004997416184, 0.76974183386322703, 0.83988962484963892, 0.89226081800387902, 0.9315419599631839, 0.96209454837808417, 0.98781637073289585 }; + static constexpr double coefs4x[4] = { 0.042448989488488006, 0.17072114107630679, 0.39329183835224008, 0.74569514831986694 }; + static constexpr double coefs8x[3] = { 0.055748680811302048, 0.24305119574153092, 0.6466991311926823 }; + + for (unsigned c = 0; c < EffectChannels; ++c) { + impl._down2x[c].set_coefs(coefs2x); + impl._down4x[c].set_coefs(coefs4x); + impl._down8x[c].set_coefs(coefs8x); + impl._up2x[c].set_coefs(coefs2x); + impl._up4x[c].set_coefs(coefs4x); + impl._up8x[c].set_coefs(coefs8x); + } +} + +void Disto::setSamplesPerBlock(int samplesPerBlock) +{ + Impl& impl = *_impl; + + for (std::unique_ptr& temp : impl._temp8x) + temp.reset(new float[8 * samplesPerBlock]); +} + +void Disto::clear() +{ + Impl& impl = *_impl; + for (unsigned c = 0; c < EffectChannels; ++c) { + for (faustDisto& stage : impl._stages[c]) + stage.instanceClear(); + } + + for (unsigned c = 0; c < EffectChannels; ++c) { + impl._toneLpfMem[c] = 0.0f; + impl._up2x[c].clear_buffers(); + impl._up4x[c].clear_buffers(); + impl._up8x[c].clear_buffers(); + impl._down2x[c].clear_buffers(); + impl._down4x[c].clear_buffers(); + impl._down8x[c].clear_buffers(); + } +} + +void Disto::process(const float* const inputs[], float* const outputs[], unsigned nframes) +{ + // Note(jpc): assumes `inputs` and `outputs` to be different buffers + + Impl& impl = *_impl; + const float dry = impl._dry; + const float wet = impl._wet; + const float depth = impl._depth; + const float toneLpfPole = std::exp(float(-2.0 * M_PI) * impl.toneCutoff() * impl._samplePeriod); + + for (unsigned c = 0; c < EffectChannels; ++c) { + // compute LPF + absl::Span channelIn(inputs[c], nframes); + absl::Span lpfOut(outputs[c], nframes); + float lpfMem = impl._toneLpfMem[c]; + for (unsigned i = 0; i < nframes; ++i) { + // Note(jpc) apply `dry` gain, note there is no output if + // `dry=0 wet=`, it is the same behavior as reference + lpfMem = channelIn[i] * dry * (1.0f - toneLpfPole) + lpfMem * toneLpfPole; + lpfOut[i] = lpfMem; + } + impl._toneLpfMem[c] = lpfMem; + + // upsample to 8x + absl::Span temp[2] = { + absl::Span(impl._temp8x[0].get(), 8 * nframes), + absl::Span(impl._temp8x[1].get(), 8 * nframes), + }; + impl._up2x[c].process_block(temp[0].data(), lpfOut.data(), nframes); + impl._up4x[c].process_block(temp[1].data(), temp[0].data(), 2 * nframes); + impl._up8x[c].process_block(temp[0].data(), temp[1].data(), 4 * nframes); + absl::Span upsamplerOut = temp[0]; + + // run disto stages + 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); + // + float *faustIn[] = { stageInOut.data() }; + float *faustOut[] = { stageInOut.data() }; + impl._stages[c][s].compute(8 * nframes, faustIn, faustOut); + } + + // downsample to 1x + impl._down8x[c].process_block(temp[1].data(), stageInOut.data(), 4 * nframes); + impl._down4x[c].process_block(temp[0].data(), temp[1].data(), 2 * nframes); + impl._down2x[c].process_block(outputs[c], temp[0].data(), nframes); + + // dry/wet mix + absl::Span mixOut(outputs[c], nframes); + for (unsigned i = 0; i < nframes; ++i) + mixOut[i] = mixOut[i] * wet + channelIn[i] * (1.0f - wet); + } +} + +std::unique_ptr Disto::makeInstance(absl::Span members) +{ + Disto* disto = new Disto; + std::unique_ptr fx { disto }; + + Impl& impl = *disto->_impl; + + for (const Opcode& opc : members) { + switch (opc.lettersOnlyHash) { + case hash("disto_tone"): + setValueFromOpcode(opc, impl._tone, {0.0f, 100.0f}); + break; + case hash("disto_depth"): + setValueFromOpcode(opc, impl._depth, {0.0f, 100.0f}); + break; + case hash("disto_stages"): + setValueFromOpcode(opc, impl._numStages, {1, Impl::maxStages}); + break; + case hash("disto_dry"): + if (auto value = readOpcode(opc.value, {0.0f, 100.0f})) + impl._dry = *value * 0.01f; + break; + case hash("disto_wet"): + if (auto value = readOpcode(opc.value, {0.0f, 100.0f})) + impl._wet = *value * 0.01f; + break; + } + } + + return fx; +} + +} // namespace sfz +} // namespace fx diff --git a/src/sfizz/effects/Disto.h b/src/sfizz/effects/Disto.h new file mode 100644 index 00000000..d9cc1ac7 --- /dev/null +++ b/src/sfizz/effects/Disto.h @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: BSD-2-Clause + +// This code is part of the sfizz library and is licensed under a BSD 2-clause +// license. You should have receive a LICENSE.md file along with the code. +// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz + +#pragma once +#include "Effects.h" +#include + +namespace sfz { +namespace fx { + + /** + * @brief Distortion effect + */ + class Disto : public Effect { + public: + Disto(); + ~Disto(); + + /** + * @brief Initializes with the given sample rate. + */ + void setSampleRate(double sampleRate) override; + + /** + * @brief Sets the maximum number of frames to render at a time. The actual + * value can be lower but should never be higher. + */ + void setSamplesPerBlock(int samplesPerBlock) override; + + /** + * @brief Reset the state to initial. + */ + void clear() override; + + /** + * @brief Copy the input signal to the output + */ + void process(const float* const inputs[], float* const outputs[], unsigned nframes) override; + + /** + * @brief Instantiates given the contents of the block. + */ + static std::unique_ptr makeInstance(absl::Span members); + + private: + struct Impl; + std::unique_ptr _impl; + }; + +} // namespace fx +} // namespace sfz diff --git a/src/sfizz/effects/dsp/disto_stage.dsp b/src/sfizz/effects/dsp/disto_stage.dsp new file mode 100644 index 00000000..f05a54fa --- /dev/null +++ b/src/sfizz/effects/dsp/disto_stage.dsp @@ -0,0 +1,40 @@ +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)); + + // the low and high hysteresis + lh(x) = sig(a*x)*b; + hh(x) = (sig(a*x)-1.0)*b; + + // + sig10 = environment { // sigmoid sampled from -10 to +10 + tablesize = 256; + table(i) = rdtable(tablesize, exact(float(ba.time)/float(tablesize)*20.0-10.0), i); + exact(x) = exp(x)/(exp(x)+1.0); + approx(x) = s1+mu*(s2-s1) with { + index = (x+10.0)*(1.0/20.0)*(sig10.tablesize-1) : max(0.0); + mu = index-int(index); + s1 = sig10.table(int(index) : min(sig10.tablesize-1)); + s2 = sig10.table(int(index) : +(1) : min(sig10.tablesize-1)); + }; + }; + + //sig = sig10.exact; + sig = sig10.approx; +} +letrec { + // hysteresis selection + 'hs = ba.if((xx') & (x>0.25), 0, hs)); +}; + +process = disto_stage(d) with { + d = hslider("[1] Depth", 100.0, 0.0, 100.0, 0.01); +}; diff --git a/src/sfizz/effects/gen/disto_stage.cxx b/src/sfizz/effects/gen/disto_stage.cxx new file mode 100644 index 00000000..7353b7ed --- /dev/null +++ b/src/sfizz/effects/gen/disto_stage.cxx @@ -0,0 +1,248 @@ +/* ------------------------------------------------------------ +name: "disto_stage" +Code generated with Faust 2.27.2 (https://faust.grame.fr) +Compilation options: -lang cpp -inpl -scal -ftz 0 +------------------------------------------------------------ */ + +#ifndef __faustDisto_H__ +#define __faustDisto_H__ + +#ifndef FAUSTFLOAT +#define FAUSTFLOAT float +#endif + +#include +#include +#include + +class faustDistoSIG0 { + + public: + + int iRec3[2]; + + public: + + int getNumInputsfaustDistoSIG0() { + return 0; + } + int getNumOutputsfaustDistoSIG0() { + return 1; + } + int getInputRatefaustDistoSIG0(int channel) { + int rate; + switch ((channel)) { + default: { + rate = -1; + break; + } + } + return rate; + } + int getOutputRatefaustDistoSIG0(int channel) { + int rate; + switch ((channel)) { + case 0: { + rate = 0; + break; + } + default: { + rate = -1; + break; + } + } + return rate; + } + + void instanceInitfaustDistoSIG0(int sample_rate) { + for (int l3 = 0; (l3 < 2); l3 = (l3 + 1)) { + iRec3[l3] = 0; + } + } + + void fillfaustDistoSIG0(int count, float* table) { + for (int i = 0; (i < count); i = (i + 1)) { + iRec3[0] = (iRec3[1] + 1); + float fTemp1 = std::exp(((0.078125f * float((iRec3[0] + -1))) + -10.0f)); + table[i] = (fTemp1 / (fTemp1 + 1.0f)); + iRec3[1] = iRec3[0]; + } + } + +}; + +static faustDistoSIG0* newfaustDistoSIG0() { return (faustDistoSIG0*)new faustDistoSIG0(); } +static void deletefaustDistoSIG0(faustDistoSIG0* dsp) { delete dsp; } + +static float ftbl0faustDistoSIG0[256]; + +#ifndef FAUSTCLASS +#define FAUSTCLASS faustDisto +#endif + +#ifdef __APPLE__ +#define exp10f __exp10f +#define exp10 __exp10 +#endif + +class faustDisto { + + public: + + float fVec0[2]; + int fSampleRate; + float fConst0; + float fConst1; + float fConst2; + float fConst3; + float fConst4; + int iConst5; + float fConst6; + int iRec2[2]; + float fConst7; + float fRec1[2]; + FAUSTFLOAT fHslider0; + float fVec1[2]; + float fRec0[2]; + + public: + + void metadata() { + } + + int getNumInputs() { + return 1; + } + int getNumOutputs() { + return 1; + } + int getInputRate(int channel) { + int rate; + switch ((channel)) { + case 0: { + rate = 1; + break; + } + default: { + rate = -1; + break; + } + } + return rate; + } + int getOutputRate(int channel) { + int rate; + switch ((channel)) { + case 0: { + rate = 1; + break; + } + default: { + rate = -1; + break; + } + } + return rate; + } + + static void classInit(int sample_rate) { + faustDistoSIG0* sig0 = newfaustDistoSIG0(); + sig0->instanceInitfaustDistoSIG0(sample_rate); + sig0->fillfaustDistoSIG0(256, ftbl0faustDistoSIG0); + deletefaustDistoSIG0(sig0); + } + + void instanceConstants(int sample_rate) { + fSampleRate = sample_rate; + fConst0 = std::min(192000.0f, std::max(1.0f, float(fSampleRate))); + fConst1 = (15.707963f / fConst0); + fConst2 = (1.0f / (fConst1 + 1.0f)); + fConst3 = (1.0f - fConst1); + fConst4 = (0.00999999978f * float(_oversampling)); + iConst5 = (std::fabs(fConst4) < 1.1920929e-07f); + fConst6 = (iConst5 ? 0.0f : std::exp((0.0f - ((1.0f / fConst0) / (iConst5 ? 1.0f : fConst4))))); + fConst7 = (1.0f - fConst6); + } + + void instanceResetUserInterface() { + fHslider0 = FAUSTFLOAT(100.0f); + } + + void instanceClear() { + for (int l0 = 0; (l0 < 2); l0 = (l0 + 1)) { + fVec0[l0] = 0.0f; + } + for (int l1 = 0; (l1 < 2); l1 = (l1 + 1)) { + iRec2[l1] = 0; + } + for (int l2 = 0; (l2 < 2); l2 = (l2 + 1)) { + fRec1[l2] = 0.0f; + } + for (int l4 = 0; (l4 < 2); l4 = (l4 + 1)) { + fVec1[l4] = 0.0f; + } + for (int l5 = 0; (l5 < 2); l5 = (l5 + 1)) { + fRec0[l5] = 0.0f; + } + } + + void init(int sample_rate) { + classInit(sample_rate); + instanceInit(sample_rate); + } + void instanceInit(int sample_rate) { + instanceConstants(sample_rate); + instanceResetUserInterface(); + instanceClear(); + } + + faustDisto* clone() { + return new faustDisto(); + } + + int getSampleRate() { + return fSampleRate; + } + + void buildUserInterface() { + } + + void compute(int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) { + FAUSTFLOAT* input0 = inputs[0]; + FAUSTFLOAT* output0 = outputs[0]; + float fSlow0 = ((0.200000003f * float(fHslider0)) + 2.0f); + for (int i = 0; (i < count); i = (i + 1)) { + float fTemp0 = float(input0[i]); + fVec0[0] = fTemp0; + iRec2[0] = (((fTemp0 < fVec0[1]) & (fTemp0 < -0.25f)) ? 1 : (((fTemp0 > fVec0[1]) & (fTemp0 > 0.25f)) ? 0 : iRec2[1])); + fRec1[0] = ((fRec1[1] * fConst6) + (float(iRec2[0]) * fConst7)); + float fTemp2 = std::max(0.0f, (12.75f * ((fSlow0 * fTemp0) + 10.0f))); + int iTemp3 = int(fTemp2); + float fTemp4 = ftbl0faustDistoSIG0[std::min(255, iTemp3)]; + float fTemp5 = (fTemp4 + ((fTemp2 - float(iTemp3)) * (ftbl0faustDistoSIG0[std::min(255, (iTemp3 + 1))] - fTemp4))); + float fTemp6 = ((fRec1[0] * (fTemp5 + -1.0f)) + ((1.0f - fRec1[0]) * fTemp5)); + fVec1[0] = fTemp6; + fRec0[0] = (fConst2 * ((fConst3 * fRec0[1]) + (2.0f * (fTemp6 - fVec1[1])))); + output0[i] = FAUSTFLOAT(fRec0[0]); + fVec0[1] = fVec0[0]; + iRec2[1] = iRec2[0]; + fRec1[1] = fRec1[0]; + fVec1[1] = fVec1[0]; + fRec0[1] = fRec0[0]; + } + } + +}; + +#ifdef FAUST_UIMACROS + + + + #define FAUST_LIST_ACTIVES(p) \ + p(HORIZONTALSLIDER, Depth, "Depth", fHslider0, 100.0f, 0.0f, 100.0f, 0.01f) \ + + #define FAUST_LIST_PASSIVES(p) \ + +#endif + +#endif