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_multi_vector.h"
12
13 #include <assert.h>
14
15 #include <algorithm>
16
17 #include "webrtc/typedefs.h"
18
19 namespace webrtc {
20
AudioMultiVector(size_t N)21 AudioMultiVector::AudioMultiVector(size_t N) {
22 assert(N > 0);
23 if (N < 1) N = 1;
24 for (size_t n = 0; n < N; ++n) {
25 channels_.push_back(new AudioVector);
26 }
27 num_channels_ = N;
28 }
29
AudioMultiVector(size_t N,size_t initial_size)30 AudioMultiVector::AudioMultiVector(size_t N, size_t initial_size) {
31 assert(N > 0);
32 if (N < 1) N = 1;
33 for (size_t n = 0; n < N; ++n) {
34 channels_.push_back(new AudioVector(initial_size));
35 }
36 num_channels_ = N;
37 }
38
~AudioMultiVector()39 AudioMultiVector::~AudioMultiVector() {
40 std::vector<AudioVector*>::iterator it = channels_.begin();
41 while (it != channels_.end()) {
42 delete (*it);
43 ++it;
44 }
45 }
46
Clear()47 void AudioMultiVector::Clear() {
48 for (size_t i = 0; i < num_channels_; ++i) {
49 channels_[i]->Clear();
50 }
51 }
52
Zeros(size_t length)53 void AudioMultiVector::Zeros(size_t length) {
54 for (size_t i = 0; i < num_channels_; ++i) {
55 channels_[i]->Clear();
56 channels_[i]->Extend(length);
57 }
58 }
59
CopyTo(AudioMultiVector * copy_to) const60 void AudioMultiVector::CopyTo(AudioMultiVector* copy_to) const {
61 if (copy_to) {
62 for (size_t i = 0; i < num_channels_; ++i) {
63 channels_[i]->CopyTo(&(*copy_to)[i]);
64 }
65 }
66 }
67
PushBackInterleaved(const int16_t * append_this,size_t length)68 void AudioMultiVector::PushBackInterleaved(const int16_t* append_this,
69 size_t length) {
70 assert(length % num_channels_ == 0);
71 if (num_channels_ == 1) {
72 // Special case to avoid extra allocation and data shuffling.
73 channels_[0]->PushBack(append_this, length);
74 return;
75 }
76 size_t length_per_channel = length / num_channels_;
77 int16_t* temp_array = new int16_t[length_per_channel]; // Temporary storage.
78 for (size_t channel = 0; channel < num_channels_; ++channel) {
79 // Copy elements to |temp_array|.
80 // Set |source_ptr| to first element of this channel.
81 const int16_t* source_ptr = &append_this[channel];
82 for (size_t i = 0; i < length_per_channel; ++i) {
83 temp_array[i] = *source_ptr;
84 source_ptr += num_channels_; // Jump to next element of this channel.
85 }
86 channels_[channel]->PushBack(temp_array, length_per_channel);
87 }
88 delete [] temp_array;
89 }
90
PushBack(const AudioMultiVector & append_this)91 void AudioMultiVector::PushBack(const AudioMultiVector& append_this) {
92 assert(num_channels_ == append_this.num_channels_);
93 if (num_channels_ == append_this.num_channels_) {
94 for (size_t i = 0; i < num_channels_; ++i) {
95 channels_[i]->PushBack(append_this[i]);
96 }
97 }
98 }
99
PushBackFromIndex(const AudioMultiVector & append_this,size_t index)100 void AudioMultiVector::PushBackFromIndex(const AudioMultiVector& append_this,
101 size_t index) {
102 assert(index < append_this.Size());
103 index = std::min(index, append_this.Size() - 1);
104 size_t length = append_this.Size() - index;
105 assert(num_channels_ == append_this.num_channels_);
106 if (num_channels_ == append_this.num_channels_) {
107 for (size_t i = 0; i < num_channels_; ++i) {
108 channels_[i]->PushBack(&append_this[i][index], length);
109 }
110 }
111 }
112
PopFront(size_t length)113 void AudioMultiVector::PopFront(size_t length) {
114 for (size_t i = 0; i < num_channels_; ++i) {
115 channels_[i]->PopFront(length);
116 }
117 }
118
PopBack(size_t length)119 void AudioMultiVector::PopBack(size_t length) {
120 for (size_t i = 0; i < num_channels_; ++i) {
121 channels_[i]->PopBack(length);
122 }
123 }
124
ReadInterleaved(size_t length,int16_t * destination) const125 size_t AudioMultiVector::ReadInterleaved(size_t length,
126 int16_t* destination) const {
127 return ReadInterleavedFromIndex(0, length, destination);
128 }
129
ReadInterleavedFromIndex(size_t start_index,size_t length,int16_t * destination) const130 size_t AudioMultiVector::ReadInterleavedFromIndex(size_t start_index,
131 size_t length,
132 int16_t* destination) const {
133 if (!destination) {
134 return 0;
135 }
136 size_t index = 0; // Number of elements written to |destination| so far.
137 assert(start_index <= Size());
138 start_index = std::min(start_index, Size());
139 if (length + start_index > Size()) {
140 length = Size() - start_index;
141 }
142 if (num_channels_ == 1) {
143 // Special case to avoid the nested for loop below.
144 memcpy(destination, &(*this)[0][start_index], length * sizeof(int16_t));
145 return length;
146 }
147 for (size_t i = 0; i < length; ++i) {
148 for (size_t channel = 0; channel < num_channels_; ++channel) {
149 destination[index] = (*this)[channel][i + start_index];
150 ++index;
151 }
152 }
153 return index;
154 }
155
ReadInterleavedFromEnd(size_t length,int16_t * destination) const156 size_t AudioMultiVector::ReadInterleavedFromEnd(size_t length,
157 int16_t* destination) const {
158 length = std::min(length, Size()); // Cannot read more than Size() elements.
159 return ReadInterleavedFromIndex(Size() - length, length, destination);
160 }
161
OverwriteAt(const AudioMultiVector & insert_this,size_t length,size_t position)162 void AudioMultiVector::OverwriteAt(const AudioMultiVector& insert_this,
163 size_t length,
164 size_t position) {
165 assert(num_channels_ == insert_this.num_channels_);
166 // Cap |length| at the length of |insert_this|.
167 assert(length <= insert_this.Size());
168 length = std::min(length, insert_this.Size());
169 if (num_channels_ == insert_this.num_channels_) {
170 for (size_t i = 0; i < num_channels_; ++i) {
171 channels_[i]->OverwriteAt(&insert_this[i][0], length, position);
172 }
173 }
174 }
175
CrossFade(const AudioMultiVector & append_this,size_t fade_length)176 void AudioMultiVector::CrossFade(const AudioMultiVector& append_this,
177 size_t fade_length) {
178 assert(num_channels_ == append_this.num_channels_);
179 if (num_channels_ == append_this.num_channels_) {
180 for (size_t i = 0; i < num_channels_; ++i) {
181 channels_[i]->CrossFade(append_this[i], fade_length);
182 }
183 }
184 }
185
Channels() const186 size_t AudioMultiVector::Channels() const {
187 return num_channels_;
188 }
189
Size() const190 size_t AudioMultiVector::Size() const {
191 assert(channels_[0]);
192 return channels_[0]->Size();
193 }
194
AssertSize(size_t required_size)195 void AudioMultiVector::AssertSize(size_t required_size) {
196 if (Size() < required_size) {
197 size_t extend_length = required_size - Size();
198 for (size_t channel = 0; channel < num_channels_; ++channel) {
199 channels_[channel]->Extend(extend_length);
200 }
201 }
202 }
203
Empty() const204 bool AudioMultiVector::Empty() const {
205 assert(channels_[0]);
206 return channels_[0]->Empty();
207 }
208
CopyChannel(size_t from_channel,size_t to_channel)209 void AudioMultiVector::CopyChannel(size_t from_channel, size_t to_channel) {
210 assert(from_channel < num_channels_);
211 assert(to_channel < num_channels_);
212 channels_[from_channel]->CopyTo(channels_[to_channel]);
213 }
214
operator [](size_t index) const215 const AudioVector& AudioMultiVector::operator[](size_t index) const {
216 return *(channels_[index]);
217 }
218
operator [](size_t index)219 AudioVector& AudioMultiVector::operator[](size_t index) {
220 return *(channels_[index]);
221 }
222
223 } // namespace webrtc
224