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