Loading...
Searching...
No Matches
juce_ProcessorChain_test.cpp
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce::dsp
{
class ProcessorChainTest final : public UnitTest
{
template <int AddValue>
struct MockProcessor
{
void prepare (const ProcessSpec&) noexcept { isPrepared = true; }
void reset() noexcept { isReset = true; }
template <typename Context>
void process (const Context& context) noexcept
{
bufferWasClear = approximatelyEqual (context.getInputBlock().getSample (0, 0), 0.0f);
if (! context.isBypassed)
context.getOutputBlock().add (AddValue);
}
bool isPrepared = false;
bool isReset = false;
bool bufferWasClear = false;
};
public:
ProcessorChainTest()
: UnitTest ("ProcessorChain", UnitTestCategories::dsp) {}
void runTest() override
{
beginTest ("After calling setBypass, processor is bypassed");
{
ProcessorChain<MockProcessor<1>, MockProcessor<2>> chain;
setBypassed<0> (chain, true);
expect (isBypassed<0> (chain));
setBypassed<0> (chain, false);
expect (! isBypassed<0> (chain));
setBypassed<1> (chain, true);
expect (isBypassed<1> (chain));
setBypassed<1> (chain, false);
expect (! isBypassed<1> (chain));
}
beginTest ("After calling prepare, all processors are prepared");
{
ProcessorChain<MockProcessor<1>, MockProcessor<2>> chain;
expect (! get<0> (chain).isPrepared);
expect (! get<1> (chain).isPrepared);
chain.prepare (ProcessSpec{});
expect (get<0> (chain).isPrepared);
expect (get<1> (chain).isPrepared);
}
beginTest ("After calling reset, all processors are reset");
{
ProcessorChain<MockProcessor<1>, MockProcessor<2>> chain;
expect (! get<0> (chain).isReset);
expect (! get<1> (chain).isReset);
chain.reset();
expect (get<0> (chain).isReset);
expect (get<1> (chain).isReset);
}
beginTest ("After calling process, all processors contribute to processing");
{
ProcessorChain<MockProcessor<1>, MockProcessor<2>> chain;
AudioBuffer<float> buffer (1, 1);
AudioBlock<float> block (buffer);
ProcessContextReplacing<float> context (block);
block.clear();
chain.process (context);
expectEquals (buffer.getSample (0, 0), 3.0f);
expect (get<0> (chain).bufferWasClear);
expect (! get<1> (chain).bufferWasClear);
setBypassed<0> (chain, true);
block.clear();
chain.process (context);
expectEquals (buffer.getSample (0, 0), 2.0f);
expect (get<0> (chain).bufferWasClear);
expect (get<1> (chain).bufferWasClear);
setBypassed<1> (chain, true);
block.clear();
chain.process (context);
expectEquals (buffer.getSample (0, 0), 0.0f);
expect (get<0> (chain).bufferWasClear);
expect (get<1> (chain).bufferWasClear);
setBypassed<0> (chain, false);
block.clear();
chain.process (context);
expectEquals (buffer.getSample (0, 0), 1.0f);
expect (get<0> (chain).bufferWasClear);
expect (! get<1> (chain).bufferWasClear);
}
beginTest ("Chains with trailing items that only support replacing contexts can be built");
{
AudioBuffer<float> inBuf (1, 1), outBuf (1, 1);
juce::dsp::AudioBlock<float> in (inBuf), out (outBuf);
struct OnlyReplacing
{
void prepare (const juce::dsp::ProcessSpec&) {}
void process (const juce::dsp::ProcessContextReplacing<float>& c)
{
c.getOutputBlock().multiplyBy (2.0f);
}
void reset() {}
};
{
juce::dsp::ProcessorChain<juce::dsp::Gain<float>, OnlyReplacing, OnlyReplacing> c;
juce::dsp::ProcessContextNonReplacing<float> context (in, out);
get<0> (c).setGainLinear (1.0f);
c.prepare (ProcessSpec{});
inBuf.setSample (0, 0, 1.0f);
c.process (context);
expectEquals (outBuf.getSample (0, 0), 4.0f);
}
}
}
};
static ProcessorChainTest processorChainUnitTest;
} // namespace juce::dsp
juce::UnitTest::expectEquals
void expectEquals(ValueType actual, ValueType expected, String failureMessage=String())
Definition juce_UnitTest.h:151
juce::UnitTest::UnitTest
UnitTest(const String &name, const String &category=String())
Definition juce_UnitTest.cpp:26
juce::UnitTest::beginTest
void beginTest(const String &testName)
Definition juce_UnitTest.cpp:89
juce::UnitTest::expect
void expect(bool testResult, const String &failureMessage=String())
Definition juce_UnitTest.cpp:97
juce::UnitTest::runTest
virtual void runTest()=0
juce::dsp::AudioBlock::multiplyBy
AudioBlock &JUCE_VECTOR_CALLTYPE multiplyBy(NumericType value) noexcept
Definition juce_AudioBlock.h:440
juce::dsp::ProcessorChain::prepare
void prepare(const ProcessSpec &spec)
Definition juce_ProcessorChain.h:80
juce::dsp::ProcessorChain::process
void process(const ProcessContext &context) noexcept
Definition juce_ProcessorChain.h:93
juce::dsp::ProcessContextReplacing::getOutputBlock
AudioBlockType & getOutputBlock() const noexcept
Definition juce_ProcessContext.h:109