Home | History | Annotate | Download | only in signal_processing
      1 /*
      2  *  Copyright (c) 2013 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 by two functions.
     14  * The description header can be found in signal_processing_library.h
     15  *
     16  */
     17 
     18 #if defined(MIPS32_LE)
     19 
     20 #include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
     21 
     22 // allpass filter coefficients.
     23 static const uint16_t kResampleAllpass1[3] = {3284, 24441, 49528};
     24 static const uint16_t kResampleAllpass2[3] = {12199, 37471, 60255};
     25 
     26 // Multiply a 32-bit value with a 16-bit value and accumulate to another input:
     27 #define MUL_ACCUM_1(a, b, c) WEBRTC_SPL_SCALEDIFF32(a, b, c)
     28 #define MUL_ACCUM_2(a, b, c) WEBRTC_SPL_SCALEDIFF32(a, b, c)
     29 
     30 // decimator
     31 void WebRtcSpl_DownsampleBy2(const int16_t* in,
     32                              int16_t len,
     33                              int16_t* out,
     34                              int32_t* filtState) {
     35   int32_t out32;
     36   int16_t i, len1;
     37 
     38   register int32_t state0 = filtState[0];
     39   register int32_t state1 = filtState[1];
     40   register int32_t state2 = filtState[2];
     41   register int32_t state3 = filtState[3];
     42   register int32_t state4 = filtState[4];
     43   register int32_t state5 = filtState[5];
     44   register int32_t state6 = filtState[6];
     45   register int32_t state7 = filtState[7];
     46 
     47 #if defined(MIPS_DSP_R2_LE)
     48   int32_t k1Res0, k1Res1, k1Res2, k2Res0, k2Res1, k2Res2;
     49 
     50   k1Res0= 3284;
     51   k1Res1= 24441;
     52   k1Res2= 49528;
     53   k2Res0= 12199;
     54   k2Res1= 37471;
     55   k2Res2= 60255;
     56   len1 = (len >> 1);
     57 
     58   const int32_t* inw = (int32_t*)in;
     59   int32_t tmp11, tmp12, tmp21, tmp22;
     60   int32_t in322, in321;
     61   int32_t diff1, diff2;
     62   for (i = len1; i > 0; i--) {
     63     __asm__ volatile (
     64       "lh         %[in321],    0(%[inw])                  \n\t"
     65       "lh         %[in322],    2(%[inw])                  \n\t"
     66 
     67       "sll        %[in321],    %[in321],      10          \n\t"
     68       "sll        %[in322],    %[in322],      10          \n\t"
     69 
     70       "addiu      %[inw],      %[inw],        4           \n\t"
     71 
     72       "subu       %[diff1],    %[in321],      %[state1]   \n\t"
     73       "subu       %[diff2],    %[in322],      %[state5]   \n\t"
     74 
     75       : [in322] "=&r" (in322), [in321] "=&r" (in321),
     76         [diff1] "=&r" (diff1), [diff2] "=r" (diff2), [inw] "+r" (inw)
     77       : [state1] "r" (state1), [state5] "r" (state5)
     78       : "memory"
     79     );
     80 
     81     __asm__ volatile (
     82       "mult       $ac0,       %[diff1],       %[k2Res0]   \n\t"
     83       "mult       $ac1,       %[diff2],       %[k1Res0]   \n\t"
     84 
     85       "extr.w     %[tmp11],   $ac0,           16          \n\t"
     86       "extr.w     %[tmp12],   $ac1,           16          \n\t"
     87 
     88       "addu       %[tmp11],   %[state0],      %[tmp11]    \n\t"
     89       "addu       %[tmp12],   %[state4],      %[tmp12]    \n\t"
     90 
     91       "addiu      %[state0],  %[in321],       0           \n\t"
     92       "addiu      %[state4],  %[in322],       0           \n\t"
     93 
     94       "subu       %[diff1],   %[tmp11],       %[state2]   \n\t"
     95       "subu       %[diff2],   %[tmp12],       %[state6]   \n\t"
     96 
     97       "mult       $ac0,       %[diff1],       %[k2Res1]   \n\t"
     98       "mult       $ac1,       %[diff2],       %[k1Res1]   \n\t"
     99 
    100       "extr.w     %[tmp21],   $ac0,           16          \n\t"
    101       "extr.w     %[tmp22],   $ac1,           16          \n\t"
    102 
    103       "addu       %[tmp21],   %[state1],      %[tmp21]    \n\t"
    104       "addu       %[tmp22],   %[state5],      %[tmp22]    \n\t"
    105 
    106       "addiu      %[state1],  %[tmp11],       0           \n\t"
    107       "addiu      %[state5],  %[tmp12],       0           \n\t"
    108       : [tmp22] "=r" (tmp22), [tmp21] "=&r" (tmp21),
    109         [tmp11] "=&r" (tmp11), [state0] "+r" (state0),
    110         [state1] "+r" (state1),
    111         [state2] "+r" (state2),
    112         [state4] "+r" (state4), [tmp12] "=&r" (tmp12),
    113         [state6] "+r" (state6), [state5] "+r" (state5)
    114       : [k1Res1] "r" (k1Res1), [k2Res1] "r" (k2Res1), [k2Res0] "r" (k2Res0),
    115         [diff2] "r" (diff2), [diff1] "r" (diff1), [in322] "r" (in322),
    116         [in321] "r" (in321), [k1Res0] "r" (k1Res0)
    117       : "hi", "lo", "$ac1hi", "$ac1lo"
    118     );
    119 
    120     // upper allpass filter
    121     __asm__ volatile (
    122       "subu       %[diff1],   %[tmp21],       %[state3]   \n\t"
    123       "subu       %[diff2],   %[tmp22],       %[state7]   \n\t"
    124 
    125       "mult       $ac0,       %[diff1],       %[k2Res2]   \n\t"
    126       "mult       $ac1,       %[diff2],       %[k1Res2]   \n\t"
    127       "extr.w     %[state3],  $ac0,           16          \n\t"
    128       "extr.w     %[state7],  $ac1,           16          \n\t"
    129       "addu       %[state3],  %[state2],      %[state3]   \n\t"
    130       "addu       %[state7],  %[state6],      %[state7]   \n\t"
    131 
    132       "addiu      %[state2],  %[tmp21],       0           \n\t"
    133       "addiu      %[state6],  %[tmp22],       0           \n\t"
    134 
    135       // add two allpass outputs, divide by two and round
    136       "addu       %[out32],   %[state3],      %[state7]   \n\t"
    137       "addiu      %[out32],   %[out32],       1024        \n\t"
    138       "sra        %[out32],   %[out32],       11          \n\t"
    139       : [state3] "+r" (state3), [state6] "+r" (state6),
    140         [state2] "+r" (state2), [diff2] "=&r" (diff2),
    141         [out32] "=r" (out32), [diff1] "=&r" (diff1), [state7] "+r" (state7)
    142       : [tmp22] "r" (tmp22), [tmp21] "r" (tmp21),
    143         [k1Res2] "r" (k1Res2), [k2Res2] "r" (k2Res2)
    144       : "hi", "lo", "$ac1hi", "$ac1lo"
    145     );
    146 
    147     // limit amplitude to prevent wrap-around, and write to output array
    148     *out++ = WebRtcSpl_SatW32ToW16(out32);
    149   }
    150 #else  // #if defined(MIPS_DSP_R2_LE)
    151   int32_t tmp1, tmp2, diff;
    152   int32_t in32;
    153   len1 = (len >> 1)/4;
    154   for (i = len1; i > 0; i--) {
    155     // lower allpass filter
    156     in32 = (int32_t)(*in++) << 10;
    157     diff = in32 - state1;
    158     tmp1 = MUL_ACCUM_1(kResampleAllpass2[0], diff, state0);
    159     state0 = in32;
    160     diff = tmp1 - state2;
    161     tmp2 = MUL_ACCUM_2(kResampleAllpass2[1], diff, state1);
    162     state1 = tmp1;
    163     diff = tmp2 - state3;
    164     state3 = MUL_ACCUM_2(kResampleAllpass2[2], diff, state2);
    165     state2 = tmp2;
    166 
    167     // upper allpass filter
    168     in32 = (int32_t)(*in++) << 10;
    169     diff = in32 - state5;
    170     tmp1 = MUL_ACCUM_1(kResampleAllpass1[0], diff, state4);
    171     state4 = in32;
    172     diff = tmp1 - state6;
    173     tmp2 = MUL_ACCUM_1(kResampleAllpass1[1], diff, state5);
    174     state5 = tmp1;
    175     diff = tmp2 - state7;
    176     state7 = MUL_ACCUM_2(kResampleAllpass1[2], diff, state6);
    177     state6 = tmp2;
    178 
    179     // add two allpass outputs, divide by two and round
    180     out32 = (state3 + state7 + 1024) >> 11;
    181 
    182     // limit amplitude to prevent wrap-around, and write to output array
    183     *out++ = WebRtcSpl_SatW32ToW16(out32);
    184     // lower allpass filter
    185     in32 = (int32_t)(*in++) << 10;
    186     diff = in32 - state1;
    187     tmp1 = MUL_ACCUM_1(kResampleAllpass2[0], diff, state0);
    188     state0 = in32;
    189     diff = tmp1 - state2;
    190     tmp2 = MUL_ACCUM_2(kResampleAllpass2[1], diff, state1);
    191     state1 = tmp1;
    192     diff = tmp2 - state3;
    193     state3 = MUL_ACCUM_2(kResampleAllpass2[2], diff, state2);
    194     state2 = tmp2;
    195 
    196     // upper allpass filter
    197     in32 = (int32_t)(*in++) << 10;
    198     diff = in32 - state5;
    199     tmp1 = MUL_ACCUM_1(kResampleAllpass1[0], diff, state4);
    200     state4 = in32;
    201     diff = tmp1 - state6;
    202     tmp2 = MUL_ACCUM_1(kResampleAllpass1[1], diff, state5);
    203     state5 = tmp1;
    204     diff = tmp2 - state7;
    205     state7 = MUL_ACCUM_2(kResampleAllpass1[2], diff, state6);
    206     state6 = tmp2;
    207 
    208     // add two allpass outputs, divide by two and round
    209     out32 = (state3 + state7 + 1024) >> 11;
    210 
    211     // limit amplitude to prevent wrap-around, and write to output array
    212     *out++ = WebRtcSpl_SatW32ToW16(out32);
    213     // lower allpass filter
    214     in32 = (int32_t)(*in++) << 10;
    215     diff = in32 - state1;
    216     tmp1 = MUL_ACCUM_1(kResampleAllpass2[0], diff, state0);
    217     state0 = in32;
    218     diff = tmp1 - state2;
    219     tmp2 = MUL_ACCUM_2(kResampleAllpass2[1], diff, state1);
    220     state1 = tmp1;
    221     diff = tmp2 - state3;
    222     state3 = MUL_ACCUM_2(kResampleAllpass2[2], diff, state2);
    223     state2 = tmp2;
    224 
    225     // upper allpass filter
    226     in32 = (int32_t)(*in++) << 10;
    227     diff = in32 - state5;
    228     tmp1 = MUL_ACCUM_1(kResampleAllpass1[0], diff, state4);
    229     state4 = in32;
    230     diff = tmp1 - state6;
    231     tmp2 = MUL_ACCUM_1(kResampleAllpass1[1], diff, state5);
    232     state5 = tmp1;
    233     diff = tmp2 - state7;
    234     state7 = MUL_ACCUM_2(kResampleAllpass1[2], diff, state6);
    235     state6 = tmp2;
    236 
    237     // add two allpass outputs, divide by two and round
    238     out32 = (state3 + state7 + 1024) >> 11;
    239 
    240     // limit amplitude to prevent wrap-around, and write to output array
    241     *out++ = WebRtcSpl_SatW32ToW16(out32);
    242     // lower allpass filter
    243     in32 = (int32_t)(*in++) << 10;
    244     diff = in32 - state1;
    245     tmp1 = MUL_ACCUM_1(kResampleAllpass2[0], diff, state0);
    246     state0 = in32;
    247     diff = tmp1 - state2;
    248     tmp2 = MUL_ACCUM_2(kResampleAllpass2[1], diff, state1);
    249     state1 = tmp1;
    250     diff = tmp2 - state3;
    251     state3 = MUL_ACCUM_2(kResampleAllpass2[2], diff, state2);
    252     state2 = tmp2;
    253 
    254     // upper allpass filter
    255     in32 = (int32_t)(*in++) << 10;
    256     diff = in32 - state5;
    257     tmp1 = MUL_ACCUM_1(kResampleAllpass1[0], diff, state4);
    258     state4 = in32;
    259     diff = tmp1 - state6;
    260     tmp2 = MUL_ACCUM_1(kResampleAllpass1[1], diff, state5);
    261     state5 = tmp1;
    262     diff = tmp2 - state7;
    263     state7 = MUL_ACCUM_2(kResampleAllpass1[2], diff, state6);
    264     state6 = tmp2;
    265 
    266     // add two allpass outputs, divide by two and round
    267     out32 = (state3 + state7 + 1024) >> 11;
    268 
    269     // limit amplitude to prevent wrap-around, and write to output array
    270     *out++ = WebRtcSpl_SatW32ToW16(out32);
    271   }
    272 #endif  // #if defined(MIPS_DSP_R2_LE)
    273   __asm__ volatile (
    274     "sw       %[state0],      0(%[filtState])     \n\t"
    275     "sw       %[state1],      4(%[filtState])     \n\t"
    276     "sw       %[state2],      8(%[filtState])     \n\t"
    277     "sw       %[state3],      12(%[filtState])    \n\t"
    278     "sw       %[state4],      16(%[filtState])    \n\t"
    279     "sw       %[state5],      20(%[filtState])    \n\t"
    280     "sw       %[state6],      24(%[filtState])    \n\t"
    281     "sw       %[state7],      28(%[filtState])    \n\t"
    282     :
    283     : [state0] "r" (state0), [state1] "r" (state1), [state2] "r" (state2),
    284       [state3] "r" (state3), [state4] "r" (state4), [state5] "r" (state5),
    285       [state6] "r" (state6), [state7] "r" (state7), [filtState] "r" (filtState)
    286     : "memory"
    287   );
    288 }
    289 
    290 #endif  // #if defined(MIPS32_LE)
    291