29class FIRFilterTest final :
public UnitTest
31 template <
typename Type>
34 static void fillRandom (Random& random, Type* buffer,
size_t n)
36 for (
size_t i = 0; i < n; ++i)
37 buffer[i] = (2.0f * random.nextFloat()) - 1.0f;
40 static bool checkArrayIsSimilar (Type* a, Type* b,
size_t n)
noexcept
42 for (
size_t i = 0; i < n; ++i)
43 if (std::abs (a[i] - b[i]) > 1e-6f)
51 template <
typename Type>
52 struct Helpers<SIMDRegister<Type>>
54 static void fillRandom (Random& random, SIMDRegister<Type>* buffer,
size_t n)
59 static bool checkArrayIsSimilar (SIMDRegister<Type>* a, SIMDRegister<Type>* b,
size_t n)
noexcept
61 return Helpers<Type>::checkArrayIsSimilar (
reinterpret_cast<Type*
> (a),
62 reinterpret_cast<Type*
> (b),
68 template <
typename Type>
69 static void fillRandom (Random& random, Type* buffer,
size_t n) { Helpers<Type>::fillRandom (random, buffer, n); }
71 template <
typename Type>
72 static bool checkArrayIsSimilar (Type* a, Type* b,
size_t n)
noexcept {
return Helpers<Type>::checkArrayIsSimilar (a, b, n); }
76 template <
typename SampleType,
typename NumericType>
77 static void reference (
const NumericType* firCoefficients,
size_t numCoefficients,
78 const SampleType* input, SampleType* output,
size_t n)
noexcept
80 if (numCoefficients == 0)
82 zeromem (output,
sizeof (SampleType) * n);
86 HeapBlock<SampleType> scratchBuffer (numCoefficients
94 SampleType* buffer = scratchBuffer.getData();
97 zeromem (buffer,
sizeof (SampleType) * numCoefficients);
99 for (
size_t i = 0; i < n; ++i)
101 for (
size_t j = (numCoefficients - 1); j >= 1; --j)
102 buffer[j] = buffer[j-1];
104 buffer[0] = input[i];
108 for (
size_t j = 0; j < numCoefficients; ++j)
109 sum += buffer[j] * firCoefficients[j];
116 struct LargeBlockTest
118 template <
typename FloatType>
119 static void run (FIR::Filter<FloatType>& filter, FloatType* src, FloatType* dst,
size_t n)
121 AudioBlock<const FloatType> input (&src, 1, n);
122 AudioBlock<FloatType> output (&dst, 1, n);
123 ProcessContextNonReplacing<FloatType> context (input, output);
125 filter.process (context);
129 struct SampleBySampleTest
131 template <
typename FloatType>
132 static void run (FIR::Filter<FloatType>& filter, FloatType* src, FloatType* dst,
size_t n)
134 for (
size_t i = 0; i < n; ++i)
135 dst[i] = filter.processSample (src[i]);
139 struct SplitBlockTest
141 template <
typename FloatType>
142 static void run (FIR::Filter<FloatType>& filter, FloatType* input, FloatType* output,
size_t n)
145 for (
size_t i = 0; i < n; i += len)
147 len = jmin (n - i, n / 3);
148 auto* src = input + i;
149 auto* dst = output + i;
151 AudioBlock<const FloatType> inBlock (&src, 1, len);
152 AudioBlock<FloatType> outBlock (&dst, 1, len);
153 ProcessContextNonReplacing<FloatType> context (inBlock, outBlock);
155 filter.process (context);
161 template <
typename TheTest,
typename SampleType,
typename NumericType>
162 void runTestForType()
164 Random random (8392829);
166 for (
auto size : {1, 2, 4, 8, 12, 13, 25})
168 constexpr size_t n = 813;
170 HeapBlock<char> inputBuffer, outputBuffer, refBuffer;
171 AudioBlock<SampleType> input (inputBuffer, 1, n), output (outputBuffer, 1, n), ref (refBuffer, 1, n);
172 fillRandom (random, input.getChannelPointer (0), n);
174 HeapBlock<char> firBlock;
175 AudioBlock<NumericType> fir (firBlock, 1,
static_cast<size_t> (size));
176 fillRandom (random, fir.getChannelPointer (0),
static_cast<size_t> (size));
178 FIR::Filter<SampleType> filter (*
new FIR::Coefficients<NumericType> (fir.getChannelPointer (0),
static_cast<size_t> (size)));
179 ProcessSpec spec {0.0, n, 1};
180 filter.prepare (spec);
182 reference<SampleType, NumericType> (fir.getChannelPointer (0),
static_cast<size_t> (size),
183 input.getChannelPointer (0), ref.getChannelPointer (0), n);
185 TheTest::template run<SampleType> (filter, input.getChannelPointer (0), output.getChannelPointer (0), n);
186 expect (checkArrayIsSimilar (output.getChannelPointer (0), ref.getChannelPointer (0), n));
190 template <
typename TheTest>
191 void runTestForAllTypes (
const char* unitTestName)
195 runTestForType<TheTest, float, float>();
196 runTestForType<TheTest, double, double>();
198 runTestForType<TheTest, SIMDRegister<float>,
float>();
199 runTestForType<TheTest, SIMDRegister<double>,
double>();
206 :
UnitTest (
"FIR Filter", UnitTestCategories::dsp)
211 runTestForAllTypes<LargeBlockTest> (
"Large Blocks");
212 runTestForAllTypes<SampleBySampleTest> (
"Sample by Sample");
213 runTestForAllTypes<SplitBlockTest> (
"Split Block");
217static FIRFilterTest firFilterUnitTest;
UnitTest(const String &name, const String &category=String())
void beginTest(const String &testName)
void expect(bool testResult, const String &failureMessage=String())
static ElementType * getNextSIMDAlignedPtr(ElementType *ptr) noexcept
static constexpr size_t SIMDRegisterSize
static constexpr size_t size() noexcept