• 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/symmetric_matrix_buffer.h"
12 
13 #include "modules/audio_processing/agc2/rnn_vad/ring_buffer.h"
14 #include "test/gtest.h"
15 
16 namespace webrtc {
17 namespace rnn_vad {
18 namespace test {
19 namespace {
20 
21 template <typename T, size_t S>
CheckSymmetry(const SymmetricMatrixBuffer<T,S> * sym_matrix_buf)22 void CheckSymmetry(const SymmetricMatrixBuffer<T, S>* sym_matrix_buf) {
23   for (size_t row = 0; row < S - 1; ++row)
24     for (size_t col = row + 1; col < S; ++col)
25       EXPECT_EQ(sym_matrix_buf->GetValue(row, col),
26                 sym_matrix_buf->GetValue(col, row));
27 }
28 
29 using PairType = std::pair<int, int>;
30 
31 // Checks that the symmetric matrix buffer contains any pair with a value equal
32 // to the given one.
33 template <size_t S>
CheckPairsWithValueExist(const SymmetricMatrixBuffer<PairType,S> * sym_matrix_buf,const int value)34 bool CheckPairsWithValueExist(
35     const SymmetricMatrixBuffer<PairType, S>* sym_matrix_buf,
36     const int value) {
37   for (size_t row = 0; row < S - 1; ++row) {
38     for (size_t col = row + 1; col < S; ++col) {
39       auto p = sym_matrix_buf->GetValue(row, col);
40       if (p.first == value || p.second == value)
41         return true;
42     }
43   }
44   return false;
45 }
46 
47 }  // namespace
48 
49 // Test that shows how to combine RingBuffer and SymmetricMatrixBuffer to
50 // efficiently compute pair-wise scores. This test verifies that the evolution
51 // of a SymmetricMatrixBuffer instance follows that of RingBuffer.
TEST(RnnVadTest,SymmetricMatrixBufferUseCase)52 TEST(RnnVadTest, SymmetricMatrixBufferUseCase) {
53   // Instance a ring buffer which will be fed with a series of integer values.
54   constexpr int kRingBufSize = 10;
55   RingBuffer<int, 1, static_cast<size_t>(kRingBufSize)> ring_buf;
56   // Instance a symmetric matrix buffer for the ring buffer above. It stores
57   // pairs of integers with which this test can easily check that the evolution
58   // of RingBuffer and SymmetricMatrixBuffer match.
59   SymmetricMatrixBuffer<PairType, kRingBufSize> sym_matrix_buf;
60   for (int t = 1; t <= 100; ++t) {  // Evolution steps.
61     SCOPED_TRACE(t);
62     const int t_removed = ring_buf.GetArrayView(kRingBufSize - 1)[0];
63     ring_buf.Push({&t, 1});
64     // The head of the ring buffer is |t|.
65     ASSERT_EQ(t, ring_buf.GetArrayView(0)[0]);
66     // Create the comparisons between |t| and the older elements in the ring
67     // buffer.
68     std::array<PairType, kRingBufSize - 1> new_comparions;
69     for (int i = 0; i < kRingBufSize - 1; ++i) {
70       // Start comparing |t| to the second newest element in the ring buffer.
71       const int delay = i + 1;
72       const auto t_prev = ring_buf.GetArrayView(delay)[0];
73       ASSERT_EQ(std::max(0, t - delay), t_prev);
74       // Compare the last element |t| with |t_prev|.
75       new_comparions[i].first = t_prev;
76       new_comparions[i].second = t;
77     }
78     // Push the new comparisons in the symmetric matrix buffer.
79     sym_matrix_buf.Push({new_comparions.data(), new_comparions.size()});
80     // Tests.
81     CheckSymmetry(&sym_matrix_buf);
82     // Check that the pairs resulting from the content in the ring buffer are
83     // in the right position.
84     for (size_t delay1 = 0; delay1 < kRingBufSize - 1; ++delay1) {
85       for (size_t delay2 = delay1 + 1; delay2 < kRingBufSize; ++delay2) {
86         const auto t1 = ring_buf.GetArrayView(delay1)[0];
87         const auto t2 = ring_buf.GetArrayView(delay2)[0];
88         ASSERT_LE(t2, t1);
89         const auto p = sym_matrix_buf.GetValue(delay1, delay2);
90         EXPECT_EQ(p.first, t2);
91         EXPECT_EQ(p.second, t1);
92       }
93     }
94     // Check that every older element in the ring buffer still has a
95     // corresponding pair in the symmetric matrix buffer.
96     for (size_t delay = 1; delay < kRingBufSize; ++delay) {
97       const auto t_prev = ring_buf.GetArrayView(delay)[0];
98       EXPECT_TRUE(CheckPairsWithValueExist(&sym_matrix_buf, t_prev));
99     }
100     // Check that the element removed from the ring buffer has no corresponding
101     // pairs in the symmetric matrix buffer.
102     if (t > kRingBufSize - 1) {
103       EXPECT_FALSE(CheckPairsWithValueExist(&sym_matrix_buf, t_removed));
104     }
105   }
106 }
107 
108 }  // namespace test
109 }  // namespace rnn_vad
110 }  // namespace webrtc
111