Home | History | Annotate | Download | only in audio_processing
      1 /*
      2  *  Copyright (c) 2011 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 "audio_buffer.h"
     12 
     13 #include "signal_processing_library.h"
     14 
     15 namespace webrtc {
     16 namespace {
     17 
     18 enum {
     19   kSamplesPer8kHzChannel = 80,
     20   kSamplesPer16kHzChannel = 160,
     21   kSamplesPer32kHzChannel = 320
     22 };
     23 
     24 void StereoToMono(const int16_t* left, const int16_t* right,
     25                   int16_t* out, int samples_per_channel) {
     26   assert(left != NULL && right != NULL && out != NULL);
     27   for (int i = 0; i < samples_per_channel; i++) {
     28     int32_t data32 = (static_cast<int32_t>(left[i]) +
     29                       static_cast<int32_t>(right[i])) >> 1;
     30 
     31     out[i] = WebRtcSpl_SatW32ToW16(data32);
     32   }
     33 }
     34 }  // namespace
     35 
     36 struct AudioChannel {
     37   AudioChannel() {
     38     memset(data, 0, sizeof(data));
     39   }
     40 
     41   int16_t data[kSamplesPer32kHzChannel];
     42 };
     43 
     44 struct SplitAudioChannel {
     45   SplitAudioChannel() {
     46     memset(low_pass_data, 0, sizeof(low_pass_data));
     47     memset(high_pass_data, 0, sizeof(high_pass_data));
     48     memset(analysis_filter_state1, 0, sizeof(analysis_filter_state1));
     49     memset(analysis_filter_state2, 0, sizeof(analysis_filter_state2));
     50     memset(synthesis_filter_state1, 0, sizeof(synthesis_filter_state1));
     51     memset(synthesis_filter_state2, 0, sizeof(synthesis_filter_state2));
     52   }
     53 
     54   int16_t low_pass_data[kSamplesPer16kHzChannel];
     55   int16_t high_pass_data[kSamplesPer16kHzChannel];
     56 
     57   WebRtc_Word32 analysis_filter_state1[6];
     58   WebRtc_Word32 analysis_filter_state2[6];
     59   WebRtc_Word32 synthesis_filter_state1[6];
     60   WebRtc_Word32 synthesis_filter_state2[6];
     61 };
     62 
     63 // TODO(andrew): check range of input parameters?
     64 AudioBuffer::AudioBuffer(int max_num_channels,
     65                          int samples_per_channel)
     66   : max_num_channels_(max_num_channels),
     67     num_channels_(0),
     68     num_mixed_channels_(0),
     69     num_mixed_low_pass_channels_(0),
     70     data_was_mixed_(false),
     71     samples_per_channel_(samples_per_channel),
     72     samples_per_split_channel_(samples_per_channel),
     73     reference_copied_(false),
     74     activity_(AudioFrame::kVadUnknown),
     75     is_muted_(false),
     76     data_(NULL),
     77     channels_(NULL),
     78     split_channels_(NULL),
     79     mixed_channels_(NULL),
     80     mixed_low_pass_channels_(NULL),
     81     low_pass_reference_channels_(NULL) {
     82   if (max_num_channels_ > 1) {
     83     channels_.reset(new AudioChannel[max_num_channels_]);
     84     mixed_channels_.reset(new AudioChannel[max_num_channels_]);
     85     mixed_low_pass_channels_.reset(new AudioChannel[max_num_channels_]);
     86   }
     87   low_pass_reference_channels_.reset(new AudioChannel[max_num_channels_]);
     88 
     89   if (samples_per_channel_ == kSamplesPer32kHzChannel) {
     90     split_channels_.reset(new SplitAudioChannel[max_num_channels_]);
     91     samples_per_split_channel_ = kSamplesPer16kHzChannel;
     92   }
     93 }
     94 
     95 AudioBuffer::~AudioBuffer() {}
     96 
     97 int16_t* AudioBuffer::data(int channel) const {
     98   assert(channel >= 0 && channel < num_channels_);
     99   if (data_ != NULL) {
    100     return data_;
    101   }
    102 
    103   return channels_[channel].data;
    104 }
    105 
    106 int16_t* AudioBuffer::low_pass_split_data(int channel) const {
    107   assert(channel >= 0 && channel < num_channels_);
    108   if (split_channels_.get() == NULL) {
    109     return data(channel);
    110   }
    111 
    112   return split_channels_[channel].low_pass_data;
    113 }
    114 
    115 int16_t* AudioBuffer::high_pass_split_data(int channel) const {
    116   assert(channel >= 0 && channel < num_channels_);
    117   if (split_channels_.get() == NULL) {
    118     return NULL;
    119   }
    120 
    121   return split_channels_[channel].high_pass_data;
    122 }
    123 
    124 int16_t* AudioBuffer::mixed_data(int channel) const {
    125   assert(channel >= 0 && channel < num_mixed_channels_);
    126 
    127   return mixed_channels_[channel].data;
    128 }
    129 
    130 int16_t* AudioBuffer::mixed_low_pass_data(int channel) const {
    131   assert(channel >= 0 && channel < num_mixed_low_pass_channels_);
    132 
    133   return mixed_low_pass_channels_[channel].data;
    134 }
    135 
    136 int16_t* AudioBuffer::low_pass_reference(int channel) const {
    137   assert(channel >= 0 && channel < num_channels_);
    138   if (!reference_copied_) {
    139     return NULL;
    140   }
    141 
    142   return low_pass_reference_channels_[channel].data;
    143 }
    144 
    145 WebRtc_Word32* AudioBuffer::analysis_filter_state1(int channel) const {
    146   assert(channel >= 0 && channel < num_channels_);
    147   return split_channels_[channel].analysis_filter_state1;
    148 }
    149 
    150 WebRtc_Word32* AudioBuffer::analysis_filter_state2(int channel) const {
    151   assert(channel >= 0 && channel < num_channels_);
    152   return split_channels_[channel].analysis_filter_state2;
    153 }
    154 
    155 WebRtc_Word32* AudioBuffer::synthesis_filter_state1(int channel) const {
    156   assert(channel >= 0 && channel < num_channels_);
    157   return split_channels_[channel].synthesis_filter_state1;
    158 }
    159 
    160 WebRtc_Word32* AudioBuffer::synthesis_filter_state2(int channel) const {
    161   assert(channel >= 0 && channel < num_channels_);
    162   return split_channels_[channel].synthesis_filter_state2;
    163 }
    164 
    165 void AudioBuffer::set_activity(AudioFrame::VADActivity activity) {
    166   activity_ = activity;
    167 }
    168 
    169 AudioFrame::VADActivity AudioBuffer::activity() const {
    170   return activity_;
    171 }
    172 
    173 bool AudioBuffer::is_muted() const {
    174   return is_muted_;
    175 }
    176 
    177 int AudioBuffer::num_channels() const {
    178   return num_channels_;
    179 }
    180 
    181 int AudioBuffer::samples_per_channel() const {
    182   return samples_per_channel_;
    183 }
    184 
    185 int AudioBuffer::samples_per_split_channel() const {
    186   return samples_per_split_channel_;
    187 }
    188 
    189 // TODO(andrew): Do deinterleaving and mixing in one step?
    190 void AudioBuffer::DeinterleaveFrom(AudioFrame* frame) {
    191   assert(frame->_audioChannel <= max_num_channels_);
    192   assert(frame->_payloadDataLengthInSamples ==  samples_per_channel_);
    193 
    194   num_channels_ = frame->_audioChannel;
    195   data_was_mixed_ = false;
    196   num_mixed_channels_ = 0;
    197   num_mixed_low_pass_channels_ = 0;
    198   reference_copied_ = false;
    199   activity_ = frame->_vadActivity;
    200   is_muted_ = false;
    201   if (frame->_energy == 0) {
    202     is_muted_ = true;
    203   }
    204 
    205   if (num_channels_ == 1) {
    206     // We can get away with a pointer assignment in this case.
    207     data_ = frame->_payloadData;
    208     return;
    209   }
    210 
    211   int16_t* interleaved = frame->_payloadData;
    212   for (int i = 0; i < num_channels_; i++) {
    213     int16_t* deinterleaved = channels_[i].data;
    214     int interleaved_idx = i;
    215     for (int j = 0; j < samples_per_channel_; j++) {
    216       deinterleaved[j] = interleaved[interleaved_idx];
    217       interleaved_idx += num_channels_;
    218     }
    219   }
    220 }
    221 
    222 void AudioBuffer::InterleaveTo(AudioFrame* frame, bool data_changed) const {
    223   assert(frame->_audioChannel == num_channels_);
    224   assert(frame->_payloadDataLengthInSamples == samples_per_channel_);
    225   frame->_vadActivity = activity_;
    226 
    227   if (!data_changed) {
    228     return;
    229   }
    230 
    231   if (num_channels_ == 1) {
    232     if (data_was_mixed_) {
    233       memcpy(frame->_payloadData,
    234              channels_[0].data,
    235              sizeof(int16_t) * samples_per_channel_);
    236     } else {
    237       // These should point to the same buffer in this case.
    238       assert(data_ == frame->_payloadData);
    239     }
    240 
    241     return;
    242   }
    243 
    244   int16_t* interleaved = frame->_payloadData;
    245   for (int i = 0; i < num_channels_; i++) {
    246     int16_t* deinterleaved = channels_[i].data;
    247     int interleaved_idx = i;
    248     for (int j = 0; j < samples_per_channel_; j++) {
    249       interleaved[interleaved_idx] = deinterleaved[j];
    250       interleaved_idx += num_channels_;
    251     }
    252   }
    253 }
    254 
    255 // TODO(andrew): would be good to support the no-mix case with pointer
    256 // assignment.
    257 // TODO(andrew): handle mixing to multiple channels?
    258 void AudioBuffer::Mix(int num_mixed_channels) {
    259   // We currently only support the stereo to mono case.
    260   assert(num_channels_ == 2);
    261   assert(num_mixed_channels == 1);
    262 
    263   StereoToMono(channels_[0].data,
    264                channels_[1].data,
    265                channels_[0].data,
    266                samples_per_channel_);
    267 
    268   num_channels_ = num_mixed_channels;
    269   data_was_mixed_ = true;
    270 }
    271 
    272 void AudioBuffer::CopyAndMix(int num_mixed_channels) {
    273   // We currently only support the stereo to mono case.
    274   assert(num_channels_ == 2);
    275   assert(num_mixed_channels == 1);
    276 
    277   StereoToMono(channels_[0].data,
    278                channels_[1].data,
    279                mixed_channels_[0].data,
    280                samples_per_channel_);
    281 
    282   num_mixed_channels_ = num_mixed_channels;
    283 }
    284 
    285 void AudioBuffer::CopyAndMixLowPass(int num_mixed_channels) {
    286   // We currently only support the stereo to mono case.
    287   assert(num_channels_ == 2);
    288   assert(num_mixed_channels == 1);
    289 
    290   StereoToMono(low_pass_split_data(0),
    291                low_pass_split_data(1),
    292                mixed_low_pass_channels_[0].data,
    293                samples_per_split_channel_);
    294 
    295   num_mixed_low_pass_channels_ = num_mixed_channels;
    296 }
    297 
    298 void AudioBuffer::CopyLowPassToReference() {
    299   reference_copied_ = true;
    300   for (int i = 0; i < num_channels_; i++) {
    301     memcpy(low_pass_reference_channels_[i].data,
    302            low_pass_split_data(i),
    303            sizeof(int16_t) * samples_per_split_channel_);
    304   }
    305 }
    306 }  // namespace webrtc
    307