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