niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. |
| 3 | * |
| 4 | * Use of this source code is governed by a BSD-style license |
| 5 | * that can be found in the LICENSE file in the root of the source |
| 6 | * tree. An additional intellectual property rights grant can be found |
| 7 | * in the file PATENTS. All contributing project authors may |
| 8 | * be found in the AUTHORS file in the root of the source tree. |
| 9 | */ |
| 10 | |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 11 | // This header file includes the inline functions in |
| 12 | // the fix point signal processing library. |
| 13 | |
Mirko Bonadei | 92ea95e | 2017-09-15 06:47:31 +0200 | [diff] [blame] | 14 | #ifndef COMMON_AUDIO_SIGNAL_PROCESSING_INCLUDE_SPL_INL_H_ |
| 15 | #define COMMON_AUDIO_SIGNAL_PROCESSING_INCLUDE_SPL_INL_H_ |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 16 | |
Mirko Bonadei | 92ea95e | 2017-09-15 06:47:31 +0200 | [diff] [blame] | 17 | #include "rtc_base/compile_assert_c.h" |
kwiberg | 729b21f | 2016-06-02 04:02:12 -0700 | [diff] [blame] | 18 | |
| 19 | extern const int8_t kWebRtcSpl_CountLeadingZeros32_Table[64]; |
| 20 | |
| 21 | // Don't call this directly except in tests! |
| 22 | static __inline int WebRtcSpl_CountLeadingZeros32_NotBuiltin(uint32_t n) { |
| 23 | // Normalize n by rounding up to the nearest number that is a sequence of 0 |
| 24 | // bits followed by a sequence of 1 bits. This number has the same number of |
| 25 | // leading zeros as the original n. There are exactly 33 such values. |
| 26 | n |= n >> 1; |
| 27 | n |= n >> 2; |
| 28 | n |= n >> 4; |
| 29 | n |= n >> 8; |
| 30 | n |= n >> 16; |
| 31 | |
| 32 | // Multiply the modified n with a constant selected (by exhaustive search) |
| 33 | // such that each of the 33 possible values of n give a product whose 6 most |
| 34 | // significant bits are unique. Then look up the answer in the table. |
| 35 | return kWebRtcSpl_CountLeadingZeros32_Table[(n * 0x8c0b2891) >> 26]; |
| 36 | } |
| 37 | |
| 38 | // Don't call this directly except in tests! |
| 39 | static __inline int WebRtcSpl_CountLeadingZeros64_NotBuiltin(uint64_t n) { |
| 40 | const int leading_zeros = n >> 32 == 0 ? 32 : 0; |
| 41 | return leading_zeros + WebRtcSpl_CountLeadingZeros32_NotBuiltin( |
| 42 | (uint32_t)(n >> (32 - leading_zeros))); |
| 43 | } |
| 44 | |
| 45 | // Returns the number of leading zero bits in the argument. |
| 46 | static __inline int WebRtcSpl_CountLeadingZeros32(uint32_t n) { |
| 47 | #ifdef __GNUC__ |
kjellander | e0ab0ad | 2017-04-10 23:21:43 -0700 | [diff] [blame] | 48 | RTC_COMPILE_ASSERT(sizeof(unsigned int) == sizeof(uint32_t)); |
kwiberg | 729b21f | 2016-06-02 04:02:12 -0700 | [diff] [blame] | 49 | return n == 0 ? 32 : __builtin_clz(n); |
| 50 | #else |
| 51 | return WebRtcSpl_CountLeadingZeros32_NotBuiltin(n); |
| 52 | #endif |
| 53 | } |
| 54 | |
| 55 | // Returns the number of leading zero bits in the argument. |
| 56 | static __inline int WebRtcSpl_CountLeadingZeros64(uint64_t n) { |
| 57 | #ifdef __GNUC__ |
kjellander | e0ab0ad | 2017-04-10 23:21:43 -0700 | [diff] [blame] | 58 | RTC_COMPILE_ASSERT(sizeof(unsigned long long) == sizeof(uint64_t)); // NOLINT |
kwiberg | 729b21f | 2016-06-02 04:02:12 -0700 | [diff] [blame] | 59 | return n == 0 ? 64 : __builtin_clzll(n); |
| 60 | #else |
| 61 | return WebRtcSpl_CountLeadingZeros64_NotBuiltin(n); |
| 62 | #endif |
| 63 | } |
| 64 | |
kma@webrtc.org | 94771cb | 2012-08-28 04:09:50 +0000 | [diff] [blame] | 65 | #ifdef WEBRTC_ARCH_ARM_V7 |
Mirko Bonadei | 92ea95e | 2017-09-15 06:47:31 +0200 | [diff] [blame] | 66 | #include "common_audio/signal_processing/include/spl_inl_armv7.h" |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 67 | #else |
| 68 | |
andrew@webrtc.org | 8bf755d | 2013-09-18 17:40:46 +0000 | [diff] [blame] | 69 | #if defined(MIPS32_LE) |
Mirko Bonadei | 92ea95e | 2017-09-15 06:47:31 +0200 | [diff] [blame] | 70 | #include "common_audio/signal_processing/include/spl_inl_mips.h" |
andrew@webrtc.org | 8bf755d | 2013-09-18 17:40:46 +0000 | [diff] [blame] | 71 | #endif |
| 72 | |
| 73 | #if !defined(MIPS_DSP_R1_LE) |
pbos@webrtc.org | b091307 | 2013-04-09 16:40:28 +0000 | [diff] [blame] | 74 | static __inline int16_t WebRtcSpl_SatW32ToW16(int32_t value32) { |
Yves Gerey | 665174f | 2018-06-19 15:03:05 +0200 | [diff] [blame] | 75 | int16_t out16 = (int16_t)value32; |
kma@google.com | 961885a | 2011-09-26 16:35:25 +0000 | [diff] [blame] | 76 | |
| 77 | if (value32 > 32767) |
| 78 | out16 = 32767; |
| 79 | else if (value32 < -32768) |
| 80 | out16 = -32768; |
| 81 | |
| 82 | return out16; |
| 83 | } |
| 84 | |
kwiberg | bca568b | 2016-05-23 04:07:00 -0700 | [diff] [blame] | 85 | static __inline int32_t WebRtcSpl_AddSatW32(int32_t a, int32_t b) { |
| 86 | // Do the addition in unsigned numbers, since signed overflow is undefined |
| 87 | // behavior. |
| 88 | const int32_t sum = (int32_t)((uint32_t)a + (uint32_t)b); |
bjornv@webrtc.org | 1de0cc4 | 2014-08-26 09:36:25 +0000 | [diff] [blame] | 89 | |
kwiberg | bca568b | 2016-05-23 04:07:00 -0700 | [diff] [blame] | 90 | // a + b can't overflow if a and b have different signs. If they have the |
| 91 | // same sign, a + b also has the same sign iff it didn't overflow. |
| 92 | if ((a < 0) == (b < 0) && (a < 0) != (sum < 0)) { |
| 93 | // The direction of the overflow is obvious from the sign of a + b. |
| 94 | return sum < 0 ? INT32_MAX : INT32_MIN; |
bjornv@webrtc.org | 1de0cc4 | 2014-08-26 09:36:25 +0000 | [diff] [blame] | 95 | } |
kwiberg | bca568b | 2016-05-23 04:07:00 -0700 | [diff] [blame] | 96 | return sum; |
bjornv@webrtc.org | 1de0cc4 | 2014-08-26 09:36:25 +0000 | [diff] [blame] | 97 | } |
| 98 | |
kwiberg | bca568b | 2016-05-23 04:07:00 -0700 | [diff] [blame] | 99 | static __inline int32_t WebRtcSpl_SubSatW32(int32_t a, int32_t b) { |
| 100 | // Do the subtraction in unsigned numbers, since signed overflow is undefined |
| 101 | // behavior. |
| 102 | const int32_t diff = (int32_t)((uint32_t)a - (uint32_t)b); |
bjornv@webrtc.org | 1de0cc4 | 2014-08-26 09:36:25 +0000 | [diff] [blame] | 103 | |
kwiberg | bca568b | 2016-05-23 04:07:00 -0700 | [diff] [blame] | 104 | // a - b can't overflow if a and b have the same sign. If they have different |
| 105 | // signs, a - b has the same sign as a iff it didn't overflow. |
| 106 | if ((a < 0) != (b < 0) && (a < 0) != (diff < 0)) { |
| 107 | // The direction of the overflow is obvious from the sign of a - b. |
| 108 | return diff < 0 ? INT32_MAX : INT32_MIN; |
bjornv@webrtc.org | 1de0cc4 | 2014-08-26 09:36:25 +0000 | [diff] [blame] | 109 | } |
kwiberg | bca568b | 2016-05-23 04:07:00 -0700 | [diff] [blame] | 110 | return diff; |
bjornv@webrtc.org | 1de0cc4 | 2014-08-26 09:36:25 +0000 | [diff] [blame] | 111 | } |
| 112 | |
pbos@webrtc.org | b091307 | 2013-04-09 16:40:28 +0000 | [diff] [blame] | 113 | static __inline int16_t WebRtcSpl_AddSatW16(int16_t a, int16_t b) { |
Yves Gerey | 665174f | 2018-06-19 15:03:05 +0200 | [diff] [blame] | 114 | return WebRtcSpl_SatW32ToW16((int32_t)a + (int32_t)b); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 115 | } |
| 116 | |
pbos@webrtc.org | b091307 | 2013-04-09 16:40:28 +0000 | [diff] [blame] | 117 | static __inline int16_t WebRtcSpl_SubSatW16(int16_t var1, int16_t var2) { |
Yves Gerey | 665174f | 2018-06-19 15:03:05 +0200 | [diff] [blame] | 118 | return WebRtcSpl_SatW32ToW16((int32_t)var1 - (int32_t)var2); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 119 | } |
andrew@webrtc.org | 8bf755d | 2013-09-18 17:40:46 +0000 | [diff] [blame] | 120 | #endif // #if !defined(MIPS_DSP_R1_LE) |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 121 | |
andrew@webrtc.org | 8bf755d | 2013-09-18 17:40:46 +0000 | [diff] [blame] | 122 | #if !defined(MIPS32_LE) |
pbos@webrtc.org | b091307 | 2013-04-09 16:40:28 +0000 | [diff] [blame] | 123 | static __inline int16_t WebRtcSpl_GetSizeInBits(uint32_t n) { |
kwiberg | 729b21f | 2016-06-02 04:02:12 -0700 | [diff] [blame] | 124 | return 32 - WebRtcSpl_CountLeadingZeros32(n); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 125 | } |
| 126 | |
kwiberg | 729b21f | 2016-06-02 04:02:12 -0700 | [diff] [blame] | 127 | // Return the number of steps a can be left-shifted without overflow, |
| 128 | // or 0 if a == 0. |
bjornv@webrtc.org | 3cbd6c2 | 2014-09-04 13:21:44 +0000 | [diff] [blame] | 129 | static __inline int16_t WebRtcSpl_NormW32(int32_t a) { |
kwiberg | 729b21f | 2016-06-02 04:02:12 -0700 | [diff] [blame] | 130 | return a == 0 ? 0 : WebRtcSpl_CountLeadingZeros32(a < 0 ? ~a : a) - 1; |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 131 | } |
| 132 | |
kwiberg | 729b21f | 2016-06-02 04:02:12 -0700 | [diff] [blame] | 133 | // Return the number of steps a can be left-shifted without overflow, |
| 134 | // or 0 if a == 0. |
bjornv@webrtc.org | 3cbd6c2 | 2014-09-04 13:21:44 +0000 | [diff] [blame] | 135 | static __inline int16_t WebRtcSpl_NormU32(uint32_t a) { |
kwiberg | 729b21f | 2016-06-02 04:02:12 -0700 | [diff] [blame] | 136 | return a == 0 ? 0 : WebRtcSpl_CountLeadingZeros32(a); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 137 | } |
| 138 | |
kwiberg | 729b21f | 2016-06-02 04:02:12 -0700 | [diff] [blame] | 139 | // Return the number of steps a can be left-shifted without overflow, |
| 140 | // or 0 if a == 0. |
bjornv@webrtc.org | 3cbd6c2 | 2014-09-04 13:21:44 +0000 | [diff] [blame] | 141 | static __inline int16_t WebRtcSpl_NormW16(int16_t a) { |
kwiberg | 729b21f | 2016-06-02 04:02:12 -0700 | [diff] [blame] | 142 | const int32_t a32 = a; |
| 143 | return a == 0 ? 0 : WebRtcSpl_CountLeadingZeros32(a < 0 ? ~a32 : a32) - 17; |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 144 | } |
| 145 | |
pbos@webrtc.org | b091307 | 2013-04-09 16:40:28 +0000 | [diff] [blame] | 146 | static __inline int32_t WebRtc_MulAccumW16(int16_t a, int16_t b, int32_t c) { |
kma@webrtc.org | a58224f | 2011-10-05 16:44:11 +0000 | [diff] [blame] | 147 | return (a * b + c); |
| 148 | } |
andrew@webrtc.org | 8bf755d | 2013-09-18 17:40:46 +0000 | [diff] [blame] | 149 | #endif // #if !defined(MIPS32_LE) |
kma@webrtc.org | a58224f | 2011-10-05 16:44:11 +0000 | [diff] [blame] | 150 | |
kma@webrtc.org | 94771cb | 2012-08-28 04:09:50 +0000 | [diff] [blame] | 151 | #endif // WEBRTC_ARCH_ARM_V7 |
kma@google.com | 0ada410 | 2011-09-09 16:23:50 +0000 | [diff] [blame] | 152 | |
Mirko Bonadei | 92ea95e | 2017-09-15 06:47:31 +0200 | [diff] [blame] | 153 | #endif // COMMON_AUDIO_SIGNAL_PROCESSING_INCLUDE_SPL_INL_H_ |