• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2012 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/vad/vad_circular_buffer.h"
12 
13 #include <stdio.h>
14 
15 #include <memory>
16 
17 #include "test/gtest.h"
18 
19 namespace webrtc {
20 
21 static const int kWidthThreshold = 7;
22 static const double kValThreshold = 1.0;
23 static const int kLongBuffSize = 100;
24 static const int kShortBuffSize = 10;
25 
InsertSequentially(int k,VadCircularBuffer * circular_buffer)26 static void InsertSequentially(int k, VadCircularBuffer* circular_buffer) {
27   double mean_val;
28   for (int n = 1; n <= k; n++) {
29     EXPECT_TRUE(!circular_buffer->is_full());
30     circular_buffer->Insert(n);
31     mean_val = circular_buffer->Mean();
32     EXPECT_EQ((n + 1.0) / 2., mean_val);
33   }
34 }
35 
Insert(double value,int num_insertion,VadCircularBuffer * circular_buffer)36 static void Insert(double value,
37                    int num_insertion,
38                    VadCircularBuffer* circular_buffer) {
39   for (int n = 0; n < num_insertion; n++)
40     circular_buffer->Insert(value);
41 }
42 
InsertZeros(int num_zeros,VadCircularBuffer * circular_buffer)43 static void InsertZeros(int num_zeros, VadCircularBuffer* circular_buffer) {
44   Insert(0.0, num_zeros, circular_buffer);
45 }
46 
TEST(VadCircularBufferTest,GeneralTest)47 TEST(VadCircularBufferTest, GeneralTest) {
48   std::unique_ptr<VadCircularBuffer> circular_buffer(
49       VadCircularBuffer::Create(kShortBuffSize));
50   double mean_val;
51 
52   // Mean should return zero if nothing is inserted.
53   mean_val = circular_buffer->Mean();
54   EXPECT_DOUBLE_EQ(0.0, mean_val);
55   InsertSequentially(kShortBuffSize, circular_buffer.get());
56 
57   // Should be full.
58   EXPECT_TRUE(circular_buffer->is_full());
59   // Correct update after being full.
60   for (int n = 1; n < kShortBuffSize; n++) {
61     circular_buffer->Insert(n);
62     mean_val = circular_buffer->Mean();
63     EXPECT_DOUBLE_EQ((kShortBuffSize + 1.) / 2., mean_val);
64     EXPECT_TRUE(circular_buffer->is_full());
65   }
66 
67   // Check reset. This should be like starting fresh.
68   circular_buffer->Reset();
69   mean_val = circular_buffer->Mean();
70   EXPECT_DOUBLE_EQ(0, mean_val);
71   InsertSequentially(kShortBuffSize, circular_buffer.get());
72   EXPECT_TRUE(circular_buffer->is_full());
73 }
74 
TEST(VadCircularBufferTest,TransientsRemoval)75 TEST(VadCircularBufferTest, TransientsRemoval) {
76   std::unique_ptr<VadCircularBuffer> circular_buffer(
77       VadCircularBuffer::Create(kLongBuffSize));
78   // Let the first transient be in wrap-around.
79   InsertZeros(kLongBuffSize - kWidthThreshold / 2, circular_buffer.get());
80 
81   double push_val = kValThreshold;
82   double mean_val;
83   for (int k = kWidthThreshold; k >= 1; k--) {
84     Insert(push_val, k, circular_buffer.get());
85     circular_buffer->Insert(0);
86     mean_val = circular_buffer->Mean();
87     EXPECT_DOUBLE_EQ(k * push_val / kLongBuffSize, mean_val);
88     circular_buffer->RemoveTransient(kWidthThreshold, kValThreshold);
89     mean_val = circular_buffer->Mean();
90     EXPECT_DOUBLE_EQ(0, mean_val);
91   }
92 }
93 
TEST(VadCircularBufferTest,TransientDetection)94 TEST(VadCircularBufferTest, TransientDetection) {
95   std::unique_ptr<VadCircularBuffer> circular_buffer(
96       VadCircularBuffer::Create(kLongBuffSize));
97   // Let the first transient be in wrap-around.
98   int num_insertion = kLongBuffSize - kWidthThreshold / 2;
99   InsertZeros(num_insertion, circular_buffer.get());
100 
101   double push_val = 2;
102   // This is longer than a transient and shouldn't be removed.
103   int num_non_zero_elements = kWidthThreshold + 1;
104   Insert(push_val, num_non_zero_elements, circular_buffer.get());
105 
106   double mean_val = circular_buffer->Mean();
107   EXPECT_DOUBLE_EQ(num_non_zero_elements * push_val / kLongBuffSize, mean_val);
108   circular_buffer->Insert(0);
109   EXPECT_EQ(0,
110             circular_buffer->RemoveTransient(kWidthThreshold, kValThreshold));
111   mean_val = circular_buffer->Mean();
112   EXPECT_DOUBLE_EQ(num_non_zero_elements * push_val / kLongBuffSize, mean_val);
113 
114   // A transient right after a non-transient, should be removed and mean is
115   // not changed.
116   num_insertion = 3;
117   Insert(push_val, num_insertion, circular_buffer.get());
118   circular_buffer->Insert(0);
119   EXPECT_EQ(0,
120             circular_buffer->RemoveTransient(kWidthThreshold, kValThreshold));
121   mean_val = circular_buffer->Mean();
122   EXPECT_DOUBLE_EQ(num_non_zero_elements * push_val / kLongBuffSize, mean_val);
123 
124   // Last input is larger than threshold, although the sequence is short but
125   // it shouldn't be considered transient.
126   Insert(push_val, num_insertion, circular_buffer.get());
127   num_non_zero_elements += num_insertion;
128   EXPECT_EQ(0,
129             circular_buffer->RemoveTransient(kWidthThreshold, kValThreshold));
130   mean_val = circular_buffer->Mean();
131   EXPECT_DOUBLE_EQ(num_non_zero_elements * push_val / kLongBuffSize, mean_val);
132 }
133 
134 }  // namespace webrtc
135