32template <
typename SampleType>
38template <
typename SampleType>
50template <
typename SampleType>
57template <
typename SampleType>
62 mix =
jlimit (
static_cast<SampleType
> (0.0),
static_cast<SampleType
> (1.0), newWetMixProportion);
66template <
typename SampleType>
73template <
typename SampleType>
88template <
typename SampleType>
101template <
typename SampleType>
111 if (range.getLength() == 0)
115 .
getSubBlock ((
size_t) range.getStart(), (
size_t) range.getLength());
117 auto inputBlock = drySamples.
getSubBlock ((
size_t) offset, (
size_t) range.getLength());
124 offset += range.getLength();
128template <
typename SampleType>
139 if (range.getLength() == 0)
143 .
getSubBlock ((
size_t) range.getStart(), (
size_t) range.getLength());
147 offset += range.getLength();
152template <
typename SampleType>
155 SampleType dryValue, wetValue;
159 case MixingRule::balanced:
160 dryValue =
static_cast<SampleType
> (2.0) *
jmin (
static_cast<SampleType
> (0.5),
static_cast<SampleType
> (1.0) -
mix);
161 wetValue =
static_cast<SampleType
> (2.0) *
jmin (
static_cast<SampleType
> (0.5),
mix);
164 case MixingRule::linear:
165 dryValue =
static_cast<SampleType
> (1.0) -
mix;
169 case MixingRule::sin3dB:
174 case MixingRule::sin4p5dB:
179 case MixingRule::sin6dB:
184 case MixingRule::squareRoot3dB:
185 dryValue = std::sqrt (
static_cast<SampleType
> (1.0) -
mix);
186 wetValue = std::sqrt (
mix);
189 case MixingRule::squareRoot4p5dB:
190 dryValue =
static_cast<SampleType
> (std::pow (std::sqrt (1.0 -
mix), 1.5));
191 wetValue =
static_cast<SampleType
> (std::pow (std::sqrt (
mix), 1.5));
195 dryValue =
jmin (
static_cast<SampleType
> (0.5),
static_cast<SampleType
> (1.0) -
mix);
196 wetValue =
jmin (
static_cast<SampleType
> (0.5),
mix);
213struct DryWetMixerTests :
public UnitTest
217 enum class Kind { down, up };
219 static auto getRampBuffer (ProcessSpec spec, Kind kind)
221 AudioBuffer<float> buffer ((
int) spec.numChannels, (
int) spec.maximumBlockSize);
225 for (
uint32_t channel = 0; channel < spec.numChannels; ++channel)
227 const auto ramp = kind == Kind::up ?
sample : spec.maximumBlockSize -
sample;
229 buffer.setSample ((
int) channel,
231 jmap ((
float) ramp, 0.0f, (
float) spec.maximumBlockSize, 0.0f, 1.0f));
238 void runTest()
override
240 constexpr ProcessSpec spec { 44100.0, 512, 2 };
241 constexpr auto numBlocks = 5;
243 const auto wetBuffer = getRampBuffer (spec, Kind::up);
244 const auto dryBuffer = getRampBuffer (spec, Kind::down);
246 for (
auto maxLatency : { 0, 100, 200, 512 })
248 beginTest (
"Mixer can push multiple small buffers");
250 DryWetMixer<float> mixer (maxLatency);
251 mixer.setWetMixProportion (0.5f);
252 mixer.prepare (spec);
254 for (
auto block = 0; block < numBlocks; ++block)
258 mixer.pushDrySamples (AudioBlock<const float> (dryBuffer).getSubBlock (
sample, 1));
261 auto outputBlock = wetBuffer;
262 mixer.mixWetSamples ({ outputBlock });
267 for (
uint32_t channel = 0; channel < spec.numChannels; ++channel)
269 const auto outputValue = outputBlock.getSample ((
int) channel, (
int)
sample);
270 expectWithinAbsoluteError (outputValue, 0.5f, 0.0001f);
276 beginTest (
"Mixer can pop multiple small buffers");
278 DryWetMixer<float> mixer (maxLatency);
279 mixer.setWetMixProportion (0.5f);
280 mixer.prepare (spec);
282 for (
auto block = 0; block < numBlocks; ++block)
285 mixer.pushDrySamples ({ dryBuffer });
290 AudioBuffer<float> outputBlock ((
int) spec.numChannels, 1);
291 AudioBlock<const float> (wetBuffer).getSubBlock (
sample, 1).copyTo (outputBlock);
292 mixer.mixWetSamples ({ outputBlock });
295 for (
uint32_t channel = 0; channel < spec.numChannels; ++channel)
297 const auto outputValue = outputBlock.getSample ((
int) channel, 0);
298 expectWithinAbsoluteError (outputValue, 0.5f, 0.0001f);
304 beginTest (
"Mixer can push and pop multiple small buffers");
306 DryWetMixer<float> mixer (maxLatency);
307 mixer.setWetMixProportion (0.5f);
308 mixer.prepare (spec);
310 for (
auto block = 0; block < numBlocks; ++block)
315 mixer.pushDrySamples (AudioBlock<const float> (dryBuffer).getSubBlock (
sample, 1));
317 AudioBuffer<float> outputBlock ((
int) spec.numChannels, 1);
318 AudioBlock<const float> (wetBuffer).getSubBlock (
sample, 1).copyTo (outputBlock);
319 mixer.mixWetSamples ({ outputBlock });
322 for (
uint32_t channel = 0; channel < spec.numChannels; ++channel)
324 const auto outputValue = outputBlock.getSample ((
int) channel, 0);
325 expectWithinAbsoluteError (outputValue, 0.5f, 0.0001f);
331 beginTest (
"Mixer can push and pop full-sized blocks after encountering a shorter block");
333 DryWetMixer<float> mixer (maxLatency);
334 mixer.setWetMixProportion (0.5f);
335 mixer.prepare (spec);
337 constexpr auto shortBlockLength = spec.maximumBlockSize / 2;
338 AudioBuffer<float> shortBlock (spec.numChannels, shortBlockLength);
339 mixer.pushDrySamples (AudioBlock<const float> (dryBuffer).getSubBlock (shortBlockLength));
340 mixer.mixWetSamples ({ shortBlock });
342 for (
auto block = 0; block < numBlocks; ++block)
345 mixer.pushDrySamples ({ dryBuffer });
348 auto outputBlock = wetBuffer;
349 mixer.mixWetSamples ({ outputBlock });
354 for (
uint32_t channel = 0; channel < spec.numChannels; ++channel)
356 const auto outputValue = outputBlock.getSample ((
int) channel, (
int)
sample);
357 expectWithinAbsoluteError (outputValue, 0.5f, 0.0001f);
366static const DryWetMixerTests dryWetMixerTests;
Type jmin(const Type a, const Type b)
Definition MathsFunctions.h:60
Definition juce_SingleThreadedAbstractFifo.h:64
Definition juce_UnitTest.h:70
Definition juce_AudioBlock.h:70
AudioBlock getSubBlock(size_t newOffset, size_t newLength) const noexcept
Definition juce_AudioBlock.h:371
AudioBlock getSubsetChannelBlock(size_t channelStart, size_t numChannelsToUse) const noexcept
Definition juce_AudioBlock.h:259
constexpr size_t getNumChannels() const noexcept
Definition juce_AudioBlock.h:235
AudioBlock &JUCE_VECTOR_CALLTYPE multiplyBy(NumericType value) noexcept
Definition juce_AudioBlock.h:442
AudioBlock &JUCE_VECTOR_CALLTYPE add(NumericType value) noexcept
Definition juce_AudioBlock.h:396
AudioBlock & copyFrom(const AudioBlock< OtherSampleType > &src) noexcept
Definition juce_AudioBlock.h:314
constexpr size_t getNumSamples() const noexcept
Definition juce_AudioBlock.h:238
Definition juce_DryWetMixer.h:54
void pushDrySamples(const AudioBlock< const SampleType > drySamples)
Definition juce_DryWetMixer.cpp:102
SmoothedValue< SampleType, ValueSmoothingTypes::Linear > wetVolume
Definition juce_DryWetMixer.h:108
int maximumWetLatencyInSamples
Definition juce_DryWetMixer.h:116
void setWetMixProportion(SampleType newWetMixProportion)
Definition juce_DryWetMixer.cpp:58
void reset()
Definition juce_DryWetMixer.cpp:89
double sampleRate
Definition juce_DryWetMixer.h:115
AudioBuffer< SampleType > bufferDry
Definition juce_DryWetMixer.h:110
DelayLine< SampleType, DelayLineInterpolationTypes::Thiran > dryDelayLine
Definition juce_DryWetMixer.h:109
MixingRule currentMixingRule
Definition juce_DryWetMixer.h:114
SampleType mix
Definition juce_DryWetMixer.h:113
SingleThreadedAbstractFifo fifo
Definition juce_DryWetMixer.h:112
void setMixingRule(MixingRule newRule)
Definition juce_DryWetMixer.cpp:51
void setWetLatency(SampleType wetLatencyInSamples)
Definition juce_DryWetMixer.cpp:67
void prepare(const ProcessSpec &spec)
Definition juce_DryWetMixer.cpp:74
DryWetMixingRule MixingRule
Definition juce_DryWetMixer.h:57
SmoothedValue< SampleType, ValueSmoothingTypes::Linear > dryVolume
Definition juce_DryWetMixer.h:108
void update()
Definition juce_DryWetMixer.cpp:153
void mixWetSamples(AudioBlock< SampleType > wetSamples)
Definition juce_DryWetMixer.cpp:129
DryWetMixer()
Definition juce_DryWetMixer.cpp:33
unsigned int uint32_t
Definition mid.cpp:100
Definition juce_UnitTestCategories.h:27
Definition juce_AudioBlock.h:29
JOCTET * buffer
Definition juce_JPEGLoader.cpp:302
Definition carla_juce.cpp:31
constexpr Type jmin(Type a, Type b)
Definition juce_MathsFunctions.h:106
Type jlimit(Type lowerLimit, Type upperLimit, Type valueToConstrain) noexcept
Definition juce_MathsFunctions.h:262
int nextPowerOfTwo(int n) noexcept
Definition juce_MathsFunctions.h:533
bool isPositiveAndNotGreaterThan(Type1 valueToTest, Type2 upperLimit) noexcept
Definition juce_MathsFunctions.h:298
static constexpr FloatType pi
Definition juce_MathsFunctions.h:382
Definition juce_ProcessContext.h:141
Definition juce_ProcessContext.h:38
uint32 numChannels
Definition juce_ProcessContext.h:46
double sampleRate
Definition juce_ProcessContext.h:40
uint32 maximumBlockSize
Definition juce_ProcessContext.h:43
signed int sample
Definition tap_dynamics_m.c:41