• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2018 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/agc2/rnn_vad/spectral_features_internal.h"
12 
13 #include <algorithm>
14 #include <array>
15 #include <complex>
16 #include <numeric>
17 #include <vector>
18 
19 #include "api/array_view.h"
20 #include "modules/audio_processing/agc2/rnn_vad/test_utils.h"
21 #include "modules/audio_processing/utility/pffft_wrapper.h"
22 // TODO(bugs.webrtc.org/8948): Add when the issue is fixed.
23 // #include "test/fpe_observer.h"
24 #include "test/gtest.h"
25 
26 namespace webrtc {
27 namespace rnn_vad {
28 namespace test {
29 namespace {
30 
31 // Generates the values for the array named |kOpusBandWeights24kHz20ms| in the
32 // anonymous namespace of the .cc file, which is the array of FFT coefficient
33 // weights for the Opus scale triangular filters.
ComputeTriangularFiltersWeights()34 std::vector<float> ComputeTriangularFiltersWeights() {
35   constexpr auto kOpusScaleNumBins24kHz20ms = GetOpusScaleNumBins24kHz20ms();
36   const auto& v = kOpusScaleNumBins24kHz20ms;  // Alias.
37   const size_t num_weights = std::accumulate(
38       kOpusScaleNumBins24kHz20ms.begin(), kOpusScaleNumBins24kHz20ms.end(), 0);
39   std::vector<float> weights(num_weights);
40   size_t next_fft_coeff_index = 0;
41   for (size_t band = 0; band < v.size(); ++band) {
42     const size_t band_size = v[band];
43     for (size_t j = 0; j < band_size; ++j) {
44       weights[next_fft_coeff_index + j] = static_cast<float>(j) / band_size;
45     }
46     next_fft_coeff_index += band_size;
47   }
48   return weights;
49 }
50 
51 }  // namespace
52 
53 // Checks that the values returned by GetOpusScaleNumBins24kHz20ms() match the
54 // Opus scale frequency boundaries.
TEST(RnnVadTest,TestOpusScaleBoundaries)55 TEST(RnnVadTest, TestOpusScaleBoundaries) {
56   constexpr int kBandFrequencyBoundariesHz[kNumBands - 1] = {
57       200,  400,  600,  800,  1000, 1200, 1400, 1600,  2000,  2400, 2800,
58       3200, 4000, 4800, 5600, 6800, 8000, 9600, 12000, 15600, 20000};
59   constexpr auto kOpusScaleNumBins24kHz20ms = GetOpusScaleNumBins24kHz20ms();
60   int prev = 0;
61   for (size_t i = 0; i < kOpusScaleNumBins24kHz20ms.size(); ++i) {
62     int boundary =
63         kBandFrequencyBoundariesHz[i] * kFrameSize20ms24kHz / kSampleRate24kHz;
64     EXPECT_EQ(kOpusScaleNumBins24kHz20ms[i], boundary - prev);
65     prev = boundary;
66   }
67 }
68 
69 // Checks that the computed triangular filters weights for the Opus scale are
70 // monotonic withing each Opus band. This test should only be enabled when
71 // ComputeTriangularFiltersWeights() is changed and |kOpusBandWeights24kHz20ms|
72 // is updated accordingly.
TEST(RnnVadTest,DISABLED_TestOpusScaleWeights)73 TEST(RnnVadTest, DISABLED_TestOpusScaleWeights) {
74   auto weights = ComputeTriangularFiltersWeights();
75   size_t i = 0;
76   for (size_t band_size : GetOpusScaleNumBins24kHz20ms()) {
77     SCOPED_TRACE(band_size);
78     rtc::ArrayView<float> band_weights(weights.data() + i, band_size);
79     float prev = -1.f;
80     for (float weight : band_weights) {
81       EXPECT_LT(prev, weight);
82       prev = weight;
83     }
84     i += band_size;
85   }
86 }
87 
88 // Checks that the computed band-wise auto-correlation is non-negative for a
89 // simple input vector of FFT coefficients.
TEST(RnnVadTest,SpectralCorrelatorValidOutput)90 TEST(RnnVadTest, SpectralCorrelatorValidOutput) {
91   // Input: vector of (1, 1j) values.
92   Pffft fft(kFrameSize20ms24kHz, Pffft::FftType::kReal);
93   auto in = fft.CreateBuffer();
94   std::array<float, kOpusBands24kHz> out;
95   auto in_view = in->GetView();
96   std::fill(in_view.begin(), in_view.end(), 1.f);
97   in_view[1] = 0.f;  // Nyquist frequency.
98   // Compute and check output.
99   SpectralCorrelator e;
100   e.ComputeAutoCorrelation(in_view, out);
101   for (size_t i = 0; i < kOpusBands24kHz; ++i) {
102     SCOPED_TRACE(i);
103     EXPECT_GT(out[i], 0.f);
104   }
105 }
106 
107 // Checks that the computed smoothed log magnitude spectrum is within tolerance
108 // given hard-coded test input data.
TEST(RnnVadTest,ComputeSmoothedLogMagnitudeSpectrumWithinTolerance)109 TEST(RnnVadTest, ComputeSmoothedLogMagnitudeSpectrumWithinTolerance) {
110   constexpr std::array<float, kNumBands> input = {
111       {86.060539245605f, 275.668334960938f, 43.406528472900f, 6.541896820068f,
112        17.964015960693f, 8.090919494629f,   1.261920094490f,  1.212702631950f,
113        1.619154453278f,  0.508935272694f,   0.346316039562f,  0.237035423517f,
114        0.172424271703f,  0.271657168865f,   0.126088857651f,  0.139967113733f,
115        0.207200810313f,  0.155893072486f,   0.091090843081f,  0.033391401172f,
116        0.013879744336f,  0.011973354965f}};
117   constexpr std::array<float, kNumBands> expected_output = {
118       {1.934854507446f,  2.440402746201f,  1.637655138969f,  0.816367030144f,
119        1.254645109177f,  0.908534288406f,  0.104459829628f,  0.087320849299f,
120        0.211962252855f,  -0.284886807203f, -0.448164641857f, -0.607240796089f,
121        -0.738917350769f, -0.550279200077f, -0.866177439690f, -0.824003994465f,
122        -0.663138568401f, -0.780171751976f, -0.995288193226f, -1.362596273422f,
123        -1.621970295906f, -1.658103585243f}};
124   std::array<float, kNumBands> computed_output;
125   {
126     // TODO(bugs.webrtc.org/8948): Add when the issue is fixed.
127     // FloatingPointExceptionObserver fpe_observer;
128     ComputeSmoothedLogMagnitudeSpectrum(input, computed_output);
129     ExpectNearAbsolute(expected_output, computed_output, 1e-5f);
130   }
131 }
132 
133 // Checks that the computed DCT is within tolerance given hard-coded test input
134 // data.
TEST(RnnVadTest,ComputeDctWithinTolerance)135 TEST(RnnVadTest, ComputeDctWithinTolerance) {
136   constexpr std::array<float, kNumBands> input = {
137       {0.232155621052f,  0.678957760334f, 0.220818966627f,  -0.077363930643f,
138        -0.559227049351f, 0.432545185089f, 0.353900641203f,  0.398993015289f,
139        0.409774333239f,  0.454977899790f, 0.300520688295f,  -0.010286616161f,
140        0.272525429726f,  0.098067551851f, 0.083649002016f,  0.046226885170f,
141        -0.033228103071f, 0.144773483276f, -0.117661058903f, -0.005628800020f,
142        -0.009547689930f, -0.045382082462f}};
143   constexpr std::array<float, kNumBands> expected_output = {
144       {0.697072803974f,  0.442710995674f,  -0.293156713247f, -0.060711503029f,
145        0.292050391436f,  0.489301353693f,  0.402255415916f,  0.134404733777f,
146        -0.086305990815f, -0.199605688453f, -0.234511867166f, -0.413774639368f,
147        -0.388507157564f, -0.032798115164f, 0.044605545700f,  0.112466648221f,
148        -0.050096966326f, 0.045971218497f,  -0.029815061018f, -0.410366982222f,
149        -0.209233760834f, -0.128037497401f}};
150   auto dct_table = ComputeDctTable();
151   std::array<float, kNumBands> computed_output;
152   {
153     // TODO(bugs.webrtc.org/8948): Add when the issue is fixed.
154     // FloatingPointExceptionObserver fpe_observer;
155     ComputeDct(input, dct_table, computed_output);
156     ExpectNearAbsolute(expected_output, computed_output, 1e-5f);
157   }
158 }
159 
160 }  // namespace test
161 }  // namespace rnn_vad
162 }  // namespace webrtc
163