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
24 #include "libavutil/attributes.h"
25 #include "libavutil/intfloat.h"
28 static void sbr_sum64x5_c(float *z
)
31 for (k
= 0; k
< 64; k
++) {
32 float f
= z
[k
] + z
[k
+ 64] + z
[k
+ 128] + z
[k
+ 192] + z
[k
+ 256];
37 static float sbr_sum_square_c(float (*x
)[2], int n
)
39 float sum0
= 0.0f
, sum1
= 0.0f
;
42 for (i
= 0; i
< n
; i
+= 2)
44 sum0
+= x
[i
+ 0][0] * x
[i
+ 0][0];
45 sum1
+= x
[i
+ 0][1] * x
[i
+ 0][1];
46 sum0
+= x
[i
+ 1][0] * x
[i
+ 1][0];
47 sum1
+= x
[i
+ 1][1] * x
[i
+ 1][1];
53 static void sbr_neg_odd_64_c(float *x
)
55 union av_intfloat32
*xi
= (union av_intfloat32
*) x
;
57 for (i
= 1; i
< 64; i
+= 4) {
58 xi
[i
+ 0].i
^= 1U << 31;
59 xi
[i
+ 2].i
^= 1U << 31;
63 static void sbr_qmf_pre_shuffle_c(float *z
)
65 union av_intfloat32
*zi
= (union av_intfloat32
*) z
;
69 for (k
= 1; k
< 31; k
+= 2) {
70 zi
[64 + 2 * k
+ 0].i
= zi
[64 - k
].i
^ (1U << 31);
71 zi
[64 + 2 * k
+ 1].i
= zi
[ k
+ 1].i
;
72 zi
[64 + 2 * k
+ 2].i
= zi
[63 - k
].i
^ (1U << 31);
73 zi
[64 + 2 * k
+ 3].i
= zi
[ k
+ 2].i
;
76 zi
[64 + 2 * 31 + 0].i
= zi
[64 - 31].i
^ (1U << 31);
77 zi
[64 + 2 * 31 + 1].i
= zi
[31 + 1].i
;
80 static void sbr_qmf_post_shuffle_c(float W
[32][2], const float *z
)
82 const union av_intfloat32
*zi
= (const union av_intfloat32
*) z
;
83 union av_intfloat32
*Wi
= (union av_intfloat32
*) W
;
85 for (k
= 0; k
< 32; k
+= 2) {
86 Wi
[2 * k
+ 0].i
= zi
[63 - k
].i
^ (1U << 31);
87 Wi
[2 * k
+ 1].i
= zi
[ k
+ 0].i
;
88 Wi
[2 * k
+ 2].i
= zi
[62 - k
].i
^ (1U << 31);
89 Wi
[2 * k
+ 3].i
= zi
[ k
+ 1].i
;
93 static void sbr_qmf_deint_neg_c(float *v
, const float *src
)
95 const union av_intfloat32
*si
= (const union av_intfloat32
*)src
;
96 union av_intfloat32
*vi
= (union av_intfloat32
*)v
;
98 for (i
= 0; i
< 32; i
++) {
99 vi
[ i
].i
= si
[63 - 2 * i
].i
;
100 vi
[63 - i
].i
= si
[63 - 2 * i
- 1].i
^ (1U << 31);
104 static void sbr_qmf_deint_bfly_c(float *v
, const float *src0
, const float *src1
)
107 for (i
= 0; i
< 64; i
++) {
108 v
[ i
] = src0
[i
] - src1
[63 - i
];
109 v
[127 - i
] = src0
[i
] + src1
[63 - i
];
115 /* This code is slower because it multiplies memory accesses.
116 * It is left for educational purposes and because it may offer
117 * a better reference for writing arch-specific DSP functions. */
118 static av_always_inline
void autocorrelate(const float x
[40][2],
119 float phi
[3][2][2], int lag
)
122 float real_sum
= 0.0f
;
123 float imag_sum
= 0.0f
;
125 for (i
= 1; i
< 38; i
++) {
126 real_sum
+= x
[i
][0] * x
[i
+lag
][0] + x
[i
][1] * x
[i
+lag
][1];
127 imag_sum
+= x
[i
][0] * x
[i
+lag
][1] - x
[i
][1] * x
[i
+lag
][0];
129 phi
[2-lag
][1][0] = real_sum
+ x
[ 0][0] * x
[lag
][0] + x
[ 0][1] * x
[lag
][1];
130 phi
[2-lag
][1][1] = imag_sum
+ x
[ 0][0] * x
[lag
][1] - x
[ 0][1] * x
[lag
][0];
132 phi
[0][0][0] = real_sum
+ x
[38][0] * x
[39][0] + x
[38][1] * x
[39][1];
133 phi
[0][0][1] = imag_sum
+ x
[38][0] * x
[39][1] - x
[38][1] * x
[39][0];
136 for (i
= 1; i
< 38; i
++) {
137 real_sum
+= x
[i
][0] * x
[i
][0] + x
[i
][1] * x
[i
][1];
139 phi
[2][1][0] = real_sum
+ x
[ 0][0] * x
[ 0][0] + x
[ 0][1] * x
[ 0][1];
140 phi
[1][0][0] = real_sum
+ x
[38][0] * x
[38][0] + x
[38][1] * x
[38][1];
144 static void sbr_autocorrelate_c(const float x
[40][2], float phi
[3][2][2])
146 autocorrelate(x
, phi
, 0);
147 autocorrelate(x
, phi
, 1);
148 autocorrelate(x
, phi
, 2);
151 static void sbr_autocorrelate_c(const float x
[40][2], float phi
[3][2][2])
153 float real_sum2
= x
[0][0] * x
[2][0] + x
[0][1] * x
[2][1];
154 float imag_sum2
= x
[0][0] * x
[2][1] - x
[0][1] * x
[2][0];
155 float real_sum1
= 0.0f
, imag_sum1
= 0.0f
, real_sum0
= 0.0f
;
157 for (i
= 1; i
< 38; i
++) {
158 real_sum0
+= x
[i
][0] * x
[i
][0] + x
[i
][1] * x
[i
][1];
159 real_sum1
+= x
[i
][0] * x
[i
+ 1][0] + x
[i
][1] * x
[i
+ 1][1];
160 imag_sum1
+= x
[i
][0] * x
[i
+ 1][1] - x
[i
][1] * x
[i
+ 1][0];
161 real_sum2
+= x
[i
][0] * x
[i
+ 2][0] + x
[i
][1] * x
[i
+ 2][1];
162 imag_sum2
+= x
[i
][0] * x
[i
+ 2][1] - x
[i
][1] * x
[i
+ 2][0];
164 phi
[2 - 2][1][0] = real_sum2
;
165 phi
[2 - 2][1][1] = imag_sum2
;
166 phi
[2 ][1][0] = real_sum0
+ x
[ 0][0] * x
[ 0][0] + x
[ 0][1] * x
[ 0][1];
167 phi
[1 ][0][0] = real_sum0
+ x
[38][0] * x
[38][0] + x
[38][1] * x
[38][1];
168 phi
[2 - 1][1][0] = real_sum1
+ x
[ 0][0] * x
[ 1][0] + x
[ 0][1] * x
[ 1][1];
169 phi
[2 - 1][1][1] = imag_sum1
+ x
[ 0][0] * x
[ 1][1] - x
[ 0][1] * x
[ 1][0];
170 phi
[0 ][0][0] = real_sum1
+ x
[38][0] * x
[39][0] + x
[38][1] * x
[39][1];
171 phi
[0 ][0][1] = imag_sum1
+ x
[38][0] * x
[39][1] - x
[38][1] * x
[39][0];
175 static void sbr_hf_gen_c(float (*X_high
)[2], const float (*X_low
)[2],
176 const float alpha0
[2], const float alpha1
[2],
177 float bw
, int start
, int end
)
182 alpha
[0] = alpha1
[0] * bw
* bw
;
183 alpha
[1] = alpha1
[1] * bw
* bw
;
184 alpha
[2] = alpha0
[0] * bw
;
185 alpha
[3] = alpha0
[1] * bw
;
187 for (i
= start
; i
< end
; i
++) {
189 X_low
[i
- 2][0] * alpha
[0] -
190 X_low
[i
- 2][1] * alpha
[1] +
191 X_low
[i
- 1][0] * alpha
[2] -
192 X_low
[i
- 1][1] * alpha
[3] +
195 X_low
[i
- 2][1] * alpha
[0] +
196 X_low
[i
- 2][0] * alpha
[1] +
197 X_low
[i
- 1][1] * alpha
[2] +
198 X_low
[i
- 1][0] * alpha
[3] +
203 static void sbr_hf_g_filt_c(float (*Y
)[2], const float (*X_high
)[40][2],
204 const float *g_filt
, int m_max
, intptr_t ixh
)
208 for (m
= 0; m
< m_max
; m
++) {
209 Y
[m
][0] = X_high
[m
][ixh
][0] * g_filt
[m
];
210 Y
[m
][1] = X_high
[m
][ixh
][1] * g_filt
[m
];
214 static av_always_inline
void sbr_hf_apply_noise(float (*Y
)[2],
224 for (m
= 0; m
< m_max
; m
++) {
227 noise
= (noise
+ 1) & 0x1ff;
229 y0
+= s_m
[m
] * phi_sign0
;
230 y1
+= s_m
[m
] * phi_sign1
;
232 y0
+= q_filt
[m
] * ff_sbr_noise_table
[noise
][0];
233 y1
+= q_filt
[m
] * ff_sbr_noise_table
[noise
][1];
237 phi_sign1
= -phi_sign1
;
241 static void sbr_hf_apply_noise_0(float (*Y
)[2], const float *s_m
,
242 const float *q_filt
, int noise
,
245 sbr_hf_apply_noise(Y
, s_m
, q_filt
, noise
, 1.0, 0.0, m_max
);
248 static void sbr_hf_apply_noise_1(float (*Y
)[2], const float *s_m
,
249 const float *q_filt
, int noise
,
252 float phi_sign
= 1 - 2 * (kx
& 1);
253 sbr_hf_apply_noise(Y
, s_m
, q_filt
, noise
, 0.0, phi_sign
, m_max
);
256 static void sbr_hf_apply_noise_2(float (*Y
)[2], const float *s_m
,
257 const float *q_filt
, int noise
,
260 sbr_hf_apply_noise(Y
, s_m
, q_filt
, noise
, -1.0, 0.0, m_max
);
263 static void sbr_hf_apply_noise_3(float (*Y
)[2], const float *s_m
,
264 const float *q_filt
, int noise
,
267 float phi_sign
= 1 - 2 * (kx
& 1);
268 sbr_hf_apply_noise(Y
, s_m
, q_filt
, noise
, 0.0, -phi_sign
, m_max
);
271 av_cold
void ff_sbrdsp_init(SBRDSPContext
*s
)
273 s
->sum64x5
= sbr_sum64x5_c
;
274 s
->sum_square
= sbr_sum_square_c
;
275 s
->neg_odd_64
= sbr_neg_odd_64_c
;
276 s
->qmf_pre_shuffle
= sbr_qmf_pre_shuffle_c
;
277 s
->qmf_post_shuffle
= sbr_qmf_post_shuffle_c
;
278 s
->qmf_deint_neg
= sbr_qmf_deint_neg_c
;
279 s
->qmf_deint_bfly
= sbr_qmf_deint_bfly_c
;
280 s
->autocorrelate
= sbr_autocorrelate_c
;
281 s
->hf_gen
= sbr_hf_gen_c
;
282 s
->hf_g_filt
= sbr_hf_g_filt_c
;
284 s
->hf_apply_noise
[0] = sbr_hf_apply_noise_0
;
285 s
->hf_apply_noise
[1] = sbr_hf_apply_noise_1
;
286 s
->hf_apply_noise
[2] = sbr_hf_apply_noise_2
;
287 s
->hf_apply_noise
[3] = sbr_hf_apply_noise_3
;
290 ff_sbrdsp_init_arm(s
);
292 ff_sbrdsp_init_x86(s
);
294 ff_sbrdsp_init_mips(s
);