Add limiter

This commit is contained in:
Jean Pierre Cimalando 2020-03-18 15:29:01 +01:00
parent 18382917c6
commit bdd2d32621
6 changed files with 267 additions and 0 deletions

View file

@ -24,6 +24,7 @@ set (SFIZZ_SOURCES
sfizz/effects/Eq.cpp
sfizz/effects/Apan.cpp
sfizz/effects/Lofi.cpp
sfizz/effects/Limiter.cpp
)
include (SfizzSIMDSourceFiles)

View file

@ -14,6 +14,7 @@
#include "effects/Eq.h"
#include "effects/Apan.h"
#include "effects/Lofi.h"
#include "effects/Limiter.h"
#include <algorithm>
namespace sfz {
@ -25,6 +26,7 @@ void EffectFactory::registerStandardEffectTypes()
registerEffectType("eq", fx::Eq::makeInstance);
registerEffectType("apan", fx::Apan::makeInstance);
registerEffectType("lofi", fx::Lofi::makeInstance);
registerEffectType("limiter", fx::Limiter::makeInstance);
}
void EffectFactory::registerEffectType(absl::string_view name, Effect::MakeInstance& make)

View file

@ -0,0 +1,66 @@
// 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 "gen/limiter.cpp"
#include "absl/memory/memory.h"
namespace sfz {
namespace fx {
Limiter::Limiter()
: _limiter(new faustLimiter)
{
_limiter->instanceResetUserInterface();
}
Limiter::~Limiter()
{
}
void Limiter::setSampleRate(double sampleRate)
{
_limiter->classInit(sampleRate);
_limiter->instanceConstants(sampleRate);
clear();
}
void Limiter::setSamplesPerBlock(int samplesPerBlock)
{
(void)samplesPerBlock;
}
void Limiter::clear()
{
_limiter->instanceClear();
}
void Limiter::process(const float* const inputs[], float* const outputs[], unsigned nframes)
{
_limiter->compute(nframes, inputs, outputs);
}
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

View file

@ -0,0 +1,53 @@
// 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"
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;
};
} // namespace fx
} // namespace sfz

View file

@ -0,0 +1,10 @@
import("stdfaust.lib");
limiter(x) = gain*x with {
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));
};
process = limiter, limiter;

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