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.33 2001/02/17 10:13:47 xiphmont Exp $
18 ********************************************************************/
25 #include "vorbis/codec.h"
26 #include "codec_internal.h"
33 /* Digital filter designed by mkfilter/mkshape/gencode A.J. Fisher */
35 static int cheb_highpass_stages=6;
36 static float cheb_highpass_B[]={1.f,-6.f,15.f,-20.f,15.f,-6.f,1.f};
38 static int cheb_bandpass_stages=6;
39 static float cheb_bandpass_B[]={-1.f,0.f,3.f,0.f,-3.f,0.f,1.f};
42 /* 10kHz Chebyshev highpass */
43 static float cheb_highpass10k_gain= 54.34519586f;
44 static float cheb_highpass10k_A[]={
52 /* 6kHz-10kHz Chebyshev bandpass */
53 static float cheb_bandpass6k_gain=113.4643935f;
54 static float cheb_bandpass6k_A[]={
62 /* 3kHz-6kHz Chebyshev bandpass */
63 static float cheb_bandpass3k_gain= 248.8359377f;
64 static float cheb_bandpass3k_A[]={
72 /* 1.5kHz-3kHz Chebyshev bandpass */
73 static float cheb_bandpass1k_gain= 1798.537183f;
74 static float cheb_bandpass1k_A[]={
82 void _ve_envelope_init(envelope_lookup *e,vorbis_info *vi){
83 codec_setup_info *ci=vi->codec_setup;
85 int window=ci->envelopesa;
88 e->minenergy=fromdB(ci->preecho_minenergy);
89 e->iir=_ogg_calloc(ch*4,sizeof(IIR_state));
90 e->filtered=_ogg_calloc(ch*4,sizeof(float *));
95 IIR_init(e->iir+i,cheb_highpass_stages,cheb_highpass10k_gain,
96 cheb_highpass10k_A,cheb_highpass_B);
97 IIR_init(e->iir+i+1,cheb_bandpass_stages,cheb_bandpass6k_gain,
98 cheb_bandpass6k_A,cheb_bandpass_B);
99 IIR_init(e->iir+i+2,cheb_bandpass_stages,cheb_bandpass3k_gain,
100 cheb_bandpass3k_A,cheb_bandpass_B);
101 IIR_init(e->iir+i+3,cheb_bandpass_stages,cheb_bandpass1k_gain,
102 cheb_bandpass1k_A,cheb_bandpass_B);
104 e->filtered[i]=_ogg_calloc(e->storage,sizeof(float));
105 e->filtered[i+1]=_ogg_calloc(e->storage,sizeof(float));
106 e->filtered[i+2]=_ogg_calloc(e->storage,sizeof(float));
107 e->filtered[i+3]=_ogg_calloc(e->storage,sizeof(float));
112 void _ve_envelope_clear(envelope_lookup *e){
114 for(i=0;i<e->ch*4;i++){
115 IIR_clear((e->iir+i));
116 _ogg_free(e->filtered[i]);
118 _ogg_free(e->filtered);
120 memset(e,0,sizeof(envelope_lookup));
123 /* straight threshhold based until we find something that works better
124 and isn't patented */
125 static float _ve_deltai(envelope_lookup *ve,float *pre,float *post){
126 long n=ve->winlength;
130 /* we want to have a 'minimum bar' for energy, else we're just
131 basing blocks on quantization noise that outweighs the signal
132 itself (for low power signals) */
134 float min=ve->minenergy;
149 long _ve_envelope_search(vorbis_dsp_state *v,long searchpoint){
150 vorbis_info *vi=v->vi;
151 codec_setup_info *ci=vi->codec_setup;
152 envelope_lookup *ve=((backend_lookup_state *)(v->backend_state))->ve;
154 float *work=alloca(sizeof(float)*ve->winlength*2);
157 /* make sure we have enough storage to match the PCM */
158 if(v->pcm_storage>ve->storage){
159 ve->storage=v->pcm_storage;
160 for(i=0;i<ve->ch*4;i++)
161 ve->filtered[i]=_ogg_realloc(ve->filtered[i],ve->storage*sizeof(float));
164 /* catch up the highpass to match the pcm */
165 for(i=0;i<ve->ch;i++){
166 float *pcm=v->pcm[i];
167 float *filtered0=ve->filtered[i*4];
168 float *filtered1=ve->filtered[i*4+1];
169 float *filtered2=ve->filtered[i*4+2];
170 float *filtered3=ve->filtered[i*4+3];
171 IIR_state *iir0=ve->iir+i*4;
172 IIR_state *iir1=ve->iir+i*4+1;
173 IIR_state *iir2=ve->iir+i*4+2;
174 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(iir1,pcm[j]);
180 filtered2[j]=IIR_filter(iir2,pcm[j]);
181 filtered3[j]=IIR_filter(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 for(i=0;i<ve->ch;i++){
207 float *filtered=ve->filtered[i*4+k]+j;
208 float m=_ve_deltai(ve,filtered-ve->winlength,filtered);
210 if(m>ci->preecho_thresh[k]){
215 if(m<ci->postecho_thresh[k]){
224 j+=min(ci->blocksizes[0],ve->winlength)/2;
234 void _ve_envelope_shift(envelope_lookup *e,long shift){
236 for(i=0;i<e->ch*4;i++)
237 memmove(e->filtered[i],e->filtered[i]+shift,(e->current-shift)*