OSDN Git Service

Add q4_27 conversion from float with tests
[android-x86/system-media.git] / audio_utils / include / audio_utils / primitives.h
1 /*
2  * Copyright (C) 2011 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 #ifndef ANDROID_AUDIO_PRIMITIVES_H
18 #define ANDROID_AUDIO_PRIMITIVES_H
19
20 #include <stdint.h>
21 #include <stdlib.h>
22 #include <sys/cdefs.h>
23
24 __BEGIN_DECLS
25
26 /* The memcpy_* conversion routines are designed to work in-place on same dst as src
27  * buffers only if the types shrink on copy, with the exception of memcpy_to_i16_from_u8().
28  * This allows the loops to go upwards for faster cache access (and may be more flexible
29  * for future optimization later).
30  */
31
32 /**
33  * Dither and clamp pairs of 32-bit input samples (sums) to 16-bit output samples (out).
34  * Each 32-bit input sample can be viewed as a signed fixed-point Q19.12 of which the
35  * .12 fraction bits are dithered and the 19 integer bits are clamped to signed 16 bits.
36  * Alternatively the input can be viewed as Q4.27, of which the lowest .12 of the fraction
37  * is dithered and the remaining fraction is converted to the output Q.15, with clamping
38  * on the 4 integer guard bits.
39  *
40  * For interleaved stereo, c is the number of sample pairs,
41  * and out is an array of interleaved pairs of 16-bit samples per channel.
42  * For mono, c is the number of samples / 2, and out is an array of 16-bit samples.
43  * The name "dither" is a misnomer; the current implementation does not actually dither
44  * but uses truncation.  This may change.
45  * The out and sums buffers must either be completely separate (non-overlapping), or
46  * they must both start at the same address.  Partially overlapping buffers are not supported.
47  */
48 void ditherAndClamp(int32_t* out, const int32_t *sums, size_t c);
49
50 /* Expand and copy samples from unsigned 8-bit offset by 0x80 to signed 16-bit.
51  * Parameters:
52  *  dst     Destination buffer
53  *  src     Source buffer
54  *  count   Number of samples to copy
55  * The destination and source buffers must either be completely separate (non-overlapping), or
56  * they must both start at the same address.  Partially overlapping buffers are not supported.
57  */
58 void memcpy_to_i16_from_u8(int16_t *dst, const uint8_t *src, size_t count);
59
60 /* Shrink and copy samples from signed 16-bit to unsigned 8-bit offset by 0x80.
61  * Parameters:
62  *  dst     Destination buffer
63  *  src     Source buffer
64  *  count   Number of samples to copy
65  * The destination and source buffers must either be completely separate (non-overlapping), or
66  * they must both start at the same address.  Partially overlapping buffers are not supported.
67  * The conversion is done by truncation, without dithering, so it loses resolution.
68  */
69 void memcpy_to_u8_from_i16(uint8_t *dst, const int16_t *src, size_t count);
70
71 /* Shrink and copy samples from signed 32-bit fixed-point Q0.31 to signed 16-bit Q0.15.
72  * Parameters:
73  *  dst     Destination buffer
74  *  src     Source buffer
75  *  count   Number of samples to copy
76  * The destination and source buffers must either be completely separate (non-overlapping), or
77  * they must both start at the same address.  Partially overlapping buffers are not supported.
78  * The conversion is done by truncation, without dithering, so it loses resolution.
79  */
80 void memcpy_to_i16_from_i32(int16_t *dst, const int32_t *src, size_t count);
81
82 /* Shrink and copy samples from single-precision floating-point to signed 16-bit.
83  * Each float should be in the range -1.0 to 1.0.  Values outside that range are clamped,
84  * refer to clamp16_from_float().
85  * Parameters:
86  *  dst     Destination buffer
87  *  src     Source buffer
88  *  count   Number of samples to copy
89  * The destination and source buffers must either be completely separate (non-overlapping), or
90  * they must both start at the same address.  Partially overlapping buffers are not supported.
91  * The conversion is done by truncation, without dithering, so it loses resolution.
92  */
93 void memcpy_to_i16_from_float(int16_t *dst, const float *src, size_t count);
94
95 /* Copy samples from signed fixed-point 32-bit Q4.27 to single-precision floating-point.
96  * The nominal output float range is [-1.0, 1.0] if the fixed-point range is
97  * [0xf8000000, 0x07ffffff].  The full float range is [-16.0, 16.0].  Note the closed range
98  * at 1.0 and 16.0 is due to rounding on conversion to float. See float_from_q4_27() for details.
99  * Parameters:
100  *  dst     Destination buffer
101  *  src     Source buffer
102  *  count   Number of samples to copy
103  * The destination and source buffers must either be completely separate (non-overlapping), or
104  * they must both start at the same address.  Partially overlapping buffers are not supported.
105  */
106 void memcpy_to_float_from_q4_27(float *dst, const int32_t *src, size_t count);
107
108 /* Copy samples from signed fixed-point 16 bit Q0.15 to single-precision floating-point.
109  * The output float range is [-1.0, 1.0) for the fixed-point range [0x8000, 0x7fff].
110  * No rounding is needed as the representation is exact.
111  * Parameters:
112  *  dst     Destination buffer
113  *  src     Source buffer
114  *  count   Number of samples to copy
115  * The destination and source buffers must be completely separate.
116  */
117 void memcpy_to_float_from_i16(float *dst, const int16_t *src, size_t count);
118
119 /* Copy samples from signed fixed-point packed 24 bit Q0.23 to single-precision floating-point.
120  * The packed 24 bit input is stored in native endian format in a uint8_t byte array.
121  * The output float range is [-1.0, 1.0) for the fixed-point range [0x800000, 0x7fffff].
122  * No rounding is needed as the representation is exact.
123  * Parameters:
124  *  dst     Destination buffer
125  *  src     Source buffer
126  *  count   Number of samples to copy
127  * The destination and source buffers must be completely separate.
128  */
129 void memcpy_to_float_from_p24(float *dst, const uint8_t *src, size_t count);
130
131 /* Copy samples from signed fixed-point packed 24 bit Q0.23 to signed fixed point 16 bit Q0.15.
132  * The packed 24 bit output is stored in native endian format in a uint8_t byte array.
133  * The data is truncated without rounding.
134  * Parameters:
135  *  dst     Destination buffer
136  *  src     Source buffer
137  *  count   Number of samples to copy
138  * The destination and source buffers must either be completely separate (non-overlapping), or
139  * they must both start at the same address.  Partially overlapping buffers are not supported.
140  */
141 void memcpy_to_i16_from_p24(int16_t *dst, const uint8_t *src, size_t count);
142
143 /* Copy samples from signed fixed point 16 bit Q0.15 to signed fixed-point packed 24 bit Q0.23.
144  * The packed 24 bit output is assumed to be a little-endian uint8_t byte array.
145  * The output data range is [0x800000, 0x7fff00] (not full).
146  * Nevertheless there is no DC offset on the output, if the input has no DC offset.
147  * Parameters:
148  *  dst     Destination buffer
149  *  src     Source buffer
150  *  count   Number of samples to copy
151  * The destination and source buffers must be completely separate.
152  */
153 void memcpy_to_p24_from_i16(uint8_t *dst, const int16_t *src, size_t count);
154
155 /* Copy samples from single-precision floating-point to signed fixed-point packed 24 bit Q0.23.
156  * The packed 24 bit output is assumed to be a little-endian uint8_t byte array.
157  * The data is clamped and rounded to nearest, ties away from zero. See clamp24_from_float()
158  * for details.
159  * Parameters:
160  *  dst     Destination buffer
161  *  src     Source buffer
162  *  count   Number of samples to copy
163  * The destination and source buffers must either be completely separate (non-overlapping), or
164  * they must both start at the same address.  Partially overlapping buffers are not supported.
165  */
166 void memcpy_to_p24_from_float(uint8_t *dst, const float *src, size_t count);
167
168 /* Copy samples from signed fixed point 16-bit Q0.15 to signed fixed-point 32-bit Q8.23.
169  * The output data range is [0xff800000, 0x007fff00] at intervals of 0x100.
170  * Parameters:
171  *  dst     Destination buffer
172  *  src     Source buffer
173  *  count   Number of samples to copy
174  * The destination and source buffers must be completely separate.
175  */
176 void memcpy_to_q8_23_from_i16(int32_t *dst, const int16_t *src, size_t count);
177
178 /* Copy samples from single-precision floating-point to signed fixed-point 32-bit Q8.23.
179  * This copy will clamp the Q8.23 representation to [0xff800000, 0x007fffff] even though there
180  * are guard bits available. Fractional lsb is rounded to nearest, ties away from zero.
181  * See clamp24_from_float() for details.
182  * Parameters:
183  *  dst     Destination buffer
184  *  src     Source buffer
185  *  count   Number of samples to copy
186  * The destination and source buffers must either be completely separate (non-overlapping), or
187  * they must both start at the same address.  Partially overlapping buffers are not supported.
188  */
189 void memcpy_to_q8_23_from_float_with_clamp(int32_t *dst, const float *src, size_t count);
190
191 /* Copy samples from single-precision floating-point to signed fixed-point 32-bit Q4.27.
192  * The conversion will use the full available Q4.27 range, including guard bits.
193  * Fractional lsb is rounded to nearest, ties away from zero.
194  * See clampq4_27_from_float() for details.
195  * Parameters:
196  *  dst     Destination buffer
197  *  src     Source buffer
198  *  count   Number of samples to copy
199  * The destination and source buffers must either be completely separate (non-overlapping), or
200  * they must both start at the same address.  Partially overlapping buffers are not supported.
201  */
202 void memcpy_to_q4_27_from_float(int32_t *dst, const float *src, size_t count);
203
204 /* Copy samples from signed fixed-point 32-bit Q8.23 to signed fixed point 16-bit Q0.15.
205  * The data is clamped, and truncated without rounding.
206  * Parameters:
207  *  dst     Destination buffer
208  *  src     Source buffer
209  *  count   Number of samples to copy
210  * The destination and source buffers must either be completely separate (non-overlapping), or
211  * they must both start at the same address.  Partially overlapping buffers are not supported.
212  */
213 void memcpy_to_i16_from_q8_23(int16_t *dst, const int32_t *src, size_t count);
214
215 /* Copy samples from signed fixed-point 32-bit Q8.23 to single-precision floating-point.
216  * The nominal output float range is [-1.0, 1.0) for the fixed-point
217  * range [0xff800000, 0x007fffff]. The maximum output float range is [-256.0, 256.0).
218  * No rounding is needed as the representation is exact for nominal values.
219  * Rounding for overflow values is to nearest, ties to even.
220  * Parameters:
221  *  dst     Destination buffer
222  *  src     Source buffer
223  *  count   Number of samples to copy
224  * The destination and source 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 void memcpy_to_float_from_q8_23(float *dst, const int32_t *src, size_t count);
228
229 /* Copy samples from signed fixed point 16-bit Q0.15 to signed fixed-point 32-bit Q0.31.
230  * The output data range is [0x80000000, 0x7fff0000] at intervals of 0x10000.
231  * Parameters:
232  *  dst     Destination buffer
233  *  src     Source buffer
234  *  count   Number of samples to copy
235  * The destination and source buffers must be completely separate.
236  */
237 void memcpy_to_i32_from_i16(int32_t *dst, const int16_t *src, size_t count);
238
239 /* Copy samples from single-precision floating-point to signed fixed-point 32-bit Q0.31.
240  * If rounding is needed on truncation, the fractional lsb is rounded to nearest,
241  * ties away from zero. See clamp32_from_float() for details.
242  * Parameters:
243  *  dst     Destination buffer
244  *  src     Source buffer
245  *  count   Number of samples to copy
246  * The destination and source buffers must either be completely separate (non-overlapping), or
247  * they must both start at the same address.  Partially overlapping buffers are not supported.
248  */
249 void memcpy_to_i32_from_float(int32_t *dst, const float *src, size_t count);
250
251 /* Copy samples from signed fixed-point 32-bit Q0.31 to single-precision floating-point.
252  * The float range is [-1.0, 1.0] for the fixed-point range [0x80000000, 0x7fffffff].
253  * Rounding is done according to float_from_i32().
254  * Parameters:
255  *  dst     Destination buffer
256  *  src     Source buffer
257  *  count   Number of samples to copy
258  * The destination and source 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 void memcpy_to_float_from_i32(float *dst, const int32_t *src, size_t count);
262
263 /* Downmix pairs of interleaved stereo input 16-bit samples to mono output 16-bit samples.
264  * Parameters:
265  *  dst     Destination buffer
266  *  src     Source buffer
267  *  count   Number of stereo frames to downmix
268  * The destination and source buffers must be completely separate (non-overlapping).
269  * The current implementation truncates the sum rather than dither, but this may change.
270  */
271 void downmix_to_mono_i16_from_stereo_i16(int16_t *dst, const int16_t *src, size_t count);
272
273 /* Upmix mono input 16-bit samples to pairs of interleaved stereo output 16-bit samples by
274  * duplicating.
275  * Parameters:
276  *  dst     Destination buffer
277  *  src     Source buffer
278  *  count   Number of mono samples to upmix
279  * The destination and source buffers must be completely separate (non-overlapping).
280  */
281 void upmix_to_stereo_i16_from_mono_i16(int16_t *dst, const int16_t *src, size_t count);
282
283 /* Return the total number of non-zero 32-bit samples */
284 size_t nonZeroMono32(const int32_t *samples, size_t count);
285
286 /* Return the total number of non-zero 16-bit samples */
287 size_t nonZeroMono16(const int16_t *samples, size_t count);
288
289 /* Return the total number of non-zero stereo frames, where a frame is considered non-zero
290  * if either of its constituent 32-bit samples is non-zero
291  */
292 size_t nonZeroStereo32(const int32_t *frames, size_t count);
293
294 /* Return the total number of non-zero stereo frames, where a frame is considered non-zero
295  * if either of its constituent 16-bit samples is non-zero
296  */
297 size_t nonZeroStereo16(const int16_t *frames, size_t count);
298
299 /**
300  * Clamp (aka hard limit or clip) a signed 32-bit sample to 16-bit range.
301  */
302 static inline int16_t clamp16(int32_t sample)
303 {
304     if ((sample>>15) ^ (sample>>31))
305         sample = 0x7FFF ^ (sample>>31);
306     return sample;
307 }
308
309 /*
310  * Convert a IEEE 754 single precision float [-1.0, 1.0) to int16_t [-32768, 32767]
311  * with clamping.  Note the open bound at 1.0, values within 1/65536 of 1.0 map
312  * to 32767 instead of 32768 (early clamping due to the smaller positive integer subrange).
313  *
314  * Values outside the range [-1.0, 1.0) are properly clamped to -32768 and 32767,
315  * including -Inf and +Inf. NaN will generally be treated either as -32768 or 32767,
316  * depending on the sign bit inside NaN (whose representation is not unique).
317  * Nevertheless, strictly speaking, NaN behavior should be considered undefined.
318  *
319  * Rounding of 0.5 lsb is to even (default for IEEE 754).
320  */
321 static inline int16_t clamp16_from_float(float f)
322 {
323     /* Offset is used to expand the valid range of [-1.0, 1.0) into the 16 lsbs of the
324      * floating point significand. The normal shift is 3<<22, but the -15 offset
325      * is used to multiply by 32768.
326      */
327     static const float offset = (float)(3 << (22 - 15));
328     /* zero = (0x10f << 22) =  0x43c00000 (not directly used) */
329     static const int32_t limneg = (0x10f << 22) /*zero*/ - 32768; /* 0x43bf8000 */
330     static const int32_t limpos = (0x10f << 22) /*zero*/ + 32767; /* 0x43c07fff */
331
332     union {
333         float f;
334         int32_t i;
335     } u;
336
337     u.f = f + offset; /* recenter valid range */
338     /* Now the valid range is represented as integers between [limneg, limpos].
339      * Clamp using the fact that float representation (as an integer) is an ordered set.
340      */
341     if (u.i < limneg)
342         u.i = -32768;
343     else if (u.i > limpos)
344         u.i = 32767;
345     return u.i; /* Return lower 16 bits, the part of interest in the significand. */
346 }
347
348 /* Convert a single-precision floating point value to a Q0.23 integer value, stored in a
349  * 32 bit signed integer (technically stored as Q8.23, but clamped to Q0.23).
350  *
351  * Rounds to nearest, ties away from 0.
352  *
353  * Values outside the range [-1.0, 1.0) are properly clamped to -8388608 and 8388607,
354  * including -Inf and +Inf. NaN values are considered undefined, and behavior may change
355  * depending on hardware and future implementation of this function.
356  */
357 static inline int32_t clamp24_from_float(float f)
358 {
359     static const float scale = (float)(1 << 23);
360     static const float limpos = 0x7fffff / scale;
361     static const float limneg = -0x800000 / scale;
362
363     if (f <= limneg) {
364         return -0x800000;
365     } else if (f >= limpos) {
366         return 0x7fffff;
367     }
368     f *= scale;
369     /* integer conversion is through truncation (though int to float is not).
370      * ensure that we round to nearest, ties away from 0.
371      */
372     return f > 0 ? f + 0.5 : f - 0.5;
373 }
374
375 /* Convert a single-precision floating point value to a Q4.27 integer value.
376  * Rounds to nearest, ties away from 0.
377  *
378  * Values outside the range [-16.0, 16.0) are properly clamped to -2147483648 and 2147483647,
379  * including -Inf and +Inf. NaN values are considered undefined, and behavior may change
380  * depending on hardware and future implementation of this function.
381  */
382 static inline int32_t clampq4_27_from_float(float f)
383 {
384     static const float scale = (float)(1UL << 27);
385     static const float limpos = 16.;
386     static const float limneg = -16.;
387
388     if (f <= limneg) {
389         return -0x80000000; /* or 0x80000000 */
390     } else if (f >= limpos) {
391         return 0x7fffffff;
392     }
393     f *= scale;
394     /* integer conversion is through truncation (though int to float is not).
395      * ensure that we round to nearest, ties away from 0.
396      */
397     return f > 0 ? f + 0.5 : f - 0.5;
398 }
399
400 /* Convert a single-precision floating point value to a Q0.31 integer value.
401  * Rounds to nearest, ties away from 0.
402  *
403  * Values outside the range [-1.0, 1.0) are properly clamped to -2147483648 and 2147483647,
404  * including -Inf and +Inf. NaN values are considered undefined, and behavior may change
405  * depending on hardware and future implementation of this function.
406  */
407 static inline int32_t clamp32_from_float(float f)
408 {
409     static const float scale = (float)(1UL << 31);
410     static const float limpos = 1.;
411     static const float limneg = -1.;
412
413     if (f <= limneg) {
414         return -0x80000000; /* or 0x80000000 */
415     } else if (f >= limpos) {
416         return 0x7fffffff;
417     }
418     f *= scale;
419     /* integer conversion is through truncation (though int to float is not).
420      * ensure that we round to nearest, ties away from 0.
421      */
422     return f > 0 ? f + 0.5 : f - 0.5;
423 }
424
425 /* Convert a signed fixed-point 32-bit Q4.27 value to single-precision floating-point.
426  * The nominal output float range is [-1.0, 1.0] if the fixed-point range is
427  * [0xf8000000, 0x07ffffff].  The full float range is [-16.0, 16.0].
428  *
429  * Note the closed range at 1.0 and 16.0 is due to rounding on conversion to float.
430  * In more detail: if the fixed-point integer exceeds 24 bit significand of single
431  * precision floating point, the 0.5 lsb in the significand conversion will round
432  * towards even, as per IEEE 754 default.
433  */
434 static inline float float_from_q4_27(int32_t ival)
435 {
436     /* The scale factor is the reciprocal of the fractional bits.
437      *
438      * Since the scale factor is a power of 2, the scaling is exact, and there
439      * is no rounding due to the multiplication - the bit pattern is preserved.
440      * However, there may be rounding due to the fixed-point to float conversion,
441      * as described above.
442      */
443     static const float scale = 1. / (float)(1UL << 27);
444
445     return ival * scale;
446 }
447
448 /* Convert a signed fixed-point 16-bit Q0.15 value to single-precision floating-point.
449  * The output float range is [-1.0, 1.0) for the fixed-point range
450  * [0x8000, 0x7fff].
451  *
452  * There is no rounding, the conversion and representation is exact.
453  */
454 static inline float float_from_i16(int16_t ival)
455 {
456     /* The scale factor is the reciprocal of the nominal 16 bit integer
457      * half-sided range (32768).
458      *
459      * Since the scale factor is a power of 2, the scaling is exact, and there
460      * is no rounding due to the multiplication - the bit pattern is preserved.
461      */
462     static const float scale = 1. / (float)(1UL << 15);
463
464     return ival * scale;
465 }
466
467 /* Convert a packed 24bit Q0.23 value stored little-endian in a uint8_t ptr
468  * to a signed fixed-point 32 bit integer Q0.31 value. The output Q0.31 range
469  * is [0x80000000, 0x7fffff00] for the fixed-point range [0x800000, 0x7fffff].
470  * Even though the output range is limited on the positive side, there is no
471  * DC offset on the output, if the input has no DC offset.
472  *
473  * Avoid relying on the limited output range, as future implementations may go
474  * to full range.
475  */
476 static inline int32_t i32_from_p24(const uint8_t *packed24)
477 {
478     /* convert to 32b */
479 #ifdef HAVE_BIG_ENDIAN
480     return (packed24[2] << 8) | (packed24[1] << 16) | (packed24[0] << 24);
481 #else
482 #ifndef HAVE_LITTLE_ENDIAN
483     /* check to see if we really have one or the other android endian flags set. */
484 #warning "Both HAVE_LITTLE_ENDIAN and HAVE_BIG_ENDIAN not defined, default to little endian"
485 #endif
486     return (packed24[0] << 8) | (packed24[1] << 16) | (packed24[2] << 24);
487 #endif
488 }
489
490 /* Convert a 32-bit Q0.31 value to single-precision floating-point.
491  * The output float range is [-1.0, 1.0] for the fixed-point range
492  * [0x80000000, 0x7fffffff].
493  *
494  * Rounding may occur in the least significant 8 bits for large fixed point
495  * values due to storage into the 24-bit floating-point significand.
496  * Rounding will be to nearest, ties to even.
497  */
498 static inline float float_from_i32(int32_t ival)
499 {
500     static const float scale = 1. / (float)(1UL << 31);
501
502     return ival * scale;
503 }
504
505 /* Convert a packed 24bit Q0.23 value stored native endian in a uint8_t ptr
506  * to single-precision floating-point. The output float range is [-1.0, 1.0)
507  * for the fixed-point range [0x800000, 0x7fffff].
508  *
509  * There is no rounding, the conversion and representation is exact.
510  */
511 static inline float float_from_p24(const uint8_t *packed24)
512 {
513     return float_from_i32(i32_from_p24(packed24));
514 }
515
516 /* Convert a 24-bit Q8.23 value to single-precision floating-point.
517  * The nominal output float range is [-1.0, 1.0) for the fixed-point
518  * range [0xff800000, 0x007fffff].  The maximum float range is [-256.0, 256.0).
519  *
520  * There is no rounding in the nominal range, the conversion and representation
521  * is exact. For values outside the nominal range, rounding is to nearest, ties to even.
522  */
523 static inline float float_from_q8_23(int32_t ival)
524 {
525     static const float scale = 1. / (float)(1UL << 23);
526
527     return ival * scale;
528 }
529
530 /**
531  * Multiply-accumulate 16-bit terms with 32-bit result: return a + in*v.
532  */
533 static inline
534 int32_t mulAdd(int16_t in, int16_t v, int32_t a)
535 {
536 #if defined(__arm__) && !defined(__thumb__)
537     int32_t out;
538     asm( "smlabb %[out], %[in], %[v], %[a] \n"
539          : [out]"=r"(out)
540          : [in]"%r"(in), [v]"r"(v), [a]"r"(a)
541          : );
542     return out;
543 #else
544     return a + in * (int32_t)v;
545 #endif
546 }
547
548 /**
549  * Multiply 16-bit terms with 32-bit result: return in*v.
550  */
551 static inline
552 int32_t mul(int16_t in, int16_t v)
553 {
554 #if defined(__arm__) && !defined(__thumb__)
555     int32_t out;
556     asm( "smulbb %[out], %[in], %[v] \n"
557          : [out]"=r"(out)
558          : [in]"%r"(in), [v]"r"(v)
559          : );
560     return out;
561 #else
562     return in * (int32_t)v;
563 #endif
564 }
565
566 /**
567  * Similar to mulAdd, but the 16-bit terms are extracted from a 32-bit interleaved stereo pair.
568  */
569 static inline
570 int32_t mulAddRL(int left, uint32_t inRL, uint32_t vRL, int32_t a)
571 {
572 #if defined(__arm__) && !defined(__thumb__)
573     int32_t out;
574     if (left) {
575         asm( "smlabb %[out], %[inRL], %[vRL], %[a] \n"
576              : [out]"=r"(out)
577              : [inRL]"%r"(inRL), [vRL]"r"(vRL), [a]"r"(a)
578              : );
579     } else {
580         asm( "smlatt %[out], %[inRL], %[vRL], %[a] \n"
581              : [out]"=r"(out)
582              : [inRL]"%r"(inRL), [vRL]"r"(vRL), [a]"r"(a)
583              : );
584     }
585     return out;
586 #else
587     if (left) {
588         return a + (int16_t)(inRL&0xFFFF) * (int16_t)(vRL&0xFFFF);
589     } else {
590         return a + (int16_t)(inRL>>16) * (int16_t)(vRL>>16);
591     }
592 #endif
593 }
594
595 /**
596  * Similar to mul, but the 16-bit terms are extracted from a 32-bit interleaved stereo pair.
597  */
598 static inline
599 int32_t mulRL(int left, uint32_t inRL, uint32_t vRL)
600 {
601 #if defined(__arm__) && !defined(__thumb__)
602     int32_t out;
603     if (left) {
604         asm( "smulbb %[out], %[inRL], %[vRL] \n"
605              : [out]"=r"(out)
606              : [inRL]"%r"(inRL), [vRL]"r"(vRL)
607              : );
608     } else {
609         asm( "smultt %[out], %[inRL], %[vRL] \n"
610              : [out]"=r"(out)
611              : [inRL]"%r"(inRL), [vRL]"r"(vRL)
612              : );
613     }
614     return out;
615 #else
616     if (left) {
617         return (int16_t)(inRL&0xFFFF) * (int16_t)(vRL&0xFFFF);
618     } else {
619         return (int16_t)(inRL>>16) * (int16_t)(vRL>>16);
620     }
621 #endif
622 }
623
624 __END_DECLS
625
626 #endif  // ANDROID_AUDIO_PRIMITIVES_H