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
StereoToMono(const int16_t * left,const int16_t * right,int16_t * out,int samples_per_channel)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 {
AudioChannelwebrtc::AudioChannel37 AudioChannel() {
38 memset(data, 0, sizeof(data));
39 }
40
41 int16_t data[kSamplesPer32kHzChannel];
42 };
43
44 struct SplitAudioChannel {
SplitAudioChannelwebrtc::SplitAudioChannel45 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?
AudioBuffer(int max_num_channels,int samples_per_channel)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
~AudioBuffer()95 AudioBuffer::~AudioBuffer() {}
96
data(int channel) const97 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
low_pass_split_data(int channel) const106 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
high_pass_split_data(int channel) const115 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
mixed_data(int channel) const124 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
mixed_low_pass_data(int channel) const130 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
low_pass_reference(int channel) const136 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
analysis_filter_state1(int channel) const145 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
analysis_filter_state2(int channel) const150 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
synthesis_filter_state1(int channel) const155 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
synthesis_filter_state2(int channel) const160 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
set_activity(AudioFrame::VADActivity activity)165 void AudioBuffer::set_activity(AudioFrame::VADActivity activity) {
166 activity_ = activity;
167 }
168
activity() const169 AudioFrame::VADActivity AudioBuffer::activity() const {
170 return activity_;
171 }
172
is_muted() const173 bool AudioBuffer::is_muted() const {
174 return is_muted_;
175 }
176
num_channels() const177 int AudioBuffer::num_channels() const {
178 return num_channels_;
179 }
180
samples_per_channel() const181 int AudioBuffer::samples_per_channel() const {
182 return samples_per_channel_;
183 }
184
samples_per_split_channel() const185 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?
DeinterleaveFrom(AudioFrame * frame)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
InterleaveTo(AudioFrame * frame,bool data_changed) const222 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?
Mix(int num_mixed_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
CopyAndMix(int num_mixed_channels)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
CopyAndMixLowPass(int num_mixed_channels)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
CopyLowPassToReference()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