Skip to content

Commit

Permalink
Merge pull request #84 from jpcima/effects
Browse files Browse the repository at this point in the history
Effects
  • Loading branch information
paulfd authored Mar 7, 2020
2 parents 291920f + e84af98 commit 53a4cf0
Show file tree
Hide file tree
Showing 23 changed files with 1,147 additions and 50 deletions.
68 changes: 37 additions & 31 deletions benchmarks/BM_multiplyAddFixedGain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,58 +14,64 @@

class MultiplyAddFixedGain : public benchmark::Fixture {
public:
void SetUp(const ::benchmark::State& state) {
std::random_device rd { };
std::mt19937 gen { rd() };
std::uniform_real_distribution<float> dist { 0, 1 };
input = std::vector<float>(state.range(0));
output = std::vector<float>(state.range(0));
gain = dist(gen);
std::fill(output.begin(), output.end(), 1.0f );
std::generate(input.begin(), input.end(), [&]() { return dist(gen); });
}

void TearDown(const ::benchmark::State& state [[maybe_unused]]) {
void SetUp(const ::benchmark::State& state)
{
std::random_device rd {};
std::mt19937 gen { rd() };
std::uniform_real_distribution<float> dist { 0, 1 };
input = std::vector<float>(state.range(0));
output = std::vector<float>(state.range(0));
gain = dist(gen);
std::fill(output.begin(), output.end(), 1.0f);
std::generate(input.begin(), input.end(), [&]() { return dist(gen); });
}

}
void TearDown(const ::benchmark::State& state [[maybe_unused]])
{
}

float gain = {};
std::vector<float> input;
std::vector<float> output;
float gain = {};
std::vector<float> input;
std::vector<float> output;
};

