xref: /aosp_15_r20/frameworks/av/media/libaudioprocessing/AudioResamplerFirOps.h (revision ec779b8e0859a360c3d303172224686826e6e0e1)
1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker  * Copyright (C) 2013 The Android Open Source Project
3*ec779b8eSAndroid Build Coastguard Worker  *
4*ec779b8eSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*ec779b8eSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*ec779b8eSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*ec779b8eSAndroid Build Coastguard Worker  *
8*ec779b8eSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*ec779b8eSAndroid Build Coastguard Worker  *
10*ec779b8eSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*ec779b8eSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*ec779b8eSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*ec779b8eSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*ec779b8eSAndroid Build Coastguard Worker  * limitations under the License.
15*ec779b8eSAndroid Build Coastguard Worker  */
16*ec779b8eSAndroid Build Coastguard Worker 
17*ec779b8eSAndroid Build Coastguard Worker #ifndef ANDROID_AUDIO_RESAMPLER_FIR_OPS_H
18*ec779b8eSAndroid Build Coastguard Worker #define ANDROID_AUDIO_RESAMPLER_FIR_OPS_H
19*ec779b8eSAndroid Build Coastguard Worker 
20*ec779b8eSAndroid Build Coastguard Worker namespace android {
21*ec779b8eSAndroid Build Coastguard Worker 
22*ec779b8eSAndroid Build Coastguard Worker #if defined(__arm__) && !defined(__thumb__)
23*ec779b8eSAndroid Build Coastguard Worker #define USE_INLINE_ASSEMBLY (true)
24*ec779b8eSAndroid Build Coastguard Worker #else
25*ec779b8eSAndroid Build Coastguard Worker #define USE_INLINE_ASSEMBLY (false)
26*ec779b8eSAndroid Build Coastguard Worker #endif
27*ec779b8eSAndroid Build Coastguard Worker 
28*ec779b8eSAndroid Build Coastguard Worker #if defined(__aarch64__) || defined(__ARM_NEON__)
29*ec779b8eSAndroid Build Coastguard Worker #ifndef USE_NEON
30*ec779b8eSAndroid Build Coastguard Worker #define USE_NEON (true)
31*ec779b8eSAndroid Build Coastguard Worker #endif
32*ec779b8eSAndroid Build Coastguard Worker #else
33*ec779b8eSAndroid Build Coastguard Worker #define USE_NEON (false)
34*ec779b8eSAndroid Build Coastguard Worker #endif
35*ec779b8eSAndroid Build Coastguard Worker #if USE_NEON
36*ec779b8eSAndroid Build Coastguard Worker #include <arm_neon.h>
37*ec779b8eSAndroid Build Coastguard Worker #endif
38*ec779b8eSAndroid Build Coastguard Worker 
39*ec779b8eSAndroid Build Coastguard Worker #if defined(__AVX2__)  // Should be supported in x86 ABI for both 32 & 64-bit.
40*ec779b8eSAndroid Build Coastguard Worker #define USE_AVX2 (true)  // Inference AVX2/FMA Intrinsics
41*ec779b8eSAndroid Build Coastguard Worker #define USE_SSE (true)
42*ec779b8eSAndroid Build Coastguard Worker #include <immintrin.h>
43*ec779b8eSAndroid Build Coastguard Worker #elif defined(__SSSE3__)  // Should be supported in x86 ABI for both 32 & 64-bit.
44*ec779b8eSAndroid Build Coastguard Worker #define USE_SSE (true)  // Inference SSE Intrinsics
45*ec779b8eSAndroid Build Coastguard Worker #define USE_AVX2 (false)
46*ec779b8eSAndroid Build Coastguard Worker #include <tmmintrin.h>
47*ec779b8eSAndroid Build Coastguard Worker #else
48*ec779b8eSAndroid Build Coastguard Worker #define USE_SSE (false)
49*ec779b8eSAndroid Build Coastguard Worker #define USE_AVX2(false)
50*ec779b8eSAndroid Build Coastguard Worker #endif
51*ec779b8eSAndroid Build Coastguard Worker 
52*ec779b8eSAndroid Build Coastguard Worker 
53*ec779b8eSAndroid Build Coastguard Worker template<typename T, typename U>
54*ec779b8eSAndroid Build Coastguard Worker struct is_same
55*ec779b8eSAndroid Build Coastguard Worker {
56*ec779b8eSAndroid Build Coastguard Worker     static const bool value = false;
57*ec779b8eSAndroid Build Coastguard Worker };
58*ec779b8eSAndroid Build Coastguard Worker 
59*ec779b8eSAndroid Build Coastguard Worker template<typename T>
60*ec779b8eSAndroid Build Coastguard Worker struct is_same<T, T>  // partial specialization
61*ec779b8eSAndroid Build Coastguard Worker {
62*ec779b8eSAndroid Build Coastguard Worker     static const bool value = true;
63*ec779b8eSAndroid Build Coastguard Worker };
64*ec779b8eSAndroid Build Coastguard Worker 
65*ec779b8eSAndroid Build Coastguard Worker static inline
66*ec779b8eSAndroid Build Coastguard Worker int32_t mulRL(int left, int32_t in, uint32_t vRL)
67*ec779b8eSAndroid Build Coastguard Worker {
68*ec779b8eSAndroid Build Coastguard Worker #if USE_INLINE_ASSEMBLY
69*ec779b8eSAndroid Build Coastguard Worker     int32_t out;
70*ec779b8eSAndroid Build Coastguard Worker     if (left) {
71*ec779b8eSAndroid Build Coastguard Worker         asm( "smultb %[out], %[in], %[vRL] \n"
72*ec779b8eSAndroid Build Coastguard Worker              : [out]"=r"(out)
73*ec779b8eSAndroid Build Coastguard Worker              : [in]"%r"(in), [vRL]"r"(vRL)
74*ec779b8eSAndroid Build Coastguard Worker              : );
75*ec779b8eSAndroid Build Coastguard Worker     } else {
76*ec779b8eSAndroid Build Coastguard Worker         asm( "smultt %[out], %[in], %[vRL] \n"
77*ec779b8eSAndroid Build Coastguard Worker              : [out]"=r"(out)
78*ec779b8eSAndroid Build Coastguard Worker              : [in]"%r"(in), [vRL]"r"(vRL)
79*ec779b8eSAndroid Build Coastguard Worker              : );
80*ec779b8eSAndroid Build Coastguard Worker     }
81*ec779b8eSAndroid Build Coastguard Worker     return out;
82*ec779b8eSAndroid Build Coastguard Worker #else
83*ec779b8eSAndroid Build Coastguard Worker     int16_t v = left ? static_cast<int16_t>(vRL) : static_cast<int16_t>(vRL>>16);
84*ec779b8eSAndroid Build Coastguard Worker     return static_cast<int32_t>((static_cast<int64_t>(in) * v) >> 16);
85*ec779b8eSAndroid Build Coastguard Worker #endif
86*ec779b8eSAndroid Build Coastguard Worker }
87*ec779b8eSAndroid Build Coastguard Worker 
88*ec779b8eSAndroid Build Coastguard Worker static inline
89*ec779b8eSAndroid Build Coastguard Worker int32_t mulAdd(int16_t in, int16_t v, int32_t a)
90*ec779b8eSAndroid Build Coastguard Worker {
91*ec779b8eSAndroid Build Coastguard Worker #if USE_INLINE_ASSEMBLY
92*ec779b8eSAndroid Build Coastguard Worker     int32_t out;
93*ec779b8eSAndroid Build Coastguard Worker     asm( "smlabb %[out], %[v], %[in], %[a] \n"
94*ec779b8eSAndroid Build Coastguard Worker          : [out]"=r"(out)
95*ec779b8eSAndroid Build Coastguard Worker          : [in]"%r"(in), [v]"r"(v), [a]"r"(a)
96*ec779b8eSAndroid Build Coastguard Worker          : );
97*ec779b8eSAndroid Build Coastguard Worker     return out;
98*ec779b8eSAndroid Build Coastguard Worker #else
99*ec779b8eSAndroid Build Coastguard Worker     return a + v * in;
100*ec779b8eSAndroid Build Coastguard Worker #endif
101*ec779b8eSAndroid Build Coastguard Worker }
102*ec779b8eSAndroid Build Coastguard Worker 
103*ec779b8eSAndroid Build Coastguard Worker static inline
104*ec779b8eSAndroid Build Coastguard Worker int32_t mulAdd(int16_t in, int32_t v, int32_t a)
105*ec779b8eSAndroid Build Coastguard Worker {
106*ec779b8eSAndroid Build Coastguard Worker #if USE_INLINE_ASSEMBLY
107*ec779b8eSAndroid Build Coastguard Worker     int32_t out;
108*ec779b8eSAndroid Build Coastguard Worker     asm( "smlawb %[out], %[v], %[in], %[a] \n"
109*ec779b8eSAndroid Build Coastguard Worker          : [out]"=r"(out)
110*ec779b8eSAndroid Build Coastguard Worker          : [in]"%r"(in), [v]"r"(v), [a]"r"(a)
111*ec779b8eSAndroid Build Coastguard Worker          : );
112*ec779b8eSAndroid Build Coastguard Worker     return out;
113*ec779b8eSAndroid Build Coastguard Worker #else
114*ec779b8eSAndroid Build Coastguard Worker     return a + static_cast<int32_t>((static_cast<int64_t>(v) * in) >> 16);
115*ec779b8eSAndroid Build Coastguard Worker #endif
116*ec779b8eSAndroid Build Coastguard Worker }
117*ec779b8eSAndroid Build Coastguard Worker 
118*ec779b8eSAndroid Build Coastguard Worker static inline
119*ec779b8eSAndroid Build Coastguard Worker int32_t mulAdd(int32_t in, int32_t v, int32_t a)
120*ec779b8eSAndroid Build Coastguard Worker {
121*ec779b8eSAndroid Build Coastguard Worker #if USE_INLINE_ASSEMBLY
122*ec779b8eSAndroid Build Coastguard Worker     int32_t out;
123*ec779b8eSAndroid Build Coastguard Worker     asm( "smmla %[out], %[v], %[in], %[a] \n"
124*ec779b8eSAndroid Build Coastguard Worker          : [out]"=r"(out)
125*ec779b8eSAndroid Build Coastguard Worker          : [in]"%r"(in), [v]"r"(v), [a]"r"(a)
126*ec779b8eSAndroid Build Coastguard Worker          : );
127*ec779b8eSAndroid Build Coastguard Worker     return out;
128*ec779b8eSAndroid Build Coastguard Worker #else
129*ec779b8eSAndroid Build Coastguard Worker     return a + static_cast<int32_t>((static_cast<int64_t>(v) * in) >> 32);
130*ec779b8eSAndroid Build Coastguard Worker #endif
131*ec779b8eSAndroid Build Coastguard Worker }
132*ec779b8eSAndroid Build Coastguard Worker 
133*ec779b8eSAndroid Build Coastguard Worker static inline
134*ec779b8eSAndroid Build Coastguard Worker int32_t mulAddRL(int left, uint32_t inRL, int16_t v, int32_t a)
135*ec779b8eSAndroid Build Coastguard Worker {
136*ec779b8eSAndroid Build Coastguard Worker #if 0 // USE_INLINE_ASSEMBLY Seems to fail with Clang b/34110890
137*ec779b8eSAndroid Build Coastguard Worker     int32_t out;
138*ec779b8eSAndroid Build Coastguard Worker     if (left) {
139*ec779b8eSAndroid Build Coastguard Worker         asm( "smlabb %[out], %[v], %[inRL], %[a] \n"
140*ec779b8eSAndroid Build Coastguard Worker              : [out]"=r"(out)
141*ec779b8eSAndroid Build Coastguard Worker              : [inRL]"%r"(inRL), [v]"r"(v), [a]"r"(a)
142*ec779b8eSAndroid Build Coastguard Worker              : );
143*ec779b8eSAndroid Build Coastguard Worker     } else {
144*ec779b8eSAndroid Build Coastguard Worker         asm( "smlabt %[out], %[v], %[inRL], %[a] \n"
145*ec779b8eSAndroid Build Coastguard Worker              : [out]"=r"(out)
146*ec779b8eSAndroid Build Coastguard Worker              : [inRL]"%r"(inRL), [v]"r"(v), [a]"r"(a)
147*ec779b8eSAndroid Build Coastguard Worker              : );
148*ec779b8eSAndroid Build Coastguard Worker     }
149*ec779b8eSAndroid Build Coastguard Worker     return out;
150*ec779b8eSAndroid Build Coastguard Worker #else
151*ec779b8eSAndroid Build Coastguard Worker     int16_t s = left ? static_cast<int16_t>(inRL) : static_cast<int16_t>(inRL>>16);
152*ec779b8eSAndroid Build Coastguard Worker     return a + v * s;
153*ec779b8eSAndroid Build Coastguard Worker #endif
154*ec779b8eSAndroid Build Coastguard Worker }
155*ec779b8eSAndroid Build Coastguard Worker 
156*ec779b8eSAndroid Build Coastguard Worker static inline
157*ec779b8eSAndroid Build Coastguard Worker int32_t mulAddRL(int left, uint32_t inRL, int32_t v, int32_t a)
158*ec779b8eSAndroid Build Coastguard Worker {
159*ec779b8eSAndroid Build Coastguard Worker #if 0 // USE_INLINE_ASSEMBLY Seems to fail with Clang b/34110890
160*ec779b8eSAndroid Build Coastguard Worker     int32_t out;
161*ec779b8eSAndroid Build Coastguard Worker     if (left) {
162*ec779b8eSAndroid Build Coastguard Worker         asm( "smlawb %[out], %[v], %[inRL], %[a] \n"
163*ec779b8eSAndroid Build Coastguard Worker              : [out]"=r"(out)
164*ec779b8eSAndroid Build Coastguard Worker              : [inRL]"%r"(inRL), [v]"r"(v), [a]"r"(a)
165*ec779b8eSAndroid Build Coastguard Worker              : );
166*ec779b8eSAndroid Build Coastguard Worker     } else {
167*ec779b8eSAndroid Build Coastguard Worker         asm( "smlawt %[out], %[v], %[inRL], %[a] \n"
168*ec779b8eSAndroid Build Coastguard Worker              : [out]"=r"(out)
169*ec779b8eSAndroid Build Coastguard Worker              : [inRL]"%r"(inRL), [v]"r"(v), [a]"r"(a)
170*ec779b8eSAndroid Build Coastguard Worker              : );
171*ec779b8eSAndroid Build Coastguard Worker     }
172*ec779b8eSAndroid Build Coastguard Worker     return out;
173*ec779b8eSAndroid Build Coastguard Worker #else
174*ec779b8eSAndroid Build Coastguard Worker     int16_t s = left ? static_cast<int16_t>(inRL) : static_cast<int16_t>(inRL>>16);
175*ec779b8eSAndroid Build Coastguard Worker     return a + static_cast<int32_t>((static_cast<int64_t>(v) * s) >> 16);
176*ec779b8eSAndroid Build Coastguard Worker #endif
177*ec779b8eSAndroid Build Coastguard Worker }
178*ec779b8eSAndroid Build Coastguard Worker 
179*ec779b8eSAndroid Build Coastguard Worker } // namespace android
180*ec779b8eSAndroid Build Coastguard Worker 
181*ec779b8eSAndroid Build Coastguard Worker #endif /*ANDROID_AUDIO_RESAMPLER_FIR_OPS_H*/
182