1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * AAC Spectral Band Replication decoding functions
3cabdff1aSopenharmony_ci * Copyright (c) 2008-2009 Robert Swain ( rob opendot cl )
4cabdff1aSopenharmony_ci * Copyright (c) 2009-2010 Alex Converse <alex.converse@gmail.com>
5cabdff1aSopenharmony_ci *
6cabdff1aSopenharmony_ci * This file is part of FFmpeg.
7cabdff1aSopenharmony_ci *
8cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or
9cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public
10cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either
11cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version.
12cabdff1aSopenharmony_ci *
13cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful,
14cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
15cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16cabdff1aSopenharmony_ci * Lesser General Public License for more details.
17cabdff1aSopenharmony_ci *
18cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public
19cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software
20cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21cabdff1aSopenharmony_ci */
22cabdff1aSopenharmony_ci
23cabdff1aSopenharmony_ci#define USE_FIXED 0
24cabdff1aSopenharmony_ci
25cabdff1aSopenharmony_ci#include "aac.h"
26cabdff1aSopenharmony_ci#include "config.h"
27cabdff1aSopenharmony_ci#include "libavutil/attributes.h"
28cabdff1aSopenharmony_ci#include "libavutil/intfloat.h"
29cabdff1aSopenharmony_ci#include "sbrdsp.h"
30cabdff1aSopenharmony_ci
31cabdff1aSopenharmony_cistatic float sbr_sum_square_c(float (*x)[2], int n)
32cabdff1aSopenharmony_ci{
33cabdff1aSopenharmony_ci    float sum0 = 0.0f, sum1 = 0.0f;
34cabdff1aSopenharmony_ci    int i;
35cabdff1aSopenharmony_ci
36cabdff1aSopenharmony_ci    for (i = 0; i < n; i += 2)
37cabdff1aSopenharmony_ci    {
38cabdff1aSopenharmony_ci        sum0 += x[i + 0][0] * x[i + 0][0];
39cabdff1aSopenharmony_ci        sum1 += x[i + 0][1] * x[i + 0][1];
40cabdff1aSopenharmony_ci        sum0 += x[i + 1][0] * x[i + 1][0];
41cabdff1aSopenharmony_ci        sum1 += x[i + 1][1] * x[i + 1][1];
42cabdff1aSopenharmony_ci    }
43cabdff1aSopenharmony_ci
44cabdff1aSopenharmony_ci    return sum0 + sum1;
45cabdff1aSopenharmony_ci}
46cabdff1aSopenharmony_ci
47cabdff1aSopenharmony_cistatic void sbr_neg_odd_64_c(float *x)
48cabdff1aSopenharmony_ci{
49cabdff1aSopenharmony_ci    union av_intfloat32 *xi = (union av_intfloat32*) x;
50cabdff1aSopenharmony_ci    int i;
51cabdff1aSopenharmony_ci    for (i = 1; i < 64; i += 4) {
52cabdff1aSopenharmony_ci        xi[i + 0].i ^= 1U << 31;
53cabdff1aSopenharmony_ci        xi[i + 2].i ^= 1U << 31;
54cabdff1aSopenharmony_ci    }
55cabdff1aSopenharmony_ci}
56cabdff1aSopenharmony_ci
57cabdff1aSopenharmony_cistatic void sbr_qmf_pre_shuffle_c(float *z)
58cabdff1aSopenharmony_ci{
59cabdff1aSopenharmony_ci    union av_intfloat32 *zi = (union av_intfloat32*) z;
60cabdff1aSopenharmony_ci    int k;
61cabdff1aSopenharmony_ci    zi[64].i = zi[0].i;
62cabdff1aSopenharmony_ci    zi[65].i = zi[1].i;
63cabdff1aSopenharmony_ci    for (k = 1; k < 31; k += 2) {
64cabdff1aSopenharmony_ci        zi[64 + 2 * k + 0].i = zi[64 - k].i ^ (1U << 31);
65cabdff1aSopenharmony_ci        zi[64 + 2 * k + 1].i = zi[ k + 1].i;
66cabdff1aSopenharmony_ci        zi[64 + 2 * k + 2].i = zi[63 - k].i ^ (1U << 31);
67cabdff1aSopenharmony_ci        zi[64 + 2 * k + 3].i = zi[ k + 2].i;
68cabdff1aSopenharmony_ci    }
69cabdff1aSopenharmony_ci
70cabdff1aSopenharmony_ci    zi[64 + 2 * 31 + 0].i = zi[64 - 31].i ^ (1U << 31);
71cabdff1aSopenharmony_ci    zi[64 + 2 * 31 + 1].i = zi[31 +  1].i;
72cabdff1aSopenharmony_ci}
73cabdff1aSopenharmony_ci
74cabdff1aSopenharmony_cistatic void sbr_qmf_post_shuffle_c(float W[32][2], const float *z)
75cabdff1aSopenharmony_ci{
76cabdff1aSopenharmony_ci    const union av_intfloat32 *zi = (const union av_intfloat32*) z;
77cabdff1aSopenharmony_ci    union av_intfloat32 *Wi       = (union av_intfloat32*) W;
78cabdff1aSopenharmony_ci    int k;
79cabdff1aSopenharmony_ci    for (k = 0; k < 32; k += 2) {
80cabdff1aSopenharmony_ci        Wi[2 * k + 0].i = zi[63 - k].i ^ (1U << 31);
81cabdff1aSopenharmony_ci        Wi[2 * k + 1].i = zi[ k + 0].i;
82cabdff1aSopenharmony_ci        Wi[2 * k + 2].i = zi[62 - k].i ^ (1U << 31);
83cabdff1aSopenharmony_ci        Wi[2 * k + 3].i = zi[ k + 1].i;
84cabdff1aSopenharmony_ci    }
85cabdff1aSopenharmony_ci}
86cabdff1aSopenharmony_ci
87cabdff1aSopenharmony_cistatic void sbr_qmf_deint_neg_c(float *v, const float *src)
88cabdff1aSopenharmony_ci{
89cabdff1aSopenharmony_ci    const union av_intfloat32 *si = (const union av_intfloat32*)src;
90cabdff1aSopenharmony_ci    union av_intfloat32 *vi = (union av_intfloat32*)v;
91cabdff1aSopenharmony_ci    int i;
92cabdff1aSopenharmony_ci    for (i = 0; i < 32; i++) {
93cabdff1aSopenharmony_ci        vi[     i].i = si[63 - 2 * i    ].i;
94cabdff1aSopenharmony_ci        vi[63 - i].i = si[63 - 2 * i - 1].i ^ (1U << 31);
95cabdff1aSopenharmony_ci    }
96cabdff1aSopenharmony_ci}
97cabdff1aSopenharmony_ci
98cabdff1aSopenharmony_ci#if 0
99cabdff1aSopenharmony_ci    /* This code is slower because it multiplies memory accesses.
100cabdff1aSopenharmony_ci     * It is left for educational purposes and because it may offer
101cabdff1aSopenharmony_ci     * a better reference for writing arch-specific DSP functions. */
102cabdff1aSopenharmony_cistatic av_always_inline void autocorrelate(const float x[40][2],
103cabdff1aSopenharmony_ci                                           float phi[3][2][2], int lag)
104cabdff1aSopenharmony_ci{
105cabdff1aSopenharmony_ci    int i;
106cabdff1aSopenharmony_ci    float real_sum = 0.0f;
107cabdff1aSopenharmony_ci    float imag_sum = 0.0f;
108cabdff1aSopenharmony_ci    if (lag) {
109cabdff1aSopenharmony_ci        for (i = 1; i < 38; i++) {
110cabdff1aSopenharmony_ci            real_sum += x[i][0] * x[i+lag][0] + x[i][1] * x[i+lag][1];
111cabdff1aSopenharmony_ci            imag_sum += x[i][0] * x[i+lag][1] - x[i][1] * x[i+lag][0];
112cabdff1aSopenharmony_ci        }
113cabdff1aSopenharmony_ci        phi[2-lag][1][0] = real_sum + x[ 0][0] * x[lag][0] + x[ 0][1] * x[lag][1];
114cabdff1aSopenharmony_ci        phi[2-lag][1][1] = imag_sum + x[ 0][0] * x[lag][1] - x[ 0][1] * x[lag][0];
115cabdff1aSopenharmony_ci        if (lag == 1) {
116cabdff1aSopenharmony_ci            phi[0][0][0] = real_sum + x[38][0] * x[39][0] + x[38][1] * x[39][1];
117cabdff1aSopenharmony_ci            phi[0][0][1] = imag_sum + x[38][0] * x[39][1] - x[38][1] * x[39][0];
118cabdff1aSopenharmony_ci        }
119cabdff1aSopenharmony_ci    } else {
120cabdff1aSopenharmony_ci        for (i = 1; i < 38; i++) {
121cabdff1aSopenharmony_ci            real_sum += x[i][0] * x[i][0] + x[i][1] * x[i][1];
122cabdff1aSopenharmony_ci        }
123cabdff1aSopenharmony_ci        phi[2][1][0] = real_sum + x[ 0][0] * x[ 0][0] + x[ 0][1] * x[ 0][1];
124cabdff1aSopenharmony_ci        phi[1][0][0] = real_sum + x[38][0] * x[38][0] + x[38][1] * x[38][1];
125cabdff1aSopenharmony_ci    }
126cabdff1aSopenharmony_ci}
127cabdff1aSopenharmony_ci
128cabdff1aSopenharmony_cistatic void sbr_autocorrelate_c(const float x[40][2], float phi[3][2][2])
129cabdff1aSopenharmony_ci{
130cabdff1aSopenharmony_ci    autocorrelate(x, phi, 0);
131cabdff1aSopenharmony_ci    autocorrelate(x, phi, 1);
132cabdff1aSopenharmony_ci    autocorrelate(x, phi, 2);
133cabdff1aSopenharmony_ci}
134cabdff1aSopenharmony_ci#else
135cabdff1aSopenharmony_cistatic void sbr_autocorrelate_c(const float x[40][2], float phi[3][2][2])
136cabdff1aSopenharmony_ci{
137cabdff1aSopenharmony_ci    float real_sum2 = x[0][0] * x[2][0] + x[0][1] * x[2][1];
138cabdff1aSopenharmony_ci    float imag_sum2 = x[0][0] * x[2][1] - x[0][1] * x[2][0];
139cabdff1aSopenharmony_ci    float real_sum1 = 0.0f, imag_sum1 = 0.0f, real_sum0 = 0.0f;
140cabdff1aSopenharmony_ci    int   i;
141cabdff1aSopenharmony_ci    for (i = 1; i < 38; i++) {
142cabdff1aSopenharmony_ci        real_sum0 += x[i][0] * x[i    ][0] + x[i][1] * x[i    ][1];
143cabdff1aSopenharmony_ci        real_sum1 += x[i][0] * x[i + 1][0] + x[i][1] * x[i + 1][1];
144cabdff1aSopenharmony_ci        imag_sum1 += x[i][0] * x[i + 1][1] - x[i][1] * x[i + 1][0];
145cabdff1aSopenharmony_ci        real_sum2 += x[i][0] * x[i + 2][0] + x[i][1] * x[i + 2][1];
146cabdff1aSopenharmony_ci        imag_sum2 += x[i][0] * x[i + 2][1] - x[i][1] * x[i + 2][0];
147cabdff1aSopenharmony_ci    }
148cabdff1aSopenharmony_ci    phi[2 - 2][1][0] = real_sum2;
149cabdff1aSopenharmony_ci    phi[2 - 2][1][1] = imag_sum2;
150cabdff1aSopenharmony_ci    phi[2    ][1][0] = real_sum0 + x[ 0][0] * x[ 0][0] + x[ 0][1] * x[ 0][1];
151cabdff1aSopenharmony_ci    phi[1    ][0][0] = real_sum0 + x[38][0] * x[38][0] + x[38][1] * x[38][1];
152cabdff1aSopenharmony_ci    phi[2 - 1][1][0] = real_sum1 + x[ 0][0] * x[ 1][0] + x[ 0][1] * x[ 1][1];
153cabdff1aSopenharmony_ci    phi[2 - 1][1][1] = imag_sum1 + x[ 0][0] * x[ 1][1] - x[ 0][1] * x[ 1][0];
154cabdff1aSopenharmony_ci    phi[0    ][0][0] = real_sum1 + x[38][0] * x[39][0] + x[38][1] * x[39][1];
155cabdff1aSopenharmony_ci    phi[0    ][0][1] = imag_sum1 + x[38][0] * x[39][1] - x[38][1] * x[39][0];
156cabdff1aSopenharmony_ci}
157cabdff1aSopenharmony_ci#endif
158cabdff1aSopenharmony_ci
159cabdff1aSopenharmony_cistatic void sbr_hf_gen_c(float (*X_high)[2], const float (*X_low)[2],
160cabdff1aSopenharmony_ci                         const float alpha0[2], const float alpha1[2],
161cabdff1aSopenharmony_ci                         float bw, int start, int end)
162cabdff1aSopenharmony_ci{
163cabdff1aSopenharmony_ci    float alpha[4];
164cabdff1aSopenharmony_ci    int i;
165cabdff1aSopenharmony_ci
166cabdff1aSopenharmony_ci    alpha[0] = alpha1[0] * bw * bw;
167cabdff1aSopenharmony_ci    alpha[1] = alpha1[1] * bw * bw;
168cabdff1aSopenharmony_ci    alpha[2] = alpha0[0] * bw;
169cabdff1aSopenharmony_ci    alpha[3] = alpha0[1] * bw;
170cabdff1aSopenharmony_ci
171cabdff1aSopenharmony_ci    for (i = start; i < end; i++) {
172cabdff1aSopenharmony_ci        X_high[i][0] =
173cabdff1aSopenharmony_ci            X_low[i - 2][0] * alpha[0] -
174cabdff1aSopenharmony_ci            X_low[i - 2][1] * alpha[1] +
175cabdff1aSopenharmony_ci            X_low[i - 1][0] * alpha[2] -
176cabdff1aSopenharmony_ci            X_low[i - 1][1] * alpha[3] +
177cabdff1aSopenharmony_ci            X_low[i][0];
178cabdff1aSopenharmony_ci        X_high[i][1] =
179cabdff1aSopenharmony_ci            X_low[i - 2][1] * alpha[0] +
180cabdff1aSopenharmony_ci            X_low[i - 2][0] * alpha[1] +
181cabdff1aSopenharmony_ci            X_low[i - 1][1] * alpha[2] +
182cabdff1aSopenharmony_ci            X_low[i - 1][0] * alpha[3] +
183cabdff1aSopenharmony_ci            X_low[i][1];
184cabdff1aSopenharmony_ci    }
185cabdff1aSopenharmony_ci}
186cabdff1aSopenharmony_ci
187cabdff1aSopenharmony_cistatic void sbr_hf_g_filt_c(float (*Y)[2], const float (*X_high)[40][2],
188cabdff1aSopenharmony_ci                            const float *g_filt, int m_max, intptr_t ixh)
189cabdff1aSopenharmony_ci{
190cabdff1aSopenharmony_ci    int m;
191cabdff1aSopenharmony_ci
192cabdff1aSopenharmony_ci    for (m = 0; m < m_max; m++) {
193cabdff1aSopenharmony_ci        Y[m][0] = X_high[m][ixh][0] * g_filt[m];
194cabdff1aSopenharmony_ci        Y[m][1] = X_high[m][ixh][1] * g_filt[m];
195cabdff1aSopenharmony_ci    }
196cabdff1aSopenharmony_ci}
197cabdff1aSopenharmony_ci
198cabdff1aSopenharmony_cistatic av_always_inline void sbr_hf_apply_noise(float (*Y)[2],
199cabdff1aSopenharmony_ci                                                const float *s_m,
200cabdff1aSopenharmony_ci                                                const float *q_filt,
201cabdff1aSopenharmony_ci                                                int noise,
202cabdff1aSopenharmony_ci                                                float phi_sign0,
203cabdff1aSopenharmony_ci                                                float phi_sign1,
204cabdff1aSopenharmony_ci                                                int m_max)
205cabdff1aSopenharmony_ci{
206cabdff1aSopenharmony_ci    int m;
207cabdff1aSopenharmony_ci
208cabdff1aSopenharmony_ci    for (m = 0; m < m_max; m++) {
209cabdff1aSopenharmony_ci        float y0 = Y[m][0];
210cabdff1aSopenharmony_ci        float y1 = Y[m][1];
211cabdff1aSopenharmony_ci        noise = (noise + 1) & 0x1ff;
212cabdff1aSopenharmony_ci        if (s_m[m]) {
213cabdff1aSopenharmony_ci            y0 += s_m[m] * phi_sign0;
214cabdff1aSopenharmony_ci            y1 += s_m[m] * phi_sign1;
215cabdff1aSopenharmony_ci        } else {
216cabdff1aSopenharmony_ci            y0 += q_filt[m] * ff_sbr_noise_table[noise][0];
217cabdff1aSopenharmony_ci            y1 += q_filt[m] * ff_sbr_noise_table[noise][1];
218cabdff1aSopenharmony_ci        }
219cabdff1aSopenharmony_ci        Y[m][0] = y0;
220cabdff1aSopenharmony_ci        Y[m][1] = y1;
221cabdff1aSopenharmony_ci        phi_sign1 = -phi_sign1;
222cabdff1aSopenharmony_ci    }
223cabdff1aSopenharmony_ci}
224cabdff1aSopenharmony_ci
225cabdff1aSopenharmony_ci#include "sbrdsp_template.c"
226