tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

aec3_fft_unittest.cc (5916B)


      1 /*
      2 *  Copyright (c) 2017 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 "modules/audio_processing/aec3/aec3_fft.h"
     12 
     13 #include <algorithm>
     14 #include <array>
     15 #include <cstddef>
     16 
     17 #include "modules/audio_processing/aec3/aec3_common.h"
     18 #include "modules/audio_processing/aec3/fft_data.h"
     19 #include "rtc_base/checks.h"
     20 #include "test/gmock.h"
     21 #include "test/gtest.h"
     22 
     23 namespace webrtc {
     24 
     25 #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
     26 
     27 // Verifies that the check for non-null input in Fft works.
     28 TEST(Aec3FftDeathTest, NullFftInput) {
     29  Aec3Fft fft;
     30  FftData X;
     31  EXPECT_DEATH(fft.Fft(nullptr, &X), "");
     32 }
     33 
     34 // Verifies that the check for non-null input in Fft works.
     35 TEST(Aec3FftDeathTest, NullFftOutput) {
     36  Aec3Fft fft;
     37  std::array<float, kFftLength> x;
     38  EXPECT_DEATH(fft.Fft(&x, nullptr), "");
     39 }
     40 
     41 // Verifies that the check for non-null output in Ifft works.
     42 TEST(Aec3FftDeathTest, NullIfftOutput) {
     43  Aec3Fft fft;
     44  FftData X;
     45  EXPECT_DEATH(fft.Ifft(X, nullptr), "");
     46 }
     47 
     48 // Verifies that the check for non-null output in ZeroPaddedFft works.
     49 TEST(Aec3FftDeathTest, NullZeroPaddedFftOutput) {
     50  Aec3Fft fft;
     51  std::array<float, kFftLengthBy2> x;
     52  EXPECT_DEATH(fft.ZeroPaddedFft(x, Aec3Fft::Window::kRectangular, nullptr),
     53               "");
     54 }
     55 
     56 // Verifies that the check for input length in ZeroPaddedFft works.
     57 TEST(Aec3FftDeathTest, ZeroPaddedFftWrongInputLength) {
     58  Aec3Fft fft;
     59  FftData X;
     60  std::array<float, kFftLengthBy2 - 1> x;
     61  EXPECT_DEATH(fft.ZeroPaddedFft(x, Aec3Fft::Window::kRectangular, &X), "");
     62 }
     63 
     64 // Verifies that the check for non-null output in PaddedFft works.
     65 TEST(Aec3FftDeathTest, NullPaddedFftOutput) {
     66  Aec3Fft fft;
     67  std::array<float, kFftLengthBy2> x;
     68  std::array<float, kFftLengthBy2> x_old;
     69  EXPECT_DEATH(fft.PaddedFft(x, x_old, nullptr), "");
     70 }
     71 
     72 // Verifies that the check for input length in PaddedFft works.
     73 TEST(Aec3FftDeathTest, PaddedFftWrongInputLength) {
     74  Aec3Fft fft;
     75  FftData X;
     76  std::array<float, kFftLengthBy2 - 1> x;
     77  std::array<float, kFftLengthBy2> x_old;
     78  EXPECT_DEATH(fft.PaddedFft(x, x_old, &X), "");
     79 }
     80 
     81 // Verifies that the check for length in the old value in PaddedFft works.
     82 TEST(Aec3FftDeathTest, PaddedFftWrongOldValuesLength) {
     83  Aec3Fft fft;
     84  FftData X;
     85  std::array<float, kFftLengthBy2> x;
     86  std::array<float, kFftLengthBy2 - 1> x_old;
     87  EXPECT_DEATH(fft.PaddedFft(x, x_old, &X), "");
     88 }
     89 
     90 #endif
     91 
     92 // Verifies that Fft works as intended.
     93 TEST(Aec3Fft, Fft) {
     94  Aec3Fft fft;
     95  FftData X;
     96  std::array<float, kFftLength> x;
     97  x.fill(0.f);
     98  fft.Fft(&x, &X);
     99  EXPECT_THAT(X.re, ::testing::Each(0.f));
    100  EXPECT_THAT(X.im, ::testing::Each(0.f));
    101 
    102  x.fill(0.f);
    103  x[0] = 1.f;
    104  fft.Fft(&x, &X);
    105  EXPECT_THAT(X.re, ::testing::Each(1.f));
    106  EXPECT_THAT(X.im, ::testing::Each(0.f));
    107 
    108  x.fill(1.f);
    109  fft.Fft(&x, &X);
    110  EXPECT_EQ(128.f, X.re[0]);
    111  std::for_each(X.re.begin() + 1, X.re.end(),
    112                [](float a) { EXPECT_EQ(0.f, a); });
    113  EXPECT_THAT(X.im, ::testing::Each(0.f));
    114 }
    115 
    116 // Verifies that InverseFft works as intended.
    117 TEST(Aec3Fft, Ifft) {
    118  Aec3Fft fft;
    119  FftData X;
    120  std::array<float, kFftLength> x;
    121 
    122  X.re.fill(0.f);
    123  X.im.fill(0.f);
    124  fft.Ifft(X, &x);
    125  EXPECT_THAT(x, ::testing::Each(0.f));
    126 
    127  X.re.fill(1.f);
    128  X.im.fill(0.f);
    129  fft.Ifft(X, &x);
    130  EXPECT_EQ(64.f, x[0]);
    131  std::for_each(x.begin() + 1, x.end(), [](float a) { EXPECT_EQ(0.f, a); });
    132 
    133  X.re.fill(0.f);
    134  X.re[0] = 128;
    135  X.im.fill(0.f);
    136  fft.Ifft(X, &x);
    137  EXPECT_THAT(x, ::testing::Each(64.f));
    138 }
    139 
    140 // Verifies that InverseFft and Fft work as intended.
    141 TEST(Aec3Fft, FftAndIfft) {
    142  Aec3Fft fft;
    143  FftData X;
    144  std::array<float, kFftLength> x;
    145  std::array<float, kFftLength> x_ref;
    146 
    147  int v = 0;
    148  for (int k = 0; k < 20; ++k) {
    149    for (size_t j = 0; j < x.size(); ++j) {
    150      x[j] = v++;
    151      x_ref[j] = x[j] * 64.f;
    152    }
    153    fft.Fft(&x, &X);
    154    fft.Ifft(X, &x);
    155    for (size_t j = 0; j < x.size(); ++j) {
    156      EXPECT_NEAR(x_ref[j], x[j], 0.001f);
    157    }
    158  }
    159 }
    160 
    161 // Verifies that ZeroPaddedFft work as intended.
    162 TEST(Aec3Fft, ZeroPaddedFft) {
    163  Aec3Fft fft;
    164  FftData X;
    165  std::array<float, kFftLengthBy2> x_in;
    166  std::array<float, kFftLength> x_ref;
    167  std::array<float, kFftLength> x_out;
    168 
    169  int v = 0;
    170  x_ref.fill(0.f);
    171  for (int k = 0; k < 20; ++k) {
    172    for (size_t j = 0; j < x_in.size(); ++j) {
    173      x_in[j] = v++;
    174      x_ref[j + kFftLengthBy2] = x_in[j] * 64.f;
    175    }
    176    fft.ZeroPaddedFft(x_in, Aec3Fft::Window::kRectangular, &X);
    177    fft.Ifft(X, &x_out);
    178    for (size_t j = 0; j < x_out.size(); ++j) {
    179      EXPECT_NEAR(x_ref[j], x_out[j], 0.1f);
    180    }
    181  }
    182 }
    183 
    184 // Verifies that ZeroPaddedFft work as intended.
    185 TEST(Aec3Fft, PaddedFft) {
    186  Aec3Fft fft;
    187  FftData X;
    188  std::array<float, kFftLengthBy2> x_in;
    189  std::array<float, kFftLength> x_out;
    190  std::array<float, kFftLengthBy2> x_old;
    191  std::array<float, kFftLengthBy2> x_old_ref;
    192  std::array<float, kFftLength> x_ref;
    193 
    194  int v = 0;
    195  x_old.fill(0.f);
    196  for (int k = 0; k < 20; ++k) {
    197    for (size_t j = 0; j < x_in.size(); ++j) {
    198      x_in[j] = v++;
    199    }
    200 
    201    std::copy(x_old.begin(), x_old.end(), x_ref.begin());
    202    std::copy(x_in.begin(), x_in.end(), x_ref.begin() + kFftLengthBy2);
    203    std::copy(x_in.begin(), x_in.end(), x_old_ref.begin());
    204    std::for_each(x_ref.begin(), x_ref.end(), [](float& a) { a *= 64.f; });
    205 
    206    fft.PaddedFft(x_in, x_old, &X);
    207    std::copy(x_in.begin(), x_in.end(), x_old.begin());
    208    fft.Ifft(X, &x_out);
    209 
    210    for (size_t j = 0; j < x_out.size(); ++j) {
    211      EXPECT_NEAR(x_ref[j], x_out[j], 0.1f);
    212    }
    213 
    214    EXPECT_EQ(x_old_ref, x_old);
    215  }
    216 }
    217 
    218 }  // namespace webrtc