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
19namespace webrtc {
20
21AudioMultiVector::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
30AudioMultiVector::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
39AudioMultiVector::~AudioMultiVector() {
40  std::vector<AudioVector*>::iterator it = channels_.begin();
41  while (it != channels_.end()) {
42    delete (*it);
43    ++it;
44  }
45}
46
47void AudioMultiVector::Clear() {
48  for (size_t i = 0; i < num_channels_; ++i) {
49    channels_[i]->Clear();
50  }
51}
52
53void 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
60void 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
68void 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
91void 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
100void 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
113void AudioMultiVector::PopFront(size_t length) {
114  for (size_t i = 0; i < num_channels_; ++i) {
115    channels_[i]->PopFront(length);
116  }
117}
118
119void AudioMultiVector::PopBack(size_t length) {
120  for (size_t i = 0; i < num_channels_; ++i) {
121    channels_[i]->PopBack(length);
122  }
123}
124
125size_t AudioMultiVector::ReadInterleaved(size_t length,
126                                         int16_t* destination) const {
127  return ReadInterleavedFromIndex(0, length, destination);
128}
129
130size_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
156size_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
162void 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
176void 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
186size_t AudioMultiVector::Size() const {
187  assert(channels_[0]);
188  return channels_[0]->Size();
189}
190
191void AudioMultiVector::AssertSize(size_t required_size) {
192  if (Size() < required_size) {
193    size_t extend_length = required_size - Size();
194    for (size_t channel = 0; channel < num_channels_; ++channel) {
195      channels_[channel]->Extend(extend_length);
196    }
197  }
198}
199
200bool AudioMultiVector::Empty() const {
201  assert(channels_[0]);
202  return channels_[0]->Empty();
203}
204
205void AudioMultiVector::CopyChannel(size_t from_channel, size_t to_channel) {
206  assert(from_channel < num_channels_);
207  assert(to_channel < num_channels_);
208  channels_[from_channel]->CopyTo(channels_[to_channel]);
209}
210
211const AudioVector& AudioMultiVector::operator[](size_t index) const {
212  return *(channels_[index]);
213}
214
215AudioVector& AudioMultiVector::operator[](size_t index) {
216  return *(channels_[index]);
217}
218
219}  // namespace webrtc
220