audio_multi_vector.cc (7465B)
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 <algorithm> 14 #include <cstddef> 15 #include <cstdint> 16 #include <memory> 17 #include <vector> 18 19 #include "api/array_view.h" 20 #include "api/audio/audio_view.h" 21 #include "modules/audio_coding/neteq/audio_vector.h" 22 #include "rtc_base/checks.h" 23 24 namespace webrtc { 25 namespace { 26 std::vector<std::unique_ptr<AudioVector>> InitializeChannelVector( 27 size_t num_channels, 28 size_t channel_size = 0u) { 29 RTC_DCHECK_GT(num_channels, 0u); 30 RTC_CHECK_LE(num_channels, kMaxNumberOfAudioChannels); 31 std::vector<std::unique_ptr<AudioVector>> channels(num_channels); 32 for (auto& c : channels) { 33 c = channel_size ? std::make_unique<AudioVector>(channel_size) 34 : std::make_unique<AudioVector>(); 35 } 36 return channels; 37 } 38 } // namespace 39 40 AudioMultiVector::AudioMultiVector(size_t N) 41 : channels_(InitializeChannelVector(N)) {} 42 43 AudioMultiVector::AudioMultiVector(size_t N, size_t initial_size) 44 : channels_(InitializeChannelVector(N, initial_size)) {} 45 46 AudioMultiVector::~AudioMultiVector() = default; 47 48 void AudioMultiVector::Clear() { 49 for (auto& c : channels_) { 50 c->Clear(); 51 } 52 } 53 54 void AudioMultiVector::Zeros(size_t length) { 55 for (auto& c : channels_) { 56 c->Clear(); 57 c->Extend(length); 58 } 59 } 60 61 void AudioMultiVector::CopyTo(AudioMultiVector* copy_to) const { 62 if (copy_to) { 63 for (size_t i = 0; i < Channels(); ++i) { 64 channels_[i]->CopyTo(&(*copy_to)[i]); 65 } 66 } 67 } 68 69 void AudioMultiVector::PushBackInterleaved( 70 ArrayView<const int16_t> append_this) { 71 RTC_DCHECK_EQ(append_this.size() % Channels(), 0); 72 if (append_this.empty()) { 73 return; 74 } 75 if (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() / Channels(); 81 int16_t* temp_array = new int16_t[length_per_channel]; // Temporary storage. 82 for (size_t channel = 0; channel < 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 * Channels()]; 86 } 87 channels_[channel]->PushBack(temp_array, length_per_channel); 88 } 89 delete[] temp_array; 90 } 91 92 void AudioMultiVector::PushBack(const AudioMultiVector& append_this) { 93 RTC_DCHECK_EQ(Channels(), append_this.Channels()); 94 if (Channels() == append_this.Channels()) { 95 for (size_t i = 0; i < Channels(); ++i) { 96 channels_[i]->PushBack(append_this[i]); 97 } 98 } 99 } 100 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(Channels(), append_this.Channels()); 107 if (Channels() == append_this.Channels()) { 108 for (size_t i = 0; i < Channels(); ++i) { 109 channels_[i]->PushBack(append_this[i], length, index); 110 } 111 } 112 } 113 114 void AudioMultiVector::PopFront(size_t length) { 115 for (auto& c : channels_) { 116 c->PopFront(length); 117 } 118 } 119 120 void AudioMultiVector::PopBack(size_t length) { 121 for (auto& c : channels_) { 122 c->PopBack(length); 123 } 124 } 125 126 size_t AudioMultiVector::ReadInterleaved(size_t length, 127 int16_t* destination) const { 128 return ReadInterleavedFromIndex(0, length, destination); 129 } 130 131 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 (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 < Channels(); ++channel) { 148 destination[index] = (*this)[channel][i + start_index]; 149 ++index; 150 } 151 } 152 return index; 153 } 154 155 bool AudioMultiVector::ReadInterleavedFromIndex( 156 const size_t start_index, 157 InterleavedView<int16_t> dst) const { 158 RTC_DCHECK_EQ(dst.num_channels(), Channels()); 159 if (start_index + dst.samples_per_channel() > Size()) { 160 return false; 161 } 162 if (Channels() == 1) { 163 // Special case to avoid the nested for loop below. 164 return channels_[0]->CopyTo(start_index, dst.AsMono()); 165 } 166 size_t index = 0; 167 for (size_t i = 0; i < dst.samples_per_channel(); ++i) { 168 for (const auto& ch : channels_) { 169 dst[index] = (*ch)[i + start_index]; 170 ++index; 171 } 172 } 173 return true; 174 } 175 176 size_t AudioMultiVector::ReadInterleavedFromEnd(size_t length, 177 int16_t* destination) const { 178 length = std::min(length, Size()); // Cannot read more than Size() elements. 179 return ReadInterleavedFromIndex(Size() - length, length, destination); 180 } 181 182 void AudioMultiVector::OverwriteAt(const AudioMultiVector& insert_this, 183 size_t length, 184 size_t position) { 185 RTC_DCHECK_EQ(Channels(), insert_this.Channels()); 186 // Cap `length` at the length of `insert_this`. 187 RTC_DCHECK_LE(length, insert_this.Size()); 188 length = std::min(length, insert_this.Size()); 189 if (Channels() == insert_this.Channels()) { 190 for (size_t i = 0; i < Channels(); ++i) { 191 channels_[i]->OverwriteAt(insert_this[i], length, position); 192 } 193 } 194 } 195 196 void AudioMultiVector::CrossFade(const AudioMultiVector& append_this, 197 size_t fade_length) { 198 RTC_DCHECK_EQ(Channels(), append_this.Channels()); 199 if (Channels() == append_this.Channels()) { 200 for (size_t i = 0; i < Channels(); ++i) { 201 channels_[i]->CrossFade(append_this[i], fade_length); 202 } 203 } 204 } 205 206 size_t AudioMultiVector::Channels() const { 207 return channels_.size(); 208 } 209 210 size_t AudioMultiVector::Size() const { 211 RTC_DCHECK(channels_[0]); 212 return channels_[0]->Size(); 213 } 214 215 void AudioMultiVector::AssertSize(size_t required_size) { 216 if (Size() < required_size) { 217 size_t extend_length = required_size - Size(); 218 for (auto& c : channels_) { 219 c->Extend(extend_length); 220 } 221 } 222 } 223 224 bool AudioMultiVector::Empty() const { 225 RTC_DCHECK(channels_[0]); 226 return channels_[0]->Empty(); 227 } 228 229 void AudioMultiVector::CopyChannel(size_t from_channel, size_t to_channel) { 230 RTC_DCHECK_LT(from_channel, Channels()); 231 RTC_DCHECK_LT(to_channel, Channels()); 232 channels_[from_channel]->CopyTo(channels_[to_channel].get()); 233 } 234 235 const AudioVector& AudioMultiVector::operator[](size_t index) const { 236 return *(channels_[index]); 237 } 238 239 AudioVector& AudioMultiVector::operator[](size_t index) { 240 return *(channels_[index]); 241 } 242 243 } // namespace webrtc