Home | History | Annotate | Download | only in libaudioprocessing
      1 /*
      2  * Copyright (C) 2013 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_RESAMPLER_FIR_OPS_H
     18 #define ANDROID_AUDIO_RESAMPLER_FIR_OPS_H
     19 
     20 namespace android {
     21 
     22 #if defined(__arm__) && !defined(__thumb__)
     23 #define USE_INLINE_ASSEMBLY (true)
     24 #else
     25 #define USE_INLINE_ASSEMBLY (false)
     26 #endif
     27 
     28 #if defined(__aarch64__) || defined(__ARM_NEON__)
     29 #ifndef USE_NEON
     30 #define USE_NEON (true)
     31 #endif
     32 #else
     33 #define USE_NEON (false)
     34 #endif
     35 #if USE_NEON
     36 #include <arm_neon.h>
     37 #endif
     38 
     39 #if defined(__SSSE3__)  // Should be supported in x86 ABI for both 32 & 64-bit.
     40 #define USE_SSE (true)
     41 #include <tmmintrin.h>
     42 #else
     43 #define USE_SSE (false)
     44 #endif
     45 
     46 template<typename T, typename U>
     47 struct is_same
     48 {
     49     static const bool value = false;
     50 };
     51 
     52 template<typename T>
     53 struct is_same<T, T>  // partial specialization
     54 {
     55     static const bool value = true;
     56 };
     57 
     58 static inline
     59 int32_t mulRL(int left, int32_t in, uint32_t vRL)
     60 {
     61 #if USE_INLINE_ASSEMBLY
     62     int32_t out;
     63     if (left) {
     64         asm( "smultb %[out], %[in], %[vRL] \n"
     65              : [out]"=r"(out)
     66              : [in]"%r"(in), [vRL]"r"(vRL)
     67              : );
     68     } else {
     69         asm( "smultt %[out], %[in], %[vRL] \n"
     70              : [out]"=r"(out)
     71              : [in]"%r"(in), [vRL]"r"(vRL)
     72              : );
     73     }
     74     return out;
     75 #else
     76     int16_t v = left ? static_cast<int16_t>(vRL) : static_cast<int16_t>(vRL>>16);
     77     return static_cast<int32_t>((static_cast<int64_t>(in) * v) >> 16);
     78 #endif
     79 }
     80 
     81 static inline
     82 int32_t mulAdd(int16_t in, int16_t v, int32_t a)
     83 {
     84 #if USE_INLINE_ASSEMBLY
     85     int32_t out;
     86     asm( "smlabb %[out], %[v], %[in], %[a] \n"
     87          : [out]"=r"(out)
     88          : [in]"%r"(in), [v]"r"(v), [a]"r"(a)
     89          : );
     90     return out;
     91 #else
     92     return a + v * in;
     93 #endif
     94 }
     95 
     96 static inline
     97 int32_t mulAdd(int16_t in, int32_t v, int32_t a)
     98 {
     99 #if USE_INLINE_ASSEMBLY
    100     int32_t out;
    101     asm( "smlawb %[out], %[v], %[in], %[a] \n"
    102          : [out]"=r"(out)
    103          : [in]"%r"(in), [v]"r"(v), [a]"r"(a)
    104          : );
    105     return out;
    106 #else
    107     return a + static_cast<int32_t>((static_cast<int64_t>(v) * in) >> 16);
    108 #endif
    109 }
    110 
    111 static inline
    112 int32_t mulAdd(int32_t in, int32_t v, int32_t a)
    113 {
    114 #if USE_INLINE_ASSEMBLY
    115     int32_t out;
    116     asm( "smmla %[out], %[v], %[in], %[a] \n"
    117          : [out]"=r"(out)
    118          : [in]"%r"(in), [v]"r"(v), [a]"r"(a)
    119          : );
    120     return out;
    121 #else
    122     return a + static_cast<int32_t>((static_cast<int64_t>(v) * in) >> 32);
    123 #endif
    124 }
    125 
    126 static inline
    127 int32_t mulAddRL(int left, uint32_t inRL, int16_t v, int32_t a)
    128 {
    129 #if 0 // USE_INLINE_ASSEMBLY Seems to fail with Clang b/34110890
    130     int32_t out;
    131     if (left) {
    132         asm( "smlabb %[out], %[v], %[inRL], %[a] \n"
    133              : [out]"=r"(out)
    134              : [inRL]"%r"(inRL), [v]"r"(v), [a]"r"(a)
    135              : );
    136     } else {
    137         asm( "smlabt %[out], %[v], %[inRL], %[a] \n"
    138              : [out]"=r"(out)
    139              : [inRL]"%r"(inRL), [v]"r"(v), [a]"r"(a)
    140              : );
    141     }
    142     return out;
    143 #else
    144     int16_t s = left ? static_cast<int16_t>(inRL) : static_cast<int16_t>(inRL>>16);
    145     return a + v * s;
    146 #endif
    147 }
    148 
    149 static inline
    150 int32_t mulAddRL(int left, uint32_t inRL, int32_t v, int32_t a)
    151 {
    152 #if 0 // USE_INLINE_ASSEMBLY Seems to fail with Clang b/34110890
    153     int32_t out;
    154     if (left) {
    155         asm( "smlawb %[out], %[v], %[inRL], %[a] \n"
    156              : [out]"=r"(out)
    157              : [inRL]"%r"(inRL), [v]"r"(v), [a]"r"(a)
    158              : );
    159     } else {
    160         asm( "smlawt %[out], %[v], %[inRL], %[a] \n"
    161              : [out]"=r"(out)
    162              : [inRL]"%r"(inRL), [v]"r"(v), [a]"r"(a)
    163              : );
    164     }
    165     return out;
    166 #else
    167     int16_t s = left ? static_cast<int16_t>(inRL) : static_cast<int16_t>(inRL>>16);
    168     return a + static_cast<int32_t>((static_cast<int64_t>(v) * s) >> 16);
    169 #endif
    170 }
    171 
    172 } // namespace android
    173 
    174 #endif /*ANDROID_AUDIO_RESAMPLER_FIR_OPS_H*/
    175