2 ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding
3 ** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License as published by
7 ** the Free Software Foundation; either version 2 of the License, or
8 ** (at your option) any later version.
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU General Public License for more details.
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 ** Any non-GPL usage of this software or parts of this software is strictly
22 ** Commercial non-GPL licensing of this software is possible.
23 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
25 ** Initially modified for use with MPlayer by Arpad Gereöffy on 2003/08/30
26 ** $Id: sbr_hfgen.c,v 1.3 2004/06/02 22:59:03 diego Exp $
27 ** detailed CVS changelog at http://www.mplayerhq.hu/cgi-bin/cvsweb.cgi/main/
30 /* High Frequency generation */
37 #include "sbr_syntax.h"
38 #include "sbr_hfgen.h"
42 /* static function declarations */
43 static void calc_prediction_coef(sbr_info
*sbr
, qmf_t Xlow
[MAX_NTSRHFG
][32],
44 complex_t
*alpha_0
, complex_t
*alpha_1
50 static void calc_aliasing_degree(sbr_info
*sbr
, real_t
*rxx
, real_t
*deg
);
52 static void calc_chirp_factors(sbr_info
*sbr
, uint8_t ch
);
53 static void patch_construction(sbr_info
*sbr
);
56 void hf_generation(sbr_info
*sbr
, qmf_t Xlow
[MAX_NTSRHFG
][32],
57 qmf_t Xhigh
[MAX_NTSRHFG
][64]
64 ALIGN complex_t alpha_0
[64], alpha_1
[64];
69 uint8_t offset
= sbr
->tHFAdj
;
70 uint8_t first
= sbr
->t_E
[ch
][0];
71 uint8_t last
= sbr
->t_E
[ch
][sbr
->L_E
[ch
]];
73 // printf("%d %d\n", first, last);
75 calc_chirp_factors(sbr
, ch
);
77 for (i
= first
; i
< last
; i
++)
79 memset(Xhigh
[i
+ offset
], 0, 64 * sizeof(qmf_t
));
82 if ((ch
== 0) && (sbr
->Reset
))
83 patch_construction(sbr
);
85 /* calculate the prediction coefficients */
86 calc_prediction_coef(sbr
, Xlow
, alpha_0
, alpha_1
93 calc_aliasing_degree(sbr
, rxx
, deg
);
96 /* actual HF generation */
97 for (i
= 0; i
< sbr
->noPatches
; i
++)
99 for (x
= 0; x
< sbr
->patchNoSubbands
[i
]; x
++)
105 /* find the low and high band for patching */
107 for (q
= 0; q
< i
; q
++)
109 k
+= sbr
->patchNoSubbands
[q
];
111 p
= sbr
->patchStartSubband
[i
] + x
;
114 if (x
!= 0 /*x < sbr->patchNoSubbands[i]-1*/)
120 g
= sbr
->table_map_k_to_g
[k
];
122 bw
= sbr
->bwArray
[ch
][g
];
125 /* do the patching */
126 /* with or without filtering */
129 RE(a0
) = MUL_C(RE(alpha_0
[p
]), bw
);
130 RE(a1
) = MUL_C(RE(alpha_1
[p
]), bw2
);
131 #ifndef SBR_LOW_POWER
132 IM(a0
) = MUL_C(IM(alpha_0
[p
]), bw
);
133 IM(a1
) = MUL_C(IM(alpha_1
[p
]), bw2
);
136 for (l
= first
; l
< last
; l
++)
138 QMF_RE(Xhigh
[l
+ offset
][k
]) = QMF_RE(Xlow
[l
+ offset
][p
]);
139 #ifndef SBR_LOW_POWER
140 QMF_IM(Xhigh
[l
+ offset
][k
]) = QMF_IM(Xlow
[l
+ offset
][p
]);
144 QMF_RE(Xhigh
[l
+ offset
][k
]) += (
145 MUL_R(RE(a0
), QMF_RE(Xlow
[l
- 1 + offset
][p
])) +
146 MUL_R(RE(a1
), QMF_RE(Xlow
[l
- 2 + offset
][p
])));
148 QMF_RE(Xhigh
[l
+ offset
][k
]) += (
149 RE(a0
) * QMF_RE(Xlow
[l
- 1 + offset
][p
]) -
150 IM(a0
) * QMF_IM(Xlow
[l
- 1 + offset
][p
]) +
151 RE(a1
) * QMF_RE(Xlow
[l
- 2 + offset
][p
]) -
152 IM(a1
) * QMF_IM(Xlow
[l
- 2 + offset
][p
]));
153 QMF_IM(Xhigh
[l
+ offset
][k
]) += (
154 IM(a0
) * QMF_RE(Xlow
[l
- 1 + offset
][p
]) +
155 RE(a0
) * QMF_IM(Xlow
[l
- 1 + offset
][p
]) +
156 IM(a1
) * QMF_RE(Xlow
[l
- 2 + offset
][p
]) +
157 RE(a1
) * QMF_IM(Xlow
[l
- 2 + offset
][p
]));
161 for (l
= first
; l
< last
; l
++)
163 QMF_RE(Xhigh
[l
+ offset
][k
]) = QMF_RE(Xlow
[l
+ offset
][p
]);
164 #ifndef SBR_LOW_POWER
165 QMF_IM(Xhigh
[l
+ offset
][k
]) = QMF_IM(Xlow
[l
+ offset
][p
]);
174 limiter_frequency_table(sbr
);
188 #define SBR_ABS(A) ((A) < 0) ? -(A) : (A)
191 static void auto_correlation(sbr_info
*sbr
, acorr_coef
*ac
,
192 qmf_t buffer
[MAX_NTSRHFG
][32],
193 uint8_t bd
, uint8_t len
)
195 real_t r01
= 0, r02
= 0, r11
= 0;
197 uint8_t offset
= sbr
->tHFAdj
;
198 const real_t rel
= 1 / (1 + 1e-6f
);
201 for (j
= offset
; j
< len
+ offset
; j
++)
203 r01
+= QMF_RE(buffer
[j
][bd
]) * QMF_RE(buffer
[j
-1][bd
]);
204 r02
+= QMF_RE(buffer
[j
][bd
]) * QMF_RE(buffer
[j
-2][bd
]);
205 r11
+= QMF_RE(buffer
[j
-1][bd
]) * QMF_RE(buffer
[j
-1][bd
]);
208 QMF_RE(buffer
[len
+offset
-1][bd
]) * QMF_RE(buffer
[len
+offset
-2][bd
]) +
209 QMF_RE(buffer
[offset
-1][bd
]) * QMF_RE(buffer
[offset
-2][bd
]);
211 QMF_RE(buffer
[len
+offset
-2][bd
]) * QMF_RE(buffer
[len
+offset
-2][bd
]) +
212 QMF_RE(buffer
[offset
-2][bd
]) * QMF_RE(buffer
[offset
-2][bd
]);
217 ac
->det
= MUL_R(RE(ac
->r11
), RE(ac
->r22
)) - MUL_C(MUL_R(RE(ac
->r12
), RE(ac
->r12
)), rel
);
220 static void auto_correlation(sbr_info
*sbr
, acorr_coef
*ac
, qmf_t buffer
[MAX_NTSRHFG
][32],
221 uint8_t bd
, uint8_t len
)
223 real_t r01r
= 0, r01i
= 0, r02r
= 0, r02i
= 0, r11r
= 0;
224 const real_t rel
= 1 / (1 + 1e-6f
);
226 uint8_t offset
= sbr
->tHFAdj
;
229 for (j
= offset
; j
< len
+ offset
; j
++)
231 r01r
+= QMF_RE(buffer
[j
][bd
]) * QMF_RE(buffer
[j
-1][bd
]) +
232 QMF_IM(buffer
[j
][bd
]) * QMF_IM(buffer
[j
-1][bd
]);
233 r01i
+= QMF_IM(buffer
[j
][bd
]) * QMF_RE(buffer
[j
-1][bd
]) -
234 QMF_RE(buffer
[j
][bd
]) * QMF_IM(buffer
[j
-1][bd
]);
235 r02r
+= QMF_RE(buffer
[j
][bd
]) * QMF_RE(buffer
[j
-2][bd
]) +
236 QMF_IM(buffer
[j
][bd
]) * QMF_IM(buffer
[j
-2][bd
]);
237 r02i
+= QMF_IM(buffer
[j
][bd
]) * QMF_RE(buffer
[j
-2][bd
]) -
238 QMF_RE(buffer
[j
][bd
]) * QMF_IM(buffer
[j
-2][bd
]);
239 r11r
+= QMF_RE(buffer
[j
-1][bd
]) * QMF_RE(buffer
[j
-1][bd
]) +
240 QMF_IM(buffer
[j
-1][bd
]) * QMF_IM(buffer
[j
-1][bd
]);
250 (QMF_RE(buffer
[len
+offset
-1][bd
]) * QMF_RE(buffer
[len
+offset
-2][bd
]) + QMF_IM(buffer
[len
+offset
-1][bd
]) * QMF_IM(buffer
[len
+offset
-2][bd
])) +
251 (QMF_RE(buffer
[offset
-1][bd
]) * QMF_RE(buffer
[offset
-2][bd
]) + QMF_IM(buffer
[offset
-1][bd
]) * QMF_IM(buffer
[offset
-2][bd
]));
253 (QMF_IM(buffer
[len
+offset
-1][bd
]) * QMF_RE(buffer
[len
+offset
-2][bd
]) - QMF_RE(buffer
[len
+offset
-1][bd
]) * QMF_IM(buffer
[len
+offset
-2][bd
])) +
254 (QMF_IM(buffer
[offset
-1][bd
]) * QMF_RE(buffer
[offset
-2][bd
]) - QMF_RE(buffer
[offset
-1][bd
]) * QMF_IM(buffer
[offset
-2][bd
]));
256 (QMF_RE(buffer
[len
+offset
-2][bd
]) * QMF_RE(buffer
[len
+offset
-2][bd
]) + QMF_IM(buffer
[len
+offset
-2][bd
]) * QMF_IM(buffer
[len
+offset
-2][bd
])) +
257 (QMF_RE(buffer
[offset
-2][bd
]) * QMF_RE(buffer
[offset
-2][bd
]) + QMF_IM(buffer
[offset
-2][bd
]) * QMF_IM(buffer
[offset
-2][bd
]));
259 ac
->det
= RE(ac
->r11
) * RE(ac
->r22
) - rel
* (RE(ac
->r12
) * RE(ac
->r12
) + IM(ac
->r12
) * IM(ac
->r12
));
263 /* calculate linear prediction coefficients using the covariance method */
264 static void calc_prediction_coef(sbr_info
*sbr
, qmf_t Xlow
[MAX_NTSRHFG
][32],
265 complex_t
*alpha_0
, complex_t
*alpha_1
275 for (k
= 1; k
< sbr
->f_master
[0]; k
++)
277 auto_correlation(sbr
, &ac
, Xlow
, k
, sbr
->numTimeSlotsRate
+ 6);
284 tmp
= MUL_R(RE(ac
.r01
), RE(ac
.r12
)) - MUL_R(RE(ac
.r02
), RE(ac
.r11
));
285 RE(alpha_1
[k
]) = SBR_DIV(tmp
, ac
.det
);
292 tmp
= RE(ac
.r01
) + MUL_R(RE(alpha_1
[k
]), RE(ac
.r12
));
293 RE(alpha_0
[k
]) = -SBR_DIV(tmp
, RE(ac
.r11
));
296 if ((RE(alpha_0
[k
]) >= REAL_CONST(4)) || (RE(alpha_1
[k
]) >= REAL_CONST(4)))
298 RE(alpha_0
[k
]) = REAL_CONST(0);
299 RE(alpha_1
[k
]) = REAL_CONST(0);
302 /* reflection coefficient */
305 rxx
[k
] = REAL_CONST(0.0);
307 rxx
[k
] = -SBR_DIV(RE(ac
.r01
), RE(ac
.r11
));
308 if (rxx
[k
] > REAL_CONST(1.0)) rxx
[k
] = REAL_CONST(1.0);
309 if (rxx
[k
] < REAL_CONST(-1.0)) rxx
[k
] = REAL_CONST(-1.0);
317 tmp
= REAL_CONST(1.0) / ac
.det
;
318 RE(alpha_1
[k
]) = (RE(ac
.r01
) * RE(ac
.r12
) - IM(ac
.r01
) * IM(ac
.r12
) - RE(ac
.r02
) * RE(ac
.r11
)) * tmp
;
319 IM(alpha_1
[k
]) = (IM(ac
.r01
) * RE(ac
.r12
) + RE(ac
.r01
) * IM(ac
.r12
) - IM(ac
.r02
) * RE(ac
.r11
)) * tmp
;
327 tmp
= 1.0f
/ RE(ac
.r11
);
328 RE(alpha_0
[k
]) = -(RE(ac
.r01
) + RE(alpha_1
[k
]) * RE(ac
.r12
) + IM(alpha_1
[k
]) * IM(ac
.r12
)) * tmp
;
329 IM(alpha_0
[k
]) = -(IM(ac
.r01
) + IM(alpha_1
[k
]) * RE(ac
.r12
) - RE(alpha_1
[k
]) * IM(ac
.r12
)) * tmp
;
332 if ((RE(alpha_0
[k
])*RE(alpha_0
[k
]) + IM(alpha_0
[k
])*IM(alpha_0
[k
]) >= 16) ||
333 (RE(alpha_1
[k
])*RE(alpha_1
[k
]) + IM(alpha_1
[k
])*IM(alpha_1
[k
]) >= 16))
345 static void calc_aliasing_degree(sbr_info
*sbr
, real_t
*rxx
, real_t
*deg
)
349 rxx
[0] = REAL_CONST(0.0);
350 deg
[1] = REAL_CONST(0.0);
352 for (k
= 2; k
< sbr
->k0
; k
++)
356 if ((k
% 2 == 0) && (rxx
[k
] < REAL_CONST(0.0)))
360 deg
[k
] = REAL_CONST(1.0);
362 if (rxx
[k
-2] > REAL_CONST(0.0))
364 deg
[k
-1] = REAL_CONST(1.0) - MUL_R(rxx
[k
-1], rxx
[k
-1]);
366 } else if (rxx
[k
-2] > REAL_CONST(0.0)) {
367 deg
[k
] = REAL_CONST(1.0) - MUL_R(rxx
[k
-1], rxx
[k
-1]);
371 if ((k
% 2 == 1) && (rxx
[k
] > REAL_CONST(0.0)))
373 if (rxx
[k
-1] > REAL_CONST(0.0))
375 deg
[k
] = REAL_CONST(1.0);
377 if (rxx
[k
-2] < REAL_CONST(0.0))
379 deg
[k
-1] = REAL_CONST(1.0) - MUL_R(rxx
[k
-1], rxx
[k
-1]);
381 } else if (rxx
[k
-2] < REAL_CONST(0.0)) {
382 deg
[k
] = REAL_CONST(1.0) - MUL_R(rxx
[k
-1], rxx
[k
-1]);
389 /* FIXED POINT: bwArray = COEF */
390 static real_t
mapNewBw(uint8_t invf_mode
, uint8_t invf_mode_prev
)
395 if (invf_mode_prev
== 0) /* NONE */
396 return COEF_CONST(0.6);
398 return COEF_CONST(0.75);
401 return COEF_CONST(0.9);
404 return COEF_CONST(0.98);
407 if (invf_mode_prev
== 1) /* LOW */
408 return COEF_CONST(0.6);
410 return COEF_CONST(0.0);
414 /* FIXED POINT: bwArray = COEF */
415 static void calc_chirp_factors(sbr_info
*sbr
, uint8_t ch
)
419 for (i
= 0; i
< sbr
->N_Q
; i
++)
421 sbr
->bwArray
[ch
][i
] = mapNewBw(sbr
->bs_invf_mode
[ch
][i
], sbr
->bs_invf_mode_prev
[ch
][i
]);
423 if (sbr
->bwArray
[ch
][i
] < sbr
->bwArray_prev
[ch
][i
])
424 sbr
->bwArray
[ch
][i
] = MUL_F(sbr
->bwArray
[ch
][i
], FRAC_CONST(0.75)) + MUL_F(sbr
->bwArray_prev
[ch
][i
], FRAC_CONST(0.25));
426 sbr
->bwArray
[ch
][i
] = MUL_F(sbr
->bwArray
[ch
][i
], FRAC_CONST(0.90625)) + MUL_F(sbr
->bwArray_prev
[ch
][i
], FRAC_CONST(0.09375));
428 if (sbr
->bwArray
[ch
][i
] < COEF_CONST(0.015625))
429 sbr
->bwArray
[ch
][i
] = COEF_CONST(0.0);
431 if (sbr
->bwArray
[ch
][i
] >= COEF_CONST(0.99609375))
432 sbr
->bwArray
[ch
][i
] = COEF_CONST(0.99609375);
434 sbr
->bwArray_prev
[ch
][i
] = sbr
->bwArray
[ch
][i
];
435 sbr
->bs_invf_mode_prev
[ch
][i
] = sbr
->bs_invf_mode
[ch
][i
];
439 static void patch_construction(sbr_info
*sbr
)
443 uint8_t msb
= sbr
->k0
;
444 uint8_t usb
= sbr
->kx
;
445 uint8_t goalSbTab
[] = { 21, 23, 43, 46, 64, 85, 93, 128, 0, 0, 0 };
446 /* (uint8_t)(2.048e6/sbr->sample_rate + 0.5); */
447 uint8_t goalSb
= goalSbTab
[get_sr_index(sbr
->sample_rate
)];
451 if (goalSb
< (sbr
->kx
+ sbr
->M
))
453 for (i
= 0, k
= 0; sbr
->f_master
[i
] < goalSb
; i
++)
467 sb
= sbr
->f_master
[j
];
468 odd
= (sb
- 2 + sbr
->k0
) % 2;
469 } while (sb
> (sbr
->k0
- 1 + msb
- odd
));
471 sbr
->patchNoSubbands
[sbr
->noPatches
] = max(sb
- usb
, 0);
472 sbr
->patchStartSubband
[sbr
->noPatches
] = sbr
->k0
- odd
-
473 sbr
->patchNoSubbands
[sbr
->noPatches
];
475 if (sbr
->patchNoSubbands
[sbr
->noPatches
] > 0)
484 if (sbr
->f_master
[k
] - sb
< 3)
486 } while (sb
!= (sbr
->kx
+ sbr
->M
));
488 if ((sbr
->patchNoSubbands
[sbr
->noPatches
-1] < 3) && (sbr
->noPatches
> 1))
493 sbr
->noPatches
= min(sbr
->noPatches
, 5);