This is from the upstream library commit id 3326535126e435f1ba647885ce43a8f0f3d317eb, corresponding to Chromium 88.0.4290.1.
690 lines
20 KiB
C
690 lines
20 KiB
C
/*
|
|
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license
|
|
* that can be found in the LICENSE file in the root of the source
|
|
* tree. An additional intellectual property rights grant can be found
|
|
* in the file PATENTS. All contributing project authors may
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
*/
|
|
|
|
|
|
/*
|
|
* This header file contains some internal resampling functions.
|
|
*
|
|
*/
|
|
|
|
#include "common_audio/signal_processing/resample_by_2_internal.h"
|
|
#include "rtc_base/sanitizer.h"
|
|
|
|
// allpass filter coefficients.
|
|
static const int16_t kResampleAllpass[2][3] = {
|
|
{821, 6110, 12382},
|
|
{3050, 9368, 15063}
|
|
};
|
|
|
|
//
|
|
// decimator
|
|
// input: int32_t (shifted 15 positions to the left, + offset 16384) OVERWRITTEN!
|
|
// output: int16_t (saturated) (of length len/2)
|
|
// state: filter state array; length = 8
|
|
|
|
void RTC_NO_SANITIZE("signed-integer-overflow") // bugs.webrtc.org/5486
|
|
WebRtcSpl_DownBy2IntToShort(int32_t *in, int32_t len, int16_t *out,
|
|
int32_t *state)
|
|
{
|
|
int32_t tmp0, tmp1, diff;
|
|
int32_t i;
|
|
|
|
len >>= 1;
|
|
|
|
// lower allpass filter (operates on even input samples)
|
|
for (i = 0; i < len; i++)
|
|
{
|
|
tmp0 = in[i << 1];
|
|
diff = tmp0 - state[1];
|
|
// UBSan: -1771017321 - 999586185 cannot be represented in type 'int'
|
|
|
|
// scale down and round
|
|
diff = (diff + (1 << 13)) >> 14;
|
|
tmp1 = state[0] + diff * kResampleAllpass[1][0];
|
|
state[0] = tmp0;
|
|
diff = tmp1 - state[2];
|
|
// scale down and truncate
|
|
diff = diff >> 14;
|
|
if (diff < 0)
|
|
diff += 1;
|
|
tmp0 = state[1] + diff * kResampleAllpass[1][1];
|
|
state[1] = tmp1;
|
|
diff = tmp0 - state[3];
|
|
// scale down and truncate
|
|
diff = diff >> 14;
|
|
if (diff < 0)
|
|
diff += 1;
|
|
state[3] = state[2] + diff * kResampleAllpass[1][2];
|
|
state[2] = tmp0;
|
|
|
|
// divide by two and store temporarily
|
|
in[i << 1] = (state[3] >> 1);
|
|
}
|
|
|
|
in++;
|
|
|
|
// upper allpass filter (operates on odd input samples)
|
|
for (i = 0; i < len; i++)
|
|
{
|
|
tmp0 = in[i << 1];
|
|
diff = tmp0 - state[5];
|
|
// scale down and round
|
|
diff = (diff + (1 << 13)) >> 14;
|
|
tmp1 = state[4] + diff * kResampleAllpass[0][0];
|
|
state[4] = tmp0;
|
|
diff = tmp1 - state[6];
|
|
// scale down and round
|
|
diff = diff >> 14;
|
|
if (diff < 0)
|
|
diff += 1;
|
|
tmp0 = state[5] + diff * kResampleAllpass[0][1];
|
|
state[5] = tmp1;
|
|
diff = tmp0 - state[7];
|
|
// scale down and truncate
|
|
diff = diff >> 14;
|
|
if (diff < 0)
|
|
diff += 1;
|
|
state[7] = state[6] + diff * kResampleAllpass[0][2];
|
|
state[6] = tmp0;
|
|
|
|
// divide by two and store temporarily
|
|
in[i << 1] = (state[7] >> 1);
|
|
}
|
|
|
|
in--;
|
|
|
|
// combine allpass outputs
|
|
for (i = 0; i < len; i += 2)
|
|
{
|
|
// divide by two, add both allpass outputs and round
|
|
tmp0 = (in[i << 1] + in[(i << 1) + 1]) >> 15;
|
|
tmp1 = (in[(i << 1) + 2] + in[(i << 1) + 3]) >> 15;
|
|
if (tmp0 > (int32_t)0x00007FFF)
|
|
tmp0 = 0x00007FFF;
|
|
if (tmp0 < (int32_t)0xFFFF8000)
|
|
tmp0 = 0xFFFF8000;
|
|
out[i] = (int16_t)tmp0;
|
|
if (tmp1 > (int32_t)0x00007FFF)
|
|
tmp1 = 0x00007FFF;
|
|
if (tmp1 < (int32_t)0xFFFF8000)
|
|
tmp1 = 0xFFFF8000;
|
|
out[i + 1] = (int16_t)tmp1;
|
|
}
|
|
}
|
|
|
|
//
|
|
// decimator
|
|
// input: int16_t
|
|
// output: int32_t (shifted 15 positions to the left, + offset 16384) (of length len/2)
|
|
// state: filter state array; length = 8
|
|
|
|
void RTC_NO_SANITIZE("signed-integer-overflow") // bugs.webrtc.org/5486
|
|
WebRtcSpl_DownBy2ShortToInt(const int16_t *in,
|
|
int32_t len,
|
|
int32_t *out,
|
|
int32_t *state)
|
|
{
|
|
int32_t tmp0, tmp1, diff;
|
|
int32_t i;
|
|
|
|
len >>= 1;
|
|
|
|
// lower allpass filter (operates on even input samples)
|
|
for (i = 0; i < len; i++)
|
|
{
|
|
tmp0 = ((int32_t)in[i << 1] << 15) + (1 << 14);
|
|
diff = tmp0 - state[1];
|
|
// scale down and round
|
|
diff = (diff + (1 << 13)) >> 14;
|
|
tmp1 = state[0] + diff * kResampleAllpass[1][0];
|
|
state[0] = tmp0;
|
|
diff = tmp1 - state[2];
|
|
// UBSan: -1379909682 - 834099714 cannot be represented in type 'int'
|
|
|
|
// scale down and truncate
|
|
diff = diff >> 14;
|
|
if (diff < 0)
|
|
diff += 1;
|
|
tmp0 = state[1] + diff * kResampleAllpass[1][1];
|
|
state[1] = tmp1;
|
|
diff = tmp0 - state[3];
|
|
// scale down and truncate
|
|
diff = diff >> 14;
|
|
if (diff < 0)
|
|
diff += 1;
|
|
state[3] = state[2] + diff * kResampleAllpass[1][2];
|
|
state[2] = tmp0;
|
|
|
|
// divide by two and store temporarily
|
|
out[i] = (state[3] >> 1);
|
|
}
|
|
|
|
in++;
|
|
|
|
// upper allpass filter (operates on odd input samples)
|
|
for (i = 0; i < len; i++)
|
|
{
|
|
tmp0 = ((int32_t)in[i << 1] << 15) + (1 << 14);
|
|
diff = tmp0 - state[5];
|
|
// scale down and round
|
|
diff = (diff + (1 << 13)) >> 14;
|
|
tmp1 = state[4] + diff * kResampleAllpass[0][0];
|
|
state[4] = tmp0;
|
|
diff = tmp1 - state[6];
|
|
// scale down and round
|
|
diff = diff >> 14;
|
|
if (diff < 0)
|
|
diff += 1;
|
|
tmp0 = state[5] + diff * kResampleAllpass[0][1];
|
|
state[5] = tmp1;
|
|
diff = tmp0 - state[7];
|
|
// scale down and truncate
|
|
diff = diff >> 14;
|
|
if (diff < 0)
|
|
diff += 1;
|
|
state[7] = state[6] + diff * kResampleAllpass[0][2];
|
|
state[6] = tmp0;
|
|
|
|
// divide by two and store temporarily
|
|
out[i] += (state[7] >> 1);
|
|
}
|
|
|
|
in--;
|
|
}
|
|
|
|
//
|
|
// interpolator
|
|
// input: int16_t
|
|
// output: int32_t (normalized, not saturated) (of length len*2)
|
|
// state: filter state array; length = 8
|
|
void WebRtcSpl_UpBy2ShortToInt(const int16_t *in, int32_t len, int32_t *out,
|
|
int32_t *state)
|
|
{
|
|
int32_t tmp0, tmp1, diff;
|
|
int32_t i;
|
|
|
|
// upper allpass filter (generates odd output samples)
|
|
for (i = 0; i < len; i++)
|
|
{
|
|
tmp0 = ((int32_t)in[i] << 15) + (1 << 14);
|
|
diff = tmp0 - state[5];
|
|
// scale down and round
|
|
diff = (diff + (1 << 13)) >> 14;
|
|
tmp1 = state[4] + diff * kResampleAllpass[0][0];
|
|
state[4] = tmp0;
|
|
diff = tmp1 - state[6];
|
|
// scale down and truncate
|
|
diff = diff >> 14;
|
|
if (diff < 0)
|
|
diff += 1;
|
|
tmp0 = state[5] + diff * kResampleAllpass[0][1];
|
|
state[5] = tmp1;
|
|
diff = tmp0 - state[7];
|
|
// scale down and truncate
|
|
diff = diff >> 14;
|
|
if (diff < 0)
|
|
diff += 1;
|
|
state[7] = state[6] + diff * kResampleAllpass[0][2];
|
|
state[6] = tmp0;
|
|
|
|
// scale down, round and store
|
|
out[i << 1] = state[7] >> 15;
|
|
}
|
|
|
|
out++;
|
|
|
|
// lower allpass filter (generates even output samples)
|
|
for (i = 0; i < len; i++)
|
|
{
|
|
tmp0 = ((int32_t)in[i] << 15) + (1 << 14);
|
|
diff = tmp0 - state[1];
|
|
// scale down and round
|
|
diff = (diff + (1 << 13)) >> 14;
|
|
tmp1 = state[0] + diff * kResampleAllpass[1][0];
|
|
state[0] = tmp0;
|
|
diff = tmp1 - state[2];
|
|
// scale down and truncate
|
|
diff = diff >> 14;
|
|
if (diff < 0)
|
|
diff += 1;
|
|
tmp0 = state[1] + diff * kResampleAllpass[1][1];
|
|
state[1] = tmp1;
|
|
diff = tmp0 - state[3];
|
|
// scale down and truncate
|
|
diff = diff >> 14;
|
|
if (diff < 0)
|
|
diff += 1;
|
|
state[3] = state[2] + diff * kResampleAllpass[1][2];
|
|
state[2] = tmp0;
|
|
|
|
// scale down, round and store
|
|
out[i << 1] = state[3] >> 15;
|
|
}
|
|
}
|
|
|
|
//
|
|
// interpolator
|
|
// input: int32_t (shifted 15 positions to the left, + offset 16384)
|
|
// output: int32_t (shifted 15 positions to the left, + offset 16384) (of length len*2)
|
|
// state: filter state array; length = 8
|
|
void WebRtcSpl_UpBy2IntToInt(const int32_t *in, int32_t len, int32_t *out,
|
|
int32_t *state)
|
|
{
|
|
int32_t tmp0, tmp1, diff;
|
|
int32_t i;
|
|
|
|
// upper allpass filter (generates odd output samples)
|
|
for (i = 0; i < len; i++)
|
|
{
|
|
tmp0 = in[i];
|
|
diff = tmp0 - state[5];
|
|
// scale down and round
|
|
diff = (diff + (1 << 13)) >> 14;
|
|
tmp1 = state[4] + diff * kResampleAllpass[0][0];
|
|
state[4] = tmp0;
|
|
diff = tmp1 - state[6];
|
|
// scale down and truncate
|
|
diff = diff >> 14;
|
|
if (diff < 0)
|
|
diff += 1;
|
|
tmp0 = state[5] + diff * kResampleAllpass[0][1];
|
|
state[5] = tmp1;
|
|
diff = tmp0 - state[7];
|
|
// scale down and truncate
|
|
diff = diff >> 14;
|
|
if (diff < 0)
|
|
diff += 1;
|
|
state[7] = state[6] + diff * kResampleAllpass[0][2];
|
|
state[6] = tmp0;
|
|
|
|
// scale down, round and store
|
|
out[i << 1] = state[7];
|
|
}
|
|
|
|
out++;
|
|
|
|
// lower allpass filter (generates even output samples)
|
|
for (i = 0; i < len; i++)
|
|
{
|
|
tmp0 = in[i];
|
|
diff = tmp0 - state[1];
|
|
// scale down and round
|
|
diff = (diff + (1 << 13)) >> 14;
|
|
tmp1 = state[0] + diff * kResampleAllpass[1][0];
|
|
state[0] = tmp0;
|
|
diff = tmp1 - state[2];
|
|
// scale down and truncate
|
|
diff = diff >> 14;
|
|
if (diff < 0)
|
|
diff += 1;
|
|
tmp0 = state[1] + diff * kResampleAllpass[1][1];
|
|
state[1] = tmp1;
|
|
diff = tmp0 - state[3];
|
|
// scale down and truncate
|
|
diff = diff >> 14;
|
|
if (diff < 0)
|
|
diff += 1;
|
|
state[3] = state[2] + diff * kResampleAllpass[1][2];
|
|
state[2] = tmp0;
|
|
|
|
// scale down, round and store
|
|
out[i << 1] = state[3];
|
|
}
|
|
}
|
|
|
|
//
|
|
// interpolator
|
|
// input: int32_t (shifted 15 positions to the left, + offset 16384)
|
|
// output: int16_t (saturated) (of length len*2)
|
|
// state: filter state array; length = 8
|
|
void WebRtcSpl_UpBy2IntToShort(const int32_t *in, int32_t len, int16_t *out,
|
|
int32_t *state)
|
|
{
|
|
int32_t tmp0, tmp1, diff;
|
|
int32_t i;
|
|
|
|
// upper allpass filter (generates odd output samples)
|
|
for (i = 0; i < len; i++)
|
|
{
|
|
tmp0 = in[i];
|
|
diff = tmp0 - state[5];
|
|
// scale down and round
|
|
diff = (diff + (1 << 13)) >> 14;
|
|
tmp1 = state[4] + diff * kResampleAllpass[0][0];
|
|
state[4] = tmp0;
|
|
diff = tmp1 - state[6];
|
|
// scale down and round
|
|
diff = diff >> 14;
|
|
if (diff < 0)
|
|
diff += 1;
|
|
tmp0 = state[5] + diff * kResampleAllpass[0][1];
|
|
state[5] = tmp1;
|
|
diff = tmp0 - state[7];
|
|
// scale down and truncate
|
|
diff = diff >> 14;
|
|
if (diff < 0)
|
|
diff += 1;
|
|
state[7] = state[6] + diff * kResampleAllpass[0][2];
|
|
state[6] = tmp0;
|
|
|
|
// scale down, saturate and store
|
|
tmp1 = state[7] >> 15;
|
|
if (tmp1 > (int32_t)0x00007FFF)
|
|
tmp1 = 0x00007FFF;
|
|
if (tmp1 < (int32_t)0xFFFF8000)
|
|
tmp1 = 0xFFFF8000;
|
|
out[i << 1] = (int16_t)tmp1;
|
|
}
|
|
|
|
out++;
|
|
|
|
// lower allpass filter (generates even output samples)
|
|
for (i = 0; i < len; i++)
|
|
{
|
|
tmp0 = in[i];
|
|
diff = tmp0 - state[1];
|
|
// scale down and round
|
|
diff = (diff + (1 << 13)) >> 14;
|
|
tmp1 = state[0] + diff * kResampleAllpass[1][0];
|
|
state[0] = tmp0;
|
|
diff = tmp1 - state[2];
|
|
// scale down and truncate
|
|
diff = diff >> 14;
|
|
if (diff < 0)
|
|
diff += 1;
|
|
tmp0 = state[1] + diff * kResampleAllpass[1][1];
|
|
state[1] = tmp1;
|
|
diff = tmp0 - state[3];
|
|
// scale down and truncate
|
|
diff = diff >> 14;
|
|
if (diff < 0)
|
|
diff += 1;
|
|
state[3] = state[2] + diff * kResampleAllpass[1][2];
|
|
state[2] = tmp0;
|
|
|
|
// scale down, saturate and store
|
|
tmp1 = state[3] >> 15;
|
|
if (tmp1 > (int32_t)0x00007FFF)
|
|
tmp1 = 0x00007FFF;
|
|
if (tmp1 < (int32_t)0xFFFF8000)
|
|
tmp1 = 0xFFFF8000;
|
|
out[i << 1] = (int16_t)tmp1;
|
|
}
|
|
}
|
|
|
|
// lowpass filter
|
|
// input: int16_t
|
|
// output: int32_t (normalized, not saturated)
|
|
// state: filter state array; length = 8
|
|
void WebRtcSpl_LPBy2ShortToInt(const int16_t* in, int32_t len, int32_t* out,
|
|
int32_t* state)
|
|
{
|
|
int32_t tmp0, tmp1, diff;
|
|
int32_t i;
|
|
|
|
len >>= 1;
|
|
|
|
// lower allpass filter: odd input -> even output samples
|
|
in++;
|
|
// initial state of polyphase delay element
|
|
tmp0 = state[12];
|
|
for (i = 0; i < len; i++)
|
|
{
|
|
diff = tmp0 - state[1];
|
|
// scale down and round
|
|
diff = (diff + (1 << 13)) >> 14;
|
|
tmp1 = state[0] + diff * kResampleAllpass[1][0];
|
|
state[0] = tmp0;
|
|
diff = tmp1 - state[2];
|
|
// scale down and truncate
|
|
diff = diff >> 14;
|
|
if (diff < 0)
|
|
diff += 1;
|
|
tmp0 = state[1] + diff * kResampleAllpass[1][1];
|
|
state[1] = tmp1;
|
|
diff = tmp0 - state[3];
|
|
// scale down and truncate
|
|
diff = diff >> 14;
|
|
if (diff < 0)
|
|
diff += 1;
|
|
state[3] = state[2] + diff * kResampleAllpass[1][2];
|
|
state[2] = tmp0;
|
|
|
|
// scale down, round and store
|
|
out[i << 1] = state[3] >> 1;
|
|
tmp0 = ((int32_t)in[i << 1] << 15) + (1 << 14);
|
|
}
|
|
in--;
|
|
|
|
// upper allpass filter: even input -> even output samples
|
|
for (i = 0; i < len; i++)
|
|
{
|
|
tmp0 = ((int32_t)in[i << 1] << 15) + (1 << 14);
|
|
diff = tmp0 - state[5];
|
|
// scale down and round
|
|
diff = (diff + (1 << 13)) >> 14;
|
|
tmp1 = state[4] + diff * kResampleAllpass[0][0];
|
|
state[4] = tmp0;
|
|
diff = tmp1 - state[6];
|
|
// scale down and round
|
|
diff = diff >> 14;
|
|
if (diff < 0)
|
|
diff += 1;
|
|
tmp0 = state[5] + diff * kResampleAllpass[0][1];
|
|
state[5] = tmp1;
|
|
diff = tmp0 - state[7];
|
|
// scale down and truncate
|
|
diff = diff >> 14;
|
|
if (diff < 0)
|
|
diff += 1;
|
|
state[7] = state[6] + diff * kResampleAllpass[0][2];
|
|
state[6] = tmp0;
|
|
|
|
// average the two allpass outputs, scale down and store
|
|
out[i << 1] = (out[i << 1] + (state[7] >> 1)) >> 15;
|
|
}
|
|
|
|
// switch to odd output samples
|
|
out++;
|
|
|
|
// lower allpass filter: even input -> odd output samples
|
|
for (i = 0; i < len; i++)
|
|
{
|
|
tmp0 = ((int32_t)in[i << 1] << 15) + (1 << 14);
|
|
diff = tmp0 - state[9];
|
|
// scale down and round
|
|
diff = (diff + (1 << 13)) >> 14;
|
|
tmp1 = state[8] + diff * kResampleAllpass[1][0];
|
|
state[8] = tmp0;
|
|
diff = tmp1 - state[10];
|
|
// scale down and truncate
|
|
diff = diff >> 14;
|
|
if (diff < 0)
|
|
diff += 1;
|
|
tmp0 = state[9] + diff * kResampleAllpass[1][1];
|
|
state[9] = tmp1;
|
|
diff = tmp0 - state[11];
|
|
// scale down and truncate
|
|
diff = diff >> 14;
|
|
if (diff < 0)
|
|
diff += 1;
|
|
state[11] = state[10] + diff * kResampleAllpass[1][2];
|
|
state[10] = tmp0;
|
|
|
|
// scale down, round and store
|
|
out[i << 1] = state[11] >> 1;
|
|
}
|
|
|
|
// upper allpass filter: odd input -> odd output samples
|
|
in++;
|
|
for (i = 0; i < len; i++)
|
|
{
|
|
tmp0 = ((int32_t)in[i << 1] << 15) + (1 << 14);
|
|
diff = tmp0 - state[13];
|
|
// scale down and round
|
|
diff = (diff + (1 << 13)) >> 14;
|
|
tmp1 = state[12] + diff * kResampleAllpass[0][0];
|
|
state[12] = tmp0;
|
|
diff = tmp1 - state[14];
|
|
// scale down and round
|
|
diff = diff >> 14;
|
|
if (diff < 0)
|
|
diff += 1;
|
|
tmp0 = state[13] + diff * kResampleAllpass[0][1];
|
|
state[13] = tmp1;
|
|
diff = tmp0 - state[15];
|
|
// scale down and truncate
|
|
diff = diff >> 14;
|
|
if (diff < 0)
|
|
diff += 1;
|
|
state[15] = state[14] + diff * kResampleAllpass[0][2];
|
|
state[14] = tmp0;
|
|
|
|
// average the two allpass outputs, scale down and store
|
|
out[i << 1] = (out[i << 1] + (state[15] >> 1)) >> 15;
|
|
}
|
|
}
|
|
|
|
// lowpass filter
|
|
// input: int32_t (shifted 15 positions to the left, + offset 16384)
|
|
// output: int32_t (normalized, not saturated)
|
|
// state: filter state array; length = 8
|
|
void RTC_NO_SANITIZE("signed-integer-overflow") // bugs.webrtc.org/5486
|
|
WebRtcSpl_LPBy2IntToInt(const int32_t* in, int32_t len, int32_t* out,
|
|
int32_t* state)
|
|
{
|
|
int32_t tmp0, tmp1, diff;
|
|
int32_t i;
|
|
|
|
len >>= 1;
|
|
|
|
// lower allpass filter: odd input -> even output samples
|
|
in++;
|
|
// initial state of polyphase delay element
|
|
tmp0 = state[12];
|
|
for (i = 0; i < len; i++)
|
|
{
|
|
diff = tmp0 - state[1];
|
|
// scale down and round
|
|
diff = (diff + (1 << 13)) >> 14;
|
|
tmp1 = state[0] + diff * kResampleAllpass[1][0];
|
|
state[0] = tmp0;
|
|
diff = tmp1 - state[2];
|
|
// scale down and truncate
|
|
diff = diff >> 14;
|
|
if (diff < 0)
|
|
diff += 1;
|
|
tmp0 = state[1] + diff * kResampleAllpass[1][1];
|
|
state[1] = tmp1;
|
|
diff = tmp0 - state[3];
|
|
// scale down and truncate
|
|
diff = diff >> 14;
|
|
if (diff < 0)
|
|
diff += 1;
|
|
state[3] = state[2] + diff * kResampleAllpass[1][2];
|
|
state[2] = tmp0;
|
|
|
|
// scale down, round and store
|
|
out[i << 1] = state[3] >> 1;
|
|
tmp0 = in[i << 1];
|
|
}
|
|
in--;
|
|
|
|
// upper allpass filter: even input -> even output samples
|
|
for (i = 0; i < len; i++)
|
|
{
|
|
tmp0 = in[i << 1];
|
|
diff = tmp0 - state[5];
|
|
// UBSan: -794814117 - 1566149201 cannot be represented in type 'int'
|
|
|
|
// scale down and round
|
|
diff = (diff + (1 << 13)) >> 14;
|
|
tmp1 = state[4] + diff * kResampleAllpass[0][0];
|
|
state[4] = tmp0;
|
|
diff = tmp1 - state[6];
|
|
// scale down and round
|
|
diff = diff >> 14;
|
|
if (diff < 0)
|
|
diff += 1;
|
|
tmp0 = state[5] + diff * kResampleAllpass[0][1];
|
|
state[5] = tmp1;
|
|
diff = tmp0 - state[7];
|
|
// scale down and truncate
|
|
diff = diff >> 14;
|
|
if (diff < 0)
|
|
diff += 1;
|
|
state[7] = state[6] + diff * kResampleAllpass[0][2];
|
|
state[6] = tmp0;
|
|
|
|
// average the two allpass outputs, scale down and store
|
|
out[i << 1] = (out[i << 1] + (state[7] >> 1)) >> 15;
|
|
}
|
|
|
|
// switch to odd output samples
|
|
out++;
|
|
|
|
// lower allpass filter: even input -> odd output samples
|
|
for (i = 0; i < len; i++)
|
|
{
|
|
tmp0 = in[i << 1];
|
|
diff = tmp0 - state[9];
|
|
// scale down and round
|
|
diff = (diff + (1 << 13)) >> 14;
|
|
tmp1 = state[8] + diff * kResampleAllpass[1][0];
|
|
state[8] = tmp0;
|
|
diff = tmp1 - state[10];
|
|
// scale down and truncate
|
|
diff = diff >> 14;
|
|
if (diff < 0)
|
|
diff += 1;
|
|
tmp0 = state[9] + diff * kResampleAllpass[1][1];
|
|
state[9] = tmp1;
|
|
diff = tmp0 - state[11];
|
|
// scale down and truncate
|
|
diff = diff >> 14;
|
|
if (diff < 0)
|
|
diff += 1;
|
|
state[11] = state[10] + diff * kResampleAllpass[1][2];
|
|
state[10] = tmp0;
|
|
|
|
// scale down, round and store
|
|
out[i << 1] = state[11] >> 1;
|
|
}
|
|
|
|
// upper allpass filter: odd input -> odd output samples
|
|
in++;
|
|
for (i = 0; i < len; i++)
|
|
{
|
|
tmp0 = in[i << 1];
|
|
diff = tmp0 - state[13];
|
|
// scale down and round
|
|
diff = (diff + (1 << 13)) >> 14;
|
|
tmp1 = state[12] + diff * kResampleAllpass[0][0];
|
|
state[12] = tmp0;
|
|
diff = tmp1 - state[14];
|
|
// scale down and round
|
|
diff = diff >> 14;
|
|
if (diff < 0)
|
|
diff += 1;
|
|
tmp0 = state[13] + diff * kResampleAllpass[0][1];
|
|
state[13] = tmp1;
|
|
diff = tmp0 - state[15];
|
|
// scale down and truncate
|
|
diff = diff >> 14;
|
|
if (diff < 0)
|
|
diff += 1;
|
|
state[15] = state[14] + diff * kResampleAllpass[0][2];
|
|
state[14] = tmp0;
|
|
|
|
// average the two allpass outputs, scale down and store
|
|
out[i << 1] = (out[i << 1] + (state[15] >> 1)) >> 15;
|
|
}
|
|
}
|