Home | History | Annotate | Download | only in voice_engine
      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/voice_engine/utility.h"
     12 
     13 #include "webrtc/common_audio/resampler/include/push_resampler.h"
     14 #include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
     15 #include "webrtc/common_types.h"
     16 #include "webrtc/modules/interface/module_common_types.h"
     17 #include "webrtc/modules/utility/interface/audio_frame_operations.h"
     18 #include "webrtc/system_wrappers/interface/logging.h"
     19 #include "webrtc/voice_engine/voice_engine_defines.h"
     20 
     21 namespace webrtc {
     22 namespace voe {
     23 
     24 // TODO(ajm): There is significant overlap between RemixAndResample and
     25 // ConvertToCodecFormat, but if we're to consolidate we should probably make a
     26 // real converter class.
     27 void RemixAndResample(const AudioFrame& src_frame,
     28                       PushResampler<int16_t>* resampler,
     29                       AudioFrame* dst_frame) {
     30   const int16_t* audio_ptr = src_frame.data_;
     31   int audio_ptr_num_channels = src_frame.num_channels_;
     32   int16_t mono_audio[AudioFrame::kMaxDataSizeSamples];
     33 
     34   // Downmix before resampling.
     35   if (src_frame.num_channels_ == 2 && dst_frame->num_channels_ == 1) {
     36     AudioFrameOperations::StereoToMono(src_frame.data_,
     37                                        src_frame.samples_per_channel_,
     38                                        mono_audio);
     39     audio_ptr = mono_audio;
     40     audio_ptr_num_channels = 1;
     41   }
     42 
     43   if (resampler->InitializeIfNeeded(src_frame.sample_rate_hz_,
     44                                     dst_frame->sample_rate_hz_,
     45                                     audio_ptr_num_channels) == -1) {
     46     LOG_FERR3(LS_ERROR, InitializeIfNeeded, src_frame.sample_rate_hz_,
     47               dst_frame->sample_rate_hz_, audio_ptr_num_channels);
     48     assert(false);
     49   }
     50 
     51   const int src_length = src_frame.samples_per_channel_ *
     52                          audio_ptr_num_channels;
     53   int out_length = resampler->Resample(audio_ptr, src_length, dst_frame->data_,
     54                                        AudioFrame::kMaxDataSizeSamples);
     55   if (out_length == -1) {
     56     LOG_FERR3(LS_ERROR, Resample, audio_ptr, src_length, dst_frame->data_);
     57     assert(false);
     58   }
     59   dst_frame->samples_per_channel_ = out_length / audio_ptr_num_channels;
     60 
     61   // Upmix after resampling.
     62   if (src_frame.num_channels_ == 1 && dst_frame->num_channels_ == 2) {
     63     // The audio in dst_frame really is mono at this point; MonoToStereo will
     64     // set this back to stereo.
     65     dst_frame->num_channels_ = 1;
     66     AudioFrameOperations::MonoToStereo(dst_frame);
     67   }
     68 
     69   dst_frame->timestamp_ = src_frame.timestamp_;
     70   dst_frame->elapsed_time_ms_ = src_frame.elapsed_time_ms_;
     71   dst_frame->ntp_time_ms_ = src_frame.ntp_time_ms_;
     72 }
     73 
     74 void DownConvertToCodecFormat(const int16_t* src_data,
     75                               int samples_per_channel,
     76                               int num_channels,
     77                               int sample_rate_hz,
     78                               int codec_num_channels,
     79                               int codec_rate_hz,
     80                               int16_t* mono_buffer,
     81                               PushResampler<int16_t>* resampler,
     82                               AudioFrame* dst_af) {
     83   assert(samples_per_channel <= kMaxMonoDataSizeSamples);
     84   assert(num_channels == 1 || num_channels == 2);
     85   assert(codec_num_channels == 1 || codec_num_channels == 2);
     86   dst_af->Reset();
     87 
     88   // Never upsample the capture signal here. This should be done at the
     89   // end of the send chain.
     90   int destination_rate = std::min(codec_rate_hz, sample_rate_hz);
     91 
     92   // If no stereo codecs are in use, we downmix a stereo stream from the
     93   // device early in the chain, before resampling.
     94   if (num_channels == 2 && codec_num_channels == 1) {
     95     AudioFrameOperations::StereoToMono(src_data, samples_per_channel,
     96                                        mono_buffer);
     97     src_data = mono_buffer;
     98     num_channels = 1;
     99   }
    100 
    101   if (resampler->InitializeIfNeeded(
    102           sample_rate_hz, destination_rate, num_channels) != 0) {
    103     LOG_FERR3(LS_ERROR,
    104               InitializeIfNeeded,
    105               sample_rate_hz,
    106               destination_rate,
    107               num_channels);
    108     assert(false);
    109   }
    110 
    111   const int in_length = samples_per_channel * num_channels;
    112   int out_length = resampler->Resample(
    113       src_data, in_length, dst_af->data_, AudioFrame::kMaxDataSizeSamples);
    114   if (out_length == -1) {
    115     LOG_FERR3(LS_ERROR, Resample, src_data, in_length, dst_af->data_);
    116     assert(false);
    117   }
    118 
    119   dst_af->samples_per_channel_ = out_length / num_channels;
    120   dst_af->sample_rate_hz_ = destination_rate;
    121   dst_af->num_channels_ = num_channels;
    122 }
    123 
    124 void MixWithSat(int16_t target[],
    125                 int target_channel,
    126                 const int16_t source[],
    127                 int source_channel,
    128                 int source_len) {
    129   assert(target_channel == 1 || target_channel == 2);
    130   assert(source_channel == 1 || source_channel == 2);
    131 
    132   if (target_channel == 2 && source_channel == 1) {
    133     // Convert source from mono to stereo.
    134     int32_t left = 0;
    135     int32_t right = 0;
    136     for (int i = 0; i < source_len; ++i) {
    137       left = source[i] + target[i * 2];
    138       right = source[i] + target[i * 2 + 1];
    139       target[i * 2] = WebRtcSpl_SatW32ToW16(left);
    140       target[i * 2 + 1] = WebRtcSpl_SatW32ToW16(right);
    141     }
    142   } else if (target_channel == 1 && source_channel == 2) {
    143     // Convert source from stereo to mono.
    144     int32_t temp = 0;
    145     for (int i = 0; i < source_len / 2; ++i) {
    146       temp = ((source[i * 2] + source[i * 2 + 1]) >> 1) + target[i];
    147       target[i] = WebRtcSpl_SatW32ToW16(temp);
    148     }
    149   } else {
    150     int32_t temp = 0;
    151     for (int i = 0; i < source_len; ++i) {
    152       temp = source[i] + target[i];
    153       target[i] = WebRtcSpl_SatW32ToW16(temp);
    154     }
    155   }
    156 }
    157 
    158 }  // namespace voe
    159 }  // namespace webrtc
    160