Memory leaks bad. Fixed memory leaks gooood.
[platform/upstream/libvorbis.git] / lib / envelope.c
1 /********************************************************************
2  *                                                                  *
3  * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
4  * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY *
5  * THE GNU LESSER/LIBRARY PUBLIC LICENSE, WHICH IS INCLUDED WITH    *
6  * THIS SOURCE. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.        *
7  *                                                                  *
8  * THE OggVorbis 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.27 2000/12/13 07:37:20 msmith 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 <ogg/ogg.h>
26 #include "vorbis/codec.h"
27 #include "codec_internal.h"
28
29 #include "os.h"
30 #include "scales.h"
31 #include "envelope.h"
32 #include "misc.h"
33
34 /* We use a Chebyshev bandbass for the preecho trigger bandpass; it's
35    close enough for sample rates 32000-48000 Hz (corner frequencies at
36    6k/14k assuming sample rate of 44.1kHz) */
37
38 /* Digital filter designed by mkfilter/mkshape/gencode A.J. Fisher
39    Command line: /www/usr/fisher/helpers/mkfilter -Ch \
40    -6.0000000000e+00 -Bp -o 5 -a 1.3605442177e-01 3.1746031746e-01 -l */
41
42 #if 0
43 static int    cheb_bandpass_stages=10;
44 static float cheb_bandpass_gain=5.589612458e+01;
45 static float cheb_bandpass_B[]={-1.,0.,5.,0.,-10.,0.,10.,0.,-5.,0.,1};
46 static float cheb_bandpass_A[]={
47   -0.1917409386,
48   0.0078657069,
49   -0.7126903444,
50   0.0266343467,
51   -1.4047174730,
52   0.0466964232,
53   -1.9032773429,
54   0.0451493360,
55   -1.4471447397,
56   0.0303413711};
57 #endif 
58
59 static int    cheb_highpass_stages=10;
60 static float cheb_highpass_gain= 5.291963434e+01;
61 /* z^-stage, z^-stage+1... */
62 static float cheb_highpass_B[]={1,-10,45,-120,210,-252,210,-120,45,-10,1};
63 static float cheb_highpass_A[]={
64   -0.1247628029,
65   0.1334086523,
66   -0.3997715614,
67   0.3213011089,
68   -1.1131924119,
69   1.7692446626,
70   -3.6241199038,
71   4.1950871291,
72   -4.2771757867,
73   2.3920318913};
74
75 void _ve_envelope_init(envelope_lookup *e,vorbis_info *vi){
76   codec_setup_info *ci=vi->codec_setup;
77   int ch=vi->channels;
78   int window=ci->envelopesa;
79   int i;
80   e->winlength=window;
81   e->minenergy=fromdB(ci->preecho_minenergy);
82   e->iir=_ogg_calloc(ch,sizeof(IIR_state));
83   e->filtered=_ogg_calloc(ch,sizeof(float *));
84   e->ch=ch;
85   e->storage=128;
86   for(i=0;i<ch;i++){
87     IIR_init(e->iir+i,cheb_highpass_stages,cheb_highpass_gain,
88              cheb_highpass_A,cheb_highpass_B);
89     e->filtered[i]=_ogg_calloc(e->storage,sizeof(float));
90   }
91
92   drft_init(&e->drft,window);
93   e->window=_ogg_malloc(e->winlength*sizeof(float));
94   /* We just use a straight sin(x) window for this */
95   for(i=0;i<e->winlength;i++)
96     e->window[i]=sin((i+.5)/e->winlength*M_PI);
97 }
98
99 void _ve_envelope_clear(envelope_lookup *e){
100   int i;
101   for(i=0;i<e->ch;i++){
102     IIR_clear((e->iir+i));
103     _ogg_free(e->filtered[i]);
104   }
105   drft_clear(&e->drft);
106   _ogg_free(e->window);
107   _ogg_free(e->filtered);
108   _ogg_free(e->iir);
109   memset(e,0,sizeof(envelope_lookup));
110 }
111
112 static float _ve_deltai(envelope_lookup *ve,IIR_state *iir,
113                       float *pre,float *post){
114   long n2=ve->winlength*2;
115   long n=ve->winlength;
116
117   float *workA=alloca(sizeof(float)*n2),A=0.;
118   float *workB=alloca(sizeof(float)*n2),B=0.;
119   long i;
120
121   /*_analysis_output("A",granulepos,pre,n,0,0);
122     _analysis_output("B",granulepos,post,n,0,0);*/
123
124   for(i=0;i<n;i++){
125     workA[i]=pre[i]*ve->window[i];
126     workB[i]=post[i]*ve->window[i];
127   }
128
129   /*_analysis_output("Awin",granulepos,workA,n,0,0);
130     _analysis_output("Bwin",granulepos,workB,n,0,0);*/
131
132   drft_forward(&ve->drft,workA);
133   drft_forward(&ve->drft,workB);
134
135   /* we want to have a 'minimum bar' for energy, else we're just
136      basing blocks on quantization noise that outweighs the signal
137      itself (for low power signals) */
138   {
139     float min=ve->minenergy;
140     for(i=0;i<n;i++){
141       if(fabs(workA[i])<min)workA[i]=min;
142       if(fabs(workB[i])<min)workB[i]=min;
143     }
144   }
145
146   /*_analysis_output("Afft",granulepos,workA,n,0,0);
147     _analysis_output("Bfft",granulepos,workB,n,0,0);*/
148
149   for(i=0;i<n;i++){
150     A+=workA[i]*workA[i];
151     B+=workB[i]*workB[i];
152   }
153
154   A=todB(A);
155   B=todB(B);
156
157   return(B-A);
158 }
159
160 long _ve_envelope_search(vorbis_dsp_state *v,long searchpoint){
161   vorbis_info *vi=v->vi;
162   codec_setup_info *ci=vi->codec_setup;
163   envelope_lookup *ve=((backend_lookup_state *)(v->backend_state))->ve;
164   long i,j;
165   
166   /* make sure we have enough storage to match the PCM */
167   if(v->pcm_storage>ve->storage){
168     ve->storage=v->pcm_storage;
169     for(i=0;i<ve->ch;i++)
170       ve->filtered[i]=_ogg_realloc(ve->filtered[i],ve->storage*sizeof(float));
171   }
172
173   /* catch up the highpass to match the pcm */
174   for(i=0;i<ve->ch;i++){
175     float *filtered=ve->filtered[i];
176     float *pcm=v->pcm[i];
177     IIR_state *iir=ve->iir+i;
178     int flag=1;
179     
180     for(j=ve->current;j<v->pcm_current;j++){
181       filtered[j]=IIR_filter(iir,pcm[j]);
182       if(pcm[j])flag=0;
183     }
184     if(flag && ve->current+64<v->pcm_current)IIR_reset(iir);
185   }
186
187   ve->current=v->pcm_current;
188
189   /* Now search through our cached highpass data for breaking points */
190   /* starting point */
191   if(v->W)
192     j=v->centerW+ci->blocksizes[1]/4-ci->blocksizes[0]/4;
193   else
194     j=v->centerW;
195
196   while(j+ve->winlength<=v->pcm_current){
197     for(i=0;i<ve->ch;i++){
198       float *filtered=ve->filtered[i]+j;
199       IIR_state *iir=ve->iir+i;
200       float m=_ve_deltai(ve,iir,filtered-ve->winlength,filtered);
201       
202       if(m>ci->preecho_thresh){
203         /*granulepos++;*/
204         return(0);
205       }
206       /*granulepos++;*/
207     }
208     
209     j+=ci->blocksizes[0]/2;
210     if(j>=searchpoint)return(1);
211   }
212   
213   return(-1);
214 }
215
216 void _ve_envelope_shift(envelope_lookup *e,long shift){
217   int i;
218   for(i=0;i<e->ch;i++)
219     memmove(e->filtered[i],e->filtered[i]+shift,(e->current-shift)*
220             sizeof(float));
221   e->current-=shift;
222 }
223
224