12#include "dsp/hart_dsp.hpp"
26template<
typename SampleType>
38 if (other.dspChain.size() == 0)
43 for (
auto& dsp : other.dspChain)
51 dspChain (std::move (other.dspChain))
53 other.m_numChannels = 0;
54 other.m_startTimestampSeconds = 0.0;
70 if (other.dspChain.size() == 0)
73 for (
auto& dsp : other.dspChain)
86 dspChain = std::move (other.dspChain);
88 other.m_numChannels = 0;
89 other.m_startTimestampSeconds = 0.0;
118 virtual void prepare (
double sampleRateHz, size_t numOutputChannels, size_t maxBlockSizeFrames) = 0;
153 virtual void represent (std::ostream& stream)
const = 0;
163 prepare (sampleRateHz
, numOutputChannels
, maxBlockSizeFrames
);
164 const size_t numInputChannels = numOutputChannels;
168 if (! dsp->supportsChannelLayout (numInputChannels, numOutputChannels))
171 if (! dsp->supportsSampleRate (sampleRateHz))
174 dsp->prepareWithEnvelopes (sampleRateHz, numInputChannels, numOutputChannels, maxBlockSizeFrames);
179 performSkipTo (sampleRateHz, numOutputChannels, maxBlockSizeFrames);
193 dsp->processWithEnvelopes (inputReplacing, output);
211 void representWithDSPChain (std::ostream& stream)
const
216 stream <<
" >> " << *dsp;
221 using m_SampleType = SampleType;
239 void performSkipTo (
double sampleRateHz, size_t numOutputChannels, size_t maxBlockSizeFrames)
245 while (fastForwardFramesLeft != 0)
247 const size_t blockSizeFrames = fastForwardFramesLeft >= maxBlockSizeFrames ? maxBlockSizeFrames : fastForwardFramesLeft;
248 AudioBuffer<SampleType> dummyAudioBlock (numOutputChannels, blockSizeFrames);
250 fastForwardFramesLeft -= blockSizeFrames;
261template<
typename SampleType,
typename Derived>
271 this->dspChain.emplace_back (dsp.copy());
272 return static_cast<Derived&> (*
this);
280 this->dspChain.emplace_back (std::move (dsp));
281 return static_cast<Derived&> (*
this);
291 typename =
typename std::enable_if<
294 typename std::decay<DerivedDSP>::type
300 this->dspChain.emplace_back (dsp.move());
301 return static_cast<Derived&> (*
this);
309 return hart::make_unique<Derived> (
static_cast<
const Derived&> (*
this));
314 return hart::make_unique<Derived> (std::move (
static_cast<
const Derived&> (*
this)));
322 Derived&
skipTo (
double startTimestampSeconds)
324 if (startTimestampSeconds < 0)
327 this->m_startTimestampSeconds += startTimestampSeconds;
328 return static_cast<Derived&> (*
this);
334 auto newSignal =
static_cast<
const Derived&> (*
this);
335 newSignal.dspChain.emplace_back (hart::make_unique<GainLinear<SampleType>> (SampleType (-1)));
349template<
typename SampleType>
350std::ostream& operator<< (std::ostream& stream,
const SignalBase<SampleType>& signal)
352 signal.representWithDSPChain (stream);
363 typename DerivedSignal,
364 typename DerivedDSP,
typename std::enable_if<std::is_base_of<
DSPBase<SampleType>,
typename std::decay<DerivedDSP>::type>::value>::type>
367 return signal.followedBy (std::move (dsp));
373template<
typename SampleType,
typename DerivedSignal>
376 return signal.followedBy (dsp);
382template<
typename SampleType,
typename DerivedSignal>
385 return std::move (signal.followedBy (dsp));
392template<
typename SampleType,
typename DerivedSignal>
395 signal.followedBy (std::move (dsp));
403template<
typename SampleType,
typename DerivedSignal>
406 signal.followedBy (std::move (dsp));
407 return std::move (signal);
416 typename DerivedSignal,
417 typename DerivedDSP,
typename =
typename std::enable_if<std::is_base_of<
DSPBase<SampleType>, DerivedDSP>::value>::type>
418Signal<SampleType, DerivedSignal>&
operator>>(
Signal<SampleType, DerivedSignal>& signal, std::unique_ptr<DerivedDSP>&& dsp)
420 signal.followedBy (std::move (dsp));
430 typename DerivedSignal,
431 typename DerivedDSP,
typename =
typename std::enable_if<std::is_base_of<
DSPBase<SampleType>, DerivedDSP>::value>::type>
432Signal<SampleType, DerivedSignal>&&
operator>>(
Signal<SampleType, DerivedSignal>&& signal, std::unique_ptr<DerivedDSP>&& dsp)
434 signal.followedBy (std::move (dsp));
435 return std::move (signal);
456#define HART_SIGNAL_FORBID_COPY_AND_MOVE
457 std::unique_ptr<Signal<SampleType>> copy() const override {
458 static_assert(false, "This Signal cannot be copied");
461 std::unique_ptr<Signal<SampleType>> move() override {
462 static_assert(false, "This Signal cannot be moved");
467#define HART_SIGNAL_DECLARE_ALIASES_FOR(ClassName)
468 namespace aliases_float{
469 using ClassName = hart::ClassName<float>;
471 namespace aliases_double{
472 using ClassName = hart::ClassName<double>;
Polymorphic base for all DSP.
Polymorphic base for all signals.
virtual void reset()=0
Resets the Signal to initial state.
virtual ~SignalBase()=default
Destructor.
virtual void represent(std::ostream &stream) const =0
Makes a text representation of this Signal for test failure outputs.
double m_startTimestampSeconds
SignalBase(const SignalBase &other)
Copies other signal.
virtual std::unique_ptr< SignalBase< SampleType > > copy() const =0
Returns a smart pointer with a copy of this object.
void renderNextBlockWithDSPChain(AudioBuffer< SampleType > &output)
Renders next block audio for the signal and all the effects in the DSP chain.
virtual void resetWithDSPChain()
Resets to Signal and all the effects attached to its DSP chain to initial state.
SignalBase & operator=(const SignalBase &other)
Copies from other signal.
SignalBase()=default
Default constructor.
SignalBase & operator=(SignalBase &&other) noexcept
Moves from other signal.
virtual void renderNextBlock(AudioBuffer< SampleType > &output)=0
Renders next block audio for the signal.
void prepareWithDSPChain(double sampleRateHz, size_t numOutputChannels, size_t maxBlockSizeFrames)
Prepares the signal and all attached effects in the DSP chain for rendering.
void setNumChannels(size_t numChannels)
SignalBase(SignalBase &&other) noexcept
Moves from other signal.
virtual std::unique_ptr< SignalBase< SampleType > > move()=0
Returns a smart pointer with a moved instance of this object.
virtual bool supportsNumChannels(size_t) const
Tells the host whether this Signal is capable of generating audio for a certain amount of channels.
virtual bool supportsSampleRate(double) const
Tells whether this Signal supports given sample rate.
std::vector< std::unique_ptr< DSPBase< SampleType > > > dspChain
virtual void prepare(double sampleRateHz, size_t numOutputChannels, size_t maxBlockSizeFrames)=0
Prepare the signal for rendering.
Signal & followedBy(std::unique_ptr< DSPBase< SampleType > > dsp)
Adds a DSP effect to the end of signal's DSP chain by transfering a smart pointer.
Derived & skipTo(double startTimestampSeconds)
Skips the signal to a specific timestamp.
Derived operator-() const
Returns a copy of this signal, but with flipped phase.
std::unique_ptr< SignalBase< SampleType > > move() override
Returns a smart pointer with a moved instance of this object.
Derived & followedBy(const DSPBase< SampleType > &dsp)
Adds a DSP effect to the end of signal's DSP chain by copying it.
Derived operator~() const
Returns a copy of this signal, but with flipped phase.
std::unique_ptr< SignalBase< SampleType > > copy() const override
Returns a smart pointer with a copy of this object.
Signal & followedBy(DerivedDSP &&dsp)
Adds a DSP effect to the end of signal's DSP chain by moving it.
Signal< SampleType, DerivedSignal > && operator>>(Signal< SampleType, DerivedSignal > &&signal, std::unique_ptr< DSPBase< SampleType > > &&dsp)
Adds a DSP effect to the end of signal's DSP chain by transfering it.
Signal< SampleType, DerivedSignal > & operator>>(Signal< SampleType, DerivedSignal > &signal, std::unique_ptr< DSPBase< SampleType > > &&dsp)
Adds a DSP effect to the end of signal's DSP chain by transfering it.
Signal< SampleType, DerivedSignal > && operator>>(Signal< SampleType, DerivedSignal > &&signal, const DSPBase< SampleType > &dsp)
Adds a DSP effect to the end of signal's DSP chain by copying it.
Signal< SampleType, DerivedSignal > & operator>>(Signal< SampleType, DerivedSignal > &signal, DerivedDSP &&dsp)
Adds a DSP effect to the end of signal's DSP chain by moving it.
Signal< SampleType, DerivedSignal > && operator>>(Signal< SampleType, DerivedSignal > &&signal, std::unique_ptr< DerivedDSP > &&dsp)
Adds a DSP effect to the end of signal's DSP chain by transfering it.
Signal< SampleType, DerivedSignal > & operator>>(Signal< SampleType, DerivedSignal > &signal, const DSPBase< SampleType > &dsp)
Adds a DSP effect to the end of signal's DSP chain by copying it.
Signal< SampleType, DerivedSignal > & operator>>(Signal< SampleType, DerivedSignal > &signal, std::unique_ptr< DerivedDSP > &&dsp)
Adds a DSP effect to the end of signal's DSP chain by transfering it.
static size_t roundToSizeT(SampleType x)
Rounds a floating point value to a size_t value.
static SampleType floatsNotEqual(SampleType a, SampleType b, SampleType epsilon=(SampleType) 1e-8)
Compares two floating point numbers within a given tolerance.
#define HART_THROW_OR_RETURN_VOID(ExceptionType, message)
#define hassert(condition)
#define HART_THROW_OR_RETURN(ExceptionType, message, returnValue)