tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

resample_by_2.c (6080B)


      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 by two functions.
     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 
     19 #ifdef WEBRTC_ARCH_ARM_V7
     20 
     21 // allpass filter coefficients.
     22 static const uint32_t kResampleAllpass1[3] = {3284, 24441, 49528 << 15};
     23 static const uint32_t kResampleAllpass2[3] = {12199, 37471 << 15, 60255 << 15};
     24 
     25 // Multiply two 32-bit values and accumulate to another input value.
     26 // Return: state + ((diff * tbl_value) >> 16)
     27 
     28 static __inline int32_t MUL_ACCUM_1(int32_t tbl_value,
     29                                    int32_t diff,
     30                                    int32_t state) {
     31  int32_t result;
     32  __asm __volatile("smlawb %0, %1, %2, %3"
     33                   : "=r"(result)
     34                   : "r"(diff), "r"(tbl_value), "r"(state));
     35  return result;
     36 }
     37 
     38 // Multiply two 32-bit values and accumulate to another input value.
     39 // Return: Return: state + (((diff << 1) * tbl_value) >> 32)
     40 //
     41 // The reason to introduce this function is that, in case we can't use smlawb
     42 // instruction (in MUL_ACCUM_1) due to input value range, we can still use
     43 // smmla to save some cycles.
     44 
     45 static __inline int32_t MUL_ACCUM_2(int32_t tbl_value,
     46                                    int32_t diff,
     47                                    int32_t state) {
     48  int32_t result;
     49  __asm __volatile("smmla %0, %1, %2, %3"
     50                   : "=r"(result)
     51                   : "r"(diff << 1), "r"(tbl_value), "r"(state));
     52  return result;
     53 }
     54 
     55 #else
     56 
     57 // allpass filter coefficients.
     58 static const uint16_t kResampleAllpass1[3] = {3284, 24441, 49528};
     59 static const uint16_t kResampleAllpass2[3] = {12199, 37471, 60255};
     60 
     61 // Multiply a 32-bit value with a 16-bit value and accumulate to another input:
     62 #define MUL_ACCUM_1(a, b, c) WEBRTC_SPL_SCALEDIFF32(a, b, c)
     63 #define MUL_ACCUM_2(a, b, c) WEBRTC_SPL_SCALEDIFF32(a, b, c)
     64 
     65 #endif  // WEBRTC_ARCH_ARM_V7
     66 
     67 // decimator
     68 #if !defined(MIPS32_LE)
     69 void WebRtcSpl_DownsampleBy2(const int16_t* in,
     70                             size_t len,
     71                             int16_t* out,
     72                             int32_t* filtState) {
     73  int32_t tmp1, tmp2, diff, in32, out32;
     74  size_t i;
     75 
     76  register int32_t state0 = filtState[0];
     77  register int32_t state1 = filtState[1];
     78  register int32_t state2 = filtState[2];
     79  register int32_t state3 = filtState[3];
     80  register int32_t state4 = filtState[4];
     81  register int32_t state5 = filtState[5];
     82  register int32_t state6 = filtState[6];
     83  register int32_t state7 = filtState[7];
     84 
     85  for (i = (len >> 1); i > 0; i--) {
     86    // lower allpass filter
     87    in32 = (int32_t)(*in++) * (1 << 10);
     88    diff = in32 - state1;
     89    tmp1 = MUL_ACCUM_1(kResampleAllpass2[0], diff, state0);
     90    state0 = in32;
     91    diff = tmp1 - state2;
     92    tmp2 = MUL_ACCUM_2(kResampleAllpass2[1], diff, state1);
     93    state1 = tmp1;
     94    diff = tmp2 - state3;
     95    state3 = MUL_ACCUM_2(kResampleAllpass2[2], diff, state2);
     96    state2 = tmp2;
     97 
     98    // upper allpass filter
     99    in32 = (int32_t)(*in++) * (1 << 10);
    100    diff = in32 - state5;
    101    tmp1 = MUL_ACCUM_1(kResampleAllpass1[0], diff, state4);
    102    state4 = in32;
    103    diff = tmp1 - state6;
    104    tmp2 = MUL_ACCUM_1(kResampleAllpass1[1], diff, state5);
    105    state5 = tmp1;
    106    diff = tmp2 - state7;
    107    state7 = MUL_ACCUM_2(kResampleAllpass1[2], diff, state6);
    108    state6 = tmp2;
    109 
    110    // add two allpass outputs, divide by two and round
    111    out32 = (state3 + state7 + 1024) >> 11;
    112 
    113    // limit amplitude to prevent wrap-around, and write to output array
    114    *out++ = WebRtcSpl_SatW32ToW16(out32);
    115  }
    116 
    117  filtState[0] = state0;
    118  filtState[1] = state1;
    119  filtState[2] = state2;
    120  filtState[3] = state3;
    121  filtState[4] = state4;
    122  filtState[5] = state5;
    123  filtState[6] = state6;
    124  filtState[7] = state7;
    125 }
    126 #endif  // #if defined(MIPS32_LE)
    127 
    128 void WebRtcSpl_UpsampleBy2(const int16_t* in,
    129                           size_t len,
    130                           int16_t* out,
    131                           int32_t* filtState) {
    132  int32_t tmp1, tmp2, diff, in32, out32;
    133  size_t i;
    134 
    135  register int32_t state0 = filtState[0];
    136  register int32_t state1 = filtState[1];
    137  register int32_t state2 = filtState[2];
    138  register int32_t state3 = filtState[3];
    139  register int32_t state4 = filtState[4];
    140  register int32_t state5 = filtState[5];
    141  register int32_t state6 = filtState[6];
    142  register int32_t state7 = filtState[7];
    143 
    144  for (i = len; i > 0; i--) {
    145    // lower allpass filter
    146    in32 = (int32_t)(*in++) * (1 << 10);
    147    diff = in32 - state1;
    148    tmp1 = MUL_ACCUM_1(kResampleAllpass1[0], diff, state0);
    149    state0 = in32;
    150    diff = tmp1 - state2;
    151    tmp2 = MUL_ACCUM_1(kResampleAllpass1[1], diff, state1);
    152    state1 = tmp1;
    153    diff = tmp2 - state3;
    154    state3 = MUL_ACCUM_2(kResampleAllpass1[2], diff, state2);
    155    state2 = tmp2;
    156 
    157    // round; limit amplitude to prevent wrap-around; write to output array
    158    out32 = (state3 + 512) >> 10;
    159    *out++ = WebRtcSpl_SatW32ToW16(out32);
    160 
    161    // upper allpass filter
    162    diff = in32 - state5;
    163    tmp1 = MUL_ACCUM_1(kResampleAllpass2[0], diff, state4);
    164    state4 = in32;
    165    diff = tmp1 - state6;
    166    tmp2 = MUL_ACCUM_2(kResampleAllpass2[1], diff, state5);
    167    state5 = tmp1;
    168    diff = tmp2 - state7;
    169    state7 = MUL_ACCUM_2(kResampleAllpass2[2], diff, state6);
    170    state6 = tmp2;
    171 
    172    // round; limit amplitude to prevent wrap-around; write to output array
    173    out32 = (state7 + 512) >> 10;
    174    *out++ = WebRtcSpl_SatW32ToW16(out32);
    175  }
    176 
    177  filtState[0] = state0;
    178  filtState[1] = state1;
    179  filtState[2] = state2;
    180  filtState[3] = state3;
    181  filtState[4] = state4;
    182  filtState[5] = state5;
    183  filtState[6] = state6;
    184  filtState[7] = state7;
    185 }