Add the rectifier
This commit is contained in:
parent
bdd2d32621
commit
5cd5db877a
4 changed files with 169 additions and 0 deletions
|
|
@ -25,6 +25,7 @@ set (SFIZZ_SOURCES
|
|||
sfizz/effects/Apan.cpp
|
||||
sfizz/effects/Lofi.cpp
|
||||
sfizz/effects/Limiter.cpp
|
||||
sfizz/effects/Rectify.cpp
|
||||
)
|
||||
include (SfizzSIMDSourceFiles)
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
#include "effects/Apan.h"
|
||||
#include "effects/Lofi.h"
|
||||
#include "effects/Limiter.h"
|
||||
#include "effects/Rectify.h"
|
||||
#include <algorithm>
|
||||
|
||||
namespace sfz {
|
||||
|
|
@ -27,6 +28,9 @@ void EffectFactory::registerStandardEffectTypes()
|
|||
registerEffectType("apan", fx::Apan::makeInstance);
|
||||
registerEffectType("lofi", fx::Lofi::makeInstance);
|
||||
registerEffectType("limiter", fx::Limiter::makeInstance);
|
||||
|
||||
// extensions (book)
|
||||
registerEffectType("rectify", fx::Rectify::makeInstance);
|
||||
}
|
||||
|
||||
void EffectFactory::registerEffectType(absl::string_view name, Effect::MakeInstance& make)
|
||||
|
|
|
|||
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) {
|
||||
float amount = amounts[i] * 0.01f;
|
||||
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
|
||||
Loading…
Add table
Reference in a new issue