diff options
author | Monty <xiphmont@xiph.org> | 2000-03-29 03:49:29 +0000 |
---|---|---|
committer | Monty <xiphmont@xiph.org> | 2000-03-29 03:49:29 +0000 |
commit | 9bb072dc5a541ffb4f724b9d215ba67fef01af0d (patch) | |
tree | 248dab6beb8044b0b09b0852cf1521b70b252db9 | |
parent | c210a7decc824c3f11256d78da06c7a62326bda0 (diff) | |
download | libvorbis-git-9bb072dc5a541ffb4f724b9d215ba67fef01af0d.tar.gz |
Don't want to lose anything while I'm integrating (also don;t want to
disturb mainline till I'm done)
Monty
svn path=/branches/unlabeled-1.1.2/vorbis/; revision=286
-rw-r--r-- | lib/masking.h | 149 | ||||
-rw-r--r-- | lib/psytune.c | 360 | ||||
-rw-r--r-- | lib/scales.h | 54 |
3 files changed, 563 insertions, 0 deletions
diff --git a/lib/masking.h b/lib/masking.h new file mode 100644 index 00000000..18aeac47 --- /dev/null +++ b/lib/masking.h @@ -0,0 +1,149 @@ +/******************************************************************** + * * + * 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-2000 * + * by Monty <monty@xiph.org> and The XIPHOPHORUS Company * + * http://www.xiph.org/ * + * * + ******************************************************************** + + function: masking curve data for psychoacoustics + last mod: $Id: masking.h,v 1.1.2.1 2000/03/29 03:49:28 xiphmont Exp $ + + ********************************************************************/ + +#ifndef _V_MASKING_H_ +#define _V_MASKING_H_ + +double ATH_Bark_dB[]={ + 70, 25, 15, 11, 9, 8, 7.5, 7, 7, 7, + 6, 4, 2, 0, -3, -5, -6, -6, -4.5, 2.5, + 11, 18, 21, 17, 25, 80, 120}; + +/* The below masking curves are straight from the R. Ehmer + (J. Acoustical Society of America) papers ca 1958-59. I modified + them slightly as Ehmer does not correct for the Absolute Threshold + of Hearing, and the low dB portions of the curves are thus highly + suspect. */ + +/* Let's all do the Trek thing and just call them 'Ehmer curves' ;-) + Note these are octaves, not Bark scale. */ + +#define EHMER_OFFSET 16 +#define EHMER_MAX 56 + +double tone_250_40dB_SL[EHMER_MAX]={ +-900,-900,-900,-900,-900,-900,-900,-900, -19, -13, -7, -1, 4, 9, 15, 20, + 22, 23, 22, 19, 18, 18, 16, 13, 9, 7, 3, 1, -1, -3, -6, -8, + -10, -13, -16, -19, -21, -24, -28, -32, -900,-900,-900,-900,-900,-900,-900,-900, +-900,-900,-900,-900,-900,-900,-900,-900}; +double tone_250_60dB_SL[EHMER_MAX]={ +-900,-900,-900,-900,-900,-900,-900,-900, -5, 1, 7, 13, 19, 25, 30, 33, + 36, 39, 38, 37, 38, 39, 39, 40, 38, 36, 35, 34, 33, 31, 29, 28, + 28, 28, 25, 20, 14, 10, 5, 0, -5,-10,-15,-20,-25,-30,-35,-40, +-900,-900,-900,-900,-900,-900,-900,-900}; +double tone_250_80dB_SL[EHMER_MAX]={ +-900,-900,-900,-900,-900,-900,-900,-900, 10, 17, 24, 30, 37, 41, 48, 49, + 60, 58, 54, 53, 53, 54, 55, 57, 57, 57, 58, 59, 60, 58, 57, 58, + 59, 58, 57, 54, 52, 50, 49, 47, 46, 47, 46, 44, 43, 42, 41, 40, + 38, 32, 27, 22, 17, 11, 6, 0}; + +double tone_500_40dB_SL[EHMER_MAX]={ +-900,-900,-900,-900,-900,-900,-900,-900, -26, -20, -14, -8, -2, 4, 10, 17, + 23, 16, 12, 9, 6, 3, 0, -3, -7, -10, -13, -16, -20, -23, -26, -30, +-900,-900,-900,-900,-900,-900,-900,-900, -900,-900,-900,-900,-900,-900,-900,-900, +-900,-900,-900,-900,-900,-900,-900,-900}; +double tone_500_60dB_SL[EHMER_MAX]={ +-900,-900,-900,-900,-900,-900,-900,-900, -18, -12, -6, 0, 6, 13, 20, 30, + 39, 34, 31, 29, 29, 27, 24, 21, 18, 16, 13, 8, 6, 3, 1, -1, + -5, -2, -5, -8, -12, -15, -18, -22, -900,-900,-900,-900,-900,-900,-900,-900, +-900,-900,-900,-900,-900,-900,-900,-900}; +double tone_500_80dB_SL[EHMER_MAX]={ +-900,-900,-900,-900,-900,-900,-900,-900, -22,-16,-10, 0, 10, 20, 32, 43, + 60, 55, 52, 50, 49, 50, 52, 55, 55, 54, 51, 49, 46, 44, 44, 42, + 38, 34, 32, 29, 29, 28, 25, 23, 20, 16, 10, 7, 4, 2, -1, -4, + -7, -10, -15, -20, -25, -30, -35, -40}; +double tone_500_100dB_SL[EHMER_MAX]={ +-900,-900,-900,-900,-900,-900,-900,-900, -7, 2, 10, 19, 27, 35, 55, 56, + 80, 70, 60, 58, 57, 57, 59, 63, 65, 66, 62, 60, 57, 57, 58, 58, + 57, 56, 56, 56, 57, 57, 56, 57, 57, 54, 47, 41, 37, 28, 21, 16, + 10, 3, -3, -8, -13, -18, -23, -28}; + +double tone_1000_40dB_SL[EHMER_MAX]={ +-900,-900,-900,-900,-900,-900,-900,-900, -55, -45, -35, -25, -15, -5, 5, 15, + 25, 20, 13, 8, 3, -3, -9, -15, -900,-900,-900,-900,-900,-900,-900,-900, +-900,-900,-900,-900,-900,-900,-900,-900, -900,-900,-900,-900,-900,-900,-900,-900, +-900,-900,-900,-900,-900,-900,-900,-900}; +double tone_1000_60dB_SL[EHMER_MAX]={ +-900,-900,-900,-900,-900,-900,-900,-900, -40,-30,-20,-10, 0, 10, 20, 30, + 40, 33, 24, 23, 21, 17, 13, 8, 3, -2, -8,-13,-18, -23, -28, -33, +-900,-900,-900,-900,-900,-900,-900,-900, -900,-900,-900,-900,-900,-900,-900,-900, +-900,-900,-900,-900,-900,-900,-900,-900}; +double tone_1000_80dB_SL[EHMER_MAX]={ +-900,-900,-900,-900,-900,-900,-900,-900, -40,-30,-20,-10, 0, 10, 24, 42, + 60, 57, 46, 41, 39, 37, 41, 46, 45, 41, 39, 35, 35, 34, 33, 31, + 28, 22, 15, 10, 5, -2, -10, -18, -900,-900,-900,-900,-900,-900,-900,-900, +-900,-900,-900,-900,-900,-900,-900,-900}; +double tone_1000_100dB_SL[EHMER_MAX]={ +-900,-900,-900,-900,-900,-900,-900,-900, -34,-24,-14, -4, 6, 16, 33, 53, + 80, 72, 55, 49, 43, 40, 44, 54, 59, 58, 49, 43, 52, 57, 57, 58, + 58, 54, 49, 47, 42, 39, 33, 28, 20, 15, 5, 0, -5,-15,-20,-25, +-900,-900,-900,-900,-900,-900,-900,-900}; + +double tone_2000_40dB_SL[EHMER_MAX]={ +-900,-900,-900,-900,-900,-900,-900,-900, -40, -30, -21, -12, -3, 5, 12, 20, + 25, 21, 15, 5, -5, -15, -25, -35, -900,-900,-900,-900,-900,-900,-900,-900, +-900,-900,-900,-900,-900,-900,-900,-900, -900,-900,-900,-900,-900,-900,-900,-900, +-900,-900,-900,-900,-900,-900,-900,-900}; +double tone_2000_60dB_SL[EHMER_MAX]={ +-900,-900,-900,-900,-900,-900,-900,-900, -40, -30, -21, -12, -2, 8, 19, 32, + 40, 35, 25, 17, 14, 13, 11, 7, 3, -2, -6, -10, -14, -20, -26, -32, +-900,-900,-900,-900,-900,-900,-900,-900, -900,-900,-900,-900,-900,-900,-900,-900, +-900,-900,-900,-900,-900,-900,-900,-900}; +double tone_2000_80dB_SL[EHMER_MAX]={ +-900,-900,-900,-900,-900,-900,-900,-900, -40, -30, -21, -12, -2, 13, 28, 41, + 60, 55, 43, 35, 28, 29, 35, 37, 37, 35, 31, 28, 25, 22, 19, 15, + 11, 8, 6, 2, -6, -14, -22, -30, -900,-900,-900,-900,-900,-900,-900,-900, +-900,-900,-900,-900,-900,-900,-900,-900}; +double tone_2000_100dB_SL[EHMER_MAX]={ +-900,-900,-900,-900,-900,-900,-900,-900, -40, -30, -21, -10, 6, 25, 42, 60, + 80, 68, 53, 43, 35, 31, 34, 47, 58, 51, 43, 45, 54, 59, 59, 56, + 54, 51, 40, 29, 20, 11, 2, -8, -17, -26, -35,-900,-900,-900,-900,-900, +-900,-900,-900,-900,-900,-900,-900,-900}; + +double tone_4000_40dB_SL[EHMER_MAX]={ +-900,-900,-900,-900,-900,-900,-900,-900, -70, -56, -43, -30, -17, -5, 7, 15, + 21, 13, 5, -2, -10, -17, -24, -31, -900,-900,-900,-900,-900,-900,-900,-900, +-900,-900,-900,-900,-900,-900,-900,-900, -900,-900,-900,-900,-900,-900,-900,-900, +-900,-900,-900,-900,-900,-900,-900,-900}; +double tone_4000_60dB_SL[EHMER_MAX]={ +-900,-900,-900,-900,-900,-900,-900,-900, -70, -56, -43, -30, -17, -5, 10, 27, + 40, 33, 20, 16, 10, 5, -5, -15, -20, -25, -30, -35, -40,-900,-900,-900, +-900,-900,-900,-900,-900,-900,-900,-900, -900,-900,-900,-900,-900,-900,-900,-900, +-900,-900,-900,-900,-900,-900,-900,-900}; +double tone_4000_80dB_SL[EHMER_MAX]={ +-900,-900,-900,-900,-900,-900,-900,-900, -60, -50, -40, -29, -12, 5, 19, 37, + 60, 53, 35, 33, 36, 36, 36, 31, 27, 17, 8, 0, -8, -16, -24, -32, +-900,-900,-900,-900,-900,-900,-900,-900, -900,-900,-900,-900,-900,-900,-900,-900, +-900,-900,-900,-900,-900,-900,-900,-900}; +double tone_4000_100dB_SL[EHMER_MAX]={ + -20, -12, -8, -4, 0, 4, 8, 11, 15, 22, 26, 28, 32, 36, 43, 54, + 80, 70, 45, 41, 48, 49, 40, 26, 40, 40, 33, 29, 24, 19, 14, 9, + 4, -1, -6, -11, -16, -21, -26, -31, -900,-900,-900,-900,-900,-900,-900,-900, +-900,-900,-900,-900,-900,-900,-900,-900}; + +double tone_8000_100dB_SL[EHMER_MAX]={ + -18, -12, -7, -3, 0, 2, 6, 9, 12, 19, 22, 21, 19, 21, 40, 40, + 80, 60, + /* educated guessing from here on out */ + 35, 31, 38, 39, 30, 16, 30, 30, 23, 19, 14, 9, 4, -1, + -6, -11, -16, -21, -26, -31, -36, -41, -900,-900,-900,-900,-900,-900,-900,-900, +-900,-900,-900,-900,-900,-900,-900,-900}; + +#endif + + diff --git a/lib/psytune.c b/lib/psytune.c new file mode 100644 index 00000000..95b8815e --- /dev/null +++ b/lib/psytune.c @@ -0,0 +1,360 @@ +/******************************************************************** + * * + * 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-2000 * + * by Monty <monty@xiph.org> and The XIPHOPHORUS Company * + * http://www.xiph.org/ * + * * + ******************************************************************** + + function: simple utility that runs audio through the psychoacoustics + without encoding + last mod: $Id: psytune.c,v 1.1.2.1 2000/03/29 03:49:28 xiphmont Exp $ + + ********************************************************************/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> + +#include "vorbis/codec.h" +#include "psy.h" +#include "mdct.h" +#include "window.h" +#include "scales.h" +#include "lpc.h" + +/* + 0 1 2 3 4 5 6 7 8 9 + 0, 100, 200, 300, 400, 510, 630, 770, 920, 1080, + + 10 11 12 13 14 15 16 17 18 19 + 1270, 1480, 1720, 2000, 2320, 2700, 3150, 3700, 4400, 5300, + + 20 21 22 23 24 25 26 Bark + 6400, 7700, 9500, 12000, 15500, 20500, 27000 Hz */ + +static vorbis_info_psy _psy_set0={ + /* ATH */ + { 70, 25, 15, 11, 9, 8, 7.5, 7, 7, 7, + 6, 4, 2, 0, -3, -5, -6, -6,-4.5, 2.5, + 11, 18, 21, 17, 25, 80,120}, + /* master attenuation */ + 120., + + /* mask1 attenuation proportion */ + { .7, .75, .80, .83, .84, .85, .85, .85, .85, .85, + .00, .00, .00, .00, .00, .00, .00, .00, .00, .00, + /* .85, .85, .85, .85, .00, .00, .00, .00, .00, .00,*/ + .00, .00, .00, .00, .00, .00, .00}, + /* mask1 slope */ + {-40, -24, -12, -8., -4., -4, -4, -4, -4, -4, + -99, -99, -99, -99, -99,-99,-99,-99,-99,-99, + -99,-99,-99,-99,-99,-99,-99}, + + /* mask2 attenuation proportion */ + { .60, .60, .60, .60, .55, .55, .50, .50, .50, .50, + .50, .50, .50, .50, .50, .50, .50, .50, .50, .55, + .60, .65, .66, .67, .68, .7, .7}, + /* mask2 slope */ + {-40.,-24.,-11., -8., -6., -5.,-3.,-1.8, -1.8,-1.8, + -1.8,-1.8,-1.9,-1.9,-2, -2, -2, -2,-2,-1.8, + -1.7,-1.7,-1.6,-1.6,-1.6,-1.6,-1.6}, + + -33., /* backward masking rolloff */ + + .9998, .9997 /* attack/decay control */ +}; + +static int noisy=0; +void analysis(char *base,int i,double *v,int n,int bark,int dB){ + if(noisy){ + int j; + FILE *of; + char buffer[80]; + sprintf(buffer,"%s_%d.m",base,i); + of=fopen(buffer,"w"); + + for(j=0;j<n;j++){ + if(dB && v[j]==0) + fprintf(of,"\n\n"); + else{ + if(bark) + fprintf(of,"%g ",toBARK(22050.*j/n)); + else + fprintf(of,"%g ",(double)j); + + if(dB){ + fprintf(of,"%g\n",todB(fabs(v[j]))); + }else{ + fprintf(of,"%g\n",v[j]); + } + } + } + fclose(of); + } +} + +long frameno=0; + +int main(int argc,char *argv[]){ + int eos=0; + double nonz=0.; + double acc=0.; + double tot=0.; + + int framesize=2048; + int order=32; + + double *pcm[2],*out[2],*window,*mask,*maskwindow,*decay[2],*lpc,*floor; + signed char *buffer,*buffer2; + mdct_lookup m_look; + vorbis_look_psy p_look; + long i,j,k; + + drft_lookup fft_look; + lpc_lookup lpc_look; + + int ath=0; + int mask1p=0; + int mask2p=0; + int mask3p=0; + int backp=0; + int decayp=0; + + argv++; + while(*argv){ + if(*argv[0]=='-'){ + /* option */ + if(argv[0][1]=='v'){ + noisy=0; + } + if(argv[0][1]=='A'){ + ath=0; + } + if(argv[0][1]=='1'){ + mask1p=0; + } + if(argv[0][1]=='2'){ + mask2p=0; + } + if(argv[0][1]=='3'){ + mask3p=0; + } + if(argv[0][1]=='B'){ + backp=0; + } + if(argv[0][1]=='D'){ + decayp=0; + } + if(argv[0][1]=='X'){ + ath=0; + mask1p=0; + mask2p=0; + mask3p=0; + decayp=0; + backp=0; + } + }else + if(*argv[0]=='+'){ + /* option */ + if(argv[0][1]=='v'){ + noisy=1; + } + if(argv[0][1]=='A'){ + ath=1; + } + if(argv[0][1]=='1'){ + mask1p=1; + } + if(argv[0][1]=='2'){ + mask2p=1; + } + if(argv[0][1]=='3'){ + mask3p=1; + } + if(argv[0][1]=='B'){ + backp=1; + } + if(argv[0][1]=='D'){ + decayp=1; + } + if(argv[0][1]=='X'){ + ath=1; + mask1p=1; + mask2p=1; + mask3p=1; + decayp=1; + backp=1; + } + }else + framesize=atoi(argv[0]); + argv++; + } + + pcm[0]=malloc(framesize*sizeof(double)); + pcm[1]=malloc(framesize*sizeof(double)); + out[0]=calloc(framesize/2,sizeof(double)); + out[1]=calloc(framesize/2,sizeof(double)); + decay[0]=calloc(framesize/2,sizeof(double)); + decay[1]=calloc(framesize/2,sizeof(double)); + mask=malloc(framesize*sizeof(double)); + floor=malloc(framesize*sizeof(double)); + lpc=malloc(order*sizeof(double)); + buffer=malloc(framesize*4); + buffer2=buffer+framesize*2; + window=_vorbis_window(0,framesize,framesize/2,framesize/2); + maskwindow=_vorbis_window(0,framesize,framesize/2,framesize/2); + mdct_init(&m_look,framesize); + _vp_psy_init(&p_look,&_psy_set0,framesize/2,44100); + lpc_init(&lpc_look,framesize/2,256,44100,order); + + for(j=0;j<framesize;j++) + maskwindow[j]*=maskwindow[j]; + + /* we cheat on the WAV header; we just bypass 44 bytes and never + verify that it matches 16bit/stereo/44.1kHz. */ + + fread(buffer,1,44,stdin); + fwrite(buffer,1,44,stdout); + memset(buffer,0,framesize*2); + + analysis("window",0,window,framesize,0,0); + + fprintf(stderr,"Processing for frame size %d...\n",framesize); + + while(!eos){ + long s; + long bytes=fread(buffer2,1,framesize*2,stdin); + if(bytes<framesize*2) + memset(buffer2+bytes,0,framesize*2-bytes); + + if(bytes!=0){ + + /* uninterleave samples */ + for(i=0;i<framesize;i++){ + pcm[0][i]=((buffer[i*4+1]<<8)| + (0x00ff&(int)buffer[i*4]))/32768.; + pcm[1][i]=((buffer[i*4+3]<<8)| + (0x00ff&(int)buffer[i*4+2]))/32768.; + } + + for(i=0;i<2;i++){ + + analysis("pre",frameno,pcm[i],framesize,0,0); + + /* do the psychacoustics */ + memset(mask,0,sizeof(double)*framesize/2); + for(j=0;j<framesize;j++) + mask[j]=pcm[i][j]*maskwindow[j]; + + mdct_forward(&m_look,mask,mask); + + analysis("maskmdct",frameno,mask,framesize/2,1,1); + _vp_tone_tone_mask(&p_look,mask,mask, + 1,1,decayp,decay[i]); + analysis("mask",frameno,mask,framesize/2,1,0); + analysis("lmask",frameno,mask,framesize/2,0,0); + analysis("decay",frameno,decay[i],framesize/2,1,1); + analysis("ldecay",frameno,decay[i],framesize/2,0,1); + + for(j=0;j<framesize;j++) + pcm[i][j]=pcm[i][j]*window[j]; + analysis("pcm",frameno,pcm[i],framesize,0,0); + + mdct_forward(&m_look,pcm[i],pcm[i]); + analysis("mdct",frameno,pcm[i],framesize/2,1,1); + analysis("lmdct",frameno,pcm[i],framesize/2,0,1); + + /* floor */ + { + double amp; + + for(j=0;j<framesize/2;j++)floor[j]=mask[j]+DYNAMIC_RANGE_dB; + amp=sqrt(vorbis_curve_to_lpc(floor,lpc,&lpc_look)); + fprintf(stderr,"amp=%g\n",amp); + vorbis_lpc_to_curve(floor,lpc,amp,&lpc_look); + for(j=0;j<framesize/2;j++)floor[j]-=DYNAMIC_RANGE_dB; + analysis("floor",frameno,floor,framesize/2,1,0); + + } + + + /* quantize according to masking */ + for(j=0;j<framesize/2;j++){ + double val; + if(mask[j]==0) + val=0; + else{ + val=todB(pcm[i][j])-floor[j]-3.; + if(val<-6.){ + val=0; + }else{ + nonz+=1; + if(val<1.5){ + val=1; + }else{ + val=rint(val/3.)+1; + } + } + if(pcm[i][j]<0)val= -val; + } + + acc+=log(fabs(val)*2.+1.)/log(2); + tot++; + if(val==0) + pcm[i][j]=0.; + else{ + if(val>0) + pcm[i][j]=fromdB(val*3.+floor[j]-3.); + else + pcm[i][j]=-fromdB(floor[j]-val*3.-3.); + } + } + + analysis("final",frameno,pcm[i],framesize/2,1,1); + + /* take it back to time */ + mdct_backward(&m_look,pcm[i],pcm[i]); + for(j=0;j<framesize/2;j++) + out[i][j]+=pcm[i][j]*window[j]; + + frameno++; + } + + /* write data. Use the part of buffer we're about to shift out */ + for(i=0;i<2;i++){ + char *ptr=buffer+i*2; + double *mono=out[i]; + for(j=0;j<framesize/2;j++){ + int val=mono[j]*32767.; + /* might as well guard against clipping */ + if(val>32767)val=32767; + if(val<-32768)val=-32768; + ptr[0]=val&0xff; + ptr[1]=(val>>8)&0xff; + ptr+=4; + } + } + + fwrite(buffer,1,framesize*2,stdout); + memmove(buffer,buffer2,framesize*2); + + for(i=0;i<2;i++){ + for(j=0,k=framesize/2;j<framesize/2;j++,k++) + out[i][j]=pcm[i][k]*window[k]; + } + }else + eos=1; + } + fprintf(stderr,"average raw bits of entropy: %.03g/sample\n",acc/tot); + fprintf(stderr,"average nonzero samples: %.03g/%d\n",nonz/tot*framesize/2, + framesize/2); + fprintf(stderr,"Done\n\n"); + return 0; +} diff --git a/lib/scales.h b/lib/scales.h new file mode 100644 index 00000000..39e7f6ab --- /dev/null +++ b/lib/scales.h @@ -0,0 +1,54 @@ +/******************************************************************** + * * + * 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-2000 * + * by Monty <monty@xiph.org> and The XIPHOPHORUS Company * + * http://www.xiph.org/ * + * * + ******************************************************************** + + function: linear scale -> dB, Bark and Mel scales + last mod: $Id: scales.h,v 1.1.2.1 2000/03/29 03:49:29 xiphmont Exp $ + + ********************************************************************/ + +#ifndef _V_SCALE_H_ +#define _V_SCALES_H_ + +#include <math.h> + +#define min(x,y) ((x)>(y)?(y):(x)) +#define max(x,y) ((x)<(y)?(y):(x)) + +/* 20log10(x) */ +#define DYNAMIC_RANGE_dB 200. +#define todB(x) ((x)==0?-9.e40:log(fabs(x))*8.6858896) +#define fromdB(x) (exp((x)*.11512925)) + + +/* The bark scale equations are approximations, since the original + table was somewhat hand rolled. The below are chosen to have the + best possible fit to the rolled tables, thus their somewhat odd + appearance (these are more accurate and over a longer range than + the oft-quoted bark equations found in the texts I have). The + approximations are valid from 0 - 30kHz (nyquist) or so. + + all f in Hz, z in Bark */ + +#define toBARK(f) (13.1*atan(.00074*(f))+2.24*atan((f)*(f)*1.85e-8)+1e-4*(f)) +#define fromBARK(z) (102.*(z)-2.*pow(z,2.)+.4*pow(z,3)+pow(1.46,z)-1.) +#define toMEL(f) (log(1.+(f)*.001)*1442.695) +#define fromMEL(m) (1000.*exp((m)/1442.695)-1000.) + +/* Frequency to octave. We arbitrarily declare 250.0 Hz to be octave + 0.0 */ + +#define toOC(f) (log(f)*1.442695-7.965784) +#define fromOC(o) (exp(((o)+7.965784)*.693147)) + +#endif + |