From: Jean-Marc Valin Date: Wed, 8 Feb 2012 14:41:50 +0000 (-0500) Subject: Modifies the comparison tool to make it much more permissive. X-Git-Tag: v0.9.9~1 X-Git-Url: http://git.xiph.org/?p=opus.git;a=commitdiff_plain;h=c4ff3a0423060761d4587fef214fa231d252ed90 Modifies the comparison tool to make it much more permissive. --- diff --git a/src/opus_compare.c b/src/opus_compare.c index 31ebedc..a74acb0 100644 --- a/src/opus_compare.c +++ b/src/opus_compare.c @@ -5,13 +5,8 @@ #define OPUS_PI (3.14159265F) -#define OPUS_MIN(_x,_y) ((_x)<(_y)?(_x):(_y)) -#define OPUS_MAX(_x,_y) ((_x)>(_y)?(_x):(_y)) -#define OPUS_CLAMP(_a,_b,_c) OPUS_MAX(_a,OPUS_MIN(_b,_c)) #define OPUS_COSF(_x) ((float)cos(_x)) #define OPUS_SINF(_x) ((float)sin(_x)) -#define OPUS_SQRTF(_x) ((float)sqrt(_x)) -#define OPUS_LOG10F(_x) ((float)log10(_x)) static void *check_alloc(void *_ptr){ if(_ptr==NULL){ @@ -29,8 +24,7 @@ static void *opus_realloc(void *_ptr,size_t _size){ return check_alloc(realloc(_ptr,_size)); } -static size_t read_pcm16(float **_samples,FILE *_fin, - int _nchannels){ +static size_t read_pcm16(float **_samples,FILE *_fin,int _nchannels){ unsigned char buf[1024]; float *samples; size_t nsamples; @@ -60,47 +54,46 @@ static size_t read_pcm16(float **_samples,FILE *_fin, nsamples+=nread; } *_samples=(float *)opus_realloc(samples, - _nchannels*nsamples*sizeof(*samples)); + _nchannels*nsamples*sizeof(*samples)); return nsamples; } -static void band_energy(float *_out,const int *_bands,int _nbands, +static void band_energy(float *_out,float *_ps,const int *_bands,int _nbands, const float *_in,int _nchannels,size_t _nframes,int _window_sz, - int _step){ + int _step,int _downsample){ float *window; float *x; float *c; float *s; size_t xi; int xj; - window=(float *)opus_malloc((3+_nchannels)*_window_sz - *sizeof(*window)); + int ps_sz; + window=(float *)opus_malloc((3+_nchannels)*_window_sz*sizeof(*window)); c=window+_window_sz; s=c+_window_sz; x=s+_window_sz; + ps_sz=_window_sz/2; for(xj=0;xj<_window_sz;xj++){ window[xj]=0.5F-0.5F*OPUS_COSF((2*OPUS_PI/(_window_sz-1))*xj); } - for(xj=0;xj<_window_sz;xj++) - c[xj]=OPUS_COSF((2*OPUS_PI/_window_sz)*xj); - for(xj=0;xj<_window_sz;xj++) - s[xj]=OPUS_SINF((2*OPUS_PI/_window_sz)*xj); + for(xj=0;xj<_window_sz;xj++){ + c[xj]=OPUS_COSF((2*OPUS_PI/_window_sz)*xj); + } + for(xj=0;xj<_window_sz;xj++){ + s[xj]=OPUS_SINF((2*OPUS_PI/_window_sz)*xj); + } for(xi=0;xi<_nframes;xi++){ int ci; int xk; int bi; for(ci=0;ci<_nchannels;ci++){ for(xk=0;xk<_window_sz;xk++){ - x[ci*_window_sz+xk]=window[xk] - *_in[(xi*_step+xk)*_nchannels+ci]; + x[ci*_window_sz+xk]=window[xk]*_in[(xi*_step+xk)*_nchannels+ci]; } } for(bi=xj=0;bi<_nbands;bi++){ - float e2; - e2=0; + float p[2]={0}; for(;xj<_bands[bi+1];xj++){ - float p; - p=0; for(ci=0;ci<_nchannels;ci++){ float re; float im; @@ -113,26 +106,25 @@ static void band_energy(float *_out,const int *_bands,int _nbands, ti+=xj; if(ti>=_window_sz)ti-=_window_sz; } - p+=OPUS_SQRTF(re*re+im*im); + re*=_downsample; + im*=_downsample; + _ps[(xi*ps_sz+xj)*_nchannels+ci]=re*re+im*im+100000; + p[ci]+=_ps[(xi*ps_sz+xj)*_nchannels+ci]; + } + } + if(_out){ + _out[(xi*_nbands+bi)*_nchannels]=p[0]/(_bands[bi+1]-_bands[bi]); + if(_nchannels==2){ + _out[(xi*_nbands+bi)*_nchannels+1]=p[1]/(_bands[bi+1]-_bands[bi]); } - p*=(1.0F/_nchannels); - e2+=p*p; } - _out[xi*_nbands+bi]=e2/(_bands[bi+1]-_bands[bi])+1; } } free(window); } -static int cmp_float(const void *_a,const void *_b){ - float a; - float b; - a=*(const float *)_a; - b=*(const float *)_b; - return (a>b)-(a>1) int main(int _argc,const char **_argv){ - FILE *fin1; - FILE *fin2; - float *x; - float *y; - float *xb; - float *eb; - float *nmr; - float thresh; - float mismatch; - float err; - float nmr_sum; - size_t weight; - size_t xlength; - size_t ylength; - size_t nframes; - size_t xi; - int bi; - int nchannels; - if(_argc<3||_argc>4){ - fprintf(stderr,"Usage: %s [-s] \n", - _argv[0]); + FILE *fin1; + FILE *fin2; + float *x; + float *y; + float *xb; + float *X; + float *Y; + float err; + float Q; + size_t xlength; + size_t ylength; + size_t nframes; + size_t xi; + int ci; + int xj; + int bi; + int nchannels; + unsigned rate; + int downsample; + int ybands; + int yfreqs; + int max_compare; + if(_argc<3||_argc>6){ + fprintf(stderr,"Usage: %s [-s] [-r rate2] \n", + _argv[0]); return EXIT_FAILURE; } nchannels=1; - if(strcmp(_argv[1],"-s")==0)nchannels=2; - fin1=fopen(_argv[nchannels],"rb"); + if(strcmp(_argv[1],"-s")==0){ + nchannels=2; + _argv++; + } + rate=48000; + ybands=NBANDS; + yfreqs=NFREQS; + downsample=1; + if(strcmp(_argv[1],"-r")==0){ + rate=atoi(_argv[2]); + if(rate!=8000&&rate!=12000&&rate!=16000&&rate!=24000&&rate!=48000){ + fprintf(stderr, + "Sampling rate must be 8000, 12000, 16000, 24000, or 48000\n"); + return EXIT_FAILURE; + } + downsample=48000/rate; + switch(rate){ + case 8000:ybands=13;break; + case 12000:ybands=15;break; + case 16000:ybands=17;break; + case 24000:ybands=19;break; + } + yfreqs=NFREQS/downsample; + _argv+=2; + } + fin1=fopen(_argv[1],"rb"); if(fin1==NULL){ - fprintf(stderr,"Error opening '%s'.\n",_argv[nchannels]); + fprintf(stderr,"Error opening '%s'.\n",_argv[1]); return EXIT_FAILURE; } - fin2=fopen(_argv[nchannels+1],"rb"); + fin2=fopen(_argv[2],"rb"); if(fin2==NULL){ - fprintf(stderr,"Error opening '%s'.\n",_argv[nchannels+1]); + fprintf(stderr,"Error opening '%s'.\n",_argv[2]); fclose(fin1); return EXIT_FAILURE; } /*Read in the data and allocate scratch space.*/ - xlength=read_pcm16(&x,fin1,nchannels); + xlength=read_pcm16(&x,fin1,2); + if(nchannels==1){ + for(xi=0;xi0;) - xb[xi*NBANDS+bi]+=0.03F*xb[xi*NBANDS+bi+1]; + for(bi=NBANDS-1;bi-->0;){ + for(ci=0;ci0){ /*Temporal masking: 5 dB/5ms slope.*/ - for(bi=0;bithresh){ - mismatch+=NMR_THRESH[bi]/nmr[xi*NBANDS+bi]; - weight++; + float Ef; + Ef=0; + for(xj=0;xj=79&&xj<=81)im*=0.1F; + if(xj==80)im*=0.1F; + Ef+=im*im; } } + /*Using a fixed normalization value means we're willing to accept slightly + lower quality for lower sampling rates.*/ + Ef/=200*nchannels; + Ef*=Ef; + err+=Ef*Ef; } - free(nmr); - free(eb); - printf("Average pseudo-NMR: %3.2f dB\n",nmr_sum/(nframes*NBANDS)); - if(weight<=0){ - err=-100; - printf("Mismatch level: below noise floor\n"); + err=pow(err/nframes,1.0/16); + Q=100*(1-0.5*log(1+err)/log(1.13)); + if(Q<0){ + fprintf(stderr,"Test vector FAILS\n"); + fprintf(stderr,"Internal weighted error is %f\n",err); + return EXIT_FAILURE; } else{ - err=10*OPUS_LOG10F(mismatch/weight); - printf("Weighted mismatch: %3.2f dB\n",err); - } - printf("\n"); - if(err<0){ - printf("**Decoder PASSES test (mismatch < 0 dB)\n"); + fprintf(stderr,"Test vector PASSES\n"); + fprintf(stderr, + "Opus quality metric: %.1f %% (internal weighted error is %f)\n",Q,err); return EXIT_SUCCESS; } - printf("**Decoder FAILS test (mismatch >= 0 dB)\n"); - return EXIT_FAILURE; }