mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-11-26 19:01:44 +02:00
976a8b2179
* qatar/master: (40 commits) H.264: template left MB handling H.264: faster fill_decode_caches H.264: faster write_back_* H.264: faster fill_filter_caches H.264: make filter_mb_fast support the case of unavailable top mb Do not include log.h in avutil.h Do not include pixfmt.h in avutil.h Do not include rational.h in avutil.h Do not include mathematics.h in avutil.h Do not include intfloat_readwrite.h in avutil.h Remove return statements following infinite loops without break RTSP: Doxygen comment cleanup doxygen: Escape '\' in Doxygen documentation. md5: cosmetics md5: use AV_WL32 to write result md5: add fate test md5: include correct headers md5: fix test program doxygen: Drop array size declarations from Doxygen parameter names. doxygen: Fix parameter names to match the function prototypes. ... Conflicts: libavcodec/x86/dsputil_mmx.c libavformat/flvenc.c libavformat/oggenc.c libavformat/wtv.c Merged-by: Michael Niedermayer <michaelni@gmx.at>
1038 lines
38 KiB
C
1038 lines
38 KiB
C
/*
|
|
* MPEG-4 Parametric Stereo decoding functions
|
|
* Copyright (c) 2010 Alex Converse <alex.converse@gmail.com>
|
|
*
|
|
* 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
|
|
*/
|
|
|
|
#include <stdint.h>
|
|
#include "libavutil/common.h"
|
|
#include "libavutil/mathematics.h"
|
|
#include "avcodec.h"
|
|
#include "get_bits.h"
|
|
#include "aacps.h"
|
|
#include "aacps_tablegen.h"
|
|
#include "aacpsdata.c"
|
|
|
|
#define PS_BASELINE 0 //< Operate in Baseline PS mode
|
|
//< Baseline implies 10 or 20 stereo bands,
|
|
//< mixing mode A, and no ipd/opd
|
|
|
|
#define numQMFSlots 32 //numTimeSlots * RATE
|
|
|
|
static const int8_t num_env_tab[2][4] = {
|
|
{ 0, 1, 2, 4, },
|
|
{ 1, 2, 3, 4, },
|
|
};
|
|
|
|
static const int8_t nr_iidicc_par_tab[] = {
|
|
10, 20, 34, 10, 20, 34,
|
|
};
|
|
|
|
static const int8_t nr_iidopd_par_tab[] = {
|
|
5, 11, 17, 5, 11, 17,
|
|
};
|
|
|
|
enum {
|
|
huff_iid_df1,
|
|
huff_iid_dt1,
|
|
huff_iid_df0,
|
|
huff_iid_dt0,
|
|
huff_icc_df,
|
|
huff_icc_dt,
|
|
huff_ipd_df,
|
|
huff_ipd_dt,
|
|
huff_opd_df,
|
|
huff_opd_dt,
|
|
};
|
|
|
|
static const int huff_iid[] = {
|
|
huff_iid_df0,
|
|
huff_iid_df1,
|
|
huff_iid_dt0,
|
|
huff_iid_dt1,
|
|
};
|
|
|
|
static VLC vlc_ps[10];
|
|
|
|
/**
|
|
* Read Inter-channel Intensity Difference/Inter-Channel Coherence/
|
|
* Inter-channel Phase Difference/Overall Phase Difference parameters from the
|
|
* bitstream.
|
|
*
|
|
* @param avctx contains the current codec context
|
|
* @param gb pointer to the input bitstream
|
|
* @param ps pointer to the Parametric Stereo context
|
|
* @param PAR pointer to the parameter to be read
|
|
* @param e envelope to decode
|
|
* @param dt 1: time delta-coded, 0: frequency delta-coded
|
|
*/
|
|
#define READ_PAR_DATA(PAR, OFFSET, MASK, ERR_CONDITION) \
|
|
static int read_ ## PAR ## _data(AVCodecContext *avctx, GetBitContext *gb, PSContext *ps, \
|
|
int8_t (*PAR)[PS_MAX_NR_IIDICC], int table_idx, int e, int dt) \
|
|
{ \
|
|
int b, num = ps->nr_ ## PAR ## _par; \
|
|
VLC_TYPE (*vlc_table)[2] = vlc_ps[table_idx].table; \
|
|
if (dt) { \
|
|
int e_prev = e ? e - 1 : ps->num_env_old - 1; \
|
|
e_prev = FFMAX(e_prev, 0); \
|
|
for (b = 0; b < num; b++) { \
|
|
int val = PAR[e_prev][b] + get_vlc2(gb, vlc_table, 9, 3) - OFFSET; \
|
|
if (MASK) val &= MASK; \
|
|
PAR[e][b] = val; \
|
|
if (ERR_CONDITION) \
|
|
goto err; \
|
|
} \
|
|
} else { \
|
|
int val = 0; \
|
|
for (b = 0; b < num; b++) { \
|
|
val += get_vlc2(gb, vlc_table, 9, 3) - OFFSET; \
|
|
if (MASK) val &= MASK; \
|
|
PAR[e][b] = val; \
|
|
if (ERR_CONDITION) \
|
|
goto err; \
|
|
} \
|
|
} \
|
|
return 0; \
|
|
err: \
|
|
av_log(avctx, AV_LOG_ERROR, "illegal "#PAR"\n"); \
|
|
return -1; \
|
|
}
|
|
|
|
READ_PAR_DATA(iid, huff_offset[table_idx], 0, FFABS(ps->iid_par[e][b]) > 7 + 8 * ps->iid_quant)
|
|
READ_PAR_DATA(icc, huff_offset[table_idx], 0, ps->icc_par[e][b] > 7U)
|
|
READ_PAR_DATA(ipdopd, 0, 0x07, 0)
|
|
|
|
static int ps_read_extension_data(GetBitContext *gb, PSContext *ps, int ps_extension_id)
|
|
{
|
|
int e;
|
|
int count = get_bits_count(gb);
|
|
|
|
if (ps_extension_id)
|
|
return 0;
|
|
|
|
ps->enable_ipdopd = get_bits1(gb);
|
|
if (ps->enable_ipdopd) {
|
|
for (e = 0; e < ps->num_env; e++) {
|
|
int dt = get_bits1(gb);
|
|
read_ipdopd_data(NULL, gb, ps, ps->ipd_par, dt ? huff_ipd_dt : huff_ipd_df, e, dt);
|
|
dt = get_bits1(gb);
|
|
read_ipdopd_data(NULL, gb, ps, ps->opd_par, dt ? huff_opd_dt : huff_opd_df, e, dt);
|
|
}
|
|
}
|
|
skip_bits1(gb); //reserved_ps
|
|
return get_bits_count(gb) - count;
|
|
}
|
|
|
|
static void ipdopd_reset(int8_t *opd_hist, int8_t *ipd_hist)
|
|
{
|
|
int i;
|
|
for (i = 0; i < PS_MAX_NR_IPDOPD; i++) {
|
|
opd_hist[i] = 0;
|
|
ipd_hist[i] = 0;
|
|
}
|
|
}
|
|
|
|
int ff_ps_read_data(AVCodecContext *avctx, GetBitContext *gb_host, PSContext *ps, int bits_left)
|
|
{
|
|
int e;
|
|
int bit_count_start = get_bits_count(gb_host);
|
|
int header;
|
|
int bits_consumed;
|
|
GetBitContext gbc = *gb_host, *gb = &gbc;
|
|
|
|
header = get_bits1(gb);
|
|
if (header) { //enable_ps_header
|
|
ps->enable_iid = get_bits1(gb);
|
|
if (ps->enable_iid) {
|
|
int iid_mode = get_bits(gb, 3);
|
|
if (iid_mode > 5) {
|
|
av_log(avctx, AV_LOG_ERROR, "iid_mode %d is reserved.\n",
|
|
iid_mode);
|
|
goto err;
|
|
}
|
|
ps->nr_iid_par = nr_iidicc_par_tab[iid_mode];
|
|
ps->iid_quant = iid_mode > 2;
|
|
ps->nr_ipdopd_par = nr_iidopd_par_tab[iid_mode];
|
|
}
|
|
ps->enable_icc = get_bits1(gb);
|
|
if (ps->enable_icc) {
|
|
ps->icc_mode = get_bits(gb, 3);
|
|
if (ps->icc_mode > 5) {
|
|
av_log(avctx, AV_LOG_ERROR, "icc_mode %d is reserved.\n",
|
|
ps->icc_mode);
|
|
goto err;
|
|
}
|
|
ps->nr_icc_par = nr_iidicc_par_tab[ps->icc_mode];
|
|
}
|
|
ps->enable_ext = get_bits1(gb);
|
|
}
|
|
|
|
ps->frame_class = get_bits1(gb);
|
|
ps->num_env_old = ps->num_env;
|
|
ps->num_env = num_env_tab[ps->frame_class][get_bits(gb, 2)];
|
|
|
|
ps->border_position[0] = -1;
|
|
if (ps->frame_class) {
|
|
for (e = 1; e <= ps->num_env; e++)
|
|
ps->border_position[e] = get_bits(gb, 5);
|
|
} else
|
|
for (e = 1; e <= ps->num_env; e++)
|
|
ps->border_position[e] = (e * numQMFSlots >> ff_log2_tab[ps->num_env]) - 1;
|
|
|
|
if (ps->enable_iid) {
|
|
for (e = 0; e < ps->num_env; e++) {
|
|
int dt = get_bits1(gb);
|
|
if (read_iid_data(avctx, gb, ps, ps->iid_par, huff_iid[2*dt+ps->iid_quant], e, dt))
|
|
goto err;
|
|
}
|
|
} else
|
|
memset(ps->iid_par, 0, sizeof(ps->iid_par));
|
|
|
|
if (ps->enable_icc)
|
|
for (e = 0; e < ps->num_env; e++) {
|
|
int dt = get_bits1(gb);
|
|
if (read_icc_data(avctx, gb, ps, ps->icc_par, dt ? huff_icc_dt : huff_icc_df, e, dt))
|
|
goto err;
|
|
}
|
|
else
|
|
memset(ps->icc_par, 0, sizeof(ps->icc_par));
|
|
|
|
if (ps->enable_ext) {
|
|
int cnt = get_bits(gb, 4);
|
|
if (cnt == 15) {
|
|
cnt += get_bits(gb, 8);
|
|
}
|
|
cnt *= 8;
|
|
while (cnt > 7) {
|
|
int ps_extension_id = get_bits(gb, 2);
|
|
cnt -= 2 + ps_read_extension_data(gb, ps, ps_extension_id);
|
|
}
|
|
if (cnt < 0) {
|
|
av_log(avctx, AV_LOG_ERROR, "ps extension overflow %d", cnt);
|
|
goto err;
|
|
}
|
|
skip_bits(gb, cnt);
|
|
}
|
|
|
|
ps->enable_ipdopd &= !PS_BASELINE;
|
|
|
|
//Fix up envelopes
|
|
if (!ps->num_env || ps->border_position[ps->num_env] < numQMFSlots - 1) {
|
|
//Create a fake envelope
|
|
int source = ps->num_env ? ps->num_env - 1 : ps->num_env_old - 1;
|
|
if (source >= 0 && source != ps->num_env) {
|
|
if (ps->enable_iid) {
|
|
memcpy(ps->iid_par+ps->num_env, ps->iid_par+source, sizeof(ps->iid_par[0]));
|
|
}
|
|
if (ps->enable_icc) {
|
|
memcpy(ps->icc_par+ps->num_env, ps->icc_par+source, sizeof(ps->icc_par[0]));
|
|
}
|
|
if (ps->enable_ipdopd) {
|
|
memcpy(ps->ipd_par+ps->num_env, ps->ipd_par+source, sizeof(ps->ipd_par[0]));
|
|
memcpy(ps->opd_par+ps->num_env, ps->opd_par+source, sizeof(ps->opd_par[0]));
|
|
}
|
|
}
|
|
ps->num_env++;
|
|
ps->border_position[ps->num_env] = numQMFSlots - 1;
|
|
}
|
|
|
|
|
|
ps->is34bands_old = ps->is34bands;
|
|
if (!PS_BASELINE && (ps->enable_iid || ps->enable_icc))
|
|
ps->is34bands = (ps->enable_iid && ps->nr_iid_par == 34) ||
|
|
(ps->enable_icc && ps->nr_icc_par == 34);
|
|
|
|
//Baseline
|
|
if (!ps->enable_ipdopd) {
|
|
memset(ps->ipd_par, 0, sizeof(ps->ipd_par));
|
|
memset(ps->opd_par, 0, sizeof(ps->opd_par));
|
|
}
|
|
|
|
if (header)
|
|
ps->start = 1;
|
|
|
|
bits_consumed = get_bits_count(gb) - bit_count_start;
|
|
if (bits_consumed <= bits_left) {
|
|
skip_bits_long(gb_host, bits_consumed);
|
|
return bits_consumed;
|
|
}
|
|
av_log(avctx, AV_LOG_ERROR, "Expected to read %d PS bits actually read %d.\n", bits_left, bits_consumed);
|
|
err:
|
|
ps->start = 0;
|
|
skip_bits_long(gb_host, bits_left);
|
|
return bits_left;
|
|
}
|
|
|
|
/** Split one subband into 2 subsubbands with a symmetric real filter.
|
|
* The filter must have its non-center even coefficients equal to zero. */
|
|
static void hybrid2_re(float (*in)[2], float (*out)[32][2], const float filter[7], int len, int reverse)
|
|
{
|
|
int i, j;
|
|
for (i = 0; i < len; i++, in++) {
|
|
float re_in = filter[6] * in[6][0]; //real inphase
|
|
float re_op = 0.0f; //real out of phase
|
|
float im_in = filter[6] * in[6][1]; //imag inphase
|
|
float im_op = 0.0f; //imag out of phase
|
|
for (j = 0; j < 6; j += 2) {
|
|
re_op += filter[j+1] * (in[j+1][0] + in[12-j-1][0]);
|
|
im_op += filter[j+1] * (in[j+1][1] + in[12-j-1][1]);
|
|
}
|
|
out[ reverse][i][0] = re_in + re_op;
|
|
out[ reverse][i][1] = im_in + im_op;
|
|
out[!reverse][i][0] = re_in - re_op;
|
|
out[!reverse][i][1] = im_in - im_op;
|
|
}
|
|
}
|
|
|
|
/** Split one subband into 6 subsubbands with a complex filter */
|
|
static void hybrid6_cx(float (*in)[2], float (*out)[32][2], const float (*filter)[7][2], int len)
|
|
{
|
|
int i, j, ssb;
|
|
int N = 8;
|
|
float temp[8][2];
|
|
|
|
for (i = 0; i < len; i++, in++) {
|
|
for (ssb = 0; ssb < N; ssb++) {
|
|
float sum_re = filter[ssb][6][0] * in[6][0], sum_im = filter[ssb][6][0] * in[6][1];
|
|
for (j = 0; j < 6; j++) {
|
|
float in0_re = in[j][0];
|
|
float in0_im = in[j][1];
|
|
float in1_re = in[12-j][0];
|
|
float in1_im = in[12-j][1];
|
|
sum_re += filter[ssb][j][0] * (in0_re + in1_re) - filter[ssb][j][1] * (in0_im - in1_im);
|
|
sum_im += filter[ssb][j][0] * (in0_im + in1_im) + filter[ssb][j][1] * (in0_re - in1_re);
|
|
}
|
|
temp[ssb][0] = sum_re;
|
|
temp[ssb][1] = sum_im;
|
|
}
|
|
out[0][i][0] = temp[6][0];
|
|
out[0][i][1] = temp[6][1];
|
|
out[1][i][0] = temp[7][0];
|
|
out[1][i][1] = temp[7][1];
|
|
out[2][i][0] = temp[0][0];
|
|
out[2][i][1] = temp[0][1];
|
|
out[3][i][0] = temp[1][0];
|
|
out[3][i][1] = temp[1][1];
|
|
out[4][i][0] = temp[2][0] + temp[5][0];
|
|
out[4][i][1] = temp[2][1] + temp[5][1];
|
|
out[5][i][0] = temp[3][0] + temp[4][0];
|
|
out[5][i][1] = temp[3][1] + temp[4][1];
|
|
}
|
|
}
|
|
|
|
static void hybrid4_8_12_cx(float (*in)[2], float (*out)[32][2], const float (*filter)[7][2], int N, int len)
|
|
{
|
|
int i, j, ssb;
|
|
|
|
for (i = 0; i < len; i++, in++) {
|
|
for (ssb = 0; ssb < N; ssb++) {
|
|
float sum_re = filter[ssb][6][0] * in[6][0], sum_im = filter[ssb][6][0] * in[6][1];
|
|
for (j = 0; j < 6; j++) {
|
|
float in0_re = in[j][0];
|
|
float in0_im = in[j][1];
|
|
float in1_re = in[12-j][0];
|
|
float in1_im = in[12-j][1];
|
|
sum_re += filter[ssb][j][0] * (in0_re + in1_re) - filter[ssb][j][1] * (in0_im - in1_im);
|
|
sum_im += filter[ssb][j][0] * (in0_im + in1_im) + filter[ssb][j][1] * (in0_re - in1_re);
|
|
}
|
|
out[ssb][i][0] = sum_re;
|
|
out[ssb][i][1] = sum_im;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void hybrid_analysis(float out[91][32][2], float in[5][44][2], float L[2][38][64], int is34, int len)
|
|
{
|
|
int i, j;
|
|
for (i = 0; i < 5; i++) {
|
|
for (j = 0; j < 38; j++) {
|
|
in[i][j+6][0] = L[0][j][i];
|
|
in[i][j+6][1] = L[1][j][i];
|
|
}
|
|
}
|
|
if (is34) {
|
|
hybrid4_8_12_cx(in[0], out, f34_0_12, 12, len);
|
|
hybrid4_8_12_cx(in[1], out+12, f34_1_8, 8, len);
|
|
hybrid4_8_12_cx(in[2], out+20, f34_2_4, 4, len);
|
|
hybrid4_8_12_cx(in[3], out+24, f34_2_4, 4, len);
|
|
hybrid4_8_12_cx(in[4], out+28, f34_2_4, 4, len);
|
|
for (i = 0; i < 59; i++) {
|
|
for (j = 0; j < len; j++) {
|
|
out[i+32][j][0] = L[0][j][i+5];
|
|
out[i+32][j][1] = L[1][j][i+5];
|
|
}
|
|
}
|
|
} else {
|
|
hybrid6_cx(in[0], out, f20_0_8, len);
|
|
hybrid2_re(in[1], out+6, g1_Q2, len, 1);
|
|
hybrid2_re(in[2], out+8, g1_Q2, len, 0);
|
|
for (i = 0; i < 61; i++) {
|
|
for (j = 0; j < len; j++) {
|
|
out[i+10][j][0] = L[0][j][i+3];
|
|
out[i+10][j][1] = L[1][j][i+3];
|
|
}
|
|
}
|
|
}
|
|
//update in_buf
|
|
for (i = 0; i < 5; i++) {
|
|
memcpy(in[i], in[i]+32, 6 * sizeof(in[i][0]));
|
|
}
|
|
}
|
|
|
|
static void hybrid_synthesis(float out[2][38][64], float in[91][32][2], int is34, int len)
|
|
{
|
|
int i, n;
|
|
if (is34) {
|
|
for (n = 0; n < len; n++) {
|
|
memset(out[0][n], 0, 5*sizeof(out[0][n][0]));
|
|
memset(out[1][n], 0, 5*sizeof(out[1][n][0]));
|
|
for (i = 0; i < 12; i++) {
|
|
out[0][n][0] += in[ i][n][0];
|
|
out[1][n][0] += in[ i][n][1];
|
|
}
|
|
for (i = 0; i < 8; i++) {
|
|
out[0][n][1] += in[12+i][n][0];
|
|
out[1][n][1] += in[12+i][n][1];
|
|
}
|
|
for (i = 0; i < 4; i++) {
|
|
out[0][n][2] += in[20+i][n][0];
|
|
out[1][n][2] += in[20+i][n][1];
|
|
out[0][n][3] += in[24+i][n][0];
|
|
out[1][n][3] += in[24+i][n][1];
|
|
out[0][n][4] += in[28+i][n][0];
|
|
out[1][n][4] += in[28+i][n][1];
|
|
}
|
|
}
|
|
for (i = 0; i < 59; i++) {
|
|
for (n = 0; n < len; n++) {
|
|
out[0][n][i+5] = in[i+32][n][0];
|
|
out[1][n][i+5] = in[i+32][n][1];
|
|
}
|
|
}
|
|
} else {
|
|
for (n = 0; n < len; n++) {
|
|
out[0][n][0] = in[0][n][0] + in[1][n][0] + in[2][n][0] +
|
|
in[3][n][0] + in[4][n][0] + in[5][n][0];
|
|
out[1][n][0] = in[0][n][1] + in[1][n][1] + in[2][n][1] +
|
|
in[3][n][1] + in[4][n][1] + in[5][n][1];
|
|
out[0][n][1] = in[6][n][0] + in[7][n][0];
|
|
out[1][n][1] = in[6][n][1] + in[7][n][1];
|
|
out[0][n][2] = in[8][n][0] + in[9][n][0];
|
|
out[1][n][2] = in[8][n][1] + in[9][n][1];
|
|
}
|
|
for (i = 0; i < 61; i++) {
|
|
for (n = 0; n < len; n++) {
|
|
out[0][n][i+3] = in[i+10][n][0];
|
|
out[1][n][i+3] = in[i+10][n][1];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// All-pass filter decay slope
|
|
#define DECAY_SLOPE 0.05f
|
|
/// Number of frequency bands that can be addressed by the parameter index, b(k)
|
|
static const int NR_PAR_BANDS[] = { 20, 34 };
|
|
/// Number of frequency bands that can be addressed by the sub subband index, k
|
|
static const int NR_BANDS[] = { 71, 91 };
|
|
/// Start frequency band for the all-pass filter decay slope
|
|
static const int DECAY_CUTOFF[] = { 10, 32 };
|
|
/// Number of all-pass filer bands
|
|
static const int NR_ALLPASS_BANDS[] = { 30, 50 };
|
|
/// First stereo band using the short one sample delay
|
|
static const int SHORT_DELAY_BAND[] = { 42, 62 };
|
|
|
|
/** Table 8.46 */
|
|
static void map_idx_10_to_20(int8_t *par_mapped, const int8_t *par, int full)
|
|
{
|
|
int b;
|
|
if (full)
|
|
b = 9;
|
|
else {
|
|
b = 4;
|
|
par_mapped[10] = 0;
|
|
}
|
|
for (; b >= 0; b--) {
|
|
par_mapped[2*b+1] = par_mapped[2*b] = par[b];
|
|
}
|
|
}
|
|
|
|
static void map_idx_34_to_20(int8_t *par_mapped, const int8_t *par, int full)
|
|
{
|
|
par_mapped[ 0] = (2*par[ 0] + par[ 1]) / 3;
|
|
par_mapped[ 1] = ( par[ 1] + 2*par[ 2]) / 3;
|
|
par_mapped[ 2] = (2*par[ 3] + par[ 4]) / 3;
|
|
par_mapped[ 3] = ( par[ 4] + 2*par[ 5]) / 3;
|
|
par_mapped[ 4] = ( par[ 6] + par[ 7]) / 2;
|
|
par_mapped[ 5] = ( par[ 8] + par[ 9]) / 2;
|
|
par_mapped[ 6] = par[10];
|
|
par_mapped[ 7] = par[11];
|
|
par_mapped[ 8] = ( par[12] + par[13]) / 2;
|
|
par_mapped[ 9] = ( par[14] + par[15]) / 2;
|
|
par_mapped[10] = par[16];
|
|
if (full) {
|
|
par_mapped[11] = par[17];
|
|
par_mapped[12] = par[18];
|
|
par_mapped[13] = par[19];
|
|
par_mapped[14] = ( par[20] + par[21]) / 2;
|
|
par_mapped[15] = ( par[22] + par[23]) / 2;
|
|
par_mapped[16] = ( par[24] + par[25]) / 2;
|
|
par_mapped[17] = ( par[26] + par[27]) / 2;
|
|
par_mapped[18] = ( par[28] + par[29] + par[30] + par[31]) / 4;
|
|
par_mapped[19] = ( par[32] + par[33]) / 2;
|
|
}
|
|
}
|
|
|
|
static void map_val_34_to_20(float par[PS_MAX_NR_IIDICC])
|
|
{
|
|
par[ 0] = (2*par[ 0] + par[ 1]) * 0.33333333f;
|
|
par[ 1] = ( par[ 1] + 2*par[ 2]) * 0.33333333f;
|
|
par[ 2] = (2*par[ 3] + par[ 4]) * 0.33333333f;
|
|
par[ 3] = ( par[ 4] + 2*par[ 5]) * 0.33333333f;
|
|
par[ 4] = ( par[ 6] + par[ 7]) * 0.5f;
|
|
par[ 5] = ( par[ 8] + par[ 9]) * 0.5f;
|
|
par[ 6] = par[10];
|
|
par[ 7] = par[11];
|
|
par[ 8] = ( par[12] + par[13]) * 0.5f;
|
|
par[ 9] = ( par[14] + par[15]) * 0.5f;
|
|
par[10] = par[16];
|
|
par[11] = par[17];
|
|
par[12] = par[18];
|
|
par[13] = par[19];
|
|
par[14] = ( par[20] + par[21]) * 0.5f;
|
|
par[15] = ( par[22] + par[23]) * 0.5f;
|
|
par[16] = ( par[24] + par[25]) * 0.5f;
|
|
par[17] = ( par[26] + par[27]) * 0.5f;
|
|
par[18] = ( par[28] + par[29] + par[30] + par[31]) * 0.25f;
|
|
par[19] = ( par[32] + par[33]) * 0.5f;
|
|
}
|
|
|
|
static void map_idx_10_to_34(int8_t *par_mapped, const int8_t *par, int full)
|
|
{
|
|
if (full) {
|
|
par_mapped[33] = par[9];
|
|
par_mapped[32] = par[9];
|
|
par_mapped[31] = par[9];
|
|
par_mapped[30] = par[9];
|
|
par_mapped[29] = par[9];
|
|
par_mapped[28] = par[9];
|
|
par_mapped[27] = par[8];
|
|
par_mapped[26] = par[8];
|
|
par_mapped[25] = par[8];
|
|
par_mapped[24] = par[8];
|
|
par_mapped[23] = par[7];
|
|
par_mapped[22] = par[7];
|
|
par_mapped[21] = par[7];
|
|
par_mapped[20] = par[7];
|
|
par_mapped[19] = par[6];
|
|
par_mapped[18] = par[6];
|
|
par_mapped[17] = par[5];
|
|
par_mapped[16] = par[5];
|
|
} else {
|
|
par_mapped[16] = 0;
|
|
}
|
|
par_mapped[15] = par[4];
|
|
par_mapped[14] = par[4];
|
|
par_mapped[13] = par[4];
|
|
par_mapped[12] = par[4];
|
|
par_mapped[11] = par[3];
|
|
par_mapped[10] = par[3];
|
|
par_mapped[ 9] = par[2];
|
|
par_mapped[ 8] = par[2];
|
|
par_mapped[ 7] = par[2];
|
|
par_mapped[ 6] = par[2];
|
|
par_mapped[ 5] = par[1];
|
|
par_mapped[ 4] = par[1];
|
|
par_mapped[ 3] = par[1];
|
|
par_mapped[ 2] = par[0];
|
|
par_mapped[ 1] = par[0];
|
|
par_mapped[ 0] = par[0];
|
|
}
|
|
|
|
static void map_idx_20_to_34(int8_t *par_mapped, const int8_t *par, int full)
|
|
{
|
|
if (full) {
|
|
par_mapped[33] = par[19];
|
|
par_mapped[32] = par[19];
|
|
par_mapped[31] = par[18];
|
|
par_mapped[30] = par[18];
|
|
par_mapped[29] = par[18];
|
|
par_mapped[28] = par[18];
|
|
par_mapped[27] = par[17];
|
|
par_mapped[26] = par[17];
|
|
par_mapped[25] = par[16];
|
|
par_mapped[24] = par[16];
|
|
par_mapped[23] = par[15];
|
|
par_mapped[22] = par[15];
|
|
par_mapped[21] = par[14];
|
|
par_mapped[20] = par[14];
|
|
par_mapped[19] = par[13];
|
|
par_mapped[18] = par[12];
|
|
par_mapped[17] = par[11];
|
|
}
|
|
par_mapped[16] = par[10];
|
|
par_mapped[15] = par[ 9];
|
|
par_mapped[14] = par[ 9];
|
|
par_mapped[13] = par[ 8];
|
|
par_mapped[12] = par[ 8];
|
|
par_mapped[11] = par[ 7];
|
|
par_mapped[10] = par[ 6];
|
|
par_mapped[ 9] = par[ 5];
|
|
par_mapped[ 8] = par[ 5];
|
|
par_mapped[ 7] = par[ 4];
|
|
par_mapped[ 6] = par[ 4];
|
|
par_mapped[ 5] = par[ 3];
|
|
par_mapped[ 4] = (par[ 2] + par[ 3]) / 2;
|
|
par_mapped[ 3] = par[ 2];
|
|
par_mapped[ 2] = par[ 1];
|
|
par_mapped[ 1] = (par[ 0] + par[ 1]) / 2;
|
|
par_mapped[ 0] = par[ 0];
|
|
}
|
|
|
|
static void map_val_20_to_34(float par[PS_MAX_NR_IIDICC])
|
|
{
|
|
par[33] = par[19];
|
|
par[32] = par[19];
|
|
par[31] = par[18];
|
|
par[30] = par[18];
|
|
par[29] = par[18];
|
|
par[28] = par[18];
|
|
par[27] = par[17];
|
|
par[26] = par[17];
|
|
par[25] = par[16];
|
|
par[24] = par[16];
|
|
par[23] = par[15];
|
|
par[22] = par[15];
|
|
par[21] = par[14];
|
|
par[20] = par[14];
|
|
par[19] = par[13];
|
|
par[18] = par[12];
|
|
par[17] = par[11];
|
|
par[16] = par[10];
|
|
par[15] = par[ 9];
|
|
par[14] = par[ 9];
|
|
par[13] = par[ 8];
|
|
par[12] = par[ 8];
|
|
par[11] = par[ 7];
|
|
par[10] = par[ 6];
|
|
par[ 9] = par[ 5];
|
|
par[ 8] = par[ 5];
|
|
par[ 7] = par[ 4];
|
|
par[ 6] = par[ 4];
|
|
par[ 5] = par[ 3];
|
|
par[ 4] = (par[ 2] + par[ 3]) * 0.5f;
|
|
par[ 3] = par[ 2];
|
|
par[ 2] = par[ 1];
|
|
par[ 1] = (par[ 0] + par[ 1]) * 0.5f;
|
|
par[ 0] = par[ 0];
|
|
}
|
|
|
|
static void decorrelation(PSContext *ps, float (*out)[32][2], const float (*s)[32][2], int is34)
|
|
{
|
|
float power[34][PS_QMF_TIME_SLOTS] = {{0}};
|
|
float transient_gain[34][PS_QMF_TIME_SLOTS];
|
|
float *peak_decay_nrg = ps->peak_decay_nrg;
|
|
float *power_smooth = ps->power_smooth;
|
|
float *peak_decay_diff_smooth = ps->peak_decay_diff_smooth;
|
|
float (*delay)[PS_QMF_TIME_SLOTS + PS_MAX_DELAY][2] = ps->delay;
|
|
float (*ap_delay)[PS_AP_LINKS][PS_QMF_TIME_SLOTS + PS_MAX_AP_DELAY][2] = ps->ap_delay;
|
|
const int8_t *k_to_i = is34 ? k_to_i_34 : k_to_i_20;
|
|
const float peak_decay_factor = 0.76592833836465f;
|
|
const float transient_impact = 1.5f;
|
|
const float a_smooth = 0.25f; //< Smoothing coefficient
|
|
int i, k, m, n;
|
|
int n0 = 0, nL = 32;
|
|
static const int link_delay[] = { 3, 4, 5 };
|
|
static const float a[] = { 0.65143905753106f,
|
|
0.56471812200776f,
|
|
0.48954165955695f };
|
|
|
|
if (is34 != ps->is34bands_old) {
|
|
memset(ps->peak_decay_nrg, 0, sizeof(ps->peak_decay_nrg));
|
|
memset(ps->power_smooth, 0, sizeof(ps->power_smooth));
|
|
memset(ps->peak_decay_diff_smooth, 0, sizeof(ps->peak_decay_diff_smooth));
|
|
memset(ps->delay, 0, sizeof(ps->delay));
|
|
memset(ps->ap_delay, 0, sizeof(ps->ap_delay));
|
|
}
|
|
|
|
for (n = n0; n < nL; n++) {
|
|
for (k = 0; k < NR_BANDS[is34]; k++) {
|
|
int i = k_to_i[k];
|
|
power[i][n] += s[k][n][0] * s[k][n][0] + s[k][n][1] * s[k][n][1];
|
|
}
|
|
}
|
|
|
|
//Transient detection
|
|
for (i = 0; i < NR_PAR_BANDS[is34]; i++) {
|
|
for (n = n0; n < nL; n++) {
|
|
float decayed_peak = peak_decay_factor * peak_decay_nrg[i];
|
|
float denom;
|
|
peak_decay_nrg[i] = FFMAX(decayed_peak, power[i][n]);
|
|
power_smooth[i] += a_smooth * (power[i][n] - power_smooth[i]);
|
|
peak_decay_diff_smooth[i] += a_smooth * (peak_decay_nrg[i] - power[i][n] - peak_decay_diff_smooth[i]);
|
|
denom = transient_impact * peak_decay_diff_smooth[i];
|
|
transient_gain[i][n] = (denom > power_smooth[i]) ?
|
|
power_smooth[i] / denom : 1.0f;
|
|
}
|
|
}
|
|
|
|
//Decorrelation and transient reduction
|
|
// PS_AP_LINKS - 1
|
|
// -----
|
|
// | | Q_fract_allpass[k][m]*z^-link_delay[m] - a[m]*g_decay_slope[k]
|
|
//H[k][z] = z^-2 * phi_fract[k] * | | ----------------------------------------------------------------
|
|
// | | 1 - a[m]*g_decay_slope[k]*Q_fract_allpass[k][m]*z^-link_delay[m]
|
|
// m = 0
|
|
//d[k][z] (out) = transient_gain_mapped[k][z] * H[k][z] * s[k][z]
|
|
for (k = 0; k < NR_ALLPASS_BANDS[is34]; k++) {
|
|
int b = k_to_i[k];
|
|
float g_decay_slope = 1.f - DECAY_SLOPE * (k - DECAY_CUTOFF[is34]);
|
|
float ag[PS_AP_LINKS];
|
|
g_decay_slope = av_clipf(g_decay_slope, 0.f, 1.f);
|
|
memcpy(delay[k], delay[k]+nL, PS_MAX_DELAY*sizeof(delay[k][0]));
|
|
memcpy(delay[k]+PS_MAX_DELAY, s[k], numQMFSlots*sizeof(delay[k][0]));
|
|
for (m = 0; m < PS_AP_LINKS; m++) {
|
|
memcpy(ap_delay[k][m], ap_delay[k][m]+numQMFSlots, 5*sizeof(ap_delay[k][m][0]));
|
|
ag[m] = a[m] * g_decay_slope;
|
|
}
|
|
for (n = n0; n < nL; n++) {
|
|
float in_re = delay[k][n+PS_MAX_DELAY-2][0] * phi_fract[is34][k][0] -
|
|
delay[k][n+PS_MAX_DELAY-2][1] * phi_fract[is34][k][1];
|
|
float in_im = delay[k][n+PS_MAX_DELAY-2][0] * phi_fract[is34][k][1] +
|
|
delay[k][n+PS_MAX_DELAY-2][1] * phi_fract[is34][k][0];
|
|
for (m = 0; m < PS_AP_LINKS; m++) {
|
|
float a_re = ag[m] * in_re;
|
|
float a_im = ag[m] * in_im;
|
|
float link_delay_re = ap_delay[k][m][n+5-link_delay[m]][0];
|
|
float link_delay_im = ap_delay[k][m][n+5-link_delay[m]][1];
|
|
float fractional_delay_re = Q_fract_allpass[is34][k][m][0];
|
|
float fractional_delay_im = Q_fract_allpass[is34][k][m][1];
|
|
ap_delay[k][m][n+5][0] = in_re;
|
|
ap_delay[k][m][n+5][1] = in_im;
|
|
in_re = link_delay_re * fractional_delay_re - link_delay_im * fractional_delay_im - a_re;
|
|
in_im = link_delay_re * fractional_delay_im + link_delay_im * fractional_delay_re - a_im;
|
|
ap_delay[k][m][n+5][0] += ag[m] * in_re;
|
|
ap_delay[k][m][n+5][1] += ag[m] * in_im;
|
|
}
|
|
out[k][n][0] = transient_gain[b][n] * in_re;
|
|
out[k][n][1] = transient_gain[b][n] * in_im;
|
|
}
|
|
}
|
|
for (; k < SHORT_DELAY_BAND[is34]; k++) {
|
|
memcpy(delay[k], delay[k]+nL, PS_MAX_DELAY*sizeof(delay[k][0]));
|
|
memcpy(delay[k]+PS_MAX_DELAY, s[k], numQMFSlots*sizeof(delay[k][0]));
|
|
for (n = n0; n < nL; n++) {
|
|
//H = delay 14
|
|
out[k][n][0] = transient_gain[k_to_i[k]][n] * delay[k][n+PS_MAX_DELAY-14][0];
|
|
out[k][n][1] = transient_gain[k_to_i[k]][n] * delay[k][n+PS_MAX_DELAY-14][1];
|
|
}
|
|
}
|
|
for (; k < NR_BANDS[is34]; k++) {
|
|
memcpy(delay[k], delay[k]+nL, PS_MAX_DELAY*sizeof(delay[k][0]));
|
|
memcpy(delay[k]+PS_MAX_DELAY, s[k], numQMFSlots*sizeof(delay[k][0]));
|
|
for (n = n0; n < nL; n++) {
|
|
//H = delay 1
|
|
out[k][n][0] = transient_gain[k_to_i[k]][n] * delay[k][n+PS_MAX_DELAY-1][0];
|
|
out[k][n][1] = transient_gain[k_to_i[k]][n] * delay[k][n+PS_MAX_DELAY-1][1];
|
|
}
|
|
}
|
|
}
|
|
|
|
static void remap34(int8_t (**p_par_mapped)[PS_MAX_NR_IIDICC],
|
|
int8_t (*par)[PS_MAX_NR_IIDICC],
|
|
int num_par, int num_env, int full)
|
|
{
|
|
int8_t (*par_mapped)[PS_MAX_NR_IIDICC] = *p_par_mapped;
|
|
int e;
|
|
if (num_par == 20 || num_par == 11) {
|
|
for (e = 0; e < num_env; e++) {
|
|
map_idx_20_to_34(par_mapped[e], par[e], full);
|
|
}
|
|
} else if (num_par == 10 || num_par == 5) {
|
|
for (e = 0; e < num_env; e++) {
|
|
map_idx_10_to_34(par_mapped[e], par[e], full);
|
|
}
|
|
} else {
|
|
*p_par_mapped = par;
|
|
}
|
|
}
|
|
|
|
static void remap20(int8_t (**p_par_mapped)[PS_MAX_NR_IIDICC],
|
|
int8_t (*par)[PS_MAX_NR_IIDICC],
|
|
int num_par, int num_env, int full)
|
|
{
|
|
int8_t (*par_mapped)[PS_MAX_NR_IIDICC] = *p_par_mapped;
|
|
int e;
|
|
if (num_par == 34 || num_par == 17) {
|
|
for (e = 0; e < num_env; e++) {
|
|
map_idx_34_to_20(par_mapped[e], par[e], full);
|
|
}
|
|
} else if (num_par == 10 || num_par == 5) {
|
|
for (e = 0; e < num_env; e++) {
|
|
map_idx_10_to_20(par_mapped[e], par[e], full);
|
|
}
|
|
} else {
|
|
*p_par_mapped = par;
|
|
}
|
|
}
|
|
|
|
static void stereo_processing(PSContext *ps, float (*l)[32][2], float (*r)[32][2], int is34)
|
|
{
|
|
int e, b, k, n;
|
|
|
|
float (*H11)[PS_MAX_NUM_ENV+1][PS_MAX_NR_IIDICC] = ps->H11;
|
|
float (*H12)[PS_MAX_NUM_ENV+1][PS_MAX_NR_IIDICC] = ps->H12;
|
|
float (*H21)[PS_MAX_NUM_ENV+1][PS_MAX_NR_IIDICC] = ps->H21;
|
|
float (*H22)[PS_MAX_NUM_ENV+1][PS_MAX_NR_IIDICC] = ps->H22;
|
|
int8_t *opd_hist = ps->opd_hist;
|
|
int8_t *ipd_hist = ps->ipd_hist;
|
|
int8_t iid_mapped_buf[PS_MAX_NUM_ENV][PS_MAX_NR_IIDICC];
|
|
int8_t icc_mapped_buf[PS_MAX_NUM_ENV][PS_MAX_NR_IIDICC];
|
|
int8_t ipd_mapped_buf[PS_MAX_NUM_ENV][PS_MAX_NR_IIDICC];
|
|
int8_t opd_mapped_buf[PS_MAX_NUM_ENV][PS_MAX_NR_IIDICC];
|
|
int8_t (*iid_mapped)[PS_MAX_NR_IIDICC] = iid_mapped_buf;
|
|
int8_t (*icc_mapped)[PS_MAX_NR_IIDICC] = icc_mapped_buf;
|
|
int8_t (*ipd_mapped)[PS_MAX_NR_IIDICC] = ipd_mapped_buf;
|
|
int8_t (*opd_mapped)[PS_MAX_NR_IIDICC] = opd_mapped_buf;
|
|
const int8_t *k_to_i = is34 ? k_to_i_34 : k_to_i_20;
|
|
const float (*H_LUT)[8][4] = (PS_BASELINE || ps->icc_mode < 3) ? HA : HB;
|
|
|
|
//Remapping
|
|
memcpy(H11[0][0], H11[0][ps->num_env_old], PS_MAX_NR_IIDICC*sizeof(H11[0][0][0]));
|
|
memcpy(H11[1][0], H11[1][ps->num_env_old], PS_MAX_NR_IIDICC*sizeof(H11[1][0][0]));
|
|
memcpy(H12[0][0], H12[0][ps->num_env_old], PS_MAX_NR_IIDICC*sizeof(H12[0][0][0]));
|
|
memcpy(H12[1][0], H12[1][ps->num_env_old], PS_MAX_NR_IIDICC*sizeof(H12[1][0][0]));
|
|
memcpy(H21[0][0], H21[0][ps->num_env_old], PS_MAX_NR_IIDICC*sizeof(H21[0][0][0]));
|
|
memcpy(H21[1][0], H21[1][ps->num_env_old], PS_MAX_NR_IIDICC*sizeof(H21[1][0][0]));
|
|
memcpy(H22[0][0], H22[0][ps->num_env_old], PS_MAX_NR_IIDICC*sizeof(H22[0][0][0]));
|
|
memcpy(H22[1][0], H22[1][ps->num_env_old], PS_MAX_NR_IIDICC*sizeof(H22[1][0][0]));
|
|
if (is34) {
|
|
remap34(&iid_mapped, ps->iid_par, ps->nr_iid_par, ps->num_env, 1);
|
|
remap34(&icc_mapped, ps->icc_par, ps->nr_icc_par, ps->num_env, 1);
|
|
if (ps->enable_ipdopd) {
|
|
remap34(&ipd_mapped, ps->ipd_par, ps->nr_ipdopd_par, ps->num_env, 0);
|
|
remap34(&opd_mapped, ps->opd_par, ps->nr_ipdopd_par, ps->num_env, 0);
|
|
}
|
|
if (!ps->is34bands_old) {
|
|
map_val_20_to_34(H11[0][0]);
|
|
map_val_20_to_34(H11[1][0]);
|
|
map_val_20_to_34(H12[0][0]);
|
|
map_val_20_to_34(H12[1][0]);
|
|
map_val_20_to_34(H21[0][0]);
|
|
map_val_20_to_34(H21[1][0]);
|
|
map_val_20_to_34(H22[0][0]);
|
|
map_val_20_to_34(H22[1][0]);
|
|
ipdopd_reset(ipd_hist, opd_hist);
|
|
}
|
|
} else {
|
|
remap20(&iid_mapped, ps->iid_par, ps->nr_iid_par, ps->num_env, 1);
|
|
remap20(&icc_mapped, ps->icc_par, ps->nr_icc_par, ps->num_env, 1);
|
|
if (ps->enable_ipdopd) {
|
|
remap20(&ipd_mapped, ps->ipd_par, ps->nr_ipdopd_par, ps->num_env, 0);
|
|
remap20(&opd_mapped, ps->opd_par, ps->nr_ipdopd_par, ps->num_env, 0);
|
|
}
|
|
if (ps->is34bands_old) {
|
|
map_val_34_to_20(H11[0][0]);
|
|
map_val_34_to_20(H11[1][0]);
|
|
map_val_34_to_20(H12[0][0]);
|
|
map_val_34_to_20(H12[1][0]);
|
|
map_val_34_to_20(H21[0][0]);
|
|
map_val_34_to_20(H21[1][0]);
|
|
map_val_34_to_20(H22[0][0]);
|
|
map_val_34_to_20(H22[1][0]);
|
|
ipdopd_reset(ipd_hist, opd_hist);
|
|
}
|
|
}
|
|
|
|
//Mixing
|
|
for (e = 0; e < ps->num_env; e++) {
|
|
for (b = 0; b < NR_PAR_BANDS[is34]; b++) {
|
|
float h11, h12, h21, h22;
|
|
h11 = H_LUT[iid_mapped[e][b] + 7 + 23 * ps->iid_quant][icc_mapped[e][b]][0];
|
|
h12 = H_LUT[iid_mapped[e][b] + 7 + 23 * ps->iid_quant][icc_mapped[e][b]][1];
|
|
h21 = H_LUT[iid_mapped[e][b] + 7 + 23 * ps->iid_quant][icc_mapped[e][b]][2];
|
|
h22 = H_LUT[iid_mapped[e][b] + 7 + 23 * ps->iid_quant][icc_mapped[e][b]][3];
|
|
if (!PS_BASELINE && ps->enable_ipdopd && b < ps->nr_ipdopd_par) {
|
|
//The spec say says to only run this smoother when enable_ipdopd
|
|
//is set but the reference decoder appears to run it constantly
|
|
float h11i, h12i, h21i, h22i;
|
|
float ipd_adj_re, ipd_adj_im;
|
|
int opd_idx = opd_hist[b] * 8 + opd_mapped[e][b];
|
|
int ipd_idx = ipd_hist[b] * 8 + ipd_mapped[e][b];
|
|
float opd_re = pd_re_smooth[opd_idx];
|
|
float opd_im = pd_im_smooth[opd_idx];
|
|
float ipd_re = pd_re_smooth[ipd_idx];
|
|
float ipd_im = pd_im_smooth[ipd_idx];
|
|
opd_hist[b] = opd_idx & 0x3F;
|
|
ipd_hist[b] = ipd_idx & 0x3F;
|
|
|
|
ipd_adj_re = opd_re*ipd_re + opd_im*ipd_im;
|
|
ipd_adj_im = opd_im*ipd_re - opd_re*ipd_im;
|
|
h11i = h11 * opd_im;
|
|
h11 = h11 * opd_re;
|
|
h12i = h12 * ipd_adj_im;
|
|
h12 = h12 * ipd_adj_re;
|
|
h21i = h21 * opd_im;
|
|
h21 = h21 * opd_re;
|
|
h22i = h22 * ipd_adj_im;
|
|
h22 = h22 * ipd_adj_re;
|
|
H11[1][e+1][b] = h11i;
|
|
H12[1][e+1][b] = h12i;
|
|
H21[1][e+1][b] = h21i;
|
|
H22[1][e+1][b] = h22i;
|
|
}
|
|
H11[0][e+1][b] = h11;
|
|
H12[0][e+1][b] = h12;
|
|
H21[0][e+1][b] = h21;
|
|
H22[0][e+1][b] = h22;
|
|
}
|
|
for (k = 0; k < NR_BANDS[is34]; k++) {
|
|
float h11r, h12r, h21r, h22r;
|
|
float h11i, h12i, h21i, h22i;
|
|
float h11r_step, h12r_step, h21r_step, h22r_step;
|
|
float h11i_step, h12i_step, h21i_step, h22i_step;
|
|
int start = ps->border_position[e];
|
|
int stop = ps->border_position[e+1];
|
|
float width = 1.f / (stop - start);
|
|
b = k_to_i[k];
|
|
h11r = H11[0][e][b];
|
|
h12r = H12[0][e][b];
|
|
h21r = H21[0][e][b];
|
|
h22r = H22[0][e][b];
|
|
if (!PS_BASELINE && ps->enable_ipdopd) {
|
|
//Is this necessary? ps_04_new seems unchanged
|
|
if ((is34 && k <= 13 && k >= 9) || (!is34 && k <= 1)) {
|
|
h11i = -H11[1][e][b];
|
|
h12i = -H12[1][e][b];
|
|
h21i = -H21[1][e][b];
|
|
h22i = -H22[1][e][b];
|
|
} else {
|
|
h11i = H11[1][e][b];
|
|
h12i = H12[1][e][b];
|
|
h21i = H21[1][e][b];
|
|
h22i = H22[1][e][b];
|
|
}
|
|
}
|
|
//Interpolation
|
|
h11r_step = (H11[0][e+1][b] - h11r) * width;
|
|
h12r_step = (H12[0][e+1][b] - h12r) * width;
|
|
h21r_step = (H21[0][e+1][b] - h21r) * width;
|
|
h22r_step = (H22[0][e+1][b] - h22r) * width;
|
|
if (!PS_BASELINE && ps->enable_ipdopd) {
|
|
h11i_step = (H11[1][e+1][b] - h11i) * width;
|
|
h12i_step = (H12[1][e+1][b] - h12i) * width;
|
|
h21i_step = (H21[1][e+1][b] - h21i) * width;
|
|
h22i_step = (H22[1][e+1][b] - h22i) * width;
|
|
}
|
|
for (n = start + 1; n <= stop; n++) {
|
|
//l is s, r is d
|
|
float l_re = l[k][n][0];
|
|
float l_im = l[k][n][1];
|
|
float r_re = r[k][n][0];
|
|
float r_im = r[k][n][1];
|
|
h11r += h11r_step;
|
|
h12r += h12r_step;
|
|
h21r += h21r_step;
|
|
h22r += h22r_step;
|
|
if (!PS_BASELINE && ps->enable_ipdopd) {
|
|
h11i += h11i_step;
|
|
h12i += h12i_step;
|
|
h21i += h21i_step;
|
|
h22i += h22i_step;
|
|
|
|
l[k][n][0] = h11r*l_re + h21r*r_re - h11i*l_im - h21i*r_im;
|
|
l[k][n][1] = h11r*l_im + h21r*r_im + h11i*l_re + h21i*r_re;
|
|
r[k][n][0] = h12r*l_re + h22r*r_re - h12i*l_im - h22i*r_im;
|
|
r[k][n][1] = h12r*l_im + h22r*r_im + h12i*l_re + h22i*r_re;
|
|
} else {
|
|
l[k][n][0] = h11r*l_re + h21r*r_re;
|
|
l[k][n][1] = h11r*l_im + h21r*r_im;
|
|
r[k][n][0] = h12r*l_re + h22r*r_re;
|
|
r[k][n][1] = h12r*l_im + h22r*r_im;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
int ff_ps_apply(AVCodecContext *avctx, PSContext *ps, float L[2][38][64], float R[2][38][64], int top)
|
|
{
|
|
float Lbuf[91][32][2];
|
|
float Rbuf[91][32][2];
|
|
const int len = 32;
|
|
int is34 = ps->is34bands;
|
|
|
|
top += NR_BANDS[is34] - 64;
|
|
memset(ps->delay+top, 0, (NR_BANDS[is34] - top)*sizeof(ps->delay[0]));
|
|
if (top < NR_ALLPASS_BANDS[is34])
|
|
memset(ps->ap_delay + top, 0, (NR_ALLPASS_BANDS[is34] - top)*sizeof(ps->ap_delay[0]));
|
|
|
|
hybrid_analysis(Lbuf, ps->in_buf, L, is34, len);
|
|
decorrelation(ps, Rbuf, Lbuf, is34);
|
|
stereo_processing(ps, Lbuf, Rbuf, is34);
|
|
hybrid_synthesis(L, Lbuf, is34, len);
|
|
hybrid_synthesis(R, Rbuf, is34, len);
|
|
|
|
return 0;
|
|
}
|
|
|
|
#define PS_INIT_VLC_STATIC(num, size) \
|
|
INIT_VLC_STATIC(&vlc_ps[num], 9, ps_tmp[num].table_size / ps_tmp[num].elem_size, \
|
|
ps_tmp[num].ps_bits, 1, 1, \
|
|
ps_tmp[num].ps_codes, ps_tmp[num].elem_size, ps_tmp[num].elem_size, \
|
|
size);
|
|
|
|
#define PS_VLC_ROW(name) \
|
|
{ name ## _codes, name ## _bits, sizeof(name ## _codes), sizeof(name ## _codes[0]) }
|
|
|
|
av_cold void ff_ps_init(void) {
|
|
// Syntax initialization
|
|
static const struct {
|
|
const void *ps_codes, *ps_bits;
|
|
const unsigned int table_size, elem_size;
|
|
} ps_tmp[] = {
|
|
PS_VLC_ROW(huff_iid_df1),
|
|
PS_VLC_ROW(huff_iid_dt1),
|
|
PS_VLC_ROW(huff_iid_df0),
|
|
PS_VLC_ROW(huff_iid_dt0),
|
|
PS_VLC_ROW(huff_icc_df),
|
|
PS_VLC_ROW(huff_icc_dt),
|
|
PS_VLC_ROW(huff_ipd_df),
|
|
PS_VLC_ROW(huff_ipd_dt),
|
|
PS_VLC_ROW(huff_opd_df),
|
|
PS_VLC_ROW(huff_opd_dt),
|
|
};
|
|
|
|
PS_INIT_VLC_STATIC(0, 1544);
|
|
PS_INIT_VLC_STATIC(1, 832);
|
|
PS_INIT_VLC_STATIC(2, 1024);
|
|
PS_INIT_VLC_STATIC(3, 1036);
|
|
PS_INIT_VLC_STATIC(4, 544);
|
|
PS_INIT_VLC_STATIC(5, 544);
|
|
PS_INIT_VLC_STATIC(6, 512);
|
|
PS_INIT_VLC_STATIC(7, 512);
|
|
PS_INIT_VLC_STATIC(8, 512);
|
|
PS_INIT_VLC_STATIC(9, 512);
|
|
|
|
ps_tableinit();
|
|
}
|
|
|
|
av_cold void ff_ps_ctx_init(PSContext *ps)
|
|
{
|
|
}
|