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