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
15namespace webrtc {
16namespace {
17
18enum {
19  kSamplesPer8kHzChannel = 80,
20  kSamplesPer16kHzChannel = 160,
21  kSamplesPer32kHzChannel = 320
22};
23
24void 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
36struct AudioChannel {
37  AudioChannel() {
38    memset(data, 0, sizeof(data));
39  }
40
41  int16_t data[kSamplesPer32kHzChannel];
42};
43
44struct 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?
64AudioBuffer::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
95AudioBuffer::~AudioBuffer() {}
96
97int16_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
106int16_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
115int16_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
124int16_t* AudioBuffer::mixed_data(int channel) const {
125  assert(channel >= 0 && channel < num_mixed_channels_);
126
127  return mixed_channels_[channel].data;
128}
129
130int16_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
136int16_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
145WebRtc_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
150WebRtc_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
155WebRtc_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
160WebRtc_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
165void AudioBuffer::set_activity(AudioFrame::VADActivity activity) {
166  activity_ = activity;
167}
168
169AudioFrame::VADActivity AudioBuffer::activity() const {
170  return activity_;
171}
172
173bool AudioBuffer::is_muted() const {
174  return is_muted_;
175}
176
177int AudioBuffer::num_channels() const {
178  return num_channels_;
179}
180
181int AudioBuffer::samples_per_channel() const {
182  return samples_per_channel_;
183}
184
185int AudioBuffer::samples_per_split_channel() const {
186  return samples_per_split_channel_;
187}
188
189// TODO(andrew): Do deinterleaving and mixing in one step?
190void 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
222void 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?
258void 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
272void 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
285void 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
298void 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