• 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/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.
RemixAndResample(const AudioFrame & src_frame,PushResampler<int16_t> * resampler,AudioFrame * dst_frame)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 
DownConvertToCodecFormat(const int16_t * src_data,int samples_per_channel,int num_channels,int sample_rate_hz,int codec_num_channels,int codec_rate_hz,int16_t * mono_buffer,PushResampler<int16_t> * resampler,AudioFrame * dst_af)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 
MixWithSat(int16_t target[],int target_channel,const int16_t source[],int source_channel,int source_len)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