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