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 #include <assert.h>
14 
15 #include <algorithm>
16 
17 #include "rtc_base/checks.h"
18 
19 namespace webrtc {
20 
AudioMultiVector(size_t N)21 AudioMultiVector::AudioMultiVector(size_t N) {
22   assert(N > 0);
23   if (N < 1)
24     N = 1;
25   for (size_t n = 0; n < N; ++n) {
26     channels_.push_back(new AudioVector);
27   }
28   num_channels_ = N;
29 }
30 
AudioMultiVector(size_t N,size_t initial_size)31 AudioMultiVector::AudioMultiVector(size_t N, size_t initial_size) {
32   assert(N > 0);
33   if (N < 1)
34     N = 1;
35   for (size_t n = 0; n < N; ++n) {
36     channels_.push_back(new AudioVector(initial_size));
37   }
38   num_channels_ = N;
39 }
40 
~AudioMultiVector()41 AudioMultiVector::~AudioMultiVector() {
42   std::vector<AudioVector*>::iterator it = channels_.begin();
43   while (it != channels_.end()) {
44     delete (*it);
45     ++it;
46   }
47 }
48 
Clear()49 void AudioMultiVector::Clear() {
50   for (size_t i = 0; i < num_channels_; ++i) {
51     channels_[i]->Clear();
52   }
53 }
54 
Zeros(size_t length)55 void AudioMultiVector::Zeros(size_t length) {
56   for (size_t i = 0; i < num_channels_; ++i) {
57     channels_[i]->Clear();
58     channels_[i]->Extend(length);
59   }
60 }
61 
CopyTo(AudioMultiVector * copy_to) const62 void AudioMultiVector::CopyTo(AudioMultiVector* copy_to) const {
63   if (copy_to) {
64     for (size_t i = 0; i < num_channels_; ++i) {
65       channels_[i]->CopyTo(&(*copy_to)[i]);
66     }
67   }
68 }
69 
PushBackInterleaved(rtc::ArrayView<const int16_t> append_this)70 void AudioMultiVector::PushBackInterleaved(
71     rtc::ArrayView<const int16_t> append_this) {
72   RTC_DCHECK_EQ(append_this.size() % num_channels_, 0);
73   if (num_channels_ == 1) {
74     // Special case to avoid extra allocation and data shuffling.
75     channels_[0]->PushBack(append_this.data(), append_this.size());
76     return;
77   }
78   size_t length_per_channel = append_this.size() / num_channels_;
79   int16_t* temp_array = new int16_t[length_per_channel];  // Temporary storage.
80   for (size_t channel = 0; channel < num_channels_; ++channel) {
81     // Copy elements to |temp_array|.
82     // Set |source_ptr| to first element of this channel.
83     const int16_t* source_ptr = &append_this[channel];
84     for (size_t i = 0; i < length_per_channel; ++i) {
85       temp_array[i] = *source_ptr;
86       source_ptr += num_channels_;  // Jump to next element of this channel.
87     }
88     channels_[channel]->PushBack(temp_array, length_per_channel);
89   }
90   delete[] temp_array;
91 }
92 
PushBack(const AudioMultiVector & append_this)93 void AudioMultiVector::PushBack(const AudioMultiVector& append_this) {
94   assert(num_channels_ == append_this.num_channels_);
95   if (num_channels_ == append_this.num_channels_) {
96     for (size_t i = 0; i < num_channels_; ++i) {
97       channels_[i]->PushBack(append_this[i]);
98     }
99   }
100 }
101 
PushBackFromIndex(const AudioMultiVector & append_this,size_t index)102 void AudioMultiVector::PushBackFromIndex(const AudioMultiVector& append_this,
103                                          size_t index) {
104   assert(index < append_this.Size());
105   index = std::min(index, append_this.Size() - 1);
106   size_t length = append_this.Size() - index;
107   assert(num_channels_ == append_this.num_channels_);
108   if (num_channels_ == append_this.num_channels_) {
109     for (size_t i = 0; i < num_channels_; ++i) {
110       channels_[i]->PushBack(append_this[i], length, index);
111     }
112   }
113 }
114 
PopFront(size_t length)115 void AudioMultiVector::PopFront(size_t length) {
116   for (size_t i = 0; i < num_channels_; ++i) {
117     channels_[i]->PopFront(length);
118   }
119 }
120 
PopBack(size_t length)121 void AudioMultiVector::PopBack(size_t length) {
122   for (size_t i = 0; i < num_channels_; ++i) {
123     channels_[i]->PopBack(length);
124   }
125 }
126 
ReadInterleaved(size_t length,int16_t * destination) const127 size_t AudioMultiVector::ReadInterleaved(size_t length,
128                                          int16_t* destination) const {
129   return ReadInterleavedFromIndex(0, length, destination);
130 }
131 
ReadInterleavedFromIndex(size_t start_index,size_t length,int16_t * destination) const132 size_t AudioMultiVector::ReadInterleavedFromIndex(size_t start_index,
133                                                   size_t length,
134                                                   int16_t* destination) const {
135   RTC_DCHECK(destination);
136   size_t index = 0;  // Number of elements written to |destination| so far.
137   RTC_DCHECK_LE(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     (*this)[0].CopyTo(length, start_index, destination);
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], 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