# 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 $
###############################################################################
# #
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
function: single-block PCM analysis
author: Monty <xiphmont@mit.edu>
modifications by: Monty
- last modification date: Oct 4 1999
+ last modification date: Oct 7 1999
********************************************************************/
#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;i<vi->channels;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;i<vi->channels;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];
}
}*/
-
- /* extract the spectral envelope and residue */
- /* just do by channel. No coupling yet */
- {
- for(i=0;i<vi->channels;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;i<vl->m;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;i<n/2;i++)
- fprintf(out,"%g\n",fabs(C[i]));
- fclose(out);
-
- sprintf(buffer,"qD%d.m",frameno);
- out=fopen(buffer,"w+");
- for(i=0;i<n/2;i++)
- fprintf(out,"%g\n",fabs(D[i]));
- fclose(out);
-
- sprintf(buffer,"floor%d.m",frameno);
- out=fopen(buffer,"w+");
- for(i=0;i<n/2;i++)
- fprintf(out,"%g\n",floor1[i]);
- fclose(out);
-
- sprintf(buffer,"lpc%d.m",frameno);
- out=fopen(buffer,"w+");
- for(i=0;i<n/2;i++)
- fprintf(out,"%g\n",work[i]);
- fclose(out);
-
- sprintf(buffer,"curve%d.m",frameno);
- out=fopen(buffer,"w+");
- for(i=0;i<n/2;i++)
- fprintf(out,"%g\n",curve[i]);
- fclose(out);
-
- sprintf(buffer,"lsp%d.m",frameno);
- out=fopen(buffer,"w+");
- for(i=0;i<30;i++){
- fprintf(out,"%g 0.\n",lsp1[i]);
- fprintf(out,"%g .1\n",lsp1[i]);
- fprintf(out,"\n");
- fprintf(out,"\n");
- }
- fclose(out);*/
-
- frameno++;
- }
- }
- /* unmix */
- _vp_balance_apply(D,C,balance_v,balance_amp,vbal,0);
- }
-
- return(0);
-}
-
b->endbit=b->endbyte=0;
}
-void _oggpack_writefree(oggpack_buffer *b){
+void _oggpack_writeclear(oggpack_buffer *b){
free(b->buffer);
memset(b,0,sizeof(oggpack_buffer));
}
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);
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;i<vb->pcm_channels;i++)
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);
}
free(vb->mult[i]);
free(vb->mult);
}
+ if(vb->vd->analysisp)
+ _oggpack_writeclear(&vb->opb);
+
memset(vb,0,sizeof(vorbis_block));
return(0);
}
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 */
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 *));
{
/* 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;i<v->envelope_channels;i++){
+ for(i=0;i<vi->envelopech;i++){
v->multipliers[i]=calloc(v->envelope_storage,sizeof(double));
}
}
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);
}
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);
}
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;i<v->pcm_channels;i++)
+ for(i=0;i<vi->channels;i++)
if(v->pcm[i])free(v->pcm[i]);
free(v->pcm);
if(v->pcmret)free(v->pcmret);
}
if(v->multipliers){
- for(i=0;i<v->envelope_channels;i++)
+ for(i=0;i<vi->envelopech;i++)
if(v->multipliers[i])free(v->multipliers[i]);
free(v->multipliers);
}
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;i<v->pcm_channels;i++){
+ for(i=0;i<vi->channels;i++){
v->pcm[i]=realloc(v->pcm[i],v->pcm_storage*sizeof(double));
}
- for(i=0;i<v->envelope_channels;i++){
+ for(i=0;i<vi->envelopech;i++){
v->multipliers[i]=realloc(v->multipliers[i],
v->envelope_storage*sizeof(double));
}
}
- for(i=0;i<v->pcm_channels;i++)
+ for(i=0;i<vi->channels;i++)
v->pcmret[i]=v->pcm[i]+v->pcm_current;
return(v->pcmret);
/* 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;i<v->pcm_channels;i++)
+ v->pcm_current+=v->vi->blocksize[1]*2;
+ for(i=0;i<vi->channels;i++)
memset(v->pcm[i]+v->eofflag,0,
(v->pcm_current-v->eofflag)*sizeof(double));
}else{
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);
/* 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);
/* 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.smallblock<v->vi.largeblock){
+ if(vi->blocksize[0]<vi->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(;i<v->envelope_current;i++){
- for(j=0;j<v->envelope_channels;j++)
- if(v->multipliers[j][i-1]*v->vi.preecho_thresh<
+ for(j=0;j<vi->envelopech;j++)
+ if(v->multipliers[j][i-1]*vi->preecho_thresh<
v->multipliers[j][i])break;
- if(j<v->envelope_channels)break;
+ if(j<vi->envelopech)break;
}
if(i<v->envelope_current){
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;
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_current<blockbound)return(0); /* not enough data yet */
}
vb->nW=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;i<v->pcm_channels;i++)
- memcpy(vb->pcm[i],v->pcm[i]+beginW,v->block_size[v->W]*sizeof(double));
- for(i=0;i<v->envelope_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;i<vi->channels;i++)
+ memcpy(vb->pcm[i],v->pcm[i]+beginW,vi->blocksize[v->W]*sizeof(double));
+ for(i=0;i<vi->envelopech;i++)
+ memcpy(vb->mult[i],v->multipliers[i]+beginM,vi->blocksize[v->W]/
+ vi->envelopesa*sizeof(double));
vb->frameno=v->frame;
/* 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;i<v->pcm_channels;i++)
+ for(i=0;i<vi->channels;i++)
memmove(v->pcm[i],v->pcm[i]+movementW,
(v->pcm_current-movementW)*sizeof(double));
- for(i=0;i<v->envelope_channels;i++){
+ for(i=0;i<vi->envelopech;i++){
memmove(v->multipliers[i],v->multipliers[i]+movementM,
(v->envelope_current-movementM)*sizeof(double));
}
/* 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);
}
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_returned<shift?v->pcm_returned:shift);
v->pcm_current-=shift;
if(shift){
int i;
- for(i=0;i<v->pcm_channels;i++)
+ for(i=0;i<vi->channels;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;
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;i<v->pcm_channels;i++)
+ for(i=0;i<vi->channels;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;j<v->pcm_channels;j++){
+ for(j=0;j<vi->channels;j++){
double *pcm=v->pcm[j]+beginW;
/* the add section */
}
int vorbis_synthesis_pcmout(vorbis_dsp_state *v,double ***pcm){
+ vorbis_info *vi=v->vi;
if(v->pcm_returned<v->centerW){
int i;
- for(i=0;i<v->pcm_channels;i++)
+ for(i=0;i<vi->channels;i++)
v->pcmret[i]=v->pcm[i]+v->pcm_returned;
*pcm=v->pcmret;
return(v->centerW-v->pcm_returned);
function: codec headers
author: Monty <xiphmont@mit.edu>
modifications by: Monty
- last modification date: Oct 4 1999
+ last modification date: Oct 6 1999
********************************************************************/
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;
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;
double **lpc;
double **lsp;
double *amp;
+ oggpack_buffer opb;
int pcm_channels; /* allocated, not used */
int pcm_storage; /* allocated, not used */
/* 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;
ptr+=2;
}
}
+ fwrite(convbuffer,2*vi.channels,out,stdout);
vorbis_synthesis_read(&vd,out); /* tell libvorbis how
many samples we
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
function: PCM data envelope analysis and manipulation
author: Monty <xiphmont@mit.edu>
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
#include "codec.h"
#include "envelope.h"
+#include "bitwise.h"
void _ve_envelope_init(envelope_lookup *e,int samples_per){
int i;
}
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;ech<vi->envelopech;ech++){
double *mult=v->multipliers[ech]+dcurr;
coefficients */
void _ve_envelope_sparsify(vorbis_block *vb){
+ vorbis_info *vi=vb->vd->vi;
int ch;
- for(ch=0;ch<vb->vd->vi.envelopech;ch++){
+ for(ch=0;ch<vi->envelopech;ch++){
int flag=0;
double *mult=vb->mult[ch];
int n=vb->multend;
/* are we going to multiply anything? */
for(i=1;i<n;i++){
- if(mult[i]>=last*vb->vd->vi.preecho_thresh){
+ if(mult[i]>=last*vi->preecho_thresh){
flag=1;
break;
}
- if(i<n-1 && mult[i+1]>=last*vb->vd->vi.preecho_thresh){
+ if(i<n-1 && mult[i+1]>=last*vi->preecho_thresh){
flag=1;
break;
}
last=1;
for(;i<n;i++){
- if(mult[i]/last>clamp*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;
}
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;
}
}
+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;i<vi->envelopech;i++){
+ double *mult=vb->mult[i];
+ for(j=0;j<n;j++)
+ _oggpack_write(&vb->opb,(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;i<vi->envelopech;i++){
+ double *mult=vb->mult[i];
+ for(j=0;j<n;j++)
+ mult[j]=_oggpack_read(&vb->opb,4);
+ }
+ return(0);
+}
+
+
function: PCM data envelope analysis and manipulation
author: Monty <xiphmont@mit.edu>
modifications by: Monty
- last modification date: Aug 07 1999
+ last modification date: Oct 07 1999
********************************************************************/
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
function: maintain the info structure, info <-> header packets
author: Monty <xiphmont@mit.edu>
modifications by: Monty
- last modification date: Oct 04 1999
+ last modification date: Oct 06 1999
********************************************************************/
return(-1);
}
switch(_oggpack_read(&opb,8)){
- case 0:
+ case 0x80:
if(!op->b_o_s){
/* Not the initial packet */
return(-1);
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);
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;i<vi->comments;i++){
int len=_oggpack_read(&opb,32);
vi->user_comments[i]=calloc(len+1,1);
_v_readstring(&opb,vi->user_comments[i],len);
}
return(0);
- case 2:
+ case 0x82:
if(vi->rate==0){
/* um... we didn;t get the initial header */
return(-1);
/* 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 */
/* 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)
_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);
/* 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));
op_code->e_o_s=0;
op_code->frameno=0;
- _oggpack_writefree(&opb);
+ _oggpack_writeclear(&opb);
return(0);
}
author: Monty <xiphmont@mit.edu>
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
********************************************************************/
-/* Undef the following if you want a normal MDCT */
-#define VORBIS_SPECIFIC_MODIFICATIONS
-
#include <stdlib.h>
#include <string.h>
#include <math.h>
double *BE=init->trig+n2;
double *BO=BE+n4;
double *out2=out+n2;
+ double scale=4./n;
for(i=0;i<n4;i++){
- out[i] =x[0]* *BE+x[2]* *BO;
- *(--out2)=x[0]* *BO-x[2]* *BE;
+ out[i] =(x[0]* *BE+x[2]* *BO)*scale;
+ *(--out2)=(x[0]* *BO-x[2]* *BE)*scale;
x+=4;
BO++;
BE++;
double *BO=BE+n4;
int o1=n4,o2=o1-1;
int o3=n4+n2,o4=o3-1;
- double scale=n/4.;
for(i=0;i<n4;i++){
- double BEv=BE[i];
- double BOv=BO[i];
-#ifdef VORBIS_SPECIFIC_MODIFICATIONS
- double temp= (*x * BOv - *(x+2) * BEv)/ scale;
- out[o3]=out[o4]=(*x * BEv + *(x+2) * BOv)/ -scale;
+ double temp= (*x * *BO - *(x+2) * *BE);
+ out[o3]=out[o4]= -(*x * *BE + *(x+2) * *BO);
out[o1]=-temp*window[o1];
out[o2]=temp*window[o2];
-#else
- double temp1= (*x * BOv - *(x+2) * BEv)* scale;
- double temp2= (*x * BEv + *(x+2) * BOv)* -scale;
-
- out[o1]=-temp1*window[o1];
- out[o2]=temp1*window[o2];
- out[o3]=temp2*window[o3];
- out[o4]=temp2*window[o4];
-#endif
o1++;
o2--;
o3++;
o4--;
x+=4;
+ BE++;BO++;
}
}
}
-
-
-
-
-
-
-
-
vorbis_info predef_modes[]={
/* CD quality stereo, no channel coupling */
- { 2, 44100, 0, NULL, 0, NULL, 512, 2048, 64, 2, 30, 5, 2, 0, 0, 10, .5,
+ { 2, 44100, 0, NULL, 0, NULL, {512, 2048}, {30,30}, {5,5}, 64,2,2, 10, .5,
NULL,NULL,NULL},
};
#include "smallft.h"
#include "xlogmap.h"
-#define NOISEdB 10
+#define NOISEdB 0
#define MASKdB 18
#define HROLL 60
}
}
-void _vp_psy_quantize(double *f, double *m,int n){
- int i;
- for(i=0;i<n;i++){
- int val=rint(f[i]/m[i]);
- if(val>16)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<n;i++)
- f[i]*=m[i];
-}
-
-void _vp_psy_sparsify(double *f, double *m,int n){
- int i;
- for(i=0;i<n;i++)
- if(fabs(f[i])<m[i]*.5)f[i]=0;
-}
-
/* s must be padded at the end with m-1 zeroes */
static void time_convolve(double *s,double *r,int n,int m){
int i;
--- /dev/null
+/********************************************************************
+ * *
+ * 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 <monty@xiph.org> and The XIPHOPHORUS Company *
+ * http://www.xiph.org/ *
+ * *
+ ********************************************************************
+
+ function: spectrum envelope and residue code/decode
+ author: Monty <xiphmont@mit.edu>
+ modifications by: Monty
+ last modification date: Oct 10 1999
+
+ ********************************************************************/
+
+#include <stdio.h>
+#include <math.h>
+#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;i<vb->vd->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;i<vb->vd->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;i<n;i++){
+
+ int val=rint(data[i]/curve[i]);
+ if(val>16)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;i<n;i++){
+ _oggpack_write(&vb->opb,(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;i<n;i++){
+ data[i]=_oggpack_read(&vb->opb,6)-16;
+ /*if(data[i]>=0)data[i]+=1;*/
+ }
+ return(0);
+}
+
--- /dev/null
+/********************************************************************
+ * *
+ * 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 <monty@xiph.org> 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
function: single-block PCM synthesis
author: Monty <xiphmont@mit.edu>
modifications by: Monty
- last modification date: Aug 08 1999
+ last modification date: Oct 07 1999
********************************************************************/
+#include <stdio.h>
#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;i<vi->floorch;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;i<vi->channels;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;i<vb->pcm_channels;i++)
+ /* recover the time envelope */
+ /*if(_ve_envelope_decode(vb)<0)return(-1);*/
+
+ for(i=0;i<vi->channels;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);
}