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