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 <assert.h>
14#include <stdlib.h>
15
16namespace webrtc {
17
18VadCircularBuffer::VadCircularBuffer(int buffer_size)
19    : buffer_(new double[buffer_size]),
20      is_full_(false),
21      index_(0),
22      buffer_size_(buffer_size),
23      sum_(0) {
24}
25
26VadCircularBuffer::~VadCircularBuffer() {
27}
28
29void VadCircularBuffer::Reset() {
30  is_full_ = false;
31  index_ = 0;
32  sum_ = 0;
33}
34
35VadCircularBuffer* VadCircularBuffer::Create(int buffer_size) {
36  if (buffer_size <= 0)
37    return NULL;
38  return new VadCircularBuffer(buffer_size);
39}
40
41double VadCircularBuffer::Oldest() const {
42  if (!is_full_)
43    return buffer_[0];
44  else
45    return buffer_[index_];
46}
47
48double VadCircularBuffer::Mean() {
49  double m;
50  if (is_full_) {
51    m = sum_ / buffer_size_;
52  } else {
53    if (index_ > 0)
54      m = sum_ / index_;
55    else
56      m = 0;
57  }
58  return m;
59}
60
61void VadCircularBuffer::Insert(double value) {
62  if (is_full_) {
63    sum_ -= buffer_[index_];
64  }
65  sum_ += value;
66  buffer_[index_] = value;
67  index_++;
68  if (index_ >= buffer_size_) {
69    is_full_ = true;
70    index_ = 0;
71  }
72}
73int VadCircularBuffer::BufferLevel() {
74  if (is_full_)
75    return buffer_size_;
76  return index_;
77}
78
79int VadCircularBuffer::Get(int index, double* value) const {
80  int err = ConvertToLinearIndex(&index);
81  if (err < 0)
82    return -1;
83  *value = buffer_[index];
84  return 0;
85}
86
87int VadCircularBuffer::Set(int index, double value) {
88  int err = ConvertToLinearIndex(&index);
89  if (err < 0)
90    return -1;
91
92  sum_ -= buffer_[index];
93  buffer_[index] = value;
94  sum_ += value;
95  return 0;
96}
97
98int VadCircularBuffer::ConvertToLinearIndex(int* index) const {
99  if (*index < 0 || *index >= buffer_size_)
100    return -1;
101
102  if (!is_full_ && *index >= index_)
103    return -1;
104
105  *index = index_ - 1 - *index;
106  if (*index < 0)
107    *index += buffer_size_;
108  return 0;
109}
110
111int VadCircularBuffer::RemoveTransient(int width_threshold,
112                                       double val_threshold) {
113  if (!is_full_ && index_ < width_threshold + 2)
114    return 0;
115
116  int index_1 = 0;
117  int index_2 = width_threshold + 1;
118  double v = 0;
119  if (Get(index_1, &v) < 0)
120    return -1;
121  if (v < val_threshold) {
122    Set(index_1, 0);
123    int index;
124    for (index = index_2; index > index_1; index--) {
125      if (Get(index, &v) < 0)
126        return -1;
127      if (v < val_threshold)
128        break;
129    }
130    for (; index > index_1; index--) {
131      if (Set(index, 0.0) < 0)
132        return -1;
133    }
134  }
135  return 0;
136}
137
138}  // namespace webrtc
139