2 * AAC Spectral Band Replication decoding functions
3 * Copyright (c) 2008-2009 Robert Swain ( rob opendot cl )
4 * Copyright (c) 2009-2010 Alex Converse <alex.converse@gmail.com>
6 * This file is part of FFmpeg.
8 * FFmpeg is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * FFmpeg is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with FFmpeg; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
27 #include "libavutil/attributes.h"
28 #include "libavutil/intfloat.h"
31 static float sbr_sum_square_c(float (*x
)[2], int n
)
33 float sum0
= 0.0f
, sum1
= 0.0f
;
36 for (i
= 0; i
< n
; i
+= 2)
38 sum0
+= x
[i
+ 0][0] * x
[i
+ 0][0];
39 sum1
+= x
[i
+ 0][1] * x
[i
+ 0][1];
40 sum0
+= x
[i
+ 1][0] * x
[i
+ 1][0];
41 sum1
+= x
[i
+ 1][1] * x
[i
+ 1][1];
47 static void sbr_neg_odd_64_c(float *x
)
49 union av_intfloat32
*xi
= (union av_intfloat32
*) x
;
51 for (i
= 1; i
< 64; i
+= 4) {
52 xi
[i
+ 0].i
^= 1U << 31;
53 xi
[i
+ 2].i
^= 1U << 31;
57 static void sbr_qmf_pre_shuffle_c(float *z
)
59 union av_intfloat32
*zi
= (union av_intfloat32
*) z
;
63 for (k
= 1; k
< 31; k
+= 2) {
64 zi
[64 + 2 * k
+ 0].i
= zi
[64 - k
].i
^ (1U << 31);
65 zi
[64 + 2 * k
+ 1].i
= zi
[ k
+ 1].i
;
66 zi
[64 + 2 * k
+ 2].i
= zi
[63 - k
].i
^ (1U << 31);
67 zi
[64 + 2 * k
+ 3].i
= zi
[ k
+ 2].i
;
70 zi
[64 + 2 * 31 + 0].i
= zi
[64 - 31].i
^ (1U << 31);
71 zi
[64 + 2 * 31 + 1].i
= zi
[31 + 1].i
;
74 static void sbr_qmf_post_shuffle_c(float W
[32][2], const float *z
)
76 const union av_intfloat32
*zi
= (const union av_intfloat32
*) z
;
77 union av_intfloat32
*Wi
= (union av_intfloat32
*) W
;
79 for (k
= 0; k
< 32; k
+= 2) {
80 Wi
[2 * k
+ 0].i
= zi
[63 - k
].i
^ (1U << 31);
81 Wi
[2 * k
+ 1].i
= zi
[ k
+ 0].i
;
82 Wi
[2 * k
+ 2].i
= zi
[62 - k
].i
^ (1U << 31);
83 Wi
[2 * k
+ 3].i
= zi
[ k
+ 1].i
;
87 static void sbr_qmf_deint_neg_c(float *v
, const float *src
)
89 const union av_intfloat32
*si
= (const union av_intfloat32
*)src
;
90 union av_intfloat32
*vi
= (union av_intfloat32
*)v
;
92 for (i
= 0; i
< 32; i
++) {
93 vi
[ i
].i
= si
[63 - 2 * i
].i
;
94 vi
[63 - i
].i
= si
[63 - 2 * i
- 1].i
^ (1U << 31);
99 /* This code is slower because it multiplies memory accesses.
100 * It is left for educational purposes and because it may offer
101 * a better reference for writing arch-specific DSP functions. */
102 static av_always_inline
void autocorrelate(const float x
[40][2],
103 float phi
[3][2][2], int lag
)
106 float real_sum
= 0.0f
;
107 float imag_sum
= 0.0f
;
109 for (i
= 1; i
< 38; i
++) {
110 real_sum
+= x
[i
][0] * x
[i
+lag
][0] + x
[i
][1] * x
[i
+lag
][1];
111 imag_sum
+= x
[i
][0] * x
[i
+lag
][1] - x
[i
][1] * x
[i
+lag
][0];
113 phi
[2-lag
][1][0] = real_sum
+ x
[ 0][0] * x
[lag
][0] + x
[ 0][1] * x
[lag
][1];
114 phi
[2-lag
][1][1] = imag_sum
+ x
[ 0][0] * x
[lag
][1] - x
[ 0][1] * x
[lag
][0];
116 phi
[0][0][0] = real_sum
+ x
[38][0] * x
[39][0] + x
[38][1] * x
[39][1];
117 phi
[0][0][1] = imag_sum
+ x
[38][0] * x
[39][1] - x
[38][1] * x
[39][0];
120 for (i
= 1; i
< 38; i
++) {
121 real_sum
+= x
[i
][0] * x
[i
][0] + x
[i
][1] * x
[i
][1];
123 phi
[2][1][0] = real_sum
+ x
[ 0][0] * x
[ 0][0] + x
[ 0][1] * x
[ 0][1];
124 phi
[1][0][0] = real_sum
+ x
[38][0] * x
[38][0] + x
[38][1] * x
[38][1];
128 static void sbr_autocorrelate_c(const float x
[40][2], float phi
[3][2][2])
130 autocorrelate(x
, phi
, 0);
131 autocorrelate(x
, phi
, 1);
132 autocorrelate(x
, phi
, 2);
135 static void sbr_autocorrelate_c(const float x
[40][2], float phi
[3][2][2])
137 float real_sum2
= x
[0][0] * x
[2][0] + x
[0][1] * x
[2][1];
138 float imag_sum2
= x
[0][0] * x
[2][1] - x
[0][1] * x
[2][0];
139 float real_sum1
= 0.0f
, imag_sum1
= 0.0f
, real_sum0
= 0.0f
;
141 for (i
= 1; i
< 38; i
++) {
142 real_sum0
+= x
[i
][0] * x
[i
][0] + x
[i
][1] * x
[i
][1];
143 real_sum1
+= x
[i
][0] * x
[i
+ 1][0] + x
[i
][1] * x
[i
+ 1][1];
144 imag_sum1
+= x
[i
][0] * x
[i
+ 1][1] - x
[i
][1] * x
[i
+ 1][0];
145 real_sum2
+= x
[i
][0] * x
[i
+ 2][0] + x
[i
][1] * x
[i
+ 2][1];
146 imag_sum2
+= x
[i
][0] * x
[i
+ 2][1] - x
[i
][1] * x
[i
+ 2][0];
148 phi
[2 - 2][1][0] = real_sum2
;
149 phi
[2 - 2][1][1] = imag_sum2
;
150 phi
[2 ][1][0] = real_sum0
+ x
[ 0][0] * x
[ 0][0] + x
[ 0][1] * x
[ 0][1];
151 phi
[1 ][0][0] = real_sum0
+ x
[38][0] * x
[38][0] + x
[38][1] * x
[38][1];
152 phi
[2 - 1][1][0] = real_sum1
+ x
[ 0][0] * x
[ 1][0] + x
[ 0][1] * x
[ 1][1];
153 phi
[2 - 1][1][1] = imag_sum1
+ x
[ 0][0] * x
[ 1][1] - x
[ 0][1] * x
[ 1][0];
154 phi
[0 ][0][0] = real_sum1
+ x
[38][0] * x
[39][0] + x
[38][1] * x
[39][1];
155 phi
[0 ][0][1] = imag_sum1
+ x
[38][0] * x
[39][1] - x
[38][1] * x
[39][0];
159 static void sbr_hf_gen_c(float (*X_high
)[2], const float (*X_low
)[2],
160 const float alpha0
[2], const float alpha1
[2],
161 float bw
, int start
, int end
)
166 alpha
[0] = alpha1
[0] * bw
* bw
;
167 alpha
[1] = alpha1
[1] * bw
* bw
;
168 alpha
[2] = alpha0
[0] * bw
;
169 alpha
[3] = alpha0
[1] * bw
;
171 for (i
= start
; i
< end
; i
++) {
173 X_low
[i
- 2][0] * alpha
[0] -
174 X_low
[i
- 2][1] * alpha
[1] +
175 X_low
[i
- 1][0] * alpha
[2] -
176 X_low
[i
- 1][1] * alpha
[3] +
179 X_low
[i
- 2][1] * alpha
[0] +
180 X_low
[i
- 2][0] * alpha
[1] +
181 X_low
[i
- 1][1] * alpha
[2] +
182 X_low
[i
- 1][0] * alpha
[3] +
187 static void sbr_hf_g_filt_c(float (*Y
)[2], const float (*X_high
)[40][2],
188 const float *g_filt
, int m_max
, intptr_t ixh
)
192 for (m
= 0; m
< m_max
; m
++) {
193 Y
[m
][0] = X_high
[m
][ixh
][0] * g_filt
[m
];
194 Y
[m
][1] = X_high
[m
][ixh
][1] * g_filt
[m
];
198 static av_always_inline
void sbr_hf_apply_noise(float (*Y
)[2],
208 for (m
= 0; m
< m_max
; m
++) {
211 noise
= (noise
+ 1) & 0x1ff;
213 y0
+= s_m
[m
] * phi_sign0
;
214 y1
+= s_m
[m
] * phi_sign1
;
216 y0
+= q_filt
[m
] * ff_sbr_noise_table
[noise
][0];
217 y1
+= q_filt
[m
] * ff_sbr_noise_table
[noise
][1];
221 phi_sign1
= -phi_sign1
;
225 #include "sbrdsp_template.c"