2 * Copyright (c) 2010 Alex Converse <alex.converse@gmail.com>
4 * This file is part of FFmpeg.
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 #include "libavutil/attributes.h"
25 static void ps_add_squares_c(float *dst
, const float (*src
)[2], int n
)
28 for (i
= 0; i
< n
; i
++)
29 dst
[i
] += src
[i
][0] * src
[i
][0] + src
[i
][1] * src
[i
][1];
32 static void ps_mul_pair_single_c(float (*dst
)[2], float (*src0
)[2], float *src1
,
36 for (i
= 0; i
< n
; i
++) {
37 dst
[i
][0] = src0
[i
][0] * src1
[i
];
38 dst
[i
][1] = src0
[i
][1] * src1
[i
];
42 static void ps_hybrid_analysis_c(float (*out
)[2], float (*in
)[2],
43 const float (*filter
)[8][2],
48 for (i
= 0; i
< n
; i
++) {
49 float sum_re
= filter
[i
][6][0] * in
[6][0];
50 float sum_im
= filter
[i
][6][0] * in
[6][1];
52 for (j
= 0; j
< 6; j
++) {
53 float in0_re
= in
[j
][0];
54 float in0_im
= in
[j
][1];
55 float in1_re
= in
[12-j
][0];
56 float in1_im
= in
[12-j
][1];
57 sum_re
+= filter
[i
][j
][0] * (in0_re
+ in1_re
) -
58 filter
[i
][j
][1] * (in0_im
- in1_im
);
59 sum_im
+= filter
[i
][j
][0] * (in0_im
+ in1_im
) +
60 filter
[i
][j
][1] * (in0_re
- in1_re
);
62 out
[i
* stride
][0] = sum_re
;
63 out
[i
* stride
][1] = sum_im
;
67 static void ps_hybrid_analysis_ileave_c(float (*out
)[32][2], float L
[2][38][64],
73 for (j
= 0; j
< len
; j
++) {
74 out
[i
][j
][0] = L
[0][j
][i
];
75 out
[i
][j
][1] = L
[1][j
][i
];
80 static void ps_hybrid_synthesis_deint_c(float out
[2][38][64],
87 for (n
= 0; n
< len
; n
++) {
88 out
[0][n
][i
] = in
[i
][n
][0];
89 out
[1][n
][i
] = in
[i
][n
][1];
94 static void ps_decorrelate_c(float (*out
)[2], float (*delay
)[2],
95 float (*ap_delay
)[PS_QMF_TIME_SLOTS
+ PS_MAX_AP_DELAY
][2],
96 const float phi_fract
[2], const float (*Q_fract
)[2],
97 const float *transient_gain
,
101 static const float a
[] = { 0.65143905753106f
,
104 float ag
[PS_AP_LINKS
];
107 for (m
= 0; m
< PS_AP_LINKS
; m
++)
108 ag
[m
] = a
[m
] * g_decay_slope
;
110 for (n
= 0; n
< len
; n
++) {
111 float in_re
= delay
[n
][0] * phi_fract
[0] - delay
[n
][1] * phi_fract
[1];
112 float in_im
= delay
[n
][0] * phi_fract
[1] + delay
[n
][1] * phi_fract
[0];
113 for (m
= 0; m
< PS_AP_LINKS
; m
++) {
114 float a_re
= ag
[m
] * in_re
;
115 float a_im
= ag
[m
] * in_im
;
116 float link_delay_re
= ap_delay
[m
][n
+2-m
][0];
117 float link_delay_im
= ap_delay
[m
][n
+2-m
][1];
118 float fractional_delay_re
= Q_fract
[m
][0];
119 float fractional_delay_im
= Q_fract
[m
][1];
120 float apd_re
= in_re
;
121 float apd_im
= in_im
;
122 in_re
= link_delay_re
* fractional_delay_re
-
123 link_delay_im
* fractional_delay_im
- a_re
;
124 in_im
= link_delay_re
* fractional_delay_im
+
125 link_delay_im
* fractional_delay_re
- a_im
;
126 ap_delay
[m
][n
+5][0] = apd_re
+ ag
[m
] * in_re
;
127 ap_delay
[m
][n
+5][1] = apd_im
+ ag
[m
] * in_im
;
129 out
[n
][0] = transient_gain
[n
] * in_re
;
130 out
[n
][1] = transient_gain
[n
] * in_im
;
134 static void ps_stereo_interpolate_c(float (*l
)[2], float (*r
)[2],
135 float h
[2][4], float h_step
[2][4],
142 float hs0
= h_step
[0][0];
143 float hs1
= h_step
[0][1];
144 float hs2
= h_step
[0][2];
145 float hs3
= h_step
[0][3];
148 for (n
= 0; n
< len
; n
++) {
150 float l_re
= l
[n
][0];
151 float l_im
= l
[n
][1];
152 float r_re
= r
[n
][0];
153 float r_im
= r
[n
][1];
158 l
[n
][0] = h0
* l_re
+ h2
* r_re
;
159 l
[n
][1] = h0
* l_im
+ h2
* r_im
;
160 r
[n
][0] = h1
* l_re
+ h3
* r_re
;
161 r
[n
][1] = h1
* l_im
+ h3
* r_im
;
165 static void ps_stereo_interpolate_ipdopd_c(float (*l
)[2], float (*r
)[2],
166 float h
[2][4], float h_step
[2][4],
169 float h00
= h
[0][0], h10
= h
[1][0];
170 float h01
= h
[0][1], h11
= h
[1][1];
171 float h02
= h
[0][2], h12
= h
[1][2];
172 float h03
= h
[0][3], h13
= h
[1][3];
173 float hs00
= h_step
[0][0], hs10
= h_step
[1][0];
174 float hs01
= h_step
[0][1], hs11
= h_step
[1][1];
175 float hs02
= h_step
[0][2], hs12
= h_step
[1][2];
176 float hs03
= h_step
[0][3], hs13
= h_step
[1][3];
179 for (n
= 0; n
< len
; n
++) {
181 float l_re
= l
[n
][0];
182 float l_im
= l
[n
][1];
183 float r_re
= r
[n
][0];
184 float r_im
= r
[n
][1];
194 l
[n
][0] = h00
* l_re
+ h02
* r_re
- h10
* l_im
- h12
* r_im
;
195 l
[n
][1] = h00
* l_im
+ h02
* r_im
+ h10
* l_re
+ h12
* r_re
;
196 r
[n
][0] = h01
* l_re
+ h03
* r_re
- h11
* l_im
- h13
* r_im
;
197 r
[n
][1] = h01
* l_im
+ h03
* r_im
+ h11
* l_re
+ h13
* r_re
;
201 av_cold
void ff_psdsp_init(PSDSPContext
*s
)
203 s
->add_squares
= ps_add_squares_c
;
204 s
->mul_pair_single
= ps_mul_pair_single_c
;
205 s
->hybrid_analysis
= ps_hybrid_analysis_c
;
206 s
->hybrid_analysis_ileave
= ps_hybrid_analysis_ileave_c
;
207 s
->hybrid_synthesis_deint
= ps_hybrid_synthesis_deint_c
;
208 s
->decorrelate
= ps_decorrelate_c
;
209 s
->stereo_interpolate
[0] = ps_stereo_interpolate_c
;
210 s
->stereo_interpolate
[1] = ps_stereo_interpolate_ipdopd_c
;
213 ff_psdsp_init_arm(s
);
215 ff_psdsp_init_mips(s
);