Home | History | Annotate | Download | only in vad
      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 
     18 namespace webrtc {
     19 
     20 static const int kWidthThreshold = 7;
     21 static const double kValThreshold = 1.0;
     22 static const int kLongBuffSize = 100;
     23 static const int kShortBuffSize = 10;
     24 
     25 static 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 
     35 static 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 
     42 static void InsertZeros(int num_zeros, VadCircularBuffer* circular_buffer) {
     43   Insert(0.0, num_zeros, circular_buffer);
     44 }
     45 
     46 TEST(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 
     74 TEST(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 
     93 TEST(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