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_coding/neteq/audio_vector.h"
12
13 #include <assert.h>
14
15 #include <algorithm>
16
17 #include "webrtc/typedefs.h"
18
19 namespace webrtc {
20
AudioVector()21 AudioVector::AudioVector()
22 : array_(new int16_t[kDefaultInitialSize]),
23 first_free_ix_(0),
24 capacity_(kDefaultInitialSize) {
25 }
26
AudioVector(size_t initial_size)27 AudioVector::AudioVector(size_t initial_size)
28 : array_(new int16_t[initial_size]),
29 first_free_ix_(initial_size),
30 capacity_(initial_size) {
31 memset(array_.get(), 0, initial_size * sizeof(int16_t));
32 }
33
34 AudioVector::~AudioVector() = default;
35
Clear()36 void AudioVector::Clear() {
37 first_free_ix_ = 0;
38 }
39
CopyTo(AudioVector * copy_to) const40 void AudioVector::CopyTo(AudioVector* copy_to) const {
41 if (copy_to) {
42 copy_to->Reserve(Size());
43 assert(copy_to->capacity_ >= Size());
44 memcpy(copy_to->array_.get(), array_.get(), Size() * sizeof(int16_t));
45 copy_to->first_free_ix_ = first_free_ix_;
46 }
47 }
48
PushFront(const AudioVector & prepend_this)49 void AudioVector::PushFront(const AudioVector& prepend_this) {
50 size_t insert_length = prepend_this.Size();
51 Reserve(Size() + insert_length);
52 memmove(&array_[insert_length], &array_[0], Size() * sizeof(int16_t));
53 memcpy(&array_[0], &prepend_this.array_[0], insert_length * sizeof(int16_t));
54 first_free_ix_ += insert_length;
55 }
56
PushFront(const int16_t * prepend_this,size_t length)57 void AudioVector::PushFront(const int16_t* prepend_this, size_t length) {
58 // Same operation as InsertAt beginning.
59 InsertAt(prepend_this, length, 0);
60 }
61
PushBack(const AudioVector & append_this)62 void AudioVector::PushBack(const AudioVector& append_this) {
63 PushBack(append_this.array_.get(), append_this.Size());
64 }
65
PushBack(const int16_t * append_this,size_t length)66 void AudioVector::PushBack(const int16_t* append_this, size_t length) {
67 Reserve(Size() + length);
68 memcpy(&array_[first_free_ix_], append_this, length * sizeof(int16_t));
69 first_free_ix_ += length;
70 }
71
PopFront(size_t length)72 void AudioVector::PopFront(size_t length) {
73 if (length >= Size()) {
74 // Remove all elements.
75 Clear();
76 } else {
77 size_t remaining_samples = Size() - length;
78 memmove(&array_[0], &array_[length], remaining_samples * sizeof(int16_t));
79 first_free_ix_ -= length;
80 }
81 }
82
PopBack(size_t length)83 void AudioVector::PopBack(size_t length) {
84 // Never remove more than what is in the array.
85 length = std::min(length, Size());
86 first_free_ix_ -= length;
87 }
88
Extend(size_t extra_length)89 void AudioVector::Extend(size_t extra_length) {
90 Reserve(Size() + extra_length);
91 memset(&array_[first_free_ix_], 0, extra_length * sizeof(int16_t));
92 first_free_ix_ += extra_length;
93 }
94
InsertAt(const int16_t * insert_this,size_t length,size_t position)95 void AudioVector::InsertAt(const int16_t* insert_this,
96 size_t length,
97 size_t position) {
98 Reserve(Size() + length);
99 // Cap the position at the current vector length, to be sure the iterator
100 // does not extend beyond the end of the vector.
101 position = std::min(Size(), position);
102 int16_t* insert_position_ptr = &array_[position];
103 size_t samples_to_move = Size() - position;
104 memmove(insert_position_ptr + length, insert_position_ptr,
105 samples_to_move * sizeof(int16_t));
106 memcpy(insert_position_ptr, insert_this, length * sizeof(int16_t));
107 first_free_ix_ += length;
108 }
109
InsertZerosAt(size_t length,size_t position)110 void AudioVector::InsertZerosAt(size_t length,
111 size_t position) {
112 Reserve(Size() + length);
113 // Cap the position at the current vector length, to be sure the iterator
114 // does not extend beyond the end of the vector.
115 position = std::min(capacity_, position);
116 int16_t* insert_position_ptr = &array_[position];
117 size_t samples_to_move = Size() - position;
118 memmove(insert_position_ptr + length, insert_position_ptr,
119 samples_to_move * sizeof(int16_t));
120 memset(insert_position_ptr, 0, length * sizeof(int16_t));
121 first_free_ix_ += length;
122 }
123
OverwriteAt(const int16_t * insert_this,size_t length,size_t position)124 void AudioVector::OverwriteAt(const int16_t* insert_this,
125 size_t length,
126 size_t position) {
127 // Cap the insert position at the current array length.
128 position = std::min(Size(), position);
129 Reserve(position + length);
130 memcpy(&array_[position], insert_this, length * sizeof(int16_t));
131 if (position + length > Size()) {
132 // Array was expanded.
133 first_free_ix_ += position + length - Size();
134 }
135 }
136
CrossFade(const AudioVector & append_this,size_t fade_length)137 void AudioVector::CrossFade(const AudioVector& append_this,
138 size_t fade_length) {
139 // Fade length cannot be longer than the current vector or |append_this|.
140 assert(fade_length <= Size());
141 assert(fade_length <= append_this.Size());
142 fade_length = std::min(fade_length, Size());
143 fade_length = std::min(fade_length, append_this.Size());
144 size_t position = Size() - fade_length;
145 // Cross fade the overlapping regions.
146 // |alpha| is the mixing factor in Q14.
147 // TODO(hlundin): Consider skipping +1 in the denominator to produce a
148 // smoother cross-fade, in particular at the end of the fade.
149 int alpha_step = 16384 / (static_cast<int>(fade_length) + 1);
150 int alpha = 16384;
151 for (size_t i = 0; i < fade_length; ++i) {
152 alpha -= alpha_step;
153 array_[position + i] = (alpha * array_[position + i] +
154 (16384 - alpha) * append_this[i] + 8192) >> 14;
155 }
156 assert(alpha >= 0); // Verify that the slope was correct.
157 // Append what is left of |append_this|.
158 size_t samples_to_push_back = append_this.Size() - fade_length;
159 if (samples_to_push_back > 0)
160 PushBack(&append_this[fade_length], samples_to_push_back);
161 }
162
163 // Returns the number of elements in this AudioVector.
Size() const164 size_t AudioVector::Size() const {
165 return first_free_ix_;
166 }
167
168 // Returns true if this AudioVector is empty.
Empty() const169 bool AudioVector::Empty() const {
170 return first_free_ix_ == 0;
171 }
172
operator [](size_t index) const173 const int16_t& AudioVector::operator[](size_t index) const {
174 return array_[index];
175 }
176
operator [](size_t index)177 int16_t& AudioVector::operator[](size_t index) {
178 return array_[index];
179 }
180
Reserve(size_t n)181 void AudioVector::Reserve(size_t n) {
182 if (capacity_ < n) {
183 rtc::scoped_ptr<int16_t[]> temp_array(new int16_t[n]);
184 memcpy(temp_array.get(), array_.get(), Size() * sizeof(int16_t));
185 array_.swap(temp_array);
186 capacity_ = n;
187 }
188 }
189
190 } // namespace webrtc
191