blob: 9e4da1d876e64215f60dea75b5f0fc8e9bcf1b5d [file] [log] [blame]
/*
* MP3 quantization
*
* Copyright (c) 1999 Mark Taylor
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <assert.h>
#include "util.h"
#include "l3side.h"
#include "quantize.h"
#include "l3bitstream.h"
#include "reservoir.h"
#include "quantize-pvt.h"
#ifdef HAVEGTK
#include "gtkanal.h"
#endif
#define DEBUGXX
FLOAT8 calc_sfb_ave_noise(FLOAT8 *xr, FLOAT8 *xr34, int stride, int bw, FLOAT8 sfpow)
{
int j;
FLOAT8 xfsf=0;
FLOAT8 sfpow34 = pow(sfpow,3.0/4.0);
for ( j=0; j < stride*bw ; j += stride) {
int ix;
FLOAT8 temp,temp2;
/* ix=(int)( xr34[j]/sfpow34 + 0.4054);*/
ix=floor( xr34[j]/sfpow34);
if (ix > IXMAX_VAL) return -1.0;
temp = fabs(xr[j])- pow43[ix]*sfpow;
if (ix < IXMAX_VAL) {
temp2 = fabs(xr[j])- pow43[ix+1]*sfpow;
if (fabs(temp2)<fabs(temp)) temp=temp2;
}
#ifdef MAXQUANTERROR
temp *= temp;
xfsf = bw*Max(xfsf,temp);
#else
xfsf += temp * temp;
#endif
}
return xfsf/bw;
}
FLOAT8 find_scalefac(FLOAT8 *xr,FLOAT8 *xr34,int stride,int sfb,
FLOAT8 l3_xmin,int bw)
{
FLOAT8 xfsf,sfpow,sf,sf_ok,delsf;
int sf4,sf_ok4,delsf4;
int i;
/* search will range from sf: -52.25 -> 11.25 */
/* search will range from sf4: -209 -> 45 */
sf = -20.5;
sf4 = -82;
delsf = 32;
delsf4 = 128;
sf_ok =10000;
sf_ok4=10000;
for (i=0; i<7; i++) {
delsf /= 2;
delsf4 /= 2;
sfpow = pow(2.0,sf);
/* sfpow = pow(2.0,sf4/4.0); */
xfsf = calc_sfb_ave_noise(xr,xr34,stride,bw,sfpow);
if (xfsf < 0) {
/* scalefactors too small */
sf += delsf;
sf4 += delsf4;
}else{
if (sf_ok==10000) sf_ok=sf;
if (sf_ok4==10000) sf_ok4=sf4;
if (xfsf > l3_xmin) {
/* distortion. try a smaller scalefactor */
sf -= delsf;
sf4 -= delsf4;
}else{
sf_ok=sf;
sf_ok4 = sf4;
sf += delsf;
sf4 += delsf4;
}
}
}
/* sf_ok accurate to within +/- 2*final_value_of_delsf */
assert(sf_ok!=10000);
/* NOTE: noise is not a monotone function of the sf, even though
* the number of bits used is! do a brute force search in the
* neighborhood of sf_ok:
*
* sf = sf_ok + 1.75 works 1% of the time
* sf = sf_ok + 1.50 works 1% of the time
* sf = sf_ok + 1.25 works 2% of the time
* sf = sf_ok + 1.00 works 3% of the time
* sf = sf_ok + 0.75 works 9% of the time
* sf = sf_ok + 0.50 0 % (because it was tried above)
* sf = sf_ok + 0.25 works 39% of the time
* sf = sf_ok + 0.00 works the rest of the time
*/
sf = sf_ok + 0.75;
sf4 = sf_ok4 + 3;
while (sf>(sf_ok+.01)) {
/* sf = sf_ok + 2*delsf was tried above, skip it: */
if (fabs(sf-(sf_ok+2*delsf)) < .01) sf -=.25;
if (sf4 == sf_ok4+2*delsf4) sf4 -=1;
sfpow = pow(2.0,sf);
/* sfpow = pow(2.0,sf4/4.0) */
xfsf = calc_sfb_ave_noise(xr,xr34,stride,bw,sfpow);
if (xfsf > 0) {
if (xfsf <= l3_xmin) return sf;
}
sf -= .25;
sf4 -= 1;
}
return sf_ok;
}
/*
sfb=0..5 scalefac < 16
sfb>5 scalefac < 8
ifqstep = ( cod_info->scalefac_scale == 0 ) ? .5 : 1.0;
ol_sf = (cod_info->global_gain-210.0)/4.0;
ol_sf -= 2*cod_info->subblock_gain[i];
ol_sf -= ifqstep*scalefac[gr][ch].s[sfb][i];
*/
FLOAT8 compute_scalefacs_short(FLOAT8 vbrsf[SBPSY_s][3],gr_info *cod_info,int scalefac[SBPSY_s][3])
{
FLOAT8 maxrange,maxover;
FLOAT8 sf[SBPSY_s][3];
int sfb,i;
int ifqstep_inv = ( cod_info->scalefac_scale == 0 ) ? 2 : 1;
/* make a working copy of the desired scalefacs */
memcpy(sf,vbrsf,SBPSY_s*3*sizeof(FLOAT8));
/* see if we should use subblock gain */
maxover=0;
for ( sfb = 0; sfb < SBPSY_s; sfb++ ) {
for (i=0; i<3; ++i) {
/* ifqstep*scalefac + 2*subblock_gain >= -sf[sfb] */
scalefac[sfb][i]=floor( -sf[sfb][i]*ifqstep_inv +.75 + .0001) ;
if (sfb < 6) maxrange = 15.0/ifqstep_inv;
else maxrange = 7.0/ifqstep_inv;
if (maxrange + sf[sfb][i] > maxover) maxover = maxrange+sf[sfb][i];
}
}
return maxover;
}
/*
sfb=0..10 scalefac < 16
sfb>10 scalefac < 8
ifqstep = ( cod_info->scalefac_scale == 0 ) ? .5 : 1.0;
ol_sf = (cod_info->global_gain-210.0)/4.0;
ol_sf -= ifqstep*scalefac[gr][ch].l[sfb];
if (cod_info->preflag && sfb>=11)
ol_sf -= ifqstep*pretab[sfb];
*/
FLOAT8 compute_scalefacs_long(FLOAT8 vbrsf[SBPSY_l],gr_info *cod_info,int scalefac[SBPSY_l])
{
int sfb;
FLOAT8 sf[SBPSY_l];
FLOAT8 maxrange,maxover;
int ifqstep_inv = ( cod_info->scalefac_scale == 0 ) ? 2 : 1;
/* make a working copy of the desired scalefacs */
memcpy(sf,vbrsf,SBPSY_l*sizeof(FLOAT8));
cod_info->preflag=0;
for ( sfb = 11; sfb < SBPSY_l; sfb++ ) {
if (sf[sfb] + pretab[sfb]/ifqstep_inv > 0) break;
}
if (sfb==SBPSY_l) {
cod_info->preflag=1;
for ( sfb = 11; sfb < SBPSY_l; sfb++ )
sf[sfb] += pretab[sfb]/ifqstep_inv;
}
maxover=0;
for ( sfb = 0; sfb < SBPSY_l; sfb++ ) {
/* ifqstep*scalefac >= -sf[sfb] */
scalefac[sfb]=floor( -sf[sfb]*ifqstep_inv +.75 + .0001) ;
if (sfb < 11) maxrange = 15.0/ifqstep_inv;
else maxrange = 7.0/ifqstep_inv;
if (maxrange + sf[sfb] > maxover) maxover = maxrange+sf[sfb];
}
return maxover;
}
/************************************************************************
*
* VBR_iteration_loop()
*
*
************************************************************************/
void
VBR_iteration_loop_new (lame_global_flags *gfp,
FLOAT8 pe[2][2], FLOAT8 ms_ener_ratio[2],
FLOAT8 xr[2][2][576], III_psy_ratio ratio[2][2],
III_side_info_t * l3_side, int l3_enc[2][2][576],
III_scalefac_t scalefac[2][2])
{
III_psy_xmin l3_xmin[2][2];
FLOAT8 masking_lower_db;
FLOAT8 ifqstep;
int start,end,bw,sfb, i,ch, gr, over;
III_psy_xmin vbrsf;
FLOAT8 vbrmax;
iteration_init(gfp,l3_side,l3_enc);
/* Adjust allowed masking based on quality setting */
/* db_lower varies from -10 to +8 db */
masking_lower_db = -10 + 2*gfp->VBR_q;
/* adjust by -6(min)..0(max) depending on bitrate */
masking_lower = pow(10.0,masking_lower_db/10);
masking_lower = 1;
for (gr = 0; gr < gfp->mode_gr; gr++) {
if (convert_mdct)
ms_convert(xr[gr],xr[gr]);
for (ch = 0; ch < gfp->stereo; ch++) {
FLOAT8 xr34[576];
gr_info *cod_info = &l3_side->gr[gr].ch[ch].tt;
int shortblock;
over = 0;
shortblock = (cod_info->block_type == SHORT_TYPE);
for(i=0;i<576;i++) {
FLOAT8 temp=fabs(xr[gr][ch][i]);
xr34[i]=sqrt(sqrt(temp)*temp);
}
calc_xmin( gfp,xr[gr][ch], &ratio[gr][ch], cod_info, &l3_xmin[gr][ch]);
vbrmax=0;
if (shortblock) {
for ( sfb = 0; sfb < SBPSY_s; sfb++ ) {
for ( i = 0; i < 3; i++ ) {
start = scalefac_band.s[ sfb ];
end = scalefac_band.s[ sfb+1 ];
bw = end - start;
vbrsf.s[sfb][i] = find_scalefac(&xr[gr][ch][3*start+i],&xr34[3*start+i],3,sfb,
masking_lower*l3_xmin[gr][ch].s[sfb][i],bw);
if (vbrsf.s[sfb][i]>vbrmax) vbrmax=vbrsf.s[sfb][i];
}
}
}else{
for ( sfb = 0; sfb < SBPSY_l; sfb++ ) {
start = scalefac_band.l[ sfb ];
end = scalefac_band.l[ sfb+1 ];
bw = end - start;
vbrsf.l[sfb] = find_scalefac(&xr[gr][ch][start],&xr34[start],1,sfb,
masking_lower*l3_xmin[gr][ch].l[sfb],bw);
if (vbrsf.l[sfb]>vbrmax) vbrmax = vbrsf.l[sfb];
}
} /* compute scalefactors */
/* sf = (cod_info->global_gain-210.0)/4.0; */
cod_info->global_gain = floor(4*vbrmax +210 + .5);
if (shortblock) {
for ( sfb = 0; sfb < SBPSY_s; sfb++ ) {
for ( i = 0; i < 3; i++ ) {
vbrsf.s[sfb][i] -= vbrmax;
}
}
cod_info->scalefac_scale = 0;
if (compute_scalefacs_short(vbrsf.s,cod_info,scalefac[gr][ch].s) > 0) {
cod_info->scalefac_scale = 1;
if (compute_scalefacs_short(vbrsf.s,cod_info,scalefac[gr][ch].s) >0) {
/* what do we do now? */
exit(32);
}
}
}else{
for ( sfb = 0; sfb < SBPSY_l; sfb++ )
vbrsf.l[sfb] -= vbrmax;
/* can we get away with scalefac_scale=0? */
cod_info->scalefac_scale = 0;
if (compute_scalefacs_long(vbrsf.l,cod_info,scalefac[gr][ch].l) > 0) {
cod_info->scalefac_scale = 1;
if (compute_scalefacs_long(vbrsf.l,cod_info,scalefac[gr][ch].l) >0) {
/* what do we do now? */
exit(32);
}
}
}
} /* ch */
} /* gr */
}