7#include <unordered_map>
11#include "envelopes/hart_envelope.hpp"
24using EnvelopeBuffers = std::unordered_map<
int, std::vector<
double>>;
31template <
typename SampleType>
46 virtual void prepare (
double sampleRateHz, size_t numInputChannels, size_t numOutputChannels, size_t maxBlockSizeFrames) = 0;
84 virtual void setValue (
int paramId,
double value) = 0;
111 virtual void represent (std::ostream& stream)
const = 0;
125 virtual std::unique_ptr<
DSPBase<SampleType>>
copy()
const {
return nullptr; }
141 for (
auto& pair : other.m_envelopes)
142 m_envelopes.emplace (pair.first, pair.second->copy());
160 for (
auto& pair : other.m_envelopes)
161 m_envelopes.emplace (pair.first, pair.second->copy());
194 void prepareWithEnvelopes (
double sampleRateHz, size_t numInputChannels, size_t numOutputChannels, size_t maxBlockSizeFrames)
196 m_envelopeBuffers.clear();
200 const int paramId = item.first;
201 m_envelopeBuffers.emplace (paramId, std::vector<
double> (maxBlockSizeFrames));
206 for (
auto& item : m_envelopeBuffers)
208 const int paramId = item.first;
209 auto& envelopeBuffer = item.second;
213 hassert (
hasEnvelopeFor (paramId
) &&
"Envelope for this param id is not attached, yet there's an envelope buffer allocated for it");
215 if (envelopeBuffer.size() != maxBlockSizeFrames)
216 envelopeBuffer.resize (maxBlockSizeFrames);
220 prepare (sampleRateHz
, numInputChannels
, numOutputChannels
, maxBlockSizeFrames
);
229 std::unique_ptr<
Envelope>& envelope = item.second;
254 for (
auto& item : m_envelopeBuffers)
256 const int paramId = item.first;
257 auto& envelopeBuffer = item.second;
261 hassert (
hasEnvelopeFor (paramId
) &&
"Envelope for this param id is not attached, yet there's an envelope buffer allocated for it");
262 hassert (input.getNumFrames() <= envelopeBuffer.size() &&
"Envelope Buffers were not allocated properly for this buffer size");
265 getValues (paramId, input.getNumFrames(), envelopeBuffer);
275 this->represent (stream);
280 stream <<
".atChannels (";
287 using SampleTypePublicAlias = SampleType;
294 EnvelopeBuffers m_envelopeBuffers;
300 void getValues (
int paramId, size_t blockSize, std::vector<
double>& valuesOutput)
302 if (valuesOutput.size() < blockSize)
304 HART_WARNING (
"Make sure to configure your envelope container size before processing audio");
305 valuesOutput.resize (blockSize);
311 std::fill (valuesOutput.begin(), valuesOutput.end(), value);
339template<
typename SampleType,
typename Derived>
354 _withEnvelope (paramId, envelope);
355 return static_cast<Derived&> (*
this);
368 _withEnvelope (paramId, envelope);
369 return static_cast<Derived&&> (*
this);
382 _withEnvelope (paramId, envelope);
383 return static_cast<Derived&> (*
this);
396 _withEnvelope (paramId, envelope);
397 return static_cast<Derived&&> (*
this);
405 return hart::make_unique<Derived> (std::move (
static_cast<Derived&> (*
this)));
415 Derived&
atChannels (std::initializer_list<size_t> channelsToProcess) &
417 _atChannels (channelsToProcess);
418 return static_cast<Derived&> (*
this);
428 Derived&&
atChannels (std::initializer_list<size_t> channelsToProcess) &&
430 _atChannels (channelsToProcess);
431 return static_cast<Derived&&> (*
this);
445 _atChannel (channelToProcess);
446 return static_cast<Derived&> (*
this);
460 _atChannel (channelToProcess);
461 return static_cast<Derived&&> (*
this);
470 this->m_channelsToProcess.setAllTo (
true);
471 return static_cast<Derived&> (*
this);
480 this->m_channelsToProcess.setAllTo (
true);
481 return static_cast<Derived&&> (*
this);
493 _atAllChannelsExcept (channelsToSkip);
494 return static_cast<Derived&> (*
this);
506 _atAllChannelsExcept (channelsToSkip);
507 return static_cast<Derived&&> (*
this);
511 void _withEnvelope (
int paramId,
Envelope&& envelope)
513 if (!
this->supportsEnvelopeFor (paramId))
519 void _withEnvelope (
int paramId,
const Envelope& envelope)
521 if (!
this->supportsEnvelopeFor(paramId))
524 this->m_envelopes.emplace (paramId, envelope
.copy());
527 void _atChannels (std::initializer_list<size_t> channelsToProcess)
529 this->m_channelsToProcess.setAllTo (
false);
531 for (size_t channel : channelsToProcess)
533 if (channel >=
this->m_channelsToProcess.size())
536 this->m_channelsToProcess[channel] =
true;
540 void _atChannel (size_t channelToProcess)
542 if (channelToProcess >=
this->m_channelsToProcess.size())
545 this->m_channelsToProcess.setAllTo (
false);
546 this->m_channelsToProcess[channelToProcess] =
true;
549 void _atAllChannelsExcept (std::initializer_list<size_t> channelsToSkip)
551 this->m_channelsToProcess.setAllTo (
true);
553 for (size_t channel : channelsToSkip)
555 if (channel >=
this->m_channelsToProcess.size())
558 this->m_channelsToProcess[channel] =
false;
566template <
typename SampleType>
567inline std::ostream& operator<< (std::ostream& stream,
const DSPBase<SampleType>& dsp)
570 dsp.representWithActiveChannels (stream);
579#define HART_DSP_NON_COPYABLE
580 std::unique_ptr<DSP<SampleType>> copy() const override { return nullptr; }
594#define HART_DSP_NON_MOVABLE
595 std::unique_ptr<DSP<SampleType>> move() override { return nullptr; }
599#define HART_DSP_COPYABLE(ClassName) virtual
600 std::unique_ptr<DSPBase<SampleType>> copy() const override \
601{
602 return hart::make_unique<ClassName> (static_cast<const ClassName&> (*this)); \
603}
607#define HART_DSP_MOVABLE(ClassName) virtual
608 std::unique_ptr<DSPBase<SampleType>> move() override \
609{
610 return hart::make_unique<ClassName> (std::move (static_cast<ClassName&> (*this))); \
611}
616#define HART_DSP_DECLARE_ALIASES_FOR(ClassName)
617 namespace aliases_float{
618 using ClassName = hart::ClassName<float>;
620 namespace aliases_double{
621 using ClassName = hart::ClassName<double>;
Container for audio data.
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 std::unique_ptr< DSPBase< SampleType > > move()=0
Returns a smart pointer with a moved instance of this object.
virtual std::unique_ptr< DSPBase< SampleType > > copy() const
Returns a smart pointer with a copy of this object.
virtual void represent(std::ostream &stream) const =0
Makes a text representation of this DSP effect for test failure outputs.
ChannelFlags m_channelsToProcess
virtual void reset()
Resets to initial state.
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 double getValue(int) const
Retrieves DSP value.
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.
void resetWithEnvelopes()
Resets the DSP instance, and all associated Envelopes.
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
virtual std::unique_ptr< DSPBase< SampleType > > move() override
Returns a smart pointer with a moved instance of this object.
Derived && atChannel(size_t channelToProcess) &&
Makes this DSP process only specific channels, and bypass the rest.
Derived && withEnvelope(int paramId, const Envelope &envelope) &&
Adds envelope to a specific parameter by copying it.
Derived && withEnvelope(int paramId, Envelope &&envelope) &&
Adds envelope to a specific parameter by moving it.
Derived & atAllChannelsExcept(std::initializer_list< size_t > channelsToSkip) &
Makes this DSP process only specific channels, and bypass the rest.
Derived & withEnvelope(int paramId, const Envelope &envelope) &
Adds envelope to a specific parameter by copying it.
Derived & atAllChannels() &
Makes this DSP apply to all channels.
Derived && atAllChannels() &&
Makes this DSP apply to all channels.
Derived && atChannels(std::initializer_list< size_t > channelsToProcess) &&
Makes this DSP process only specific channels, and ignore the rest.
Derived & atChannels(std::initializer_list< size_t > channelsToProcess) &
Makes this DSP process only specific channels, and ignore the rest.
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 && atAllChannelsExcept(std::initializer_list< size_t > channelsToSkip) &&
Makes this DSP process only specific channels, and bypass the rest.
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
Thrown when some parameter has an unsupported value.
Thrown when an inappropriate value is encountered.
#define HART_THROW_OR_RETURN_VOID(ExceptionType, message)
Throws an exception if HART_DO_NOT_THROW_EXCEPTIONS is set, prints a message and returns otherwise.
#define HART_WARNING(message)
Prints a warning message.
#define hassert(condition)
Triggers a HartAssertException if the condition is false
#define HART_THROW_OR_RETURN(ExceptionType, message, returnValue)
Throws an exception if HART_DO_NOT_THROW_EXCEPTIONS is set, prints a message and returns a specified ...
std::unique_ptr< ObjectType > make_unique(Args &&... args)
std::make_unique() replacement for C++11