sfizz/src/sfizz/Effects.h
2020-03-06 11:20:18 +01:00

154 lines
3.8 KiB
C++

// 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 "AudioBuffer.h"
#include "absl/strings/string_view.h"
#include "absl/types/span.h"
#include <array>
#include <vector>
#include <memory>
namespace sfz {
struct Opcode;
enum {
// Number of channels processed by effects
EffectChannels = 2,
};
/**
@brief Abstract base of SFZ effects
*/
class Effect {
public:
virtual ~Effect() {}
/**
@brief Initializes with the given sample rate.
*/
virtual void init(double sampleRate) = 0;
/**
@brief Reset the state to initial.
*/
virtual void clear() = 0;
/**
@brief Computes a cycle of the effect in stereo.
*/
virtual void process(const float* const inputs[], float* const outputs[], unsigned nframes) = 0;
/**
@brief Type of the factory function used to instantiate an effect given
the contents of the <effect> block
*/
typedef std::unique_ptr<Effect>(MakeInstance)(absl::Span<const Opcode> members);
};
/**
@brief SFZ effects factory
*/
class EffectFactory {
public:
/**
@brief Registers all available standard effects into the factory.
*/
void registerStandardEffectTypes();
/**
@brief Registers a user-defined effect into the factory.
*/
void registerEffectType(absl::string_view name, Effect::MakeInstance& make);
/**
@brief Instantiates an effect given the contents of the <effect> block.
*/
std::unique_ptr<Effect> makeEffect(absl::Span<const Opcode> members);
private:
struct FactoryEntry {
std::string name;
Effect::MakeInstance* make;
};
std::vector<FactoryEntry> _entries;
};
/**
@brief Sequence of effects processed in series
*/
class EffectBus {
public:
EffectBus();
~EffectBus();
/**
@brief Adds an effect at the end of the bus.
*/
void addEffect(std::unique_ptr<Effect> fx);
/**
@brief Checks whether this bus can produce output.
*/
bool hasNonZeroOutput() const { return _gainToMain != 0 || _gainToMix != 0; }
/**
@brief Sets the amount of effect output going to the main.
*/
void setGainToMain(float gain) { _gainToMain = gain; }
/**
@brief Sets the amount of effect output going to the mix.
*/
void setGainToMix(float gain) { _gainToMix = gain; }
/**
@brief Resets the input buffers to zero.
*/
void clearInputs(unsigned nframes);
/**
@brief Adds some audio into the input buffer.
*/
void addToInputs(const float* const addInput[], float addGain, unsigned nframes);
/**
@brief Initializes all effects in the bus with the given sample rate.
*/
void init(double sampleRate);
/**
@brief Resets the state of all effects in the bus.
*/
void clear();
/**
@brief Computes a cycle of the effect bus.
*/
void process(unsigned nframes);
/**
@brief Mixes the outputs into a pair of stereo signals: Main and Mix.
*/
void mixOutputsTo(float* const mainOutput[], float* const mixOutput[], unsigned nframes);
/**
* @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) noexcept;
private:
std::vector<std::unique_ptr<Effect>> _effects;
AudioBuffer<float> _inputs { EffectChannels, config::defaultSamplesPerBlock };
AudioBuffer<float> _outputs { EffectChannels, config::defaultSamplesPerBlock };
float _gainToMain = 0.0;
float _gainToMix = 0.0;
};
} // namespace sfz