• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_vector.h"
12 
13 #include <assert.h>
14 
15 #include <algorithm>
16 
17 #include "webrtc/typedefs.h"
18 
19 namespace webrtc {
20 
AudioVector()21 AudioVector::AudioVector()
22     : array_(new int16_t[kDefaultInitialSize]),
23       first_free_ix_(0),
24       capacity_(kDefaultInitialSize) {
25 }
26 
AudioVector(size_t initial_size)27 AudioVector::AudioVector(size_t initial_size)
28     : array_(new int16_t[initial_size]),
29       first_free_ix_(initial_size),
30       capacity_(initial_size) {
31   memset(array_.get(), 0, initial_size * sizeof(int16_t));
32 }
33 
34 AudioVector::~AudioVector() = default;
35 
Clear()36 void AudioVector::Clear() {
37   first_free_ix_ = 0;
38 }
39 
CopyTo(AudioVector * copy_to) const40 void AudioVector::CopyTo(AudioVector* copy_to) const {
41   if (copy_to) {
42     copy_to->Reserve(Size());
43     assert(copy_to->capacity_ >= Size());
44     memcpy(copy_to->array_.get(), array_.get(), Size() * sizeof(int16_t));
45     copy_to->first_free_ix_ = first_free_ix_;
46   }
47 }
48 
PushFront(const AudioVector & prepend_this)49 void AudioVector::PushFront(const AudioVector& prepend_this) {
50   size_t insert_length = prepend_this.Size();
51   Reserve(Size() + insert_length);
52   memmove(&array_[insert_length], &array_[0], Size() * sizeof(int16_t));
53   memcpy(&array_[0], &prepend_this.array_[0], insert_length * sizeof(int16_t));
54   first_free_ix_ += insert_length;
55 }
56 
PushFront(const int16_t * prepend_this,size_t length)57 void AudioVector::PushFront(const int16_t* prepend_this, size_t length) {
58   // Same operation as InsertAt beginning.
59   InsertAt(prepend_this, length, 0);
60 }
61 
PushBack(const AudioVector & append_this)62 void AudioVector::PushBack(const AudioVector& append_this) {
63   PushBack(append_this.array_.get(), append_this.Size());
64 }
65 
PushBack(const int16_t * append_this,size_t length)66 void AudioVector::PushBack(const int16_t* append_this, size_t length) {
67   Reserve(Size() + length);
68   memcpy(&array_[first_free_ix_], append_this, length * sizeof(int16_t));
69   first_free_ix_ += length;
70 }
71 
PopFront(size_t length)72 void AudioVector::PopFront(size_t length) {
73   if (length >= Size()) {
74     // Remove all elements.
75     Clear();
76   } else {
77     size_t remaining_samples = Size() - length;
78     memmove(&array_[0], &array_[length], remaining_samples * sizeof(int16_t));
79     first_free_ix_ -= length;
80   }
81 }
82 
PopBack(size_t length)83 void AudioVector::PopBack(size_t length) {
84   // Never remove more than what is in the array.
85   length = std::min(length, Size());
86   first_free_ix_ -= length;
87 }
88 
Extend(size_t extra_length)89 void AudioVector::Extend(size_t extra_length) {
90   Reserve(Size() + extra_length);
91   memset(&array_[first_free_ix_], 0, extra_length * sizeof(int16_t));
92   first_free_ix_ += extra_length;
93 }
94 
InsertAt(const int16_t * insert_this,size_t length,size_t position)95 void AudioVector::InsertAt(const int16_t* insert_this,
96                            size_t length,
97                            size_t position) {
98   Reserve(Size() + length);
99   // Cap the position at the current vector length, to be sure the iterator
100   // does not extend beyond the end of the vector.
101   position = std::min(Size(), position);
102   int16_t* insert_position_ptr = &array_[position];
103   size_t samples_to_move = Size() - position;
104   memmove(insert_position_ptr + length, insert_position_ptr,
105           samples_to_move * sizeof(int16_t));
106   memcpy(insert_position_ptr, insert_this, length * sizeof(int16_t));
107   first_free_ix_ += length;
108 }
109 
InsertZerosAt(size_t length,size_t position)110 void AudioVector::InsertZerosAt(size_t length,
111                                 size_t position) {
112   Reserve(Size() + length);
113   // Cap the position at the current vector length, to be sure the iterator
114   // does not extend beyond the end of the vector.
115   position = std::min(capacity_, position);
116   int16_t* insert_position_ptr = &array_[position];
117   size_t samples_to_move = Size() - position;
118   memmove(insert_position_ptr + length, insert_position_ptr,
119           samples_to_move * sizeof(int16_t));
120   memset(insert_position_ptr, 0, length * sizeof(int16_t));
121   first_free_ix_ += length;
122 }
123 
OverwriteAt(const int16_t * insert_this,size_t length,size_t position)124 void AudioVector::OverwriteAt(const int16_t* insert_this,
125                               size_t length,
126                               size_t position) {
127   // Cap the insert position at the current array length.
128   position = std::min(Size(), position);
129   Reserve(position + length);
130   memcpy(&array_[position], insert_this, length * sizeof(int16_t));
131   if (position + length > Size()) {
132     // Array was expanded.
133     first_free_ix_ += position + length - Size();
134   }
135 }
136 
CrossFade(const AudioVector & append_this,size_t fade_length)137 void AudioVector::CrossFade(const AudioVector& append_this,
138                             size_t fade_length) {
139   // Fade length cannot be longer than the current vector or |append_this|.
140   assert(fade_length <= Size());
141   assert(fade_length <= append_this.Size());
142   fade_length = std::min(fade_length, Size());
143   fade_length = std::min(fade_length, append_this.Size());
144   size_t position = Size() - fade_length;
145   // Cross fade the overlapping regions.
146   // |alpha| is the mixing factor in Q14.
147   // TODO(hlundin): Consider skipping +1 in the denominator to produce a
148   // smoother cross-fade, in particular at the end of the fade.
149   int alpha_step = 16384 / (static_cast<int>(fade_length) + 1);
150   int alpha = 16384;
151   for (size_t i = 0; i < fade_length; ++i) {
152     alpha -= alpha_step;
153     array_[position + i] = (alpha * array_[position + i] +
154         (16384 - alpha) * append_this[i] + 8192) >> 14;
155   }
156   assert(alpha >= 0);  // Verify that the slope was correct.
157   // Append what is left of |append_this|.
158   size_t samples_to_push_back = append_this.Size() - fade_length;
159   if (samples_to_push_back > 0)
160     PushBack(&append_this[fade_length], samples_to_push_back);
161 }
162 
163 // Returns the number of elements in this AudioVector.
Size() const164 size_t AudioVector::Size() const {
165   return first_free_ix_;
166 }
167 
168 // Returns true if this AudioVector is empty.
Empty() const169 bool AudioVector::Empty() const {
170   return first_free_ix_ == 0;
171 }
172 
operator [](size_t index) const173 const int16_t& AudioVector::operator[](size_t index) const {
174   return array_[index];
175 }
176 
operator [](size_t index)177 int16_t& AudioVector::operator[](size_t index) {
178   return array_[index];
179 }
180 
Reserve(size_t n)181 void AudioVector::Reserve(size_t n) {
182   if (capacity_ < n) {
183     rtc::scoped_ptr<int16_t[]> temp_array(new int16_t[n]);
184     memcpy(temp_array.get(), array_.get(), Size() * sizeof(int16_t));
185     array_.swap(temp_array);
186     capacity_ = n;
187   }
188 }
189 
190 }  // namespace webrtc
191