primitives.h revision 632e0c016c9a518b36f09988b740b3bc1199c3e4
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 <sys/cdefs.h>
22
23__BEGIN_DECLS
24
25/**
26 * Dither and clamp pairs of 32-bit input samples (sums) to 16-bit output samples (out).
27 * Each 32-bit input sample is a signed fixed-point Q19.12.
28 * The .12 fraction is dithered, and the integer portion is then clamped to Q15.
29 * For interleaved stereo, c is the number of sample pairs,
30 * and out is an array of interleaved pairs of 16-bit samples per channel.
31 * For mono, c is the number of samples / 2, and out is an array of 16-bit samples.
32 * The name "dither" is a misnomer; the current implementation does not actually dither
33 * but uses truncation.  This may change.
34 */
35void ditherAndClamp(int32_t* out, const int32_t *sums, size_t c);
36
37/**
38 * Clamp (aka hard limit or clip) a signed 32-bit sample to 16-bit range.
39 */
40static inline int16_t clamp16(int32_t sample)
41{
42    if ((sample>>15) ^ (sample>>31))
43        sample = 0x7FFF ^ (sample>>31);
44    return sample;
45}
46
47/**
48 * Multiply-accumulate 16-bit terms with 32-bit result: return a + in*v.
49 */
50static inline
51int32_t mulAdd(int16_t in, int16_t v, int32_t a)
52{
53#if defined(__arm__) && !defined(__thumb__)
54    int32_t out;
55    asm( "smlabb %[out], %[in], %[v], %[a] \n"
56         : [out]"=r"(out)
57         : [in]"%r"(in), [v]"r"(v), [a]"r"(a)
58         : );
59    return out;
60#else
61    return a + in * (int32_t)v;
62#endif
63}
64
65/**
66 * Multiply 16-bit terms with 32-bit result: return in*v.
67 */
68static inline
69int32_t mul(int16_t in, int16_t v)
70{
71#if defined(__arm__) && !defined(__thumb__)
72    int32_t out;
73    asm( "smulbb %[out], %[in], %[v] \n"
74         : [out]"=r"(out)
75         : [in]"%r"(in), [v]"r"(v)
76         : );
77    return out;
78#else
79    return in * (int32_t)v;
80#endif
81}
82
83/**
84 * Similar to mulAdd, but the 16-bit terms are extracted from a 32-bit interleaved stereo pair.
85 */
86static inline
87int32_t mulAddRL(int left, uint32_t inRL, uint32_t vRL, int32_t a)
88{
89#if defined(__arm__) && !defined(__thumb__)
90    int32_t out;
91    if (left) {
92        asm( "smlabb %[out], %[inRL], %[vRL], %[a] \n"
93             : [out]"=r"(out)
94             : [inRL]"%r"(inRL), [vRL]"r"(vRL), [a]"r"(a)
95             : );
96    } else {
97        asm( "smlatt %[out], %[inRL], %[vRL], %[a] \n"
98             : [out]"=r"(out)
99             : [inRL]"%r"(inRL), [vRL]"r"(vRL), [a]"r"(a)
100             : );
101    }
102    return out;
103#else
104    if (left) {
105        return a + (int16_t)(inRL&0xFFFF) * (int16_t)(vRL&0xFFFF);
106    } else {
107        return a + (int16_t)(inRL>>16) * (int16_t)(vRL>>16);
108    }
109#endif
110}
111
112/**
113 * Similar to mul, but the 16-bit terms are extracted from a 32-bit interleaved stereo pair.
114 */
115static inline
116int32_t mulRL(int left, uint32_t inRL, uint32_t vRL)
117{
118#if defined(__arm__) && !defined(__thumb__)
119    int32_t out;
120    if (left) {
121        asm( "smulbb %[out], %[inRL], %[vRL] \n"
122             : [out]"=r"(out)
123             : [inRL]"%r"(inRL), [vRL]"r"(vRL)
124             : );
125    } else {
126        asm( "smultt %[out], %[inRL], %[vRL] \n"
127             : [out]"=r"(out)
128             : [inRL]"%r"(inRL), [vRL]"r"(vRL)
129             : );
130    }
131    return out;
132#else
133    if (left) {
134        return (int16_t)(inRL&0xFFFF) * (int16_t)(vRL&0xFFFF);
135    } else {
136        return (int16_t)(inRL>>16) * (int16_t)(vRL>>16);
137    }
138#endif
139}
140
141__END_DECLS
142
143#endif  // ANDROID_AUDIO_PRIMITIVES_H
144