Home | History | Annotate | Download | only in common_audio
      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