From 669884bb7b74880a5ace7f7a46ec858943ecc35d Mon Sep 17 00:00:00 2001 From: Monty Date: Sun, 23 Dec 2001 10:12:04 +0000 Subject: [PATCH] bitrate management bugfixes and tuning svn path=/trunk/vorbis/; revision=2897 --- examples/encoder_example.c | 18 +++- lib/bitrate.c | 252 ++++++++++++++++++++++++++------------------- lib/bitrate.h | 3 +- lib/modes/residue_44.h | 10 +- lib/vorbisenc.c | 20 +--- 5 files changed, 172 insertions(+), 131 deletions(-) diff --git a/examples/encoder_example.c b/examples/encoder_example.c index 3870d64..a073149 100644 --- a/examples/encoder_example.c +++ b/examples/encoder_example.c @@ -11,7 +11,7 @@ ******************************************************************** function: simple example encoder - last mod: $Id: encoder_example.c,v 1.32 2001/12/20 01:00:24 segher Exp $ + last mod: $Id: encoder_example.c,v 1.33 2001/12/23 10:12:02 xiphmont Exp $ ********************************************************************/ @@ -73,6 +73,18 @@ int main(){ _setmode( _fileno( stdout ), _O_BINARY ); #endif + +# include + unsigned int mask; + _FPU_GETCW(mask); + /* Set the Linux mask to abort on most FPE's */ + /* if bit is set, we _mask_ SIGFPE on that error! */ + /* mask &= ~( _FPU_MASK_IM | _FPU_MASK_ZM | _FPU_MASK_OM | _FPU_MASK_UM ++);*/ + mask &= ~( _FPU_MASK_IM | _FPU_MASK_ZM | _FPU_MASK_OM ); + _FPU_SETCW(mask); + + /* we cheat on the WAV header; we just bypass the header and never verify that it matches 16bit/stereo/44.1kHz. This is just an example, after all. */ @@ -96,8 +108,8 @@ int main(){ /* (quality mode .4: 44kHz stereo coupled, roughly 128kbps VBR) */ vorbis_info_init(&vi); - vorbis_encode_init_vbr(&vi,2,44100,.1); - /*vorbis_encode_init(&vi,2,44100,70000,64000,-1);*/ + vorbis_encode_init_vbr(&vi,1,44100,.4); + /*vorbis_encode_init(&vi,2,44100,64000,-1,-1);*/ /* add a comment */ vorbis_comment_init(&vc); diff --git a/lib/bitrate.c b/lib/bitrate.c index 3f67c0c..1424348 100644 --- a/lib/bitrate.c +++ b/lib/bitrate.c @@ -11,7 +11,7 @@ ******************************************************************** function: bitrate tracking and management - last mod: $Id: bitrate.c,v 1.6 2001/12/19 08:10:03 xiphmont Exp $ + last mod: $Id: bitrate.c,v 1.7 2001/12/23 10:12:03 xiphmont Exp $ ********************************************************************/ @@ -25,7 +25,26 @@ #include "os.h" #include "bitrate.h" -#define BINBITS(pos,bin) ((bin)>0?bm->queue_binned[(pos)*bins+(bin)-1]:0) + +static long BINBITS(bitrate_manager_state *bm,long pos,long inbin){ + int bins=bm->queue_bins; + int bin=((inbin&0x7fffffffUL)>>BITTRACK_BPT); + ogg_uint32_t lobits=0; + ogg_uint32_t hibits=0; + ogg_uint32_t bitdel; + + if(bin>0)lobits=bm->queue_binned[pos*bins+bin-1]; + if(binqueue_binned[pos*bins+bin]; + else + hibits=lobits; + + bitdel=hibits-lobits; + + return(lobits+bitdel*(inbin&((1<-bins?\ bm->minmax_binstack[(pos)*bins*2+((bin)+bins)-1]:0) @@ -59,7 +78,7 @@ static double floater_interpolate(bitrate_manager_state *bm,vorbis_info *vi, return bin/(double)BITTRACK_DIVISOR; }else{ double delta=(desired_rate-lobitrate)/(hibitrate-lobitrate); - return (bin+delta)/(double)BITTRACK_DIVISOR; + return (bin+delta)/BITTRACK_DIVISOR; } } @@ -124,11 +143,11 @@ void vorbis_bitrate_init(vorbis_info *vi,bitrate_manager_state *bm){ if((bi->queue_hardmin>0 || bi->queue_hardmax>0) && bi->queue_minmax_time>0){ - bm->minmax_binstack=_ogg_malloc((bins+1)*bins*2* + bm->minmax_binstack=_ogg_calloc((bins+1)*bins*2, sizeof(bm->minmax_binstack)); - bm->minmax_posstack=_ogg_malloc((bins+1)* + bm->minmax_posstack=_ogg_calloc((bins+1), sizeof(bm->minmax_posstack)); - bm->minmax_limitstack=_ogg_malloc((bins+1)* + bm->minmax_limitstack=_ogg_calloc((bins+1), sizeof(bm->minmax_limitstack)); }else{ bm->minmax_tail= -1; @@ -273,102 +292,106 @@ int vorbis_bitrate_addblock(vorbis_block *vb){ bm->avg_sampleacc+=ci->blocksizes[vb->W]>>1; bm->avg_centeracc+=ci->blocksizes[vb->W]>>1; - /* update the avg tail if needed */ - while(bm->avg_sampleacc>bm->avg_sampledesired){ - int samples= - ci->blocksizes[bm->queue_actual[bm->avg_tail]&0x80000000UL?1:0]>>1; - for(i=0;iqueue_bins;i++) - bm->avg_binacc[i]-=LACING_ADJUST(bm->queue_binned[bins*bm->avg_tail+i]); - bm->avg_sampleacc-=samples; - bm->avg_tail++; - if(bm->avg_tail>=bm->queue_size)bm->avg_tail=0; - } - - /* update the avg center */ - if(bm->avg_centeracc>desired_center){ - /* choose the new average floater */ - double upper=floater_interpolate(bm,vi,bi->queue_avgmax); - double lower=floater_interpolate(bm,vi,bi->queue_avgmin); - double new=bi->avgfloat_initial,slew; - int bin; - - if(upper>0. && upperavgfloat_minimum) - lower=bi->avgfloat_minimum; - if(lower>new)new=lower; - - slew=new-bm->avgfloat; - - if(slewavgfloat_downhyst || slew>bi->avgfloat_uphyst){ - if(slewavgfloat_downslew_max) - new=bm->avgfloat+bi->avgfloat_downslew_max; - if(slew>bi->avgfloat_upslew_max) - new=bm->avgfloat+bi->avgfloat_upslew_max; - - bm->avgfloat=new; + if(bm->avg_sampleacc>bm->avg_sampledesired || eofflag){ + + /* update the avg tail if needed */ + while(bm->avg_sampleacc>bm->avg_sampledesired){ + int samples= + ci->blocksizes[bm->queue_actual[bm->avg_tail]&0x80000000UL?1:0]>>1; + for(i=0;iqueue_bins;i++) + bm->avg_binacc[i]-=LACING_ADJUST(bm->queue_binned[bins*bm->avg_tail+i]); + bm->avg_sampleacc-=samples; + bm->avg_tail++; + if(bm->avg_tail>=bm->queue_size)bm->avg_tail=0; } - /* apply the average floater to new blocks */ - bin=bm->avgfloat*BITTRACK_DIVISOR; /* truncate on purpose */ - while(bm->avg_centeracc>desired_center){ - int samples= + /* update the avg center */ + if(bm->avg_centeracc>desired_center){ + /* choose the new average floater */ + int samples=ci->blocksizes[vb->W]>>1; + double upper=floater_interpolate(bm,vi,bi->queue_avgmax); + double lower=floater_interpolate(bm,vi,bi->queue_avgmin); + double new=bi->avgfloat_initial,slew; + int bin; + + if(upper>0. && upperavgfloat_minimum) + lower=bi->avgfloat_minimum; + if(lower>new)new=lower; + + slew=(new-bm->avgfloat)/samples*vi->rate; + + if(slewavgfloat_downhyst || slew>bi->avgfloat_uphyst){ + if(slewavgfloat_downslew_max) + new=bm->avgfloat+bi->avgfloat_downslew_max/vi->rate*samples; + if(slew>bi->avgfloat_upslew_max) + new=bm->avgfloat+bi->avgfloat_upslew_max/vi->rate*samples; + + bm->avgfloat=new; + } + + /* apply the average floater to new blocks */ + bin=bm->avgfloat*(BITTRACK_DIVISOR<avg_centeracc>desired_center){ samples=ci->blocksizes[bm->queue_actual[bm->avg_center]& 0x80000000UL?1:0]>>1; + + bm->queue_actual[bm->avg_center]|=bin; + + bm->avg_centeracc-=samples; + bm->avg_center++; + if(bm->noisetrigger_postpone)bm->noisetrigger_postpone-=samples; + if(bm->avg_center>=bm->queue_size)bm->avg_center=0; + } + new_minmax_head=bm->avg_center; - bm->queue_actual[bm->avg_center]|=bin; + /* track noise bias triggers and noise bias */ + if(bm->avgfloatavgfloat_noise_lowtrigger) + bm->noisetrigger_request+=1.f; + else + if(bm->noisetrigger_request>0. && bm->avgnoise>0.) + bm->noisetrigger_request-=.2f; - bm->avg_centeracc-=samples; - bm->avg_center++; - if(bm->noisetrigger_postpone)bm->noisetrigger_postpone-=samples; - if(bm->avg_center>=bm->queue_size)bm->avg_center=0; - } - new_minmax_head=bm->avg_center; - - /* track noise bias triggers and noise bias */ - if(bm->avgfloatavgfloat_noise_lowtrigger) - bm->noisetrigger_request+=1.f; - else - if(bm->noisetrigger_request>0. && bm->avgnoise>0.) - bm->noisetrigger_request-=.2f; - - if(bm->avgfloat>bi->avgfloat_noise_hightrigger) - bm->noisetrigger_request-=1.f; - else - if(bm->noisetrigger_request<0 && bm->avgnoise<0.) - bm->noisetrigger_request+=.2f; - - if(bm->noisetrigger_postpone<=0){ - if(bm->noisetrigger_request<0.){ - bm->avgnoise-=1.f; - if(-bm->noisetrigger_request>(signed long)(bm->avg_sampleacc)/2) - bm->avgnoise-=1.f; - bm->noisetrigger_postpone=bm->avg_sampleacc/2; - } - if(bm->noisetrigger_request>0.){ - bm->avgnoise+=1.f; - if(bm->noisetrigger_request>(signed long)(bm->avg_sampleacc)/2) + if(bm->avgfloat>bi->avgfloat_noise_hightrigger) + bm->noisetrigger_request-=1.f; + else + if(bm->noisetrigger_request<0 && bm->avgnoise<0.) + bm->noisetrigger_request+=.2f; + + if(bm->noisetrigger_postpone<=0){ + if(bm->noisetrigger_request<0.){ + bm->avgnoise-=1.f; + if(-bm->noisetrigger_request>(signed long)(bm->avg_sampleacc)/2) + bm->avgnoise-=1.f; + bm->noisetrigger_postpone=bm->avg_sampleacc/2; + } + if(bm->noisetrigger_request>0.){ bm->avgnoise+=1.f; - bm->noisetrigger_postpone=bm->avg_sampleacc/2; - } + if(bm->noisetrigger_request>(signed long)(bm->avg_sampleacc)/2) + bm->avgnoise+=1.f; + bm->noisetrigger_postpone=bm->avg_sampleacc/2; + } - /* we generally want the noise bias to drift back to zero */ - bm->noisetrigger_request=0.f; - if(bm->avgnoise>0) - bm->noisetrigger_request= -1.; - if(bm->avgnoise<0) - bm->noisetrigger_request= +1.; - - if(bm->avgnoiseavgfloat_noise_minval) - bm->avgnoise=bi->avgfloat_noise_minval; - if(bm->avgnoise>bi->avgfloat_noise_maxval) - bm->avgnoise=bi->avgfloat_noise_maxval; + /* we generally want the noise bias to drift back to zero */ + bm->noisetrigger_request=0.f; + if(bm->avgnoise>0) + bm->noisetrigger_request= -1.; + if(bm->avgnoise<0) + bm->noisetrigger_request= +1.; + + if(bm->avgnoiseavgfloat_noise_minval) + bm->avgnoise=bi->avgfloat_noise_minval; + if(bm->avgnoise>bi->avgfloat_noise_maxval) + bm->avgnoise=bi->avgfloat_noise_maxval; + } } } }else{ /* if we're not using an average tracker, the 'float' is nailed to the avgfloat_initial value. It needs to be set for the min/max to deal properly */ - long bin=bi->avgfloat_initial*BITTRACK_DIVISOR; /* truncate on purpose */ + long bin=bi->avgfloat_initial*(BITTRACK_DIVISOR<queue_actual[head]|=bin; new_minmax_head=next_head; } @@ -406,15 +429,19 @@ int vorbis_bitrate_addblock(vorbis_block *vb){ for(i=0;i<(unsigned int)bins;i++){ bm->minmax_binstack[bm->minmax_stackptr*bins*2+bins+i]+= LACING_ADJUST( - BINBITS(minmax_head, - (bm->queue_actual[minmax_head]&0x7fffffffUL)>i+1? - (bm->queue_actual[minmax_head]&0x7fffffffUL):i+1)); + BINBITS(bm,minmax_head, + (bm->queue_actual[minmax_head]&0x7fffffffUL)> + ((i+1)<queue_actual[minmax_head]: + ((i+1)<minmax_binstack[bm->minmax_stackptr*bins*2+i]+= LACING_ADJUST( - BINBITS(minmax_head, - (bm->queue_actual[minmax_head]&0x7fffffffUL)queue_actual[minmax_head]&0x7fffffffUL):i+1)); + BINBITS(bm,minmax_head, + (bm->queue_actual[minmax_head]&0x7fffffffUL)< + ((i+1)<queue_actual[minmax_head]: + ((i+1)<minmax_posstack[bm->minmax_stackptr]=minmax_head; /* not one @@ -425,7 +452,7 @@ int vorbis_bitrate_addblock(vorbis_block *vb){ bm->minmax_sampleacc+=samples; bm->minmax_acctotal+= LACING_ADJUST( - BINBITS(minmax_head,(bm->queue_actual[minmax_head]&0x7fffffffUL))); + BINBITS(bm,minmax_head,bm->queue_actual[minmax_head])); minmax_head++; if(minmax_head>=bm->queue_size)minmax_head=0; @@ -441,8 +468,9 @@ int vorbis_bitrate_addblock(vorbis_block *vb){ int newstack; int stackctr; long bitsum=limit_sum(bm,0); + bitrate=(double)bitsum/bm->minmax_sampleacc*vi->rate; - + /* we're off rate. Iteratively try out new hard floater limits until we find one that brings us inside. Here's where we see the whole point of the limit stacks. */ @@ -461,6 +489,11 @@ int vorbis_bitrate_addblock(vorbis_block *vb){ if(bitrate>bi->queue_hardmax)limit--; } + for(i=limit-1;i>-bins;i--){ + long bitsum=limit_sum(bm,i); + bitrate=(double)bitsum/bm->minmax_sampleacc*vi->rate; + } + bitsum=limit_sum(bm,limit); bitrate=(double)bitsum/bm->minmax_sampleacc*vi->rate; @@ -510,22 +543,27 @@ int vorbis_bitrate_addblock(vorbis_block *vb){ for(i=0;iminmax_binstack[bins+i]-= /* always comes off the stack bottom */ - LACING_ADJUST(BINBITS(bm->minmax_tail,actual>i+1?actual:i+1)); + LACING_ADJUST(BINBITS(bm,bm->minmax_tail, + actual>((i+1)<minmax_binstack[i]-= - LACING_ADJUST(BINBITS(bm->minmax_tail,actualminmax_tail, + actual<((i+1)<minmax_limitstack[0]>actual) - actual=bm->minmax_limitstack[0]; - if(bins+bm->minmax_limitstack[0]minmax_limitstack[0]; + if((bm->minmax_limitstack[0]<actual) + actual=(bm->minmax_limitstack[0]<minmax_limitstack[0])<minmax_limitstack[0])<minmax_acctotal-=LACING_ADJUST(BINBITS(bm->minmax_tail,actual)); + bm->minmax_acctotal-=LACING_ADJUST(BINBITS(bm,bm->minmax_tail,actual)); bm->minmax_sampleacc-=samples; /* revise queue_actual to reflect the limit */ - bm->queue_actual[bm->minmax_tail]=actual; + bm->queue_actual[bm->minmax_tail]&=0x80000000UL; + bm->queue_actual[bm->minmax_tail]|=actual; if(bm->minmax_tail==bm->minmax_posstack[0]){ /* the stack becomes a FIFO; the first data has fallen off */ @@ -563,14 +601,13 @@ int vorbis_bitrate_flushpacket(vorbis_dsp_state *vd,ogg_packet *op){ bm->queue_head=0; }else{ - long bins=bm->queue_bins; long bin; long bytes; if(bm->next_to_flush==bm->last_to_flush)return(0); - bin=bm->queue_actual[bm->next_to_flush]&0x7fffffffUL; - bytes=(BINBITS(bm->next_to_flush,bin)+7)/8; + bin=bm->queue_actual[bm->next_to_flush]; + bytes=(BINBITS(bm,bm->next_to_flush,bin)+7)/8; memcpy(op,bm->queue_packets+bm->next_to_flush,sizeof(*op)); if(bytesbytes)op->bytes=bytes; @@ -578,6 +615,7 @@ int vorbis_bitrate_flushpacket(vorbis_dsp_state *vd,ogg_packet *op){ bm->next_to_flush++; if(bm->next_to_flush>=bm->queue_size)bm->next_to_flush=0; + if(bytes==0)exit(1); } return(1); diff --git a/lib/bitrate.h b/lib/bitrate.h index 87ef704..5bf6d3b 100644 --- a/lib/bitrate.h +++ b/lib/bitrate.h @@ -11,7 +11,7 @@ ******************************************************************** function: bitrate tracking and management - last mod: $Id: bitrate.h,v 1.3 2001/12/19 07:33:51 xiphmont Exp $ + last mod: $Id: bitrate.h,v 1.4 2001/12/23 10:12:03 xiphmont Exp $ ********************************************************************/ @@ -24,6 +24,7 @@ /* encode side bitrate tracking */ #define BITTRACK_DIVISOR 16 +#define BITTRACK_BPT 6 typedef struct bitrate_manager_state { ogg_uint32_t *queue_binned; ogg_uint32_t *queue_actual; diff --git a/lib/modes/residue_44.h b/lib/modes/residue_44.h index fd543eb..e500f60 100644 --- a/lib/modes/residue_44.h +++ b/lib/modes/residue_44.h @@ -11,7 +11,7 @@ ******************************************************************** function: toplevel residue templates for 32/44.1/48kHz - last mod: $Id: residue_44.h,v 1.9 2001/12/20 01:00:38 segher Exp $ + last mod: $Id: residue_44.h,v 1.10 2001/12/23 10:12:04 xiphmont Exp $ ********************************************************************/ @@ -20,14 +20,14 @@ static bitrate_manager_info _bm_44_default={ /* progressive coding and bitrate controls */ - 2.,.5, + 4.,.0, 2., 0, 0, 0, 0, - 4.0,2.3, -1., .05, - -.05, .05, + 4.0,2.3, -350, .02, + -.00, .00, 3.2,5.0, - -6.f,+2.f + 0.,0. }; /***** residue backends *********************************************/ diff --git a/lib/vorbisenc.c b/lib/vorbisenc.c index 36f920e..204574b 100644 --- a/lib/vorbisenc.c +++ b/lib/vorbisenc.c @@ -11,7 +11,7 @@ ******************************************************************** function: simple programmatic interface for encoder mode setup - last mod: $Id: vorbisenc.c,v 1.31 2001/12/22 09:40:39 xiphmont Exp $ + last mod: $Id: vorbisenc.c,v 1.32 2001/12/23 10:12:03 xiphmont Exp $ ********************************************************************/ @@ -914,6 +914,7 @@ int vorbis_encode_setup_managed(vorbis_info *vi, long nominal_bitrate, long min_bitrate){ + double tnominal=nominal_bitrate; double approx_vbr=approx_bitrate_to_vbr(channels,(channels==2), (float)nominal_bitrate,rate); int ret=0; @@ -973,18 +974,15 @@ int vorbis_encode_setup_managed(vorbis_info *vi, ci->bi.queue_hardmin=min_bitrate; ci->bi.queue_hardmax=max_bitrate; - ci->bi.queue_avgmin=nominal_bitrate; - ci->bi.queue_avgmax=nominal_bitrate; + ci->bi.queue_avgmin=tnominal; + ci->bi.queue_avgmax=tnominal; /* adjust management */ if(max_bitrate<=0. && min_bitrate<=0.){ /* just an average tracker; no reason for the window to be as small as 2s. */ - ci->bi.queue_avg_time=4.; + //ci->bi.queue_avg_time=4.; } ci->bi.avgfloat_noise_maxval=_bm_max_noise_offset[(int)approx_vbr]; - /*if(max_bitrate>0.){ - ci->bi.avgfloat_minimum=0.; - }*/ } return(ret); @@ -1016,11 +1014,3 @@ int vorbis_encode_init(vorbis_info *vi, int vorbis_encode_ctl(vorbis_info *vi,int number,void *arg){ return(OV_EIMPL); } - - - - - - - - -- 2.7.4