Reimplementing NetEq4's AudioVector
The current implementation using std::vector is too slow. This CL introduces a new implementation, using a regular array as data container. In AudioMultiVector::ReadInterleavedFromIndex, a special case for 1 channel was implemented, to further reduce runtime. Finally, AudioMultiVector::Channels was reimplemented. The changes in this CL reduces the runtime of neteq4_speed_test by 33%. BUG=1363 R=turaj@webrtc.org Review URL: https://webrtc-codereview.appspot.com/3509004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@5115 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
@@ -24,6 +24,7 @@ AudioMultiVector::AudioMultiVector(size_t N) {
|
|||||||
for (size_t n = 0; n < N; ++n) {
|
for (size_t n = 0; n < N; ++n) {
|
||||||
channels_.push_back(new AudioVector);
|
channels_.push_back(new AudioVector);
|
||||||
}
|
}
|
||||||
|
num_channels_ = N;
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioMultiVector::AudioMultiVector(size_t N, size_t initial_size) {
|
AudioMultiVector::AudioMultiVector(size_t N, size_t initial_size) {
|
||||||
@@ -32,6 +33,7 @@ AudioMultiVector::AudioMultiVector(size_t N, size_t initial_size) {
|
|||||||
for (size_t n = 0; n < N; ++n) {
|
for (size_t n = 0; n < N; ++n) {
|
||||||
channels_.push_back(new AudioVector(initial_size));
|
channels_.push_back(new AudioVector(initial_size));
|
||||||
}
|
}
|
||||||
|
num_channels_ = N;
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioMultiVector::~AudioMultiVector() {
|
AudioMultiVector::~AudioMultiVector() {
|
||||||
@@ -43,13 +45,13 @@ AudioMultiVector::~AudioMultiVector() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AudioMultiVector::Clear() {
|
void AudioMultiVector::Clear() {
|
||||||
for (size_t i = 0; i < Channels(); ++i) {
|
for (size_t i = 0; i < num_channels_; ++i) {
|
||||||
channels_[i]->Clear();
|
channels_[i]->Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioMultiVector::Zeros(size_t length) {
|
void AudioMultiVector::Zeros(size_t length) {
|
||||||
for (size_t i = 0; i < Channels(); ++i) {
|
for (size_t i = 0; i < num_channels_; ++i) {
|
||||||
channels_[i]->Clear();
|
channels_[i]->Clear();
|
||||||
channels_[i]->Extend(length);
|
channels_[i]->Extend(length);
|
||||||
}
|
}
|
||||||
@@ -57,7 +59,7 @@ void AudioMultiVector::Zeros(size_t length) {
|
|||||||
|
|
||||||
void AudioMultiVector::CopyFrom(AudioMultiVector* copy_to) const {
|
void AudioMultiVector::CopyFrom(AudioMultiVector* copy_to) const {
|
||||||
if (copy_to) {
|
if (copy_to) {
|
||||||
for (size_t i = 0; i < Channels(); ++i) {
|
for (size_t i = 0; i < num_channels_; ++i) {
|
||||||
channels_[i]->CopyFrom(&(*copy_to)[i]);
|
channels_[i]->CopyFrom(&(*copy_to)[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -65,22 +67,22 @@ void AudioMultiVector::CopyFrom(AudioMultiVector* copy_to) const {
|
|||||||
|
|
||||||
void AudioMultiVector::PushBackInterleaved(const int16_t* append_this,
|
void AudioMultiVector::PushBackInterleaved(const int16_t* append_this,
|
||||||
size_t length) {
|
size_t length) {
|
||||||
assert(length % Channels() == 0);
|
assert(length % num_channels_ == 0);
|
||||||
if (Channels() == 1) {
|
if (num_channels_ == 1) {
|
||||||
// Special case to avoid extra allocation and data shuffling.
|
// Special case to avoid extra allocation and data shuffling.
|
||||||
channels_[0]->PushBack(append_this, length);
|
channels_[0]->PushBack(append_this, length);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
size_t length_per_channel = length / Channels();
|
size_t length_per_channel = length / num_channels_;
|
||||||
int16_t* temp_array =
|
int16_t* temp_array =
|
||||||
new int16_t[length_per_channel]; // Intermediate storage.
|
new int16_t[length_per_channel]; // Intermediate storage.
|
||||||
for (size_t channel = 0; channel < Channels(); ++channel) {
|
for (size_t channel = 0; channel < num_channels_; ++channel) {
|
||||||
// Copy elements to |temp_array|.
|
// Copy elements to |temp_array|.
|
||||||
// Set |source_ptr| to first element of this channel.
|
// Set |source_ptr| to first element of this channel.
|
||||||
const int16_t* source_ptr = &append_this[channel];
|
const int16_t* source_ptr = &append_this[channel];
|
||||||
for (size_t i = 0; i < length_per_channel; ++i) {
|
for (size_t i = 0; i < length_per_channel; ++i) {
|
||||||
temp_array[i] = *source_ptr;
|
temp_array[i] = *source_ptr;
|
||||||
source_ptr += Channels(); // Jump to next element of this channel.
|
source_ptr += num_channels_; // Jump to next element of this channel.
|
||||||
}
|
}
|
||||||
channels_[channel]->PushBack(temp_array, length_per_channel);
|
channels_[channel]->PushBack(temp_array, length_per_channel);
|
||||||
}
|
}
|
||||||
@@ -88,9 +90,9 @@ void AudioMultiVector::PushBackInterleaved(const int16_t* append_this,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AudioMultiVector::PushBack(const AudioMultiVector& append_this) {
|
void AudioMultiVector::PushBack(const AudioMultiVector& append_this) {
|
||||||
assert(Channels() == append_this.Channels());
|
assert(num_channels_ == append_this.num_channels_);
|
||||||
if (Channels() == append_this.Channels()) {
|
if (num_channels_ == append_this.num_channels_) {
|
||||||
for (size_t i = 0; i < Channels(); ++i) {
|
for (size_t i = 0; i < num_channels_; ++i) {
|
||||||
channels_[i]->PushBack(append_this[i]);
|
channels_[i]->PushBack(append_this[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -101,22 +103,22 @@ void AudioMultiVector::PushBackFromIndex(const AudioMultiVector& append_this,
|
|||||||
assert(index < append_this.Size());
|
assert(index < append_this.Size());
|
||||||
index = std::min(index, append_this.Size() - 1);
|
index = std::min(index, append_this.Size() - 1);
|
||||||
size_t length = append_this.Size() - index;
|
size_t length = append_this.Size() - index;
|
||||||
assert(Channels() == append_this.Channels());
|
assert(num_channels_ == append_this.num_channels_);
|
||||||
if (Channels() == append_this.Channels()) {
|
if (num_channels_ == append_this.num_channels_) {
|
||||||
for (size_t i = 0; i < Channels(); ++i) {
|
for (size_t i = 0; i < num_channels_; ++i) {
|
||||||
channels_[i]->PushBack(&append_this[i][index], length);
|
channels_[i]->PushBack(&append_this[i][index], length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioMultiVector::PopFront(size_t length) {
|
void AudioMultiVector::PopFront(size_t length) {
|
||||||
for (size_t i = 0; i < Channels(); ++i) {
|
for (size_t i = 0; i < num_channels_; ++i) {
|
||||||
channels_[i]->PopFront(length);
|
channels_[i]->PopFront(length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioMultiVector::PopBack(size_t length) {
|
void AudioMultiVector::PopBack(size_t length) {
|
||||||
for (size_t i = 0; i < Channels(); ++i) {
|
for (size_t i = 0; i < num_channels_; ++i) {
|
||||||
channels_[i]->PopBack(length);
|
channels_[i]->PopBack(length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -138,8 +140,13 @@ size_t AudioMultiVector::ReadInterleavedFromIndex(size_t start_index,
|
|||||||
if (length + start_index > Size()) {
|
if (length + start_index > Size()) {
|
||||||
length = Size() - start_index;
|
length = Size() - start_index;
|
||||||
}
|
}
|
||||||
|
if (num_channels_ == 1) {
|
||||||
|
// Special case to avoid the nested for loop below.
|
||||||
|
memcpy(destination, &(*this)[0][start_index], length * sizeof(int16_t));
|
||||||
|
return length;
|
||||||
|
}
|
||||||
for (size_t i = 0; i < length; ++i) {
|
for (size_t i = 0; i < length; ++i) {
|
||||||
for (size_t channel = 0; channel < Channels(); ++channel) {
|
for (size_t channel = 0; channel < num_channels_; ++channel) {
|
||||||
destination[index] = (*this)[channel][i + start_index];
|
destination[index] = (*this)[channel][i + start_index];
|
||||||
++index;
|
++index;
|
||||||
}
|
}
|
||||||
@@ -156,12 +163,12 @@ size_t AudioMultiVector::ReadInterleavedFromEnd(size_t length,
|
|||||||
void AudioMultiVector::OverwriteAt(const AudioMultiVector& insert_this,
|
void AudioMultiVector::OverwriteAt(const AudioMultiVector& insert_this,
|
||||||
size_t length,
|
size_t length,
|
||||||
size_t position) {
|
size_t position) {
|
||||||
assert(Channels() == insert_this.Channels());
|
assert(num_channels_ == insert_this.num_channels_);
|
||||||
// Cap |length| at the length of |insert_this|.
|
// Cap |length| at the length of |insert_this|.
|
||||||
assert(length <= insert_this.Size());
|
assert(length <= insert_this.Size());
|
||||||
length = std::min(length, insert_this.Size());
|
length = std::min(length, insert_this.Size());
|
||||||
if (Channels() == insert_this.Channels()) {
|
if (num_channels_ == insert_this.num_channels_) {
|
||||||
for (size_t i = 0; i < Channels(); ++i) {
|
for (size_t i = 0; i < num_channels_; ++i) {
|
||||||
channels_[i]->OverwriteAt(&insert_this[i][0], length, position);
|
channels_[i]->OverwriteAt(&insert_this[i][0], length, position);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -169,9 +176,9 @@ void AudioMultiVector::OverwriteAt(const AudioMultiVector& insert_this,
|
|||||||
|
|
||||||
void AudioMultiVector::CrossFade(const AudioMultiVector& append_this,
|
void AudioMultiVector::CrossFade(const AudioMultiVector& append_this,
|
||||||
size_t fade_length) {
|
size_t fade_length) {
|
||||||
assert(Channels() == append_this.Channels());
|
assert(num_channels_ == append_this.num_channels_);
|
||||||
if (Channels() == append_this.Channels()) {
|
if (num_channels_ == append_this.num_channels_) {
|
||||||
for (size_t i = 0; i < Channels(); ++i) {
|
for (size_t i = 0; i < num_channels_; ++i) {
|
||||||
channels_[i]->CrossFade(append_this[i], fade_length);
|
channels_[i]->CrossFade(append_this[i], fade_length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -185,7 +192,7 @@ size_t AudioMultiVector::Size() const {
|
|||||||
void AudioMultiVector::AssertSize(size_t required_size) {
|
void AudioMultiVector::AssertSize(size_t required_size) {
|
||||||
if (Size() < required_size) {
|
if (Size() < required_size) {
|
||||||
size_t extend_length = required_size - Size();
|
size_t extend_length = required_size - Size();
|
||||||
for (size_t channel = 0; channel < Channels(); ++channel) {
|
for (size_t channel = 0; channel < num_channels_; ++channel) {
|
||||||
channels_[channel]->Extend(extend_length);
|
channels_[channel]->Extend(extend_length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ class AudioMultiVector {
|
|||||||
size_t fade_length);
|
size_t fade_length);
|
||||||
|
|
||||||
// Returns the number of channels.
|
// Returns the number of channels.
|
||||||
virtual size_t Channels() const { return channels_.size(); }
|
virtual size_t Channels() const { return num_channels_; }
|
||||||
|
|
||||||
// Returns the number of elements per channel in this AudioMultiVector.
|
// Returns the number of elements per channel in this AudioMultiVector.
|
||||||
virtual size_t Size() const;
|
virtual size_t Size() const;
|
||||||
@@ -124,6 +124,7 @@ class AudioMultiVector {
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::vector<AudioVector*> channels_;
|
std::vector<AudioVector*> channels_;
|
||||||
|
size_t num_channels_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DISALLOW_COPY_AND_ASSIGN(AudioMultiVector);
|
DISALLOW_COPY_AND_ASSIGN(AudioMultiVector);
|
||||||
|
|||||||
@@ -19,18 +19,24 @@
|
|||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
void AudioVector::Clear() {
|
void AudioVector::Clear() {
|
||||||
vector_.clear();
|
first_free_ix_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioVector::CopyFrom(AudioVector* copy_to) const {
|
void AudioVector::CopyFrom(AudioVector* copy_to) const {
|
||||||
if (copy_to) {
|
if (copy_to) {
|
||||||
copy_to->vector_.assign(vector_.begin(), vector_.end());
|
copy_to->Reserve(Size());
|
||||||
|
assert(copy_to->capacity_ >= Size());
|
||||||
|
memcpy(copy_to->array_.get(), array_.get(), Size() * sizeof(int16_t));
|
||||||
|
copy_to->first_free_ix_ = first_free_ix_;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioVector::PushFront(const AudioVector& prepend_this) {
|
void AudioVector::PushFront(const AudioVector& prepend_this) {
|
||||||
vector_.insert(vector_.begin(), prepend_this.vector_.begin(),
|
size_t insert_length = prepend_this.Size();
|
||||||
prepend_this.vector_.end());
|
Reserve(Size() + insert_length);
|
||||||
|
memmove(&array_[insert_length], &array_[0], Size() * sizeof(int16_t));
|
||||||
|
memcpy(&array_[0], &prepend_this.array_[0], insert_length * sizeof(int16_t));
|
||||||
|
first_free_ix_ += insert_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioVector::PushFront(const int16_t* prepend_this, size_t length) {
|
void AudioVector::PushFront(const int16_t* prepend_this, size_t length) {
|
||||||
@@ -39,83 +45,77 @@ void AudioVector::PushFront(const int16_t* prepend_this, size_t length) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AudioVector::PushBack(const AudioVector& append_this) {
|
void AudioVector::PushBack(const AudioVector& append_this) {
|
||||||
vector_.reserve(vector_.size() + append_this.Size());
|
PushBack(append_this.array_.get(), append_this.Size());
|
||||||
for (size_t i = 0; i < append_this.Size(); ++i) {
|
|
||||||
vector_.push_back(append_this[i]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioVector::PushBack(const int16_t* append_this, size_t length) {
|
void AudioVector::PushBack(const int16_t* append_this, size_t length) {
|
||||||
vector_.reserve(vector_.size() + length);
|
Reserve(Size() + length);
|
||||||
for (size_t i = 0; i < length; ++i) {
|
memcpy(&array_[first_free_ix_], append_this, length * sizeof(int16_t));
|
||||||
vector_.push_back(append_this[i]);
|
first_free_ix_ += length;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioVector::PopFront(size_t length) {
|
void AudioVector::PopFront(size_t length) {
|
||||||
if (length >= vector_.size()) {
|
if (length >= Size()) {
|
||||||
// Remove all elements.
|
// Remove all elements.
|
||||||
vector_.clear();
|
Clear();
|
||||||
} else {
|
} else {
|
||||||
std::vector<int16_t>::iterator end_range = vector_.begin();
|
size_t remaining_samples = Size() - length;
|
||||||
end_range += length;
|
memmove(&array_[0], &array_[length], remaining_samples * sizeof(int16_t));
|
||||||
// Erase all elements in range vector_.begin() and |end_range| (not
|
first_free_ix_ -= length;
|
||||||
// including |end_range|).
|
|
||||||
vector_.erase(vector_.begin(), end_range);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioVector::PopBack(size_t length) {
|
void AudioVector::PopBack(size_t length) {
|
||||||
// Make sure that new_size is never negative (which causes wrap-around).
|
// Never remove more than what is in the array.
|
||||||
size_t new_size = vector_.size() - std::min(length, vector_.size());
|
length = std::min(length, Size());
|
||||||
vector_.resize(new_size);
|
first_free_ix_ -= length;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioVector::Extend(size_t extra_length) {
|
void AudioVector::Extend(size_t extra_length) {
|
||||||
vector_.insert(vector_.end(), extra_length, 0);
|
Reserve(Size() + extra_length);
|
||||||
|
memset(&array_[first_free_ix_], 0, extra_length * sizeof(int16_t));
|
||||||
|
first_free_ix_ += extra_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioVector::InsertAt(const int16_t* insert_this,
|
void AudioVector::InsertAt(const int16_t* insert_this,
|
||||||
size_t length,
|
size_t length,
|
||||||
size_t position) {
|
size_t position) {
|
||||||
std::vector<int16_t>::iterator insert_position = vector_.begin();
|
Reserve(Size() + length);
|
||||||
// Cap the position at the current vector length, to be sure the iterator
|
// Cap the position at the current vector length, to be sure the iterator
|
||||||
// does not extend beyond the end of the vector.
|
// does not extend beyond the end of the vector.
|
||||||
position = std::min(vector_.size(), position);
|
position = std::min(Size(), position);
|
||||||
insert_position += position;
|
int16_t* insert_position_ptr = &array_[position];
|
||||||
// First, insert zeros at the position. This makes the vector longer (and
|
size_t samples_to_move = Size() - position;
|
||||||
// invalidates the iterator |insert_position|.
|
memmove(insert_position_ptr + length, insert_position_ptr,
|
||||||
vector_.insert(insert_position, length, 0);
|
samples_to_move * sizeof(int16_t));
|
||||||
// Write the new values into the vector.
|
memcpy(insert_position_ptr, insert_this, length * sizeof(int16_t));
|
||||||
for (size_t i = 0; i < length; ++i) {
|
first_free_ix_ += length;
|
||||||
vector_[position + i] = insert_this[i];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioVector::InsertZerosAt(size_t length,
|
void AudioVector::InsertZerosAt(size_t length,
|
||||||
size_t position) {
|
size_t position) {
|
||||||
std::vector<int16_t>::iterator insert_position = vector_.begin();
|
Reserve(Size() + length);
|
||||||
// Cap the position at the current vector length, to be sure the iterator
|
// Cap the position at the current vector length, to be sure the iterator
|
||||||
// does not extend beyond the end of the vector.
|
// does not extend beyond the end of the vector.
|
||||||
position = std::min(vector_.size(), position);
|
position = std::min(capacity_, position);
|
||||||
insert_position += position;
|
int16_t* insert_position_ptr = &array_[position];
|
||||||
// Insert zeros at the position. This makes the vector longer (and
|
size_t samples_to_move = Size() - position;
|
||||||
// invalidates the iterator |insert_position|.
|
memmove(insert_position_ptr + length, insert_position_ptr,
|
||||||
vector_.insert(insert_position, length, 0);
|
samples_to_move * sizeof(int16_t));
|
||||||
|
memset(insert_position_ptr, 0, length * sizeof(int16_t));
|
||||||
|
first_free_ix_ += length;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioVector::OverwriteAt(const int16_t* insert_this,
|
void AudioVector::OverwriteAt(const int16_t* insert_this,
|
||||||
size_t length,
|
size_t length,
|
||||||
size_t position) {
|
size_t position) {
|
||||||
// Cap the insert position at the current vector length.
|
// Cap the insert position at the current array length.
|
||||||
position = std::min(vector_.size(), position);
|
position = std::min(Size(), position);
|
||||||
// Extend the vector if needed. (It is valid to overwrite beyond the current
|
Reserve(position + length);
|
||||||
// end of the vector.)
|
memcpy(&array_[position], insert_this, length * sizeof(int16_t));
|
||||||
if (position + length > vector_.size()) {
|
if (position + length > Size()) {
|
||||||
Extend(position + length - vector_.size());
|
// Array was expanded.
|
||||||
}
|
first_free_ix_ += position + length - Size();
|
||||||
for (size_t i = 0; i < length; ++i) {
|
|
||||||
vector_[position + i] = insert_this[i];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,7 +135,7 @@ void AudioVector::CrossFade(const AudioVector& append_this,
|
|||||||
int alpha = 16384;
|
int alpha = 16384;
|
||||||
for (size_t i = 0; i < fade_length; ++i) {
|
for (size_t i = 0; i < fade_length; ++i) {
|
||||||
alpha -= alpha_step;
|
alpha -= alpha_step;
|
||||||
vector_[position + i] = (alpha * vector_[position + i] +
|
array_[position + i] = (alpha * array_[position + i] +
|
||||||
(16384 - alpha) * append_this[i] + 8192) >> 14;
|
(16384 - alpha) * append_this[i] + 8192) >> 14;
|
||||||
}
|
}
|
||||||
assert(alpha >= 0); // Verify that the slope was correct.
|
assert(alpha >= 0); // Verify that the slope was correct.
|
||||||
@@ -146,11 +146,20 @@ void AudioVector::CrossFade(const AudioVector& append_this,
|
|||||||
}
|
}
|
||||||
|
|
||||||
const int16_t& AudioVector::operator[](size_t index) const {
|
const int16_t& AudioVector::operator[](size_t index) const {
|
||||||
return vector_[index];
|
return array_[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
int16_t& AudioVector::operator[](size_t index) {
|
int16_t& AudioVector::operator[](size_t index) {
|
||||||
return vector_[index];
|
return array_[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioVector::Reserve(size_t n) {
|
||||||
|
if (capacity_ < n) {
|
||||||
|
scoped_ptr<int16_t[]> temp_array(new int16_t[n]);
|
||||||
|
memcpy(temp_array.get(), array_.get(), Size() * sizeof(int16_t));
|
||||||
|
array_.swap(temp_array);
|
||||||
|
capacity_ = n;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|||||||
@@ -13,9 +13,8 @@
|
|||||||
|
|
||||||
#include <string.h> // Access to size_t.
|
#include <string.h> // Access to size_t.
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "webrtc/system_wrappers/interface/constructor_magic.h"
|
#include "webrtc/system_wrappers/interface/constructor_magic.h"
|
||||||
|
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
|
||||||
#include "webrtc/typedefs.h"
|
#include "webrtc/typedefs.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
@@ -23,11 +22,18 @@ namespace webrtc {
|
|||||||
class AudioVector {
|
class AudioVector {
|
||||||
public:
|
public:
|
||||||
// Creates an empty AudioVector.
|
// Creates an empty AudioVector.
|
||||||
AudioVector() {}
|
AudioVector()
|
||||||
|
: array_(new int16_t[kDefaultInitialSize]),
|
||||||
|
first_free_ix_(0),
|
||||||
|
capacity_(kDefaultInitialSize) {}
|
||||||
|
|
||||||
// Creates an AudioVector with an initial size.
|
// Creates an AudioVector with an initial size.
|
||||||
explicit AudioVector(size_t initial_size)
|
explicit AudioVector(size_t initial_size)
|
||||||
: vector_(initial_size, 0) {}
|
: array_(new int16_t[initial_size]),
|
||||||
|
first_free_ix_(initial_size),
|
||||||
|
capacity_(initial_size) {
|
||||||
|
memset(array_.get(), 0, initial_size * sizeof(int16_t));
|
||||||
|
}
|
||||||
|
|
||||||
virtual ~AudioVector() {}
|
virtual ~AudioVector() {}
|
||||||
|
|
||||||
@@ -88,17 +94,24 @@ class AudioVector {
|
|||||||
virtual void CrossFade(const AudioVector& append_this, size_t fade_length);
|
virtual void CrossFade(const AudioVector& append_this, size_t fade_length);
|
||||||
|
|
||||||
// Returns the number of elements in this AudioVector.
|
// Returns the number of elements in this AudioVector.
|
||||||
virtual size_t Size() const { return vector_.size(); }
|
virtual size_t Size() const { return first_free_ix_; }
|
||||||
|
|
||||||
// Returns true if this AudioVector is empty.
|
// Returns true if this AudioVector is empty.
|
||||||
virtual bool Empty() const { return vector_.empty(); }
|
virtual bool Empty() const { return (first_free_ix_ == 0); }
|
||||||
|
|
||||||
// Accesses and modifies an element of AudioVector.
|
// Accesses and modifies an element of AudioVector.
|
||||||
const int16_t& operator[](size_t index) const;
|
const int16_t& operator[](size_t index) const;
|
||||||
int16_t& operator[](size_t index);
|
int16_t& operator[](size_t index);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<int16_t> vector_;
|
static const size_t kDefaultInitialSize = 10;
|
||||||
|
|
||||||
|
void Reserve(size_t n);
|
||||||
|
|
||||||
|
scoped_ptr<int16_t[]> array_;
|
||||||
|
size_t first_free_ix_; // The first index after the last sample in array_.
|
||||||
|
// Note that this index may point outside of array_.
|
||||||
|
size_t capacity_; // Allocated number of samples in the array.
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(AudioVector);
|
DISALLOW_COPY_AND_ASSIGN(AudioVector);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user