blob: d1e06f5f91a573fa730cc235fb371bb33e1bbc06 [file] [log] [blame]
henrik.lundin@webrtc.org9a400812013-01-29 12:09:21 +00001/*
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/neteq4/audio_vector.h"
12
13#include <assert.h>
14
15#include <algorithm>
16
17#include "webrtc/typedefs.h"
18
19namespace webrtc {
20
21template<typename T>
22void AudioVector<T>::Clear() {
23 vector_.clear();
24}
25
26template<typename T>
27void AudioVector<T>::CopyFrom(AudioVector<T>* copy_to) const {
28 if (copy_to) {
29 copy_to->vector_.assign(vector_.begin(), vector_.end());
30 }
31}
32
33template<typename T>
34void AudioVector<T>::PushFront(const AudioVector<T>& prepend_this) {
35 vector_.insert(vector_.begin(), prepend_this.vector_.begin(),
36 prepend_this.vector_.end());
37}
38
39template<typename T>
40void AudioVector<T>::PushFront(const T* prepend_this, size_t length) {
41 // Same operation as InsertAt beginning.
42 InsertAt(prepend_this, length, 0);
43}
44
45template<typename T>
46void AudioVector<T>::PushBack(const AudioVector<T>& append_this) {
47 vector_.reserve(vector_.size() + append_this.Size());
48 for (size_t i = 0; i < append_this.Size(); ++i) {
49 vector_.push_back(append_this[i]);
50 }
51}
52
53template<typename T>
54void AudioVector<T>::PushBack(const T* append_this, size_t length) {
55 vector_.reserve(vector_.size() + length);
56 for (size_t i = 0; i < length; ++i) {
57 vector_.push_back(append_this[i]);
58 }
59}
60
61template<typename T>
62void AudioVector<T>::PopFront(size_t length) {
63 if (length >= vector_.size()) {
64 // Remove all elements.
65 vector_.clear();
66 } else {
67 typename std::vector<T>::iterator end_range = vector_.begin();
68 end_range += length;
69 // Erase all elements in range vector_.begin() and |end_range| (not
70 // including |end_range|).
71 vector_.erase(vector_.begin(), end_range);
72 }
73}
74
75template<typename T>
76void AudioVector<T>::PopBack(size_t length) {
77 // Make sure that new_size is never negative (which causes wrap-around).
78 size_t new_size = vector_.size() - std::min(length, vector_.size());
79 vector_.resize(new_size);
80}
81
82template<typename T>
83void AudioVector<T>::Extend(size_t extra_length) {
84 vector_.insert(vector_.end(), extra_length, 0);
85}
86
87template<typename T>
88void AudioVector<T>::InsertAt(const T* insert_this,
89 size_t length,
90 size_t position) {
91 typename std::vector<T>::iterator insert_position = vector_.begin();
92 // Cap the position at the current vector length, to be sure the iterator
93 // does not extend beyond the end of the vector.
94 position = std::min(vector_.size(), position);
95 insert_position += position;
96 // First, insert zeros at the position. This makes the vector longer (and
97 // invalidates the iterator |insert_position|.
98 vector_.insert(insert_position, length, 0);
99 // Write the new values into the vector.
100 for (size_t i = 0; i < length; ++i) {
101 vector_[position + i] = insert_this[i];
102 }
103}
104
105template<typename T>
106void AudioVector<T>::InsertZerosAt(size_t length,
107 size_t position) {
108 typename std::vector<T>::iterator insert_position = vector_.begin();
109 // Cap the position at the current vector length, to be sure the iterator
110 // does not extend beyond the end of the vector.
111 position = std::min(vector_.size(), position);
112 insert_position += position;
113 // Insert zeros at the position. This makes the vector longer (and
114 // invalidates the iterator |insert_position|.
115 vector_.insert(insert_position, length, 0);
116}
117
118template<typename T>
119void AudioVector<T>::OverwriteAt(const T* insert_this,
120 size_t length,
121 size_t position) {
122 // Cap the insert position at the current vector length.
123 position = std::min(vector_.size(), position);
124 // Extend the vector if needed. (It is valid to overwrite beyond the current
125 // end of the vector.)
126 if (position + length > vector_.size()) {
127 Extend(position + length - vector_.size());
128 }
129 for (size_t i = 0; i < length; ++i) {
130 vector_[position + i] = insert_this[i];
131 }
132}
133
134template<typename T>
135void AudioVector<T>::CrossFade(const AudioVector<T>& append_this,
136 size_t fade_length) {
137 // Fade length cannot be longer than the current vector or |append_this|.
138 assert(fade_length <= Size());
139 assert(fade_length <= append_this.Size());
140 fade_length = std::min(fade_length, Size());
141 fade_length = std::min(fade_length, append_this.Size());
142 size_t position = Size() - fade_length;
143 // Cross fade the overlapping regions.
144 // |alpha| is the mixing factor in Q14.
145 // TODO(hlundin): Consider skipping +1 in the denominator to produce a
146 // smoother cross-fade, in particular at the end of the fade.
147 int alpha_step = 16384 / (fade_length + 1);
148 int alpha = 16384;
149 for (size_t i = 0; i < fade_length; ++i) {
150 alpha -= alpha_step;
151 vector_[position + i] = (alpha * vector_[position + i] +
152 (16384 - alpha) * append_this[i] + 8192) >> 14;
153 }
154 assert(alpha >= 0); // Verify that the slope was correct.
155 // Append what is left of |append_this|.
henrik.lundin@webrtc.org3b70afa2013-01-30 09:41:56 +0000156 size_t samples_to_push_back = append_this.Size() - fade_length;
157 if (samples_to_push_back > 0)
158 PushBack(&append_this[fade_length], samples_to_push_back);
henrik.lundin@webrtc.org9a400812013-01-29 12:09:21 +0000159}
160
161// Template specialization for double. The only difference is in the calculation
162// of the cross-faded value, where we divide by 16384 instead of shifting with
163// 14 steps, and also not adding 8192 before scaling.
164template<>
165void AudioVector<double>::CrossFade(const AudioVector<double>& append_this,
166 size_t fade_length) {
167 // Fade length cannot be longer than the current vector or |append_this|.
168 assert(fade_length <= Size());
169 assert(fade_length <= append_this.Size());
170 fade_length = std::min(fade_length, Size());
171 fade_length = std::min(fade_length, append_this.Size());
172 size_t position = Size() - fade_length;
173 // Cross fade the overlapping regions.
174 // |alpha| is the mixing factor in Q14.
175 // TODO(hlundin): Consider skipping +1 in the denominator to produce a
176 // smoother cross-fade, in particular at the end of the fade.
177 int alpha_step = 16384 / (fade_length + 1);
178 int alpha = 16384;
179 for (size_t i = 0; i < fade_length; ++i) {
180 alpha -= alpha_step;
181 vector_[position + i] = (alpha * vector_[position + i] +
182 (16384 - alpha) * append_this[i]) / 16384;
183 }
184 assert(alpha >= 0); // Verify that the slope was correct.
185 // Append what is left of |append_this|.
henrik.lundin@webrtc.org3b70afa2013-01-30 09:41:56 +0000186 size_t samples_to_push_back = append_this.Size() - fade_length;
187 if (samples_to_push_back > 0)
188 PushBack(&append_this[fade_length], samples_to_push_back);
henrik.lundin@webrtc.org9a400812013-01-29 12:09:21 +0000189}
190
191template<typename T>
192const T& AudioVector<T>::operator[](size_t index) const {
193 return vector_[index];
194}
195
196template<typename T>
197T& AudioVector<T>::operator[](size_t index) {
198 return vector_[index];
199}
200
201// Instantiate the template for a few types.
202template class AudioVector<int16_t>;
203template class AudioVector<int32_t>;
204template class AudioVector<double>;
205
206} // namespace webrtc