1 /********************************************************************
3 * THIS FILE IS PART OF THE Ogg Vorbis SOFTWARE CODEC SOURCE CODE. *
4 * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY *
5 * THE GNU PUBLIC LICENSE 2, WHICH IS INCLUDED WITH THIS SOURCE. *
6 * PLEASE READ THESE TERMS DISTRIBUTING. *
8 * THE OggSQUISH SOURCE CODE IS (C) COPYRIGHT 1994-2000 *
9 * by Monty <monty@xiph.org> and The XIPHOPHORUS Company *
10 * http://www.xiph.org/ *
12 ********************************************************************
14 function: random psychoacoustics (not including preecho)
15 last mod: $Id: psy.c,v 1.7 1999/12/30 07:26:47 xiphmont Exp $
17 ********************************************************************/
29 /* Set up decibel threshhold 'curves'. Actually, just set a level at
30 log frequency intervals, interpolate, and call it a curve. */
32 static void set_curve(double *points,
33 double *ref,int rn,double rrate,
34 double *c,int n, double crate){
38 int endpos=points[i+1]*n*rrate/crate;
40 double delta=(ref[i+1]-base)/(endpos-j);
41 for(;j<endpos && j<n;j++){
48 void _vp_psy_init(psy_lookup *p,vorbis_info *vi,int n){
49 memset(p,0,sizeof(psy_lookup));
50 p->noisethresh=malloc(n*sizeof(double));
51 p->maskthresh=malloc(n*sizeof(double));
55 /* set up the curves for a given blocksize and sample rate */
57 set_curve(vi->threshhold_points,
58 vi->noisethresh,THRESH_POINTS,48000,p->noisethresh,n,vi->rate);
59 set_curve(vi->threshhold_points,
60 vi->maskthresh, THRESH_POINTS,48000,p->maskthresh, n,vi->rate);
68 sprintf(buffer,"noise_threshhold_%d.m",n);
69 out=fopen(buffer,"w+");
71 fprintf(out,"%g\n",p->noisethresh[j]);
73 sprintf(buffer,"mask_threshhold_%d.m",n);
74 out=fopen(buffer,"w+");
76 fprintf(out,"%g\n",p->maskthresh[j]);
83 void _vp_psy_clear(psy_lookup *p){
85 if(p->noisethresh)free(p->noisethresh);
86 if(p->maskthresh)free(p->maskthresh);
87 memset(p,0,sizeof(psy_lookup));
91 /* Find the mean log energy of a given 'band'; used to evaluate tones
92 against background noise */
94 /* This is faster than a real convolution, gives us roughly the log f
95 scale we seek, and gives OK results. So, that means it's a good
98 void _vp_noise_floor(psy_lookup *p, double *f, double *m){
100 vorbis_info *vi=p->vi;
107 double bias=n*vi->noisebias;
110 long newlo=i*vi->lnoise-bias;
111 long newhi=i*vi->hnoise+bias;
117 for(j=hi;j<newhi;j++){
121 for(j=lo;j<newlo;j++){
129 /* attenuate by the noise threshhold curve */
130 temp=fromdB(acc/div+p->noisethresh[i]);
131 if(m[i]<temp)m[i]=temp;
135 /* Masking curve: linear rolloff on a dB scale, adjusted by octave,
136 attenuated by maskthresh */
138 void _vp_mask_floor(psy_lookup *p,double *f, double *m){
140 double hroll=p->vi->hroll;
141 double lroll=p->vi->lroll;
142 double ocSCALE=1./log(2);
143 double curmask=-9.e40;
144 double maskbias=n*p->vi->maskbias;
145 double curoc=log(maskbias)*ocSCALE;
148 /* run mask forward then backward */
150 double newmask=todB(f[i])+p->maskthresh[i];
151 double newoc=log(i+maskbias)*ocSCALE;
152 double roll=curmask-(newoc-curoc)*hroll;
155 roll=curmask=newmask;
159 if(m[i]<troll)m[i]=troll;
163 curoc=log(n+maskbias)*ocSCALE;
165 double newmask=todB(f[i])+p->maskthresh[i];
166 double newoc=log(i+maskbias)*ocSCALE;
167 double roll=curmask-(curoc-newoc)*lroll;
170 roll=curmask=newmask;
174 if(m[i]<troll)m[i]=troll;
178 /* s must be padded at the end with m-1 zeroes */
179 static void time_convolve(double *s,double *r,int n,int m){
187 acc+=s[i+j]*r[m-j-1];