/*
(c) Copyright 1998-2001 - Tord Jansson
======================================
This file is part of the BladeEnc MP3 Encoder, based on
ISO's reference code for MPEG Layer 3 compression, and might
contain smaller or larger sections that are directly taken
from ISO's reference code.
All changes to the ISO reference code herein are either
copyrighted by Tord Jansson (tord.jansson@swipnet.se)
or sublicensed to Tord Jansson by a third party.
BladeEnc is free software; you can redistribute this file
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.
------------ Changes ------------
2000-12-05 Andre Piotrowski
- speed up: implemented prepacking of fft-data
2000-12-11 ap
- speed up: faster psycho_anal()
- optional bug fix: integrated better norm calclulation and block selecting
2000-12-12 ap
- use SHORT_FFT_MIN_IDX to allow switching of "ORG_SHORT_CW_LIMIT" in "l3psy.h"
2001-01-12 ap
- use some explicit type casting to avoid compiler warnings
*/
#define RING_BUFFER 1
#include <stdlib.h>
#include "common.h"
#include "tables.h"
#include "encoder.h"
#include "l3side.h"
#include "l3psy.h"
/*____ Global Static Variables ______________________________________________*/
/* The static variables "r", "phi_sav", "new_", "old" and "oldest" have */
/* to be remembered for the unpredictability measure. For "r" and */
/* "phi_sav", the first index from the left is the channel select and */
/* the second index is the "age" of the data. */
static int new_, old, oldest;
static int flush, sync_flush, syncsize;
#if RING_BUFFER==1
static int savebuf_start_idx[2];
#endif
#if NEW_L3PARM_TABLES
static double *minval, *qthr_l;
static double *qthr_s, *SNR_s;
static int *cbw_l, *bu_l, *bo_l;
static int *cbw_s, *bu_s, *bo_s;
static double *w1_l, *w2_l;
static double *w1_s, *w2_s;
#if ORG_NUMLINES_NORM
static int cbmax_l = CBANDS, cbmax_s = CBANDS_s;
static int numlines_l [CBANDS];
static int partition_l [HBLKSIZE];
static int partition_s [HBLKSIZE_s];
static double s3_l [CBANDS][CBANDS];
static double *norm_l, *norm_s;
#else
static int cbmax_l, cbmax_s;
static int *numlines_l;
static int *numlines_s;
/* the non-zero entries of norm_l[i] * s3_l[i][j] */
static FLOAT normed_s3_l [900]; /* a bit more space than needed [799|855|735] */
static int lo_s3_l [CBANDS];
static int hi_s3_l [CBANDS];
static FLOAT normed_s3_s [500]; /* a bit more space than needed [445|395|378] */
static int lo_s3_s [CBANDS_s];
static int hi_s3_s [CBANDS_s];
#endif /* ORG_NUMLINES_NORM */
#else
static double minval[CBANDS], qthr_l[CBANDS], norm_l[CBANDS];
static double qthr_s[CBANDS_s], norm_s[CBANDS_s], SNR_s[CBANDS_s];
static int cbw_l[SBMAX_l],bu_l[SBMAX_l],bo_l[SBMAX_l];
static int cbw_s[SBMAX_s],bu_s[SBMAX_s],bo_s[SBMAX_s];
static double w1_l[SBMAX_l], w2_l[SBMAX_l];
static double w1_s[SBMAX_s], w2_s[SBMAX_s];
static int numlines_l [CBANDS];
static int partition_l [HBLKSIZE];
static int partition_s [HBLKSIZE_s];
static double s3_l [CBANDS][CBANDS];
#endif /* NEW_L3PARM_TABLES */
/* Scale Factor Bands */
static int blocktype_old[2];
static double nb_1 [2][CBANDS];
static double nb_2 [2][CBANDS];
static double cw [HBLKSIZE];
static FLOAT window [BLKSIZE];
static FLOAT r [2][2][6];
static FLOAT phi_sav [2][2][6];
static FLOAT window_s [BLKSIZE_s];
static double ratio [2][SBMAX_l];
static double ratio_s [2][SBMAX_s][3];
#if NEW_L3PARM_TABLES
static void L3para_read (int sfreq);
#if !ORG_NUMLINES_NORM
static void calc_normed_spreading
(
int cbmax, /* number of lines and rows */
const double bval[], /* input values to compute the matrix */
FLOAT s3_ptr[], /* the resulting non-zero entries */
int lo_s3[],
int hi_s3[],
const double norm[]
);
#endif
#else
static void L3para_read
(
int sfreq,
int numlines_l[CBANDS],
int partition_l[HBLKSIZE],
double minval[CBANDS],
double qthr_l[CBANDS],
double norm_l[CBANDS],
double s3_l[CBANDS][CBANDS],
int partition_s[HBLKSIZE_s],
double qthr_s[CBANDS_s],
double norm_s[CBANDS_s],
double SNR_s[CBANDS_s],
int cbw_l[SBMAX_l],
int bu_l[SBMAX_l],
int bo_l[SBMAX_l],
double w1_l[SBMAX_l],
double w2_l[SBMAX_l],
int cbw_s[SBMAX_s],
int bu_s[SBMAX_s],
int bo_s[SBMAX_s],
double w1_s[SBMAX_s],
double w2_s[SBMAX_s]
);
#endif
/*____ psycho_anal_init() ___________________________________________________*/
void psycho_anal_init (double sfreq)
{
unsigned int ch, sfb, b, i, j;
/* reset the r, phi_sav "ring buffer" indices */
old = 1 - (new_ = oldest = 0);
/* clear the ratio arrays */
for (ch = 0; ch < 2; ch++)
{
for (sfb = 0; sfb < SBMAX_l; sfb++)
ratio[ch][sfb] = 0.0;
for (sfb = 0; sfb < SBMAX_s; sfb++)
for (b = 0; b < 3; b++)
ratio_s[ch][sfb][b] = 0.0;
}
/* clear preecho arrays */
for (ch = 0; ch < 2; ch++)
{
for (i = 0; i < CBANDS; i++)
{
nb_1[ch][i] = 0;
nb_2[ch][i] = 0;
}
}
/* clear blocktype information */
for (ch = 0; ch < 2; ch++)
blocktype_old[ch] = NORM_TYPE;
sync_flush = 768;
flush = 576;
syncsize = 1344; /* sync_flush + flush */
#if RING_BUFFER==1
for (ch = 0; ch < 2; ch++)
savebuf_start_idx[ch] = 0;
#endif
/* calculate HANN window coefficients */
for (i = 0; i < BLKSIZE; i++)
window[i] = (FLOAT) (0.5 * (1 - cos (2.0 * PI * (i - 0.5) / BLKSIZE)));
for (i = 0; i < BLKSIZE_s; i++)
window_s[i] = (FLOAT) (0.5 * (1 - cos (2.0 * PI * (i - 0.5) / BLKSIZE_s)));
/* reset states used in unpredictability measure */
for (ch = 0; ch < 2; ch++)
{
for (i = 0; i < 2; i++)
{
for (j = 0; j < 6; j++)
{
r[ch][i][j] = 0.0;
phi_sav[ch][i][j] = 0.0;
}
}
}
#if NEW_L3PARM_TABLES
L3para_read ((int) sfreq);
#else
L3para_read
(
(int) sfreq,
numlines_l, partition_l, minval, qthr_l, norm_l, s3_l,
partition_s, qthr_s, norm_s, SNR_s,
cbw_l, bu_l, bo_l, w1_l, w2_l,
cbw_s, bu_s, bo_s, w1_s, w2_s
);
#endif
/* Set unpredicatiblility of remaining spectral lines to 0.4 */
for (j = 206; j < HBLKSIZE; j++)
cw[j] = 0.4;
}
/*____ psycho_anal_exit() ___________________________________________________*/
void psycho_anal_exit( void )
{
/* nothing to do */
}
/*____ psycho_anal() ________________________________________________________*/
void psycho_anal
(
#if ORG_BUFFERS
short int *buffer,
short int savebuf[2048],
#else
FLOAT *buffer,
int buffer_idx,
#endif
int ch,
int lay,
/* float snr32[32], */
double ratio_d[SBMAX_l],
double ratio_ds[SBMAX_s][3],
double *pe,
gr_info *cod_info
)
{
int blocktype;
unsigned int sfb, b, j, k;
double r_prime, phi_prime; /* not FLOAT */
double temp1, temp2, temp3;
#if !ORG_NUMLINES_NORM && NEW_L3PARM_TABLES
FLOAT *s3_ptr;
#endif
int sblock;
double thr [CBANDS];
double eb [CBANDS];
FLOAT cb [CBANDS];
FLOAT wsamp_r [HBLKSIZE];
FLOAT wsamp_i [HBLKSIZE];
FLOAT energy [HBLKSIZE];
FLOAT phi [6];
FLOAT energy_s [3][BLKSIZE_s];
FLOAT phi_s [3][52];
#if ORG_BUFFERS
#if RING_BUFFER==1
int beg, idx, fin;
#endif
#else
# define savebuf buffer
# define beg buffer_idx
int idx, fin;
#endif
for (sfb = 0; sfb < SBMAX_l; sfb++)
ratio_d[sfb] = ratio[ch][sfb];
for (sfb = 0; sfb < SBMAX_s; sfb++)
for (b = 0; b < 3; b++)
ratio_ds[sfb][b] = ratio_s[ch][sfb][b];
if (ch == 0)
old = 1 - (new_ = oldest = old);
#if ORG_BUFFERS
/**********************************************************************
* Delay signal by sync_flush=768 samples *
**********************************************************************/
# if RING_BUFFER==0
for (j = 0; j < sync_flush; j++) /* for long window samples */
savebuf[j] = savebuf[j+flush];
for (j = sync_flush; j < syncsize; j++)
savebuf[j] = *buffer++;
# else
beg = savebuf_start_idx[ch] = (savebuf_start_idx[ch] + flush) & 2047;
idx = (beg + sync_flush) & 2047;
fin = (idx + flush) & 2047;
if (idx >= fin)
{
while (idx < 2048)
savebuf[idx++] = *buffer++;
idx = 0;
}
while (idx < fin)
savebuf[idx++] = *buffer++;
# endif
#endif
/**********************************************************************
* compute unpredicatability of first six spectral lines *
**********************************************************************/
#if RING_BUFFER==0
for (j = 0, k = 0, idx = 0; j < BLKSIZE/2; j++)
{
wsamp_r[j] = window[k++] * savebuf[idx++];
wsamp_i[j] = window[k++] * savebuf[idx++];
}
#else
j = 0; k = 0;
idx = beg;
fin = (idx + BLKSIZE) & 2047;
if (idx >= fin)
{
while (idx < 2048)
{
wsamp_r[j] = window[k++] * savebuf[idx++];
wsamp_i[j] = window[k++] * savebuf[idx++];
j++;
}
idx = 0;
}
while (idx < fin)
{
wsamp_r[j] = window[k++] * savebuf[idx++];
wsamp_i[j] = window[k++] * savebuf[idx++];
j++;
}
#endif
fft(wsamp_r, wsamp_i, energy, phi, BLKSIZE); /* long FFT */
for (j = 0; j < 6; j++)
{ /* calculate unpredictability measure cw */
double r1, phi1;
r_prime = 2.0 * r[ch][old][j] - r[ch][oldest][j];
phi_prime = 2.0 * phi_sav[ch][old][j] - phi_sav[ch][oldest][j];
r[ch][new_][j] = (FLOAT) ( r1 = sqrt((double) energy[j]));
phi_sav[ch][new_][j] = (FLOAT) (phi1 = phi[j] );
temp3 = r1 + fabs(r_prime);
if (temp3 != 0.0)
{
temp1 = r1 * cos(phi1) - r_prime * cos(phi_prime);
temp2 = r1 * sin(phi1) - r_prime * sin(phi_prime);
cw[j] = sqrt(temp1*temp1 + temp2*temp2) / temp3;
}
else
cw[j] = 0;
}
/**********************************************************************
* compute unpredicatibility of next 200 spectral lines *
**********************************************************************/
for (b = 0; b < 3; b++)
{
#if RING_BUFFER==0
for (j = 0, k = 0, idx = 128*(2 + b); j < BLKSIZE_s/2; j++)
{ /* window data with HANN window */
wsamp_r[j] = window_s[k++] * savebuf[idx++];
wsamp_i[j] = window_s[k++] * savebuf[idx++];
}
#else
j = 0; k = 0;
idx = (beg + 128*(2 + b)) & 2047;
fin = (idx + BLKSIZE_s) & 2047;
if (idx >= fin)
{
while (idx < 2048)
{
wsamp_r[j] = window_s[k++] * savebuf[idx++];
wsamp_i[j] = window_s[k++] * savebuf[idx++];
j++;
}
idx = 0;
}
while (idx < fin)
{
wsamp_r[j] = window_s[k++] * savebuf[idx++];
wsamp_i[j] = window_s[k++] * savebuf[idx++];
j++;
}
#endif
fft (wsamp_r, wsamp_i, energy_s[b], phi_s[b], BLKSIZE_s); /* short FFT*/
}
for (j = 6, k = SHORT_FFT_MIN_IDX; j < 206; j += 4, k++)
{ /* calculate unpredictability measure cw */
double r1, phi1;
r_prime = 2.0 * sqrt((double) energy_s[0][k]) - sqrt((double) energy_s[2][k]);
phi_prime = 2.0 * phi_s[0][k] - phi_s[2][k];
r1 = sqrt((double) energy_s[1][k]);
phi1 = phi_s[1][k];
temp3 = r1 + fabs(r_prime);
if (temp3 != 0.0)
{
temp1 = r1 * cos(phi1) - r_prime * cos(phi_prime);
temp2 = r1 * sin(phi1) - r_prime * sin(phi_prime);
cw[j] = sqrt(temp1*temp1 + temp2*temp2) / temp3;
}
else
cw[j] = 0.0;
cw[j+1] = cw[j+2] = cw[j+3] = cw[j];
}
/**********************************************************************
* Calculate the energy and the unpredictability in the threshold *
* calculation partitions *
**********************************************************************/
#if ORG_NUMLINES_NORM || !NEW_L3PARM_TABLES
for (b = 0; b < cbmax_l; b++)
{
eb[b] = 0.0;
cb[b] = 0.0;
}
for (j = 0; j < HBLKSIZE; j++)
{
int tp = partition_l[j];
if (tp >= 0)
{
eb[tp] += energy[j];
cb[tp] += cw[j] * energy[j];
}
}
#else
j = 0;
for (b = 0; b < cbmax_l; b++)
{
eb[b] = 0.0;
cb[b] = 0.0;
/*
Calculate the energy and the unpredictability in the threshold
calculation partitions
cbmax_l holds the number of valid numlines_l entries
*/
k = numlines_l[b];
do {
eb[b] += energy[j];
cb[b] += cw[j] * energy[j];
} while (j++, --k);
}
s3_ptr = normed_s3_l;
#endif
*pe = 0.0;
for (b = 0; b < cbmax_l; b++)
{
FLOAT nb;
FLOAT ecb = 0.0;
double ctb = 0.0;
double SNR_l;
double cbb, tbb;
/*
convolve the partitioned energy and unpredictability
with the spreading function, normed_s3_l[b][k]
*/
#if ORG_NUMLINES_NORM || !NEW_L3PARM_TABLES
for (k = 0; k < cbmax_l; k++)
{
ecb += s3_l[b][k] * eb[k]; /* sprdngf for Layer III */
ctb += s3_l[b][k] * cb[k];
}
#else
for (k = lo_s3_l[b]; k < hi_s3_l[b]; k++)
{
ecb += *s3_ptr * eb[k]; /* sprdngf for Layer III */
ctb += *s3_ptr++ * cb[k];
}
#endif
/*
calculate the tonality of each threshold calculation partition
calculate the SNR in each threshhold calculation partition
*/
if (ecb != 0.0)
{
cbb = ctb / ecb;
if (cbb < 0.01)
cbb = 0.01;
tbb = -0.299 - 0.43 * log(cbb); /* conv1=-0.299, conv2=-0.43 */
tbb = MIN(MAX (0.0, tbb), 1.0) ; /* 0<=tbb<=1 */
}
else
tbb = 0.0; /* cbb==0 => -0.299-0.43*cbb<0 => tbb=0*/
/* TMN=29.0,NMT=6.0 for all calculation partitions */
SNR_l = MAX (minval[b], 23.0 * tbb + 6.0); /* 29*tbb + 6*(1-tbb) */
/* calculate the threshold for each partition */
#if ORG_NUMLINES_NORM || !NEW_L3PARM_TABLES
nb = ecb * norm_l[b] * exp(-SNR_l * LN_TO_LOG10);
#else
nb = ecb * exp(-SNR_l * LN_TO_LOG10); /* our ecb is already normed */
#endif
/*
pre-echo control
*/
thr[b] = MAX (qthr_l[b], MIN(nb, nb_2[ch][b]));
nb_2[ch][b] = MIN(2.0 * nb, 16.0 * nb_1[ch][b]);
nb_1[ch][b] = nb;
/*
calculate percetual entropy
thr[b] -> thr[b]+1.0 : for non sound portition
*/
if (eb[b] > thr[b])
*pe += numlines_l[b] * log((eb[b]+1.0) / (thr[b]+1.0));
}
#define switch_pe 1800
if (*pe < switch_pe)
{
/* no attack : use long blocks */
if (blocktype_old[ch] == SHORT_TYPE)
blocktype = STOP_TYPE;
else /* NORM_TYPE, STOP_TYPE */
blocktype = NORM_TYPE;
/* threshold calculation (part 2) */
for (sfb = 0; sfb < SBMAX_l; sfb++)
{
int bu = bu_l[sfb];
int bo = bo_l[sfb];
double en = w1_l[sfb] * eb[bu] + w2_l[sfb] * eb[bo];
for (b = bu+1; b < bo; b++)
en += eb[b];
if (en != 0.0)
{
double thm = w1_l[sfb] * thr[bu] + w2_l[sfb] * thr[bo];
for (b = bu+1; b < bo; b++)
thm += thr[b];
ratio[ch][sfb] = thm / en;
}
else
ratio[ch][sfb] = 0.0;
}
}
else
{
/* attack : use short blocks */
blocktype = SHORT_TYPE;
#if ORG_BLOCK_SELECT
if (blocktype_old[ch] == NORM_TYPE)
blocktype_old[ch] = START_TYPE;
else /* SHORT_TYPE, STOP_TYPE */
blocktype_old[ch] = SHORT_TYPE;
#else /* ISO */
if (blocktype_old[ch] == SHORT_TYPE)
blocktype_old[ch] = SHORT_TYPE;
else /* NORM_TYPE, STOP_TYPE */
blocktype_old[ch] = START_TYPE;
#endif
/* threshold calculation for short blocks */
for (sblock = 0; sblock < 3; sblock++)
{
#if ORG_NUMLINES_NORM || !NEW_L3PARM_TABLES
for (b = 0; b < cbmax_s; b++)
eb[b] = 0.0;
for (j = 0; j < HBLKSIZE_s; j++)
eb[partition_s[j]] += energy_s[sblock][j];
#else
j = 0;
for (b = 0; b < cbmax_s; b++)
{
eb[b] = 0.0;
/*
Calculate the energy and the unpredictability in the threshold
calculation partitions
cbmax_s holds the number of valid numlines_s entries
*/
k = numlines_s[b];
do {
eb[b] += energy_s[sblock][j];
} while (j++, --k);
}
s3_ptr = normed_s3_s;
#endif
for (b = 0; b < cbmax_s; b++)
{
FLOAT nb;
FLOAT ecb = 0.0;
#if ORG_NUMLINES_NORM || !NEW_L3PARM_TABLES
for (k = 0; k < cbmax_s; k++)
ecb += s3_l[b][k] * eb[k];
nb = ecb * norm_l[b] * exp((double) SNR_s[b] * LN_TO_LOG10);
#else
for (k = lo_s3_s[b]; k < hi_s3_s[b]; k++)
ecb += *s3_ptr++ * eb[k];
nb = ecb * exp((double) SNR_s[b] * LN_TO_LOG10); /* our ecb is already normed */
#endif
thr[b] = MAX(qthr_s[b], nb);
}
for (sfb = 0; sfb < SBMAX_s; sfb++)
{
int bu = bu_s[sfb];
int bo = bo_s[sfb];
double en = w1_s[sfb] * eb[bu] + w2_s[sfb] * eb[bo];
for (b = bu+1; b < bo; b++)
en += eb[b];
if (en != 0.0)
{
double thm = w1_s[sfb] * thr[bu] + w2_s[sfb] * thr[bo];
for (b = bu+1; b < bo; b++)
thm += thr[b];
ratio_s[ch][sfb][sblock] = thm / en;
}
else
ratio_s[ch][sfb][sblock] = 0.0;
}
}
}
cod_info->block_type = blocktype_old[ch];
blocktype_old[ch] = blocktype;
if ( cod_info->block_type == NORM_TYPE )
cod_info->window_switching_flag = 0;
else
cod_info->window_switching_flag = 1;
cod_info->mixed_block_flag = 0;
}
/*____ L3para_read() __________________________________________________________*/
#if NEW_L3PARM_TABLES
static void L3para_read (int sfreq)
{
int sfreq_idx;
l3_parm_block *parm;
double *bval_l, *bval_s;
#if ORG_NUMLINES_NORM
int cbmax_l, cbmax_s;
int i, j, k;
#else
double *norm_l, *norm_s;
#endif
/*
Set parameter block
*/
switch (sfreq)
{
case 32000: sfreq_idx = 2; break;
case 44100: sfreq_idx = 0; break;
case 48000: sfreq_idx = 1; break;
default : return; /* Just to avoid compiler warnings */
}
parm = l3_parm + sfreq_idx;
/*
Read long block data
*/
cbmax_l = parm->long_data.cbmax_l;
#if ORG_NUMLINES_NORM
for (i = 0, j = 0; i < cbmax_l; i++)
{
numlines_l[i] = parm->long_data.numlines_l[i];
for (k = 0; k < numlines_l[i]; k++)
partition_l[j++] = i;
}
#else
numlines_l = parm->long_data.numlines_l;
#endif
minval = parm->long_data.minval;
qthr_l = parm->long_data.qthr_l;
norm_l = parm->long_data.norm_l;
bval_l = parm->long_data.bval_l;
/*
Compute the normed spreading function norm_l[i] * s3_l[i][j]
*/
#if ORG_NUMLINES_NORM
for (i = 0; i < cbmax_l; i++)
{
double x, temp, tempx, tempy;
for (j = 0; j < cbmax_l; j++)
{
/* tempx = (bval_l[i]-bval_l[j]) * 1.05; */
if (j >= i)
tempx = (bval_l[i]-bval_l[j]) * 3.0;
else
tempx = (bval_l[i]-bval_l[j]) * 1.5;
/* if (j >= i) tempx = (bval_l[j]-bval_l[i]) * 3.0;
else tempx = (bval_l[j]-bval_l[i]) * 1.5; */
if (tempx > 0.5 && tempx < 2.5)
{
temp = tempx - 0.5;
x = 8.0 * temp * (temp-2.0);
}
else x = 0.0;
tempx += 0.474;
tempy = 15.811389 + 7.5*tempx - 17.5*sqrt(1.0+tempx*tempx);
if (tempy <= -60.0) s3_l[i][j] = 0.0;
else s3_l[i][j] = exp((x + tempy) * LN_TO_LOG10);
}
}
#else
calc_normed_spreading (cbmax_l, bval_l, normed_s3_l, lo_s3_l, hi_s3_l, norm_l);
#endif
/*
Read short block data
*/
cbmax_s = parm->short_data.cbmax_s;
#if ORG_NUMLINES_NORM
for (i = 0, j = 0; i < cbmax_s; i++)
{
numlines_l[i] = parm->short_data.numlines_s[i];
for (k = 0; k < numlines_l[i]; k++)
partition_s[j++] = i;
}
#else
numlines_s = parm->short_data.numlines_s;
#endif
qthr_s = parm->short_data.qthr_s;
norm_s = parm->short_data.norm_s;
SNR_s = parm->short_data.SNR_s;
bval_s = parm->short_data.bval_s;
#if !ORG_NUMLINES_NORM
/*
Compute the normed spreading function norm_s[i] * s3_s[i][j]
*/
calc_normed_spreading (cbmax_s, bval_s, normed_s3_s, lo_s3_s, hi_s3_s, norm_s);
#endif
/*
Read long block data for converting threshold
calculation partitions to scale factor bands
*/
cbw_l = parm->long_thres.cbw_l;
bu_l = parm->long_thres.bu_l;
bo_l = parm->long_thres.bo_l;
w1_l = parm->long_thres.w1_l;
w2_l = parm->long_thres.w2_l;
/*
Read short block data for converting threshold
calculation partitions to scale factor bands
*/
cbw_s = parm->short_thres.cbw_s;
bu_s = parm->short_thres.bu_s;
bo_s = parm->short_thres.bo_s;
w1_s = parm->short_thres.w1_s;
w2_s = parm->short_thres.w2_s;
}
#else /* NEW_L3PARM_TABLES */
static void L3para_read
(
int sfreq,
int numlines_l[CBANDS],
int partition_l[HBLKSIZE],
double minval[CBANDS],
double qthr_l[CBANDS],
double norm_l[CBANDS],
double s3_l[CBANDS][CBANDS],
int partition_s[HBLKSIZE_s],
double qthr_s[CBANDS_s],
double norm_s[CBANDS_s],
double SNR_s[CBANDS_s],
int cbw_l[SBMAX_l],
int bu_l[SBMAX_l],
int bo_l[SBMAX_l],
double w1_l[SBMAX_l],
double w2_l[SBMAX_l],
int cbw_s[SBMAX_s],
int bu_s[SBMAX_s],
int bo_s[SBMAX_s],
double w1_s[SBMAX_s],
double w2_s[SBMAX_s]
)
{
static double bval_l[CBANDS];
int cbmax_tp;
int sbmax;
int i, j, k, k2;
psyDataElem *rpa1;
psyDataElem2 *rpa2;
psyDataElem3 *rpa3;
/* Read long block data */
switch (sfreq)
{
case 32000: rpa1 = psy_longBlock_32000_58; cbmax_tp = 59; break;
case 44100: rpa1 = psy_longBlock_44100_62; cbmax_tp = 63; break;
case 48000: rpa1 = psy_longBlock_48000_61; cbmax_tp = 62; break;
default : return; /* Just to avoid compiler warnings */
}
for (i = 0, k2 = 0; i < cbmax_tp; i++)
{
numlines_l[i] = rpa1->lines;
minval[i] = rpa1->minVal;
qthr_l[i] = rpa1->qthr;
norm_l[i] = rpa1->norm;
bval_l[i] = rpa1->bVal;
rpa1++;
for (k = 0; k < numlines_l[i]; k++)
partition_l[k2++] = i;
}
/************************************************************************
* Now compute the spreading function, s[j][i], the value of the spread-*
* ing function, centered at band j, for band i, store for later use *
************************************************************************/
for (i = 0; i < cbmax_tp; i++)
{
double x, temp, tempx, tempy;
for (j = 0; j < cbmax_tp; j++)
{
/* tempx = (bval_l[i]-bval_l[j]) * 1.05; */
if (j >= i)
tempx = (bval_l[i]-bval_l[j]) * 3.0;
else
tempx = (bval_l[i]-bval_l[j]) * 1.5;
/* if (j >= i) tempx = (bval_l[j]-bval_l[i]) * 3.0;
else tempx = (bval_l[j]-bval_l[i]) * 1.5; */
if (tempx > 0.5 && tempx < 2.5)
{
temp = tempx - 0.5;
x = 8.0 * temp * (temp-2.0);
}
else x = 0.0;
tempx += 0.474;
tempy = 15.811389 + 7.5*tempx - 17.5*sqrt(1.0+tempx*tempx);
if (tempy <= -60.0) s3_l[i][j] = 0.0;
else s3_l[i][j] = exp((x + tempy) * LN_TO_LOG10);
}
}
/* Read short block data */
switch (sfreq)
{
case 32000: rpa2 = psy_shortBlock_32000_41; cbmax_tp = 42; break;
case 44100: rpa2 = psy_shortBlock_44100_38; cbmax_tp = 39; break;
case 48000: rpa2 = psy_shortBlock_48000_37; cbmax_tp = 38; break;
default : return; /* Just to avoid compiler warnings */
}
for (i = 0, k2 = 0; i < cbmax_tp; i++)
{
numlines_l[i] = rpa2->lines;
qthr_s[i] = rpa2->qthr;
norm_s[i] = rpa2->norm;
SNR_s[i] = rpa2->snr;
rpa2++;
for (k = 0; k < numlines_l[i]; k++)
partition_s[k2++] = i;
}
/* Read long block data for converting threshold calculation
partitions to scale factor bands */
switch (sfreq)
{
case 32000: rpa3 = psy_data3_32000_20; break;
case 44100: rpa3 = psy_data3_44100_20; break;
case 48000: rpa3 = psy_data3_48000_20; break;
default : return; /* Just to avoid compiler warnings */
}
sbmax = SBMAX_l;
for (i = 0; i < sbmax; i++)
{
cbw_l[i] = rpa3->cbw;
bu_l[i] = rpa3->bu;
bo_l[i] = rpa3->bo;
w1_l[i] = rpa3->w1;
w2_l[i] = rpa3->w2;
rpa3++;
}
/* Read short block data for converting threshold calculation
partitions to scale factor bands */
switch (sfreq)
{
case 32000: rpa3 = psy_data4_32000_11; break;
case 44100: rpa3 = psy_data4_44100_11; break;
case 48000: rpa3 = psy_data4_48000_11; break;
default : return; /* Just to avoid compiler warnings */
}
sbmax = SBMAX_s;
for (i = 0; i < sbmax; i++)
{
cbw_s[i] = rpa3->cbw;
bu_s[i] = rpa3->bu;
bo_s[i] = rpa3->bo;
w1_s[i] = rpa3->w1;
w2_s[i] = rpa3->w2;
rpa3++;
}
}
#endif /* NEW_L3PARM_TABLES */
#if !ORG_NUMLINES_NORM && NEW_L3PARM_TABLES
/* ======================================================================================== */
/* calc_normed_spreading */
/* ======================================================================================== */
/*
Compute the normed spreading function,
the normed value of the spreading function,
centered at band j, for band i, store for later use
Since this is a band matrix, we store only the non-zero entries
in linear order in the single dimension array normed_s3.
The array has to be accessed in linear order, too, starting with line 0,
up to line cbmax-1. For line b, the current entries represent
norm[b] * s3[b][lo_s3[b]] ... norm[b] * s3[b][hi_s3[b]-1]
Normally, we could easily compute the norm [building the reciprocal of the line sum].
Alas, dist10 uses somewhat (strange and) different, that made our norm differring too
much at the last few lines. Thus, we renounce and use the original values.
*/
static void calc_normed_spreading
(
int cbmax, /* number of lines and rows */
const double bval[], /* input values to compute the matrix */
FLOAT s3_ptr[], /* the resulting non-zero entries */
int lo_s3[],
int hi_s3[],
const double norm[]
)
{
double arg, x, y;
double s3[CBANDS];
int i, j;
int non_zero_part;
for (i = 0; i < cbmax; i++)
{
non_zero_part = FALSE;
hi_s3[i] = cbmax; /* we preset this value for the case that the line ends with a non-zero entry */
for (j = 0; j < cbmax; j++)
{
if (j >= i)
arg = (bval[i] - bval[j]) * 3.0;
else
arg = (bval[i] - bval[j]) * 1.5;
if (arg > 0.5 && arg < 2.5)
x = 8.0 * (arg - 0.5) * (arg - 2.5);
else
x = 0.0;
arg += 0.474;
y = 15.811389 + 7.5 * arg - 17.5 * sqrt(1.0 + arg * arg);
if (y <= -60.0)
{
if (non_zero_part) /* only zeroes will follow */
{
hi_s3[i] = j;
break; /* so cut the computing for this line */
}
}
else
{
s3[j] = exp((x + y) * LN_TO_LOG10);
if (! non_zero_part)
{
lo_s3[i] = j;
non_zero_part = TRUE; /* the first non-zero entry ends the non_zero_part */
}
}
}
for (j = lo_s3[i]; j < hi_s3[i]; j++)
*s3_ptr++ = s3[j] * norm[i];
}
}
#endif /* ORG_NUMLINES_NORM */
|