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