Home | History | Annotate | Download | only in neteq
      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::CopyFrom(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