Merge pull request #131 from jpcima/new-effects
Add effects: limiter, rectifier, gain, width
This commit is contained in:
commit
77acae7992
12 changed files with 720 additions and 0 deletions
|
|
@ -24,6 +24,10 @@ set (SFIZZ_SOURCES
|
|||
sfizz/effects/Eq.cpp
|
||||
sfizz/effects/Apan.cpp
|
||||
sfizz/effects/Lofi.cpp
|
||||
sfizz/effects/Limiter.cpp
|
||||
sfizz/effects/Rectify.cpp
|
||||
sfizz/effects/Gain.cpp
|
||||
sfizz/effects/Width.cpp
|
||||
)
|
||||
include (SfizzSIMDSourceFiles)
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,10 @@
|
|||
#include "effects/Eq.h"
|
||||
#include "effects/Apan.h"
|
||||
#include "effects/Lofi.h"
|
||||
#include "effects/Limiter.h"
|
||||
#include "effects/Rectify.h"
|
||||
#include "effects/Gain.h"
|
||||
#include "effects/Width.h"
|
||||
#include <algorithm>
|
||||
|
||||
namespace sfz {
|
||||
|
|
@ -25,6 +29,12 @@ void EffectFactory::registerStandardEffectTypes()
|
|||
registerEffectType("eq", fx::Eq::makeInstance);
|
||||
registerEffectType("apan", fx::Apan::makeInstance);
|
||||
registerEffectType("lofi", fx::Lofi::makeInstance);
|
||||
registerEffectType("limiter", fx::Limiter::makeInstance);
|
||||
|
||||
// extensions (book)
|
||||
registerEffectType("rectify", fx::Rectify::makeInstance);
|
||||
registerEffectType("gain", fx::Gain::makeInstance);
|
||||
registerEffectType("width", fx::Width::makeInstance);
|
||||
}
|
||||
|
||||
void EffectFactory::registerEffectType(absl::string_view name, Effect::MakeInstance& make)
|
||||
|
|
|
|||
73
src/sfizz/effects/Gain.cpp
Normal file
73
src/sfizz/effects/Gain.cpp
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
// 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): this effect is book-only, mentioned but not documented
|
||||
|
||||
Note(jpc): implementation status
|
||||
|
||||
- [x] gain
|
||||
- [ ] gain_oncc
|
||||
*/
|
||||
|
||||
#include "Gain.h"
|
||||
#include "Opcode.h"
|
||||
#include "SIMDHelpers.h"
|
||||
#include "absl/memory/memory.h"
|
||||
|
||||
namespace sfz {
|
||||
namespace fx {
|
||||
|
||||
void Gain::setSampleRate(double sampleRate)
|
||||
{
|
||||
(void)sampleRate;
|
||||
}
|
||||
|
||||
void Gain::setSamplesPerBlock(int samplesPerBlock)
|
||||
{
|
||||
_tempBuffer.resize(samplesPerBlock);
|
||||
}
|
||||
|
||||
void Gain::clear()
|
||||
{
|
||||
}
|
||||
|
||||
void Gain::process(const float* const inputs[], float* const outputs[], unsigned nframes)
|
||||
{
|
||||
const float baseGain = _gain;
|
||||
|
||||
absl::Span<float> gains = _tempBuffer.getSpan(0);
|
||||
std::fill(gains.begin(), gains.end(), baseGain);
|
||||
|
||||
// to linear
|
||||
for (unsigned i = 0; i < nframes; ++i)
|
||||
gains[i] = std::pow(10.0f, 0.05f * gains[i]);
|
||||
|
||||
for (unsigned c = 0; c < EffectChannels; ++c) {
|
||||
absl::Span<const float> input { inputs[c], nframes };
|
||||
absl::Span<float> output { outputs[c], nframes };
|
||||
sfz::applyGain(absl::Span<const float> { gains }, input, output);
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<Effect> Gain::makeInstance(absl::Span<const Opcode> members)
|
||||
{
|
||||
auto fx = absl::make_unique<Gain>();
|
||||
|
||||
for (const Opcode& opc : members) {
|
||||
switch (opc.lettersOnlyHash) {
|
||||
case hash("gain"):
|
||||
setValueFromOpcode(opc, fx->_gain, {-96.0f, 96.0f});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return CXX11_MOVE(fx);
|
||||
}
|
||||
|
||||
} // namespace fx
|
||||
} // namespace sfz
|
||||
50
src/sfizz/effects/Gain.h
Normal file
50
src/sfizz/effects/Gain.h
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
// 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"
|
||||
|
||||
namespace sfz {
|
||||
namespace fx {
|
||||
|
||||
/**
|
||||
* @brief Gain effect
|
||||
*/
|
||||
class Gain : public Effect {
|
||||
public:
|
||||
/**
|
||||
* @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:
|
||||
float _gain = 0; // in dB
|
||||
AudioBuffer<float, 1> _tempBuffer { 1, config::defaultSamplesPerBlock };
|
||||
};
|
||||
|
||||
} // namespace fx
|
||||
} // namespace sfz
|
||||
85
src/sfizz/effects/Limiter.cpp
Normal file
85
src/sfizz/effects/Limiter.cpp
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
// 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
|
||||
|
||||
Complete (no opcodes)
|
||||
*/
|
||||
|
||||
#include "Limiter.h"
|
||||
#include "Opcode.h"
|
||||
#include "AudioSpan.h"
|
||||
#include "absl/memory/memory.h"
|
||||
|
||||
static constexpr int _oversampling = 2;
|
||||
#include "gen/limiter.cpp"
|
||||
|
||||
namespace sfz {
|
||||
namespace fx {
|
||||
|
||||
Limiter::Limiter()
|
||||
: _limiter(new faustLimiter)
|
||||
{
|
||||
_limiter->instanceResetUserInterface();
|
||||
}
|
||||
|
||||
Limiter::~Limiter()
|
||||
{
|
||||
}
|
||||
|
||||
void Limiter::setSampleRate(double sampleRate)
|
||||
{
|
||||
_limiter->classInit(sampleRate);
|
||||
_limiter->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 };
|
||||
|
||||
for (unsigned c = 0; c < EffectChannels; ++c) {
|
||||
_downsampler2x[c].set_coefs(coefs2x);
|
||||
_upsampler2x[c].set_coefs(coefs2x);
|
||||
}
|
||||
|
||||
clear();
|
||||
}
|
||||
|
||||
void Limiter::setSamplesPerBlock(int samplesPerBlock)
|
||||
{
|
||||
_tempBuffer2x.resize(2 * samplesPerBlock);
|
||||
}
|
||||
|
||||
void Limiter::clear()
|
||||
{
|
||||
_limiter->instanceClear();
|
||||
}
|
||||
|
||||
void Limiter::process(const float* const inputs[], float* const outputs[], unsigned nframes)
|
||||
{
|
||||
auto inOut2x = AudioSpan<float>( _tempBuffer2x).first(2 * nframes);
|
||||
|
||||
for (unsigned c = 0; c < EffectChannels; ++c)
|
||||
_upsampler2x[c].process_block(inOut2x.getSpan(c).data(), inputs[c], nframes);
|
||||
|
||||
_limiter->compute(2 * nframes, inOut2x, inOut2x);
|
||||
|
||||
for (unsigned c = 0; c < EffectChannels; ++c)
|
||||
_downsampler2x[c].process_block(outputs[c], inOut2x.getSpan(c).data(), nframes);
|
||||
}
|
||||
|
||||
std::unique_ptr<Effect> Limiter::makeInstance(absl::Span<const Opcode> members)
|
||||
{
|
||||
auto fx = absl::make_unique<Limiter>();
|
||||
|
||||
for (const Opcode& opc : members) {
|
||||
// no opcodes
|
||||
(void)opc;
|
||||
}
|
||||
|
||||
return CXX11_MOVE(fx);
|
||||
}
|
||||
|
||||
} // namespace fx
|
||||
} // namespace sfz
|
||||
58
src/sfizz/effects/Limiter.h
Normal file
58
src/sfizz/effects/Limiter.h
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
// 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 "hiir/Downsampler2xFpu.h"
|
||||
#include "hiir/Upsampler2xFpu.h"
|
||||
class faustLimiter;
|
||||
|
||||
namespace sfz {
|
||||
namespace fx {
|
||||
|
||||
/**
|
||||
* @brief Limiter effect
|
||||
*/
|
||||
class Limiter : public Effect {
|
||||
public:
|
||||
Limiter();
|
||||
~Limiter();
|
||||
|
||||
/**
|
||||
* @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 Computes a cycle of the effect in stereo.
|
||||
*/
|
||||
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:
|
||||
std::unique_ptr<faustLimiter> _limiter;
|
||||
AudioBuffer<float, 2> _tempBuffer2x { 2, 2 * config::defaultSamplesPerBlock };
|
||||
hiir::Downsampler2xFpu<12> _downsampler2x[EffectChannels];
|
||||
hiir::Upsampler2xFpu<12> _upsampler2x[EffectChannels];
|
||||
};
|
||||
|
||||
} // namespace fx
|
||||
} // namespace sfz
|
||||
106
src/sfizz/effects/Rectify.cpp
Normal file
106
src/sfizz/effects/Rectify.cpp
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
// 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): this effect is book-only, mentioned but not documented
|
||||
|
||||
Note(jpc): implementation status
|
||||
|
||||
- [x] rectify_mode
|
||||
- [x] rectify
|
||||
- [ ] rectify_oncc
|
||||
*/
|
||||
|
||||
#include "Rectify.h"
|
||||
#include "Opcode.h"
|
||||
|
||||
namespace sfz {
|
||||
namespace fx {
|
||||
|
||||
Rectify::Rectify()
|
||||
{
|
||||
}
|
||||
|
||||
void Rectify::setSampleRate(double sampleRate)
|
||||
{
|
||||
(void)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 };
|
||||
|
||||
for (unsigned c = 0; c < EffectChannels; ++c) {
|
||||
_downsampler2x[c].set_coefs(coefs2x);
|
||||
_upsampler2x[c].set_coefs(coefs2x);
|
||||
}
|
||||
}
|
||||
|
||||
void Rectify::setSamplesPerBlock(int samplesPerBlock)
|
||||
{
|
||||
_tempBuffer.resize(samplesPerBlock);
|
||||
}
|
||||
|
||||
void Rectify::clear()
|
||||
{
|
||||
for (unsigned c = 0; c < EffectChannels; ++c) {
|
||||
_downsampler2x[c].clear_buffers();
|
||||
_upsampler2x[c].clear_buffers();
|
||||
}
|
||||
}
|
||||
|
||||
void Rectify::process(const float* const inputs[], float* const outputs[], unsigned nframes)
|
||||
{
|
||||
// Note(jpc) I define opcode `rectify` to be a mix amount.
|
||||
// half-wave rectification is achieved simply by halving it.
|
||||
const float baseAmount = _amount * (_full ? 1.0f : 0.5f);
|
||||
|
||||
absl::Span<float> amounts = _tempBuffer.getSpan(0);
|
||||
std::fill(amounts.begin(), amounts.end(), baseAmount);
|
||||
|
||||
for (unsigned c = 0; c < EffectChannels; ++c) {
|
||||
const float *input = inputs[c];
|
||||
float *output = outputs[c];
|
||||
|
||||
auto &up2x = _upsampler2x[c];
|
||||
auto &down2x = _downsampler2x[c];
|
||||
|
||||
for (unsigned i = 0; i < nframes; ++i) {
|
||||
const float amount = normalizePercents(amounts[i]);
|
||||
float in = input[i];
|
||||
|
||||
float in2x[2];
|
||||
up2x.process_sample(in2x[0], in2x[1], in);
|
||||
|
||||
float out2x[2];
|
||||
out2x[0] = amount * std::fabs(in2x[0]) + (1.0f - amount) * in2x[0];
|
||||
out2x[1] = amount * std::fabs(in2x[1]) + (1.0f - amount) * in2x[1];
|
||||
|
||||
output[i] = down2x.process_sample(out2x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<Effect> Rectify::makeInstance(absl::Span<const Opcode> members)
|
||||
{
|
||||
auto fx = absl::make_unique<Rectify>();
|
||||
|
||||
for (const Opcode& opc : members) {
|
||||
switch (opc.lettersOnlyHash) {
|
||||
case hash("rectify_mode"):
|
||||
if (opc.value == "full")
|
||||
fx->_full = true;
|
||||
else if (opc.value == "half")
|
||||
fx->_full = false;
|
||||
break;
|
||||
case hash("rectify"):
|
||||
setValueFromOpcode(opc, fx->_amount, { 0.0, 100.0 });
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return CXX11_MOVE(fx);
|
||||
}
|
||||
|
||||
} // namespace fx
|
||||
} // namespace sfz
|
||||
58
src/sfizz/effects/Rectify.h
Normal file
58
src/sfizz/effects/Rectify.h
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
// 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 "hiir/Downsampler2xFpu.h"
|
||||
#include "hiir/Upsampler2xFpu.h"
|
||||
|
||||
namespace sfz {
|
||||
namespace fx {
|
||||
|
||||
/**
|
||||
* @brief Half-wave and full-wave rectifier
|
||||
*/
|
||||
class Rectify : public Effect {
|
||||
public:
|
||||
Rectify();
|
||||
|
||||
/**
|
||||
* @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:
|
||||
AudioBuffer<float, 1> _tempBuffer { 1, config::defaultSamplesPerBlock };
|
||||
hiir::Downsampler2xFpu<12> _downsampler2x[2];
|
||||
hiir::Upsampler2xFpu<12> _upsampler2x[2];
|
||||
|
||||
float _amount = 0;
|
||||
bool _full = false;
|
||||
};
|
||||
|
||||
} // namespace fx
|
||||
} // namespace sfz
|
||||
80
src/sfizz/effects/Width.cpp
Normal file
80
src/sfizz/effects/Width.cpp
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
// 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): this effect is book-only, mentioned but not documented
|
||||
|
||||
Note(jpc): implementation status
|
||||
|
||||
- [x] width
|
||||
- [ ] width_oncc
|
||||
*/
|
||||
|
||||
#include "Width.h"
|
||||
#include "Opcode.h"
|
||||
#include "SIMDHelpers.h"
|
||||
#include "absl/memory/memory.h"
|
||||
|
||||
namespace sfz {
|
||||
namespace fx {
|
||||
|
||||
void Width::setSampleRate(double sampleRate)
|
||||
{
|
||||
(void)sampleRate;
|
||||
}
|
||||
|
||||
void Width::setSamplesPerBlock(int samplesPerBlock)
|
||||
{
|
||||
_tempBuffer.resize(samplesPerBlock);
|
||||
}
|
||||
|
||||
void Width::clear()
|
||||
{
|
||||
}
|
||||
|
||||
void Width::process(const float* const inputs[], float* const outputs[], unsigned nframes)
|
||||
{
|
||||
const float baseWidth = _width;
|
||||
|
||||
absl::Span<float> widths = _tempBuffer.getSpan(0);
|
||||
std::fill(widths.begin(), widths.end(), baseWidth);
|
||||
|
||||
absl::Span<const float> input1 { inputs[0], nframes };
|
||||
absl::Span<const float> input2 { inputs[1], nframes };
|
||||
absl::Span<float> output1 { outputs[0], nframes };
|
||||
absl::Span<float> output2 { outputs[1], nframes };
|
||||
|
||||
for (unsigned i = 0; i < nframes; ++i) {
|
||||
const float l = input1[i];
|
||||
const float r = input2[i];
|
||||
|
||||
const float w = clamp((widths[i] + 100.0f) * 0.005f, 0.0f, 1.0f);
|
||||
const float coeff1 = _internals::panLookup(w);
|
||||
const float coeff2 = _internals::panLookup(1.0f - w);
|
||||
|
||||
output1[i] = l * coeff2 + r * coeff1;
|
||||
output2[i] = l * coeff1 + r * coeff2;
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<Effect> Width::makeInstance(absl::Span<const Opcode> members)
|
||||
{
|
||||
auto fx = absl::make_unique<Width>();
|
||||
|
||||
for (const Opcode& opc : members) {
|
||||
switch (opc.lettersOnlyHash) {
|
||||
case hash("width"):
|
||||
setValueFromOpcode(opc, fx->_width, {-100.0f, 100.0f});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return CXX11_MOVE(fx);
|
||||
}
|
||||
|
||||
} // namespace fx
|
||||
} // namespace sfz
|
||||
50
src/sfizz/effects/Width.h
Normal file
50
src/sfizz/effects/Width.h
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
// 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"
|
||||
|
||||
namespace sfz {
|
||||
namespace fx {
|
||||
|
||||
/**
|
||||
* @brief Stereo width effect
|
||||
*/
|
||||
class Width : public Effect {
|
||||
public:
|
||||
/**
|
||||
* @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:
|
||||
float _width = 100;
|
||||
AudioBuffer<float, 1> _tempBuffer { 1, config::defaultSamplesPerBlock };
|
||||
};
|
||||
|
||||
} // namespace fx
|
||||
} // namespace sfz
|
||||
11
src/sfizz/effects/dsp/limiter.dsp
Normal file
11
src/sfizz/effects/dsp/limiter.dsp
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
import("stdfaust.lib");
|
||||
|
||||
limiter(x) = gain*x with {
|
||||
att = 0.0008 * over;
|
||||
rel = 0.5 * over;
|
||||
over = fconstant(int _oversampling, <math.h>);
|
||||
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));
|
||||
};
|
||||
|
||||
process = limiter, limiter;
|
||||
135
src/sfizz/effects/gen/limiter.cpp
Normal file
135
src/sfizz/effects/gen/limiter.cpp
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
/* ------------------------------------------------------------
|
||||
name: "limiter"
|
||||
Code generated with Faust 2.20.2 (https://faust.grame.fr)
|
||||
Compilation options: -lang cpp -inpl -scal -ftz 0
|
||||
------------------------------------------------------------ */
|
||||
|
||||
#ifndef __faustLimiter_H__
|
||||
#define __faustLimiter_H__
|
||||
|
||||
#ifndef FAUSTFLOAT
|
||||
#define FAUSTFLOAT float
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <math.h>
|
||||
|
||||
#ifndef FAUSTCLASS
|
||||
#define FAUSTCLASS faustLimiter
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
#define exp10f __exp10f
|
||||
#define exp10 __exp10
|
||||
#endif
|
||||
|
||||
class faustLimiter {
|
||||
|
||||
private:
|
||||
int fSampleRate;
|
||||
float fConst0;
|
||||
float fConst1;
|
||||
float fConst2;
|
||||
float fConst3;
|
||||
float fConst4;
|
||||
float fConst5;
|
||||
float fConst6;
|
||||
float fRec2[2];
|
||||
float fRec1[2];
|
||||
float fRec0[2];
|
||||
float fRec5[2];
|
||||
float fRec4[2];
|
||||
float fRec3[2];
|
||||
|
||||
public:
|
||||
static void classInit(int sample_rate)
|
||||
{
|
||||
(void)sample_rate;
|
||||
}
|
||||
|
||||
void instanceConstants(int sample_rate)
|
||||
{
|
||||
fSampleRate = sample_rate;
|
||||
fConst0 = (std::min<float>(192000.0f, std::max<float>(1.0f, float(fSampleRate))) * float(_oversampling));
|
||||
fConst1 = std::exp((0.0f - (2500.0f / fConst0)));
|
||||
fConst2 = (1.0f - fConst1);
|
||||
fConst3 = std::exp((0.0f - (1250.0f / fConst0)));
|
||||
fConst4 = (1.0f - fConst3);
|
||||
fConst5 = std::exp((0.0f - (2.0f / fConst0)));
|
||||
fConst6 = (1.0f - fConst5);
|
||||
}
|
||||
|
||||
void instanceResetUserInterface()
|
||||
{
|
||||
}
|
||||
|
||||
void instanceClear()
|
||||
{
|
||||
for (int l0 = 0; (l0 < 2); l0 = (l0 + 1)) {
|
||||
fRec2[l0] = 0.0f;
|
||||
}
|
||||
for (int l1 = 0; (l1 < 2); l1 = (l1 + 1)) {
|
||||
fRec1[l1] = 0.0f;
|
||||
}
|
||||
for (int l2 = 0; (l2 < 2); l2 = (l2 + 1)) {
|
||||
fRec0[l2] = 0.0f;
|
||||
}
|
||||
for (int l3 = 0; (l3 < 2); l3 = (l3 + 1)) {
|
||||
fRec5[l3] = 0.0f;
|
||||
}
|
||||
for (int l4 = 0; (l4 < 2); l4 = (l4 + 1)) {
|
||||
fRec4[l4] = 0.0f;
|
||||
}
|
||||
for (int l5 = 0; (l5 < 2); l5 = (l5 + 1)) {
|
||||
fRec3[l5] = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void init(int sample_rate)
|
||||
{
|
||||
classInit(sample_rate);
|
||||
instanceInit(sample_rate);
|
||||
}
|
||||
void instanceInit(int sample_rate)
|
||||
{
|
||||
instanceConstants(sample_rate);
|
||||
instanceResetUserInterface();
|
||||
instanceClear();
|
||||
}
|
||||
|
||||
int getSampleRate()
|
||||
{
|
||||
return fSampleRate;
|
||||
}
|
||||
|
||||
void compute(int count, const FAUSTFLOAT* const* inputs, FAUSTFLOAT* const* outputs)
|
||||
{
|
||||
const FAUSTFLOAT* input0 = inputs[0];
|
||||
const FAUSTFLOAT* input1 = inputs[1];
|
||||
FAUSTFLOAT* output0 = outputs[0];
|
||||
FAUSTFLOAT* output1 = outputs[1];
|
||||
for (int i = 0; (i < count); i = (i + 1)) {
|
||||
float fTemp0 = float(input0[i]);
|
||||
float fTemp1 = float(input1[i]);
|
||||
float fTemp2 = std::fabs(fTemp0);
|
||||
fRec2[0] = std::max<float>(fTemp2, ((fConst5 * fRec2[1]) + (fConst6 * fTemp2)));
|
||||
fRec1[0] = ((fConst3 * fRec1[1]) + (fConst4 * fRec2[0]));
|
||||
fRec0[0] = ((fConst1 * fRec0[1]) + (fConst2 * ((fRec1[0] > 1.0f) ? (1.0f / fRec1[0]) : 1.0f)));
|
||||
output0[i] = FAUSTFLOAT((fTemp0 * fRec0[0]));
|
||||
float fTemp3 = std::fabs(fTemp1);
|
||||
fRec5[0] = std::max<float>(fTemp3, ((fConst5 * fRec5[1]) + (fConst6 * fTemp3)));
|
||||
fRec4[0] = ((fConst3 * fRec4[1]) + (fConst4 * fRec5[0]));
|
||||
fRec3[0] = ((fConst1 * fRec3[1]) + (fConst2 * ((fRec4[0] > 1.0f) ? (1.0f / fRec4[0]) : 1.0f)));
|
||||
output1[i] = FAUSTFLOAT((fTemp1 * fRec3[0]));
|
||||
fRec2[1] = fRec2[0];
|
||||
fRec1[1] = fRec1[0];
|
||||
fRec0[1] = fRec0[0];
|
||||
fRec5[1] = fRec5[0];
|
||||
fRec4[1] = fRec4[0];
|
||||
fRec3[1] = fRec3[0];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
Loading…
Add table
Reference in a new issue