| /* |
| * 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 */ |