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.32 2001/02/15 19:05:45 xiphmont Exp $
18 ********************************************************************/
25 #include "vorbis/codec.h"
26 #include "codec_internal.h"
33 /* Digital filter designed by mkfilter/mkshape/gencode A.J. Fisher */
37 static int cheb_highpass_stages=6;
38 static float cheb_highpass_B[]={1.f,-6.f,15.f,-20.f,15.f,-6.f,1.f};
40 static int cheb_bandpass_stages=6;
41 static float cheb_bandpass_B[]={-1.f,0.f,3.f,0.f,-3.f,0.f,1.f};
44 /* 10kHz Chebyshev highpass */
45 static float cheb_highpass10k_gain= 54.34519586f;
46 static float cheb_highpass10k_A[]={
54 /* 6kHz-10kHz Chebyshev bandpass */
55 static float cheb_bandpass6k_gain=113.4643935f;
56 static float cheb_bandpass6k_A[]={
64 /* 3kHz-6kHz Chebyshev bandpass */
65 static float cheb_bandpass3k_gain= 248.8359377f;
66 static float cheb_bandpass3k_A[]={
74 /* 1.5kHz-3kHz Chebyshev bandpass */
75 static float cheb_bandpass1k_gain= 1798.537183f;
76 static float cheb_bandpass1k_A[]={
85 void _ve_envelope_init(envelope_lookup *e,vorbis_info *vi){
86 codec_setup_info *ci=vi->codec_setup;
88 int window=ci->envelopesa;
91 e->minenergy=fromdB(ci->preecho_minenergy);
92 e->iir=_ogg_calloc(ch*4,sizeof(IIR_state));
93 e->filtered=_ogg_calloc(ch*4,sizeof(float *));
98 IIR_init(e->iir+i,cheb_highpass_stages,cheb_highpass10k_gain,
99 cheb_highpass10k_A,cheb_highpass_B);
100 IIR_init(e->iir+i+1,cheb_bandpass_stages,cheb_bandpass6k_gain,
101 cheb_bandpass6k_A,cheb_bandpass_B);
102 IIR_init(e->iir+i+2,cheb_bandpass_stages,cheb_bandpass3k_gain,
103 cheb_bandpass3k_A,cheb_bandpass_B);
104 IIR_init(e->iir+i+3,cheb_bandpass_stages,cheb_bandpass1k_gain,
105 cheb_bandpass1k_A,cheb_bandpass_B);
107 e->filtered[i]=_ogg_calloc(e->storage,sizeof(float));
108 e->filtered[i+1]=_ogg_calloc(e->storage,sizeof(float));
109 e->filtered[i+2]=_ogg_calloc(e->storage,sizeof(float));
110 e->filtered[i+3]=_ogg_calloc(e->storage,sizeof(float));
115 void _ve_envelope_clear(envelope_lookup *e){
117 for(i=0;i<e->ch*4;i++){
118 IIR_clear((e->iir+i));
119 _ogg_free(e->filtered[i]);
121 _ogg_free(e->filtered);
123 memset(e,0,sizeof(envelope_lookup));
126 /* straight threshhold based until we find something that works better
127 and isn't patented */
128 static float _ve_deltai(envelope_lookup *ve,float *pre,float *post){
129 long n=ve->winlength;
133 /* we want to have a 'minimum bar' for energy, else we're just
134 basing blocks on quantization noise that outweighs the signal
135 itself (for low power signals) */
137 float min=ve->minenergy;
141 /*_analysis_output("A",granulepos,pre,n,0,0);
142 _analysis_output("B",granulepos,post,n,0,0);*/
155 long _ve_envelope_search(vorbis_dsp_state *v,long searchpoint){
156 vorbis_info *vi=v->vi;
157 codec_setup_info *ci=vi->codec_setup;
158 envelope_lookup *ve=((backend_lookup_state *)(v->backend_state))->ve;
160 float *work=alloca(sizeof(float)*ve->winlength*2);
163 /* make sure we have enough storage to match the PCM */
164 if(v->pcm_storage>ve->storage){
165 ve->storage=v->pcm_storage;
166 for(i=0;i<ve->ch*4;i++)
167 ve->filtered[i]=_ogg_realloc(ve->filtered[i],ve->storage*sizeof(float));
170 /* catch up the highpass to match the pcm */
171 for(i=0;i<ve->ch;i++){
172 float *pcm=v->pcm[i];
173 float *filtered0=ve->filtered[i*4];
174 float *filtered1=ve->filtered[i*4+1];
175 float *filtered2=ve->filtered[i*4+2];
176 float *filtered3=ve->filtered[i*4+3];
177 IIR_state *iir0=ve->iir+i*4;
178 IIR_state *iir1=ve->iir+i*4+1;
179 IIR_state *iir2=ve->iir+i*4+2;
180 IIR_state *iir3=ve->iir+i*4+3;
183 for(j=ve->current;j<v->pcm_current;j++){
184 filtered0[j]=IIR_filter(iir0,pcm[j]);
185 filtered1[j]=IIR_filter(iir1,pcm[j]);
186 filtered2[j]=IIR_filter(iir2,pcm[j]);
187 filtered3[j]=IIR_filter(iir3,pcm[j]);
190 if(flag && ve->current+64<v->pcm_current){
197 _analysis_output("pcm",seq,pcm+v->centerW,v->pcm_current-v->centerW,0,0);
198 _analysis_output("f0",seq,filtered0+v->centerW,v->pcm_current-v->centerW,
200 _analysis_output("f1",seq,filtered1+v->centerW,v->pcm_current-v->centerW,
202 _analysis_output("f2",seq,filtered2+v->centerW,v->pcm_current-v->centerW,
204 _analysis_output("f3",seq++,filtered3+v->centerW,v->pcm_current-v->centerW,
209 ve->current=v->pcm_current;
211 /* Now search through our cached highpass data for breaking points */
214 j=v->centerW+ci->blocksizes[1]/4-ci->blocksizes[0]/4;
218 while(j+ve->winlength<=v->pcm_current){
219 for(i=0;i<ve->ch;i++){
221 float *filtered=ve->filtered[i*4+k]+j;
222 float m=_ve_deltai(ve,filtered-ve->winlength,filtered);
224 if(m>ci->preecho_thresh[k]){
228 if(m<ci->postecho_thresh[k]){
236 j+=min(ci->blocksizes[0],ve->winlength)/2;
246 void _ve_envelope_shift(envelope_lookup *e,long shift){
248 for(i=0;i<e->ch*4;i++)
249 memmove(e->filtered[i],e->filtered[i]+shift,(e->current-shift)*