|  | /* | 
|  | *  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 <stdlib.h> | 
|  |  | 
|  | 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 NULL; | 
|  | 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 |