HART  0.1.0
High level Audio Regression and Testing
Loading...
Searching...
No Matches
hart_gainlinear.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <algorithm> // fill()
4#include <iomanip>
5#include <vector>
6
7#include "hart_dsp.hpp"
9
10namespace hart
11{
12
13/// @brief Applies linear gain (not decibels) to the signal
14/// @details To set gain in decibels, consider using @ref GainDb class instead
15/// @ingroup DSP
16template <typename SampleType>
18 public hart::DSP<SampleType>
19{
20public:
21 enum Params
22 {
23 gainLinear ///< Linear gain
24 };
25
26 /// @brief Constructor
27 /// @param initialGainLinear Linear gain
28 GainLinear (double initialGainLinear = 1.0):
29 m_initialGainLinear (initialGainLinear),
30 m_gainLinear (initialGainLinear)
31 {
32 }
33
34 void prepare (double /* sampleRateHz */, size_t /* numInputChannels */, size_t /* numOutputChannels */, size_t /* maxBlockSizeFrames */) override {}
35
36 void process (const AudioBuffer<SampleType>& input, AudioBuffer<SampleType>& output, const EnvelopeBuffers& envelopeBuffers) override
37 {
38 const size_t numInputChannels = input.getNumChannels();
39 const size_t numOutputChannels = output.getNumChannels();
40 hassert (output.getNumFrames() == input.getNumFrames());
41
42 if (! supportsChannelLayout (numInputChannels, numOutputChannels))
43 HART_THROW_OR_RETURN_VOID (hart::ChannelLayoutError, "Unsupported channel configuration");
44
45 const bool hasGainEnvelope = ! envelopeBuffers.empty() && contains (envelopeBuffers, (int) Params::gainLinear);
46 const bool multiplexerMode = numInputChannels != numOutputChannels;
47
48 if (hasGainEnvelope)
49 {
50 if (multiplexerMode)
51 processEnvelopedGainAsMultiplexer (input, output, envelopeBuffers.at (GainLinear::gainLinear));
52 else
53 processEnvelopedGainAsMultiChannel (input, output, envelopeBuffers.at (GainLinear::gainLinear));
54
55 return;
56 }
57
58 // No gain envelope
59 if (multiplexerMode)
60 processConstantGainAsMultiplexer (input, output);
61 else
62 processConstantGainAsMultiChannel (input, output);
63 }
64
65 void reset() override {}
66
67 /// @param id Only @ref GainLinear::gainLinear is accepted
68 /// @param value linear gain
69 void setValue (int id, double value) override
70 {
71 if (id == Params::gainLinear)
72 m_gainLinear = value;
73 }
74
75 /// @param id Only @ref GainLinear::gainLinear is accepted
76 /// @return linear gain
77 double getValue (int id) const override
78 {
79 if (id == Params::gainLinear)
80 return m_gainLinear;
81
82 return 0.0;
83 }
84
85 /// @details Supports either 1-to-n or n-to-n configurations
86 virtual bool supportsChannelLayout (size_t numInputChannels, size_t numOutputChannels) const override
87 {
88 if (numInputChannels == numOutputChannels)
89 return true;
90
91 if (numInputChannels == 1)
92 return true;
93
94 return false;
95 }
96
97 virtual void represent (std::ostream& stream) const override
98 {
99 stream << dbPrecision << "GainLinear (" << m_initialGainLinear << ")";
100 }
101
102 /// @param id Only @ref GainLinear::gainLinear is accepted
103 /// return true for GainLinear::gainLinear, else otherwise
104 bool supportsEnvelopeFor (int id) const override
105 {
106 return id == Params::gainLinear;
107 }
108
110
111private:
112 double m_initialGainLinear;
113 double m_gainLinear;
114
115 void processConstantGainAsMultiChannel (const AudioBuffer<SampleType>& input, AudioBuffer<SampleType>& output)
116 {
117 for (size_t channel = 0; channel < input.getNumChannels(); ++channel)
118 for (size_t frame = 0; frame < input.getNumFrames(); ++frame)
119 output[channel][frame] = input[channel][frame] * (SampleType) m_gainLinear;
120 }
121
122 void processConstantGainAsMultiplexer (const AudioBuffer<SampleType>& input, AudioBuffer<SampleType>& output)
123 {
124 for (size_t channel = 0; channel < output.getNumChannels(); ++channel)
125 for (size_t frame = 0; frame < input.getNumFrames(); ++frame)
126 output[channel][frame] = input[0][frame] * (SampleType) m_gainLinear;
127 }
128
129 void processEnvelopedGainAsMultiChannel (const AudioBuffer<SampleType>& input, AudioBuffer<SampleType>& output, const std::vector<double>& gainEnvelopeValues)
130 {
131 for (size_t channel = 0; channel < input.getNumChannels(); ++channel)
132 for (size_t frame = 0; frame < input.getNumFrames(); ++frame)
133 output[channel][frame] = input[channel][frame] * (SampleType) gainEnvelopeValues[frame];
134 }
135
136 void processEnvelopedGainAsMultiplexer (const AudioBuffer<SampleType>& input, AudioBuffer<SampleType>& output, const std::vector<double>& gainEnvelopeValues)
137 {
138 for (size_t channel = 0; channel < output.getNumChannels(); ++channel)
139 for (size_t frame = 0; frame < input.getNumFrames(); ++frame)
140 output[channel][frame] = input[0][frame] * (SampleType) gainEnvelopeValues[frame];
141 }
142};
143
145
146} // namespace hart
Base for DSP effects.
Definition hart_dsp.hpp:34
Applies linear gain (not decibels) to the signal.
virtual bool supportsChannelLayout(size_t numInputChannels, size_t numOutputChannels) const override
void prepare(double, size_t, size_t, size_t) override
Prepare for processing.
double getValue(int id) const override
void process(const AudioBuffer< SampleType > &input, AudioBuffer< SampleType > &output, const EnvelopeBuffers &envelopeBuffers) override
Processes the audio.
@ gainLinear
Linear gain.
virtual void represent(std::ostream &stream) const override
Makes a text representation of this DSP effect for test failure outputs.
void setValue(int id, double value) override
bool supportsEnvelopeFor(int id) const override
void reset() override
Resets to initial state.
GainLinear(double initialGainLinear=1.0)
Constructor.
#define HART_DSP_DEFINE_COPY_AND_MOVE(ClassName)
Defines hart::DSP::copy() and hart::DSP::move() methods.
Definition hart_dsp.hpp:334
std::ostream & dbPrecision(std::ostream &stream)
Sets number of decimal places for values in decibels.
static bool contains(const std::unordered_map< KeyType, ValueType > &map, const KeyType &key)
std::unordered_map::contains() replacement for C++11
#define HART_DSP_DECLARE_ALIASES_FOR(ClassName)
Definition hart_dsp.hpp:370
#define HART_THROW_OR_RETURN_VOID(ExceptionType, message)
#define hassert(condition)