********************************************************************
function: libvorbis codec headers
- last mod: $Id: codec.h,v 1.7 2000/01/28 14:31:23 xiphmont Exp $
+ last mod: $Id: codec.h,v 1.8 2000/02/06 13:39:37 xiphmont Exp $
********************************************************************/
double maskthresh[MAX_BARK];
double lrolldB;
double hrolldB;
+
+ /* quantization information to match the residue encoding */
+ /*int blocklen; comes from res info */
+ /*int elements[4]; comes from res info */
+ double cutoffs[4];
+ int quantval[4];
+
} vorbis_info_psy;
/* vorbis_info contains all the setup information specific to the
/* local storage to avoid remallocing; it's up to the mapping to
structure it */
- double *localstore;
+ void *localstore;
long localtop;
long localalloc;
long totaluse;
********************************************************************
function: PCM data vector blocking, windowing and dis/reassembly
- last mod: $Id: block.c,v 1.24 2000/01/28 09:05:06 xiphmont Exp $
+ last mod: $Id: block.c,v 1.25 2000/02/06 13:39:38 xiphmont Exp $
Handle windowing, overlap-add, etc of the PCM vectors. This is made
more amusing by Vorbis' current two allowed block sizes.
vb->localstore=malloc(vb->localalloc);
vb->localtop=0;
}
- return(vb->localstore+vb->localtop);
+ {
+ void *ret=vb->localstore+vb->localtop;
+ vb->localtop+=bytes;
+ return ret;
+ }
}
/* reap the chain, pull the ripcord */
/* initialize all the mapping/backend lookups */
v->mode=calloc(vi->modes,sizeof(vorbis_look_mapping *));
for(i=0;i<vi->modes;i++){
- int maptype=vi->mode_param[i]->mapping;
+ int mapnum=vi->mode_param[i]->mapping;
+ int maptype=vi->map_type[mapnum];
v->mode[i]=_mapping_P[maptype]->look(vi,vi->mode_param[i],
- vi->map_param[maptype]);
+ vi->map_param[mapnum]);
}
/* initialize the storage vectors to a decent size greater than the
free(v->transform[0]);
free(v->transform[1]);
- /* free mode lookups */
+ /* free mode lookups; these are actually vorbis_look_mapping structs */
for(i=0;i<vi->modes;i++){
- int maptype=vi->mode_param[i]->mapping;
+ int mapnum=vi->mode_param[i]->mapping;
+ int maptype=vi->map_type[mapnum];
_mapping_P[maptype]->free_look(v->mode[i]);
}
if(v->mode)free(v->mode);
********************************************************************
function: basic codebook pack/unpack/code/decode operations
- last mod: $Id: codebook.c,v 1.5 2000/02/05 23:23:58 xiphmont Exp $
+ last mod: $Id: codebook.c,v 1.6 2000/02/06 13:39:39 xiphmont Exp $
********************************************************************/
return(book->c->lengthlist[a]);
}
-/* returns the number of bits and *modifies a* to the entry value *****/
+/* returns the number of bits and *modifies a* to the residual error *****/
+static double _dist(double *a, double *b,int dim){
+ int i;
+ double acc=0.;
+ for(i=0;i<dim;i++){
+ double val=(a[i]-b[i]);
+ acc+=val*val;
+ }
+ return sqrt(acc);
+}
+
int vorbis_book_encodev(codebook *book, double *a, oggpack_buffer *b){
encode_aux *t=book->c->encode_tree;
int dim=book->dim;
int ptr=0,k;
-
- while(1){
+
+ /*while(1){
double c=0.;
double *p=book->valuelist+t->p[ptr];
double *q=book->valuelist+t->q[ptr];
for(k=0;k<dim;k++)
c+=(p[k]-q[k])*(a[k]-(p[k]+q[k])*.5);
- if(c>0.) /* in A */
+ if(c>0.) /* in A
ptr= -t->ptr0[ptr];
- else /* in B */
+ else /* in B
ptr= -t->ptr1[ptr];
if(ptr<=0)break;
- }
- memcpy(a,book->valuelist-ptr*dim,dim*sizeof(double));
+ }*/
+
+ {
+ long i;
+ double best=999999.;
+ for(i=0;i<book->entries;i++){
+ double this=_dist(a,book->valuelist+i*dim,dim);
+ if(this<best){
+ best=this;
+ ptr=-i;
+ }
+ }
+ }
+
+
+ for(k=0;k<dim;k++)a[k]-=(book->valuelist-ptr*dim)[k];
return(vorbis_book_encode(book,-ptr,b));
}
/* returns the entry number or -1 on eof ****************************/
long vorbis_book_decodev(codebook *book, double *a, oggpack_buffer *b){
long entry=vorbis_book_decode(book,b);
+ int i;
if(entry==-1)return(-1);
- memcpy(a,book->valuelist+entry*book->dim,sizeof(double)*book->dim);
- return(0);
+ for(i=0;i<book->dim;i++)a[i]+=(book->valuelist+entry*book->dim)[i];
+ return(entry);
}
#ifdef _V_SELFTEST
double *qv=alloca(sizeof(double)*TESTSIZE);
double *iv=alloca(sizeof(double)*TESTSIZE);
memcpy(qv,testvec[ptr],sizeof(double)*TESTSIZE);
+ memset(iv,0,sizeof(double)*TESTSIZE);
fprintf(stderr,"\tpacking/coding %ld... ",ptr);
}
for(i=0;i<TESTSIZE;i+=TESTDIM)
- if(vorbis_book_decodev(&c,iv+i,&read)){
+ if(vorbis_book_decodev(&c,iv+i,&read)==-1){
fprintf(stderr,"Error reading codebook test data (EOP).\n");
exit(1);
}
for(i=0;i<TESTSIZE;i++)
- if(qv[i]!=iv[i]){
+ if(fabs(testvec[ptr][i]-qv[i]-iv[i])>.000001){
fprintf(stderr,"input (%g) != output (%g) at position (%ld)\n",
- iv[i],qv[i],i);
+ iv[i],testvec[ptr][i]-qv[i],i);
exit(1);
}
********************************************************************
function: floor backend 0 implementation
- last mod: $Id: floor0.c,v 1.5 2000/01/28 14:34:43 xiphmont Exp $
+ last mod: $Id: floor0.c,v 1.6 2000/02/06 13:39:40 xiphmont Exp $
********************************************************************/
#include <stdlib.h>
#include <string.h>
+#include <math.h>
#include "vorbis/codec.h"
#include "bitwise.h"
#include "registry.h"
+#include "lpc.h"
+#include "lsp.h"
+#include "bookinternal.h"
+
+typedef struct {
+ long n;
+ long m;
+ vorbis_info_floor0 *vi;
+ lpc_lookup lpclook;
+} vorbis_look_floor0;
static void free_info(vorbis_info_floor *i){
if(i){
free(i);
}
}
+
static void free_look(vorbis_look_floor *i){
+ vorbis_look_floor0 *f=(vorbis_look_floor0 *)i;
+ if(i){
+ lpc_clear(&f->lpclook);
+ memset(f,0,sizeof(vorbis_look_floor0));
+ free(f);
+ }
}
static void pack (vorbis_info_floor *i,oggpack_buffer *opb){
static vorbis_look_floor *look (vorbis_info *vi,vorbis_info_mode *mi,
vorbis_info_floor *i){
-
+ vorbis_info_floor0 *d=(vorbis_info_floor0 *)i;
+ vorbis_look_floor0 *ret=malloc(sizeof(vorbis_look_floor0));
+ ret->m=d->order;
+ ret->n=vi->blocksizes[mi->blockflag]/2;
+ ret->vi=d;
+ lpc_init(&ret->lpclook,ret->n,d->barkmap,d->rate,ret->m);
+ return ret;
}
+#include <stdio.h>
+
static int forward(vorbis_block *vb,vorbis_look_floor *i,
double *in,double *out){
+ long j,k,l;
+ vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
+ vorbis_info_floor0 *info=look->vi;
+
+ /* use 'out' as temp storage */
+ /* Convert our floor to a set of lpc coefficients */
+ double amp=sqrt(vorbis_curve_to_lpc(in,out,&look->lpclook));
+ double *work=alloca(sizeof(double)*look->m);
+
+ /* LSP <-> LPC is orthogonal and LSP quantizes more stably */
+ vorbis_lpc_to_lsp(out,out,look->m);
+ memcpy(work,out,sizeof(double)*look->m);
+
+ for(j=12;j<20;j++)
+ fprintf(stderr,"%0.3g, ",out[j]);
+ fprintf(stderr,"\n");
+
+ /* code the spectral envelope, and keep track of the actual quantized
+ values */
+ _oggpack_write(&vb->opb,amp*32768,18);
+ {
+ codebook *b=vb->vd->fullbooks+info->books[0];
+ double last=0.;
+ for(j=0;j<look->m;){
+ double next=out[j+b->dim-1];
+ for(k=0;k<b->dim;k++,j++)out[j]-=last;
+ last=next;
+ }
+ }
+ for(k=0;k<info->stages;k++){
+ codebook *b=vb->vd->fullbooks+info->books[k];
+ for(j=0;j<look->m;j+=b->dim)
+ vorbis_book_encodev(b,out+j,&vb->opb);
+ }
+
+ for(j=0;j<look->m;j++)
+ out[j]=work[j]-out[j];
- /* 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
+ /* take the coefficients back to a spectral envelope curve */
+ vorbis_lsp_to_lpc(out,out,look->m);
+ vorbis_lpc_to_curve(out,out,amp,&look->lpclook);
- vorbis_lsp_to_lpc(lsp,lpc,vl->m);
- vorbis_lpc_to_curve(curve,lpc,vb->amp[i],vl);*/
return(0);
}
-static int inverse(vorbis_block *vb,vorbis_look_floor *i,
- double *buf){
+
+static int inverse(vorbis_block *vb,vorbis_look_floor *i,double *out){
+ vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
+ vorbis_info_floor0 *info=look->vi;
+ int j,k;
+
+ double amp=_oggpack_read(&vb->opb,18)/32768.;
+ memset(out,0,sizeof(double)*look->m);
+ for(k=0;k<info->stages;k++){
+ codebook *b=vb->vd->fullbooks+info->books[k];
+ for(j=0;j<look->m;j+=b->dim)
+ vorbis_book_decodev(b,out+j,&vb->opb);
+ }
+
+ {
+ codebook *b=vb->vd->fullbooks+info->books[0];
+ double last=0.;
+ for(j=0;j<look->m;){
+ for(k=0;k<b->dim;k++,j++)out[j]+=last;
+ last=out[j-1];
+ }
+ }
+
+ for(j=12;j<20;j++)
+ fprintf(stderr,"%0.3g, ",out[j]);
+ fprintf(stderr,"\n");
+
+
+ /* take the coefficients back to a spectral envelope curve */
+ vorbis_lsp_to_lpc(out,out,look->m);
+ vorbis_lpc_to_curve(out,out,amp,&look->lpclook);
+
return(0);
}
********************************************************************
function: maintain the info structure, info <-> header packets
- last mod: $Id: info.c,v 1.19 2000/01/28 14:31:26 xiphmont Exp $
+ last mod: $Id: info.c,v 1.20 2000/02/06 13:39:41 xiphmont Exp $
********************************************************************/
/*if(vi->mode_param)free(vi->mode_param);*/
for(i=0;i<vi->maps;i++) /* unpack does the range checking */
- _mapping_P[i]->free_info(vi->map_param[i]);
+ _mapping_P[vi->map_type[i]]->free_info(vi->map_param[i]);
/*if(vi->map_param)free(vi->map_param);*/
for(i=0;i<vi->times;i++) /* unpack does the range checking */
- _time_P[i]->free_info(vi->time_param[i]);
+ _time_P[vi->time_type[i]]->free_info(vi->time_param[i]);
/*if(vi->time_param)free(vi->time_param);*/
for(i=0;i<vi->floors;i++) /* unpack does the range checking */
- _floor_P[i]->free_info(vi->floor_param[i]);
+ _floor_P[vi->floor_type[i]]->free_info(vi->floor_param[i]);
/*if(vi->floor_param)free(vi->floor_param);*/
for(i=0;i<vi->residues;i++) /* unpack does the range checking */
- _residue_P[i]->free_info(vi->residue_param[i]);
+ _residue_P[vi->residue_type[i]]->free_info(vi->residue_param[i]);
/*if(vi->residue_param)free(vi->residue_param);*/
/* the static codebooks *are* freed if you call info_clear, because
/* second header packet (comments) **********************************/
_oggpack_reset(&opb);
- _v_writestring(&opb,"vorbis");
- _oggpack_write(&opb,0x81,8);
if(_vorbis_pack_comment(&opb,vc))goto err_out;
if(v->header1)free(v->header1);
/* third header packet (modes/codebooks) ****************************/
_oggpack_reset(&opb);
- _v_writestring(&opb,"vorbis");
- _oggpack_write(&opb,0x82,8);
if(_vorbis_pack_books(&opb,vi))goto err_out;
if(v->header2)free(v->header2);
********************************************************************
function: LPC low level routines
- last mod: $Id: lpc.c,v 1.15 2000/01/28 09:05:11 xiphmont Exp $
+ last mod: $Id: lpc.c,v 1.16 2000/02/06 13:39:42 xiphmont Exp $
********************************************************************/
double *lcurve=alloca(sizeof(double)*(l->ln*2));
int i;
+ if(amp==0){
+ memset(curve,0,sizeof(double)*l->n);
+ return;
+ }
_vlpc_de_helper(lcurve,lpc,amp,l);
#ifdef ANALYSIS
#endif
- if(amp==0)return;
-
for(i=0;i<l->ln;i++)lcurve[i]/=l->barknorm[i];
for(i=0;i<l->n;i++)curve[i]=lcurve[l->linearmap[i]];
********************************************************************
function: channel mapping 0 implementation
- last mod: $Id: mapping0.c,v 1.6 2000/01/28 15:25:09 xiphmont Exp $
+ last mod: $Id: mapping0.c,v 1.7 2000/02/06 13:39:43 xiphmont Exp $
********************************************************************/
free(l->floor_look);
free(l->residue_look);
if(l->psy_look)free(l->psy_look);
- memset(l,0,sizeof(vorbis_info_mapping0));
+ memset(l,0,sizeof(vorbis_look_mapping0));
free(l);
}
}
ret->time_look=calloc(map->submaps,sizeof(vorbis_look_time *));
ret->floor_look=calloc(map->submaps,sizeof(vorbis_look_floor *));
ret->residue_look=calloc(map->submaps,sizeof(vorbis_look_residue *));
- ret->psy_look=calloc(map->submaps,sizeof(vorbis_look_psy));
+ if(vi->psys)ret->psy_look=calloc(map->submaps,sizeof(vorbis_look_psy));
ret->time_func=calloc(map->submaps,sizeof(vorbis_func_time *));
ret->floor_func=calloc(map->submaps,sizeof(vorbis_func_floor *));
ret->residue_look[i]=ret->residue_func[i]->
look(vi,vm,vi->residue_param[resnum]);
- if(map->psysubmap){
+ if(vi->psys){
int psynum=map->psysubmap[i];
_vp_psy_init(ret->psy_look+i,vi->psy_param[psynum],
- vi->blocksizes[vm->blockflag],vi->rate);
+ vi->blocksizes[vm->blockflag]/2,vi->rate);
}
}
/* perform residue prequantization. Do it now so we have all
the values if we need them */
- _vp_quantize(look->psy_look+submap,pcm,mask,decfloor,pcmaux[i]);
+ _vp_quantize(look->psy_look+submap,pcm,mask,decfloor,pcmaux[i],0,n/2,n/2);
}
********************************************************************
function: psychoacoustics not including preecho
- last mod: $Id: psy.c,v 1.14 2000/01/28 15:25:10 xiphmont Exp $
+ last mod: $Id: psy.c,v 1.15 2000/02/06 13:39:44 xiphmont Exp $
********************************************************************/
}
}
+/* take a masking curve and raw residue; eliminate the inaduble and
+ quantize to the final form handed to the VQ. All and any tricks to
+ squeeze out bits given knowledge of the encoding mode should go
+ here too */
+
+/* modifies the pcm vector, returns book membership in aux */
+
+void _vp_quantize(vorbis_look_psy *p, double *pcm, double *mask,
+ double *floor,int *aux,long begin, long n,long subn){
+ long i,j;
+ /* for now, we're not worrying about subvector, but the idea is
+ that we normal blocks not have zeroes; zeroes only exist as an
+ all-zero block */
+
+ for(i=begin;i<n;i++){
+ double value=rint(pcm[i]/floor[i]);
+ if(value>15)value=15;
+ if(value<-15)value=-15;
+ pcm[i]=value;
+ }
+
+}
+
/* 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;
********************************************************************
function: random psychoacoustics (not including preecho)
- last mod: $Id: psy.h,v 1.9 2000/02/05 23:31:50 xiphmont Exp $
+ last mod: $Id: psy.h,v 1.10 2000/02/06 13:39:45 xiphmont Exp $
********************************************************************/
extern void _vp_mask_floor(vorbis_look_psy *p,double *pcm,
double *mask,double *floor);
extern void _vp_quantize(vorbis_look_psy *p, double *pcm, double *mask,
- double *floor,int *aux);
+ double *floor,int *aux,
+ long begin,long n, long subn);
#endif
********************************************************************
function: residue backend 0 implementation
- last mod: $Id: res0.c,v 1.3 2000/01/28 14:31:28 xiphmont Exp $
+ last mod: $Id: res0.c,v 1.4 2000/02/06 13:39:46 xiphmont Exp $
********************************************************************/
#include <stdlib.h>
#include <string.h>
+#include <math.h>
#include "vorbis/codec.h"
#include "bitwise.h"
#include "registry.h"
/* unfinished as of 20000118 */
void free_info(vorbis_info_residue *i){
- if(i){
- memset(i,0,sizeof(vorbis_info_residue0));
- free(i);
- }
}
void free_look(vorbis_look_residue *i){
/* vorbis_info is for range checking */
vorbis_info_residue *unpack(vorbis_info *vi,oggpack_buffer *opb){
+ return "";
}
vorbis_look_residue *look (vorbis_info *vi,vorbis_info_mode *vm,
vorbis_info_residue *vr){
+ return "";
}
-int forward(vorbis_block *vb,vorbis_look_residue *l,double **in,int **aux,int ch){
+int forward(vorbis_block *vb,vorbis_look_residue *l,
+ double **in,int **aux,int ch){
+ long i,j;
+ for(i=0;i<ch;i++)
+ for(j=0;j<vb->pcmend/2;j++)
+ _oggpack_write(&vb->opb,rint(in[i][j])+16,5);
+ return(0);
}
+
int inverse(vorbis_block *vb,vorbis_look_residue *l,double **in,int ch){
+ long i,j;
+ for(i=0;i<ch;i++)
+ for(j=0;j<vb->pcmend/2;j++)
+ in[i][j]*=_oggpack_read(&vb->opb,5)-16;
+ return(0);
}
vorbis_func_residue residue0_exportbundle={
********************************************************************
function: time backend 0 (dummy)
- last mod: $Id: time0.c,v 1.2 2000/01/22 13:28:34 xiphmont Exp $
+ last mod: $Id: time0.c,v 1.3 2000/02/06 13:39:47 xiphmont Exp $
********************************************************************/
static void pack (vorbis_info_time *i,oggpack_buffer *opb){
}
static vorbis_info_time *unpack (vorbis_info *vi,oggpack_buffer *opb){
- return NULL;
+ return "";
+
}
static vorbis_look_time *look (vorbis_info *vi,vorbis_info_mode *mi,
vorbis_info_time *i){
- return NULL;
+ return "";
}
static void free_info(vorbis_info_time *i){
}
********************************************************************
function: window functions
- last mod: $Id: window.c,v 1.5 2000/01/28 15:25:12 xiphmont Exp $
+ last mod: $Id: window.c,v 1.6 2000/02/06 13:39:48 xiphmont Exp $
********************************************************************/
ret[i+rightbegin]=x;
}
}
+ break;
default:
free(ret);
return(NULL);