xref: /aosp_15_r20/external/webrtc/modules/audio_processing/agc2/rnn_vad/spectral_features_unittest.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
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 #include "rtc_base/numerics/safe_compare.h"
18 // TODO(bugs.webrtc.org/8948): Add when the issue is fixed.
19 // #include "test/fpe_observer.h"
20 #include "test/gtest.h"
21 
22 namespace webrtc {
23 namespace rnn_vad {
24 namespace {
25 
26 constexpr int 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 (int i = 0; rtc::SafeLt(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 // Checks that silence is detected when the input signal is 0 and that the
69 // feature vector is written only if the input signal is not tagged as silence.
TEST(RnnVadTest,SpectralFeaturesWithAndWithoutSilence)70 TEST(RnnVadTest, SpectralFeaturesWithAndWithoutSilence) {
71   // Initialize.
72   SpectralFeaturesExtractor sfe;
73   std::array<float, kFrameSize20ms24kHz> samples;
74   rtc::ArrayView<float, kFrameSize20ms24kHz> samples_view(samples);
75   bool is_silence;
76   std::array<float, kTestFeatureVectorSize> feature_vector;
77 
78   // Write an initial value in the feature vector to detect changes.
79   std::fill(feature_vector.begin(), feature_vector.end(), kInitialFeatureVal);
80 
81   // TODO(bugs.webrtc.org/8948): Add when the issue is fixed.
82   // FloatingPointExceptionObserver fpe_observer;
83 
84   // With silence.
85   std::fill(samples.begin(), samples.end(), 0.f);
86   is_silence = sfe.CheckSilenceComputeFeatures(
87       samples_view, samples_view, GetHigherBandsSpectrum(&feature_vector),
88       GetAverage(&feature_vector), GetFirstDerivative(&feature_vector),
89       GetSecondDerivative(&feature_vector),
90       GetCepstralCrossCorrelation(&feature_vector),
91       GetCepstralVariability(&feature_vector));
92   // Silence is expected, the output won't be overwritten.
93   EXPECT_TRUE(is_silence);
94   EXPECT_TRUE(std::all_of(feature_vector.begin(), feature_vector.end(),
95                           [](float x) { return x == kInitialFeatureVal; }));
96 
97   // With no silence.
98   WriteTestData(samples);
99   is_silence = sfe.CheckSilenceComputeFeatures(
100       samples_view, samples_view, GetHigherBandsSpectrum(&feature_vector),
101       GetAverage(&feature_vector), GetFirstDerivative(&feature_vector),
102       GetSecondDerivative(&feature_vector),
103       GetCepstralCrossCorrelation(&feature_vector),
104       GetCepstralVariability(&feature_vector));
105   // Silence is not expected, the output will be overwritten.
106   EXPECT_FALSE(is_silence);
107   EXPECT_FALSE(std::all_of(feature_vector.begin(), feature_vector.end(),
108                            [](float x) { return x == kInitialFeatureVal; }));
109 }
110 
111 // Feeds a constant input signal and checks that:
112 // - the cepstral coefficients average does not change;
113 // - the derivatives are zero;
114 // - the cepstral variability score does not change.
TEST(RnnVadTest,CepstralFeaturesConstantAverageZeroDerivative)115 TEST(RnnVadTest, CepstralFeaturesConstantAverageZeroDerivative) {
116   // Initialize.
117   SpectralFeaturesExtractor sfe;
118   std::array<float, kFrameSize20ms24kHz> samples;
119   rtc::ArrayView<float, kFrameSize20ms24kHz> samples_view(samples);
120   WriteTestData(samples);
121 
122   // Fill the spectral features with test data.
123   std::array<float, kTestFeatureVectorSize> feature_vector;
124   for (int i = 0; i < kCepstralCoeffsHistorySize; ++i) {
125     sfe.CheckSilenceComputeFeatures(
126         samples_view, samples_view, GetHigherBandsSpectrum(&feature_vector),
127         GetAverage(&feature_vector), GetFirstDerivative(&feature_vector),
128         GetSecondDerivative(&feature_vector),
129         GetCepstralCrossCorrelation(&feature_vector),
130         GetCepstralVariability(&feature_vector));
131   }
132 
133   // Feed the test data one last time but using a different output vector.
134   std::array<float, kTestFeatureVectorSize> feature_vector_last;
135   sfe.CheckSilenceComputeFeatures(
136       samples_view, samples_view, GetHigherBandsSpectrum(&feature_vector_last),
137       GetAverage(&feature_vector_last),
138       GetFirstDerivative(&feature_vector_last),
139       GetSecondDerivative(&feature_vector_last),
140       GetCepstralCrossCorrelation(&feature_vector_last),
141       GetCepstralVariability(&feature_vector_last));
142 
143   // Average is unchanged.
144   ExpectEqualFloatArray({feature_vector.data(), kNumLowerBands},
145                         {feature_vector_last.data(), kNumLowerBands});
146   // First and second derivatives are zero.
147   constexpr std::array<float, kNumLowerBands> zeros{};
148   ExpectEqualFloatArray(
149       {feature_vector_last.data() + kNumBands, kNumLowerBands}, zeros);
150   ExpectEqualFloatArray(
151       {feature_vector_last.data() + kNumBands + kNumLowerBands, kNumLowerBands},
152       zeros);
153   // Variability is unchanged.
154   EXPECT_FLOAT_EQ(feature_vector[kNumBands + 3 * kNumLowerBands],
155                   feature_vector_last[kNumBands + 3 * kNumLowerBands]);
156 }
157 
158 }  // namespace
159 }  // namespace rnn_vad
160 }  // namespace webrtc
161