Keeping up to date.
[platform/upstream/libvorbis.git] / lib / psy.c
1 /********************************************************************
2  *                                                                  *
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.                            *
7  *                                                                  *
8  * THE OggSQUISH SOURCE CODE IS (C) COPYRIGHT 1994-1999             *
9  * by 1999 Monty <monty@xiph.org> and The XIPHOPHORUS Company       *
10  * http://www.xiph.org/                                             *
11  *                                                                  *
12  ********************************************************************
13
14  function: random psychoacoustics (not including preecho)
15  author: Monty <xiphmont@mit.edu>
16  modifications by: Monty
17  last modification date: Aug 08 1999
18
19  ********************************************************************/
20
21 #include <math.h>
22 #include "codec.h"
23 #include "psy.h"
24
25 #define NOISEdB 6
26
27 #define MASKdB  12
28 #define HROLL   60
29 #define LROLL   90
30 #define MASKBIAS  40
31
32 #define LNOISE  .8
33 #define HNOISE  1.01
34 #define NOISEBIAS  20
35
36 /* Find the mean log energy of a given 'band'; used to evaluate tones
37    against background noise */
38
39 /* This is faster than a real convolution, gives us roughly the log f
40    scale we seek, and gives OK results.  So, that means it's a good
41    hack */
42
43 /* To add: f scale noise attenuation curve */
44
45 void _vp_noise_floor(double *f, double *m,int n){
46   long lo=0,hi=0;
47   double acc=0,div=0;
48   int i,j;
49
50   for(i=0;i<n;i++){
51     long newlo=i*LNOISE-NOISEBIAS;
52     long newhi=i*HNOISE+NOISEBIAS;
53     double temp;
54     
55     if(newhi>n)newhi=n;
56     if(newlo<0)newlo=0;
57
58     for(j=hi;j<newhi;j++){
59       acc+=todB(f[j]);
60       div++;
61     }
62     for(j=lo;j<newlo;j++){
63       acc-=todB(f[j]);
64       div--;
65     }
66
67     hi=newhi;
68     lo=newlo;
69
70     temp=fromdB(acc/div+NOISEdB); /* The NOISEdB constant should be an
71                                      attenuation curve */
72     if(m[i]<temp)m[i]=temp;
73   }
74 }
75
76 /* figure the masking curve.  linear rolloff on a dB scale, adjusted
77    by octave */
78 void _vp_mask_floor(double *f, double *m,int n){
79   double ocSCALE=1./log(2);
80   double curmask=-9.e40;
81   double curoc=log(MASKBIAS)*ocSCALE;
82   long i;
83
84   /* run mask forward then backward */
85   for(i=0;i<n;i++){
86     double newmask=todB(f[i])-MASKdB;
87     double newoc=log(i+MASKBIAS)*ocSCALE;
88     double roll=curmask-(newoc-curoc)*HROLL;
89     double lroll;
90     if(newmask>roll){
91       roll=curmask=newmask;
92       curoc=newoc;
93     }
94     lroll=fromdB(roll);
95     if(m[i]<lroll)m[i]=lroll;
96   }
97
98   curmask=-9.e40;
99   curoc=log(n+MASKBIAS)*ocSCALE;
100   for(i=n-1;i>=0;i--){
101     double newmask=todB(f[i])-MASKdB;
102     double newoc=log(i+MASKBIAS)*ocSCALE;
103     double roll=curmask-(curoc-newoc)*LROLL;
104     double lroll;
105     if(newmask>roll){
106       roll=curmask=newmask;
107       curoc=newoc;
108     }
109     lroll=fromdB(roll);
110     if(m[i]<lroll)m[i]=lroll;
111   }
112 }
113
114 void _vp_psy_quantize(double *f, double *m,int n){
115   int i;
116   for(i=0;i<n;i++){
117     int val=rint(f[i]/m[i]);
118     if(val>16)val=16;
119     if(val<-16)val=-16;
120     f[i]=val*m[i];
121   }
122 }
123
124 void _vp_psy_sparsify(double *f, double *m,int n){
125   int i;
126   for(i=0;i<n;i++)
127     if(fabs(f[i])<m[i])f[i]=0;
128 }
129
130 void  _vp_psy_make_lsp(vorbis_block *vb){
131
132
133
134
135 }
136