OSDN Git Service

Move histogram code from PerformanceAnalysis.cpp.
[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 an input buffer to an output buffer.
90  * See expand_selected_channels() function below for parameter definitions.
91  * Selected channels are replaced in the output buffer, with any extra channels
92  * per frame left alone.
93  *
94  * Move from back to front so that the conversion can be done in-place
95  * i.e. in_buff == out_buff
96  * NOTE: num_in_bytes must be a multiple of in_buff_channels * in_buff_sample_size.
97  */
98 /* This is written as a C macro because it operates on generic types,
99  * which in a C++ file could be alternatively achieved by a "template"
100  * or an "auto" declaration.
101  * TODO: convert this from a C file to a C++ file.
102  */
103 #define EXPAND_SELECTED_CHANNELS( \
104         in_buff, in_buff_chans, out_buff, out_buff_chans, num_in_bytes) \
105 { \
106     size_t num_in_samples = (num_in_bytes) / sizeof(*(in_buff)); \
107     size_t num_out_samples = (num_in_samples * (out_buff_chans)) / (in_buff_chans); \
108     typeof(out_buff) dst_ptr = (out_buff) + num_out_samples - 1; \
109     size_t src_index; \
110     typeof(in_buff) src_ptr = (in_buff) + num_in_samples - 1; \
111     size_t num_extra_chans = (out_buff_chans) - (in_buff_chans); \
112     for (src_index = 0; src_index < num_in_samples; src_index += (in_buff_chans)) { \
113         dst_ptr -= num_extra_chans; \
114         for (size_t dst_offset = num_extra_chans; dst_offset < (out_buff_chans); dst_offset++) { \
115             *dst_ptr-- = *src_ptr--; \
116         } \
117     } \
118     /* return number of *bytes* generated */ \
119     return num_out_samples * sizeof(*(out_buff)); \
120 }
121
122
123 /* Channel expands from a MONO input buffer to a MULTICHANNEL output buffer by duplicating the
124  * single input channel to the first 2 output channels and 0-filling the remaining.
125  * See expand_channels() function below for parameter definitions.
126  *
127  * in_buff_chans MUST be 1 and out_buff_chans MUST be >= 2
128  *
129  * Move from back to front so that the conversion can be done in-place
130  * i.e. in_buff == out_buff
131  * NOTE: num_in_bytes must be a multiple of in_buff_channels * in_buff_sample_size.
132  */
133 #define EXPAND_MONO_TO_MULTI(in_buff, in_buff_chans, out_buff, out_buff_chans, num_in_bytes, zero) \
134 { \
135     size_t num_in_samples = (num_in_bytes) / sizeof(*(in_buff)); \
136     size_t num_out_samples = (num_in_samples * (out_buff_chans)) / (in_buff_chans); \
137     typeof(out_buff) dst_ptr = (out_buff) + num_out_samples - 1; \
138     size_t src_index; \
139     typeof(in_buff) src_ptr = (in_buff) + num_in_samples - 1; \
140     size_t num_zero_chans = (out_buff_chans) - (in_buff_chans) - 1; \
141     for (src_index = 0; src_index < num_in_samples; src_index += (in_buff_chans)) { \
142         size_t dst_offset; \
143         for (dst_offset = 0; dst_offset < num_zero_chans; dst_offset++) { \
144             *dst_ptr-- = zero; \
145         } \
146         for (; dst_offset < (out_buff_chans); dst_offset++) { \
147             *dst_ptr-- = *src_ptr; \
148         } \
149         src_ptr--; \
150     } \
151     /* return number of *bytes* generated */ \
152     return num_out_samples * sizeof(*(out_buff)); \
153 }
154
155 /* Channel contracts (removes from audio frame end) from an input buffer to an output buffer.
156  * See contract_channels() function below for parameter definitions.
157  *
158  * Move from front to back so that the conversion can be done in-place
159  * i.e. in_buff == out_buff
160  * NOTE: num_in_bytes must be a multiple of in_buff_channels * in_buff_sample_size.
161  */
162 #define CONTRACT_CHANNELS(in_buff, in_buff_chans, out_buff, out_buff_chans, num_in_bytes) \
163 { \
164     size_t num_in_samples = (num_in_bytes) / sizeof(*(in_buff)); \
165     size_t num_out_samples = (num_in_samples * (out_buff_chans)) / (in_buff_chans); \
166     size_t num_skip_samples = (in_buff_chans) - (out_buff_chans); \
167     typeof(out_buff) dst_ptr = out_buff; \
168     typeof(in_buff) src_ptr = in_buff; \
169     size_t src_index; \
170     for (src_index = 0; src_index < num_in_samples; src_index += (in_buff_chans)) { \
171         size_t dst_offset; \
172         for (dst_offset = 0; dst_offset < (out_buff_chans); dst_offset++) { \
173             *dst_ptr++ = *src_ptr++; \
174         } \
175         src_ptr += num_skip_samples; \
176     } \
177     /* return number of *bytes* generated */ \
178     return num_out_samples * sizeof(*(out_buff)); \
179 }
180
181 /* Channel contracts from a MULTICHANNEL input buffer to a MONO output buffer by mixing the
182  * first two input channels into the single output channel (and skipping the rest).
183  * See contract_channels() function below for parameter definitions.
184  *
185  * in_buff_chans MUST be >= 2 and out_buff_chans MUST be 1
186  *
187  * Move from front to back so that the conversion can be done in-place
188  * i.e. in_buff == out_buff
189  * NOTE: num_in_bytes must be a multiple of in_buff_channels * in_buff_sample_size.
190  * NOTE: Overload of the summed channels is avoided by averaging the two input channels.
191  * NOTE: Can not be used for uint8x3_t samples, see CONTRACT_TO_MONO_24() below.
192  */
193 #define CONTRACT_TO_MONO(in_buff, out_buff, num_in_bytes) \
194 { \
195     size_t num_in_samples = (num_in_bytes) / sizeof(*(in_buff)); \
196     size_t num_out_samples = (num_in_samples * out_buff_chans) / in_buff_chans; \
197     size_t num_skip_samples = in_buff_chans - 2; \
198     typeof(out_buff) dst_ptr = out_buff; \
199     typeof(in_buff) src_ptr = in_buff; \
200     int32_t temp0, temp1; \
201     size_t src_index; \
202     for (src_index = 0; src_index < num_in_samples; src_index += in_buff_chans) { \
203         temp0 = *src_ptr++; \
204         temp1 = *src_ptr++; \
205         /* *dst_ptr++ = temp >> 1; */ \
206         /* This bit of magic adds and normalizes without overflow (or so claims hunga@) */ \
207         /* Bitwise half adder trick, see http://en.wikipedia.org/wiki/Adder_(electronics) */ \
208         /* Hacker's delight, p. 19 http://www.hackersdelight.org/basics2.pdf */ \
209         *dst_ptr++ = (temp0 & temp1) + ((temp0 ^ temp1) >> 1); \
210         src_ptr += num_skip_samples; \
211     } \
212     /* return number of *bytes* generated */ \
213     return num_out_samples * sizeof(*(out_buff)); \
214 }
215
216 /* Channel contracts from a MULTICHANNEL uint8x3_t input buffer to a MONO uint8x3_t output buffer
217  * by mixing the first two input channels into the single output channel (and skipping the rest).
218  * See contract_channels() function below for parameter definitions.
219  *
220  * Move from front to back so that the conversion can be done in-place
221  * i.e. in_buff == out_buff
222  * NOTE: num_in_bytes must be a multiple of in_buff_channels * in_buff_sample_size.
223  * NOTE: Overload of the summed channels is avoided by averaging the two input channels.
224  * NOTE: Can not be used for normal, scalar samples, see CONTRACT_TO_MONO() above.
225  */
226 #define CONTRACT_TO_MONO_24(in_buff, out_buff, num_in_bytes) \
227 { \
228     size_t num_in_samples = (num_in_bytes) / sizeof(*(in_buff)); \
229     size_t num_out_samples = (num_in_samples * out_buff_chans) / in_buff_chans; \
230     size_t num_skip_samples = in_buff_chans - 2; \
231     typeof(out_buff) dst_ptr = out_buff; \
232     typeof(in_buff) src_ptr = in_buff; \
233     int32_t temp; \
234     size_t src_index; \
235     for (src_index = 0; src_index < num_in_samples; src_index += in_buff_chans) { \
236         temp = uint8x3_to_int32(*src_ptr++); \
237         temp += uint8x3_to_int32(*src_ptr++); \
238         *dst_ptr = int32_to_uint8x3(temp >> 1); \
239         src_ptr += num_skip_samples; \
240     } \
241     /* return number of *bytes* generated */ \
242     return num_out_samples * sizeof(*(out_buff)); \
243 }
244
245 /*
246  * Convert a buffer of N-channel, interleaved samples to M-channel
247  * (where N > M).
248  *   in_buff points to the buffer of samples
249  *   in_buff_channels Specifies the number of channels in the input buffer.
250  *   out_buff points to the buffer to receive converted samples.
251  *   out_buff_channels Specifies the number of channels in the output buffer.
252  *   sample_size_in_bytes Specifies the number of bytes per sample.
253  *   num_in_bytes size of input buffer in BYTES
254  * returns
255  *   the number of BYTES of output data.
256  * NOTE
257  *   channels > M are thrown away.
258  *   The out and sums buffers must either be completely separate (non-overlapping), or
259  *   they must both start at the same address. Partially overlapping buffers are not supported.
260  */
261 static size_t contract_channels(const void* in_buff, size_t in_buff_chans,
262                                 void* out_buff, size_t out_buff_chans,
263                                 unsigned sample_size_in_bytes, size_t num_in_bytes)
264 {
265     switch (sample_size_in_bytes) {
266     case 1:
267         if (out_buff_chans == 1) {
268             /* Special case Multi to Mono */
269             CONTRACT_TO_MONO((const uint8_t*)in_buff, (uint8_t*)out_buff, num_in_bytes);
270             // returns in macro
271         } else {
272             CONTRACT_CHANNELS((const uint8_t*)in_buff, in_buff_chans,
273                               (uint8_t*)out_buff, out_buff_chans,
274                               num_in_bytes);
275             // returns in macro
276         }
277     case 2:
278         if (out_buff_chans == 1) {
279             /* Special case Multi to Mono */
280             CONTRACT_TO_MONO((const int16_t*)in_buff, (int16_t*)out_buff, num_in_bytes);
281             // returns in macro
282         } else {
283             CONTRACT_CHANNELS((const int16_t*)in_buff, in_buff_chans,
284                               (int16_t*)out_buff, out_buff_chans,
285                               num_in_bytes);
286             // returns in macro
287         }
288     case 3:
289         if (out_buff_chans == 1) {
290             /* Special case Multi to Mono */
291             CONTRACT_TO_MONO_24((const uint8x3_t*)in_buff,
292                                        (uint8x3_t*)out_buff, num_in_bytes);
293             // returns in macro
294         } else {
295             CONTRACT_CHANNELS((const uint8x3_t*)in_buff, in_buff_chans,
296                               (uint8x3_t*)out_buff, out_buff_chans,
297                               num_in_bytes);
298             // returns in macro
299         }
300     case 4:
301         if (out_buff_chans == 1) {
302             /* Special case Multi to Mono */
303             CONTRACT_TO_MONO((const int32_t*)in_buff, (int32_t*)out_buff, num_in_bytes);
304             // returns in macro
305         } else {
306             CONTRACT_CHANNELS((const int32_t*)in_buff, in_buff_chans,
307                               (int32_t*)out_buff, out_buff_chans,
308                               num_in_bytes);
309             // returns in macro
310         }
311     default:
312         return 0;
313     }
314 }
315
316 /*
317  * Convert a buffer of N-channel, interleaved samples to M-channel
318  * (where N < M).
319  *   in_buff points to the buffer of samples
320  *   in_buff_channels Specifies the number of channels in the input buffer.
321  *   out_buff points to the buffer to receive converted samples.
322  *   out_buff_channels Specifies the number of channels in the output buffer.
323  *   sample_size_in_bytes Specifies the number of bytes per sample.
324  *   num_in_bytes size of input buffer in BYTES
325  * returns
326  *   the number of BYTES of output data.
327  * NOTE
328  *   channels > N are filled with silence.
329  *   The out and sums buffers must either be completely separate (non-overlapping), or
330  *   they must both start at the same address. Partially overlapping buffers are not supported.
331  */
332 static size_t expand_channels(const void* in_buff, size_t in_buff_chans,
333                               void* out_buff, size_t out_buff_chans,
334                               unsigned sample_size_in_bytes, size_t num_in_bytes)
335 {
336     static const uint8x3_t packed24_zero; /* zero 24 bit sample */
337
338     switch (sample_size_in_bytes) {
339     case 1:
340         if (in_buff_chans == 1) {
341             /* special case of mono source to multi-channel */
342             EXPAND_MONO_TO_MULTI((const uint8_t*)in_buff, in_buff_chans,
343                             (uint8_t*)out_buff, out_buff_chans,
344                             num_in_bytes, 0);
345             // returns in macro
346         } else {
347             EXPAND_CHANNELS((const uint8_t*)in_buff, in_buff_chans,
348                             (uint8_t*)out_buff, out_buff_chans,
349                             num_in_bytes, 0);
350             // returns in macro
351         }
352     case 2:
353         if (in_buff_chans == 1) {
354             /* special case of mono source to multi-channel */
355             EXPAND_MONO_TO_MULTI((const int16_t*)in_buff, in_buff_chans,
356                             (int16_t*)out_buff, out_buff_chans,
357                             num_in_bytes, 0);
358             // returns in macro
359         } else {
360             EXPAND_CHANNELS((const int16_t*)in_buff, in_buff_chans,
361                             (int16_t*)out_buff, out_buff_chans,
362                             num_in_bytes, 0);
363             // returns in macro
364         }
365     case 3:
366         if (in_buff_chans == 1) {
367             /* special case of mono source to multi-channel */
368             EXPAND_MONO_TO_MULTI((const uint8x3_t*)in_buff, in_buff_chans,
369                             (uint8x3_t*)out_buff, out_buff_chans,
370                             num_in_bytes, packed24_zero);
371             // returns in macro
372         } else {
373             EXPAND_CHANNELS((const uint8x3_t*)in_buff, in_buff_chans,
374                             (uint8x3_t*)out_buff, out_buff_chans,
375                             num_in_bytes, packed24_zero);
376             // returns in macro
377         }
378     case 4:
379         if (in_buff_chans == 1) {
380             /* special case of mono source to multi-channel */
381             EXPAND_MONO_TO_MULTI((const int32_t*)in_buff, in_buff_chans,
382                             (int32_t*)out_buff, out_buff_chans,
383                             num_in_bytes, 0);
384             // returns in macro
385         } else {
386            EXPAND_CHANNELS((const int32_t*)in_buff, in_buff_chans,
387                             (int32_t*)out_buff, out_buff_chans,
388                             num_in_bytes, 0);
389             // returns in macro
390         }
391     default:
392         return 0;
393     }
394 }
395
396 size_t adjust_channels(const void* in_buff, size_t in_buff_chans,
397                        void* out_buff, size_t out_buff_chans,
398                        unsigned sample_size_in_bytes, size_t num_in_bytes)
399 {
400     if (out_buff_chans > in_buff_chans) {
401         return expand_channels(in_buff, in_buff_chans, out_buff,  out_buff_chans,
402                                sample_size_in_bytes, num_in_bytes);
403     } else if (out_buff_chans < in_buff_chans) {
404         return contract_channels(in_buff, in_buff_chans, out_buff,  out_buff_chans,
405                                  sample_size_in_bytes, num_in_bytes);
406     } else if (in_buff != out_buff) {
407         memcpy(out_buff, in_buff, num_in_bytes);
408     }
409
410     return num_in_bytes;
411 }
412
413 /*
414  * Convert a buffer of N-channel, interleaved samples to M-channel
415  * (where N < M).
416  *   in_buff points to the buffer of samples
417  *   in_buff_channels Specifies the number of channels in the input buffer.
418  *   out_buff points to the buffer to receive converted samples.
419  *   out_buff_channels Specifies the number of channels in the output buffer.
420  *   sample_size_in_bytes Specifies the number of bytes per sample.
421  *   num_in_bytes size of input buffer in BYTES
422  * returns
423  *   the number of BYTES of output data.
424  * NOTE
425  *   channels > N are left alone in out_buff.
426  *   The out and in buffers must either be completely separate (non-overlapping), or
427  *   they must both start at the same address. Partially overlapping buffers are not supported.
428  */
429 static size_t expand_selected_channels(const void* in_buff, size_t in_buff_chans,
430                               void* out_buff, size_t out_buff_chans,
431                               unsigned sample_size_in_bytes, size_t num_in_bytes)
432 {
433     switch (sample_size_in_bytes) {
434     case 1:
435
436         EXPAND_SELECTED_CHANNELS((const uint8_t*)in_buff, in_buff_chans,
437                         (uint8_t*)out_buff, out_buff_chans,
438                         num_in_bytes);
439         // returns in macro
440
441     case 2:
442
443         EXPAND_SELECTED_CHANNELS((const int16_t*)in_buff, in_buff_chans,
444                         (int16_t*)out_buff, out_buff_chans,
445                         num_in_bytes);
446         // returns in macro
447
448     case 3:
449
450         EXPAND_SELECTED_CHANNELS((const uint8x3_t*)in_buff, in_buff_chans,
451                         (uint8x3_t*)out_buff, out_buff_chans,
452                         num_in_bytes);
453         // returns in macro
454
455     case 4:
456
457         EXPAND_SELECTED_CHANNELS((const int32_t*)in_buff, in_buff_chans,
458                         (int32_t*)out_buff, out_buff_chans,
459                         num_in_bytes);
460         // returns in macro
461
462     default:
463         return 0;
464     }
465 }
466
467 size_t adjust_selected_channels(const void* in_buff, size_t in_buff_chans,
468                        void* out_buff, size_t out_buff_chans,
469                        unsigned sample_size_in_bytes, size_t num_in_bytes)
470 {
471     if (out_buff_chans > in_buff_chans) {
472         return expand_selected_channels(in_buff, in_buff_chans, out_buff, out_buff_chans,
473                                sample_size_in_bytes, num_in_bytes);
474     } else if (out_buff_chans < in_buff_chans) {
475         return contract_channels(in_buff, in_buff_chans, out_buff, out_buff_chans,
476                                  sample_size_in_bytes, num_in_bytes);
477     } else if (in_buff != out_buff) {
478         memcpy(out_buff, in_buff, num_in_bytes);
479     }
480
481     return num_in_bytes;
482 }
483