30template <
typename SampleType>
36template <
typename SampleType>
41 dryDelayLine.setDelay (0);
48template <
typename SampleType>
55template <
typename SampleType>
64template <
typename SampleType>
71template <
typename SampleType>
77 sampleRate =
spec.sampleRate;
79 dryDelayLine.prepare (
spec);
80 bufferDry.setSize ((
int)
spec.numChannels, (
int)
spec.maximumBlockSize,
false,
false,
true);
86template <
typename SampleType>
89 dryVolume.reset (sampleRate, 0.05);
90 wetVolume.reset (sampleRate, 0.05);
95 bufferDry.setSize (bufferDry.getNumChannels(), fifo.getSize(),
false,
false,
true);
99template <
typename SampleType>
107 for (
const auto& range : fifo.write ((
int)
drySamples.getNumSamples()))
109 if (range.getLength() == 0)
113 .getSubBlock ((
size_t) range.getStart(), (
size_t) range.getLength());
115 auto inputBlock =
drySamples.getSubBlock ((
size_t) offset, (
size_t) range.getLength());
117 if (maximumWetLatencyInSamples == 0)
118 block.copyFrom (inputBlock);
122 offset += range.getLength();
126template <
typename SampleType>
135 for (
const auto& range : fifo.read ((
int)
inOutBlock.getNumSamples()))
137 if (range.getLength() == 0)
141 .getSubBlock ((
size_t) range.getStart(), (
size_t) range.getLength());
142 block.multiplyBy (dryVolume);
145 offset += range.getLength();
150template <
typename SampleType>
155 switch (currentMixingRule)
157 case MixingRule::balanced:
158 dryValue =
static_cast<SampleType
> (2.0) *
jmin (
static_cast<SampleType
> (0.5),
static_cast<SampleType
> (1.0) - mix);
159 wetValue =
static_cast<SampleType
> (2.0) *
jmin (
static_cast<SampleType
> (0.5), mix);
162 case MixingRule::linear:
163 dryValue =
static_cast<SampleType
> (1.0) - mix;
167 case MixingRule::sin3dB:
172 case MixingRule::sin4p5dB:
177 case MixingRule::sin6dB:
182 case MixingRule::squareRoot3dB:
187 case MixingRule::squareRoot4p5dB:
193 dryValue =
jmin (
static_cast<SampleType
> (0.5),
static_cast<SampleType
> (1.0) - mix);
198 dryVolume.setTargetValue (
dryValue);
199 wetVolume.setTargetValue (
wetValue);
215 enum class Kind {
down,
up };
219 AudioBuffer<float> buffer ((
int)
spec.numChannels, (
int)
spec.maximumBlockSize);
223 for (uint32_t channel = 0; channel <
spec.numChannels; ++channel)
227 buffer.setSample ((
int) channel,
229 jmap ((
float)
ramp, 0.0f, (
float)
spec.maximumBlockSize, 0.0f, 1.0f));
236 void runTest()
override
238 constexpr ProcessSpec
spec { 44100.0, 512, 2 };
239 constexpr auto numBlocks = 5;
246 beginTest (
"Mixer can push multiple small buffers");
249 mixer.setWetMixProportion (0.5f);
250 mixer.prepare (
spec);
260 mixer.mixWetSamples ({ outputBlock });
265 for (uint32_t channel = 0; channel <
spec.numChannels; ++channel)
267 const auto outputValue = outputBlock.getSample ((
int) channel, (
int) sample);
268 expectWithinAbsoluteError (
outputValue, 0.5f, 0.0001f);
274 beginTest (
"Mixer can pop multiple small buffers");
277 mixer.setWetMixProportion (0.5f);
278 mixer.prepare (
spec);
288 AudioBuffer<float> outputBlock ((
int)
spec.numChannels, 1);
290 mixer.mixWetSamples ({ outputBlock });
293 for (uint32_t channel = 0; channel <
spec.numChannels; ++channel)
295 const auto outputValue = outputBlock.getSample ((
int) channel, 0);
296 expectWithinAbsoluteError (
outputValue, 0.5f, 0.0001f);
302 beginTest (
"Mixer can push and pop multiple small buffers");
305 mixer.setWetMixProportion (0.5f);
306 mixer.prepare (
spec);
315 AudioBuffer<float> outputBlock ((
int)
spec.numChannels, 1);
317 mixer.mixWetSamples ({ outputBlock });
320 for (uint32_t channel = 0; channel <
spec.numChannels; ++channel)
322 const auto outputValue = outputBlock.getSample ((
int) channel, 0);
323 expectWithinAbsoluteError (
outputValue, 0.5f, 0.0001f);
329 beginTest (
"Mixer can push and pop full-sized blocks after encountering a shorter block");
332 mixer.setWetMixProportion (0.5f);
333 mixer.prepare (
spec);
347 mixer.mixWetSamples ({ outputBlock });
352 for (uint32_t channel = 0; channel <
spec.numChannels; ++channel)
354 const auto outputValue = outputBlock.getSample ((
int) channel, (
int) sample);
355 expectWithinAbsoluteError (
outputValue, 0.5f, 0.0001f);
Encapsulates the logic for a single-threaded FIFO.
Minimal and lightweight data-structure which contains a list of pointers to channels containing some ...
A processor to handle dry/wet mixing of two audio signals, where the wet signal may have additional l...
void pushDrySamples(const AudioBlock< const SampleType > drySamples)
Copies the dry path samples into an internal delay line.
void setWetMixProportion(SampleType newWetMixProportion)
Sets the current dry/wet mix proportion, with 0.0 being full dry and 1.0 being fully wet.
void reset()
Resets the internal state variables of the processor.
void setMixingRule(MixingRule newRule)
Sets the mix rule.
void setWetLatency(SampleType wetLatencyInSamples)
Sets the relative latency of the wet signal path compared to the dry signal path, and thus the amount...
void prepare(const ProcessSpec &spec)
Initialises the processor.
void mixWetSamples(AudioBlock< SampleType > wetSamples)
Mixes the supplied wet samples with the latency-compensated dry samples from pushDrySamples.
DryWetMixer()
Default constructor.
constexpr Type jmap(Type value0To1, Type targetRangeMin, Type targetRangeMax)
Remaps a normalised value (between 0 and 1) to a target range.
constexpr Type jmin(Type a, Type b)
Returns the smaller of two values.
Type jlimit(Type lowerLimit, Type upperLimit, Type valueToConstrain) noexcept
Constrains a value to keep it within a given range.
int nextPowerOfTwo(int n) noexcept
Returns the smallest power-of-two which is equal to or greater than the given integer.
Type unalignedPointerCast(void *ptr) noexcept
Casts a pointer to another type via void*, which suppresses the cast-align warning which sometimes ar...
bool isPositiveAndNotGreaterThan(Type1 valueToTest, Type2 upperLimit) noexcept
Returns true if a value is at least zero, and also less than or equal to a specified upper limit.
Commonly used mathematical constants.
Contains context information that is passed into an algorithm's process method.
This structure is passed into a DSP algorithm's prepare() method, and contains information about vari...