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-2000 *
9 * by Monty <monty@xiph.org> and the XIPHOPHORUS Company *
10 * http://www.xiph.org/ *
12 ********************************************************************
14 function: PCM data envelope analysis and manipulation
15 last mod: $Id: envelope.c,v 1.30 2001/01/31 23:58:49 xiphmont Exp $
19 ********************************************************************/
26 #include "vorbis/codec.h"
27 #include "codec_internal.h"
34 /* Digital filter designed by mkfilter/mkshape/gencode A.J. Fisher
35 Command line: /www/usr/fisher/helpers/mkfilter -Ch \
36 -6.0000000000e+00 -Bp -o 5 -a 1.3605442177e-01 3.1746031746e-01 -l */
39 static int cheb_bandpass_stages=10;
40 static float cheb_bandpass_gain=5.589612458e+01f;
41 static float cheb_bandpass_B[]={-1.f,0.f,5.f,0.f,-10.f,0.f,
42 10.f,0.f,-5.f,0.f,1f};
43 static float cheb_bandpass_A[]={
56 /* 4kHz Chebyshev highpass */
57 static int cheb_highpass_stages=10;
58 static float cheb_highpass_gain= 1.314337427e+01f;
59 /* z^-stage, z^-stage+1... */
60 static float cheb_highpass_B[]={1.f,-10.f,45.f,-120.f,210.f,
61 -252.f,210.f,-120.f,45.f,-10.f,1.f};
62 static float cheb_highpass_A[]={
75 /* 6kHz Chebyshev highpass */
76 static int cheb_highpass_stages=10;
77 static float cheb_highpass_gain= 5.291963434e+01f;
78 /* z^-stage, z^-stage+1... */
79 static float cheb_highpass_B[]={1.f,-10.f,45.f,-120.f,210.f,
80 -252.f,210.f,-120.f,45.f,-10.f,1.f};
81 static float cheb_highpass_A[]={
94 void _ve_envelope_init(envelope_lookup *e,vorbis_info *vi){
95 codec_setup_info *ci=vi->codec_setup;
97 int window=ci->envelopesa;
100 e->minenergy=fromdB(ci->preecho_minenergy);
101 e->iir=_ogg_calloc(ch,sizeof(IIR_state));
102 e->filtered=_ogg_calloc(ch,sizeof(float *));
106 IIR_init(e->iir+i,cheb_highpass_stages,cheb_highpass_gain,
107 cheb_highpass_A,cheb_highpass_B);
108 e->filtered[i]=_ogg_calloc(e->storage,sizeof(float));
111 drft_init(&e->drft,window);
112 e->window=_ogg_malloc(e->winlength*sizeof(float));
113 /* We just use a straight sin(x) window for this */
114 for(i=0;i<e->winlength;i++)
115 e->window[i]=sin((i+.5)/e->winlength*M_PI);
118 void _ve_envelope_clear(envelope_lookup *e){
120 for(i=0;i<e->ch;i++){
121 IIR_clear((e->iir+i));
122 _ogg_free(e->filtered[i]);
124 drft_clear(&e->drft);
125 _ogg_free(e->window);
126 _ogg_free(e->filtered);
128 memset(e,0,sizeof(envelope_lookup));
131 /* straight threshhold based until we find something that works better
132 and isn't patented */
133 static float _ve_deltai(envelope_lookup *ve,float *pre,float *post){
134 long n=ve->winlength;
138 /* we want to have a 'minimum bar' for energy, else we're just
139 basing blocks on quantization noise that outweighs the signal
140 itself (for low power signals) */
142 float min=ve->minenergy;
146 /*_analysis_output("A",granulepos,pre,n,0,0);
147 _analysis_output("B",granulepos,post,n,0,0);*/
160 static float _ve_ampi(envelope_lookup *ve,float *pre){
161 long n=ve->winlength;
165 /* we want to have a 'minimum bar' for energy, else we're just
166 basing blocks on quantization noise that outweighs the signal
167 itself (for low power signals) */
169 float min=ve->minenergy;
180 long _ve_envelope_search(vorbis_dsp_state *v,long searchpoint){
181 vorbis_info *vi=v->vi;
182 codec_setup_info *ci=vi->codec_setup;
183 envelope_lookup *ve=((backend_lookup_state *)(v->backend_state))->ve;
185 float *work=alloca(sizeof(float)*ve->winlength*2);
187 /* make sure we have enough storage to match the PCM */
188 if(v->pcm_storage>ve->storage){
189 ve->storage=v->pcm_storage;
190 for(i=0;i<ve->ch;i++)
191 ve->filtered[i]=_ogg_realloc(ve->filtered[i],ve->storage*sizeof(float));
194 /* catch up the highpass to match the pcm */
195 for(i=0;i<ve->ch;i++){
196 float *filtered=ve->filtered[i];
197 float *pcm=v->pcm[i];
198 IIR_state *iir=ve->iir+i;
201 for(j=ve->current;j<v->pcm_current;j++){
202 filtered[j]=IIR_filter(iir,pcm[j]);
205 if(flag && ve->current+64<v->pcm_current)IIR_reset(iir);
208 ve->current=v->pcm_current;
210 /* Now search through our cached highpass data for breaking points */
213 j=v->centerW+ci->blocksizes[1]/4-ci->blocksizes[0]/4;
217 while(j+ve->winlength<=v->pcm_current){
218 for(i=0;i<ve->ch;i++){
219 float *filtered=ve->filtered[i]+j;
220 float m=_ve_deltai(ve,filtered-ve->winlength,filtered);
222 if(m>ci->preecho_thresh){
226 if(m<ci->postecho_thresh){
233 /* look also for preecho in coupled channel pairs with the center
234 subtracted out (A-B) */
235 for(i=1;i<ve->ch;i+=2){
236 float *filteredA=ve->filtered[i-1]+j-ve->winlength;
237 float *filteredB=ve->filtered[i]+j-ve->winlength;
240 for(k=0;k<ve->winlength*2;k++)
241 work[k]=filteredA[k]-filteredB[k];
243 m=_ve_deltai(ve,work,work+ve->winlength);
245 if(m>ci->preecho_thresh){
249 if(m<ci->postecho_thresh){
257 j+=min(ci->blocksizes[0],ve->winlength)/2;
267 void _ve_envelope_shift(envelope_lookup *e,long shift){
270 memmove(e->filtered[i],e->filtered[i]+shift,(e->current-shift)*