From 430b54128bf57ead82632b2c199e4af3a342cf7b Mon Sep 17 00:00:00 2001 From: Jean Pierre Cimalando Date: Wed, 18 Mar 2020 20:49:52 +0100 Subject: [PATCH] Add the width effect --- src/CMakeLists.txt | 1 + src/sfizz/Effects.cpp | 2 + src/sfizz/effects/Width.cpp | 80 +++++++++++++++++++++++++++++++++++++ src/sfizz/effects/Width.h | 50 +++++++++++++++++++++++ 4 files changed, 133 insertions(+) create mode 100644 src/sfizz/effects/Width.cpp create mode 100644 src/sfizz/effects/Width.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d4c738d2..821fb8fe 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -27,6 +27,7 @@ set (SFIZZ_SOURCES sfizz/effects/Limiter.cpp sfizz/effects/Rectify.cpp sfizz/effects/Gain.cpp + sfizz/effects/Width.cpp ) include (SfizzSIMDSourceFiles) diff --git a/src/sfizz/Effects.cpp b/src/sfizz/Effects.cpp index bfa8f52c..9facbfcb 100644 --- a/src/sfizz/Effects.cpp +++ b/src/sfizz/Effects.cpp @@ -17,6 +17,7 @@ #include "effects/Limiter.h" #include "effects/Rectify.h" #include "effects/Gain.h" +#include "effects/Width.h" #include namespace sfz { @@ -33,6 +34,7 @@ void EffectFactory::registerStandardEffectTypes() // 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) diff --git a/src/sfizz/effects/Width.cpp b/src/sfizz/effects/Width.cpp new file mode 100644 index 00000000..9a9fa336 --- /dev/null +++ b/src/sfizz/effects/Width.cpp @@ -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 widths = _tempBuffer.getSpan(0); + std::fill(widths.begin(), widths.end(), baseWidth); + + absl::Span input1 { inputs[0], nframes }; + absl::Span input2 { inputs[1], nframes }; + absl::Span output1 { outputs[0], nframes }; + absl::Span output2 { outputs[1], nframes }; + + for (unsigned i = 0; i < nframes; ++i) { + float l = input1[i]; + float r = input2[i]; + + float w = clamp((widths[i] + 100.0f) * 0.005f, 0.0f, 1.0f); + float coeff1 = _internals::panLookup(w); + float coeff2 = _internals::panLookup(1.0f - w); + + output1[i] = l * coeff2 + r * coeff1; + output2[i] = l * coeff1 + r * coeff2; + } + } + + std::unique_ptr Width::makeInstance(absl::Span members) + { + auto fx = absl::make_unique(); + + 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 diff --git a/src/sfizz/effects/Width.h b/src/sfizz/effects/Width.h new file mode 100644 index 00000000..82ebb7b8 --- /dev/null +++ b/src/sfizz/effects/Width.h @@ -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 block. + */ + static std::unique_ptr makeInstance(absl::Span members); + + private: + float _width = 100; + AudioBuffer _tempBuffer { 1, config::defaultSamplesPerBlock }; + }; + +} // namespace fx +} // namespace sfz