1 /********************************************************************
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. *
8 * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2001 *
9 * by the XIPHOPHORUS Company http://www.xiph.org/ *
11 ********************************************************************
13 function: PCM data envelope analysis and manipulation
14 last mod: $Id: envelope.c,v 1.31 2001/02/02 03:51:56 xiphmont Exp $
18 ********************************************************************/
25 #include "vorbis/codec.h"
26 #include "codec_internal.h"
33 /* Digital filter designed by mkfilter/mkshape/gencode A.J. Fisher
34 Command line: /www/usr/fisher/helpers/mkfilter -Ch \
35 -6.0000000000e+00 -Bp -o 5 -a 1.3605442177e-01 3.1746031746e-01 -l */
38 static int cheb_bandpass_stages=10;
39 static float cheb_bandpass_gain=5.589612458e+01f;
40 static float cheb_bandpass_B[]={-1.f,0.f,5.f,0.f,-10.f,0.f,
41 10.f,0.f,-5.f,0.f,1f};
42 static float cheb_bandpass_A[]={
55 /* 4kHz Chebyshev highpass */
56 static int cheb_highpass_stages=10;
57 static float cheb_highpass_gain= 1.314337427e+01f;
58 /* z^-stage, z^-stage+1... */
59 static float cheb_highpass_B[]={1.f,-10.f,45.f,-120.f,210.f,
60 -252.f,210.f,-120.f,45.f,-10.f,1.f};
61 static float cheb_highpass_A[]={
74 /* 6kHz Chebyshev highpass */
75 static int cheb_highpass_stages=10;
76 static float cheb_highpass_gain= 5.291963434e+01f;
77 /* z^-stage, z^-stage+1... */
78 static float cheb_highpass_B[]={1.f,-10.f,45.f,-120.f,210.f,
79 -252.f,210.f,-120.f,45.f,-10.f,1.f};
80 static float cheb_highpass_A[]={
93 void _ve_envelope_init(envelope_lookup *e,vorbis_info *vi){
94 codec_setup_info *ci=vi->codec_setup;
96 int window=ci->envelopesa;
99 e->minenergy=fromdB(ci->preecho_minenergy);
100 e->iir=_ogg_calloc(ch,sizeof(IIR_state));
101 e->filtered=_ogg_calloc(ch,sizeof(float *));
105 IIR_init(e->iir+i,cheb_highpass_stages,cheb_highpass_gain,
106 cheb_highpass_A,cheb_highpass_B);
107 e->filtered[i]=_ogg_calloc(e->storage,sizeof(float));
110 drft_init(&e->drft,window);
111 e->window=_ogg_malloc(e->winlength*sizeof(float));
112 /* We just use a straight sin(x) window for this */
113 for(i=0;i<e->winlength;i++)
114 e->window[i]=sin((i+.5)/e->winlength*M_PI);
117 void _ve_envelope_clear(envelope_lookup *e){
119 for(i=0;i<e->ch;i++){
120 IIR_clear((e->iir+i));
121 _ogg_free(e->filtered[i]);
123 drft_clear(&e->drft);
124 _ogg_free(e->window);
125 _ogg_free(e->filtered);
127 memset(e,0,sizeof(envelope_lookup));
130 /* straight threshhold based until we find something that works better
131 and isn't patented */
132 static float _ve_deltai(envelope_lookup *ve,float *pre,float *post){
133 long n=ve->winlength;
137 /* we want to have a 'minimum bar' for energy, else we're just
138 basing blocks on quantization noise that outweighs the signal
139 itself (for low power signals) */
141 float min=ve->minenergy;
145 /*_analysis_output("A",granulepos,pre,n,0,0);
146 _analysis_output("B",granulepos,post,n,0,0);*/
159 static float _ve_ampi(envelope_lookup *ve,float *pre){
160 long n=ve->winlength;
164 /* we want to have a 'minimum bar' for energy, else we're just
165 basing blocks on quantization noise that outweighs the signal
166 itself (for low power signals) */
168 float min=ve->minenergy;
179 long _ve_envelope_search(vorbis_dsp_state *v,long searchpoint){
180 vorbis_info *vi=v->vi;
181 codec_setup_info *ci=vi->codec_setup;
182 envelope_lookup *ve=((backend_lookup_state *)(v->backend_state))->ve;
184 float *work=alloca(sizeof(float)*ve->winlength*2);
186 /* make sure we have enough storage to match the PCM */
187 if(v->pcm_storage>ve->storage){
188 ve->storage=v->pcm_storage;
189 for(i=0;i<ve->ch;i++)
190 ve->filtered[i]=_ogg_realloc(ve->filtered[i],ve->storage*sizeof(float));
193 /* catch up the highpass to match the pcm */
194 for(i=0;i<ve->ch;i++){
195 float *filtered=ve->filtered[i];
196 float *pcm=v->pcm[i];
197 IIR_state *iir=ve->iir+i;
200 for(j=ve->current;j<v->pcm_current;j++){
201 filtered[j]=IIR_filter(iir,pcm[j]);
204 if(flag && ve->current+64<v->pcm_current)IIR_reset(iir);
207 ve->current=v->pcm_current;
209 /* Now search through our cached highpass data for breaking points */
212 j=v->centerW+ci->blocksizes[1]/4-ci->blocksizes[0]/4;
216 while(j+ve->winlength<=v->pcm_current){
217 for(i=0;i<ve->ch;i++){
218 float *filtered=ve->filtered[i]+j;
219 float m=_ve_deltai(ve,filtered-ve->winlength,filtered);
221 if(m>ci->preecho_thresh){
225 if(m<ci->postecho_thresh){
232 /* look also for preecho in coupled channel pairs with the center
233 subtracted out (A-B) */
234 for(i=1;i<ve->ch;i+=2){
235 float *filteredA=ve->filtered[i-1]+j-ve->winlength;
236 float *filteredB=ve->filtered[i]+j-ve->winlength;
239 for(k=0;k<ve->winlength*2;k++)
240 work[k]=filteredA[k]-filteredB[k];
242 m=_ve_deltai(ve,work,work+ve->winlength);
244 if(m>ci->preecho_thresh){
248 if(m<ci->postecho_thresh){
256 j+=min(ci->blocksizes[0],ve->winlength)/2;
266 void _ve_envelope_shift(envelope_lookup *e,long shift){
269 memmove(e->filtered[i],e->filtered[i]+shift,(e->current-shift)*