Commit 357f3923 authored by Monty's avatar Monty
Browse files

Ongoig psychoacoustic work:

Scaling bugfixes
More psychoacoustic tuning
preecho improvements
filter coding bugfix

Monty

svn path=/trunk/vorbis/; revision=152
parent 15ab9475
# vorbis makefile configured for use with gcc on any platform
# $Id: Makefile.in,v 1.11 1999/10/10 20:32:17 xiphmont Exp $
# $Id: Makefile.in,v 1.12 1999/10/18 09:41:07 xiphmont Exp $
###############################################################################
# #
......@@ -27,7 +27,7 @@ AR=@AR@
RANLIB=@RANLIB@
LIBS=@LIBS@ -lm
HFILES = mdct.h codec.h bitwise.h envelope.h lpc.h lsp.h modes.h\
HFILES = mdct.h codec.h bitwise.h envelope.h lpc.h lsp.h \
psy.h smallft.h window.h xlogmap.h
LFILES = framing.o mdct.o smallft.o block.o envelope.o window.o\
......@@ -42,6 +42,9 @@ all:
debug:
$(MAKE) target CFLAGS="$(DEBUG)"
analysis:
$(MAKE) target CFLAGS="$(DEBUG) -DANALYSIS"
profile:
$(MAKE) target CFLAGS="$(PROFILE)"
......@@ -70,6 +73,8 @@ libvorbis.a: $(LFILES)
$(LFILES): $(HFILES)
info.o: modes.h
.c.o:
$(CC) $(CFLAGS) -c $<
......
......@@ -14,7 +14,7 @@
function: single-block PCM analysis
author: Monty <xiphmont@mit.edu>
modifications by: Monty
last modification date: Oct 7 1999
last modification date: Oct 15 1999
********************************************************************/
......@@ -34,10 +34,9 @@
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];
psy_lookup *vp=&vb->vd->vp[vb->W];
lpc_lookup *vl=&vb->vd->vl[vb->W];
vorbis_dsp_state *vd=vb->vd;
vorbis_info *vi=vd->vi;
......@@ -46,6 +45,11 @@ int vorbis_analysis(vorbis_block *vb,ogg_packet *op){
int n=vb->pcmend;
int spectral_order=vi->floororder[vb->W];
vb->gluebits=0;
vb->time_envelope_bits=0;
vb->spectral_envelope_bits=0;
vb->spectral_residue_bits=0;
/*lpc_lookup *vbal=&vb->vd->vbal[vb->W];
double balance_v[vbal->m];
double balance_amp;*/
......@@ -74,6 +78,8 @@ int vorbis_analysis(vorbis_block *vb,ogg_packet *op){
/* just do by channel. No coupling yet */
{
for(i=0;i<vi->channels;i++){
static int frameno=0;
int j;
double floor[n/2];
double curve[n/2];
double *lpc=vb->lpc[i];
......@@ -81,8 +87,41 @@ int vorbis_analysis(vorbis_block *vb,ogg_packet *op){
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);
_vp_noise_floor(vp,vb->pcm[i],floor);
#ifdef ANALYSIS
{
FILE *out;
char buffer[80];
sprintf(buffer,"spectrum.m");
out=fopen(buffer,"w+");
for(j=0;j<n/2;j++)
fprintf(out,"%g\n",vb->pcm[i][j]);
fclose(out);
sprintf(buffer,"noise.m");
out=fopen(buffer,"w+");
for(j=0;j<n/2;j++)
fprintf(out,"%g\n",floor[j]);
fclose(out);
}
#endif
_vp_mask_floor(vp,vb->pcm[i],floor);
#ifdef ANALYSIS
{
FILE *out;
char buffer[80];
sprintf(buffer,"premask.m");
out=fopen(buffer,"w+");
for(j=0;j<n/2;j++)
fprintf(out,"%g\n",floor[j]);
fclose(out);
}
#endif
/* Convert our floor to a set of lpc coefficients */
vb->amp[i]=sqrt(vorbis_curve_to_lpc(floor,lpc,vl));
......@@ -104,6 +143,25 @@ int vorbis_analysis(vorbis_block *vb,ogg_packet *op){
/* this may do various interesting massaging too...*/
_vs_residue_quantize(vb->pcm[i],curve,vi,n/2);
#ifdef ANALYSIS
{
FILE *out;
char buffer[80];
sprintf(buffer,"mask.m");
out=fopen(buffer,"w+");
for(j=0;j<n/2;j++)
fprintf(out,"%g\n",curve[j]);
fclose(out);
sprintf(buffer,"res.m");
out=fopen(buffer,"w+");
for(j=0;j<n/2;j++)
fprintf(out,"%g\n",vb->pcm[i][j]);
fclose(out);
}
#endif
/* encode the residue */
_vs_residue_encode(vb,vb->pcm[i]);
......
......@@ -14,7 +14,7 @@
function: PCM data vector blocking, windowing and dis/reassembly
author: Monty <xiphmont@mit.edu>
modifications by: Monty
last modification date: Oct 2 1999
last modification date: Oct 15 1999
Handle windowing, overlap-add, etc of the PCM vectors. This is made
more amusing by Vorbis' current two allowed block sizes.
......@@ -32,6 +32,8 @@
#include "envelope.h"
#include "mdct.h"
#include "lpc.h"
#include "bitwise.h"
#include "psy.h"
/* pcm accumulator examples (not exhaustive):
......@@ -199,12 +201,15 @@ int vorbis_analysis_init(vorbis_dsp_state *v,vorbis_info *vi){
/* the coder init is different for read/write */
v->analysisp=1;
_vp_psy_init(&v->vp[0],vi,vi->blocksize[0]/2);
_vp_psy_init(&v->vp[1],vi,vi->blocksize[1]/2);
/* Yes, wasteful to have four lookups. This will get collapsed once
things crystallize */
lpc_init(&v->vl[0],vi->blocksize[0]/2,vi->blocksize[0]/8,
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]/8,
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->blocksize[0]/2,256,
......@@ -240,6 +245,8 @@ void vorbis_dsp_clear(vorbis_dsp_state *v){
mdct_clear(&v->vm[1]);
lpc_clear(&v->vl[0]);
lpc_clear(&v->vl[1]);
_vp_psy_clear(&v->vp[0]);
_vp_psy_clear(&v->vp[1]);
/*lpc_clear(&v->vbal[0]);
lpc_clear(&v->vbal[1]);*/
memset(v,0,sizeof(vorbis_dsp_state));
......@@ -394,7 +401,8 @@ int vorbis_analysis_blockout(vorbis_dsp_state *v,vorbis_block *vb){
memcpy(vb->mult[i],v->multipliers[i]+beginM,vi->blocksize[v->W]/
vi->envelopesa*sizeof(double));
vb->frameno=v->frame;
vb->sequence=v->sequence;
vb->frameno=v->frameno;
/* handle eof detection: eof==0 means that we've not yet received EOF
eof>0 marks the last 'real' sample in pcm[]
......@@ -433,8 +441,8 @@ int vorbis_analysis_blockout(vorbis_dsp_state *v,vorbis_block *vb){
v->W=v->nW;
v->centerW=new_centerNext;
v->frame++;
v->samples+=movementW;
v->sequence++;
v->frameno+=movementW;
if(v->eofflag)
v->eofflag-=movementW;
......@@ -452,9 +460,9 @@ 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->blocksize[0]/2,vi->blocksize[0]/8,
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]/8,
lpc_init(&v->vl[1],vi->blocksize[1]/2,vi->blocksize[0]/2,
vi->floororder[1],vi->flooroctaves[1],0);
/*lpc_init(&v->vbal[0],vi->blocksize[0]/2,256,
vi->balanceorder,vi->balanceoctaves,0);
......@@ -477,6 +485,7 @@ int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb){
/* Shift out any PCM that we returned previously */
v->sequence++;
if(v->pcm_returned && v->centerW>vi->blocksize[1]/2){
/* don't shift too much; we need to have a minimum PCM buffer of
......@@ -500,6 +509,11 @@ int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb){
v->lW=v->W;
v->W=vb->W;
v->gluebits+=vb->gluebits;
v->time_envelope_bits+=vb->time_envelope_bits;
v->spectral_envelope_bits+=vb->spectral_envelope_bits;
v->spectral_residue_bits+=vb->spectral_residue_bits;
{
int sizeW=vi->blocksize[v->W];
int centerW=v->centerW+vi->blocksize[v->lW]/4+sizeW/4;
......
......@@ -36,6 +36,15 @@
/* lookup structures for various simple transforms *****************/
typedef struct {
int n;
struct vorbis_info *vi;
double *noisethresh;
double *maskthresh;
} psy_lookup;
typedef struct {
int n;
int log2n;
......@@ -87,6 +96,8 @@ typedef struct {
compression/decompression mode in progress (eg, psychoacoustic settings,
channel setup, options, codebook etc) *********************************/
#define THRESH_POINTS 20
typedef struct vorbis_info{
int channels;
int rate;
......@@ -116,9 +127,21 @@ typedef struct vorbis_info{
int balanceoctaves;
this would likely need to be by channel and blocksize anyway*/
/* Encode-side settings for analysis */
double preecho_thresh;
double preecho_clamp;
double *threshhold_points;
double noisethresh[THRESH_POINTS];
double lnoise;
double hnoise;
double noisebias;
double maskthresh[THRESH_POINTS];
double lroll;
double hroll;
double maskbias;
/* local storage, only used on the encoding size. This way the
application does not need to worry about freeing some packets'
memory and not others'. Packet storage is always tracked */
......@@ -206,6 +229,7 @@ typedef struct vorbis_dsp_state{
mdct_lookup vm[2];
lpc_lookup vl[2];
lpc_lookup vbal[2];
psy_lookup vp[2];
double **pcm;
double **pcmret;
......@@ -224,8 +248,8 @@ typedef struct vorbis_dsp_state{
long nW;
long centerW;
long frame;
long samples;
long frameno;
long sequence;
size64 gluebits;
size64 time_envelope_bits;
......@@ -262,6 +286,7 @@ typedef struct vorbis_block{
int eofflag;
int frameno;
int sequence;
vorbis_dsp_state *vd; /* For read-only access of configuration */
long gluebits;
......
/********************************************************************
* *
* 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: coder backend; handles encoding into and decoding from
codewords, codebook generation, and codebook transmission
author: Monty <xiphmont@mit.edu>
modifications by: Monty
last modification date: Oct 13 1999
********************************************************************/
#include <stdlib.h>
#include "codec.h"
/* several basic functions:
create codebooks from representation
create codebooks from data
encode codebooks
decode codebooks
encode using codebook
decode using codebook
map an entry to a sparse codebook's (eg, VQ) codeword index
*/
typedef struct vorbis_codebook{
int entries;
/*** codebook side ****************************************************/
/* encode side tree structure (indice->codeword) */
int *codewords; /* null if indice==codeword (ie fixed len codeword) */
int *codelengths; /* null if indice==codeword */
int len; /* -1 if varlength */
/* decode side tree structure (codeword->indice) */
int *tree; /* null if codeword==indice */
/*** mapping side *****************************************************/
int wordsper;
/* decode is easy */
int remaining;
int *mapping;
/* encode in the VQ case is what's hard. We need to find the
'closest match' out of a large n-dimentional space */
} vorbis_codebook;
......@@ -197,6 +197,7 @@ int main(){
while((samples=vorbis_synthesis_pcmout(&vd,&pcm))>0){
int j;
int clipflag=0;
int out=(samples<convsize?samples:convsize);
/* convert doubles to 16 bit signed ints (host order) and
......@@ -207,12 +208,23 @@ int main(){
for(j=0;j<out;j++){
int val=rint(mono[j]*32767.);
/* might as well guard clipping */
if(val>32767)val=32767;
if(val<-32768)val=-32768;
if(val>32767){
val=32767;
clipflag=1;
}
if(val<-32768){
val=-32768;
clipflag=1;
}
*ptr=val;
ptr+=2;
}
}
if(clipflag)
fprintf(stderr,"Clipping in frame %ld\n",vd.sequence);
fwrite(convbuffer,2*vi.channels,out,stdout);
vorbis_synthesis_read(&vd,out); /* tell libvorbis how
......
......@@ -14,7 +14,7 @@
function: PCM data envelope analysis and manipulation
author: Monty <xiphmont@mit.edu>
modifications by: Monty
last modification date: Oct 06 1999
last modification date: Oct 17 1999
Vorbis manipulates the dynamic range of the incoming PCM data
envelope to minimise time-domain energy leakage from percussive and
......@@ -28,6 +28,7 @@
#include <math.h>
#include "codec.h"
#include "mdct.h"
#include "envelope.h"
#include "bitwise.h"
......@@ -98,26 +99,40 @@ static int _ve_envelope_generate(double *mult,double *env,double *look,
return(1);
}
/* right now, we do things simple and dirty (read: our current preecho
is a joke). Should this prove inadequate, then we'll think of
something different. The details of the encoding format do not
depend on the exact behavior, only the format of the bits that come
out.
Mark Taylor probably has much witter ways of doing this... Let's
see if simple delta analysis gives us acceptible results for now. */
/* use MDCT for spectral power estimation */
static void _ve_deltas(double *deltas,double *pcm,int n,double *win,
int winsize){
int i,j,p=winsize/2;
int i,j;
mdct_lookup m;
double out[winsize/2];
mdct_init(&m,winsize);
for(j=0;j<n;j++){
p-=winsize/2;
for(i=0;i<winsize-1;i++,p++){
double temp=fabs(win[i]*pcm[p]-win[i+1]*pcm[p+1]);
if(deltas[j]<temp)deltas[j]=temp;
}
p++;
double acc=0.;
mdct_forward(&m,pcm+j*winsize/2,out,win);
for(i=0;i<winsize/2;i++)
acc+=fabs(out[i]);
if(deltas[j]<acc)deltas[j]=acc;
}
mdct_clear(&m);
#ifdef ANALYSIS
{
static int frameno=0;
FILE *out;
char buffer[80];
sprintf(buffer,"delta%d.m",frameno++);
out=fopen(buffer,"w+");
for(j=0;j<n;j++)
fprintf(out,"%g\n",deltas[j]);
fclose(out);
}
#endif
}
void _ve_envelope_multipliers(vorbis_dsp_state *v){
......@@ -171,6 +186,21 @@ void _ve_envelope_sparsify(vorbis_block *vb){
double clamp;
int i;
#ifdef ANALYSIS
{
static int frameno=0.;
FILE *out;
int j;
char buffer[80];
sprintf(buffer,"del%d.m",frameno++);
out=fopen(buffer,"w+");
for(j=0;j<n;j++)
fprintf(out,"%g\n",mult[j]);
fclose(out);
}
#endif
/* are we going to multiply anything? */
for(i=1;i<n;i++){
......@@ -193,12 +223,11 @@ void _ve_envelope_sparsify(vorbis_block *vb){
for(i=0;i<begin;i++)mult[i]=0;
last=1;
for(;i<n;i++){
if(mult[i]/last>clamp*vi->preecho_thresh){
last=mult[i]/vi->preecho_clamp;
if(mult[i]>=last*vi->preecho_thresh){
last=mult[i];
mult[i]=floor(log(mult[i]/clamp/vi->preecho_clamp)/log(2))-1;
mult[i]=floor(log(mult[i]/clamp)/log(2));
if(mult[i]>15)mult[i]=15;
if(mult[i]<1)mult[i]=1;
......@@ -208,14 +237,32 @@ void _ve_envelope_sparsify(vorbis_block *vb){
}
}else
memset(mult,0,sizeof(double)*n);
#ifdef ANALYSIS
{
static int frameno=0.;
FILE *out;
int j;
char buffer[80];
sprintf(buffer,"sparse%d.m",frameno++);
out=fopen(buffer,"w+");
for(j=0;j<n;j++)
fprintf(out,"%g\n",mult[j]);
fclose(out);
}
#endif
}
}
void _ve_envelope_apply(vorbis_block *vb,int multp){
static int frameno=0;
vorbis_info *vi=vb->vd->vi;
double env[vb->multend*vi->envelopesa];
envelope_lookup *look=&vb->vd->ve;
int i,j;
int i,j,k;
for(i=0;i<vi->envelopech;i++){
double *mult=vb->mult[i];
......@@ -234,14 +281,49 @@ void _ve_envelope_apply(vorbis_block *vb,int multp){
/* compute the envelope curve */
if(_ve_envelope_generate(mult,env,look->window,vb->multend,
vi->envelopesa)){
if(multp)
#ifdef ANALYSIS
{
FILE *out;
char buffer[80];
sprintf(buffer,"env%d.m",frameno);
out=fopen(buffer,"w+");
for(j=0;j<vb->multend*vi->envelopesa;j++)
vb->pcm[i][j]*=env[j];
else
fprintf(out,"%g\n",env[j]);
fclose(out);
sprintf(buffer,"prepcm%d.m",frameno);
out=fopen(buffer,"w+");
for(j=0;j<vb->multend*vi->envelopesa;j++)
vb->pcm[i][j]/=env[j];
fprintf(out,"%g\n",vb->pcm[i][j]);
fclose(out);
}
#endif
for(k=0;k<vi->channels;k++){
if(multp)
for(j=0;j<vb->multend*vi->envelopesa;j++)
vb->pcm[k][j]*=env[j];
else
for(j=0;j<vb->multend*vi->envelopesa;j++)
vb->pcm[k][j]/=env[j];
}
#ifdef ANALYSIS
{
FILE *out;
char buffer[80];
sprintf(buffer,"pcm%d.m",frameno);
out=fopen(buffer,"w+");
for(j=0;j<vb->multend*vi->envelopesa;j++)
fprintf(out,"%g\n",vb->pcm[i][j]);
fclose(out);
}
#endif
}
frameno++;
}
}
......
......@@ -37,8 +37,9 @@ int vorbis_info_modeset(vorbis_info *vi, int mode){
/* handle the flat settings first */
memcpy(vi,&(predef_modes[mode]),sizeof(vorbis_info));
vi->threshhold_points=threshhold_points;
vi->user_comments=calloc(1,sizeof(char *));
vi->vendor=strdup("Xiphophorus libVorbis I 19991012");
vi->vendor=strdup("Xiphophorus libVorbis I 19991018");
return(0);
}
......
......@@ -67,7 +67,7 @@ double vorbis_gen_lpc(double *curve,double *lpc,lpc_lookup *l){
int n=l->ln;
int m=l->m;
double aut[m+1],work[n+n],error;
double fscale=1./n;
double fscale=.5/n;