Add the distortion
This commit is contained in:
parent
d85a53f40c
commit
b56821db00
8 changed files with 629 additions and 1 deletions
1
dpf.mk
1
dpf.mk
|
|
@ -61,6 +61,7 @@ SFIZZ_SOURCES = \
|
||||||
src/sfizz/effects/Apan.cpp \
|
src/sfizz/effects/Apan.cpp \
|
||||||
src/sfizz/Effects.cpp \
|
src/sfizz/Effects.cpp \
|
||||||
src/sfizz/effects/Compressor.cpp \
|
src/sfizz/effects/Compressor.cpp \
|
||||||
|
src/sfizz/effects/Disto.cpp \
|
||||||
src/sfizz/effects/Eq.cpp \
|
src/sfizz/effects/Eq.cpp \
|
||||||
src/sfizz/effects/Filter.cpp \
|
src/sfizz/effects/Filter.cpp \
|
||||||
src/sfizz/effects/Gain.cpp \
|
src/sfizz/effects/Gain.cpp \
|
||||||
|
|
|
||||||
54
scripts/generate_disto.sh
Executable file
54
scripts/generate_disto.sh
Executable file
|
|
@ -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
|
||||||
|
|
@ -11,7 +11,8 @@ set (FAUST_FILES
|
||||||
sfizz/effects/dsp/limiter.dsp
|
sfizz/effects/dsp/limiter.dsp
|
||||||
sfizz/effects/dsp/resonant_string.dsp
|
sfizz/effects/dsp/resonant_string.dsp
|
||||||
sfizz/effects/dsp/compressor.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})
|
source_group ("Faust Files" FILES ${FAUST_FILES})
|
||||||
|
|
||||||
set (SFIZZ_HEADERS
|
set (SFIZZ_HEADERS
|
||||||
|
|
@ -35,6 +36,7 @@ set (SFIZZ_HEADERS
|
||||||
sfizz/effects/CommonLFO.h
|
sfizz/effects/CommonLFO.h
|
||||||
sfizz/effects/CommonLFO.hpp
|
sfizz/effects/CommonLFO.hpp
|
||||||
sfizz/effects/Compressor.h
|
sfizz/effects/Compressor.h
|
||||||
|
sfizz/effects/Disto.h
|
||||||
sfizz/effects/Eq.h
|
sfizz/effects/Eq.h
|
||||||
sfizz/effects/Filter.h
|
sfizz/effects/Filter.h
|
||||||
sfizz/effects/Gain.h
|
sfizz/effects/Gain.h
|
||||||
|
|
@ -130,6 +132,7 @@ set (SFIZZ_SOURCES
|
||||||
sfizz/effects/Limiter.cpp
|
sfizz/effects/Limiter.cpp
|
||||||
sfizz/effects/Compressor.cpp
|
sfizz/effects/Compressor.cpp
|
||||||
sfizz/effects/Gate.cpp
|
sfizz/effects/Gate.cpp
|
||||||
|
sfizz/effects/Disto.cpp
|
||||||
sfizz/effects/Strings.cpp
|
sfizz/effects/Strings.cpp
|
||||||
sfizz/effects/Rectify.cpp
|
sfizz/effects/Rectify.cpp
|
||||||
sfizz/effects/Gain.cpp
|
sfizz/effects/Gain.cpp
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
#include "effects/Limiter.h"
|
#include "effects/Limiter.h"
|
||||||
#include "effects/Compressor.h"
|
#include "effects/Compressor.h"
|
||||||
#include "effects/Gate.h"
|
#include "effects/Gate.h"
|
||||||
|
#include "effects/Disto.h"
|
||||||
#include "effects/Strings.h"
|
#include "effects/Strings.h"
|
||||||
#include "effects/Rectify.h"
|
#include "effects/Rectify.h"
|
||||||
#include "effects/Gain.h"
|
#include "effects/Gain.h"
|
||||||
|
|
@ -35,6 +36,7 @@ void EffectFactory::registerStandardEffectTypes()
|
||||||
registerEffectType("limiter", fx::Limiter::makeInstance);
|
registerEffectType("limiter", fx::Limiter::makeInstance);
|
||||||
registerEffectType("comp", fx::Compressor::makeInstance);
|
registerEffectType("comp", fx::Compressor::makeInstance);
|
||||||
registerEffectType("gate", fx::Gate::makeInstance);
|
registerEffectType("gate", fx::Gate::makeInstance);
|
||||||
|
registerEffectType("disto", fx::Disto::makeInstance);
|
||||||
registerEffectType("strings", fx::Strings::makeInstance);
|
registerEffectType("strings", fx::Strings::makeInstance);
|
||||||
|
|
||||||
// extensions (book)
|
// extensions (book)
|
||||||
|
|
|
||||||
226
src/sfizz/effects/Disto.cpp
Normal file
226
src/sfizz/effects/Disto.cpp
Normal file
|
|
@ -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 <hiir/Upsampler2xFpu.h>
|
||||||
|
#include <hiir/Downsampler2xFpu.h>
|
||||||
|
#include <absl/types/span.h>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
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<float[]> _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<float[]>& 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<const float> channelIn(inputs[c], nframes);
|
||||||
|
absl::Span<float> 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=<any>`, 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<float> temp[2] = {
|
||||||
|
absl::Span<float>(impl._temp8x[0].get(), 8 * nframes),
|
||||||
|
absl::Span<float>(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<float> upsamplerOut = temp[0];
|
||||||
|
|
||||||
|
// run disto stages
|
||||||
|
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);
|
||||||
|
//
|
||||||
|
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<float> mixOut(outputs[c], nframes);
|
||||||
|
for (unsigned i = 0; i < nframes; ++i)
|
||||||
|
mixOut[i] = mixOut[i] * wet + channelIn[i] * (1.0f - wet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<Effect> Disto::makeInstance(absl::Span<const Opcode> members)
|
||||||
|
{
|
||||||
|
Disto* disto = new Disto;
|
||||||
|
std::unique_ptr<Effect> 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<float>(opc.value, {0.0f, 100.0f}))
|
||||||
|
impl._dry = *value * 0.01f;
|
||||||
|
break;
|
||||||
|
case hash("disto_wet"):
|
||||||
|
if (auto value = readOpcode<float>(opc.value, {0.0f, 100.0f}))
|
||||||
|
impl._wet = *value * 0.01f;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fx;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace sfz
|
||||||
|
} // namespace fx
|
||||||
54
src/sfizz/effects/Disto.h
Normal file
54
src/sfizz/effects/Disto.h
Normal file
|
|
@ -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 <memory>
|
||||||
|
|
||||||
|
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 <effect> block.
|
||||||
|
*/
|
||||||
|
static std::unique_ptr<Effect> makeInstance(absl::Span<const Opcode> members);
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct Impl;
|
||||||
|
std::unique_ptr<Impl> _impl;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace fx
|
||||||
|
} // namespace sfz
|
||||||
40
src/sfizz/effects/dsp/disto_stage.dsp
Normal file
40
src/sfizz/effects/dsp/disto_stage.dsp
Normal file
|
|
@ -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, <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));
|
||||||
|
|
||||||
|
// 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((x<x') & (x<-0.25), 1, ba.if((x>x') & (x>0.25), 0, hs));
|
||||||
|
};
|
||||||
|
|
||||||
|
process = disto_stage(d) with {
|
||||||
|
d = hslider("[1] Depth", 100.0, 0.0, 100.0, 0.01);
|
||||||
|
};
|
||||||
248
src/sfizz/effects/gen/disto_stage.cxx
Normal file
248
src/sfizz/effects/gen/disto_stage.cxx
Normal file
|
|
@ -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 <algorithm>
|
||||||
|
#include <cmath>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
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<float>(192000.0f, std::max<float>(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<float>(0.0f, (12.75f * ((fSlow0 * fTemp0) + 10.0f)));
|
||||||
|
int iTemp3 = int(fTemp2);
|
||||||
|
float fTemp4 = ftbl0faustDistoSIG0[std::min<int>(255, iTemp3)];
|
||||||
|
float fTemp5 = (fTemp4 + ((fTemp2 - float(iTemp3)) * (ftbl0faustDistoSIG0[std::min<int>(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
|
||||||
Loading…
Add table
Reference in a new issue