andrew@webrtc.org | a7b57da | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2012 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 | |
pbos@webrtc.org | abf0cd8 | 2013-05-27 09:49:58 +0000 | [diff] [blame] | 11 | #include "testing/gtest/include/gtest/gtest.h" |
| 12 | #include "webrtc/common_audio/signal_processing/include/signal_processing_library.h" |
andrew@webrtc.org | a7b57da | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 13 | |
| 14 | static const int kVector16Size = 9; |
| 15 | static const int16_t vector16[kVector16Size] = {1, -15511, 4323, 1963, |
| 16 | WEBRTC_SPL_WORD16_MAX, 0, WEBRTC_SPL_WORD16_MIN + 5, -3333, 345}; |
| 17 | |
| 18 | class SplTest : public testing::Test { |
| 19 | protected: |
| 20 | SplTest() { |
| 21 | WebRtcSpl_Init(); |
| 22 | } |
| 23 | virtual ~SplTest() { |
| 24 | } |
| 25 | }; |
| 26 | |
| 27 | TEST_F(SplTest, MacroTest) { |
| 28 | // Macros with inputs. |
| 29 | int A = 10; |
| 30 | int B = 21; |
| 31 | int a = -3; |
| 32 | int b = WEBRTC_SPL_WORD32_MAX; |
| 33 | int nr = 2; |
| 34 | int d_ptr2 = 0; |
| 35 | |
| 36 | EXPECT_EQ(10, WEBRTC_SPL_MIN(A, B)); |
| 37 | EXPECT_EQ(21, WEBRTC_SPL_MAX(A, B)); |
| 38 | |
| 39 | EXPECT_EQ(3, WEBRTC_SPL_ABS_W16(a)); |
| 40 | EXPECT_EQ(3, WEBRTC_SPL_ABS_W32(a)); |
| 41 | EXPECT_EQ(0, WEBRTC_SPL_GET_BYTE(&B, nr)); |
| 42 | WEBRTC_SPL_SET_BYTE(&d_ptr2, 1, nr); |
| 43 | EXPECT_EQ(65536, d_ptr2); |
| 44 | |
| 45 | EXPECT_EQ(-63, WEBRTC_SPL_MUL(a, B)); |
| 46 | EXPECT_EQ(-2147483645, WEBRTC_SPL_MUL(a, b)); |
| 47 | EXPECT_EQ(2147483651u, WEBRTC_SPL_UMUL(a, b)); |
| 48 | b = WEBRTC_SPL_WORD16_MAX >> 1; |
andrew@webrtc.org | a7b57da | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 49 | EXPECT_EQ(1073627139u, WEBRTC_SPL_UMUL_16_16(a, b)); |
andrew@webrtc.org | a7b57da | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 50 | EXPECT_EQ(4294918147u, WEBRTC_SPL_UMUL_32_16(a, b)); |
| 51 | EXPECT_EQ(65535u, WEBRTC_SPL_UMUL_32_16_RSFT16(a, b)); |
| 52 | EXPECT_EQ(-49149, WEBRTC_SPL_MUL_16_U16(a, b)); |
| 53 | |
| 54 | a = b; |
| 55 | b = -3; |
| 56 | EXPECT_EQ(-5461, WEBRTC_SPL_DIV(a, b)); |
| 57 | EXPECT_EQ(0u, WEBRTC_SPL_UDIV(a, b)); |
| 58 | |
| 59 | EXPECT_EQ(-1, WEBRTC_SPL_MUL_16_32_RSFT16(a, b)); |
| 60 | EXPECT_EQ(-1, WEBRTC_SPL_MUL_16_32_RSFT15(a, b)); |
| 61 | EXPECT_EQ(-3, WEBRTC_SPL_MUL_16_32_RSFT14(a, b)); |
| 62 | EXPECT_EQ(-24, WEBRTC_SPL_MUL_16_32_RSFT11(a, b)); |
| 63 | |
andrew@webrtc.org | a7b57da | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 64 | int a32a = (WEBRTC_SPL_WORD32_MAX >> 16); |
| 65 | int a32b = (WEBRTC_SPL_WORD32_MAX & 0x0000ffff); |
| 66 | EXPECT_EQ(5, WEBRTC_SPL_MUL_32_32_RSFT32(a32a, a32b, A)); |
andrew@webrtc.org | a7b57da | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 67 | |
| 68 | EXPECT_EQ(-12288, WEBRTC_SPL_MUL_16_16_RSFT(a, b, 2)); |
| 69 | EXPECT_EQ(-12287, WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND(a, b, 2)); |
andrew@webrtc.org | a7b57da | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 70 | |
| 71 | EXPECT_EQ(16380, WEBRTC_SPL_ADD_SAT_W32(a, b)); |
| 72 | EXPECT_EQ(21, WEBRTC_SPL_SAT(a, A, B)); |
| 73 | EXPECT_EQ(21, WEBRTC_SPL_SAT(a, B, A)); |
| 74 | EXPECT_EQ(-49149, WEBRTC_SPL_MUL_32_16(a, b)); |
| 75 | |
| 76 | EXPECT_EQ(16386, WEBRTC_SPL_SUB_SAT_W32(a, b)); |
| 77 | EXPECT_EQ(16380, WEBRTC_SPL_ADD_SAT_W16(a, b)); |
andrew@webrtc.org | a7b57da | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 78 | |
andrew@webrtc.org | a7b57da | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 79 | // Shifting with negative numbers allowed |
| 80 | int shift_amount = 1; // Workaround compiler warning using variable here. |
| 81 | // Positive means left shift |
andrew@webrtc.org | a7b57da | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 82 | EXPECT_EQ(32766, WEBRTC_SPL_SHIFT_W32(a, shift_amount)); |
| 83 | |
| 84 | // Shifting with negative numbers not allowed |
| 85 | // We cannot do casting here due to signed/unsigned problem |
| 86 | EXPECT_EQ(8191, WEBRTC_SPL_RSHIFT_W16(a, 1)); |
| 87 | EXPECT_EQ(32766, WEBRTC_SPL_LSHIFT_W16(a, 1)); |
| 88 | EXPECT_EQ(8191, WEBRTC_SPL_RSHIFT_W32(a, 1)); |
| 89 | EXPECT_EQ(32766, WEBRTC_SPL_LSHIFT_W32(a, 1)); |
| 90 | |
andrew@webrtc.org | a7b57da | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 91 | EXPECT_EQ(8191u, WEBRTC_SPL_RSHIFT_U32(a, 1)); |
| 92 | EXPECT_EQ(32766u, WEBRTC_SPL_LSHIFT_U32(a, 1)); |
| 93 | |
| 94 | EXPECT_EQ(1470, WEBRTC_SPL_RAND(A)); |
| 95 | |
| 96 | EXPECT_EQ(-49149, WEBRTC_SPL_MUL_16_16(a, b)); |
| 97 | EXPECT_EQ(1073676289, WEBRTC_SPL_MUL_16_16(WEBRTC_SPL_WORD16_MAX, |
| 98 | WEBRTC_SPL_WORD16_MAX)); |
| 99 | EXPECT_EQ(1073709055, WEBRTC_SPL_MUL_16_32_RSFT16(WEBRTC_SPL_WORD16_MAX, |
| 100 | WEBRTC_SPL_WORD32_MAX)); |
| 101 | EXPECT_EQ(1073741824, WEBRTC_SPL_MUL_16_32_RSFT16(WEBRTC_SPL_WORD16_MIN, |
| 102 | WEBRTC_SPL_WORD32_MIN)); |
| 103 | #ifdef WEBRTC_ARCH_ARM_V7 |
| 104 | EXPECT_EQ(-1073741824, |
| 105 | WEBRTC_SPL_MUL_16_32_RSFT16(WEBRTC_SPL_WORD16_MIN, |
| 106 | WEBRTC_SPL_WORD32_MAX)); |
| 107 | EXPECT_EQ(0x3fffffff, WEBRTC_SPL_MUL_32_32_RSFT32(WEBRTC_SPL_WORD16_MAX, |
| 108 | 0xffff, WEBRTC_SPL_WORD32_MAX)); |
andrew@webrtc.org | a7b57da | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 109 | #else |
| 110 | EXPECT_EQ(-1073741823, |
| 111 | WEBRTC_SPL_MUL_16_32_RSFT16(WEBRTC_SPL_WORD16_MIN, |
| 112 | WEBRTC_SPL_WORD32_MAX)); |
| 113 | EXPECT_EQ(0x3fff7ffe, WEBRTC_SPL_MUL_32_32_RSFT32(WEBRTC_SPL_WORD16_MAX, |
| 114 | 0xffff, WEBRTC_SPL_WORD32_MAX)); |
andrew@webrtc.org | a7b57da | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 115 | #endif |
| 116 | } |
| 117 | |
| 118 | TEST_F(SplTest, InlineTest) { |
pbos@webrtc.org | 1727dc7 | 2013-04-09 16:40:28 +0000 | [diff] [blame] | 119 | int16_t a16 = 121; |
| 120 | int16_t b16 = -17; |
| 121 | int32_t a32 = 111121; |
| 122 | int32_t b32 = -1711; |
andrew@webrtc.org | a7b57da | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 123 | char bVersion[8]; |
| 124 | |
| 125 | EXPECT_EQ(17, WebRtcSpl_GetSizeInBits(a32)); |
| 126 | |
| 127 | EXPECT_EQ(0, WebRtcSpl_NormW32(0)); |
| 128 | EXPECT_EQ(31, WebRtcSpl_NormW32(-1)); |
| 129 | EXPECT_EQ(0, WebRtcSpl_NormW32(WEBRTC_SPL_WORD32_MIN)); |
| 130 | EXPECT_EQ(14, WebRtcSpl_NormW32(a32)); |
| 131 | |
| 132 | EXPECT_EQ(0, WebRtcSpl_NormW16(0)); |
| 133 | EXPECT_EQ(15, WebRtcSpl_NormW16(-1)); |
| 134 | EXPECT_EQ(0, WebRtcSpl_NormW16(WEBRTC_SPL_WORD16_MIN)); |
| 135 | EXPECT_EQ(4, WebRtcSpl_NormW16(b32)); |
| 136 | |
| 137 | EXPECT_EQ(0, WebRtcSpl_NormU32(0)); |
| 138 | EXPECT_EQ(0, WebRtcSpl_NormU32(-1)); |
| 139 | EXPECT_EQ(0, WebRtcSpl_NormU32(WEBRTC_SPL_WORD32_MIN)); |
| 140 | EXPECT_EQ(15, WebRtcSpl_NormU32(a32)); |
| 141 | |
| 142 | EXPECT_EQ(104, WebRtcSpl_AddSatW16(a16, b16)); |
| 143 | EXPECT_EQ(138, WebRtcSpl_SubSatW16(a16, b16)); |
| 144 | |
| 145 | EXPECT_EQ(109410, WebRtcSpl_AddSatW32(a32, b32)); |
| 146 | EXPECT_EQ(112832, WebRtcSpl_SubSatW32(a32, b32)); |
| 147 | |
| 148 | a32 = 0x80000000; |
| 149 | b32 = 0x80000000; |
| 150 | // Cast to signed int to avoid compiler complaint on gtest.h. |
| 151 | EXPECT_EQ(static_cast<int>(0x80000000), WebRtcSpl_AddSatW32(a32, b32)); |
| 152 | a32 = 0x7fffffff; |
| 153 | b32 = 0x7fffffff; |
| 154 | EXPECT_EQ(0x7fffffff, WebRtcSpl_AddSatW32(a32, b32)); |
| 155 | a32 = 0; |
| 156 | b32 = 0x80000000; |
| 157 | EXPECT_EQ(0x7fffffff, WebRtcSpl_SubSatW32(a32, b32)); |
| 158 | a32 = 0x7fffffff; |
| 159 | b32 = 0x80000000; |
| 160 | EXPECT_EQ(0x7fffffff, WebRtcSpl_SubSatW32(a32, b32)); |
| 161 | a32 = 0x80000000; |
| 162 | b32 = 0x7fffffff; |
| 163 | EXPECT_EQ(static_cast<int>(0x80000000), WebRtcSpl_SubSatW32(a32, b32)); |
| 164 | |
| 165 | EXPECT_EQ(0, WebRtcSpl_get_version(bVersion, 8)); |
| 166 | } |
| 167 | |
| 168 | TEST_F(SplTest, MathOperationsTest) { |
| 169 | int A = 1134567892; |
pbos@webrtc.org | 1727dc7 | 2013-04-09 16:40:28 +0000 | [diff] [blame] | 170 | int32_t num = 117; |
| 171 | int32_t den = -5; |
| 172 | uint16_t denU = 5; |
andrew@webrtc.org | a7b57da | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 173 | EXPECT_EQ(33700, WebRtcSpl_Sqrt(A)); |
| 174 | EXPECT_EQ(33683, WebRtcSpl_SqrtFloor(A)); |
| 175 | |
| 176 | |
| 177 | EXPECT_EQ(-91772805, WebRtcSpl_DivResultInQ31(den, num)); |
pbos@webrtc.org | 1727dc7 | 2013-04-09 16:40:28 +0000 | [diff] [blame] | 178 | EXPECT_EQ(-23, WebRtcSpl_DivW32W16ResW16(num, (int16_t)den)); |
| 179 | EXPECT_EQ(-23, WebRtcSpl_DivW32W16(num, (int16_t)den)); |
andrew@webrtc.org | a7b57da | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 180 | EXPECT_EQ(23u, WebRtcSpl_DivU32U16(num, denU)); |
| 181 | EXPECT_EQ(0, WebRtcSpl_DivW32HiLow(128, 0, 256)); |
| 182 | } |
| 183 | |
| 184 | TEST_F(SplTest, BasicArrayOperationsTest) { |
| 185 | const int kVectorSize = 4; |
| 186 | int B[] = {4, 12, 133, 1100}; |
pbos@webrtc.org | 1727dc7 | 2013-04-09 16:40:28 +0000 | [diff] [blame] | 187 | uint8_t b8[kVectorSize]; |
| 188 | int16_t b16[kVectorSize]; |
| 189 | int32_t b32[kVectorSize]; |
andrew@webrtc.org | a7b57da | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 190 | |
pbos@webrtc.org | 1727dc7 | 2013-04-09 16:40:28 +0000 | [diff] [blame] | 191 | uint8_t bTmp8[kVectorSize]; |
| 192 | int16_t bTmp16[kVectorSize]; |
| 193 | int32_t bTmp32[kVectorSize]; |
andrew@webrtc.org | a7b57da | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 194 | |
| 195 | WebRtcSpl_MemSetW16(b16, 3, kVectorSize); |
| 196 | for (int kk = 0; kk < kVectorSize; ++kk) { |
| 197 | EXPECT_EQ(3, b16[kk]); |
| 198 | } |
| 199 | EXPECT_EQ(kVectorSize, WebRtcSpl_ZerosArrayW16(b16, kVectorSize)); |
| 200 | for (int kk = 0; kk < kVectorSize; ++kk) { |
| 201 | EXPECT_EQ(0, b16[kk]); |
| 202 | } |
| 203 | EXPECT_EQ(kVectorSize, WebRtcSpl_OnesArrayW16(b16, kVectorSize)); |
| 204 | for (int kk = 0; kk < kVectorSize; ++kk) { |
| 205 | EXPECT_EQ(1, b16[kk]); |
| 206 | } |
| 207 | WebRtcSpl_MemSetW32(b32, 3, kVectorSize); |
| 208 | for (int kk = 0; kk < kVectorSize; ++kk) { |
| 209 | EXPECT_EQ(3, b32[kk]); |
| 210 | } |
| 211 | EXPECT_EQ(kVectorSize, WebRtcSpl_ZerosArrayW32(b32, kVectorSize)); |
| 212 | for (int kk = 0; kk < kVectorSize; ++kk) { |
| 213 | EXPECT_EQ(0, b32[kk]); |
| 214 | } |
| 215 | EXPECT_EQ(kVectorSize, WebRtcSpl_OnesArrayW32(b32, kVectorSize)); |
| 216 | for (int kk = 0; kk < kVectorSize; ++kk) { |
| 217 | EXPECT_EQ(1, b32[kk]); |
| 218 | } |
| 219 | for (int kk = 0; kk < kVectorSize; ++kk) { |
pbos@webrtc.org | 1727dc7 | 2013-04-09 16:40:28 +0000 | [diff] [blame] | 220 | bTmp8[kk] = (int8_t)kk; |
| 221 | bTmp16[kk] = (int16_t)kk; |
| 222 | bTmp32[kk] = (int32_t)kk; |
andrew@webrtc.org | a7b57da | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 223 | } |
| 224 | WEBRTC_SPL_MEMCPY_W8(b8, bTmp8, kVectorSize); |
| 225 | for (int kk = 0; kk < kVectorSize; ++kk) { |
| 226 | EXPECT_EQ(b8[kk], bTmp8[kk]); |
| 227 | } |
| 228 | WEBRTC_SPL_MEMCPY_W16(b16, bTmp16, kVectorSize); |
| 229 | for (int kk = 0; kk < kVectorSize; ++kk) { |
| 230 | EXPECT_EQ(b16[kk], bTmp16[kk]); |
| 231 | } |
| 232 | // WEBRTC_SPL_MEMCPY_W32(b32, bTmp32, kVectorSize); |
| 233 | // for (int kk = 0; kk < kVectorSize; ++kk) { |
| 234 | // EXPECT_EQ(b32[kk], bTmp32[kk]); |
| 235 | // } |
| 236 | EXPECT_EQ(2, WebRtcSpl_CopyFromEndW16(b16, kVectorSize, 2, bTmp16)); |
| 237 | for (int kk = 0; kk < 2; ++kk) { |
| 238 | EXPECT_EQ(kk+2, bTmp16[kk]); |
| 239 | } |
| 240 | |
| 241 | for (int kk = 0; kk < kVectorSize; ++kk) { |
| 242 | b32[kk] = B[kk]; |
pbos@webrtc.org | 1727dc7 | 2013-04-09 16:40:28 +0000 | [diff] [blame] | 243 | b16[kk] = (int16_t)B[kk]; |
andrew@webrtc.org | a7b57da | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 244 | } |
| 245 | WebRtcSpl_VectorBitShiftW32ToW16(bTmp16, kVectorSize, b32, 1); |
| 246 | for (int kk = 0; kk < kVectorSize; ++kk) { |
| 247 | EXPECT_EQ((B[kk]>>1), bTmp16[kk]); |
| 248 | } |
| 249 | WebRtcSpl_VectorBitShiftW16(bTmp16, kVectorSize, b16, 1); |
| 250 | for (int kk = 0; kk < kVectorSize; ++kk) { |
| 251 | EXPECT_EQ((B[kk]>>1), bTmp16[kk]); |
| 252 | } |
| 253 | WebRtcSpl_VectorBitShiftW32(bTmp32, kVectorSize, b32, 1); |
| 254 | for (int kk = 0; kk < kVectorSize; ++kk) { |
| 255 | EXPECT_EQ((B[kk]>>1), bTmp32[kk]); |
| 256 | } |
| 257 | |
| 258 | WebRtcSpl_MemCpyReversedOrder(&bTmp16[3], b16, kVectorSize); |
| 259 | for (int kk = 0; kk < kVectorSize; ++kk) { |
| 260 | EXPECT_EQ(b16[3-kk], bTmp16[kk]); |
| 261 | } |
| 262 | } |
| 263 | |
| 264 | TEST_F(SplTest, ExeptionsHandlingMinMaxOperationsTest) { |
| 265 | // Test how the functions handle exceptional cases. |
| 266 | const int kVectorSize = 2; |
| 267 | int16_t vector16[kVectorSize] = {0}; |
| 268 | int32_t vector32[kVectorSize] = {0}; |
| 269 | |
| 270 | EXPECT_EQ(-1, WebRtcSpl_MaxAbsValueW16(vector16, 0)); |
| 271 | EXPECT_EQ(-1, WebRtcSpl_MaxAbsValueW16(NULL, kVectorSize)); |
| 272 | EXPECT_EQ(WEBRTC_SPL_WORD16_MIN, WebRtcSpl_MaxValueW16(vector16, 0)); |
| 273 | EXPECT_EQ(WEBRTC_SPL_WORD16_MIN, WebRtcSpl_MaxValueW16(NULL, kVectorSize)); |
| 274 | EXPECT_EQ(WEBRTC_SPL_WORD16_MAX, WebRtcSpl_MinValueW16(vector16, 0)); |
| 275 | EXPECT_EQ(WEBRTC_SPL_WORD16_MAX, WebRtcSpl_MinValueW16(NULL, kVectorSize)); |
| 276 | EXPECT_EQ(-1, WebRtcSpl_MaxAbsValueW32(vector32, 0)); |
| 277 | EXPECT_EQ(-1, WebRtcSpl_MaxAbsValueW32(NULL, kVectorSize)); |
| 278 | EXPECT_EQ(WEBRTC_SPL_WORD32_MIN, WebRtcSpl_MaxValueW32(vector32, 0)); |
| 279 | EXPECT_EQ(WEBRTC_SPL_WORD32_MIN, WebRtcSpl_MaxValueW32(NULL, kVectorSize)); |
| 280 | EXPECT_EQ(WEBRTC_SPL_WORD32_MAX, WebRtcSpl_MinValueW32(vector32, 0)); |
| 281 | EXPECT_EQ(WEBRTC_SPL_WORD32_MAX, WebRtcSpl_MinValueW32(NULL, kVectorSize)); |
| 282 | EXPECT_EQ(-1, WebRtcSpl_MaxAbsIndexW16(vector16, 0)); |
| 283 | EXPECT_EQ(-1, WebRtcSpl_MaxAbsIndexW16(NULL, kVectorSize)); |
| 284 | EXPECT_EQ(-1, WebRtcSpl_MaxIndexW16(vector16, 0)); |
| 285 | EXPECT_EQ(-1, WebRtcSpl_MaxIndexW16(NULL, kVectorSize)); |
| 286 | EXPECT_EQ(-1, WebRtcSpl_MaxIndexW32(vector32, 0)); |
| 287 | EXPECT_EQ(-1, WebRtcSpl_MaxIndexW32(NULL, kVectorSize)); |
| 288 | EXPECT_EQ(-1, WebRtcSpl_MinIndexW16(vector16, 0)); |
| 289 | EXPECT_EQ(-1, WebRtcSpl_MinIndexW16(NULL, kVectorSize)); |
| 290 | EXPECT_EQ(-1, WebRtcSpl_MinIndexW32(vector32, 0)); |
| 291 | EXPECT_EQ(-1, WebRtcSpl_MinIndexW32(NULL, kVectorSize)); |
| 292 | } |
| 293 | |
| 294 | TEST_F(SplTest, MinMaxOperationsTest) { |
| 295 | const int kVectorSize = 17; |
| 296 | |
| 297 | // Vectors to test the cases where minimum values have to be caught |
| 298 | // outside of the unrolled loops in ARM-Neon. |
| 299 | int16_t vector16[kVectorSize] = {-1, 7485, 0, 3333, |
| 300 | -18283, 0, 12334, -29871, 988, -3333, |
| 301 | 345, -456, 222, 999, 888, 8774, WEBRTC_SPL_WORD16_MIN}; |
| 302 | int32_t vector32[kVectorSize] = {-1, 0, 283211, 3333, |
| 303 | 8712345, 0, -3333, 89345, -374585456, 222, 999, 122345334, |
| 304 | -12389756, -987329871, 888, -2, WEBRTC_SPL_WORD32_MIN}; |
| 305 | |
| 306 | EXPECT_EQ(WEBRTC_SPL_WORD16_MIN, |
| 307 | WebRtcSpl_MinValueW16(vector16, kVectorSize)); |
| 308 | EXPECT_EQ(WEBRTC_SPL_WORD32_MIN, |
| 309 | WebRtcSpl_MinValueW32(vector32, kVectorSize)); |
| 310 | EXPECT_EQ(kVectorSize - 1, WebRtcSpl_MinIndexW16(vector16, kVectorSize)); |
| 311 | EXPECT_EQ(kVectorSize - 1, WebRtcSpl_MinIndexW32(vector32, kVectorSize)); |
| 312 | |
| 313 | // Test the cases where maximum values have to be caught |
| 314 | // outside of the unrolled loops in ARM-Neon. |
| 315 | vector16[kVectorSize - 1] = WEBRTC_SPL_WORD16_MAX; |
| 316 | vector32[kVectorSize - 1] = WEBRTC_SPL_WORD32_MAX; |
| 317 | |
| 318 | EXPECT_EQ(WEBRTC_SPL_WORD16_MAX, |
| 319 | WebRtcSpl_MaxAbsValueW16(vector16, kVectorSize)); |
| 320 | EXPECT_EQ(WEBRTC_SPL_WORD16_MAX, |
| 321 | WebRtcSpl_MaxValueW16(vector16, kVectorSize)); |
| 322 | EXPECT_EQ(WEBRTC_SPL_WORD32_MAX, |
| 323 | WebRtcSpl_MaxAbsValueW32(vector32, kVectorSize)); |
| 324 | EXPECT_EQ(WEBRTC_SPL_WORD32_MAX, |
| 325 | WebRtcSpl_MaxValueW32(vector32, kVectorSize)); |
| 326 | EXPECT_EQ(kVectorSize - 1, WebRtcSpl_MaxAbsIndexW16(vector16, kVectorSize)); |
| 327 | EXPECT_EQ(kVectorSize - 1, WebRtcSpl_MaxIndexW16(vector16, kVectorSize)); |
| 328 | EXPECT_EQ(kVectorSize - 1, WebRtcSpl_MaxIndexW32(vector32, kVectorSize)); |
| 329 | |
| 330 | // Test the cases where multiple maximum and minimum values are present. |
| 331 | vector16[1] = WEBRTC_SPL_WORD16_MAX; |
| 332 | vector16[6] = WEBRTC_SPL_WORD16_MIN; |
| 333 | vector16[11] = WEBRTC_SPL_WORD16_MIN; |
| 334 | vector32[1] = WEBRTC_SPL_WORD32_MAX; |
| 335 | vector32[6] = WEBRTC_SPL_WORD32_MIN; |
| 336 | vector32[11] = WEBRTC_SPL_WORD32_MIN; |
| 337 | |
| 338 | EXPECT_EQ(WEBRTC_SPL_WORD16_MAX, |
| 339 | WebRtcSpl_MaxAbsValueW16(vector16, kVectorSize)); |
| 340 | EXPECT_EQ(WEBRTC_SPL_WORD16_MAX, |
| 341 | WebRtcSpl_MaxValueW16(vector16, kVectorSize)); |
| 342 | EXPECT_EQ(WEBRTC_SPL_WORD16_MIN, |
| 343 | WebRtcSpl_MinValueW16(vector16, kVectorSize)); |
| 344 | EXPECT_EQ(WEBRTC_SPL_WORD32_MAX, |
| 345 | WebRtcSpl_MaxAbsValueW32(vector32, kVectorSize)); |
| 346 | EXPECT_EQ(WEBRTC_SPL_WORD32_MAX, |
| 347 | WebRtcSpl_MaxValueW32(vector32, kVectorSize)); |
| 348 | EXPECT_EQ(WEBRTC_SPL_WORD32_MIN, |
| 349 | WebRtcSpl_MinValueW32(vector32, kVectorSize)); |
| 350 | EXPECT_EQ(6, WebRtcSpl_MaxAbsIndexW16(vector16, kVectorSize)); |
| 351 | EXPECT_EQ(1, WebRtcSpl_MaxIndexW16(vector16, kVectorSize)); |
| 352 | EXPECT_EQ(1, WebRtcSpl_MaxIndexW32(vector32, kVectorSize)); |
| 353 | EXPECT_EQ(6, WebRtcSpl_MinIndexW16(vector16, kVectorSize)); |
| 354 | EXPECT_EQ(6, WebRtcSpl_MinIndexW32(vector32, kVectorSize)); |
| 355 | } |
| 356 | |
| 357 | TEST_F(SplTest, VectorOperationsTest) { |
| 358 | const int kVectorSize = 4; |
| 359 | int B[] = {4, 12, 133, 1100}; |
pbos@webrtc.org | 1727dc7 | 2013-04-09 16:40:28 +0000 | [diff] [blame] | 360 | int16_t a16[kVectorSize]; |
| 361 | int16_t b16[kVectorSize]; |
| 362 | int16_t bTmp16[kVectorSize]; |
andrew@webrtc.org | a7b57da | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 363 | |
| 364 | for (int kk = 0; kk < kVectorSize; ++kk) { |
| 365 | a16[kk] = B[kk]; |
| 366 | b16[kk] = B[kk]; |
| 367 | } |
| 368 | |
| 369 | WebRtcSpl_AffineTransformVector(bTmp16, b16, 3, 7, 2, kVectorSize); |
| 370 | for (int kk = 0; kk < kVectorSize; ++kk) { |
| 371 | EXPECT_EQ((B[kk]*3+7)>>2, bTmp16[kk]); |
| 372 | } |
| 373 | WebRtcSpl_ScaleAndAddVectorsWithRound(b16, 3, b16, 2, 2, bTmp16, kVectorSize); |
| 374 | for (int kk = 0; kk < kVectorSize; ++kk) { |
| 375 | EXPECT_EQ((B[kk]*3+B[kk]*2+2)>>2, bTmp16[kk]); |
| 376 | } |
| 377 | |
| 378 | WebRtcSpl_AddAffineVectorToVector(bTmp16, b16, 3, 7, 2, kVectorSize); |
| 379 | for (int kk = 0; kk < kVectorSize; ++kk) { |
| 380 | EXPECT_EQ(((B[kk]*3+B[kk]*2+2)>>2)+((b16[kk]*3+7)>>2), bTmp16[kk]); |
| 381 | } |
| 382 | |
| 383 | WebRtcSpl_ScaleVector(b16, bTmp16, 13, kVectorSize, 2); |
| 384 | for (int kk = 0; kk < kVectorSize; ++kk) { |
| 385 | EXPECT_EQ((b16[kk]*13)>>2, bTmp16[kk]); |
| 386 | } |
| 387 | WebRtcSpl_ScaleVectorWithSat(b16, bTmp16, 13, kVectorSize, 2); |
| 388 | for (int kk = 0; kk < kVectorSize; ++kk) { |
| 389 | EXPECT_EQ((b16[kk]*13)>>2, bTmp16[kk]); |
| 390 | } |
| 391 | WebRtcSpl_ScaleAndAddVectors(a16, 13, 2, b16, 7, 2, bTmp16, kVectorSize); |
| 392 | for (int kk = 0; kk < kVectorSize; ++kk) { |
| 393 | EXPECT_EQ(((a16[kk]*13)>>2)+((b16[kk]*7)>>2), bTmp16[kk]); |
| 394 | } |
| 395 | |
| 396 | WebRtcSpl_AddVectorsAndShift(bTmp16, a16, b16, kVectorSize, 2); |
| 397 | for (int kk = 0; kk < kVectorSize; ++kk) { |
| 398 | EXPECT_EQ(B[kk] >> 1, bTmp16[kk]); |
| 399 | } |
| 400 | WebRtcSpl_ReverseOrderMultArrayElements(bTmp16, a16, &b16[3], kVectorSize, 2); |
| 401 | for (int kk = 0; kk < kVectorSize; ++kk) { |
| 402 | EXPECT_EQ((a16[kk]*b16[3-kk])>>2, bTmp16[kk]); |
| 403 | } |
| 404 | WebRtcSpl_ElementwiseVectorMult(bTmp16, a16, b16, kVectorSize, 6); |
| 405 | for (int kk = 0; kk < kVectorSize; ++kk) { |
| 406 | EXPECT_EQ((a16[kk]*b16[kk])>>6, bTmp16[kk]); |
| 407 | } |
| 408 | |
| 409 | WebRtcSpl_SqrtOfOneMinusXSquared(b16, kVectorSize, bTmp16); |
| 410 | for (int kk = 0; kk < kVectorSize - 1; ++kk) { |
| 411 | EXPECT_EQ(32767, bTmp16[kk]); |
| 412 | } |
| 413 | EXPECT_EQ(32749, bTmp16[kVectorSize - 1]); |
| 414 | |
| 415 | EXPECT_EQ(0, WebRtcSpl_GetScalingSquare(b16, kVectorSize, 1)); |
| 416 | } |
| 417 | |
| 418 | TEST_F(SplTest, EstimatorsTest) { |
| 419 | const int kVectorSize = 4; |
| 420 | int B[] = {4, 12, 133, 1100}; |
pbos@webrtc.org | 1727dc7 | 2013-04-09 16:40:28 +0000 | [diff] [blame] | 421 | int16_t b16[kVectorSize]; |
| 422 | int32_t b32[kVectorSize]; |
| 423 | int16_t bTmp16[kVectorSize]; |
andrew@webrtc.org | a7b57da | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 424 | |
| 425 | for (int kk = 0; kk < kVectorSize; ++kk) { |
| 426 | b16[kk] = B[kk]; |
| 427 | b32[kk] = B[kk]; |
| 428 | } |
| 429 | |
| 430 | EXPECT_EQ(0, WebRtcSpl_LevinsonDurbin(b32, b16, bTmp16, 2)); |
| 431 | } |
| 432 | |
| 433 | TEST_F(SplTest, FilterTest) { |
| 434 | const int kVectorSize = 4; |
| 435 | const int kFilterOrder = 3; |
pbos@webrtc.org | 1727dc7 | 2013-04-09 16:40:28 +0000 | [diff] [blame] | 436 | int16_t A[] = {1, 2, 33, 100}; |
| 437 | int16_t A5[] = {1, 2, 33, 100, -5}; |
| 438 | int16_t B[] = {4, 12, 133, 110}; |
| 439 | int16_t data_in[kVectorSize]; |
| 440 | int16_t data_out[kVectorSize]; |
| 441 | int16_t bTmp16Low[kVectorSize]; |
| 442 | int16_t bState[kVectorSize]; |
| 443 | int16_t bStateLow[kVectorSize]; |
andrew@webrtc.org | a7b57da | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 444 | |
| 445 | WebRtcSpl_ZerosArrayW16(bState, kVectorSize); |
| 446 | WebRtcSpl_ZerosArrayW16(bStateLow, kVectorSize); |
| 447 | |
| 448 | for (int kk = 0; kk < kVectorSize; ++kk) { |
| 449 | data_in[kk] = A[kk]; |
| 450 | data_out[kk] = 0; |
| 451 | } |
| 452 | |
| 453 | // MA filters. |
| 454 | // Note that the input data has |kFilterOrder| states before the actual |
| 455 | // data (one sample). |
| 456 | WebRtcSpl_FilterMAFastQ12(&data_in[kFilterOrder], data_out, B, |
| 457 | kFilterOrder + 1, 1); |
| 458 | EXPECT_EQ(0, data_out[0]); |
| 459 | // AR filters. |
| 460 | // Note that the output data has |kFilterOrder| states before the actual |
| 461 | // data (one sample). |
| 462 | WebRtcSpl_FilterARFastQ12(data_in, &data_out[kFilterOrder], A, |
| 463 | kFilterOrder + 1, 1); |
| 464 | EXPECT_EQ(0, data_out[kFilterOrder]); |
| 465 | |
| 466 | EXPECT_EQ(kVectorSize, WebRtcSpl_FilterAR(A5, |
| 467 | 5, |
| 468 | data_in, |
| 469 | kVectorSize, |
| 470 | bState, |
| 471 | kVectorSize, |
| 472 | bStateLow, |
| 473 | kVectorSize, |
| 474 | data_out, |
| 475 | bTmp16Low, |
| 476 | kVectorSize)); |
| 477 | } |
| 478 | |
| 479 | TEST_F(SplTest, RandTest) { |
| 480 | const int kVectorSize = 4; |
pbos@webrtc.org | 1727dc7 | 2013-04-09 16:40:28 +0000 | [diff] [blame] | 481 | int16_t BU[] = {3653, 12446, 8525, 30691}; |
| 482 | int16_t b16[kVectorSize]; |
| 483 | uint32_t bSeed = 100000; |
andrew@webrtc.org | a7b57da | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 484 | |
bjornv@webrtc.org | 9d1179d | 2014-05-16 06:38:47 +0000 | [diff] [blame] | 485 | EXPECT_EQ(7086, WebRtcSpl_RandU(&bSeed)); |
andrew@webrtc.org | a7b57da | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 486 | EXPECT_EQ(31565, WebRtcSpl_RandU(&bSeed)); |
| 487 | EXPECT_EQ(-9786, WebRtcSpl_RandN(&bSeed)); |
| 488 | EXPECT_EQ(kVectorSize, WebRtcSpl_RandUArray(b16, kVectorSize, &bSeed)); |
| 489 | for (int kk = 0; kk < kVectorSize; ++kk) { |
| 490 | EXPECT_EQ(BU[kk], b16[kk]); |
| 491 | } |
| 492 | } |
| 493 | |
| 494 | TEST_F(SplTest, DotProductWithScaleTest) { |
| 495 | EXPECT_EQ(605362796, WebRtcSpl_DotProductWithScale(vector16, |
| 496 | vector16, kVector16Size, 2)); |
| 497 | } |
| 498 | |
| 499 | TEST_F(SplTest, CrossCorrelationTest) { |
| 500 | // Note the function arguments relation specificed by API. |
| 501 | const int kCrossCorrelationDimension = 3; |
| 502 | const int kShift = 2; |
| 503 | const int kStep = 1; |
| 504 | const int kSeqDimension = 6; |
| 505 | |
| 506 | const int16_t kVector16[kVector16Size] = {1, 4323, 1963, |
| 507 | WEBRTC_SPL_WORD16_MAX, WEBRTC_SPL_WORD16_MIN + 5, -3333, -876, 8483, 142}; |
| 508 | int32_t vector32[kCrossCorrelationDimension] = {0}; |
| 509 | |
| 510 | WebRtcSpl_CrossCorrelation(vector32, vector16, kVector16, kSeqDimension, |
| 511 | kCrossCorrelationDimension, kShift, kStep); |
| 512 | |
| 513 | // WebRtcSpl_CrossCorrelationC() and WebRtcSpl_CrossCorrelationNeon() |
| 514 | // are not bit-exact. |
| 515 | const int32_t kExpected[kCrossCorrelationDimension] = |
| 516 | {-266947903, -15579555, -171282001}; |
andrew@webrtc.org | fccf64c | 2013-09-18 17:40:46 +0000 | [diff] [blame] | 517 | const int32_t* expected = kExpected; |
| 518 | #if !defined(MIPS32_LE) |
andrew@webrtc.org | a7b57da | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 519 | const int32_t kExpectedNeon[kCrossCorrelationDimension] = |
| 520 | {-266947901, -15579553, -171281999}; |
andrew@webrtc.org | a7b57da | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 521 | if (WebRtcSpl_CrossCorrelation != WebRtcSpl_CrossCorrelationC) { |
| 522 | expected = kExpectedNeon; |
| 523 | } |
andrew@webrtc.org | fccf64c | 2013-09-18 17:40:46 +0000 | [diff] [blame] | 524 | #endif |
andrew@webrtc.org | a7b57da | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 525 | for (int i = 0; i < kCrossCorrelationDimension; ++i) { |
| 526 | EXPECT_EQ(expected[i], vector32[i]); |
| 527 | } |
| 528 | } |
| 529 | |
| 530 | TEST_F(SplTest, AutoCorrelationTest) { |
| 531 | int scale = 0; |
| 532 | int32_t vector32[kVector16Size]; |
| 533 | const int32_t expected[kVector16Size] = {302681398, 14223410, -121705063, |
| 534 | -85221647, -17104971, 61806945, 6644603, -669329, 43}; |
| 535 | |
| 536 | EXPECT_EQ(-1, WebRtcSpl_AutoCorrelation(vector16, |
| 537 | kVector16Size, kVector16Size + 1, vector32, &scale)); |
| 538 | EXPECT_EQ(kVector16Size, WebRtcSpl_AutoCorrelation(vector16, |
| 539 | kVector16Size, kVector16Size - 1, vector32, &scale)); |
| 540 | EXPECT_EQ(3, scale); |
| 541 | for (int i = 0; i < kVector16Size; ++i) { |
| 542 | EXPECT_EQ(expected[i], vector32[i]); |
| 543 | } |
| 544 | } |
| 545 | |
| 546 | TEST_F(SplTest, SignalProcessingTest) { |
| 547 | const int kVectorSize = 4; |
| 548 | int A[] = {1, 2, 33, 100}; |
pbos@webrtc.org | 1727dc7 | 2013-04-09 16:40:28 +0000 | [diff] [blame] | 549 | const int16_t kHanning[4] = { 2399, 8192, 13985, 16384 }; |
| 550 | int16_t b16[kVectorSize]; |
andrew@webrtc.org | a7b57da | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 551 | |
pbos@webrtc.org | 1727dc7 | 2013-04-09 16:40:28 +0000 | [diff] [blame] | 552 | int16_t bTmp16[kVectorSize]; |
andrew@webrtc.org | a7b57da | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 553 | |
| 554 | int bScale = 0; |
| 555 | |
| 556 | for (int kk = 0; kk < kVectorSize; ++kk) { |
| 557 | b16[kk] = A[kk]; |
| 558 | } |
| 559 | |
| 560 | // TODO(bjornv): Activate the Reflection Coefficient tests when refactoring. |
| 561 | // WebRtcSpl_ReflCoefToLpc(b16, kVectorSize, bTmp16); |
| 562 | //// for (int kk = 0; kk < kVectorSize; ++kk) { |
| 563 | //// EXPECT_EQ(aTmp16[kk], bTmp16[kk]); |
| 564 | //// } |
| 565 | // WebRtcSpl_LpcToReflCoef(bTmp16, kVectorSize, b16); |
| 566 | //// for (int kk = 0; kk < kVectorSize; ++kk) { |
| 567 | //// EXPECT_EQ(a16[kk], b16[kk]); |
| 568 | //// } |
| 569 | // WebRtcSpl_AutoCorrToReflCoef(b32, kVectorSize, bTmp16); |
| 570 | //// for (int kk = 0; kk < kVectorSize; ++kk) { |
| 571 | //// EXPECT_EQ(aTmp16[kk], bTmp16[kk]); |
| 572 | //// } |
| 573 | |
| 574 | WebRtcSpl_GetHanningWindow(bTmp16, kVectorSize); |
| 575 | for (int kk = 0; kk < kVectorSize; ++kk) { |
| 576 | EXPECT_EQ(kHanning[kk], bTmp16[kk]); |
| 577 | } |
| 578 | |
| 579 | for (int kk = 0; kk < kVectorSize; ++kk) { |
| 580 | b16[kk] = A[kk]; |
| 581 | } |
| 582 | EXPECT_EQ(11094 , WebRtcSpl_Energy(b16, kVectorSize, &bScale)); |
| 583 | EXPECT_EQ(0, bScale); |
| 584 | } |
| 585 | |
| 586 | TEST_F(SplTest, FFTTest) { |
pbos@webrtc.org | 1727dc7 | 2013-04-09 16:40:28 +0000 | [diff] [blame] | 587 | int16_t B[] = {1, 2, 33, 100, |
andrew@webrtc.org | a7b57da | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 588 | 2, 3, 34, 101, |
| 589 | 3, 4, 35, 102, |
| 590 | 4, 5, 36, 103}; |
| 591 | |
| 592 | EXPECT_EQ(0, WebRtcSpl_ComplexFFT(B, 3, 1)); |
| 593 | // for (int kk = 0; kk < 16; ++kk) { |
| 594 | // EXPECT_EQ(A[kk], B[kk]); |
| 595 | // } |
| 596 | EXPECT_EQ(0, WebRtcSpl_ComplexIFFT(B, 3, 1)); |
| 597 | // for (int kk = 0; kk < 16; ++kk) { |
| 598 | // EXPECT_EQ(A[kk], B[kk]); |
| 599 | // } |
| 600 | WebRtcSpl_ComplexBitReverse(B, 3); |
| 601 | for (int kk = 0; kk < 16; ++kk) { |
| 602 | //EXPECT_EQ(A[kk], B[kk]); |
| 603 | } |
| 604 | } |
tina.legrand@webrtc.org | 82e863b | 2012-11-15 08:34:38 +0000 | [diff] [blame] | 605 | |
| 606 | TEST_F(SplTest, Resample48WithSaturationTest) { |
| 607 | // The test resamples 3*kBlockSize number of samples to 2*kBlockSize number |
| 608 | // of samples. |
| 609 | const int kBlockSize = 16; |
| 610 | |
| 611 | // Saturated input vector of 48 samples. |
| 612 | const int32_t kVectorSaturated[3 * kBlockSize + 7] = { |
| 613 | -32768, -32768, -32768, -32768, -32768, -32768, -32768, -32768, |
| 614 | -32768, -32768, -32768, -32768, -32768, -32768, -32768, -32768, |
| 615 | -32768, -32768, -32768, -32768, -32768, -32768, -32768, -32768, |
| 616 | 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, |
| 617 | 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, |
| 618 | 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, |
| 619 | 32767, 32767, 32767, 32767, 32767, 32767, 32767 |
| 620 | }; |
| 621 | |
| 622 | // All values in |out_vector| should be |kRefValue32kHz|. |
| 623 | const int32_t kRefValue32kHz1 = -1077493760; |
| 624 | const int32_t kRefValue32kHz2 = 1077493645; |
| 625 | |
| 626 | // After bit shift with saturation, |out_vector_w16| is saturated. |
| 627 | |
| 628 | const int16_t kRefValue16kHz1 = -32768; |
| 629 | const int16_t kRefValue16kHz2 = 32767; |
| 630 | // Vector for storing output. |
| 631 | int32_t out_vector[2 * kBlockSize]; |
| 632 | int16_t out_vector_w16[2 * kBlockSize]; |
| 633 | |
| 634 | WebRtcSpl_Resample48khzTo32khz(kVectorSaturated, out_vector, kBlockSize); |
| 635 | WebRtcSpl_VectorBitShiftW32ToW16(out_vector_w16, 2 * kBlockSize, out_vector, |
| 636 | 15); |
| 637 | |
| 638 | // Comparing output values against references. The values at position |
| 639 | // 12-15 are skipped to account for the filter lag. |
| 640 | for (int i = 0; i < 12; ++i) { |
| 641 | EXPECT_EQ(kRefValue32kHz1, out_vector[i]); |
| 642 | EXPECT_EQ(kRefValue16kHz1, out_vector_w16[i]); |
| 643 | } |
| 644 | for (int i = 16; i < 2 * kBlockSize; ++i) { |
| 645 | EXPECT_EQ(kRefValue32kHz2, out_vector[i]); |
| 646 | EXPECT_EQ(kRefValue16kHz2, out_vector_w16[i]); |
| 647 | } |
| 648 | } |