Bringing rc2 (minus the modes it needs) onto mainline.
[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 LIBRARY SOURCE IS     *
5  * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
6  * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
7  *                                                                  *
8  * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2001             *
9  * by the XIPHOPHORUS Company http://www.xiph.org/                  *
10
11  ********************************************************************
12
13  function: PCM data envelope analysis and manipulation
14  last mod: $Id: envelope.c,v 1.37 2001/08/13 01:36:56 xiphmont Exp $
15
16  Preecho calculation.
17
18  ********************************************************************/
19
20 #include <stdlib.h>
21 #include <string.h>
22 #include <stdio.h>
23 #include <math.h>
24 #include <ogg/ogg.h>
25 #include "vorbis/codec.h"
26 #include "codec_internal.h"
27
28 #include "os.h"
29 #include "scales.h"
30 #include "envelope.h"
31 #include "misc.h"
32 #include "iir.c" /* Yes, ugly, but needed for inlining */
33
34 /* Digital filter designed by mkfilter/mkshape/gencode A.J. Fisher */
35
36 static int   cheb_highpass_stages=6;
37 static float cheb_highpass_B[]={1.f,-6.f,15.f,-20.f,15.f,-6.f,1.f};
38
39 static int   cheb_bandpass_stages=6;
40 static float cheb_bandpass_B[]={-1.f,0.f,3.f,0.f,-3.f,0.f,1.f};
41
42
43 /* 10kHz Chebyshev highpass */
44 static float cheb_highpass10k_gain= 54.34519586f;
45 static float cheb_highpass10k_A[]={
46   -0.2064797169f,
47   -0.5609713214f,
48   -1.1352465327f,
49   -1.4495555418f,
50   -1.7938140760f,
51   -0.9473564683f};
52
53 /* 6kHz-10kHz Chebyshev bandpass */
54 static float cheb_bandpass6k_gain=113.4643935f;
55 static float cheb_bandpass6k_A[]={
56   -0.5712621337f,
57   1.5626130710f,
58   -3.3348854983f,
59   4.0471340821f,
60   -4.0051680331f,
61   2.2786325610f};
62
63 /* 3kHz-6kHz Chebyshev bandpass */
64 static float cheb_bandpass3k_gain= 248.8359377f;
65 static float cheb_bandpass3k_A[]={
66   -0.6564230022f,
67   3.3747911257f,
68   -8.0098635981f,
69   11.0040876874f,
70   -9.2250963484f,
71   4.4760355389f};
72
73 /* 1.5kHz-3kHz Chebyshev bandpass */
74 static float cheb_bandpass1k_gain= 1798.537183f;
75 static float cheb_bandpass1k_A[]={
76   -0.8097527363f,
77   4.7725742682f,
78   -11.9800219408f,
79   16.3770336223f,
80   -12.8553129536f,
81   5.4948074309f};
82
83 void _ve_envelope_init(envelope_lookup *e,vorbis_info *vi){
84   codec_setup_info *ci=vi->codec_setup;
85   vorbis_info_psy_global *gi=ci->psy_g_param;
86   int ch=vi->channels;
87   int window=gi->envelopesa;
88   int i;
89   e->winlength=window;
90   e->minenergy=fromdB(gi->preecho_minenergy);
91   e->iir=_ogg_calloc(ch*4,sizeof(IIR_state));
92   e->filtered=_ogg_calloc(ch*4,sizeof(float *));
93   e->ch=ch;
94   e->storage=128;
95   for(i=0;i<ch*4;i+=4){
96
97     IIR_init(e->iir+i,cheb_highpass_stages,cheb_highpass10k_gain,
98              cheb_highpass10k_A,cheb_highpass_B);
99     IIR_init(e->iir+i+1,cheb_bandpass_stages,cheb_bandpass6k_gain,
100              cheb_bandpass6k_A,cheb_bandpass_B);
101     IIR_init(e->iir+i+2,cheb_bandpass_stages,cheb_bandpass3k_gain,
102              cheb_bandpass3k_A,cheb_bandpass_B);
103     IIR_init(e->iir+i+3,cheb_bandpass_stages,cheb_bandpass1k_gain,
104              cheb_bandpass1k_A,cheb_bandpass_B);
105
106     e->filtered[i]=_ogg_calloc(e->storage,sizeof(float));
107     e->filtered[i+1]=_ogg_calloc(e->storage,sizeof(float));
108     e->filtered[i+2]=_ogg_calloc(e->storage,sizeof(float));
109     e->filtered[i+3]=_ogg_calloc(e->storage,sizeof(float));
110   }
111
112 }
113
114 void _ve_envelope_clear(envelope_lookup *e){
115   int i;
116   for(i=0;i<e->ch*4;i++){
117     IIR_clear((e->iir+i));
118     _ogg_free(e->filtered[i]);
119   }
120   _ogg_free(e->filtered);
121   _ogg_free(e->iir);
122   memset(e,0,sizeof(envelope_lookup));
123 }
124
125 /* straight threshhold based until we find something that works better
126    and isn't patented */
127 static float _ve_deltai(envelope_lookup *ve,float *pre,float *post){
128   long n=ve->winlength;
129
130   long i;
131
132   /* we want to have a 'minimum bar' for energy, else we're just
133      basing blocks on quantization noise that outweighs the signal
134      itself (for low power signals) */
135
136   float minV=ve->minenergy;
137   float A=minV*minV*n;
138   float B=A;
139
140   for(i=0;i<n;i++){
141     A+=pre[i]*pre[i];
142     B+=post[i]*post[i];
143   }
144
145   A=todB(&A);
146   B=todB(&B);
147
148   return(B-A);
149 }
150
151 long _ve_envelope_search(vorbis_dsp_state *v,long searchpoint){
152   vorbis_info *vi=v->vi;
153   codec_setup_info *ci=vi->codec_setup;
154   vorbis_info_psy_global *gi=ci->psy_g_param;
155   envelope_lookup *ve=((backend_lookup_state *)(v->backend_state))->ve;
156   long i,j,k;
157
158   /* make sure we have enough storage to match the PCM */
159   if(v->pcm_storage>ve->storage){
160     ve->storage=v->pcm_storage;
161     for(i=0;i<ve->ch*4;i++)
162       ve->filtered[i]=_ogg_realloc(ve->filtered[i],ve->storage*sizeof(float));
163   }
164
165   /* catch up the highpass to match the pcm */
166   for(i=0;i<ve->ch;i++){
167     float *pcm=v->pcm[i];
168     float *filtered0=ve->filtered[i*4];
169     float *filtered1=ve->filtered[i*4+1];
170     float *filtered2=ve->filtered[i*4+2];
171     float *filtered3=ve->filtered[i*4+3];
172     IIR_state *iir0=ve->iir+i*4;
173     IIR_state *iir1=ve->iir+i*4+1;
174     IIR_state *iir2=ve->iir+i*4+2;
175     IIR_state *iir3=ve->iir+i*4+3;
176     int flag=1;
177     for(j=ve->current;j<v->pcm_current;j++){
178       filtered0[j]=IIR_filter(iir0,pcm[j]);
179       filtered1[j]=IIR_filter_Band(iir1,pcm[j]);
180       filtered2[j]=IIR_filter_Band(iir2,pcm[j]);
181       filtered3[j]=IIR_filter_Band(iir3,pcm[j]);
182       if(pcm[j])flag=0;
183     }
184     if(flag && ve->current+64<v->pcm_current){
185       IIR_reset(iir0);
186       IIR_reset(iir1);
187       IIR_reset(iir2);
188       IIR_reset(iir3);
189     }
190
191   }
192
193   ve->current=v->pcm_current;
194
195   /* Now search through our cached highpass data for breaking points */
196   /* starting point */
197   if(v->W)
198     j=v->centerW+ci->blocksizes[1]/4-ci->blocksizes[0]/4;
199   else
200     j=v->centerW;
201
202   if(j<ve->lastmark)j=ve->lastmark;
203   
204   while(j+ve->winlength<=v->pcm_current){
205     if(j>=searchpoint)return(1);
206
207     ve->lastmark=j;
208     for(i=0;i<ve->ch;i++){
209       for(k=0;k<4;k++){
210         float *filtered=ve->filtered[i*4+k]+j;
211         float m=_ve_deltai(ve,filtered-ve->winlength,filtered);
212       
213         if(m>gi->preecho_thresh[k])return(0);
214         if(m<gi->postecho_thresh[k])return(0);
215
216       }
217     }
218
219     j+=min(ci->blocksizes[0],ve->winlength)/2;
220    
221   }
222   if(j>=searchpoint)return(1);
223  
224   return(-1);
225 }
226
227 void _ve_envelope_shift(envelope_lookup *e,long shift){
228   int i;
229   for(i=0;i<e->ch*4;i++)
230     memmove(e->filtered[i],e->filtered[i]+shift,(e->current-shift)*
231             sizeof(float));
232   e->current-=shift;
233   e->lastmark-=shift;
234 }
235
236