7#include <unordered_map>
11#include "envelopes/hart_envelope.hpp"
23using EnvelopeBuffers = std::unordered_map<
int, std::vector<
double>>;
30template <
typename SampleType>
45 virtual void prepare (
double sampleRateHz, size_t numInputChannels, size_t numOutputChannels, size_t maxBlockSizeFrames) = 0;
80 virtual void setValue (
int paramId,
double value) = 0;
88 virtual double getValue (
int paramId)
const = 0;
104 virtual void represent (std::ostream& stream)
const = 0;
134 for (
auto& pair : other.m_envelopes)
135 m_envelopes.emplace (pair.first, pair.second->copy());
153 for (
auto& pair : other.m_envelopes)
154 m_envelopes.emplace (pair.first, pair.second->copy());
187 void prepareWithEnvelopes (
double sampleRateHz, size_t numInputChannels, size_t numOutputChannels, size_t maxBlockSizeFrames)
189 m_envelopeBuffers.clear();
193 const int paramId = item.first;
194 m_envelopeBuffers.emplace (paramId, std::vector<
double> (maxBlockSizeFrames));
199 for (
auto& item : m_envelopeBuffers)
201 const int paramId = item.first;
202 auto& envelopeBuffer = item.second;
206 hassert (
hasEnvelopeFor (paramId
) &&
"Envelope for this param id is not attached, yet there's an envelope buffer allocated for it");
208 if (envelopeBuffer.size() != maxBlockSizeFrames)
209 envelopeBuffer.resize (maxBlockSizeFrames);
213 prepare (sampleRateHz
, numInputChannels
, numOutputChannels
, maxBlockSizeFrames
);
234 for (
auto& item : m_envelopeBuffers)
236 const int paramId = item.first;
237 auto& envelopeBuffer = item.second;
241 hassert (
hasEnvelopeFor (paramId
) &&
"Envelope for this param id is not attached, yet there's an envelope buffer allocated for it");
242 hassert (input.getNumFrames() <= envelopeBuffer.size() &&
"Envelope Buffers were not allocated properly for this buffer size");
245 getValues (paramId, envelopeBuffer.size(), envelopeBuffer);
255 this->represent (stream);
260 stream <<
".atChannels (";
267 using SampleTypePublicAlias = SampleType;
274 EnvelopeBuffers m_envelopeBuffers;
280 void getValues (
int paramId, size_t blockSize, std::vector<
double>& valuesOutput)
282 if (valuesOutput.size() < blockSize)
284 HART_WARNING (
"Make sure to configure your envelope container size before processing audio");
285 valuesOutput.resize (blockSize);
291 std::fill (valuesOutput.begin(), valuesOutput.end(), value);
319template<
typename SampleType,
typename Derived>
335 if (!
this->supportsEnvelopeFor (paramId))
339 return static_cast<Derived&> (*
this);
352 if (!
this->supportsEnvelopeFor(paramId))
355 this->m_envelopes.emplace (paramId, envelope
.copy());
356 return static_cast<Derived&> (*
this);
362 virtual std::unique_ptr<
DSPBase<SampleType>>
copy()
const override
364 return hart::make_unique<Derived> (
static_cast<
const Derived&> (*
this));
370 return hart::make_unique<Derived> (std::move (
static_cast<Derived&> (*
this)));
380 Derived&
atChannels (std::initializer_list<size_t> channelsToProcess)
382 this->m_channelsToProcess.setAllTo (
false);
384 for (size_t channel : channelsToProcess)
386 if (channel >=
this->m_channelsToProcess.size())
389 this->m_channelsToProcess[channel] =
true;
392 return static_cast<Derived&> (*
this);
406 if (channelToProcess >=
this->m_channelsToProcess.size())
409 this->m_channelsToProcess.setAllTo (
false);
410 this->m_channelsToProcess[channelToProcess] =
true;
412 return static_cast<Derived&> (*
this);
421 this->m_channelsToProcess.setAllTo (
true);
422 return static_cast<Derived&> (*
this);
434 this->m_channelsToProcess.setAllTo (
true);
436 for (size_t channel : channelsToSkip)
438 if (channel >=
this->m_channelsToProcess.size())
441 this->m_channelsToProcess[channel] =
false;
444 return static_cast<Derived&> (*
this);
451template <
typename SampleType>
452inline std::ostream& operator<< (std::ostream& stream,
const DSPBase<SampleType>& dsp)
455 dsp.representWithActiveChannels (stream);
474#define HART_DSP_FORBID_COPY_AND_MOVE
475 std::unique_ptr<DSP<SampleType>> copy() const override {
476 static_assert(false, "This DSP cannot be copied");
479 std::unique_ptr<DSP<SampleType>> move() override {
480 static_assert(false, "This DSP cannot be moved");
487#define HART_DSP_DECLARE_ALIASES_FOR(ClassName)
488 namespace aliases_float{
489 using ClassName = hart::ClassName<float>;
491 namespace aliases_double{
492 using ClassName = hart::ClassName<double>;
A set of boolean flags mapped to each audio channel.
bool allTrue() const noexcept
Checks if all flags are set to true
ChannelFlags(bool defaultValues=true, size_t numChannels=m_maxChannels)
Creates a new channel flags object.
void resize(size_t newNumChannels)
Resizes the container.
void representAsInitializerList(std::ostream &stream) const
Makes text representation of itself as a initializer list of active channels.
Polymorphic base for all DSP.
virtual ~DSPBase()=default
Destructor.
DSPBase(const DSPBase &other)
Copies from another DSP effect instance.
virtual bool supportsChannelLayout(size_t numInputChannels, size_t numOutputChannels) const =0
Tells the runner (host) whether this effect supports a specific i/o configuration.
void prepareWithEnvelopes(double sampleRateHz, size_t numInputChannels, size_t numOutputChannels, size_t maxBlockSizeFrames)
Prepares all the attached envelopes and the effect itself for processing.
void representWithActiveChannels(std::ostream &stream) const
Makes a text representation of this DSP with optional "atChannels" appendix.
virtual void reset()=0
Resets to initial state.
virtual std::unique_ptr< DSPBase< SampleType > > move()=0
Returns a smart pointer with a moved instance of this object.
virtual void represent(std::ostream &stream) const =0
Makes a text representation of this DSP effect for test failure outputs.
virtual std::unique_ptr< DSPBase< SampleType > > copy() const =0
Returns a smart pointer with a copy of this object.
virtual double getValue(int paramId) const =0
Retrieves DSP value.
ChannelFlags m_channelsToProcess
DSPBase(DSPBase &&other) noexcept
Move constructor.
virtual bool supportsSampleRate(double) const
Tells whether this effect supports given sample rate.
void processWithEnvelopes(const AudioBuffer< SampleType > &input, AudioBuffer< SampleType > &output)
Renders all the automation envelopes and processes the audio.
DSPBase()=default
Default constructor.
virtual void prepare(double sampleRateHz, size_t numInputChannels, size_t numOutputChannels, size_t maxBlockSizeFrames)=0
Prepare for processing.
virtual void setValue(int paramId, double value)=0
Sets DSP value.
DSPBase & operator=(const DSPBase &other)
Copies from another DSP effect instance.
bool hasEnvelopeFor(int paramId)
Checks if there's an automation envelope attached to a specific parameter.
virtual void process(const AudioBuffer< SampleType > &input, AudioBuffer< SampleType > &output, const EnvelopeBuffers &envelopeBuffers, ChannelFlags channelsToProcess)=0
Processes the audio.
ChannelFlags getChannelsToProcess()
Returns a structure indicating which channels should be processed by this DSP.
DSPBase & operator=(DSPBase &&other) noexcept
Move assignment.
virtual bool supportsEnvelopeFor(int) const
Tells whether this effect accepts automation envelopes for a particular parameter.
std::unordered_map< int, std::unique_ptr< Envelope > > m_envelopes
Derived & atChannels(std::initializer_list< size_t > channelsToProcess)
Makes this DSP process only specific channels, and ignore the rest.
virtual std::unique_ptr< DSPBase< SampleType > > copy() const override
Returns a smart pointer with a copy of this object.
Derived & atAllChannelsExcept(std::initializer_list< size_t > channelsToSkip)
Makes this DSP process only specific channels, and bypass the rest.
virtual std::unique_ptr< DSPBase< SampleType > > move() override
Returns a smart pointer with a moved instance of this object.
Derived & withEnvelope(int paramId, Envelope &&envelope)
Adds envelope to a specific parameter by moving it.
Derived & atChannel(size_t channelToProcess)
Makes this DSP process only specific channels, and bypass the rest.
Derived & atAllChannels()
Makes this DSP apply to all channels.
Derived & withEnvelope(int paramId, const Envelope &envelope)
Adds envelope to a specific parameter by copying it.
Represents an Envelope curve for DSP parameters.
virtual void renderNextBlock(size_t blockSize, std::vector< double > &valuesOutput)=0
virtual std::unique_ptr< Envelope > copy() const =0
std::unique_ptr< ObjectType > make_unique(Args &&... args)
std::make_unique() replacement for C++11
#define HART_THROW_OR_RETURN_VOID(ExceptionType, message)
#define HART_WARNING(message)
#define hassert(condition)
#define HART_THROW_OR_RETURN(ExceptionType, message, returnValue)