mirror of https://git.ffmpeg.org/ffmpeg.git
101 lines
3.0 KiB
C
101 lines
3.0 KiB
C
|
/*
|
||
|
* AAC decoder
|
||
|
* Copyright (c) 2005-2006 Oded Shimon ( ods15 ods15 dyndns org )
|
||
|
* Copyright (c) 2006-2007 Maxim Gavrilov ( maxim.gavrilov gmail com )
|
||
|
* Copyright (c) 2008-2013 Alex Converse <alex.converse@gmail.com>
|
||
|
*
|
||
|
* AAC LATM decoder
|
||
|
* Copyright (c) 2008-2010 Paul Kendall <paul@kcbbs.gen.nz>
|
||
|
* Copyright (c) 2010 Janne Grunau <janne-libav@jannau.net>
|
||
|
*
|
||
|
* AAC decoder fixed-point implementation
|
||
|
* Copyright (c) 2013
|
||
|
* MIPS Technologies, Inc., California.
|
||
|
*
|
||
|
* This file is part of FFmpeg.
|
||
|
*
|
||
|
* FFmpeg is free software; you can redistribute it and/or
|
||
|
* modify it under the terms of the GNU Lesser General Public
|
||
|
* License as published by the Free Software Foundation; either
|
||
|
* version 2.1 of the License, or (at your option) any later version.
|
||
|
*
|
||
|
* FFmpeg is distributed in the hope that it will be useful,
|
||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
|
* Lesser General Public License for more details.
|
||
|
*
|
||
|
* You should have received a copy of the GNU Lesser General Public
|
||
|
* License along with FFmpeg; if not, write to the Free Software
|
||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||
|
*/
|
||
|
|
||
|
#ifndef AVCODEC_AAC_AACDEC_FLOAT_PREDICTION_H
|
||
|
#define AVCODEC_AAC_AACDEC_FLOAT_PREDICTION_H
|
||
|
|
||
|
static av_always_inline float flt16_round(float pf)
|
||
|
{
|
||
|
union av_intfloat32 tmp;
|
||
|
tmp.f = pf;
|
||
|
tmp.i = (tmp.i + 0x00008000U) & 0xFFFF0000U;
|
||
|
return tmp.f;
|
||
|
}
|
||
|
|
||
|
static av_always_inline float flt16_even(float pf)
|
||
|
{
|
||
|
union av_intfloat32 tmp;
|
||
|
tmp.f = pf;
|
||
|
tmp.i = (tmp.i + 0x00007FFFU + (tmp.i & 0x00010000U >> 16)) & 0xFFFF0000U;
|
||
|
return tmp.f;
|
||
|
}
|
||
|
|
||
|
static av_always_inline float flt16_trunc(float pf)
|
||
|
{
|
||
|
union av_intfloat32 pun;
|
||
|
pun.f = pf;
|
||
|
pun.i &= 0xFFFF0000U;
|
||
|
return pun.f;
|
||
|
}
|
||
|
|
||
|
static av_always_inline void predict(PredictorState *ps, float *coef,
|
||
|
int output_enable)
|
||
|
{
|
||
|
const float a = 0.953125; // 61.0 / 64
|
||
|
const float alpha = 0.90625; // 29.0 / 32
|
||
|
float e0, e1;
|
||
|
float pv;
|
||
|
float k1, k2;
|
||
|
float r0 = ps->r0, r1 = ps->r1;
|
||
|
float cor0 = ps->cor0, cor1 = ps->cor1;
|
||
|
float var0 = ps->var0, var1 = ps->var1;
|
||
|
|
||
|
k1 = var0 > 1 ? cor0 * flt16_even(a / var0) : 0;
|
||
|
k2 = var1 > 1 ? cor1 * flt16_even(a / var1) : 0;
|
||
|
|
||
|
pv = flt16_round(k1 * r0 + k2 * r1);
|
||
|
if (output_enable)
|
||
|
*coef += pv;
|
||
|
|
||
|
e0 = *coef;
|
||
|
e1 = e0 - k1 * r0;
|
||
|
|
||
|
ps->cor1 = flt16_trunc(alpha * cor1 + r1 * e1);
|
||
|
ps->var1 = flt16_trunc(alpha * var1 + 0.5f * (r1 * r1 + e1 * e1));
|
||
|
ps->cor0 = flt16_trunc(alpha * cor0 + r0 * e0);
|
||
|
ps->var0 = flt16_trunc(alpha * var0 + 0.5f * (r0 * r0 + e0 * e0));
|
||
|
|
||
|
ps->r1 = flt16_trunc(a * (r0 - k1 * e0));
|
||
|
ps->r0 = flt16_trunc(a * e0);
|
||
|
}
|
||
|
|
||
|
static av_always_inline void reset_predict_state(PredictorState *ps)
|
||
|
{
|
||
|
ps->r0 = 0.0f;
|
||
|
ps->r1 = 0.0f;
|
||
|
ps->cor0 = 0.0f;
|
||
|
ps->cor1 = 0.0f;
|
||
|
ps->var0 = 1.0f;
|
||
|
ps->var1 = 1.0f;
|
||
|
}
|
||
|
|
||
|
#endif /* AVCODEC_AAC_AACDEC_FLOAT_PREDICTION_H */
|