summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMonty <xiphmont@xiph.org>2001-12-19 07:33:52 +0000
committerMonty <xiphmont@xiph.org>2001-12-19 07:33:52 +0000
commita06da3587f26a6c068ed87a0d63d59d839399858 (patch)
tree5d648fa4d6113475db6879b336c9b2193cdae78d
parent065bbd52db2372421d9ecdf0704bc12280eec514 (diff)
downloadlibvorbis-git-a06da3587f26a6c068ed87a0d63d59d839399858.tar.gz
bitrate management is active
svn path=/trunk/vorbis/; revision=2856
-rw-r--r--lib/bitrate.c23
-rw-r--r--lib/bitrate.h4
-rw-r--r--lib/modes/residue_44.h6
-rw-r--r--lib/vorbisenc.c197
4 files changed, 183 insertions, 47 deletions
diff --git a/lib/bitrate.c b/lib/bitrate.c
index 6f19bf0e..0bfc1e48 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.4 2001/12/19 01:08:13 xiphmont Exp $
+ last mod: $Id: bitrate.c,v 1.5 2001/12/19 07:33:51 xiphmont Exp $
********************************************************************/
@@ -283,7 +283,7 @@ int vorbis_bitrate_addblock(vorbis_block *vb){
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 */
@@ -310,7 +310,7 @@ int vorbis_bitrate_addblock(vorbis_block *vb){
/* apply the average floater to new blocks */
bin=bm->avgfloat*BITTRACK_DIVISOR; /* truncate on purpose */
- fprintf(stderr,"float:%d ",bin);
+ fprintf(stderr,"u:%f l:%f float:%d ",upper,lower,bin);
while(bm->avg_centeracc>desired_center){
int samples=
samples=ci->blocksizes[bm->queue_actual[bm->avg_center]&
@@ -328,14 +328,20 @@ int vorbis_bitrate_addblock(vorbis_block *vb){
/* track noise bias triggers and noise bias */
if(bm->avgfloat<bi->avgfloat_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)
+ if(-bm->noisetrigger_request>(signed long)(bm->avg_sampleacc)/2)
bm->avgnoise-=1.f;
bm->noisetrigger_postpone=bm->avg_sampleacc/2;
}
@@ -358,7 +364,7 @@ int vorbis_bitrate_addblock(vorbis_block *vb){
if(bm->avgnoise>bi->avgfloat_noise_maxval)
bm->avgnoise=bi->avgfloat_noise_maxval;
}
- fprintf(stderr,"noise:%f req:%ld trigger:%ld\n",bm->avgnoise,
+ fprintf(stderr,"noise:%f req:%f trigger:%ld\n",bm->avgnoise,
bm->noisetrigger_request,bm->noisetrigger_postpone);
}
@@ -435,7 +441,8 @@ int vorbis_bitrate_addblock(vorbis_block *vb){
int limit=0;
fprintf(stderr,"prelimit:%dkbps ",(int)bitrate/1000);
- if(bitrate>bi->queue_hardmax || bitrate<bi->queue_hardmin){
+ if((bi->queue_hardmax>0 && bitrate>bi->queue_hardmax) ||
+ (bi->queue_hardmin>0 && bitrate<bi->queue_hardmin)){
int newstack;
int stackctr;
long bitsum=limit_sum(bm,0);
diff --git a/lib/bitrate.h b/lib/bitrate.h
index 96675f07..87ef7040 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.2 2001/12/12 09:45:24 xiphmont Exp $
+ last mod: $Id: bitrate.h,v 1.3 2001/12/19 07:33:51 xiphmont Exp $
********************************************************************/
@@ -56,7 +56,7 @@ typedef struct bitrate_manager_state {
double avgfloat;
double avgnoise;
long noisetrigger_postpone;
- long noisetrigger_request;
+ double noisetrigger_request;
/* unfortunately, we need to hold queued packet data somewhere */
oggpack_buffer *queue_packet_buffers;
diff --git a/lib/modes/residue_44.h b/lib/modes/residue_44.h
index 7d91d1ba..2babf67e 100644
--- a/lib/modes/residue_44.h
+++ b/lib/modes/residue_44.h
@@ -11,7 +11,7 @@
v ********************************************************************
function: toplevel residue templates for 32/44.1/48kHz
- last mod: $Id: residue_44.h,v 1.5 2001/12/19 01:10:27 xiphmont Exp $
+ last mod: $Id: residue_44.h,v 1.6 2001/12/19 07:33:52 xiphmont Exp $
********************************************************************/
@@ -26,8 +26,8 @@ static bitrate_manager_info _bm_44_default={
4.0, 0., -1., .05,
-.05, .05,
- 3.5,5.0,
- -10.f,+2.f
+ 3.2,5.0,
+ -6.f,+2.f
};
/***** residue backends *********************************************/
diff --git a/lib/vorbisenc.c b/lib/vorbisenc.c
index 260433ee..39ebcf06 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.25 2001/12/19 01:18:40 xiphmont Exp $
+ last mod: $Id: vorbisenc.c,v 1.26 2001/12/19 07:33:51 xiphmont Exp $
********************************************************************/
@@ -609,7 +609,7 @@ static int vorbis_encode_lowpass_setup(vorbis_info *vi,double q,int block){
/* the final setup call */
int vorbis_encode_setup_init(vorbis_info *vi){
int ret=0;
- long rate=vi->rate;
+ /*long rate=vi->rate;*/
long channels=vi->channels;
codec_setup_info *ci=vi->codec_setup;
highlevel_encode_setup *hi=&ci->hi;
@@ -667,9 +667,16 @@ int vorbis_encode_setup_init(vorbis_info *vi){
3,_psy_tone_masterguard,_psy_tone_suppress,
_vp_peakguard);
- ret|=vorbis_encode_noisebias_setup(vi,hi->blocktype[0].noise_bias_quality,
- 0,_psy_noise_suppress,_psy_noisebias_impulse,
- _psy_noiseguards_short);
+ if(hi->impulse_block_p){
+ ret|=vorbis_encode_noisebias_setup(vi,hi->blocktype[0].noise_bias_quality,
+ 0,_psy_noise_suppress,_psy_noisebias_impulse,
+ _psy_noiseguards_short);
+ }else{
+ ret|=vorbis_encode_noisebias_setup(vi,hi->blocktype[0].noise_bias_quality,
+ 0,_psy_noise_suppress,_psy_noisebias_other,
+ _psy_noiseguards_short);
+ }
+
ret|=vorbis_encode_noisebias_setup(vi,hi->blocktype[1].noise_bias_quality,
1,_psy_noise_suppress,_psy_noisebias_other,
_psy_noiseguards_short);
@@ -745,6 +752,68 @@ int vorbis_encode_setup_init(vorbis_info *vi){
}
+/* this is only tuned for 44.1kHz right now. S'ok, for other rates it
+ just doesn't guess */
+static double ratepch_un44[11]=
+ {40000.,50000.,60000.,70000.,75000.,85000.,105000.,
+ 115000.,135000.,160000.,250000.};
+static double ratepch_st44[11]=
+ {32000.,40000.,48000.,56000.,64000.,
+ 80000.,96000.,112000.,128000.,160000.,250000.};
+
+static double vbr_to_approx_bitrate(int ch,int coupled,
+ double q,long srate){
+ int iq=q*10.;
+ double dq;
+ double *r=NULL;
+
+ if(iq==10){
+ iq=9;
+ dq=1.;
+ }else{
+ dq=q*10.-iq;
+ }
+
+ if(srate>42000 && srate<46000){
+ if(coupled)
+ r=ratepch_st44;
+ else
+ r=ratepch_un44;
+ }
+
+ if(r==NULL)
+ return(-1);
+
+ return((r[iq]*(1.-dq)+r[iq+1]*dq)*ch);
+}
+
+static double approx_bitrate_to_vbr(int ch,int coupled,
+ double bitrate,long srate){
+ double *r=NULL,del;
+ int i;
+
+ if(srate>42000 && srate<46000){
+ if(coupled)
+ r=ratepch_st44;
+ else
+ r=ratepch_un44;
+ }
+
+ if(r==NULL)
+ return(-1.);
+
+ bitrate/=ch;
+
+ if(bitrate<r[0])return(0.);
+ for(i=0;i<10;i++)
+ if(r[i]<bitrate && r[i+1]>=bitrate)break;
+ if(i==10)return(10.);
+
+ del=(bitrate-r[i])/(r[i+1]-r[i]);
+
+ return((i+del)*.1);
+}
+
/* only populates the high-level settings so that we can tweak with ctl before final setup */
int vorbis_encode_setup_vbr(vorbis_info *vi,
long channels,
@@ -808,7 +877,11 @@ int vorbis_encode_setup_vbr(vorbis_info *vi,
_psy_lowpass_44[iq]*(1.-dq)+_psy_lowpass_44[iq+1]*dq;
/* set bitrate approximation */
-
+ vi->bitrate_nominal=vbr_to_approx_bitrate(vi->channels,hi->stereo_couple_p,
+ base_quality,vi->rate);
+ vi->bitrate_lower=-1;
+ vi->bitrate_upper=-1;
+ vi->bitrate_window=-1;
return(ret);
}
@@ -833,6 +906,81 @@ int vorbis_encode_init_vbr(vorbis_info *vi,
return(ret);
}
+int vorbis_encode_setup_managed(vorbis_info *vi,
+ long channels,
+ long rate,
+
+ long max_bitrate,
+ long nominal_bitrate,
+ long min_bitrate){
+
+ double approx_vbr=approx_bitrate_to_vbr(channels,(channels==2),
+ nominal_bitrate,rate);
+ int ret=0;
+ if(approx_vbr<0)return(OV_EIMPL);
+
+ if(nominal_bitrate<=0.){
+ if(max_bitrate>0.){
+ nominal_bitrate=max_bitrate*.875;
+ }else{
+ if(min_bitrate>0.){
+ nominal_bitrate=min_bitrate;
+ }else{
+ return(OV_EINVAL);
+ }
+ }
+ }
+
+ ret=vorbis_encode_setup_vbr(vi,channels,rate,approx_vbr);
+ if(ret){
+ vorbis_info_clear(vi);
+ return ret;
+ }
+
+ /* adjust to make management's life easier. Use the ctl() interface
+ once it's implemented */
+ {
+ codec_setup_info *ci=vi->codec_setup;
+ highlevel_encode_setup *hi=&ci->hi;
+
+ /* backfills */
+ hi->stereo_backfill_p=1;
+ hi->residue_backfill_p=1;
+
+ /* no impulse blocks */
+ hi->impulse_block_p=0;
+ /* de-rate stereo */
+ if(hi->stereo_point_dB && hi->stereo_couple_p && channels==2){
+ hi->stereo_point_dB++;
+ if(hi->stereo_point_dB>3)hi->stereo_point_dB=3;
+ }else{
+ /* else, slug the vbr noise setting */
+ int i;
+ for(i=0;i<4;i++){
+ hi->blocktype[i].noise_bias_quality-=.1;
+ if(hi->blocktype[i].noise_bias_quality<0.)
+ hi->blocktype[i].noise_bias_quality=0.;
+ }
+ }
+
+ /* initialize management. Currently hardcoded for 44, but so is above. */
+ memcpy(&ci->bi,&_bm_44_default,sizeof(ci->bi));
+ ci->bi.queue_hardmin=min_bitrate;
+ ci->bi.queue_hardmax=max_bitrate;
+
+ ci->bi.queue_avgmin=nominal_bitrate;
+ ci->bi.queue_avgmax=nominal_bitrate;
+
+ /* 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.;
+ }
+
+ }
+ return(ret);
+}
+
int vorbis_encode_init(vorbis_info *vi,
long channels,
long rate,
@@ -841,34 +989,15 @@ int vorbis_encode_init(vorbis_info *vi,
long nominal_bitrate,
long min_bitrate){
- /* it's temporary while I do the merge; relax */
- if(rate>40000){
- if(nominal_bitrate>360000){
- return(vorbis_encode_init_vbr(vi,channels,rate, 1.));
- }else if(nominal_bitrate>270000){
- return(vorbis_encode_init_vbr(vi,channels,rate, .9));
- }else if(nominal_bitrate>230000){
- return(vorbis_encode_init_vbr(vi,channels,rate, .8));
- }else if(nominal_bitrate>200000){
- return(vorbis_encode_init_vbr(vi,channels,rate, .7));
- }else if(nominal_bitrate>180000){
- return(vorbis_encode_init_vbr(vi,channels,rate, .6));
- }else if(nominal_bitrate>140000){
- return(vorbis_encode_init_vbr(vi,channels,rate, .5));
- }else if(nominal_bitrate>120000){
- return(vorbis_encode_init_vbr(vi,channels,rate, .4));
- }else if(nominal_bitrate>100000){
- return(vorbis_encode_init_vbr(vi,channels,rate, .3));
- }else if(nominal_bitrate>90000){
- return(vorbis_encode_init_vbr(vi,channels,rate, .2));
- }else if(nominal_bitrate>75000){
- return(vorbis_encode_init_vbr(vi,channels,rate, .1));
- }else{
- return(vorbis_encode_init_vbr(vi,channels,rate, .0));
- }
- }
-
- return(OV_EIMPL);
+ int ret=vorbis_encode_setup_managed(vi,channels,rate,
+ max_bitrate,
+ nominal_bitrate,
+ min_bitrate);
+
+ ret=vorbis_encode_setup_init(vi);
+ if(ret)
+ vorbis_info_clear(vi);
+ return(ret);
}
int vorbis_encode_ctl(vorbis_info *vi,int number,void *arg){