From: "Gabriel Bouvigne" <[EMAIL PROTECTED]>
Subject: [MP3 ENCODER] today's idea
Date: Fri, 16 Jun 2000 23:55:52 +0200
> Here is today's idea for cbr encoding:
>
> assuming we have to granules A and B, A got a distortion level of 0.1
> (arbitrary choosen unit) and B a distortion level of 0.6.
>
> The idea would be in this case, as B got an high distortion, to requantize
> granule A in order to get, as an example, a distortion ratio of 0.3. This
> would save bits, and increase the bit reservoir for next granule, which then
> could have a distortion ratio of 0.4. So the idea would be in the case of a
> granule containing high or very high distortion to reduce the previous
> granule quality in order to get a more constant distortion ratio. However
> such a thing would increase buffering complexity.
>
> What do you think about it?
>
If we don't use reservoir much optimally, it may not be difficult.
Here is a quick hack of such adjustment.
Some parameters in this code are not the best value.
Iwasa Kazmi
/************************************************************************/
/* iteration_loop() */
/************************************************************************/
void
iteration_loop( lame_global_flags *gfp,
FLOAT8 pe[2][2], FLOAT8 ms_ener_ratio[2],
FLOAT8 xr[2][2][576], III_psy_ratio ratio[2][2],
int l3_enc[2][2][576],
III_scalefac_t scalefac[2][2])
{
lame_internal_flags *gfc=gfp->internal_flags;
FLOAT8 xfsf[2][2][4][SBMAX_l];
FLOAT8 noise[2][2][4]; /* over,max_noise,over_noise,tot_noise; */
III_psy_xmin l3_xmin[2];
gr_info *cod_info;
int bitsPerFrame;
int mean_bits,max_bits;
int ch, gr, i, bit_rate;
III_side_info_t *l3_side;
FLOAT8 xr_save[2][2][576];
int targ_bits[2][2];
l3_side = &gfc->l3_side;
iteration_init(gfp,l3_side,l3_enc);
bit_rate = bitrate_table[gfp->version][gfc->bitrate_index];
getframebits(gfp,&bitsPerFrame, &mean_bits);
ResvFrameBegin(gfp, l3_side, mean_bits, bitsPerFrame );
/* quantize! */
for ( gr = 0; gr < gfc->mode_gr; gr++ ) {
if (gfc->mode_ext==MPG_MD_MS_LR)
ms_convert(xr[gr], xr[gr]);
max_bits=on_pe(gfp,pe,l3_side,targ_bits[gr],mean_bits, gr);
if (gfc->mode_ext==MPG_MD_MS_LR)
reduce_side(targ_bits[gr],ms_ener_ratio[gr],mean_bits,max_bits);
}
memcpy(xr_save, xr, sizeof(xr_save));
for (ch=0 ; ch < gfc->stereo ; ch ++) {
int try_count = 0;
try:
for ( gr = 0; gr < gfc->mode_gr; gr++ ) {
cod_info = &l3_side->gr[gr].ch[ch].tt;
if (!init_outer_loop(gfp,xr[gr][ch], cod_info))
{
/* xr contains no energy
* cod_info was set in init_outer_loop above
*/
memset(&scalefac[gr][ch],0,sizeof(III_scalefac_t));
memset(l3_enc[gr][ch],0,576*sizeof(int));
memset(xfsf[gr][ch],0,sizeof(xfsf[gr][ch]));
noise[gr][ch][0]=noise[gr][ch][1]=noise[gr][ch][2]=noise[gr][ch][3]=0;
}
else
{
int try_count = 0;
calc_xmin(gfp,xr[gr][ch], &ratio[gr][ch], cod_info, &l3_xmin[ch]);
outer_loop( gfp,xr[gr][ch], targ_bits[gr][ch], noise[gr][ch],
&l3_xmin[ch], l3_enc[gr][ch],
&scalefac[gr][ch], cod_info, xfsf[gr][ch], ch);
}
}
try_count++;
if (gfc->mode_gr == 2 && try_count < 5)
{
FLOAT8 noise_d;
noise_d= noise[0][ch][2] - noise[1][ch][2];
printf("gr noise balancing: %f\n", noise_d);
if (noise_d > 0.6)
{
int bits;
bits = targ_bits[1][ch] * 0.03;
targ_bits[1][ch] -= bits;
targ_bits[0][ch] += bits;
printf("gr noise balancing: try %d (+%d) %f\n", try_count, bits, noise_d);
memcpy(xr[0][ch], xr_save[0][ch], sizeof(FLOAT8)*576);
memcpy(xr[1][ch], xr_save[1][ch], sizeof(FLOAT8)*576);
goto try;
}
if (noise_d < -0.6)
{
int bits;
bits = targ_bits[0][ch] * 0.03;
targ_bits[0][ch] -= bits;
targ_bits[1][ch] += bits;
printf("gr noise balancing: try %d (-%d) %f\n", try_count, bits, noise_d);
memcpy(xr[0][ch], xr_save[0][ch], sizeof(FLOAT8)*576);
memcpy(xr[1][ch], xr_save[1][ch], sizeof(FLOAT8)*576);
goto try;
}
}
}
for ( gr = 0; gr < gfc->mode_gr; gr++ ) {
for (ch=0 ; ch < gfc->stereo ; ch ++) {
cod_info = &l3_side->gr[gr].ch[ch].tt;
best_scalefac_store(gfp,gr, ch, l3_enc, l3_side, scalefac);
if (gfc->use_best_huffman==1 && cod_info->block_type != SHORT_TYPE) {
best_huffman_divide(gfc, gr, ch, cod_info, l3_enc[gr][ch]);
}
assert((int)cod_info->part2_3_length < 4096);
if (gfp->gtkflag)
set_pinfo (gfp, cod_info, &ratio[gr][ch], &scalefac[gr][ch], xr[gr][ch],
xfsf[gr][ch], noise[gr][ch], gr, ch);
#define NORES_TEST
#ifndef NORES_TEST
ResvAdjust(gfp,cod_info, l3_side, mean_bits );
#endif
/* set the sign of l3_enc */
for ( i = 0; i < 576; i++) {
if (xr[gr][ch][i] < 0)
l3_enc[gr][ch][i] *= -1;
}
}
} /* loop over gr */
#ifdef NORES_TEST
/* replace ResvAdjust above with this code if you do not want
the second granule to use bits saved by the first granule.
when combined with --nores, this is usefull for testing only */
for ( gr = 0; gr < gfc->mode_gr; gr++ ) {
for ( ch = 0; ch < gfc->stereo; ch++ ) {
cod_info = &l3_side->gr[gr].ch[ch].tt;
ResvAdjust(gfp, cod_info, l3_side, mean_bits );
}
}
#endif
ResvFrameEnd(gfp,l3_side, mean_bits );
}