Home | History | Annotate | Download | only in source
      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 by two functions.
     14  * The description header can be found in signal_processing_library.h
     15  *
     16  */
     17 
     18 #include "signal_processing_library.h"
     19 
     20 // allpass filter coefficients.
     21 static const WebRtc_UWord16 kResampleAllpass1[3] = {3284, 24441, 49528};
     22 static const WebRtc_UWord16 kResampleAllpass2[3] = {12199, 37471, 60255};
     23 
     24 // decimator
     25 void WebRtcSpl_DownsampleBy2(const WebRtc_Word16* in, const WebRtc_Word16 len,
     26                              WebRtc_Word16* out, WebRtc_Word32* filtState)
     27 {
     28     const WebRtc_Word16 *inptr;
     29     WebRtc_Word16 *outptr;
     30     WebRtc_Word32 *state;
     31     WebRtc_Word32 tmp1, tmp2, diff, in32, out32;
     32     WebRtc_Word16 i;
     33 
     34     // local versions of pointers to input and output arrays
     35     inptr = in; // input array
     36     outptr = out; // output array (of length len/2)
     37     state = filtState; // filter state array; length = 8
     38 
     39     for (i = (len >> 1); i > 0; i--)
     40     {
     41         // lower allpass filter
     42         in32 = (WebRtc_Word32)(*inptr++) << 10;
     43         diff = in32 - state[1];
     44         tmp1 = WEBRTC_SPL_SCALEDIFF32( kResampleAllpass2[0], diff, state[0] );
     45         state[0] = in32;
     46         diff = tmp1 - state[2];
     47         tmp2 = WEBRTC_SPL_SCALEDIFF32( kResampleAllpass2[1], diff, state[1] );
     48         state[1] = tmp1;
     49         diff = tmp2 - state[3];
     50         state[3] = WEBRTC_SPL_SCALEDIFF32( kResampleAllpass2[2], diff, state[2] );
     51         state[2] = tmp2;
     52 
     53         // upper allpass filter
     54         in32 = (WebRtc_Word32)(*inptr++) << 10;
     55         diff = in32 - state[5];
     56         tmp1 = WEBRTC_SPL_SCALEDIFF32( kResampleAllpass1[0], diff, state[4] );
     57         state[4] = in32;
     58         diff = tmp1 - state[6];
     59         tmp2 = WEBRTC_SPL_SCALEDIFF32( kResampleAllpass1[1], diff, state[5] );
     60         state[5] = tmp1;
     61         diff = tmp2 - state[7];
     62         state[7] = WEBRTC_SPL_SCALEDIFF32( kResampleAllpass1[2], diff, state[6] );
     63         state[6] = tmp2;
     64 
     65         // add two allpass outputs, divide by two and round
     66         out32 = (state[3] + state[7] + 1024) >> 11;
     67 
     68         // limit amplitude to prevent wrap-around, and write to output array
     69         if (out32 > 32767)
     70             *outptr++ = 32767;
     71         else if (out32 < -32768)
     72             *outptr++ = -32768;
     73         else
     74             *outptr++ = (WebRtc_Word16)out32;
     75     }
     76 }
     77 
     78 void WebRtcSpl_UpsampleBy2(const WebRtc_Word16* in, WebRtc_Word16 len, WebRtc_Word16* out,
     79                            WebRtc_Word32* filtState)
     80 {
     81     const WebRtc_Word16 *inptr;
     82     WebRtc_Word16 *outptr;
     83     WebRtc_Word32 *state;
     84     WebRtc_Word32 tmp1, tmp2, diff, in32, out32;
     85     WebRtc_Word16 i;
     86 
     87     // local versions of pointers to input and output arrays
     88     inptr = in; // input array
     89     outptr = out; // output array (of length len*2)
     90     state = filtState; // filter state array; length = 8
     91 
     92     for (i = len; i > 0; i--)
     93     {
     94         // lower allpass filter
     95         in32 = (WebRtc_Word32)(*inptr++) << 10;
     96         diff = in32 - state[1];
     97         tmp1 = WEBRTC_SPL_SCALEDIFF32( kResampleAllpass1[0], diff, state[0] );
     98         state[0] = in32;
     99         diff = tmp1 - state[2];
    100         tmp2 = WEBRTC_SPL_SCALEDIFF32( kResampleAllpass1[1], diff, state[1] );
    101         state[1] = tmp1;
    102         diff = tmp2 - state[3];
    103         state[3] = WEBRTC_SPL_SCALEDIFF32( kResampleAllpass1[2], diff, state[2] );
    104         state[2] = tmp2;
    105 
    106         // round; limit amplitude to prevent wrap-around; write to output array
    107         out32 = (state[3] + 512) >> 10;
    108         if (out32 > 32767)
    109             *outptr++ = 32767;
    110         else if (out32 < -32768)
    111             *outptr++ = -32768;
    112         else
    113             *outptr++ = (WebRtc_Word16)out32;
    114 
    115         // upper allpass filter
    116         diff = in32 - state[5];
    117         tmp1 = WEBRTC_SPL_SCALEDIFF32( kResampleAllpass2[0], diff, state[4] );
    118         state[4] = in32;
    119         diff = tmp1 - state[6];
    120         tmp2 = WEBRTC_SPL_SCALEDIFF32( kResampleAllpass2[1], diff, state[5] );
    121         state[5] = tmp1;
    122         diff = tmp2 - state[7];
    123         state[7] = WEBRTC_SPL_SCALEDIFF32( kResampleAllpass2[2], diff, state[6] );
    124         state[6] = tmp2;
    125 
    126         // round; limit amplitude to prevent wrap-around; write to output array
    127         out32 = (state[7] + 512) >> 10;
    128         if (out32 > 32767)
    129             *outptr++ = 32767;
    130         else if (out32 < -32768)
    131             *outptr++ = -32768;
    132         else
    133             *outptr++ = (WebRtc_Word16)out32;
    134     }
    135 }
    136