|
HART
0.2.0
High level Audio Regression and Testing
|
A DSP unit that renders audio through a linear sequence of DSP instances. More...
#include <hart_dsp_sequence.hpp>
Public Member Functions | |
| DSPSequence (std::vector< std::unique_ptr< DSPBase< SampleType > > > dspChain) | |
| Creates a sequence of DSP processors. | |
| ~DSPSequence () override=default | |
| Destructor. | |
| DSPSequence (const DSPSequence &)=delete | |
| No copy construction. | |
| DSPSequence (DSPSequence &&) noexcept=default | |
| Moves DSP chain from another DSP sequence. | |
| DSPSequence & | operator= (const DSPSequence &)=delete |
| No copy assignment. | |
| DSPSequence & | operator= (DSPSequence &&) noexcept=default |
| Moves DSP chain from another DSP sequence. | |
| void | prepare (double sampleRateHz, size_t numInputChannels, size_t numOutputChannels, size_t maxBlockSizeFrames) override |
| Prepare for processing. | |
| void | process (const AudioBuffer< SampleType > &input, AudioBuffer< SampleType > &output, const EnvelopeBuffers &, ChannelFlags) override |
| Processes the audio. | |
| bool | supportsSampleRate (double sampleRate) const override |
| Tells whether this effect supports given sample rate. | |
| bool | supportsChannelLayout (size_t numInputChannels, size_t numOutputChannels) const override |
| Tells the runner (host) whether this effect supports a specific i/o configuration. | |
| virtual bool | supportsEnvelopeFor (int) const override |
| Tells whether this effect accepts automation envelopes for a particular parameter. | |
| virtual void | setValue (int, double) override |
| Sets DSP value. | |
| void | represent (std::ostream &stream) const override |
| Makes a text representation of this DSP effect for test failure outputs. | |
| std::unique_ptr< DSPBase< SampleType > > | copy () const override |
| Returns a smart pointer with a copy of this object. | |
| size_t | size () const noexcept |
| Returns the number of DSP elements in the sequence. | |
| template<typename DerivedDSP , typename = typename std::enable_if< ! std::is_lvalue_reference<DerivedDSP>::value && std::is_base_of< DSPBase<SampleType>, typename std::decay<DerivedDSP>::type >::value >::type> | |
| void | append (DerivedDSP &&dsp) |
| Appends an element to the end of DSP chain. | |
| void | append (std::unique_ptr< DSPBase< SampleType > > dsp) |
| Appends an element to the end of DSP chain. | |
| DSPBase< SampleType > * | operator[] (long long int index) |
| Accesses a specific element in the DSP sequence (mutable version) | |
| const DSPBase< SampleType > * | operator[] (long long int index) const |
| Accesses a specific element in the DSP sequence (immutable version) | |
| std::unique_ptr< DSPBase< SampleType > > | pop (long long int index=-1) |
| Extracts a specific element in the DSP chain by removing it. | |
Public Member Functions inherited from DSP< SampleType, DSPSequence< SampleType > > | |
| DSPSequence< SampleType > & | withEnvelope (int paramId, Envelope &&envelope) & |
| Adds envelope to a specific parameter by moving it. | |
| DSPSequence< SampleType > && | withEnvelope (int paramId, Envelope &&envelope) && |
| Adds envelope to a specific parameter by moving it. | |
| DSPSequence< SampleType > & | withEnvelope (int paramId, const Envelope &envelope) & |
| Adds envelope to a specific parameter by copying it. | |
| DSPSequence< SampleType > && | withEnvelope (int paramId, const Envelope &envelope) && |
| Adds envelope to a specific parameter by copying it. | |
| virtual std::unique_ptr< DSPBase< SampleType > > | move () override |
| Returns a smart pointer with a moved instance of this object. | |
| DSPSequence< SampleType > & | atChannels (std::initializer_list< size_t > channelsToProcess) & |
| Makes this DSP process only specific channels, and ignore the rest. | |
| DSPSequence< SampleType > && | atChannels (std::initializer_list< size_t > channelsToProcess) && |
| Makes this DSP process only specific channels, and ignore the rest. | |
| DSPSequence< SampleType > & | atChannel (size_t channelToProcess) & |
| Makes this DSP process only specific channels, and bypass the rest. | |
| DSPSequence< SampleType > && | atChannel (size_t channelToProcess) && |
| Makes this DSP process only specific channels, and bypass the rest. | |
| DSPSequence< SampleType > & | atAllChannels () & |
| Makes this DSP apply to all channels. | |
| DSPSequence< SampleType > && | atAllChannels () && |
| Makes this DSP apply to all channels. | |
| DSPSequence< SampleType > & | atAllChannelsExcept (std::initializer_list< size_t > channelsToSkip) & |
| Makes this DSP process only specific channels, and bypass the rest. | |
| DSPSequence< SampleType > && | atAllChannelsExcept (std::initializer_list< size_t > channelsToSkip) && |
| Makes this DSP process only specific channels, and bypass the rest. | |
Public Member Functions inherited from DSPBase< SampleType > | |
| virtual void | reset () |
| Resets to initial state. | |
| virtual double | getValue (int) const |
| Retrieves DSP value. | |
| virtual | ~DSPBase ()=default |
| Destructor. | |
| DSPBase ()=default | |
| Default constructor. | |
| DSPBase (const DSPBase &other) | |
| Copies from another DSP effect instance. | |
| DSPBase (DSPBase &&other) noexcept | |
| Move constructor. | |
| DSPBase & | operator= (const DSPBase &other) |
| Copies from another DSP effect instance. | |
| DSPBase & | operator= (DSPBase &&other) noexcept |
| Move assignment. | |
| bool | hasEnvelopeFor (int paramId) |
| Checks if there's an automation envelope attached to a specific parameter. | |
| 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 | resetWithEnvelopes () |
| Resets the DSP instance, and all associated Envelopes. | |
| ChannelFlags | getChannelsToProcess () |
| Returns a structure indicating which channels should be processed by this DSP. | |
| void | processWithEnvelopes (const AudioBuffer< SampleType > &input, AudioBuffer< SampleType > &output) |
| Renders all the automation envelopes and processes the audio. | |
| void | representWithActiveChannels (std::ostream &stream) const |
| Makes a text representation of this DSP with optional "atChannels" appendix. | |
Additional Inherited Members | |
Protected Attributes inherited from DSPBase< SampleType > | |
| std::unordered_map< int, std::unique_ptr< Envelope > > | m_envelopes |
| ChannelFlags | m_channelsToProcess {true} |
Related Symbols inherited from DSP< SampleType, DSPSequence< SampleType > > | |
| std::ostream & | operator<< (std::ostream &stream, const DSPBase< SampleType > &dsp) |
| Prints readable text representation of the DSP object into the I/O stream. | |
A DSP unit that renders audio through a linear sequence of DSP instances.
It's a container-like DSP subclass that owns a linear chain of other DSP units and applies them one after another. The first DSP in the chain processes the input buffer into the output buffer, while all following DSP units process the output buffer in-place. Nested DSP sequences are fully supported, since DSPSequence itself is a normal DSP subclass. Empty sequences are also valid, and just output silence (zeros).
This class is intended to be constructed via the HART_DSP_SEQUENCE() macro:
but using the ctor directly is also appropriate in some cases, for example, for creating an empty sequence, and then filling it using some loop.
The class also supports runtime mutation:
DSPSequence::atChannel ( {x, y, z} ) at the sequence level - all channels will still be processed regardless. However, using per-channel flags on the individual DSP instances works as it should. HART_DSP_SEQUENCE(), HART_DSP_SEQUENCE_T() Definition at line 49 of file hart_dsp_sequence.hpp.
|
inline |
Creates a sequence of DSP processors.
HART_DSP_SEQUENCE() or HART_DSP_SEQUENCE_T() instead of using this ctor directly, unless you intend to create an empty sequence. | dspChain | A vector with DSP objects. It will be moved into the DSPSequence, along with all DSP instances. |
Definition at line 59 of file hart_dsp_sequence.hpp.
|
overridedefault |
Destructor.
|
delete |
No copy construction.
Copy is still supported, but you have to call copy() method explicitly
|
defaultnoexcept |
|
delete |
No copy assignment.
Copy is still supported, but you have to call copy() method explicitly
|
defaultnoexcept |
|
inlineoverridevirtual |
Prepare for processing.
In real-time DSP, such methods are usually used for allocating memory and other non-realtime-safe and heavyweight operations. But keep in mind that that HART does not do real-time processing, so this merely follows common real-time DSP design conventions, where non-realtime operations are done in a separate callback like this one. This method is guaranteed to be called after supportsChannelLayout() and supportsSampleRate(), but before process(). It is guaranteed that the number of input and output channels obeys supportsChannelLayout() and supportsSampleRate() preferences. It is guaranteed that all subsequent process() calls will be in line with the arguments received in this callback.
| sampleRateHz | sample rate at which the audio should be interpreted and processed |
| numInputChannels | Number of input channels |
| numOutputChannels | Number of output channels |
| maxBlockSizeFrames | Maximum block size in frames (samples) |
Implements DSPBase< SampleType >.
Definition at line 81 of file hart_dsp_sequence.hpp.
|
inlineoverridevirtual |
Processes the audio.
Depending on circumstances, this callback will either be called once to process an entire piece of audio from start to finish, or called repeatedly, one block at a time (see AudioTestBuilder::withBlockSize()). All audio blocks except the last one are guaranteed to be equal to maxBlockSizeFrames set in prepare() callback. It is guaranteed that input and output buffers are equal in length in frames (samples) to each, but they might have different number of channels. Use supportsChannelLayout() to indicate whether the effect supports a specific i/o configuration or not, as it will be called before prepare(). It is guaranteed that envelopeBuffers will only contain the values for all attached envelopes for this instance of DSP effect, and will not contain any data (including key with empty item) if there's no envelope attached to a specific parameter ID in this effects's instance. It will never contain envelopes for IDs that get rejected by supportsEnvelopeFor(). Each vector in the envelopeBuffers map is guaranteed to be at least as large as input (and output) block. For partial blocks, only the first input.getNumFrames() elements contain valid data for the current block; the rest may be stale or uninitialized. DSP implementations are expected to ignore values beyond that index range.
input and output may be references to the same object. | input | Input audio block |
| output | Output audio block |
| envelopeBuffers | Envelope values for this block, see EnvelopeBuffers |
| channelsToProcess | Channels that need processing. Process channels that are marked true, bypass ones marked false. |
Implements DSPBase< SampleType >.
Definition at line 87 of file hart_dsp_sequence.hpp.
|
inlineoverridevirtual |
Tells whether this effect supports given sample rate.
It is guaranteed to be called before prepare()
| sampleRateHz | Sample rate in question |
Reimplemented from DSPBase< SampleType >.
Definition at line 112 of file hart_dsp_sequence.hpp.
|
inlineoverridevirtual |
Tells the runner (host) whether this effect supports a specific i/o configuration.
It is guaranteed that the effect will not receive unsupported number of channels in process(). However, it is not always possible to handle gracefully channel layout being unsupported, so in some circumstances it can cause an exception or a test failure. This method is guaranteed to be called at least once before prepare()
Implements DSPBase< SampleType >.
Definition at line 121 of file hart_dsp_sequence.hpp.
|
inlineoverridevirtual |
Tells whether this effect accepts automation envelopes for a particular parameter.
| paramId | Some ID that your subclass understands |
Reimplemented from DSPBase< SampleType >.
Definition at line 130 of file hart_dsp_sequence.hpp.
|
inlineoverridevirtual |
Sets DSP value.
| paramId | Some ID that your subclass understands; use of enums is encouraged for readability |
| value | Value of the param in an appropriate unit; use of SI units is encouraged (i.e. s instead of ms. Hz instead of kHz) to make better use of unit literals (see Units) |
envelopeBuffers provided in process() callback. Implements DSPBase< SampleType >.
Definition at line 131 of file hart_dsp_sequence.hpp.
|
inlineoverridevirtual |
Makes a text representation of this DSP effect for test failure outputs.
It is strongly encouraged to follow python's repr() conventions for returned text - basically, put something like "MyClass(value1, value2)" (with no quotes) into the stream whenever possible, or "<Readable info in angled brackets>" otherwise. Also, use built-in stream manipulators like dbPrecision wherever applicable. Use HART_DEFINE_GENERIC_REPRESENT() to get a basic implementation for this method.
| [out] | stream | Output stream to write to |
Implements DSPBase< SampleType >.
Definition at line 133 of file hart_dsp_sequence.hpp.
|
inlineoverridevirtual |
Returns a smart pointer with a copy of this object.
Reimplemented from DSPBase< SampleType >.
Definition at line 148 of file hart_dsp_sequence.hpp.
|
inlinenoexcept |
Returns the number of DSP elements in the sequence.
Definition at line 170 of file hart_dsp_sequence.hpp.
|
inline |
Appends an element to the end of DSP chain.
The element will be owned by the DSPSequence. You can get it back by using pop() method, or peek by using square brackets [] operator.
Definition at line 187 of file hart_dsp_sequence.hpp.
|
inline |
Appends an element to the end of DSP chain.
The smart pointer will be owned by the DSPSequence. You can get it back by using pop() method, or peek by using square brackets [] operator.
| dsp | Smart pointer with a DSP element ot be appended |
Definition at line 196 of file hart_dsp_sequence.hpp.
|
inline |
Accesses a specific element in the DSP sequence (mutable version)
| index | Index of the element. Can be negative. For non-negative values, it's a usual 0-based index. For negative values, it's counted from the end, e.g. "-1" is the last element, "-2" is the second to last etc. |
| hart::IndexError | if the index is out of range |
Definition at line 209 of file hart_dsp_sequence.hpp.
|
inline |
Accesses a specific element in the DSP sequence (immutable version)
| index | Index of the element. Can be negative. For non-negative values, it's a usual 0-based index. For negative values, it's counted from the end, e.g. "-1" is the last element, "-2" is the second to last etc. |
| hart::IndexError | if the index is out of range |
Definition at line 219 of file hart_dsp_sequence.hpp.
|
inline |
Extracts a specific element in the DSP chain by removing it.
| index | Index of the element. Can be negative. For non-negative values, it's a usual 0-based index. For negative values, it's counted from the end, e.g. "-1" is the last element, "-2" is the second to last etc. |
| hart::IndexError | if the index is out of range |
Definition at line 229 of file hart_dsp_sequence.hpp.