1 /********************************************************************
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. *
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.35 2001/02/26 03:50:41 xiphmont Exp $
18 ********************************************************************/
25 #include "vorbis/codec.h"
26 #include "codec_internal.h"
32 #include "iir.c" /* Yes, ugly, but needed for inlining */
34 /* Digital filter designed by mkfilter/mkshape/gencode A.J. Fisher */
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};
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};
43 /* 10kHz Chebyshev highpass */
44 static float cheb_highpass10k_gain= 54.34519586f;
45 static float cheb_highpass10k_A[]={
53 /* 6kHz-10kHz Chebyshev bandpass */
54 static float cheb_bandpass6k_gain=113.4643935f;
55 static float cheb_bandpass6k_A[]={
63 /* 3kHz-6kHz Chebyshev bandpass */
64 static float cheb_bandpass3k_gain= 248.8359377f;
65 static float cheb_bandpass3k_A[]={
73 /* 1.5kHz-3kHz Chebyshev bandpass */
74 static float cheb_bandpass1k_gain= 1798.537183f;
75 static float cheb_bandpass1k_A[]={
83 void _ve_envelope_init(envelope_lookup *e,vorbis_info *vi){
84 codec_setup_info *ci=vi->codec_setup;
86 int window=ci->envelopesa;
89 e->minenergy=fromdB(ci->preecho_minenergy);
90 e->iir=_ogg_calloc(ch*4,sizeof(IIR_state));
91 e->filtered=_ogg_calloc(ch*4,sizeof(float *));
96 IIR_init(e->iir+i,cheb_highpass_stages,cheb_highpass10k_gain,
97 cheb_highpass10k_A,cheb_highpass_B);
98 IIR_init(e->iir+i+1,cheb_bandpass_stages,cheb_bandpass6k_gain,
99 cheb_bandpass6k_A,cheb_bandpass_B);
100 IIR_init(e->iir+i+2,cheb_bandpass_stages,cheb_bandpass3k_gain,
101 cheb_bandpass3k_A,cheb_bandpass_B);
102 IIR_init(e->iir+i+3,cheb_bandpass_stages,cheb_bandpass1k_gain,
103 cheb_bandpass1k_A,cheb_bandpass_B);
105 e->filtered[i]=_ogg_calloc(e->storage,sizeof(float));
106 e->filtered[i+1]=_ogg_calloc(e->storage,sizeof(float));
107 e->filtered[i+2]=_ogg_calloc(e->storage,sizeof(float));
108 e->filtered[i+3]=_ogg_calloc(e->storage,sizeof(float));
113 void _ve_envelope_clear(envelope_lookup *e){
115 for(i=0;i<e->ch*4;i++){
116 IIR_clear((e->iir+i));
117 _ogg_free(e->filtered[i]);
119 _ogg_free(e->filtered);
121 memset(e,0,sizeof(envelope_lookup));
124 /* straight threshhold based until we find something that works better
125 and isn't patented */
126 static float _ve_deltai(envelope_lookup *ve,float *pre,float *post){
127 long n=ve->winlength;
131 /* we want to have a 'minimum bar' for energy, else we're just
132 basing blocks on quantization noise that outweighs the signal
133 itself (for low power signals) */
135 float min=ve->minenergy;
150 long _ve_envelope_search(vorbis_dsp_state *v,long searchpoint){
151 vorbis_info *vi=v->vi;
152 codec_setup_info *ci=vi->codec_setup;
153 envelope_lookup *ve=((backend_lookup_state *)(v->backend_state))->ve;
155 float *work=alloca(sizeof(float)*ve->winlength*2);
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));
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;
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]);
184 if(flag && ve->current+64<v->pcm_current){
193 ve->current=v->pcm_current;
195 /* Now search through our cached highpass data for breaking points */
198 j=v->centerW+ci->blocksizes[1]/4-ci->blocksizes[0]/4;
202 if(j<ve->lastmark)j=ve->lastmark;
204 while(j+ve->winlength<=v->pcm_current){
205 if(j>=searchpoint)return(1);
208 for(i=0;i<ve->ch;i++){
210 float *filtered=ve->filtered[i*4+k]+j;
211 float m=_ve_deltai(ve,filtered-ve->winlength,filtered);
213 if(m>ci->preecho_thresh[k])return(0);
214 if(m<ci->postecho_thresh[k])return(0);
219 j+=min(ci->blocksizes[0],ve->winlength)/2;
222 if(j>=searchpoint)return(1);
227 void _ve_envelope_shift(envelope_lookup *e,long shift){
229 for(i=0;i<e->ch*4;i++)
230 memmove(e->filtered[i],e->filtered[i]+shift,(e->current-shift)*