1b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/*
2b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *
4b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  Use of this source code is governed by a BSD-style license
5b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  that can be found in the LICENSE file in the root of the source
6b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  tree. An additional intellectual property rights grant can be found
7b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  in the file PATENTS.  All contributing project authors may
8b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
9b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */
10b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
11b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/*
12b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * filterbanks.c
13b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *
14b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * This file contains function
15b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * WebRtcIsacfix_SplitAndFilter, and WebRtcIsacfix_FilterAndCombine
16b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * which implement filterbanks that produce decimated lowpass and
17b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * highpass versions of a signal, and performs reconstruction.
18b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *
19b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */
20b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
21b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "filterbank_internal.h"
22b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
23d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org#include <assert.h>
24b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
25d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org#include "codec.h"
26d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org#include "filterbank_tables.h"
27d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org#include "settings.h"
28b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
29a9902801d5b79ccbbf117cae2676dadeb6686308kma@webrtc.org// Declare a function pointer.
30a9902801d5b79ccbbf117cae2676dadeb6686308kma@webrtc.orgAllpassFilter2FixDec16 WebRtcIsacfix_AllpassFilter2FixDec16;
31a9902801d5b79ccbbf117cae2676dadeb6686308kma@webrtc.org
32d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.orgvoid WebRtcIsacfix_AllpassFilter2FixDec16C(
33d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org    int16_t *data_ch1,  // Input and output in channel 1, in Q0
34d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org    int16_t *data_ch2,  // Input and output in channel 2, in Q0
35d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org    const int16_t *factor_ch1,  // Scaling factor for channel 1, in Q15
36d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org    const int16_t *factor_ch2,  // Scaling factor for channel 2, in Q15
37d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org    const int length,  // Length of the data buffers
38d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org    int32_t *filter_state_ch1,  // Filter state for channel 1, in Q16
39d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org    int32_t *filter_state_ch2) {  // Filter state for channel 2, in Q16
40d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org  int n = 0;
41d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org  int32_t state0_ch1 = filter_state_ch1[0], state1_ch1 = filter_state_ch1[1];
42d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org  int32_t state0_ch2 = filter_state_ch2[0], state1_ch2 = filter_state_ch2[1];
43d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org  int16_t in_out = 0;
44d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org  int32_t a = 0, b = 0;
45d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org
46d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org  // Assembly file assumption.
47d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org  assert(length % 2 == 0);
48d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org
49d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org  for (n = 0; n < length; n++) {
50d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org    // Process channel 1:
51d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org    in_out = data_ch1[n];
52d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org    a = WEBRTC_SPL_MUL_16_16(factor_ch1[0], in_out);  // Q15 * Q0 = Q15
53d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org    a <<= 1;  // Q15 -> Q16
54347671c843ed5c93d25bf1a23f9295d35ce3df4abjornv@webrtc.org    b = WebRtcSpl_AddSatW32(a, state0_ch1);
55d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org    a = WEBRTC_SPL_MUL_16_16(-factor_ch1[0], (int16_t) (b >> 16));  // Q15
56347671c843ed5c93d25bf1a23f9295d35ce3df4abjornv@webrtc.org    state0_ch1 = WebRtcSpl_AddSatW32(a << 1, (uint32_t)in_out << 16);  // Q16
57d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org    in_out = (int16_t) (b >> 16);  // Save as Q0
58d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org
59d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org    a = WEBRTC_SPL_MUL_16_16(factor_ch1[1], in_out);  // Q15 * Q0 = Q15
60d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org    a <<= 1; // Q15 -> Q16
61347671c843ed5c93d25bf1a23f9295d35ce3df4abjornv@webrtc.org    b = WebRtcSpl_AddSatW32(a, state1_ch1);  // Q16
62d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org    a = WEBRTC_SPL_MUL_16_16(-factor_ch1[1], (int16_t) (b >> 16));  // Q15
63347671c843ed5c93d25bf1a23f9295d35ce3df4abjornv@webrtc.org    state1_ch1 = WebRtcSpl_AddSatW32(a << 1, (uint32_t)in_out << 16);  // Q16
64d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org    data_ch1[n] = (int16_t) (b >> 16);  // Save as Q0
65d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org
66d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org    // Process channel 2:
67d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org    in_out = data_ch2[n];
68d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org    a = WEBRTC_SPL_MUL_16_16(factor_ch2[0], in_out);  // Q15 * Q0 = Q15
69d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org    a <<= 1;  // Q15 -> Q16
70347671c843ed5c93d25bf1a23f9295d35ce3df4abjornv@webrtc.org    b = WebRtcSpl_AddSatW32(a, state0_ch2);  // Q16
71d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org    a = WEBRTC_SPL_MUL_16_16(-factor_ch2[0], (int16_t) (b >> 16));  // Q15
72347671c843ed5c93d25bf1a23f9295d35ce3df4abjornv@webrtc.org    state0_ch2 = WebRtcSpl_AddSatW32(a << 1, (uint32_t)in_out << 16);  // Q16
73d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org    in_out = (int16_t) (b >> 16);  // Save as Q0
74d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org
75d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org    a = WEBRTC_SPL_MUL_16_16(factor_ch2[1], in_out);  // Q15 * Q0 = Q15
76d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org    a <<= 1;  // Q15 -> Q16
77347671c843ed5c93d25bf1a23f9295d35ce3df4abjornv@webrtc.org    b = WebRtcSpl_AddSatW32(a, state1_ch2);  // Q16
78d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org    a = WEBRTC_SPL_MUL_16_16(-factor_ch2[1], (int16_t) (b >> 16));  // Q15
79347671c843ed5c93d25bf1a23f9295d35ce3df4abjornv@webrtc.org    state1_ch2 = WebRtcSpl_AddSatW32(a << 1, (uint32_t)in_out << 16);  // Q16
80d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org    data_ch2[n] = (int16_t) (b >> 16);  // Save as Q0
81b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
82b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
83d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org  filter_state_ch1[0] = state0_ch1;
84d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org  filter_state_ch1[1] = state1_ch1;
85d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org  filter_state_ch2[0] = state0_ch2;
86d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org  filter_state_ch2[1] = state1_ch2;
87b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
88b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
89e4834e042a794dbf042bfd0934e335598d7ce4b8andrew@webrtc.org// Declare a function pointer.
90e4834e042a794dbf042bfd0934e335598d7ce4b8andrew@webrtc.orgHighpassFilterFixDec32 WebRtcIsacfix_HighpassFilterFixDec32;
91e4834e042a794dbf042bfd0934e335598d7ce4b8andrew@webrtc.org
92e4834e042a794dbf042bfd0934e335598d7ce4b8andrew@webrtc.orgvoid WebRtcIsacfix_HighpassFilterFixDec32C(int16_t *io,
93e4834e042a794dbf042bfd0934e335598d7ce4b8andrew@webrtc.org                                           int16_t len,
94e4834e042a794dbf042bfd0934e335598d7ce4b8andrew@webrtc.org                                           const int16_t *coefficient,
95e4834e042a794dbf042bfd0934e335598d7ce4b8andrew@webrtc.org                                           int32_t *state)
96b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
97b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int k;
98fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t a1 = 0, b1 = 0, c = 0, in = 0;
99fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t a2 = 0, b2 = 0;
100fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t state0 = state[0];
101fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t state1 = state[1];
102b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
103b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k=0; k<len; k++) {
104fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    in = (int32_t)io[k];
105b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
106b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#ifdef WEBRTC_ARCH_ARM_V7
107b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
10839dec2c6b1537a46bb35fecc0dd2ffca28bb58a8bjornv@webrtc.org      register int tmp_coeff0;
10939dec2c6b1537a46bb35fecc0dd2ffca28bb58a8bjornv@webrtc.org      register int tmp_coeff1;
110b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      __asm __volatile(
111b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        "ldr %[tmp_coeff0], [%[coeff]]\n\t"
112b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        "ldr %[tmp_coeff1], [%[coeff], #4]\n\t"
113b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        "smmulr %[a2], %[tmp_coeff0], %[state0]\n\t"
114b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        "smmulr %[b2], %[tmp_coeff1], %[state1]\n\t"
115b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        "ldr %[tmp_coeff0], [%[coeff], #8]\n\t"
116b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        "ldr %[tmp_coeff1], [%[coeff], #12]\n\t"
117b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        "smmulr %[a1], %[tmp_coeff0], %[state0]\n\t"
118b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        "smmulr %[b1], %[tmp_coeff1], %[state1]\n\t"
11939dec2c6b1537a46bb35fecc0dd2ffca28bb58a8bjornv@webrtc.org        :[a2]"=&r"(a2),
12039dec2c6b1537a46bb35fecc0dd2ffca28bb58a8bjornv@webrtc.org         [b2]"=&r"(b2),
12139dec2c6b1537a46bb35fecc0dd2ffca28bb58a8bjornv@webrtc.org         [a1]"=&r"(a1),
12239dec2c6b1537a46bb35fecc0dd2ffca28bb58a8bjornv@webrtc.org         [b1]"=r"(b1),
12339dec2c6b1537a46bb35fecc0dd2ffca28bb58a8bjornv@webrtc.org         [tmp_coeff0]"=&r"(tmp_coeff0),
12439dec2c6b1537a46bb35fecc0dd2ffca28bb58a8bjornv@webrtc.org         [tmp_coeff1]"=&r"(tmp_coeff1)
125b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        :[coeff]"r"(coefficient),
126b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org         [state0]"r"(state0),
127b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org         [state1]"r"(state1)
128b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      );
129b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
130b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#else
131b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Q35 * Q4 = Q39 ; shift 32 bit => Q7 */
132b5cd1aa773e4e5bc6ab84ded200ff3a618086032bjornv@webrtc.org    a1 = WEBRTC_SPL_MUL_16_32_RSFT16(coefficient[5], state0) +
133b5cd1aa773e4e5bc6ab84ded200ff3a618086032bjornv@webrtc.org        (WEBRTC_SPL_MUL_16_32_RSFT16(coefficient[4], state0) >> 16);
134b5cd1aa773e4e5bc6ab84ded200ff3a618086032bjornv@webrtc.org    b1 = WEBRTC_SPL_MUL_16_32_RSFT16(coefficient[7], state1) +
135b5cd1aa773e4e5bc6ab84ded200ff3a618086032bjornv@webrtc.org        (WEBRTC_SPL_MUL_16_32_RSFT16(coefficient[6], state1) >> 16);
136b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
137b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Q30 * Q4 = Q34 ; shift 32 bit => Q2 */
138b5cd1aa773e4e5bc6ab84ded200ff3a618086032bjornv@webrtc.org    a2 = WEBRTC_SPL_MUL_16_32_RSFT16(coefficient[1], state0) +
139b5cd1aa773e4e5bc6ab84ded200ff3a618086032bjornv@webrtc.org        (WEBRTC_SPL_MUL_16_32_RSFT16(coefficient[0], state0) >> 16);
140b5cd1aa773e4e5bc6ab84ded200ff3a618086032bjornv@webrtc.org    b2 = WEBRTC_SPL_MUL_16_32_RSFT16(coefficient[3], state1) +
141b5cd1aa773e4e5bc6ab84ded200ff3a618086032bjornv@webrtc.org        (WEBRTC_SPL_MUL_16_32_RSFT16(coefficient[2], state1) >> 16);
142b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#endif
143b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
144fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    c = ((int32_t)in) + WEBRTC_SPL_RSHIFT_W32(a1+b1, 7);  // Q0
145fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    io[k] = (int16_t)WebRtcSpl_SatW32ToW16(c);  // Write output as Q0.
146b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
147fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    c = WEBRTC_SPL_LSHIFT_W32((int32_t)in, 2) - a2 - b2;  // In Q2.
148fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    c = (int32_t)WEBRTC_SPL_SAT(536870911, c, -536870912);
149b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
150b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    state1 = state0;
151d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org    state0 = WEBRTC_SPL_LSHIFT_W32(c, 2);  // Write state as Q4
152b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
153b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  state[0] = state0;
154b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  state[1] = state1;
155b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
156b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
157b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
158fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgvoid WebRtcIsacfix_SplitAndFilter1(int16_t *pin,
159fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                                   int16_t *LP16,
160fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                                   int16_t *HP16,
161b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                   PreFiltBankstr *prefiltdata)
162b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
163b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Function WebRtcIsacfix_SplitAndFilter */
164b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* This function creates low-pass and high-pass decimated versions of part of
165b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     the input signal, and part of the signal in the input 'lookahead buffer'. */
166b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
167b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int k;
168b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
169fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t tempin_ch1[FRAMESAMPLES/2 + QLOOKAHEAD];
170fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t tempin_ch2[FRAMESAMPLES/2 + QLOOKAHEAD];
171fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t tmpState_ch1[2 * (QORDER-1)]; /* 4 */
172fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t tmpState_ch2[2 * (QORDER-1)]; /* 4 */
173b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
174b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* High pass filter */
175b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsacfix_HighpassFilterFixDec32(pin, FRAMESAMPLES, WebRtcIsacfix_kHpStCoeffInQ30, prefiltdata->HPstates_fix);
176b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
177b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
178b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* First Channel */
179b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k=0;k<FRAMESAMPLES/2;k++) {
180b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    tempin_ch1[QLOOKAHEAD + k] = pin[1+WEBRTC_SPL_MUL_16_16(2, k)];
181b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
182b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k=0;k<QLOOKAHEAD;k++) {
183b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    tempin_ch1[k]=prefiltdata->INLABUF1_fix[k];
184b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    prefiltdata->INLABUF1_fix[k]=pin[FRAMESAMPLES+1-WEBRTC_SPL_MUL_16_16(2, QLOOKAHEAD)+WEBRTC_SPL_MUL_16_16(2, k)];
185b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
186b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
187b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Second Channel.  This is exactly like the first channel, except that the
188b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     even samples are now filtered instead (lower channel). */
189b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k=0;k<FRAMESAMPLES/2;k++) {
190b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    tempin_ch2[QLOOKAHEAD+k] = pin[WEBRTC_SPL_MUL_16_16(2, k)];
191b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
192b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k=0;k<QLOOKAHEAD;k++) {
193b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    tempin_ch2[k]=prefiltdata->INLABUF2_fix[k];
194b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    prefiltdata->INLABUF2_fix[k]=pin[FRAMESAMPLES-WEBRTC_SPL_MUL_16_16(2, QLOOKAHEAD)+WEBRTC_SPL_MUL_16_16(2, k)];
195b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
196b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
197b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
198b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /*obtain polyphase components by forward all-pass filtering through each channel */
199b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* The all pass filtering automatically updates the filter states which are exported in the
200b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     prefiltdata structure */
201d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org  WebRtcIsacfix_AllpassFilter2FixDec16(tempin_ch1,
202d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org                                       tempin_ch2,
203d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org                                       WebRtcIsacfix_kUpperApFactorsQ15,
204d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org                                       WebRtcIsacfix_kLowerApFactorsQ15,
205d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org                                       FRAMESAMPLES/2,
206d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org                                       prefiltdata->INSTAT1_fix,
207d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org                                       prefiltdata->INSTAT2_fix);
208d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org
209d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org  for (k=0;k<WEBRTC_SPL_MUL_16_16(2, (QORDER-1));k++) {
210d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org    tmpState_ch1[k] = prefiltdata->INSTAT1_fix[k];
211d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org    tmpState_ch2[k] = prefiltdata->INSTAT2_fix[k];
212d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org  }
213d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org  WebRtcIsacfix_AllpassFilter2FixDec16(tempin_ch1 + FRAMESAMPLES/2,
214d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org                                       tempin_ch2 + FRAMESAMPLES/2,
215d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org                                       WebRtcIsacfix_kUpperApFactorsQ15,
216d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org                                       WebRtcIsacfix_kLowerApFactorsQ15,
217d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org                                       QLOOKAHEAD,
218d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org                                       tmpState_ch1,
219d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org                                       tmpState_ch2);
220b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
221b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Now Construct low-pass and high-pass signals as combinations of polyphase components */
222b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k=0; k<FRAMESAMPLES/2 + QLOOKAHEAD; k++) {
223fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    int32_t tmp1, tmp2, tmp3;
224fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    tmp1 = (int32_t)tempin_ch1[k]; // Q0 -> Q0
225fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    tmp2 = (int32_t)tempin_ch2[k]; // Q0 -> Q0
226fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    tmp3 = (int32_t)WEBRTC_SPL_RSHIFT_W32((tmp1 + tmp2), 1);/* low pass signal*/
227fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    LP16[k] = (int16_t)WebRtcSpl_SatW32ToW16(tmp3); /*low pass */
228fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    tmp3 = (int32_t)WEBRTC_SPL_RSHIFT_W32((tmp1 - tmp2), 1);/* high pass signal*/
229fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    HP16[k] = (int16_t)WebRtcSpl_SatW32ToW16(tmp3); /*high pass */
230b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
231b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
232b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}/*end of WebRtcIsacfix_SplitAndFilter */
233b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
234b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
235b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#ifdef WEBRTC_ISAC_FIX_NB_CALLS_ENABLED
236b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
237b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* Without lookahead */
238fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgvoid WebRtcIsacfix_SplitAndFilter2(int16_t *pin,
239fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                                   int16_t *LP16,
240fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                                   int16_t *HP16,
241b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                   PreFiltBankstr *prefiltdata)
242b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
243b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Function WebRtcIsacfix_SplitAndFilter2 */
244b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* This function creates low-pass and high-pass decimated versions of part of
245b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     the input signal. */
246b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
247b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int k;
248b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
249fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t tempin_ch1[FRAMESAMPLES/2];
250fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t tempin_ch2[FRAMESAMPLES/2];
251b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
252b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
253b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* High pass filter */
254b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsacfix_HighpassFilterFixDec32(pin, FRAMESAMPLES, WebRtcIsacfix_kHpStCoeffInQ30, prefiltdata->HPstates_fix);
255b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
256b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
257b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* First Channel */
258b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k=0;k<FRAMESAMPLES/2;k++) {
259b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    tempin_ch1[k] = pin[1+WEBRTC_SPL_MUL_16_16(2, k)];
260b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
261b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
262b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Second Channel.  This is exactly like the first channel, except that the
263b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     even samples are now filtered instead (lower channel). */
264b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k=0;k<FRAMESAMPLES/2;k++) {
265b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    tempin_ch2[k] = pin[WEBRTC_SPL_MUL_16_16(2, k)];
266b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
267b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
268b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
269b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /*obtain polyphase components by forward all-pass filtering through each channel */
270b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* The all pass filtering automatically updates the filter states which are exported in the
271b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     prefiltdata structure */
272d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org  WebRtcIsacfix_AllpassFilter2FixDec16(tempin_ch1,
273d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org                                       tempin_ch2,
274d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org                                       WebRtcIsacfix_kUpperApFactorsQ15,
275d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org                                       WebRtcIsacfix_kLowerApFactorsQ15,
276d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org                                       FRAMESAMPLES/2,
277d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org                                       prefiltdata->INSTAT1_fix,
278d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org                                       prefiltdata->INSTAT2_fix);
279b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
280b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Now Construct low-pass and high-pass signals as combinations of polyphase components */
281b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k=0; k<FRAMESAMPLES/2; k++) {
282fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    int32_t tmp1, tmp2, tmp3;
283fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    tmp1 = (int32_t)tempin_ch1[k]; // Q0 -> Q0
284fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    tmp2 = (int32_t)tempin_ch2[k]; // Q0 -> Q0
285fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    tmp3 = (int32_t)WEBRTC_SPL_RSHIFT_W32((tmp1 + tmp2), 1);/* low pass signal*/
286fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    LP16[k] = (int16_t)WebRtcSpl_SatW32ToW16(tmp3); /*low pass */
287fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    tmp3 = (int32_t)WEBRTC_SPL_RSHIFT_W32((tmp1 - tmp2), 1);/* high pass signal*/
288fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    HP16[k] = (int16_t)WebRtcSpl_SatW32ToW16(tmp3); /*high pass */
289b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
290b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
291b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}/*end of WebRtcIsacfix_SplitAndFilter */
292b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
293b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#endif
294b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
295b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
296b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
297b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//////////////////////////////////////////////////////////
298b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org////////// Combining
299b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* Function WebRtcIsacfix_FilterAndCombine */
300b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* This is a decoder function that takes the decimated
301b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   length FRAMESAMPLES/2 input low-pass and
302b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   high-pass signals and creates a reconstructed fullband
303b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   output signal of length FRAMESAMPLES. WebRtcIsacfix_FilterAndCombine
304b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   is the sibling function of WebRtcIsacfix_SplitAndFilter */
305b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* INPUTS:
306b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   inLP: a length FRAMESAMPLES/2 array of input low-pass
307b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   samples.
308b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   inHP: a length FRAMESAMPLES/2 array of input high-pass
309b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   samples.
310b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   postfiltdata: input data structure containing the filterbank
311b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   states from the previous decoding iteration.
312b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   OUTPUTS:
313b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   Out: a length FRAMESAMPLES array of output reconstructed
314b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   samples (fullband) based on the input low-pass and
315b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   high-pass signals.
316b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   postfiltdata: the input data structure containing the filterbank
317b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   states is updated for the next decoding iteration */
318fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgvoid WebRtcIsacfix_FilterAndCombine1(int16_t *tempin_ch1,
319fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                                     int16_t *tempin_ch2,
320fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                                     int16_t *out16,
321b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                     PostFiltBankstr *postfiltdata)
322b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
323b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int k;
324fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t in[FRAMESAMPLES];
325b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
326d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org  /* all-pass filter the new upper and lower channel signal.
327d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org     For upper channel, use the all-pass filter factors that were used as a
328d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org     lower channel at the encoding side. So at the decoder, the corresponding
329d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org     all-pass filter factors for each channel are swapped.
330d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org     For lower channel signal, since all-pass filter factors at the decoder are
331d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org     swapped from the ones at the encoder, the 'upper' channel all-pass filter
332d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org     factors (kUpperApFactors) are used to filter this new lower channel signal.
333d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org  */
334d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org  WebRtcIsacfix_AllpassFilter2FixDec16(tempin_ch1,
335d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org                                       tempin_ch2,
336d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org                                       WebRtcIsacfix_kLowerApFactorsQ15,
337d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org                                       WebRtcIsacfix_kUpperApFactorsQ15,
338d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org                                       FRAMESAMPLES/2,
339d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org                                       postfiltdata->STATE_0_UPPER_fix,
340d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org                                       postfiltdata->STATE_0_LOWER_fix);
341b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
342b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Merge outputs to form the full length output signal.*/
343b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k=0;k<FRAMESAMPLES/2;k++) {
344b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    in[WEBRTC_SPL_MUL_16_16(2, k)]=tempin_ch2[k];
345b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    in[WEBRTC_SPL_MUL_16_16(2, k)+1]=tempin_ch1[k];
346b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
347b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
348b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* High pass filter */
349b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsacfix_HighpassFilterFixDec32(in, FRAMESAMPLES, WebRtcIsacfix_kHPStCoeffOut1Q30, postfiltdata->HPstates1_fix);
350b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsacfix_HighpassFilterFixDec32(in, FRAMESAMPLES, WebRtcIsacfix_kHPStCoeffOut2Q30, postfiltdata->HPstates2_fix);
351b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
352b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k=0;k<FRAMESAMPLES;k++) {
353b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    out16[k] = in[k];
354b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
355b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
356b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
357b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
358b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#ifdef WEBRTC_ISAC_FIX_NB_CALLS_ENABLED
359b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* Function WebRtcIsacfix_FilterAndCombine */
360b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* This is a decoder function that takes the decimated
361b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   length len/2 input low-pass and
362b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   high-pass signals and creates a reconstructed fullband
363b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   output signal of length len. WebRtcIsacfix_FilterAndCombine
364b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   is the sibling function of WebRtcIsacfix_SplitAndFilter */
365b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* INPUTS:
366b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   inLP: a length len/2 array of input low-pass
367b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   samples.
368b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   inHP: a length len/2 array of input high-pass
369b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   samples.
370b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   postfiltdata: input data structure containing the filterbank
371b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   states from the previous decoding iteration.
372b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   OUTPUTS:
373b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   Out: a length len array of output reconstructed
374b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   samples (fullband) based on the input low-pass and
375b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   high-pass signals.
376b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   postfiltdata: the input data structure containing the filterbank
377b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   states is updated for the next decoding iteration */
378fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgvoid WebRtcIsacfix_FilterAndCombine2(int16_t *tempin_ch1,
379fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                                     int16_t *tempin_ch2,
380fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                                     int16_t *out16,
381b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                     PostFiltBankstr *postfiltdata,
382fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                                     int16_t len)
383b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
384b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int k;
385fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t in[FRAMESAMPLES];
386b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
387d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org  /* all-pass filter the new upper and lower channel signal.
388d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org     For upper channel, use the all-pass filter factors that were used as a
389d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org     lower channel at the encoding side. So at the decoder, the corresponding
390d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org     all-pass filter factors for each channel are swapped.
391d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org     For lower channel signal, since all-pass filter factors at the decoder are
392d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org     swapped from the ones at the encoder, the 'upper' channel all-pass filter
393d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org     factors (kUpperApFactors) are used to filter this new lower channel signal.
394d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org  */
395d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org  WebRtcIsacfix_AllpassFilter2FixDec16(tempin_ch1,
396d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org                                       tempin_ch2,
397d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org                                       WebRtcIsacfix_kLowerApFactorsQ15,
398d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org                                       WebRtcIsacfix_kUpperApFactorsQ15,
399d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org                                       len / 2,
400d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org                                       postfiltdata->STATE_0_UPPER_fix,
401d0ea5f0cdd6bee478e94877a564fedefa84cadd7kma@webrtc.org                                       postfiltdata->STATE_0_LOWER_fix);
402b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
403b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Merge outputs to form the full length output signal.*/
404b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k=0;k<len/2;k++) {
405b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    in[WEBRTC_SPL_MUL_16_16(2, k)]=tempin_ch2[k];
406b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    in[WEBRTC_SPL_MUL_16_16(2, k)+1]=tempin_ch1[k];
407b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
408b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
409b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* High pass filter */
410b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsacfix_HighpassFilterFixDec32(in, len, WebRtcIsacfix_kHPStCoeffOut1Q30, postfiltdata->HPstates1_fix);
411b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsacfix_HighpassFilterFixDec32(in, len, WebRtcIsacfix_kHPStCoeffOut2Q30, postfiltdata->HPstates2_fix);
412b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
413b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k=0;k<len;k++) {
414b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    out16[k] = in[k];
415b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
416b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
417b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
418b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#endif
419