| /* | 
 |  *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 
 |  * | 
 |  *  Use of this source code is governed by a BSD-style license | 
 |  *  that can be found in the LICENSE file in the root of the source | 
 |  *  tree. An additional intellectual property rights grant can be found | 
 |  *  in the file PATENTS.  All contributing project authors may | 
 |  *  be found in the AUTHORS file in the root of the source tree. | 
 |  */ | 
 |  | 
 | #include "modules/audio_processing/vad/vad_circular_buffer.h" | 
 |  | 
 | #include <cstdlib> | 
 |  | 
 | namespace webrtc { | 
 |  | 
 | VadCircularBuffer::VadCircularBuffer(int buffer_size) | 
 |     : buffer_(new double[buffer_size]), | 
 |       is_full_(false), | 
 |       index_(0), | 
 |       buffer_size_(buffer_size), | 
 |       sum_(0) {} | 
 |  | 
 | VadCircularBuffer::~VadCircularBuffer() {} | 
 |  | 
 | void VadCircularBuffer::Reset() { | 
 |   is_full_ = false; | 
 |   index_ = 0; | 
 |   sum_ = 0; | 
 | } | 
 |  | 
 | VadCircularBuffer* VadCircularBuffer::Create(int buffer_size) { | 
 |   if (buffer_size <= 0) | 
 |     return nullptr; | 
 |   return new VadCircularBuffer(buffer_size); | 
 | } | 
 |  | 
 | double VadCircularBuffer::Oldest() const { | 
 |   if (!is_full_) | 
 |     return buffer_[0]; | 
 |   else | 
 |     return buffer_[index_]; | 
 | } | 
 |  | 
 | double VadCircularBuffer::Mean() { | 
 |   double m; | 
 |   if (is_full_) { | 
 |     m = sum_ / buffer_size_; | 
 |   } else { | 
 |     if (index_ > 0) | 
 |       m = sum_ / index_; | 
 |     else | 
 |       m = 0; | 
 |   } | 
 |   return m; | 
 | } | 
 |  | 
 | void VadCircularBuffer::Insert(double value) { | 
 |   if (is_full_) { | 
 |     sum_ -= buffer_[index_]; | 
 |   } | 
 |   sum_ += value; | 
 |   buffer_[index_] = value; | 
 |   index_++; | 
 |   if (index_ >= buffer_size_) { | 
 |     is_full_ = true; | 
 |     index_ = 0; | 
 |   } | 
 | } | 
 | int VadCircularBuffer::BufferLevel() { | 
 |   if (is_full_) | 
 |     return buffer_size_; | 
 |   return index_; | 
 | } | 
 |  | 
 | int VadCircularBuffer::Get(int index, double* value) const { | 
 |   int err = ConvertToLinearIndex(&index); | 
 |   if (err < 0) | 
 |     return -1; | 
 |   *value = buffer_[index]; | 
 |   return 0; | 
 | } | 
 |  | 
 | int VadCircularBuffer::Set(int index, double value) { | 
 |   int err = ConvertToLinearIndex(&index); | 
 |   if (err < 0) | 
 |     return -1; | 
 |  | 
 |   sum_ -= buffer_[index]; | 
 |   buffer_[index] = value; | 
 |   sum_ += value; | 
 |   return 0; | 
 | } | 
 |  | 
 | int VadCircularBuffer::ConvertToLinearIndex(int* index) const { | 
 |   if (*index < 0 || *index >= buffer_size_) | 
 |     return -1; | 
 |  | 
 |   if (!is_full_ && *index >= index_) | 
 |     return -1; | 
 |  | 
 |   *index = index_ - 1 - *index; | 
 |   if (*index < 0) | 
 |     *index += buffer_size_; | 
 |   return 0; | 
 | } | 
 |  | 
 | int VadCircularBuffer::RemoveTransient(int width_threshold, | 
 |                                        double val_threshold) { | 
 |   if (!is_full_ && index_ < width_threshold + 2) | 
 |     return 0; | 
 |  | 
 |   int index_1 = 0; | 
 |   int index_2 = width_threshold + 1; | 
 |   double v = 0; | 
 |   if (Get(index_1, &v) < 0) | 
 |     return -1; | 
 |   if (v < val_threshold) { | 
 |     Set(index_1, 0); | 
 |     int index; | 
 |     for (index = index_2; index > index_1; index--) { | 
 |       if (Get(index, &v) < 0) | 
 |         return -1; | 
 |       if (v < val_threshold) | 
 |         break; | 
 |     } | 
 |     for (; index > index_1; index--) { | 
 |       if (Set(index, 0.0) < 0) | 
 |         return -1; | 
 |     } | 
 |   } | 
 |   return 0; | 
 | } | 
 |  | 
 | }  // namespace webrtc |