Commit monty_branch_20000724 to the mainline in prep for beta 2
[platform/upstream/libvorbis.git] / lib / envelope.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-2000             *
9  * by Monty <monty@xiph.org> and The XIPHOPHORUS Company            *
10  * http://www.xiph.org/                                             *
11  *                                                                  *
12  ********************************************************************
13
14  function: PCM data envelope analysis and manipulation
15  last mod: $Id: envelope.c,v 1.21 2000/08/15 09:09:42 xiphmont Exp $
16
17  Preecho calculation.
18
19  ********************************************************************/
20
21 #include <stdlib.h>
22 #include <string.h>
23 #include <stdio.h>
24 #include <math.h>
25 #include "vorbis/codec.h"
26
27 #include "os.h"
28 #include "scales.h"
29 #include "envelope.h"
30 #include "bitwise.h"
31 #include "misc.h"
32
33 /* We use a Chebyshev bandbass for the preecho trigger bandpass; it's
34    close enough for sample rates 32000-48000 Hz (corner frequencies at
35    6k/14k assuming sample rate of 44.1kHz) */
36
37 /* Digital filter designed by mkfilter/mkshape/gencode A.J. Fisher
38    Command line: /www/usr/fisher/helpers/mkfilter -Ch \
39    -6.0000000000e+00 -Bp -o 5 -a 1.3605442177e-01 3.1746031746e-01 -l */
40
41 static int    cheb_bandpass_stages=10;
42 static double cheb_bandpass_gain=5.589612458e+01;
43 /* z^-stage, z^-stage+1... */
44 static double cheb_bandpass_B[]={-1.,0.,5.,0.,-10.,0.,10.,0.,-5.,0.,1};
45 static double cheb_bandpass_A[]={
46   -0.1917409386,
47   0.0078657069,
48   -0.7126903444,
49   0.0266343467,
50   -1.4047174730,
51   0.0466964232,
52   -1.9032773429,
53   0.0451493360,
54   -1.4471447397,
55   0.0303413711};
56
57 static int    cheb_highpass_stages=10;
58 static double cheb_highpass_gain= 5.291963434e+01;
59 /* z^-stage, z^-stage+1... */
60 static double cheb_highpass_B[]={1,-10,45,-120,210,-252,210,-120,45,-10,1};
61 static double cheb_highpass_A[]={
62   -0.1247628029,
63   0.1334086523,
64   -0.3997715614,
65   0.3213011089,
66   -1.1131924119,
67   1.7692446626,
68   -3.6241199038,
69   4.1950871291,
70   -4.2771757867,
71   2.3920318913};
72
73 void _ve_envelope_init(envelope_lookup *e,vorbis_info *vi){
74   long rate=vi->rate;
75   int ch=vi->channels;
76   int window=vi->envelopesa;
77   int i;
78   e->winlength=window;
79   e->minenergy=fromdB(vi->preecho_minenergy);
80   e->iir=calloc(ch,sizeof(IIR_state));
81   e->filtered=calloc(ch,sizeof(double *));
82   e->ch=ch;
83   e->storage=128;
84   for(i=0;i<ch;i++){
85     IIR_init(e->iir+i,cheb_highpass_stages,cheb_highpass_gain,
86              cheb_highpass_A,cheb_highpass_B);
87     e->filtered[i]=calloc(e->storage,sizeof(double));
88   }
89
90   drft_init(&e->drft,window);
91   e->window=malloc(e->winlength*sizeof(double));
92   /* We just use a straight sin(x) window for this */
93   for(i=0;i<e->winlength;i++)
94     e->window[i]=sin((i+.5)/e->winlength*M_PI);
95 }
96
97 void _ve_envelope_clear(envelope_lookup *e){
98   int i;
99   for(i=0;i<e->ch;i++){
100     IIR_clear((e->iir+i));
101     free(e->filtered[i]);
102   }
103   drft_clear(&e->drft);
104   free(e->window);
105   free(e->filtered);
106   memset(e,0,sizeof(envelope_lookup));
107 }
108
109 /*static int frameno=0;*/
110
111 static void smooth_noise(long n,double *f,double *noise){
112   long i;
113   long lo=0,hi=0;
114   double acc=0.;
115
116   for(i=0;i<n;i++){
117     long newhi=i*1.0442718740+5;
118     long newlo=i*.8781245150-5;
119     if(newhi>n)newhi=n;
120     
121     for(;lo<newlo;lo++)
122       acc-=f[lo]*f[lo];
123     for(;hi<newhi;hi++)
124       acc+=f[hi]*f[hi];
125     noise[i]=todB(sqrt(acc/(hi-lo)));
126   }
127 }
128
129 static double _ve_deltai(envelope_lookup *ve,IIR_state *iir,
130                       double *pre,double *post){
131   long no=ve->winlength/3; /* past the highpass rollon! */
132   long n2=ve->winlength*2;
133   long n=ve->winlength;
134
135   double *workA=alloca(sizeof(double)*n2),A=0.;
136   double *workB=alloca(sizeof(double)*n2),B=0.;
137   long i;
138
139   /*_analysis_output("A",frameno,pre,n,0,0);
140     _analysis_output("B",frameno,post,n,0,0);*/
141
142   for(i=0;i<n;i++){
143     workA[i]=pre[i]*ve->window[i];
144     workB[i]=post[i]*ve->window[i];
145   }
146
147   /*_analysis_output("Awin",frameno,workA,n,0,0);
148     _analysis_output("Bwin",frameno,workB,n,0,0);*/
149
150   drft_forward(&ve->drft,workA);
151   drft_forward(&ve->drft,workB);
152
153   /* we want to have a 'minimum bar' for energy, else we're just
154      basing blocks on quantization noise that outweighs the signal
155      itself (for low power signals) */
156   {
157     double min=ve->minenergy;
158     for(i=0;i<n;i++){
159       if(fabs(workA[i])<min)workA[i]=min;
160       if(fabs(workB[i])<min)workB[i]=min;
161     }
162   }
163
164   /*_analysis_output("Afft",frameno,workA,n,0,0);
165     _analysis_output("Bfft",frameno,workB,n,0,0);*/
166
167   for(i=0;i<n;i++){
168     A+=workA[i]*workA[i];
169     B+=workB[i]*workB[i];
170   }
171
172   A=todB(A);
173   B=todB(B);
174
175   return(B-A);
176 }
177
178 long _ve_envelope_search(vorbis_dsp_state *v,long searchpoint){
179   vorbis_info *vi=v->vi;
180   envelope_lookup *ve=v->ve;
181   long i,j;
182   
183   /* make sure we have enough storage to match the PCM */
184   if(v->pcm_storage>ve->storage){
185     ve->storage=v->pcm_storage;
186     for(i=0;i<ve->ch;i++)
187       ve->filtered[i]=realloc(ve->filtered[i],ve->storage*sizeof(double));
188   }
189
190   /* catch up the highpass to match the pcm */
191   for(i=0;i<ve->ch;i++){
192     double *filtered=ve->filtered[i];
193     double *pcm=v->pcm[i];
194     IIR_state *iir=ve->iir+i;
195     
196     for(j=ve->current;j<v->pcm_current;j++)
197       filtered[j]=IIR_filter(iir,pcm[j]);
198   }
199   ve->current=v->pcm_current;
200
201   /* Now search through our cached highpass data for breaking points */
202   /* starting point */
203   if(v->W)
204     j=v->centerW+vi->blocksizes[1]/4-vi->blocksizes[0]/4;
205   else
206     j=v->centerW;
207
208   while(j+ve->winlength<=v->pcm_current){
209     for(i=0;i<ve->ch;i++){
210       double *filtered=ve->filtered[i]+j;
211       IIR_state *iir=ve->iir+i;
212       double m=_ve_deltai(ve,iir,filtered-ve->winlength,filtered);
213       
214       if(m>vi->preecho_thresh){
215         /*frameno++;*/
216         return(0);
217       }
218       /*frameno++;*/
219     }
220     
221     j+=vi->blocksizes[0]/2;
222     if(j>=searchpoint)return(1);
223   }
224   
225   return(-1);
226 }
227
228 void _ve_envelope_shift(envelope_lookup *e,long shift){
229   int i;
230   for(i=0;i<e->ch;i++)
231     memmove(e->filtered[i],e->filtered[i]+shift,(e->current-shift)*
232             sizeof(double));
233   e->current-=shift;
234 }
235
236