resample.c (16692B)
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 11 /* 12 * This file contains the resampling functions for 22 kHz. 13 * The description header can be found in signal_processing_library.h 14 * 15 */ 16 17 #include "common_audio/signal_processing/include/signal_processing_library.h" 18 #include "common_audio/signal_processing/resample_by_2_internal.h" 19 20 // Declaration of internally used functions 21 static void WebRtcSpl_32khzTo22khzIntToShort(const int32_t* In, 22 int16_t* Out, 23 int32_t K); 24 25 void WebRtcSpl_32khzTo22khzIntToInt(const int32_t* In, int32_t* Out, int32_t K); 26 27 // interpolation coefficients 28 static const int16_t kCoefficients32To22[5][9] = { 29 {127, -712, 2359, -6333, 23456, 16775, -3695, 945, -154}, 30 {-39, 230, -830, 2785, 32366, -2324, 760, -218, 38}, 31 {117, -663, 2222, -6133, 26634, 13070, -3174, 831, -137}, 32 {-77, 457, -1677, 5958, 31175, -4136, 1405, -408, 71}, 33 {98, -560, 1900, -5406, 29240, 9423, -2480, 663, -110}}; 34 35 ////////////////////// 36 // 22 kHz -> 16 kHz // 37 ////////////////////// 38 39 // number of subblocks; options: 1, 2, 4, 5, 10 40 #define SUB_BLOCKS_22_16 5 41 42 // 22 -> 16 resampler 43 void WebRtcSpl_Resample22khzTo16khz(const int16_t* in, 44 int16_t* out, 45 WebRtcSpl_State22khzTo16khz* state, 46 int32_t* tmpmem) { 47 int k; 48 49 // process two blocks of 10/SUB_BLOCKS_22_16 ms (to reduce temp buffer size) 50 for (k = 0; k < SUB_BLOCKS_22_16; k++) { 51 ///// 22 --> 44 ///// 52 // int16_t in[220/SUB_BLOCKS_22_16] 53 // int32_t out[440/SUB_BLOCKS_22_16] 54 ///// 55 WebRtcSpl_UpBy2ShortToInt(in, 220 / SUB_BLOCKS_22_16, tmpmem + 16, 56 state->S_22_44); 57 58 ///// 44 --> 32 ///// 59 // int32_t in[440/SUB_BLOCKS_22_16] 60 // int32_t out[320/SUB_BLOCKS_22_16] 61 ///// 62 // copy state to and from input array 63 tmpmem[8] = state->S_44_32[0]; 64 tmpmem[9] = state->S_44_32[1]; 65 tmpmem[10] = state->S_44_32[2]; 66 tmpmem[11] = state->S_44_32[3]; 67 tmpmem[12] = state->S_44_32[4]; 68 tmpmem[13] = state->S_44_32[5]; 69 tmpmem[14] = state->S_44_32[6]; 70 tmpmem[15] = state->S_44_32[7]; 71 state->S_44_32[0] = tmpmem[440 / SUB_BLOCKS_22_16 + 8]; 72 state->S_44_32[1] = tmpmem[440 / SUB_BLOCKS_22_16 + 9]; 73 state->S_44_32[2] = tmpmem[440 / SUB_BLOCKS_22_16 + 10]; 74 state->S_44_32[3] = tmpmem[440 / SUB_BLOCKS_22_16 + 11]; 75 state->S_44_32[4] = tmpmem[440 / SUB_BLOCKS_22_16 + 12]; 76 state->S_44_32[5] = tmpmem[440 / SUB_BLOCKS_22_16 + 13]; 77 state->S_44_32[6] = tmpmem[440 / SUB_BLOCKS_22_16 + 14]; 78 state->S_44_32[7] = tmpmem[440 / SUB_BLOCKS_22_16 + 15]; 79 80 WebRtcSpl_Resample44khzTo32khz(tmpmem + 8, tmpmem, 40 / SUB_BLOCKS_22_16); 81 82 ///// 32 --> 16 ///// 83 // int32_t in[320/SUB_BLOCKS_22_16] 84 // int32_t out[160/SUB_BLOCKS_22_16] 85 ///// 86 WebRtcSpl_DownBy2IntToShort(tmpmem, 320 / SUB_BLOCKS_22_16, out, 87 state->S_32_16); 88 89 // move input/output pointers 10/SUB_BLOCKS_22_16 ms seconds ahead 90 in += 220 / SUB_BLOCKS_22_16; 91 out += 160 / SUB_BLOCKS_22_16; 92 } 93 } 94 95 // initialize state of 22 -> 16 resampler 96 void WebRtcSpl_ResetResample22khzTo16khz(WebRtcSpl_State22khzTo16khz* state) { 97 int k; 98 for (k = 0; k < 8; k++) { 99 state->S_22_44[k] = 0; 100 state->S_44_32[k] = 0; 101 state->S_32_16[k] = 0; 102 } 103 } 104 105 ////////////////////// 106 // 16 kHz -> 22 kHz // 107 ////////////////////// 108 109 // number of subblocks; options: 1, 2, 4, 5, 10 110 #define SUB_BLOCKS_16_22 4 111 112 // 16 -> 22 resampler 113 void WebRtcSpl_Resample16khzTo22khz(const int16_t* in, 114 int16_t* out, 115 WebRtcSpl_State16khzTo22khz* state, 116 int32_t* tmpmem) { 117 int k; 118 119 // process two blocks of 10/SUB_BLOCKS_16_22 ms (to reduce temp buffer size) 120 for (k = 0; k < SUB_BLOCKS_16_22; k++) { 121 ///// 16 --> 32 ///// 122 // int16_t in[160/SUB_BLOCKS_16_22] 123 // int32_t out[320/SUB_BLOCKS_16_22] 124 ///// 125 WebRtcSpl_UpBy2ShortToInt(in, 160 / SUB_BLOCKS_16_22, tmpmem + 8, 126 state->S_16_32); 127 128 ///// 32 --> 22 ///// 129 // int32_t in[320/SUB_BLOCKS_16_22] 130 // int32_t out[220/SUB_BLOCKS_16_22] 131 ///// 132 // copy state to and from input array 133 tmpmem[0] = state->S_32_22[0]; 134 tmpmem[1] = state->S_32_22[1]; 135 tmpmem[2] = state->S_32_22[2]; 136 tmpmem[3] = state->S_32_22[3]; 137 tmpmem[4] = state->S_32_22[4]; 138 tmpmem[5] = state->S_32_22[5]; 139 tmpmem[6] = state->S_32_22[6]; 140 tmpmem[7] = state->S_32_22[7]; 141 state->S_32_22[0] = tmpmem[320 / SUB_BLOCKS_16_22]; 142 state->S_32_22[1] = tmpmem[320 / SUB_BLOCKS_16_22 + 1]; 143 state->S_32_22[2] = tmpmem[320 / SUB_BLOCKS_16_22 + 2]; 144 state->S_32_22[3] = tmpmem[320 / SUB_BLOCKS_16_22 + 3]; 145 state->S_32_22[4] = tmpmem[320 / SUB_BLOCKS_16_22 + 4]; 146 state->S_32_22[5] = tmpmem[320 / SUB_BLOCKS_16_22 + 5]; 147 state->S_32_22[6] = tmpmem[320 / SUB_BLOCKS_16_22 + 6]; 148 state->S_32_22[7] = tmpmem[320 / SUB_BLOCKS_16_22 + 7]; 149 150 WebRtcSpl_32khzTo22khzIntToShort(tmpmem, out, 20 / SUB_BLOCKS_16_22); 151 152 // move input/output pointers 10/SUB_BLOCKS_16_22 ms seconds ahead 153 in += 160 / SUB_BLOCKS_16_22; 154 out += 220 / SUB_BLOCKS_16_22; 155 } 156 } 157 158 // initialize state of 16 -> 22 resampler 159 void WebRtcSpl_ResetResample16khzTo22khz(WebRtcSpl_State16khzTo22khz* state) { 160 int k; 161 for (k = 0; k < 8; k++) { 162 state->S_16_32[k] = 0; 163 state->S_32_22[k] = 0; 164 } 165 } 166 167 ////////////////////// 168 // 22 kHz -> 8 kHz // 169 ////////////////////// 170 171 // number of subblocks; options: 1, 2, 5, 10 172 #define SUB_BLOCKS_22_8 2 173 174 // 22 -> 8 resampler 175 void WebRtcSpl_Resample22khzTo8khz(const int16_t* in, 176 int16_t* out, 177 WebRtcSpl_State22khzTo8khz* state, 178 int32_t* tmpmem) { 179 int k; 180 181 // process two blocks of 10/SUB_BLOCKS_22_8 ms (to reduce temp buffer size) 182 for (k = 0; k < SUB_BLOCKS_22_8; k++) { 183 ///// 22 --> 22 lowpass ///// 184 // int16_t in[220/SUB_BLOCKS_22_8] 185 // int32_t out[220/SUB_BLOCKS_22_8] 186 ///// 187 WebRtcSpl_LPBy2ShortToInt(in, 220 / SUB_BLOCKS_22_8, tmpmem + 16, 188 state->S_22_22); 189 190 ///// 22 --> 16 ///// 191 // int32_t in[220/SUB_BLOCKS_22_8] 192 // int32_t out[160/SUB_BLOCKS_22_8] 193 ///// 194 // copy state to and from input array 195 tmpmem[8] = state->S_22_16[0]; 196 tmpmem[9] = state->S_22_16[1]; 197 tmpmem[10] = state->S_22_16[2]; 198 tmpmem[11] = state->S_22_16[3]; 199 tmpmem[12] = state->S_22_16[4]; 200 tmpmem[13] = state->S_22_16[5]; 201 tmpmem[14] = state->S_22_16[6]; 202 tmpmem[15] = state->S_22_16[7]; 203 state->S_22_16[0] = tmpmem[220 / SUB_BLOCKS_22_8 + 8]; 204 state->S_22_16[1] = tmpmem[220 / SUB_BLOCKS_22_8 + 9]; 205 state->S_22_16[2] = tmpmem[220 / SUB_BLOCKS_22_8 + 10]; 206 state->S_22_16[3] = tmpmem[220 / SUB_BLOCKS_22_8 + 11]; 207 state->S_22_16[4] = tmpmem[220 / SUB_BLOCKS_22_8 + 12]; 208 state->S_22_16[5] = tmpmem[220 / SUB_BLOCKS_22_8 + 13]; 209 state->S_22_16[6] = tmpmem[220 / SUB_BLOCKS_22_8 + 14]; 210 state->S_22_16[7] = tmpmem[220 / SUB_BLOCKS_22_8 + 15]; 211 212 WebRtcSpl_Resample44khzTo32khz(tmpmem + 8, tmpmem, 20 / SUB_BLOCKS_22_8); 213 214 ///// 16 --> 8 ///// 215 // int32_t in[160/SUB_BLOCKS_22_8] 216 // int32_t out[80/SUB_BLOCKS_22_8] 217 ///// 218 WebRtcSpl_DownBy2IntToShort(tmpmem, 160 / SUB_BLOCKS_22_8, out, 219 state->S_16_8); 220 221 // move input/output pointers 10/SUB_BLOCKS_22_8 ms seconds ahead 222 in += 220 / SUB_BLOCKS_22_8; 223 out += 80 / SUB_BLOCKS_22_8; 224 } 225 } 226 227 // initialize state of 22 -> 8 resampler 228 void WebRtcSpl_ResetResample22khzTo8khz(WebRtcSpl_State22khzTo8khz* state) { 229 int k; 230 for (k = 0; k < 8; k++) { 231 state->S_22_22[k] = 0; 232 state->S_22_22[k + 8] = 0; 233 state->S_22_16[k] = 0; 234 state->S_16_8[k] = 0; 235 } 236 } 237 238 ////////////////////// 239 // 8 kHz -> 22 kHz // 240 ////////////////////// 241 242 // number of subblocks; options: 1, 2, 5, 10 243 #define SUB_BLOCKS_8_22 2 244 245 // 8 -> 22 resampler 246 void WebRtcSpl_Resample8khzTo22khz(const int16_t* in, 247 int16_t* out, 248 WebRtcSpl_State8khzTo22khz* state, 249 int32_t* tmpmem) { 250 int k; 251 252 // process two blocks of 10/SUB_BLOCKS_8_22 ms (to reduce temp buffer size) 253 for (k = 0; k < SUB_BLOCKS_8_22; k++) { 254 ///// 8 --> 16 ///// 255 // int16_t in[80/SUB_BLOCKS_8_22] 256 // int32_t out[160/SUB_BLOCKS_8_22] 257 ///// 258 WebRtcSpl_UpBy2ShortToInt(in, 80 / SUB_BLOCKS_8_22, tmpmem + 18, 259 state->S_8_16); 260 261 ///// 16 --> 11 ///// 262 // int32_t in[160/SUB_BLOCKS_8_22] 263 // int32_t out[110/SUB_BLOCKS_8_22] 264 ///// 265 // copy state to and from input array 266 tmpmem[10] = state->S_16_11[0]; 267 tmpmem[11] = state->S_16_11[1]; 268 tmpmem[12] = state->S_16_11[2]; 269 tmpmem[13] = state->S_16_11[3]; 270 tmpmem[14] = state->S_16_11[4]; 271 tmpmem[15] = state->S_16_11[5]; 272 tmpmem[16] = state->S_16_11[6]; 273 tmpmem[17] = state->S_16_11[7]; 274 state->S_16_11[0] = tmpmem[160 / SUB_BLOCKS_8_22 + 10]; 275 state->S_16_11[1] = tmpmem[160 / SUB_BLOCKS_8_22 + 11]; 276 state->S_16_11[2] = tmpmem[160 / SUB_BLOCKS_8_22 + 12]; 277 state->S_16_11[3] = tmpmem[160 / SUB_BLOCKS_8_22 + 13]; 278 state->S_16_11[4] = tmpmem[160 / SUB_BLOCKS_8_22 + 14]; 279 state->S_16_11[5] = tmpmem[160 / SUB_BLOCKS_8_22 + 15]; 280 state->S_16_11[6] = tmpmem[160 / SUB_BLOCKS_8_22 + 16]; 281 state->S_16_11[7] = tmpmem[160 / SUB_BLOCKS_8_22 + 17]; 282 283 WebRtcSpl_32khzTo22khzIntToInt(tmpmem + 10, tmpmem, 10 / SUB_BLOCKS_8_22); 284 285 ///// 11 --> 22 ///// 286 // int32_t in[110/SUB_BLOCKS_8_22] 287 // int16_t out[220/SUB_BLOCKS_8_22] 288 ///// 289 WebRtcSpl_UpBy2IntToShort(tmpmem, 110 / SUB_BLOCKS_8_22, out, 290 state->S_11_22); 291 292 // move input/output pointers 10/SUB_BLOCKS_8_22 ms seconds ahead 293 in += 80 / SUB_BLOCKS_8_22; 294 out += 220 / SUB_BLOCKS_8_22; 295 } 296 } 297 298 // initialize state of 8 -> 22 resampler 299 void WebRtcSpl_ResetResample8khzTo22khz(WebRtcSpl_State8khzTo22khz* state) { 300 int k; 301 for (k = 0; k < 8; k++) { 302 state->S_8_16[k] = 0; 303 state->S_16_11[k] = 0; 304 state->S_11_22[k] = 0; 305 } 306 } 307 308 // compute two inner-products and store them to output array 309 static void WebRtcSpl_DotProdIntToInt(const int32_t* in1, 310 const int32_t* in2, 311 const int16_t* coef_ptr, 312 int32_t* out1, 313 int32_t* out2) { 314 int32_t tmp1 = 16384; 315 int32_t tmp2 = 16384; 316 int16_t coef; 317 318 coef = coef_ptr[0]; 319 tmp1 += coef * in1[0]; 320 tmp2 += coef * in2[-0]; 321 322 coef = coef_ptr[1]; 323 tmp1 += coef * in1[1]; 324 tmp2 += coef * in2[-1]; 325 326 coef = coef_ptr[2]; 327 tmp1 += coef * in1[2]; 328 tmp2 += coef * in2[-2]; 329 330 coef = coef_ptr[3]; 331 tmp1 += coef * in1[3]; 332 tmp2 += coef * in2[-3]; 333 334 coef = coef_ptr[4]; 335 tmp1 += coef * in1[4]; 336 tmp2 += coef * in2[-4]; 337 338 coef = coef_ptr[5]; 339 tmp1 += coef * in1[5]; 340 tmp2 += coef * in2[-5]; 341 342 coef = coef_ptr[6]; 343 tmp1 += coef * in1[6]; 344 tmp2 += coef * in2[-6]; 345 346 coef = coef_ptr[7]; 347 tmp1 += coef * in1[7]; 348 tmp2 += coef * in2[-7]; 349 350 coef = coef_ptr[8]; 351 *out1 = tmp1 + coef * in1[8]; 352 *out2 = tmp2 + coef * in2[-8]; 353 } 354 355 // compute two inner-products and store them to output array 356 static void WebRtcSpl_DotProdIntToShort(const int32_t* in1, 357 const int32_t* in2, 358 const int16_t* coef_ptr, 359 int16_t* out1, 360 int16_t* out2) { 361 int32_t tmp1 = 16384; 362 int32_t tmp2 = 16384; 363 int16_t coef; 364 365 coef = coef_ptr[0]; 366 tmp1 += coef * in1[0]; 367 tmp2 += coef * in2[-0]; 368 369 coef = coef_ptr[1]; 370 tmp1 += coef * in1[1]; 371 tmp2 += coef * in2[-1]; 372 373 coef = coef_ptr[2]; 374 tmp1 += coef * in1[2]; 375 tmp2 += coef * in2[-2]; 376 377 coef = coef_ptr[3]; 378 tmp1 += coef * in1[3]; 379 tmp2 += coef * in2[-3]; 380 381 coef = coef_ptr[4]; 382 tmp1 += coef * in1[4]; 383 tmp2 += coef * in2[-4]; 384 385 coef = coef_ptr[5]; 386 tmp1 += coef * in1[5]; 387 tmp2 += coef * in2[-5]; 388 389 coef = coef_ptr[6]; 390 tmp1 += coef * in1[6]; 391 tmp2 += coef * in2[-6]; 392 393 coef = coef_ptr[7]; 394 tmp1 += coef * in1[7]; 395 tmp2 += coef * in2[-7]; 396 397 coef = coef_ptr[8]; 398 tmp1 += coef * in1[8]; 399 tmp2 += coef * in2[-8]; 400 401 // scale down, round and saturate 402 tmp1 >>= 15; 403 if (tmp1 > (int32_t)0x00007FFF) 404 tmp1 = 0x00007FFF; 405 if (tmp1 < (int32_t)0xFFFF8000) 406 tmp1 = 0xFFFF8000; 407 tmp2 >>= 15; 408 if (tmp2 > (int32_t)0x00007FFF) 409 tmp2 = 0x00007FFF; 410 if (tmp2 < (int32_t)0xFFFF8000) 411 tmp2 = 0xFFFF8000; 412 *out1 = (int16_t)tmp1; 413 *out2 = (int16_t)tmp2; 414 } 415 416 // Resampling ratio: 11/16 417 // input: int32_t (normalized, not saturated) :: size 16 * K 418 // output: int32_t (shifted 15 positions to the left, + offset 16384) :: size 11 419 // * K 420 // K: Number of blocks 421 422 void WebRtcSpl_32khzTo22khzIntToInt(const int32_t* In, 423 int32_t* Out, 424 int32_t K) { 425 ///////////////////////////////////////////////////////////// 426 // Filter operation: 427 // 428 // Perform resampling (16 input samples -> 11 output samples); 429 // process in sub blocks of size 16 samples. 430 int32_t m; 431 432 for (m = 0; m < K; m++) { 433 // first output sample 434 Out[0] = ((int32_t)In[3] << 15) + (1 << 14); 435 436 // sum and accumulate filter coefficients and input samples 437 WebRtcSpl_DotProdIntToInt(&In[0], &In[22], kCoefficients32To22[0], &Out[1], 438 &Out[10]); 439 440 // sum and accumulate filter coefficients and input samples 441 WebRtcSpl_DotProdIntToInt(&In[2], &In[20], kCoefficients32To22[1], &Out[2], 442 &Out[9]); 443 444 // sum and accumulate filter coefficients and input samples 445 WebRtcSpl_DotProdIntToInt(&In[3], &In[19], kCoefficients32To22[2], &Out[3], 446 &Out[8]); 447 448 // sum and accumulate filter coefficients and input samples 449 WebRtcSpl_DotProdIntToInt(&In[5], &In[17], kCoefficients32To22[3], &Out[4], 450 &Out[7]); 451 452 // sum and accumulate filter coefficients and input samples 453 WebRtcSpl_DotProdIntToInt(&In[6], &In[16], kCoefficients32To22[4], &Out[5], 454 &Out[6]); 455 456 // update pointers 457 In += 16; 458 Out += 11; 459 } 460 } 461 462 // Resampling ratio: 11/16 463 // input: int32_t (normalized, not saturated) :: size 16 * K 464 // output: int16_t (saturated) :: size 11 * K 465 // K: Number of blocks 466 467 void WebRtcSpl_32khzTo22khzIntToShort(const int32_t* In, 468 int16_t* Out, 469 int32_t K) { 470 ///////////////////////////////////////////////////////////// 471 // Filter operation: 472 // 473 // Perform resampling (16 input samples -> 11 output samples); 474 // process in sub blocks of size 16 samples. 475 int32_t tmp; 476 int32_t m; 477 478 for (m = 0; m < K; m++) { 479 // first output sample 480 tmp = In[3]; 481 if (tmp > (int32_t)0x00007FFF) 482 tmp = 0x00007FFF; 483 if (tmp < (int32_t)0xFFFF8000) 484 tmp = 0xFFFF8000; 485 Out[0] = (int16_t)tmp; 486 487 // sum and accumulate filter coefficients and input samples 488 WebRtcSpl_DotProdIntToShort(&In[0], &In[22], kCoefficients32To22[0], 489 &Out[1], &Out[10]); 490 491 // sum and accumulate filter coefficients and input samples 492 WebRtcSpl_DotProdIntToShort(&In[2], &In[20], kCoefficients32To22[1], 493 &Out[2], &Out[9]); 494 495 // sum and accumulate filter coefficients and input samples 496 WebRtcSpl_DotProdIntToShort(&In[3], &In[19], kCoefficients32To22[2], 497 &Out[3], &Out[8]); 498 499 // sum and accumulate filter coefficients and input samples 500 WebRtcSpl_DotProdIntToShort(&In[5], &In[17], kCoefficients32To22[3], 501 &Out[4], &Out[7]); 502 503 // sum and accumulate filter coefficients and input samples 504 WebRtcSpl_DotProdIntToShort(&In[6], &In[16], kCoefficients32To22[4], 505 &Out[5], &Out[6]); 506 507 // update pointers 508 In += 16; 509 Out += 11; 510 } 511 }