aacps: move some loops to function pointers
[libav.git] / libavcodec / aacps_tablegen.h
CommitLineData
a2063901
AC
1/*
2 * Header file for hardcoded Parametric Stereo tables
3 *
4 * Copyright (c) 2010 Alex Converse <alex.converse@gmail.com>
5 *
2912e87a 6 * This file is part of Libav.
a2063901 7 *
2912e87a 8 * Libav is free software; you can redistribute it and/or
a2063901
AC
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.
12 *
2912e87a 13 * Libav is distributed in the hope that it will be useful,
a2063901
AC
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.
17 *
18 * You should have received a copy of the GNU Lesser General Public
2912e87a 19 * License along with Libav; if not, write to the Free Software
a2063901
AC
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
fd6eb4a0
AC
23#ifndef AACPS_TABLEGEN_H
24#define AACPS_TABLEGEN_H
a2063901
AC
25
26#include <stdint.h>
a2063901
AC
27
28#if CONFIG_HARDCODED_TABLES
29#define ps_tableinit()
fd6eb4a0 30#include "libavcodec/aacps_tables.h"
a2063901 31#else
69d12904
MR
32#include "libavutil/common.h"
33#include "libavutil/mathematics.h"
a2063901
AC
34#define NR_ALLPASS_BANDS20 30
35#define NR_ALLPASS_BANDS34 50
36#define PS_AP_LINKS 3
37static float pd_re_smooth[8*8*8];
38static float pd_im_smooth[8*8*8];
39static float HA[46][8][4];
40static float HB[46][8][4];
41static float f20_0_8 [ 8][7][2];
42static float f34_0_12[12][7][2];
43static float f34_1_8 [ 8][7][2];
44static float f34_2_4 [ 4][7][2];
45static float Q_fract_allpass[2][50][3][2];
46static float phi_fract[2][50][2];
47
48static const float g0_Q8[] = {
49 0.00746082949812f, 0.02270420949825f, 0.04546865930473f, 0.07266113929591f,
50 0.09885108575264f, 0.11793710567217f, 0.125f
51};
52
53static const float g0_Q12[] = {
54 0.04081179924692f, 0.03812810994926f, 0.05144908135699f, 0.06399831151592f,
55 0.07428313801106f, 0.08100347892914f, 0.08333333333333f
56};
57
58static const float g1_Q8[] = {
59 0.01565675600122f, 0.03752716391991f, 0.05417891378782f, 0.08417044116767f,
60 0.10307344158036f, 0.12222452249753f, 0.125f
61};
62
63static const float g2_Q4[] = {
64 -0.05908211155639f, -0.04871498374946f, 0.0f, 0.07778723915851f,
65 0.16486303567403f, 0.23279856662996f, 0.25f
66};
67
68static void make_filters_from_proto(float (*filter)[7][2], const float *proto, int bands)
69{
70 int q, n;
71 for (q = 0; q < bands; q++) {
72 for (n = 0; n < 7; n++) {
73 double theta = 2 * M_PI * (q + 0.5) * (n - 6) / bands;
74 filter[q][n][0] = proto[n] * cos(theta);
75 filter[q][n][1] = proto[n] * -sin(theta);
76 }
77 }
78}
79
80static void ps_tableinit(void)
81{
82 static const float ipdopd_sin[] = { 0, M_SQRT1_2, 1, M_SQRT1_2, 0, -M_SQRT1_2, -1, -M_SQRT1_2 };
83 static const float ipdopd_cos[] = { 1, M_SQRT1_2, 0, -M_SQRT1_2, -1, -M_SQRT1_2, 0, M_SQRT1_2 };
84 int pd0, pd1, pd2;
85
86 static const float iid_par_dequant[] = {
87 //iid_par_dequant_default
88 0.05623413251903, 0.12589254117942, 0.19952623149689, 0.31622776601684,
89 0.44668359215096, 0.63095734448019, 0.79432823472428, 1,
90 1.25892541179417, 1.58489319246111, 2.23872113856834, 3.16227766016838,
91 5.01187233627272, 7.94328234724282, 17.7827941003892,
92 //iid_par_dequant_fine
93 0.00316227766017, 0.00562341325190, 0.01, 0.01778279410039,
94 0.03162277660168, 0.05623413251903, 0.07943282347243, 0.11220184543020,
95 0.15848931924611, 0.22387211385683, 0.31622776601684, 0.39810717055350,
96 0.50118723362727, 0.63095734448019, 0.79432823472428, 1,
97 1.25892541179417, 1.58489319246111, 1.99526231496888, 2.51188643150958,
98 3.16227766016838, 4.46683592150963, 6.30957344480193, 8.91250938133745,
99 12.5892541179417, 17.7827941003892, 31.6227766016838, 56.2341325190349,
100 100, 177.827941003892, 316.227766016837,
101 };
102 static const float icc_invq[] = {
103 1, 0.937, 0.84118, 0.60092, 0.36764, 0, -0.589, -1
104 };
105 static const float acos_icc_invq[] = {
106 0, 0.35685527, 0.57133466, 0.92614472, 1.1943263, M_PI/2, 2.2006171, M_PI
107 };
108 int iid, icc;
109
110 int k, m;
111 static const int8_t f_center_20[] = {
112 -3, -1, 1, 3, 5, 7, 10, 14, 18, 22,
113 };
114 static const int8_t f_center_34[] = {
115 2, 6, 10, 14, 18, 22, 26, 30,
116 34,-10, -6, -2, 51, 57, 15, 21,
117 27, 33, 39, 45, 54, 66, 78, 42,
118 102, 66, 78, 90,102,114,126, 90,
119 };
120 static const float fractional_delay_links[] = { 0.43f, 0.75f, 0.347f };
121 const float fractional_delay_gain = 0.39f;
122
123 for (pd0 = 0; pd0 < 8; pd0++) {
124 float pd0_re = ipdopd_cos[pd0];
125 float pd0_im = ipdopd_sin[pd0];
126 for (pd1 = 0; pd1 < 8; pd1++) {
127 float pd1_re = ipdopd_cos[pd1];
128 float pd1_im = ipdopd_sin[pd1];
129 for (pd2 = 0; pd2 < 8; pd2++) {
130 float pd2_re = ipdopd_cos[pd2];
131 float pd2_im = ipdopd_sin[pd2];
132 float re_smooth = 0.25f * pd0_re + 0.5f * pd1_re + pd2_re;
133 float im_smooth = 0.25f * pd0_im + 0.5f * pd1_im + pd2_im;
134 float pd_mag = 1 / sqrt(im_smooth * im_smooth + re_smooth * re_smooth);
135 pd_re_smooth[pd0*64+pd1*8+pd2] = re_smooth * pd_mag;
136 pd_im_smooth[pd0*64+pd1*8+pd2] = im_smooth * pd_mag;
137 }
138 }
139 }
140
141 for (iid = 0; iid < 46; iid++) {
02494787 142 float c = iid_par_dequant[iid]; ///< Linear Inter-channel Intensity Difference
a2063901
AC
143 float c1 = (float)M_SQRT2 / sqrtf(1.0f + c*c);
144 float c2 = c * c1;
145 for (icc = 0; icc < 8; icc++) {
146 /*if (PS_BASELINE || ps->icc_mode < 3)*/ {
147 float alpha = 0.5f * acos_icc_invq[icc];
148 float beta = alpha * (c1 - c2) * (float)M_SQRT1_2;
149 HA[iid][icc][0] = c2 * cosf(beta + alpha);
150 HA[iid][icc][1] = c1 * cosf(beta - alpha);
151 HA[iid][icc][2] = c2 * sinf(beta + alpha);
152 HA[iid][icc][3] = c1 * sinf(beta - alpha);
153 } /* else */ {
154 float alpha, gamma, mu, rho;
155 float alpha_c, alpha_s, gamma_c, gamma_s;
156 rho = FFMAX(icc_invq[icc], 0.05f);
157 alpha = 0.5f * atan2f(2.0f * c * rho, c*c - 1.0f);
158 mu = c + 1.0f / c;
159 mu = sqrtf(1 + (4 * rho * rho - 4)/(mu * mu));
160 gamma = atanf(sqrtf((1.0f - mu)/(1.0f + mu)));
161 if (alpha < 0) alpha += M_PI/2;
162 alpha_c = cosf(alpha);
163 alpha_s = sinf(alpha);
164 gamma_c = cosf(gamma);
165 gamma_s = sinf(gamma);
166 HB[iid][icc][0] = M_SQRT2 * alpha_c * gamma_c;
167 HB[iid][icc][1] = M_SQRT2 * alpha_s * gamma_c;
168 HB[iid][icc][2] = -M_SQRT2 * alpha_s * gamma_s;
169 HB[iid][icc][3] = M_SQRT2 * alpha_c * gamma_s;
170 }
171 }
172 }
173
174 for (k = 0; k < NR_ALLPASS_BANDS20; k++) {
175 double f_center, theta;
176 if (k < FF_ARRAY_ELEMS(f_center_20))
177 f_center = f_center_20[k] * 0.125;
178 else
179 f_center = k - 6.5f;
180 for (m = 0; m < PS_AP_LINKS; m++) {
181 theta = -M_PI * fractional_delay_links[m] * f_center;
182 Q_fract_allpass[0][k][m][0] = cos(theta);
183 Q_fract_allpass[0][k][m][1] = sin(theta);
184 }
185 theta = -M_PI*fractional_delay_gain*f_center;
186 phi_fract[0][k][0] = cos(theta);
187 phi_fract[0][k][1] = sin(theta);
188 }
189 for (k = 0; k < NR_ALLPASS_BANDS34; k++) {
190 double f_center, theta;
191 if (k < FF_ARRAY_ELEMS(f_center_34))
192 f_center = f_center_34[k] / 24.;
193 else
194 f_center = k - 26.5f;
195 for (m = 0; m < PS_AP_LINKS; m++) {
196 theta = -M_PI * fractional_delay_links[m] * f_center;
197 Q_fract_allpass[1][k][m][0] = cos(theta);
198 Q_fract_allpass[1][k][m][1] = sin(theta);
199 }
200 theta = -M_PI*fractional_delay_gain*f_center;
201 phi_fract[1][k][0] = cos(theta);
202 phi_fract[1][k][1] = sin(theta);
203 }
204
205 make_filters_from_proto(f20_0_8, g0_Q8, 8);
206 make_filters_from_proto(f34_0_12, g0_Q12, 12);
207 make_filters_from_proto(f34_1_8, g1_Q8, 8);
208 make_filters_from_proto(f34_2_4, g2_Q4, 4);
209}
210#endif /* CONFIG_HARDCODED_TABLES */
211
fd6eb4a0 212#endif /* AACPS_TABLEGEN_H */