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