BENCHMARK_DEFINE_F(MultiplyAddFixedGain, Straight)(benchmark::State& state) {
for (auto _ : state)
{
BENCHMARK_DEFINE_F(MultiplyAddFixedGain, Straight)
(benchmark::State& state)
{
for (auto _ : state) {
for (int i = 0; i < state.range(0); ++i)
output[i] += gain * input[i];
}
}

BENCHMARK_DEFINE_F(MultiplyAddFixedGain, Scalar)(benchmark::State& state) {
for (auto _ : state)
{
BENCHMARK_DEFINE_F(MultiplyAddFixedGain, Scalar)
(benchmark::State& state)
{
for (auto _ : state) {
sfz::multiplyAdd<float, false>(gain, input, absl::MakeSpan(output));
}
}

BENCHMARK_DEFINE_F(MultiplyAddFixedGain, SIMD)(benchmark::State& state) {
for (auto _ : state)
{
BENCHMARK_DEFINE_F(MultiplyAddFixedGain, SIMD)
(benchmark::State& state)
{
for (auto _ : state) {
sfz::multiplyAdd<float, true>(gain, input, absl::MakeSpan(output));
}
}

BENCHMARK_DEFINE_F(MultiplyAddFixedGain, Scalar_Unaligned)(benchmark::State& state) {
for (auto _ : state)
{
BENCHMARK_DEFINE_F(MultiplyAddFixedGain, Scalar_Unaligned)
(benchmark::State& state)
{
for (auto _ : state) {
sfz::multiplyAdd<float, false>(gain, absl::MakeSpan(input).subspan(1), absl::MakeSpan(output).subspan(1));
}
}

BENCHMARK_DEFINE_F(MultiplyAddFixedGain, SIMD_Unaligned)(benchmark::State& state) {
for (auto _ : state)
{
BENCHMARK_DEFINE_F(MultiplyAddFixedGain, SIMD_Unaligned)
(benchmark::State& state)
{
for (auto _ : state) {
sfz::multiplyAdd<float, true>(gain, absl::MakeSpan(input).subspan(1), absl::MakeSpan(output).subspan(1));
}
}
Expand Down
3 changes: 3 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ set (SFIZZ_SOURCES
sfizz/FloatEnvelopes.cpp
sfizz/Logger.cpp
sfizz/SfzFilter.cpp
sfizz/Effects.cpp
sfizz/effects/Nothing.cpp
sfizz/effects/Lofi.cpp
)
include (SfizzSIMDSourceFiles)

Expand Down
16 changes: 16 additions & 0 deletions src/sfizz/AudioSpan.h
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,22 @@ class AudioSpan {
return {};
}

/**
* @brief Convert implicitly to a pointer of channels
*/
operator const float* const*() const noexcept
{
return spans.data();
}

/**
* @brief Convert implicitly to a pointer of channels
*/
operator float* const*() noexcept
{
return spans.data();
}

/**
* @brief Get a Span<Type> corresponding to a specific channel
*
Expand Down
4 changes: 4 additions & 0 deletions src/sfizz/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ namespace config {
*/
const absl::string_view midnamManufacturer { "The Sfizz authors" };
const absl::string_view midnamModel { "Sfizz" };
/**
Limit of how many "fxN" buses are accepted (in SFZv2, maximum is 4)
*/
constexpr int maxEffectBuses { 256 };
} // namespace config

// Enable or disable SIMD accelerators by default
Expand Down
146 changes: 146 additions & 0 deletions src/sfizz/Effects.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
// 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

#include "Effects.h"
#include "AudioSpan.h"
#include "Opcode.h"
#include "SIMDHelpers.h"
#include "Config.h"
#include "effects/Nothing.h"
#include "effects/Lofi.h"
#include <algorithm>

namespace sfz {

void EffectFactory::registerStandardEffectTypes()
{
// TODO
registerEffectType("lofi", fx::Lofi::makeInstance);
}

void EffectFactory::registerEffectType(absl::string_view name, Effect::MakeInstance& make)
{
FactoryEntry ent;
ent.name = std::string(name);
ent.make = &make;
_entries.push_back(std::move(ent));
}

std::unique_ptr<Effect> EffectFactory::makeEffect(absl::Span<const Opcode> members)
{
const Opcode* opcode = nullptr;

for (auto it = members.rbegin(); it != members.rend() && !opcode; ++it) {
if (it->lettersOnlyHash == hash("type"))
opcode = &*it;
}

if (!opcode) {
DBG("The effect does not specify a type");
return std::make_unique<sfz::fx::Nothing>();
}

const absl::string_view type = opcode->value;

const auto it = absl::c_find_if(_entries, [&](auto&& entry) { return entry.name == type; });
if (it == _entries.end()) {
DBG("Unsupported effect type: " << type);
return std::make_unique<sfz::fx::Nothing>();
}

auto fx = it->make(members);
if (!fx) {
DBG("Could not instantiate effect of type: " << type);
return std::make_unique<sfz::fx::Nothing>();
}

return fx;
}

///
EffectBus::EffectBus()
{
}

EffectBus::~EffectBus()
{
}

void EffectBus::addEffect(std::unique_ptr<Effect> fx)
{
_effects.emplace_back(std::move(fx));
}

void EffectBus::clearInputs(unsigned nframes)
{
AudioSpan<float>(_inputs).first(nframes).fill(0.0f);
AudioSpan<float>(_outputs).first(nframes).fill(0.0f);
}

void EffectBus::addToInputs(const float* const addInput[], float addGain, unsigned nframes)
{
if (addGain == 0)
return;

for (unsigned c = 0; c < EffectChannels; ++c) {
absl::Span<const float> addIn { addInput[c], nframes };
sfz::multiplyAdd(addGain, addIn, _inputs.getSpan(c));
}
}

void EffectBus::setSampleRate(double sampleRate)
{
for (const auto& effectPtr : _effects)
effectPtr->setSampleRate(sampleRate);
}

void EffectBus::clear()
{
for (const auto& effectPtr : _effects)
effectPtr->clear();
}

void EffectBus::process(unsigned nframes)
{
size_t numEffects = _effects.size();

if (numEffects > 0 && hasNonZeroOutput()) {
_effects[0]->process(
AudioSpan<float>(_inputs), AudioSpan<float>(_outputs), nframes);
for (size_t i = 1; i < numEffects; ++i)
_effects[i]->process(
AudioSpan<float>(_outputs), AudioSpan<float>(_outputs), nframes);
} else
fx::Nothing().process(
AudioSpan<float>(_inputs), AudioSpan<float>(_outputs), nframes);
}

void EffectBus::mixOutputsTo(float* const mainOutput[], float* const mixOutput[], unsigned nframes)
{
const float gainToMain = _gainToMain;
const float gainToMix = _gainToMix;

for (unsigned c = 0; c < EffectChannels; ++c) {
auto fxOut = _outputs.getConstSpan(c);
sfz::multiplyAdd(gainToMain, fxOut, absl::Span<float>(mainOutput[c], nframes));
sfz::multiplyAdd(gainToMix, fxOut, absl::Span<float>(mixOutput[c], nframes));
}
}

size_t EffectBus::numEffects() const noexcept
{
return _effects.size();
}
void EffectBus::setSamplesPerBlock(int samplesPerBlock) noexcept
{
_inputs.resize(samplesPerBlock);
_outputs.resize(samplesPerBlock);

for (const auto& effectPtr : _effects)
effectPtr->setSamplesPerBlock(samplesPerBlock);
}

} // namespace sfz
Loading

0 comments on commit 53a4cf0

Please sign in to comment.