• 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.h"
12 
13 #include <algorithm>
14 
15 #include "modules/audio_processing/agc2/rnn_vad/test_utils.h"
16 #include "rtc_base/checks.h"
17 // TODO(bugs.webrtc.org/8948): Add when the issue is fixed.
18 // #include "test/fpe_observer.h"
19 #include "test/gtest.h"
20 
21 namespace webrtc {
22 namespace rnn_vad {
23 namespace test {
24 namespace {
25 
26 constexpr size_t kTestFeatureVectorSize = kNumBands + 3 * kNumLowerBands + 1;
27 
28 // Writes non-zero sample values.
WriteTestData(rtc::ArrayView<float> samples)29 void WriteTestData(rtc::ArrayView<float> samples) {
30   for (size_t i = 0; i < samples.size(); ++i) {
31     samples[i] = i % 100;
32   }
33 }
34 
GetHigherBandsSpectrum(std::array<float,kTestFeatureVectorSize> * feature_vector)35 rtc::ArrayView<float, kNumBands - kNumLowerBands> GetHigherBandsSpectrum(
36     std::array<float, kTestFeatureVectorSize>* feature_vector) {
37   return {feature_vector->data() + kNumLowerBands, kNumBands - kNumLowerBands};
38 }
39 
GetAverage(std::array<float,kTestFeatureVectorSize> * feature_vector)40 rtc::ArrayView<float, kNumLowerBands> GetAverage(
41     std::array<float, kTestFeatureVectorSize>* feature_vector) {
42   return {feature_vector->data(), kNumLowerBands};
43 }
44 
GetFirstDerivative(std::array<float,kTestFeatureVectorSize> * feature_vector)45 rtc::ArrayView<float, kNumLowerBands> GetFirstDerivative(
46     std::array<float, kTestFeatureVectorSize>* feature_vector) {
47   return {feature_vector->data() + kNumBands, kNumLowerBands};
48 }
49 
GetSecondDerivative(std::array<float,kTestFeatureVectorSize> * feature_vector)50 rtc::ArrayView<float, kNumLowerBands> GetSecondDerivative(
51     std::array<float, kTestFeatureVectorSize>* feature_vector) {
52   return {feature_vector->data() + kNumBands + kNumLowerBands, kNumLowerBands};
53 }
54 
GetCepstralCrossCorrelation(std::array<float,kTestFeatureVectorSize> * feature_vector)55 rtc::ArrayView<float, kNumLowerBands> GetCepstralCrossCorrelation(
56     std::array<float, kTestFeatureVectorSize>* feature_vector) {
57   return {feature_vector->data() + kNumBands + 2 * kNumLowerBands,
58           kNumLowerBands};
59 }
60 
GetCepstralVariability(std::array<float,kTestFeatureVectorSize> * feature_vector)61 float* GetCepstralVariability(
62     std::array<float, kTestFeatureVectorSize>* feature_vector) {
63   return feature_vector->data() + kNumBands + 3 * kNumLowerBands;
64 }
65 
66 constexpr float kInitialFeatureVal = -9999.f;
67 
68 }  // namespace
69 
70 // Checks that silence is detected when the input signal is 0 and that the
71 // feature vector is written only if the input signal is not tagged as silence.
TEST(RnnVadTest,SpectralFeaturesWithAndWithoutSilence)72 TEST(RnnVadTest, SpectralFeaturesWithAndWithoutSilence) {
73   // Initialize.
74   SpectralFeaturesExtractor sfe;
75   std::array<float, kFrameSize20ms24kHz> samples;
76   rtc::ArrayView<float, kFrameSize20ms24kHz> samples_view(samples);
77   bool is_silence;
78   std::array<float, kTestFeatureVectorSize> feature_vector;
79 
80   // Write an initial value in the feature vector to detect changes.
81   std::fill(feature_vector.begin(), feature_vector.end(), kInitialFeatureVal);
82 
83   // TODO(bugs.webrtc.org/8948): Add when the issue is fixed.
84   // FloatingPointExceptionObserver fpe_observer;
85 
86   // With silence.
87   std::fill(samples.begin(), samples.end(), 0.f);
88   is_silence = sfe.CheckSilenceComputeFeatures(
89       samples_view, samples_view, GetHigherBandsSpectrum(&feature_vector),
90       GetAverage(&feature_vector), GetFirstDerivative(&feature_vector),
91       GetSecondDerivative(&feature_vector),
92       GetCepstralCrossCorrelation(&feature_vector),
93       GetCepstralVariability(&feature_vector));
94   // Silence is expected, the output won't be overwritten.
95   EXPECT_TRUE(is_silence);
96   EXPECT_TRUE(std::all_of(feature_vector.begin(), feature_vector.end(),
97                           [](float x) { return x == kInitialFeatureVal; }));
98 
99   // With no silence.
100   WriteTestData(samples);
101   is_silence = sfe.CheckSilenceComputeFeatures(
102       samples_view, samples_view, GetHigherBandsSpectrum(&feature_vector),
103       GetAverage(&feature_vector), GetFirstDerivative(&feature_vector),
104       GetSecondDerivative(&feature_vector),
105       GetCepstralCrossCorrelation(&feature_vector),
106       GetCepstralVariability(&feature_vector));
107   // Silence is not expected, the output will be overwritten.
108   EXPECT_FALSE(is_silence);
109   EXPECT_FALSE(std::all_of(feature_vector.begin(), feature_vector.end(),
110                            [](float x) { return x == kInitialFeatureVal; }));
111 }
112 
113 // Feeds a constant input signal and checks that:
114 // - the cepstral coefficients average does not change;
115 // - the derivatives are zero;
116 // - the cepstral variability score does not change.
TEST(RnnVadTest,CepstralFeaturesConstantAverageZeroDerivative)117 TEST(RnnVadTest, CepstralFeaturesConstantAverageZeroDerivative) {
118   // Initialize.
119   SpectralFeaturesExtractor sfe;
120   std::array<float, kFrameSize20ms24kHz> samples;
121   rtc::ArrayView<float, kFrameSize20ms24kHz> samples_view(samples);
122   WriteTestData(samples);
123   bool is_silence;
124 
125   // Fill the spectral features with test data.
126   std::array<float, kTestFeatureVectorSize> feature_vector;
127   for (size_t i = 0; i < kCepstralCoeffsHistorySize; ++i) {
128     is_silence = sfe.CheckSilenceComputeFeatures(
129         samples_view, samples_view, GetHigherBandsSpectrum(&feature_vector),
130         GetAverage(&feature_vector), GetFirstDerivative(&feature_vector),
131         GetSecondDerivative(&feature_vector),
132         GetCepstralCrossCorrelation(&feature_vector),
133         GetCepstralVariability(&feature_vector));
134   }
135 
136   // Feed the test data one last time but using a different output vector.
137   std::array<float, kTestFeatureVectorSize> feature_vector_last;
138   is_silence = sfe.CheckSilenceComputeFeatures(
139       samples_view, samples_view, GetHigherBandsSpectrum(&feature_vector_last),
140       GetAverage(&feature_vector_last),
141       GetFirstDerivative(&feature_vector_last),
142       GetSecondDerivative(&feature_vector_last),
143       GetCepstralCrossCorrelation(&feature_vector_last),
144       GetCepstralVariability(&feature_vector_last));
145 
146   // Average is unchanged.
147   ExpectEqualFloatArray({feature_vector.data(), kNumLowerBands},
148                         {feature_vector_last.data(), kNumLowerBands});
149   // First and second derivatives are zero.
150   constexpr std::array<float, kNumLowerBands> zeros{};
151   ExpectEqualFloatArray(
152       {feature_vector_last.data() + kNumBands, kNumLowerBands}, zeros);
153   ExpectEqualFloatArray(
154       {feature_vector_last.data() + kNumBands + kNumLowerBands, kNumLowerBands},
155       zeros);
156   // Variability is unchanged.
157   EXPECT_FLOAT_EQ(feature_vector[kNumBands + 3 * kNumLowerBands],
158                   feature_vector_last[kNumBands + 3 * kNumLowerBands]);
159 }
160 
161 }  // namespace test
162 }  // namespace rnn_vad
163 }  // namespace webrtc
164