OSDN Git Service

Make inlines static
[android-x86/system-media.git] / audio_utils / channels.c
1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <string.h>
18 #include <audio_utils/channels.h>
19 #include "private/private.h"
20
21 /*
22  * Clamps a 24-bit value from a 32-bit sample
23  */
24 static inline int32_t clamp24(int32_t sample)
25 {
26     if ((sample>>23) ^ (sample>>31)) {
27         sample = 0x007FFFFF ^ (sample>>31);
28     }
29     return sample;
30 }
31
32 /*
33  * Converts a uint8x3_t into an int32_t
34  */
35 static inline int32_t uint8x3_to_int32(uint8x3_t val) {
36 #if HAVE_BIG_ENDIAN
37     int32_t temp = (val.c[0] << 24 | val.c[1] << 16 | val.c[2] << 8) >> 8;
38 #else
39     int32_t temp = (val.c[2] << 24 | val.c[1] << 16 | val.c[0] << 8) >> 8;
40 #endif
41     return clamp24(temp);
42 }
43
44 /*
45  * Converts an int32_t to a uint8x3_t
46  */
47 static inline uint8x3_t int32_to_uint8x3(int32_t in) {
48     uint8x3_t out;
49 #if HAVE_BIG_ENDIAN
50     out.c[2] = in;
51     out.c[1] = in >> 8;
52     out.c[0] = in >> 16;
53 #else
54     out.c[0] = in;
55     out.c[1] = in >> 8;
56     out.c[2] = in >> 16;
57 #endif
58     return out;
59 }
60
61 /* Channel expands (adds zeroes to audio frame end) from an input buffer to an output buffer.
62  * See expand_channels() function below for parameter definitions.
63  *
64  * Move from back to front so that the conversion can be done in-place
65  * i.e. in_buff == out_buff
66  * NOTE: num_in_bytes must be a multiple of in_buff_channels * in_buff_sample_size.
67  */
68 #define EXPAND_CHANNELS(in_buff, in_buff_chans, out_buff, out_buff_chans, num_in_bytes, zero) \
69 { \
70     size_t num_in_samples = (num_in_bytes) / sizeof(*(in_buff)); \
71     size_t num_out_samples = (num_in_samples * (out_buff_chans)) / (in_buff_chans); \
72     typeof(out_buff) dst_ptr = (out_buff) + num_out_samples - 1; \
73     size_t src_index; \
74     typeof(in_buff) src_ptr = (in_buff) + num_in_samples - 1; \
75     size_t num_zero_chans = (out_buff_chans) - (in_buff_chans); \
76     for (src_index = 0; src_index < num_in_samples; src_index += (in_buff_chans)) { \
77         size_t dst_offset; \
78         for (dst_offset = 0; dst_offset < num_zero_chans; dst_offset++) { \
79             *dst_ptr-- = zero; \
80         } \
81         for (; dst_offset < (out_buff_chans); dst_offset++) { \
82             *dst_ptr-- = *src_ptr--; \
83         } \
84     } \
85     /* return number of *bytes* generated */ \
86     return num_out_samples * sizeof(*(out_buff)); \
87 }
88
89 /* Channel expands from a MONO input buffer to a MULTICHANNEL output buffer by duplicating the
90  * single input channel to the first 2 output channels and 0-filling the remaining.
91  * See expand_channels() function below for parameter definitions.
92  *
93  * in_buff_chans MUST be 1 and out_buff_chans MUST be >= 2
94  *
95  * Move from back to front so that the conversion can be done in-place
96  * i.e. in_buff == out_buff
97  * NOTE: num_in_bytes must be a multiple of in_buff_channels * in_buff_sample_size.
98  */
99 #define EXPAND_MONO_TO_MULTI(in_buff, in_buff_chans, out_buff, out_buff_chans, num_in_bytes, zero) \
100 { \
101     size_t num_in_samples = (num_in_bytes) / sizeof(*(in_buff)); \
102     size_t num_out_samples = (num_in_samples * (out_buff_chans)) / (in_buff_chans); \
103     typeof(out_buff) dst_ptr = (out_buff) + num_out_samples - 1; \
104     size_t src_index; \
105     typeof(in_buff) src_ptr = (in_buff) + num_in_samples - 1; \
106     size_t num_zero_chans = (out_buff_chans) - (in_buff_chans) - 1; \
107     for (src_index = 0; src_index < num_in_samples; src_index += (in_buff_chans)) { \
108         size_t dst_offset; \
109         for (dst_offset = 0; dst_offset < num_zero_chans; dst_offset++) { \
110             *dst_ptr-- = zero; \
111         } \
112         for (; dst_offset < (out_buff_chans); dst_offset++) { \
113             *dst_ptr-- = *src_ptr; \
114         } \
115         src_ptr--; \
116     } \
117     /* return number of *bytes* generated */ \
118     return num_out_samples * sizeof(*(out_buff)); \
119 }
120
121 /* Channel contracts (removes from audio frame end) from an input buffer to an output buffer.
122  * See contract_channels() function below for parameter definitions.
123  *
124  * Move from front to back so that the conversion can be done in-place
125  * i.e. in_buff == out_buff
126  * NOTE: num_in_bytes must be a multiple of in_buff_channels * in_buff_sample_size.
127  */
128 #define CONTRACT_CHANNELS(in_buff, in_buff_chans, out_buff, out_buff_chans, num_in_bytes) \
129 { \
130     size_t num_in_samples = (num_in_bytes) / sizeof(*(in_buff)); \
131     size_t num_out_samples = (num_in_samples * (out_buff_chans)) / (in_buff_chans); \
132     size_t num_skip_samples = (in_buff_chans) - (out_buff_chans); \
133     typeof(out_buff) dst_ptr = out_buff; \
134     typeof(in_buff) src_ptr = in_buff; \
135     size_t src_index; \
136     for (src_index = 0; src_index < num_in_samples; src_index += (in_buff_chans)) { \
137         size_t dst_offset; \
138         for (dst_offset = 0; dst_offset < (out_buff_chans); dst_offset++) { \
139             *dst_ptr++ = *src_ptr++; \
140         } \
141         src_ptr += num_skip_samples; \
142     } \
143     /* return number of *bytes* generated */ \
144     return num_out_samples * sizeof(*(out_buff)); \
145 }
146
147 /* Channel contracts from a MULTICHANNEL input buffer to a MONO output buffer by mixing the
148  * first two input channels into the single output channel (and skipping the rest).
149  * See contract_channels() function below for parameter definitions.
150  *
151  * in_buff_chans MUST be >= 2 and out_buff_chans MUST be 1
152  *
153  * Move from front to back so that the conversion can be done in-place
154  * i.e. in_buff == out_buff
155  * NOTE: num_in_bytes must be a multiple of in_buff_channels * in_buff_sample_size.
156  * NOTE: Overload of the summed channels is avoided by averaging the two input channels.
157  * NOTE: Can not be used for uint8x3_t samples, see CONTRACT_TO_MONO_24() below.
158  */
159 #define CONTRACT_TO_MONO(in_buff, out_buff, num_in_bytes) \
160 { \
161     size_t num_in_samples = (num_in_bytes) / sizeof(*(in_buff)); \
162     size_t num_out_samples = (num_in_samples * out_buff_chans) / in_buff_chans; \
163     size_t num_skip_samples = in_buff_chans - 2; \
164     typeof(out_buff) dst_ptr = out_buff; \
165     typeof(in_buff) src_ptr = in_buff; \
166     int32_t temp0, temp1; \
167     size_t src_index; \
168     for (src_index = 0; src_index < num_in_samples; src_index += in_buff_chans) { \
169         temp0 = *src_ptr++; \
170         temp1 = *src_ptr++; \
171         /* *dst_ptr++ = temp >> 1; */ \
172         /* This bit of magic adds and normalizes without overflow (or so claims hunga@) */ \
173         /* Bitwise half adder trick, see http://en.wikipedia.org/wiki/Adder_(electronics) */ \
174         /* Hacker's delight, p. 19 http://www.hackersdelight.org/basics2.pdf */ \
175         *dst_ptr++ = (temp0 & temp1) + ((temp0 ^ temp1) >> 1); \
176         src_ptr += num_skip_samples; \
177     } \
178     /* return number of *bytes* generated */ \
179     return num_out_samples * sizeof(*(out_buff)); \
180 }
181
182 /* Channel contracts from a MULTICHANNEL uint8x3_t input buffer to a MONO uint8x3_t output buffer
183  * by mixing the first two input channels into the single output channel (and skipping the rest).
184  * See contract_channels() function below for parameter definitions.
185  *
186  * Move from front to back so that the conversion can be done in-place
187  * i.e. in_buff == out_buff
188  * NOTE: num_in_bytes must be a multiple of in_buff_channels * in_buff_sample_size.
189  * NOTE: Overload of the summed channels is avoided by averaging the two input channels.
190  * NOTE: Can not be used for normal, scalar samples, see CONTRACT_TO_MONO() above.
191  */
192 #define CONTRACT_TO_MONO_24(in_buff, out_buff, num_in_bytes) \
193 { \
194     size_t num_in_samples = (num_in_bytes) / sizeof(*(in_buff)); \
195     size_t num_out_samples = (num_in_samples * out_buff_chans) / in_buff_chans; \
196     size_t num_skip_samples = in_buff_chans - 2; \
197     typeof(out_buff) dst_ptr = out_buff; \
198     typeof(in_buff) src_ptr = in_buff; \
199     int32_t temp; \
200     size_t src_index; \
201     for (src_index = 0; src_index < num_in_samples; src_index += in_buff_chans) { \
202         temp = uint8x3_to_int32(*src_ptr++); \
203         temp += uint8x3_to_int32(*src_ptr++); \
204         *dst_ptr = int32_to_uint8x3(temp >> 1); \
205         src_ptr += num_skip_samples; \
206     } \
207     /* return number of *bytes* generated */ \
208     return num_out_samples * sizeof(*(out_buff)); \
209 }
210
211 /*
212  * Convert a buffer of N-channel, interleaved samples to M-channel
213  * (where N > M).
214  *   in_buff points to the buffer of samples
215  *   in_buff_channels Specifies the number of channels in the input buffer.
216  *   out_buff points to the buffer to receive converted samples.
217  *   out_buff_channels Specifies the number of channels in the output buffer.
218  *   sample_size_in_bytes Specifies the number of bytes per sample.
219  *   num_in_bytes size of input buffer in BYTES
220  * returns
221  *   the number of BYTES of output data.
222  * NOTE
223  *   channels > M are thrown away.
224  *   The out and sums buffers must either be completely separate (non-overlapping), or
225  *   they must both start at the same address. Partially overlapping buffers are not supported.
226  */
227 static size_t contract_channels(const void* in_buff, size_t in_buff_chans,
228                                 void* out_buff, size_t out_buff_chans,
229                                 unsigned sample_size_in_bytes, size_t num_in_bytes)
230 {
231     switch (sample_size_in_bytes) {
232     case 1:
233         if (out_buff_chans == 1) {
234             /* Special case Multi to Mono */
235             CONTRACT_TO_MONO((const uint8_t*)in_buff, (uint8_t*)out_buff, num_in_bytes);
236             // returns in macro
237         } else {
238             CONTRACT_CHANNELS((const uint8_t*)in_buff, in_buff_chans,
239                               (uint8_t*)out_buff, out_buff_chans,
240                               num_in_bytes);
241             // returns in macro
242         }
243     case 2:
244         if (out_buff_chans == 1) {
245             /* Special case Multi to Mono */
246             CONTRACT_TO_MONO((const int16_t*)in_buff, (int16_t*)out_buff, num_in_bytes);
247             // returns in macro
248         } else {
249             CONTRACT_CHANNELS((const int16_t*)in_buff, in_buff_chans,
250                               (int16_t*)out_buff, out_buff_chans,
251                               num_in_bytes);
252             // returns in macro
253         }
254     case 3:
255         if (out_buff_chans == 1) {
256             /* Special case Multi to Mono */
257             CONTRACT_TO_MONO_24((const uint8x3_t*)in_buff,
258                                        (uint8x3_t*)out_buff, num_in_bytes);
259             // returns in macro
260         } else {
261             CONTRACT_CHANNELS((const uint8x3_t*)in_buff, in_buff_chans,
262                               (uint8x3_t*)out_buff, out_buff_chans,
263                               num_in_bytes);
264             // returns in macro
265         }
266     case 4:
267         if (out_buff_chans == 1) {
268             /* Special case Multi to Mono */
269             CONTRACT_TO_MONO((const int32_t*)in_buff, (int32_t*)out_buff, num_in_bytes);
270             // returns in macro
271         } else {
272             CONTRACT_CHANNELS((const int32_t*)in_buff, in_buff_chans,
273                               (int32_t*)out_buff, out_buff_chans,
274                               num_in_bytes);
275             // returns in macro
276         }
277     default:
278         return 0;
279     }
280 }
281
282 /*
283  * Convert a buffer of N-channel, interleaved samples to M-channel
284  * (where N < M).
285  *   in_buff points to the buffer of samples
286  *   in_buff_channels Specifies the number of channels in the input buffer.
287  *   out_buff points to the buffer to receive converted samples.
288  *   out_buff_channels Specifies the number of channels in the output buffer.
289  *   sample_size_in_bytes Specifies the number of bytes per sample.
290  *   num_in_bytes size of input buffer in BYTES
291  * returns
292  *   the number of BYTES of output data.
293  * NOTE
294  *   channels > N are filled with silence.
295  *   The out and sums buffers must either be completely separate (non-overlapping), or
296  *   they must both start at the same address. Partially overlapping buffers are not supported.
297  */
298 static size_t expand_channels(const void* in_buff, size_t in_buff_chans,
299                               void* out_buff, size_t out_buff_chans,
300                               unsigned sample_size_in_bytes, size_t num_in_bytes)
301 {
302     static const uint8x3_t packed24_zero; /* zero 24 bit sample */
303
304     switch (sample_size_in_bytes) {
305     case 1:
306         if (in_buff_chans == 1) {
307             /* special case of mono source to multi-channel */
308             EXPAND_MONO_TO_MULTI((const uint8_t*)in_buff, in_buff_chans,
309                             (uint8_t*)out_buff, out_buff_chans,
310                             num_in_bytes, 0);
311             // returns in macro
312         } else {
313             EXPAND_CHANNELS((const uint8_t*)in_buff, in_buff_chans,
314                             (uint8_t*)out_buff, out_buff_chans,
315                             num_in_bytes, 0);
316             // returns in macro
317         }
318     case 2:
319         if (in_buff_chans == 1) {
320             /* special case of mono source to multi-channel */
321             EXPAND_MONO_TO_MULTI((const int16_t*)in_buff, in_buff_chans,
322                             (int16_t*)out_buff, out_buff_chans,
323                             num_in_bytes, 0);
324             // returns in macro
325         } else {
326             EXPAND_CHANNELS((const int16_t*)in_buff, in_buff_chans,
327                             (int16_t*)out_buff, out_buff_chans,
328                             num_in_bytes, 0);
329             // returns in macro
330         }
331     case 3:
332         if (in_buff_chans == 1) {
333             /* special case of mono source to multi-channel */
334             EXPAND_MONO_TO_MULTI((const uint8x3_t*)in_buff, in_buff_chans,
335                             (uint8x3_t*)out_buff, out_buff_chans,
336                             num_in_bytes, packed24_zero);
337             // returns in macro
338         } else {
339             EXPAND_CHANNELS((const uint8x3_t*)in_buff, in_buff_chans,
340                             (uint8x3_t*)out_buff, out_buff_chans,
341                             num_in_bytes, packed24_zero);
342             // returns in macro
343         }
344     case 4:
345         if (in_buff_chans == 1) {
346             /* special case of mono source to multi-channel */
347             EXPAND_MONO_TO_MULTI((const int32_t*)in_buff, in_buff_chans,
348                             (int32_t*)out_buff, out_buff_chans,
349                             num_in_bytes, 0);
350             // returns in macro
351         } else {
352            EXPAND_CHANNELS((const int32_t*)in_buff, in_buff_chans,
353                             (int32_t*)out_buff, out_buff_chans,
354                             num_in_bytes, 0);
355             // returns in macro
356         }
357     default:
358         return 0;
359     }
360 }
361
362 size_t adjust_channels(const void* in_buff, size_t in_buff_chans,
363                        void* out_buff, size_t out_buff_chans,
364                        unsigned sample_size_in_bytes, size_t num_in_bytes)
365 {
366     if (out_buff_chans > in_buff_chans) {
367         return expand_channels(in_buff, in_buff_chans, out_buff,  out_buff_chans,
368                                sample_size_in_bytes, num_in_bytes);
369     } else if (out_buff_chans < in_buff_chans) {
370         return contract_channels(in_buff, in_buff_chans, out_buff,  out_buff_chans,
371                                  sample_size_in_bytes, num_in_bytes);
372     } else if (in_buff != out_buff) {
373         memcpy(out_buff, in_buff, num_in_bytes);
374     }
375
376     return num_in_bytes;
377 }