1 /* 2 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include "webrtc/common_audio/fir_filter.h" 12 13 #include <string.h> 14 15 #include "testing/gtest/include/gtest/gtest.h" 16 #include "webrtc/system_wrappers/interface/scoped_ptr.h" 17 18 namespace webrtc { 19 20 static const float kCoefficients[] = {0.2f, 0.3f, 0.5f, 0.7f, 0.11f}; 21 static const size_t kCoefficientsLength = sizeof(kCoefficients) / 22 sizeof(kCoefficients[0]); 23 24 static const float kInput[] = {1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 25 8.f, 9.f, 10.f}; 26 static const size_t kInputLength = sizeof(kInput) / 27 sizeof(kInput[0]); 28 29 void VerifyOutput(const float* expected_output, 30 const float* output, 31 size_t length) { 32 EXPECT_EQ(0, memcmp(expected_output, 33 output, 34 length * sizeof(expected_output[0]))); 35 } 36 37 TEST(FIRFilterTest, FilterAsIdentity) { 38 const float kCoefficients[] = {1.f, 0.f, 0.f, 0.f, 0.f}; 39 float output[kInputLength]; 40 scoped_ptr<FIRFilter> filter(FIRFilter::Create( 41 kCoefficients, kCoefficientsLength, kInputLength)); 42 filter->Filter(kInput, kInputLength, output); 43 44 VerifyOutput(kInput, output, kInputLength); 45 } 46 47 TEST(FIRFilterTest, FilterUsedAsScalarMultiplication) { 48 const float kCoefficients[] = {5.f, 0.f, 0.f, 0.f, 0.f}; 49 float output[kInputLength]; 50 scoped_ptr<FIRFilter> filter(FIRFilter::Create( 51 kCoefficients, kCoefficientsLength, kInputLength)); 52 filter->Filter(kInput, kInputLength, output); 53 54 EXPECT_FLOAT_EQ(5.f, output[0]); 55 EXPECT_FLOAT_EQ(20.f, output[3]); 56 EXPECT_FLOAT_EQ(25.f, output[4]); 57 EXPECT_FLOAT_EQ(50.f, output[kInputLength - 1]); 58 } 59 60 TEST(FIRFilterTest, FilterUsedAsInputShifting) { 61 const float kCoefficients[] = {0.f, 0.f, 0.f, 0.f, 1.f}; 62 float output[kInputLength]; 63 scoped_ptr<FIRFilter> filter(FIRFilter::Create( 64 kCoefficients, kCoefficientsLength, kInputLength)); 65 filter->Filter(kInput, kInputLength, output); 66 67 EXPECT_FLOAT_EQ(0.f, output[0]); 68 EXPECT_FLOAT_EQ(0.f, output[3]); 69 EXPECT_FLOAT_EQ(1.f, output[4]); 70 EXPECT_FLOAT_EQ(2.f, output[5]); 71 EXPECT_FLOAT_EQ(6.f, output[kInputLength - 1]); 72 } 73 74 TEST(FIRFilterTest, FilterUsedAsArbitraryWeighting) { 75 float output[kInputLength]; 76 scoped_ptr<FIRFilter> filter(FIRFilter::Create( 77 kCoefficients, kCoefficientsLength, kInputLength)); 78 filter->Filter(kInput, kInputLength, output); 79 80 EXPECT_FLOAT_EQ(0.2f, output[0]); 81 EXPECT_FLOAT_EQ(3.4f, output[3]); 82 EXPECT_FLOAT_EQ(5.21f, output[4]); 83 EXPECT_FLOAT_EQ(7.02f, output[5]); 84 EXPECT_FLOAT_EQ(14.26f, output[kInputLength - 1]); 85 } 86 87 TEST(FIRFilterTest, FilterInLengthLesserOrEqualToCoefficientsLength) { 88 float output[kInputLength]; 89 scoped_ptr<FIRFilter> filter( 90 FIRFilter::Create(kCoefficients, kCoefficientsLength, 2)); 91 filter->Filter(kInput, 2, output); 92 93 EXPECT_FLOAT_EQ(0.2f, output[0]); 94 EXPECT_FLOAT_EQ(0.7f, output[1]); 95 filter.reset(FIRFilter::Create( 96 kCoefficients, kCoefficientsLength, kCoefficientsLength)); 97 filter->Filter(kInput, kCoefficientsLength, output); 98 99 EXPECT_FLOAT_EQ(0.2f, output[0]); 100 EXPECT_FLOAT_EQ(3.4f, output[3]); 101 EXPECT_FLOAT_EQ(5.21f, output[4]); 102 } 103 104 TEST(FIRFilterTest, MultipleFilterCalls) { 105 float output[kInputLength]; 106 scoped_ptr<FIRFilter> filter( 107 FIRFilter::Create(kCoefficients, kCoefficientsLength, 3)); 108 filter->Filter(kInput, 2, output); 109 EXPECT_FLOAT_EQ(0.2f, output[0]); 110 EXPECT_FLOAT_EQ(0.7f, output[1]); 111 112 filter->Filter(kInput, 2, output); 113 EXPECT_FLOAT_EQ(1.3f, output[0]); 114 EXPECT_FLOAT_EQ(2.4f, output[1]); 115 116 filter->Filter(kInput, 2, output); 117 EXPECT_FLOAT_EQ(2.81f, output[0]); 118 EXPECT_FLOAT_EQ(2.62f, output[1]); 119 120 filter->Filter(kInput, 2, output); 121 EXPECT_FLOAT_EQ(2.81f, output[0]); 122 EXPECT_FLOAT_EQ(2.62f, output[1]); 123 124 filter->Filter(&kInput[3], 3, output); 125 EXPECT_FLOAT_EQ(3.41f, output[0]); 126 EXPECT_FLOAT_EQ(4.12f, output[1]); 127 EXPECT_FLOAT_EQ(6.21f, output[2]); 128 129 filter->Filter(&kInput[3], 3, output); 130 EXPECT_FLOAT_EQ(8.12f, output[0]); 131 EXPECT_FLOAT_EQ(9.14f, output[1]); 132 EXPECT_FLOAT_EQ(9.45f, output[2]); 133 } 134 135 TEST(FIRFilterTest, VerifySampleBasedVsBlockBasedFiltering) { 136 float output_block_based[kInputLength]; 137 scoped_ptr<FIRFilter> filter(FIRFilter::Create( 138 kCoefficients, kCoefficientsLength, kInputLength)); 139 filter->Filter(kInput, kInputLength, output_block_based); 140 141 float output_sample_based[kInputLength]; 142 filter.reset(FIRFilter::Create(kCoefficients, kCoefficientsLength, 1)); 143 for (size_t i = 0; i < kInputLength; ++i) { 144 filter->Filter(&kInput[i], 1, &output_sample_based[i]); 145 } 146 147 EXPECT_EQ(0, memcmp(output_sample_based, 148 output_block_based, 149 kInputLength)); 150 } 151 152 TEST(FIRFilterTest, SimplestHighPassFilter) { 153 const float kCoefficients[] = {1.f, -1.f}; 154 const size_t kCoefficientsLength = sizeof(kCoefficients) / 155 sizeof(kCoefficients[0]); 156 157 float kConstantInput[] = {1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f}; 158 const size_t kConstantInputLength = sizeof(kConstantInput) / 159 sizeof(kConstantInput[0]); 160 161 float output[kConstantInputLength]; 162 scoped_ptr<FIRFilter> filter(FIRFilter::Create( 163 kCoefficients, kCoefficientsLength, kConstantInputLength)); 164 filter->Filter(kConstantInput, kConstantInputLength, output); 165 EXPECT_FLOAT_EQ(1.f, output[0]); 166 for (size_t i = kCoefficientsLength - 1; i < kConstantInputLength; ++i) { 167 EXPECT_FLOAT_EQ(0.f, output[i]); 168 } 169 } 170 171 TEST(FIRFilterTest, SimplestLowPassFilter) { 172 const float kCoefficients[] = {1.f, 1.f}; 173 const size_t kCoefficientsLength = sizeof(kCoefficients) / 174 sizeof(kCoefficients[0]); 175 176 float kHighFrequencyInput[] = {-1.f, 1.f, -1.f, 1.f, -1.f, 1.f, -1.f, 1.f}; 177 const size_t kHighFrequencyInputLength = sizeof(kHighFrequencyInput) / 178 sizeof(kHighFrequencyInput[0]); 179 180 float output[kHighFrequencyInputLength]; 181 scoped_ptr<FIRFilter> filter(FIRFilter::Create( 182 kCoefficients, kCoefficientsLength, kHighFrequencyInputLength)); 183 filter->Filter(kHighFrequencyInput, kHighFrequencyInputLength, output); 184 EXPECT_FLOAT_EQ(-1.f, output[0]); 185 for (size_t i = kCoefficientsLength - 1; i < kHighFrequencyInputLength; ++i) { 186 EXPECT_FLOAT_EQ(0.f, output[i]); 187 } 188 } 189 190 TEST(FIRFilterTest, SameOutputWhenSwapedCoefficientsAndInput) { 191 float output[kCoefficientsLength]; 192 float output_swaped[kCoefficientsLength]; 193 scoped_ptr<FIRFilter> filter(FIRFilter::Create( 194 kCoefficients, kCoefficientsLength, kCoefficientsLength)); 195 // Use kCoefficientsLength for in_length to get same-length outputs. 196 filter->Filter(kInput, kCoefficientsLength, output); 197 198 filter.reset(FIRFilter::Create( 199 kInput, kCoefficientsLength, kCoefficientsLength)); 200 filter->Filter(kCoefficients, kCoefficientsLength, output_swaped); 201 202 for (size_t i = 0 ; i < kCoefficientsLength; ++i) { 203 EXPECT_FLOAT_EQ(output[i], output_swaped[i]); 204 } 205 } 206 207 } // namespace webrtc 208