From 0024760a1024769fa7d26939f1291c45c36fd51a Mon Sep 17 00:00:00 2001 From: Monty Date: Sun, 10 Oct 1999 20:32:30 +0000 Subject: [PATCH] OK, libvorbis encodes and decodes bitstreams (not complete Vorbis bitstreams, but they work). Lib and examples debugged. Lib does not yet do *any* backend compression and it's slow as hell. We address both next. Monty svn path=/trunk/vorbis/; revision=143 --- lib/Makefile.in | 5 +- lib/analysis.c | 185 +++++++++++++++++++------------------------ lib/bitwise.c | 2 +- lib/bitwise.h | 2 +- lib/block.c | 215 +++++++++++++++++++++++++------------------------- lib/codec.h | 32 ++++---- lib/decoder_example.c | 11 +-- lib/envelope.c | 63 ++++++++++++--- lib/envelope.h | 6 +- lib/info.c | 57 +++++++------ lib/mdct.c | 36 ++------- lib/modes.h | 2 +- lib/psy.c | 31 +------- lib/spectrum.c | 122 ++++++++++++++++++++++++++++ lib/spectrum.h | 23 ++++++ lib/synthesis.c | 100 +++++++++++++++-------- 16 files changed, 525 insertions(+), 367 deletions(-) create mode 100644 lib/spectrum.c create mode 100644 lib/spectrum.h diff --git a/lib/Makefile.in b/lib/Makefile.in index 96a046a..2d3cdc4 100644 --- a/lib/Makefile.in +++ b/lib/Makefile.in @@ -1,6 +1,6 @@ # vorbis makefile configured for use with gcc on any platform -# $Id: Makefile.in,v 1.10 1999/10/05 15:34:56 xiphmont Exp $ +# $Id: Makefile.in,v 1.11 1999/10/10 20:32:17 xiphmont Exp $ ############################################################################### # # @@ -31,7 +31,8 @@ HFILES = mdct.h codec.h bitwise.h envelope.h lpc.h lsp.h modes.h\ psy.h smallft.h window.h xlogmap.h LFILES = framing.o mdct.o smallft.o block.o envelope.o window.o\ - lsp.o lpc.o analysis.o synthesis.o psy.o info.o bitwise.o + lsp.o lpc.o analysis.o synthesis.o psy.o info.o bitwise.o\ + spectrum.o EFILES = encoder_example.o decoder_example.o diff --git a/lib/analysis.c b/lib/analysis.c index 7f54a20..d617d6a 100644 --- a/lib/analysis.c +++ b/lib/analysis.c @@ -14,7 +14,7 @@ function: single-block PCM analysis author: Monty modifications by: Monty - last modification date: Oct 4 1999 + last modification date: Oct 7 1999 ********************************************************************/ @@ -27,31 +27,104 @@ #include "envelope.h" #include "mdct.h" #include "psy.h" +#include "bitwise.h" +#include "spectrum.h" /* this code is still seriously abbreviated. I'm filling in pieces as we go... --Monty 19991004 */ int vorbis_analysis(vorbis_block *vb,ogg_packet *op){ + static int frameno=0; + int i; double *window=vb->vd->window[vb->W][vb->lW][vb->nW]; lpc_lookup *vl=&vb->vd->vl[vb->W]; - vorbis_dsp_state *vd=vi->vd; + vorbis_dsp_state *vd=vb->vd; vorbis_info *vi=vd->vi; + oggpack_buffer *opb=&vb->opb; + int n=vb->pcmend; + int spectral_order=vi->floororder[vb->W]; /*lpc_lookup *vbal=&vb->vd->vbal[vb->W]; double balance_v[vbal->m]; double balance_amp;*/ - /* we have the preecho metrics; decie what to do with them */ - _ve_envelope_sparsify(vb); - _ve_envelope_apply(vb,0); + /* first things first. Make sure encode is ready*/ + _oggpack_reset(opb); + /* Encode the packet type */ + _oggpack_write(opb,0,1); + /* Encode the block size */ + _oggpack_write(opb,vb->W,1); + + /* we have the preecho metrics; decide what to do with them */ + /*_ve_envelope_sparsify(vb); + _ve_envelope_apply(vb,0);*/ + + /* Encode the envelope */ + /*if(_ve_envelope_encode(vb))return(-1);*/ + /* time domain PCM -> MDCT domain */ for(i=0;ichannels;i++) mdct_forward(&vd->vm[vb->W],vb->pcm[i],vb->pcm[i],window); + /* no balance yet */ + + /* extract the spectral envelope and residue */ + /* just do by channel. No coupling yet */ + { + for(i=0;ichannels;i++){ + double floor[n/2]; + double curve[n/2]; + double *lpc=vb->lpc[i]; + double *lsp=vb->lsp[i]; + + memset(floor,0,sizeof(double)*n/2); + + _vp_noise_floor(vb->pcm[i],floor,n/2); + _vp_mask_floor(vb->pcm[i],floor,n/2); + + /* Convert our floor to a set of lpc coefficients */ + vb->amp[i]=sqrt(vorbis_curve_to_lpc(floor,lpc,vl)); + + /* LSP <-> LPC is orthogonal and LSP quantizes more stably */ + vorbis_lpc_to_lsp(lpc,lsp,vl->m); + + /* code the spectral envelope; mutates the lsp coeffs to reflect + what was actually encoded */ + _vs_spectrum_encode(vb,vb->amp[i],lsp); + + /* Generate residue from the decoded envelope, which will be + slightly different to the pre-encoding floor due to + quantization. Slow, yes, but perhaps more accurate */ + + vorbis_lsp_to_lpc(lsp,lpc,vl->m); + vorbis_lpc_to_curve(curve,lpc,vb->amp[i],vl); + + /* this may do various interesting massaging too...*/ + _vs_residue_quantize(vb->pcm[i],curve,vi,n/2); + + /* encode the residue */ + _vs_residue_encode(vb,vb->pcm[i]); + + } + } + + /* set up the packet wrapper */ + + op->packet=opb->buffer; + op->bytes=_oggpack_bytes(opb); + op->b_o_s=0; + op->e_o_s=vb->eofflag; + op->frameno=vb->frameno; + + return(0); +} + + + - /* no balance or channel coupling yet */ +/* commented out, relocated balance stuff */ /*{ double *C=vb->pcm[0]; double *D=vb->pcm[1]; @@ -115,103 +188,3 @@ int vorbis_analysis(vorbis_block *vb,ogg_packet *op){ } }*/ - - /* extract the spectral envelope and residue */ - /* just do by channel. No coupling yet */ - { - for(i=0;ichannels;vi++){ - double floor[n/2]; - double curve[n/2]; - double *lpc=vb->lpc[i]; - double *lsp=vb->lsp[i]; - - memset(floor,0,sizeof(double)*n/2); - - _vp_noise_floor(vb->pcm[i],floor,n/2); - _vp_mask_floor(vb->pcm[i],floor,n/2); - vb->amp[i]=sqrt(vorbis_curve_to_lpc(floor,lpc,vl)); - - vorbis_lpc_to_lsp(lpc,lsp,vl->m); - - { - /* make this scale configurable */ - int scale=1020; - int last=0; - for(i=0;im;i++){ - double q=lsp[i]/M_PI*scale; - int val=rint(q-last); - - last+=val; - lsp[i]=val; - - } - } - - /* make residue. Get the floor curve back from LPC (do we want - to recover all the way from LSP in the future? Yes, once the - residue massaging is smarter) */ - - vorbis_lpc_to_curve(work,lpc1,amp1,vl); - - _vp_psy_quantize(C,work,n/2); - _vp_psy_quantize(D,work,n/2); - - _vp_psy_unquantize(C,work,n/2); - _vp_psy_unquantize(D,work,n/2); - - - { - FILE *out; - char buffer[80]; - - - /*sprintf(buffer,"qC%d.m",frameno); - out=fopen(buffer,"w+"); - for(i=0;iendbit=b->endbyte=0; } -void _oggpack_writefree(oggpack_buffer *b){ +void _oggpack_writeclear(oggpack_buffer *b){ free(b->buffer); memset(b,0,sizeof(oggpack_buffer)); } diff --git a/lib/bitwise.h b/lib/bitwise.h index 19a5d4e..c614946 100644 --- a/lib/bitwise.h +++ b/lib/bitwise.h @@ -22,7 +22,7 @@ extern void _oggpack_writeinit(oggpack_buffer *b); extern void _oggpack_reset(oggpack_buffer *b); -extern void _oggpack_writefree(oggpack_buffer *b); +extern void _oggpack_writeclear(oggpack_buffer *b); extern void _oggpack_readinit(oggpack_buffer *b,char *buf,int bytes); extern void _oggpack_write(oggpack_buffer *b,unsigned long value,int bits); extern long _oggpack_look(oggpack_buffer *b,int bits); diff --git a/lib/block.c b/lib/block.c index 3dafdab..eb003a9 100644 --- a/lib/block.c +++ b/lib/block.c @@ -75,15 +75,16 @@ int vorbis_block_init(vorbis_dsp_state *v, vorbis_block *vb){ int i; + vorbis_info *vi=v->vi; memset(vb,0,sizeof(vorbis_block)); vb->vd=v; - vb->pcm_storage=v->block_size[1]; - vb->pcm_channels=v->pcm_channels; - vb->mult_storage=v->block_size[1]/v->samples_per_envelope_step; - vb->mult_channels=v->envelope_channels; - vb->floor_channels=v->vi.floorch; - vb->floor_storage=v->vi.floororder; + vb->pcm_storage=vi->blocksize[1]; + vb->pcm_channels=vi->channels; + vb->mult_storage=vi->blocksize[1]/vi->envelopesa; + vb->mult_channels=vi->envelopech; + vb->floor_channels=vi->floorch; + vb->floor_storage=max(vi->floororder[0],vi->floororder[1]); vb->pcm=malloc(vb->pcm_channels*sizeof(double *)); for(i=0;ipcm_channels;i++) @@ -100,6 +101,8 @@ int vorbis_block_init(vorbis_dsp_state *v, vorbis_block *vb){ vb->lsp[i]=malloc(vb->floor_storage*sizeof(double)); vb->lpc[i]=malloc(vb->floor_storage*sizeof(double)); } + if(v->analysisp) + _oggpack_writeinit(&vb->opb); return(0); } @@ -116,6 +119,9 @@ int vorbis_block_clear(vorbis_block *vb){ free(vb->mult[i]); free(vb->mult); } + if(vb->vd->analysisp) + _oggpack_writeclear(&vb->opb); + memset(vb,0,sizeof(vorbis_block)); return(0); } @@ -127,29 +133,25 @@ int vorbis_block_clear(vorbis_block *vb){ static int _vds_shared_init(vorbis_dsp_state *v,vorbis_info *vi){ memset(v,0,sizeof(vorbis_dsp_state)); - memcpy(&v->vi,vi,sizeof(vorbis_info)); + v->vi=vi; _ve_envelope_init(&v->ve,vi->envelopesa); - mdct_init(&v->vm[0],vi->smallblock); - mdct_init(&v->vm[1],vi->largeblock); + mdct_init(&v->vm[0],vi->blocksize[0]); + mdct_init(&v->vm[1],vi->blocksize[1]); - v->samples_per_envelope_step=vi->envelopesa; - v->block_size[0]=vi->smallblock; - v->block_size[1]=vi->largeblock; - - v->window[0][0][0]=_vorbis_window(v->block_size[0], - v->block_size[0]/2,v->block_size[0]/2); + v->window[0][0][0]=_vorbis_window(vi->blocksize[0], + vi->blocksize[0]/2,vi->blocksize[0]/2); v->window[0][0][1]=v->window[0][0][0]; v->window[0][1][0]=v->window[0][0][0]; v->window[0][1][1]=v->window[0][0][0]; - v->window[1][0][0]=_vorbis_window(v->block_size[1], - v->block_size[0]/2,v->block_size[0]/2); - v->window[1][0][1]=_vorbis_window(v->block_size[1], - v->block_size[0]/2,v->block_size[1]/2); - v->window[1][1][0]=_vorbis_window(v->block_size[1], - v->block_size[1]/2,v->block_size[0]/2); - v->window[1][1][1]=_vorbis_window(v->block_size[1], - v->block_size[1]/2,v->block_size[1]/2); + v->window[1][0][0]=_vorbis_window(vi->blocksize[1], + vi->blocksize[0]/2,vi->blocksize[0]/2); + v->window[1][0][1]=_vorbis_window(vi->blocksize[1], + vi->blocksize[0]/2,vi->blocksize[1]/2); + v->window[1][1][0]=_vorbis_window(vi->blocksize[1], + vi->blocksize[1]/2,vi->blocksize[0]/2); + v->window[1][1][1]=_vorbis_window(vi->blocksize[1], + vi->blocksize[1]/2,vi->blocksize[1]/2); /* initialize the storage vectors to a decent size greater than the minimum */ @@ -157,7 +159,6 @@ static int _vds_shared_init(vorbis_dsp_state *v,vorbis_info *vi){ v->pcm_storage=8192; /* we'll assume later that we have a minimum of twice the blocksize of accumulated samples in analysis */ - v->pcm_channels=v->vi.channels=vi->channels; v->pcm=malloc(vi->channels*sizeof(double *)); v->pcmret=malloc(vi->channels*sizeof(double *)); { @@ -169,12 +170,11 @@ static int _vds_shared_init(vorbis_dsp_state *v,vorbis_info *vi){ /* Initialize the envelope multiplier storage */ if(vi->envelopech){ - v->envelope_storage=v->pcm_storage/v->samples_per_envelope_step; - v->envelope_channels=vi->envelopech; - v->multipliers=calloc(v->envelope_channels,sizeof(double *)); + v->envelope_storage=v->pcm_storage/vi->envelopesa; + v->multipliers=calloc(vi->envelopech,sizeof(double *)); { int i; - for(i=0;ienvelope_channels;i++){ + for(i=0;ienvelopech;i++){ v->multipliers[i]=calloc(v->envelope_storage,sizeof(double)); } } @@ -186,10 +186,10 @@ static int _vds_shared_init(vorbis_dsp_state *v,vorbis_info *vi){ v->W=0; /* current window size */ /* all vector indexes; multiples of samples_per_envelope_step */ - v->centerW=v->block_size[1]/2; + v->centerW=vi->blocksize[1]/2; v->pcm_current=v->centerW; - v->envelope_current=v->centerW/v->samples_per_envelope_step; + v->envelope_current=v->centerW/vi->envelopesa; return(0); } @@ -197,17 +197,20 @@ static int _vds_shared_init(vorbis_dsp_state *v,vorbis_info *vi){ int vorbis_analysis_init(vorbis_dsp_state *v,vorbis_info *vi){ _vds_shared_init(v,vi); + /* the coder init is different for read/write */ + v->analysisp=1; + /* Yes, wasteful to have four lookups. This will get collapsed once things crystallize */ - lpc_init(&v->vl[0],vi->smallblock/2,vi->smallblock/2, - vi->floororder,vi->flooroctaves,1); - lpc_init(&v->vl[1],vi->largeblock/2,vi->largeblock/2, - vi->floororder,vi->flooroctaves,1); + lpc_init(&v->vl[0],vi->blocksize[0]/2,vi->blocksize[0]/2, + vi->floororder[0],vi->flooroctaves[0],1); + lpc_init(&v->vl[1],vi->blocksize[1]/2,vi->blocksize[1]/2, + vi->floororder[0],vi->flooroctaves[0],1); - lpc_init(&v->vbal[0],vi->smallblock/2,256, - vi->balanceorder,vi->balanceoctaves,1); - lpc_init(&v->vbal[1],vi->largeblock/2,256, + /*lpc_init(&v->vbal[0],vi->blocksize[0]/2,256, vi->balanceorder,vi->balanceoctaves,1); + lpc_init(&v->vbal[1],vi->blocksize[1]/2,256, + vi->balanceorder,vi->balanceoctaves,1);*/ return(0); } @@ -215,19 +218,20 @@ int vorbis_analysis_init(vorbis_dsp_state *v,vorbis_info *vi){ void vorbis_dsp_clear(vorbis_dsp_state *v){ int i,j,k; if(v){ + vorbis_info *vi=v->vi; if(v->window[0][0][0])free(v->window[0][0][0]); for(j=0;j<2;j++) for(k=0;k<2;k++) if(v->window[1][j][k])free(v->window[1][j][k]); if(v->pcm){ - for(i=0;ipcm_channels;i++) + for(i=0;ichannels;i++) if(v->pcm[i])free(v->pcm[i]); free(v->pcm); if(v->pcmret)free(v->pcmret); } if(v->multipliers){ - for(i=0;ienvelope_channels;i++) + for(i=0;ienvelopech;i++) if(v->multipliers[i])free(v->multipliers[i]); free(v->multipliers); } @@ -236,32 +240,33 @@ void vorbis_dsp_clear(vorbis_dsp_state *v){ mdct_clear(&v->vm[1]); lpc_clear(&v->vl[0]); lpc_clear(&v->vl[1]); - lpc_clear(&v->vbal[0]); - lpc_clear(&v->vbal[1]); + /*lpc_clear(&v->vbal[0]); + lpc_clear(&v->vbal[1]);*/ memset(v,0,sizeof(vorbis_dsp_state)); } } double **vorbis_analysis_buffer(vorbis_dsp_state *v, int vals){ int i; + vorbis_info *vi=v->vi; /* Do we have enough storage space for the requested buffer? If not, expand the PCM (and envelope) storage */ if(v->pcm_current+vals>=v->pcm_storage){ v->pcm_storage=v->pcm_current+vals*2; - v->envelope_storage=v->pcm_storage/v->samples_per_envelope_step; + v->envelope_storage=v->pcm_storage/v->vi->envelopesa; - for(i=0;ipcm_channels;i++){ + for(i=0;ichannels;i++){ v->pcm[i]=realloc(v->pcm[i],v->pcm_storage*sizeof(double)); } - for(i=0;ienvelope_channels;i++){ + for(i=0;ienvelopech;i++){ v->multipliers[i]=realloc(v->multipliers[i], v->envelope_storage*sizeof(double)); } } - for(i=0;ipcm_channels;i++) + for(i=0;ichannels;i++) v->pcmret[i]=v->pcm[i]+v->pcm_current; return(v->pcmret); @@ -270,15 +275,16 @@ double **vorbis_analysis_buffer(vorbis_dsp_state *v, int vals){ /* call with val<=0 to set eof */ int vorbis_analysis_wrote(vorbis_dsp_state *v, int vals){ + vorbis_info *vi=v->vi; if(vals<=0){ /* We're encoding the end of the stream. Just make sure we have [at least] a full block of zeroes at the end. */ int i; - vorbis_analysis_buffer(v,v->block_size[1]*2); + vorbis_analysis_buffer(v,v->vi->blocksize[1]*2); v->eofflag=v->pcm_current; - v->pcm_current+=v->block_size[1]*2; - for(i=0;ipcm_channels;i++) + v->pcm_current+=v->vi->blocksize[1]*2; + for(i=0;ichannels;i++) memset(v->pcm[i]+v->eofflag,0, (v->pcm_current-v->eofflag)*sizeof(double)); }else{ @@ -295,8 +301,9 @@ int vorbis_analysis_wrote(vorbis_dsp_state *v, int vals){ the next block on which to continue analysis */ int vorbis_analysis_blockout(vorbis_dsp_state *v,vorbis_block *vb){ int i,j; - long beginW=v->centerW-v->block_size[v->W]/2,centerNext; - long beginM=beginW/v->samples_per_envelope_step; + vorbis_info *vi=v->vi; + long beginW=v->centerW-vi->blocksize[v->W]/2,centerNext; + long beginM=beginW/vi->envelopesa; /* check to see if we're done... */ if(v->eofflag==-1)return(0); @@ -304,7 +311,7 @@ int vorbis_analysis_blockout(vorbis_dsp_state *v,vorbis_block *vb){ /* if we have any unfilled envelope blocks for which we have PCM data, fill them up in before proceeding. */ - if(v->pcm_current/v->samples_per_envelope_step>v->envelope_current){ + if(v->pcm_current/vi->envelopesa>v->envelope_current){ /* This generates the multipliers, but does not sparsify the vector. That's done by block before coding */ _ve_envelope_multipliers(v); @@ -317,22 +324,22 @@ int vorbis_analysis_blockout(vorbis_dsp_state *v,vorbis_block *vb){ /* overconserve for now; any block with a non-placeholder multiplier should be minimal size. We can be greedy and only look at nW size */ - if(v->vi.smallblockvi.largeblock){ + if(vi->blocksize[0]blocksize[1]){ if(v->W) /* this is a long window; we start the search forward of centerW because that's the fastest we could react anyway */ - i=v->centerW+v->block_size[1]/4-v->block_size[0]/4; + i=v->centerW+vi->blocksize[1]/4-vi->blocksize[0]/4; else /* short window. Search from centerW */ i=v->centerW; - i/=v->samples_per_envelope_step; + i/=vi->envelopesa; for(;ienvelope_current;i++){ - for(j=0;jenvelope_channels;j++) - if(v->multipliers[j][i-1]*v->vi.preecho_thresh< + for(j=0;jenvelopech;j++) + if(v->multipliers[j][i-1]*vi->preecho_thresh< v->multipliers[j][i])break; - if(jenvelope_channels)break; + if(jenvelopech)break; } if(ienvelope_current){ @@ -340,10 +347,10 @@ int vorbis_analysis_blockout(vorbis_dsp_state *v,vorbis_block *vb){ upcoming block large ? */ long largebound; if(v->W) - largebound=v->centerW+v->block_size[1]; + largebound=v->centerW+vi->blocksize[1]; else - largebound=v->centerW+v->block_size[0]/4+v->block_size[1]*3/4; - largebound/=v->samples_per_envelope_step; + largebound=v->centerW+vi->blocksize[0]/4+vi->blocksize[1]*3/4; + largebound/=vi->envelopesa; if(i>=largebound) v->nW=1; @@ -365,10 +372,10 @@ int vorbis_analysis_blockout(vorbis_dsp_state *v,vorbis_block *vb){ know the size of the next block for sure and we need that now to figure out the window shape of this block */ - centerNext=v->centerW+v->block_size[v->W]/4+v->block_size[v->nW]/4; + centerNext=v->centerW+vi->blocksize[v->W]/4+vi->blocksize[v->nW]/4; { - long blockbound=centerNext+v->block_size[v->nW]/2; + long blockbound=centerNext+vi->blocksize[v->nW]/2; if(v->pcm_currentnW=v->nW; vb->vd=v; - vb->pcmend=v->block_size[v->W]; - vb->multend=vb->pcmend / v->samples_per_envelope_step; - - if(vb->floor_channels!=v->vi.floorch || - vb->floor_storage!=v->vi.floororder || - v->pcm_channels!=vb->pcm_channels || - v->block_size[1]!=vb->pcm_storage || - v->envelope_channels!=vb->mult_channels){ - - /* Storage not initialized or initilized for some other codec - instance with different settings */ - - vorbis_block_clear(vb); - vorbis_block_init(v,vb); - } + vb->pcmend=vi->blocksize[v->W]; + vb->multend=vb->pcmend / vi->envelopesa; /* copy the vectors */ - for(i=0;ipcm_channels;i++) - memcpy(vb->pcm[i],v->pcm[i]+beginW,v->block_size[v->W]*sizeof(double)); - for(i=0;ienvelope_channels;i++) - memcpy(vb->mult[i],v->multipliers[i]+beginM,v->block_size[v->W]/ - v->samples_per_envelope_step*sizeof(double)); + for(i=0;ichannels;i++) + memcpy(vb->pcm[i],v->pcm[i]+beginW,vi->blocksize[v->W]*sizeof(double)); + for(i=0;ienvelopech;i++) + memcpy(vb->mult[i],v->multipliers[i]+beginM,vi->blocksize[v->W]/ + vi->envelopesa*sizeof(double)); vb->frameno=v->frame; @@ -416,19 +410,19 @@ int vorbis_analysis_blockout(vorbis_dsp_state *v,vorbis_block *vb){ /* advance storage vectors and clean up */ { - int new_centerNext=v->block_size[1]/2; + int new_centerNext=vi->blocksize[1]/2; int movementW=centerNext-new_centerNext; - int movementM=movementW/v->samples_per_envelope_step; + int movementM=movementW/vi->envelopesa; /* the multipliers and pcm stay synced up because the blocksizes must be multiples of samples_per_envelope_step (minimum multiple is 2) */ - for(i=0;ipcm_channels;i++) + for(i=0;ichannels;i++) memmove(v->pcm[i],v->pcm[i]+movementW, (v->pcm_current-movementW)*sizeof(double)); - for(i=0;ienvelope_channels;i++){ + for(i=0;ienvelopech;i++){ memmove(v->multipliers[i],v->multipliers[i]+movementM, (v->envelope_current-movementM)*sizeof(double)); } @@ -459,19 +453,19 @@ int vorbis_synthesis_init(vorbis_dsp_state *v,vorbis_info *vi){ /* Yes, wasteful to have four lookups. This will get collapsed once things crystallize */ - lpc_init(&v->vl[0],vi->smallblock/2,vi->smallblock/2, - vi->floororder,vi->flooroctaves,0); - lpc_init(&v->vl[1],vi->largeblock/2,vi->largeblock/2, - vi->floororder,vi->flooroctaves,0); - lpc_init(&v->vbal[0],vi->smallblock/2,256, - vi->balanceorder,vi->balanceoctaves,0); - lpc_init(&v->vbal[1],vi->largeblock/2,256, + lpc_init(&v->vl[0],vi->blocksize[0]/2,vi->blocksize[0]/2, + vi->floororder[0],vi->flooroctaves[0],0); + lpc_init(&v->vl[1],vi->blocksize[1]/2,vi->blocksize[1]/2, + vi->floororder[1],vi->flooroctaves[1],0); + /*lpc_init(&v->vbal[0],vi->blocksize[0]/2,256, vi->balanceorder,vi->balanceoctaves,0); + lpc_init(&v->vbal[1],vi->blocksize[1]/2,256, + vi->balanceorder,vi->balanceoctaves,0);*/ /* Adjust centerW to allow an easier mechanism for determining output */ v->pcm_returned=v->centerW; - v->centerW-= v->block_size[v->W]/4+v->block_size[v->lW]/4; + v->centerW-= vi->blocksize[v->W]/4+vi->blocksize[v->lW]/4; return(0); } @@ -480,15 +474,16 @@ int vorbis_synthesis_init(vorbis_dsp_state *v,vorbis_info *vi){ each block) */ int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb){ + vorbis_info *vi=v->vi; /* Shift out any PCM that we returned previously */ - if(v->pcm_returned && v->centerW>v->block_size[1]/2){ + if(v->pcm_returned && v->centerW>vi->blocksize[1]/2){ /* don't shift too much; we need to have a minimum PCM buffer of 1/2 long block */ - int shift=v->centerW-v->block_size[1]/2; + int shift=v->centerW-vi->blocksize[1]/2; shift=(v->pcm_returnedpcm_returned:shift); v->pcm_current-=shift; @@ -497,15 +492,18 @@ int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb){ if(shift){ int i; - for(i=0;ipcm_channels;i++) + for(i=0;ichannels;i++) memmove(v->pcm[i],v->pcm[i]+shift, v->pcm_current*sizeof(double)); } } + v->lW=v->W; + v->W=vb->W; + { - int sizeW=v->block_size[vb->W]; - int centerW=v->centerW+v->block_size[vb->lW]/4+sizeW/4; + int sizeW=vi->blocksize[v->W]; + int centerW=v->centerW+vi->blocksize[v->lW]/4+sizeW/4; int beginW=centerW-sizeW/2; int endW=beginW+sizeW; int beginSl; @@ -517,27 +515,27 @@ int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb){ if(endW>v->pcm_storage){ /* expand the PCM storage */ - v->pcm_storage=endW+v->block_size[1]; + v->pcm_storage=endW+vi->blocksize[1]; - for(i=0;ipcm_channels;i++) + for(i=0;ichannels;i++) v->pcm[i]=realloc(v->pcm[i],v->pcm_storage*sizeof(double)); } /* Overlap/add */ - switch(vb->W){ + switch(v->W){ case 0: beginSl=0; - endSl=v->block_size[0]/2; + endSl=vi->blocksize[0]/2; break; case 1: - beginSl=v->block_size[1]/4-v->block_size[vb->lW]/4; - endSl=beginSl+v->block_size[vb->lW]/2; + beginSl=vi->blocksize[1]/4-vi->blocksize[v->lW]/4; + endSl=beginSl+vi->blocksize[v->lW]/2; break; } - window=v->window[vb->W][0][vb->lW]+v->block_size[vb->W]/2; + window=v->window[v->W][0][v->lW]+vi->blocksize[v->W]/2; - for(j=0;jpcm_channels;j++){ + for(j=0;jchannels;j++){ double *pcm=v->pcm[j]+beginW; /* the add section */ @@ -559,9 +557,10 @@ int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb){ } int vorbis_synthesis_pcmout(vorbis_dsp_state *v,double ***pcm){ + vorbis_info *vi=v->vi; if(v->pcm_returnedcenterW){ int i; - for(i=0;ipcm_channels;i++) + for(i=0;ichannels;i++) v->pcmret[i]=v->pcm[i]+v->pcm_returned; *pcm=v->pcmret; return(v->centerW-v->pcm_returned); diff --git a/lib/codec.h b/lib/codec.h index cd34444..d72056e 100644 --- a/lib/codec.h +++ b/lib/codec.h @@ -14,7 +14,7 @@ function: codec headers author: Monty modifications by: Monty - last modification date: Oct 4 1999 + last modification date: Oct 6 1999 ********************************************************************/ @@ -96,18 +96,25 @@ typedef struct vorbis_info{ int comments; char *vendor; - int smallblock; - int largeblock; + int blocksize[2]; + int floororder[2]; + int flooroctaves[2]; + int envelopesa; int envelopech; + int floorch; + + /* int smallblock; + int largeblock; int floororder; int flooroctaves; - int floorch; + int floorch;*/ - /* no mapping, copuling, balance yet. */ + /* no mapping, coupling, balance yet. */ - int balanceorder; - int balanceoctaves; + /*int balanceorder; + int balanceoctaves; + this would likely need to be by channel and blocksize anyway*/ double preecho_thresh; double preecho_clamp; @@ -191,27 +198,23 @@ typedef struct { logical bitstream ****************************************************/ typedef struct vorbis_dsp_state{ - int samples_per_envelope_step; - int block_size[2]; - double *window[2][2][2]; /* windowsize, leadin, leadout */ + int analysisp; + vorbis_info *vi; + double *window[2][2][2]; /* windowsize, leadin, leadout */ envelope_lookup ve; mdct_lookup vm[2]; lpc_lookup vl[2]; lpc_lookup vbal[2]; - vorbis_info vi; - double **pcm; double **pcmret; int pcm_storage; - int pcm_channels; int pcm_current; int pcm_returned; double **multipliers; int envelope_storage; - int envelope_channels; int envelope_current; int eofflag; @@ -237,6 +240,7 @@ typedef struct vorbis_block{ double **lpc; double **lsp; double *amp; + oggpack_buffer opb; int pcm_channels; /* allocated, not used */ int pcm_storage; /* allocated, not used */ diff --git a/lib/decoder_example.c b/lib/decoder_example.c index addfa18..62acc70 100644 --- a/lib/decoder_example.c +++ b/lib/decoder_example.c @@ -145,13 +145,13 @@ int main(){ /* Throw the comments plus a few lines about the bitstream we're decoding */ { - char **ptr=vi->user_comments; + char **ptr=vi.user_comments; while(*ptr){ fprintf(stderr,"%s\n",*ptr); ++ptr; } - fprintf(stderr,"\nBitstream is %d channel, %dHz\n",vi->channels,vi->rate); - fprintf(stderr,"Encoded by: %s\n\n",vi->vendor); + fprintf(stderr,"\nBitstream is %d channel, %dHz\n",vi.channels,vi.rate); + fprintf(stderr,"Encoded by: %s\n\n",vi.vendor); } convsize=4096/vi.channels; @@ -213,6 +213,7 @@ int main(){ ptr+=2; } } + fwrite(convbuffer,2*vi.channels,out,stdout); vorbis_synthesis_read(&vd,out); /* tell libvorbis how many samples we @@ -226,9 +227,9 @@ int main(){ if(!eos){ buffer=ogg_sync_buffer(&oy,4096); bytes=fread(buffer,1,4096,stdin); - if(bytes==0)eos=1; - }else ogg_sync_wrote(&oy,bytes); + if(bytes==0)eos=1; + } } /* clean up and exit (this example doesn't deal with the possibility diff --git a/lib/envelope.c b/lib/envelope.c index 5c41382..514ef89 100644 --- a/lib/envelope.c +++ b/lib/envelope.c @@ -14,7 +14,7 @@ function: PCM data envelope analysis and manipulation author: Monty modifications by: Monty - last modification date: Oct 02 1999 + last modification date: Oct 06 1999 Vorbis manipulates the dynamic range of the incoming PCM data envelope to minimise time-domain energy leakage from percussive and @@ -29,6 +29,7 @@ #include "codec.h" #include "envelope.h" +#include "bitwise.h" void _ve_envelope_init(envelope_lookup *e,int samples_per){ int i; @@ -120,17 +121,17 @@ static void _ve_deltas(double *deltas,double *pcm,int n,double *win, } void _ve_envelope_multipliers(vorbis_dsp_state *v){ - int step=v->samples_per_envelope_step; + vorbis_info *vi=v->vi; + int step=vi->envelopesa; static int frame=0; /* we need a 1-1/4 envelope window overlap begin and 1/4 end */ - int dtotal=(v->pcm_current-step/2)/v->samples_per_envelope_step; + int dtotal=(v->pcm_current-step/2)/vi->envelopesa; int dcurr=v->envelope_current; double *window=v->ve.window; int winlen=v->ve.winlen; int pch,ech; - vorbis_info *vi=&v->vi; - + if(dtotal>dcurr){ for(ech=0;echenvelopech;ech++){ double *mult=v->multipliers[ech]+dcurr; @@ -159,8 +160,9 @@ void _ve_envelope_multipliers(vorbis_dsp_state *v){ coefficients */ void _ve_envelope_sparsify(vorbis_block *vb){ + vorbis_info *vi=vb->vd->vi; int ch; - for(ch=0;chvd->vi.envelopech;ch++){ + for(ch=0;chenvelopech;ch++){ int flag=0; double *mult=vb->mult[ch]; int n=vb->multend; @@ -172,11 +174,11 @@ void _ve_envelope_sparsify(vorbis_block *vb){ /* are we going to multiply anything? */ for(i=1;i=last*vb->vd->vi.preecho_thresh){ + if(mult[i]>=last*vi->preecho_thresh){ flag=1; break; } - if(i=last*vb->vd->vi.preecho_thresh){ + if(i=last*vi->preecho_thresh){ flag=1; break; } @@ -193,10 +195,10 @@ void _ve_envelope_sparsify(vorbis_block *vb){ last=1; for(;iclamp*vb->vd->vi.preecho_thresh){ - last=mult[i]/vb->vd->vi.preecho_clamp; + if(mult[i]/last>clamp*vi->preecho_thresh){ + last=mult[i]/vi->preecho_clamp; - mult[i]=floor(log(mult[i]/clamp/vb->vd->vi.preecho_clamp)/log(2))-1; + mult[i]=floor(log(mult[i]/clamp/vi->preecho_clamp)/log(2))-1; if(mult[i]>15)mult[i]=15; }else{ mult[i]=0; @@ -208,7 +210,7 @@ void _ve_envelope_sparsify(vorbis_block *vb){ } void _ve_envelope_apply(vorbis_block *vb,int multp){ - vorbis_info *vi=&vb->vd->vi; + vorbis_info *vi=vb->vd->vi; double env[vb->multend*vi->envelopesa]; envelope_lookup *look=&vb->vd->ve; int i,j,k; @@ -249,3 +251,40 @@ void _ve_envelope_apply(vorbis_block *vb,int multp){ } } +int _ve_envelope_encode(vorbis_block *vb){ + /* Not huffcoded yet. */ + + vorbis_info *vi=vb->vd->vi; + int scale=vb->W; + int n=vb->multend; + int i,j; + + /* range is 0-15 */ + + for(i=0;ienvelopech;i++){ + double *mult=vb->mult[i]; + for(j=0;jopb,(int)(mult[j]),4); + } + return(0); +} + +/* synthesis expands the buffers in vb if needed. We can assume we + have enough storage handed to us. */ +int _ve_envelope_decode(vorbis_block *vb){ + vorbis_info *vi=vb->vd->vi; + int scale=vb->W; + int n=vb->multend; + int i,j; + + /* range is 0-15 */ + + for(i=0;ienvelopech;i++){ + double *mult=vb->mult[i]; + for(j=0;jopb,4); + } + return(0); +} + + diff --git a/lib/envelope.h b/lib/envelope.h index fd92685..a21c771 100644 --- a/lib/envelope.h +++ b/lib/envelope.h @@ -14,7 +14,7 @@ function: PCM data envelope analysis and manipulation author: Monty modifications by: Monty - last modification date: Aug 07 1999 + last modification date: Oct 07 1999 ********************************************************************/ @@ -27,5 +27,9 @@ extern void _ve_envelope_sparsify(vorbis_block *vb); extern void _ve_envelope_init(envelope_lookup *e,int samples_per); extern void _ve_envelope_clear(envelope_lookup *e); + +extern int _ve_envelope_encode(vorbis_block *vb); +extern int _ve_envelope_decode(vorbis_block *vb); + #endif diff --git a/lib/info.c b/lib/info.c index 5dc6d53..f2bce56 100644 --- a/lib/info.c +++ b/lib/info.c @@ -14,7 +14,7 @@ function: maintain the info structure, info <-> header packets author: Monty modifications by: Monty - last modification date: Oct 04 1999 + last modification date: Oct 06 1999 ********************************************************************/ @@ -88,7 +88,7 @@ int vorbis_info_headerin(vorbis_info *vi,ogg_packet *op){ return(-1); } switch(_oggpack_read(&opb,8)){ - case 0: + case 0x80: if(!op->b_o_s){ /* Not the initial packet */ return(-1); @@ -98,18 +98,26 @@ int vorbis_info_headerin(vorbis_info *vi,ogg_packet *op){ return(-1); } + if(_oggpack_read(&opb,32)!=0){ + return(-1); + } vi->channels=_oggpack_read(&opb,32); vi->rate=_oggpack_read(&opb,32); - vi->smallblock=_oggpack_read(&opb,32); - vi->largeblock=_oggpack_read(&opb,32); + + vi->blocksize[0]=_oggpack_read(&opb,32); + vi->blocksize[1]=_oggpack_read(&opb,32); + + vi->floororder[0]=_oggpack_read(&opb,8); + vi->floororder[1]=_oggpack_read(&opb,8); + vi->flooroctaves[0]=_oggpack_read(&opb,8); + vi->flooroctaves[1]=_oggpack_read(&opb,8); + vi->envelopesa=_oggpack_read(&opb,32); vi->envelopech=_oggpack_read(&opb,16); - vi->floororder=_oggpack_read(&opb,8); - vi->flooroctaves=_oggpack_read(&opb,8); vi->floorch=_oggpack_read(&opb,16); return(0); - case 1: + case 0x81: if(vi->rate==0){ /* um... we didn;t get the initial header */ return(-1); @@ -124,7 +132,7 @@ int vorbis_info_headerin(vorbis_info *vi,ogg_packet *op){ vi->comments=_oggpack_read(&opb,32); vi->user_comments=calloc(vi->comments+1,sizeof(char **)); - for(i=0;i<=vi->comments;i++){ + for(i=0;icomments;i++){ int len=_oggpack_read(&opb,32); vi->user_comments[i]=calloc(len+1,1); _v_readstring(&opb,vi->user_comments[i],len); @@ -132,7 +140,7 @@ int vorbis_info_headerin(vorbis_info *vi,ogg_packet *op){ } return(0); - case 2: + case 0x82: if(vi->rate==0){ /* um... we didn;t get the initial header */ return(-1); @@ -160,34 +168,39 @@ int vorbis_info_headerout(vorbis_info *vi, /* initial header: codec id "vorbis" - header id 0 (byte) + header id 0x80 (byte) codec ver (4 octets, lsb first: currently 0x00) pcm channels (4 octets, lsb first) pcm rate (4 octets, lsb first) small block (4 octets, lsb first) large block (4 octets, lsb first) + floor order for small block (octet) + floor order for large block (octet) + floor octaves for small block (octet) + floor octaves for large block (octet) + envelopesa (4 octets, lsb first) envelopech (4 octets, lsb first) - floororder octet - flooroctaves octet floorch (4 octets, lsb first) */ _oggpack_writeinit(&opb); _v_writestring(&opb,"vorbis"); - _oggpack_write(&opb,0x00,8); + _oggpack_write(&opb,0x80,8); _oggpack_write(&opb,0x00,32); _oggpack_write(&opb,vi->channels,32); _oggpack_write(&opb,vi->rate,32); - _oggpack_write(&opb,vi->smallblock,32); - _oggpack_write(&opb,vi->largeblock,32); + _oggpack_write(&opb,vi->blocksize[0],32); + _oggpack_write(&opb,vi->blocksize[1],32); + _oggpack_write(&opb,vi->floororder[0],8); + _oggpack_write(&opb,vi->floororder[1],8); + _oggpack_write(&opb,vi->flooroctaves[0],8); + _oggpack_write(&opb,vi->flooroctaves[1],8); _oggpack_write(&opb,vi->envelopesa,32); _oggpack_write(&opb,vi->envelopech,16); - _oggpack_write(&opb,vi->floororder,8); - _oggpack_write(&opb,vi->flooroctaves,8); _oggpack_write(&opb,vi->floorch,16); /* build the packet */ @@ -202,7 +215,7 @@ int vorbis_info_headerout(vorbis_info *vi, /* comment header: codec id "vorbis" - header id 1 (byte) + header id 0x81 (byte) vendor len (4 octets, lsb first) vendor and id (n octects as above) comments (4 octets, lsb first) @@ -215,7 +228,7 @@ int vorbis_info_headerout(vorbis_info *vi, _oggpack_reset(&opb); _v_writestring(&opb,"vorbis"); - _oggpack_write(&opb,0x01,8); + _oggpack_write(&opb,0x81,8); if(vi->vendor){ _oggpack_write(&opb,strlen(vi->vendor),32); @@ -248,12 +261,12 @@ int vorbis_info_headerout(vorbis_info *vi, /* codebook header: codec id "vorbis" - header id 2 (byte) + header id 0x82 (byte) nul so far; not encoded yet */ _oggpack_reset(&opb); _v_writestring(&opb,"vorbis"); - _oggpack_write(&opb,0x02,8); + _oggpack_write(&opb,0x82,8); if(vi->header2)free(vi->header2); vi->header2=malloc(_oggpack_bytes(&opb)); @@ -264,7 +277,7 @@ int vorbis_info_headerout(vorbis_info *vi, op_code->e_o_s=0; op_code->frameno=0; - _oggpack_writefree(&opb); + _oggpack_writeclear(&opb); return(0); } diff --git a/lib/mdct.c b/lib/mdct.c index 2131b84..ccd943d 100644 --- a/lib/mdct.c +++ b/lib/mdct.c @@ -16,7 +16,7 @@ author: Monty modifications by: Monty - last modification date: Jul 29 1999 + last modification date: Oct 10 1999 Algorithm adapted from _The use of multirate filter banks for coding of high quality digital audio_, by T. Sporer, K. Brandenburg and @@ -36,9 +36,6 @@ ********************************************************************/ -/* Undef the following if you want a normal MDCT */ -#define VORBIS_SPECIFIC_MODIFICATIONS - #include #include #include @@ -262,9 +259,10 @@ void mdct_forward(mdct_lookup *init, double *in, double *out, double *window){ double *BE=init->trig+n2; double *BO=BE+n4; double *out2=out+n2; + double scale=4./n; for(i=0;i16)val=16; - if(val<-16)val=-16; - if(val==0 || val==2){ - if(f[i]<0){ - f[i]=-1; - }else{ - f[i]=1; - } - } - - f[i]=val; - } -} -void _vp_psy_unquantize(double *f, double *m,int n){ - int i; - for(i=0;i and The XIPHOPHORUS Company * + * http://www.xiph.org/ * + * * + ******************************************************************** + + function: spectrum envelope and residue code/decode + author: Monty + modifications by: Monty + last modification date: Oct 10 1999 + + ********************************************************************/ + +#include +#include +#include "codec.h" +#include "bitwise.h" +#include "spectrum.h" + +/* this code is still seriously abbreviated. I'm filling in pieces as + we go... --Monty 19991004 */ + +int _vs_spectrum_encode(vorbis_block *vb,double amp,double *lsp){ + /* no real coding yet. Just write out full sized words for now + because people need bitstreams to work with */ + + int scale=vb->W; + int n=vb->pcmend/2; + int last=0; + int bits=rint(log(n)/log(2)); + int i; + + _oggpack_write(&vb->opb,amp*32768,15); + + for(i=0;ivd->vi->floororder[scale];i++){ + int val=rint(lsp[i]/M_PI*n-last); + lsp[i]=(last+=val)*M_PI/n; + _oggpack_write(&vb->opb,val,bits); + } + return(0); +} + +int _vs_spectrum_decode(vorbis_block *vb,double *amp,double *lsp){ + int scale=vb->W; + int n=vb->pcmend/2; + int last=0; + int bits=rint(log(n)/log(2)); + int i; + + *amp=_oggpack_read(&vb->opb,15)/32768.; + + for(i=0;ivd->vi->floororder[scale];i++){ + int val=_oggpack_read(&vb->opb,bits); + lsp[i]=(last+=val)*M_PI/n; + } + return(0); +} + + +void _vs_residue_quantize(double *data,double *curve, + vorbis_info *vi,int n){ + + /* The following is temporary, hardwired bullshit */ + int i; + + for(i=0;i16)val=16; + if(val<-16)val=-16; + + /*if(val==0){ + if(data[i]<0){ + val=-1; + }else{ + val=1; + } + }*/ + + data[i]=val; + /*if(val<0){ + }else{ + data[i]=val+15; + }*/ + } +} + +int _vs_residue_encode(vorbis_block *vb,double *data){ + /* no real coding yet. Just write out full sized words for now + because people need bitstreams to work with */ + + int n=vb->pcmend/2; + int i; + + for(i=0;iopb,(int)(data[i]+16),6); + } + + return(0); +} + +int _vs_residue_decode(vorbis_block *vb,double *data){ + /* no real coding yet. Just write out full sized words for now + because people need bitstreams to work with */ + + int n=vb->pcmend/2; + int i; + + for(i=0;iopb,6)-16; + /*if(data[i]>=0)data[i]+=1;*/ + } + return(0); +} + diff --git a/lib/spectrum.h b/lib/spectrum.h new file mode 100644 index 0000000..a369d86 --- /dev/null +++ b/lib/spectrum.h @@ -0,0 +1,23 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE Ogg Vorbis SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY * + * THE GNU PUBLIC LICENSE 2, WHICH IS INCLUDED WITH THIS SOURCE. * + * PLEASE READ THESE TERMS DISTRIBUTING. * + * * + * THE OggSQUISH SOURCE CODE IS (C) COPYRIGHT 1994-1999 * + * by 1999 Monty and The XIPHOPHORUS Company * + * http://www.xiph.org/ * + * * + ********************************************************************/ + +#ifndef _V_SPECT_H_ +#define _V_SPECT_H_ + +extern int _vs_spectrum_encode(vorbis_block *vb,double amp,double *lsp); +extern int _vs_spectrum_decode(vorbis_block *vb,double *amp,double *lsp); +extern void _vs_residue_quantize(double *data,double *curve, + vorbis_info *vi,int n); +extern int _vs_residue_encode(vorbis_block *vb,double *data); + +#endif diff --git a/lib/synthesis.c b/lib/synthesis.c index aa5d927..5faa705 100644 --- a/lib/synthesis.c +++ b/lib/synthesis.c @@ -14,53 +14,83 @@ function: single-block PCM synthesis author: Monty modifications by: Monty - last modification date: Aug 08 1999 + last modification date: Oct 07 1999 ********************************************************************/ +#include #include "codec.h" #include "envelope.h" #include "mdct.h" #include "lpc.h" #include "lsp.h" +#include "bitwise.h" +#include "spectrum.h" int vorbis_synthesis(vorbis_block *vb,ogg_packet *op){ - int i; - vorbis_info *vi=&vb->vd->vi; - double *window=vb->vd->window[vb->W][vb->lW][vb->nW]; - lpc_lookup *vl=&vb->vd->vl[vb->W]; - - /* get the LSP params back to LPC params. This will be for each - spectral floor curve */ - - - /* { - int scale=1020; - double last=0; - for(i=0;i<30;i++){ - last+=lsp1[i]; - lsp2[i]=last*M_PI/scale; - } - } - - - - vorbis_lsp_to_lpc(lsp2,lpc1,30);*/ - - - /*for(i=0;ifloorch;i++) - vorbis_lsp_to_lpc(vb->lsp[i],vb->lpc[i],vi->floororder);*/ - - /* Map the resulting floors back to the appropriate channels */ - - /*for(i=0;ichannels;i++) - vorbis_lpc_apply(vb->pcm[i],vb->pcmend,vb->lpc[vi->floormap[i]], - vb->amp[vi->floormap[i]],vi->floororder);*/ + static int frameno=0; + vorbis_dsp_state *vd=vb->vd; + vorbis_info *vi=vd->vi; + oggpack_buffer *opb=&vb->opb; + lpc_lookup *vl; + double *window; + int spectral_order; + int n,i; + + /* first things first. Make sure decode is ready */ + _oggpack_readinit(opb,op->packet,op->bytes); + + /* Check the packet type */ + if(_oggpack_read(opb,1)!=0){ + /* Oops. This is not an audio data packet */ + return(-1); + } + + /* Encode the block size */ + vb->W=_oggpack_read(opb,1); + + /* other random setup */ + vb->frameno=op->frameno; + vb->eofflag=op->e_o_s; + vl=&vb->vd->vl[vb->W]; + spectral_order=vi->floororder[vb->W]; + + /* The storage vectors are large enough; set the use markers */ + n=vb->pcmend=vi->blocksize[vb->W]; + vb->multend=vb->pcmend/vi->envelopesa; + + /* we don't know the size of the following window, but we don't need + it yet. We only use the first half of the window */ + window=vb->vd->window[vb->W][vb->lW][0]; - for(i=0;ipcm_channels;i++) + /* recover the time envelope */ + /*if(_ve_envelope_decode(vb)<0)return(-1);*/ + + for(i=0;ichannels;i++){ + double *lpc=vb->lpc[i]; + double *lsp=vb->lsp[i]; + + /* recover the spectral envelope */ + if(_vs_spectrum_decode(vb,&vb->amp[i],lsp)<0)return(-1); + + /* recover the spectral residue */ + if(_vs_residue_decode(vb,vb->pcm[i])<0)return(-1); + + /* LSP->LPC */ + vorbis_lsp_to_lpc(lsp,lpc,vl->m); + + /* apply envelope to residue */ + + vorbis_lpc_apply(vb->pcm[i],lpc,vb->amp[i],vl); + + /* MDCT->time */ mdct_backward(&vb->vd->vm[vb->W],vb->pcm[i],vb->pcm[i],window); - _ve_envelope_apply(vb,1); - + + /* apply time domain envelope */ + /*_ve_envelope_apply(vb,1);*/ + } + + return(0); } -- 2.7.4