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
14 last mod: $Id: envelope.c,v 1.42 2002/03/17 19:50:47 xiphmont Exp $
16 ********************************************************************/
23 #include "vorbis/codec.h"
24 #include "codec_internal.h"
32 void _ve_envelope_init(envelope_lookup *e,vorbis_info *vi){
33 codec_setup_info *ci=vi->codec_setup;
34 vorbis_info_psy_global *gi=&ci->psy_g_param;
37 int n=e->winlength=ci->blocksizes[0];
38 e->searchstep=ci->blocksizes[0]/VE_DIV; /* not random */
40 e->minenergy=fromdB(gi->preecho_minenergy);
43 e->cursor=ci->blocksizes[1]/2;
44 e->mdct_win=_ogg_calloc(n,sizeof(*e->mdct_win));
45 mdct_init(&e->mdct,n);
48 e->mdct_win[i]=sin((i+.5)/n*M_PI);
49 e->mdct_win[i]*=e->mdct_win[i];
52 /* overlapping bands, assuming 22050 (which is not always true, but
54 /* 2(1.3-3) 4(2.6-6) 8(5.3-12) 16(10.6-18) */
56 e->band[0].begin=rint(1300.f/22050.f*n/4.f)*2.f;
57 e->band[0].end=rint(3000.f/22050.f*n/4.f)*2.f-e->band[0].begin;
58 e->band[1].begin=rint(2600.f/22050.f*n/4.f)*2.f;
59 e->band[1].end=rint(6000.f/22050.f*n/4.f)*2.f-e->band[1].begin;
60 e->band[2].begin=rint(5300.f/22050.f*n/4.f)*2.f;
61 e->band[2].end=rint(12000.f/22050.f*n/4.f)*2.f-e->band[2].begin;
62 e->band[3].begin=rint(10600.f/22050.f*n/4.f)*2.f;
63 e->band[3].end=rint(18000.f/22050.f*n/4.f)*2.f-e->band[3].begin;
65 e->band[0].window=_ogg_malloc((e->band[0].end)*sizeof(*e->band[0].window));
66 e->band[1].window=_ogg_malloc((e->band[1].end)*sizeof(*e->band[1].window));
67 e->band[2].window=_ogg_malloc((e->band[2].end)*sizeof(*e->band[2].window));
68 e->band[3].window=_ogg_malloc((e->band[3].end)*sizeof(*e->band[3].window));
72 e->band[0].window[i]=sin((i+.5)/n*M_PI);
75 e->band[1].window[i]=sin((i+.5)/n*M_PI);
78 e->band[2].window[i]=sin((i+.5)/n*M_PI);
81 e->band[3].window[i]=sin((i+.5)/n*M_PI);
83 e->filter=_ogg_calloc(VE_BANDS*ch,sizeof(*e->filter));
84 e->mark=_ogg_calloc(e->storage,sizeof(*e->mark));
89 void _ve_envelope_clear(envelope_lookup *e){
92 for(i=0;i<VE_BANDS;i++)
93 _ogg_free(e->band[i].window);
94 _ogg_free(e->mdct_win);
97 memset(e,0,sizeof(*e));
100 /* fairly straight threshhold-by-band based until we find something
101 that works better and isn't patented. */
103 static int _ve_amp(envelope_lookup *ve,
104 vorbis_info_psy_global *gi,
106 envelope_band *bands,
107 envelope_filter_state *filters,
109 long n=ve->winlength;
113 /* we want to have a 'minimum bar' for energy, else we're just
114 basing blocks on quantization noise that outweighs the signal
115 itself (for low power signals) */
117 float minV=ve->minenergy,acc[VE_BANDS];
118 float *vec=alloca(n*sizeof(*vec));
119 memset(acc,0,sizeof(acc));
121 /* window and transform */
123 vec[i]=data[i]*ve->mdct_win[i];
124 mdct_forward(&ve->mdct,vec,vec);
126 /* accumulate amplitude by band */
127 for(j=0;j<VE_BANDS;j++){
128 for(i=0;i<bands[j].end;i++){
129 float val=vec[i+bands[j].begin];
130 acc[j]+=val*val*bands[j].window[i];
133 if(acc[j]<minV*minV)acc[j]=minV*minV;
137 /* convert amplitude to delta */
138 for(j=0;j<VE_BANDS;j++){
139 float val=acc[j]-filters[j].ampbuf[filters[j].ampptr];
140 filters[j].ampbuf[filters[j].ampptr]=acc[j];
143 if(filters[j].ampptr>=VE_DIV)filters[j].ampptr=0;
146 /* convolve deltas to threshhold values */
147 for(j=0;j<VE_BANDS;j++){
148 float *buf=filters[j].delbuf;
149 float val=.14*buf[0]+.14*buf[1]+.72*acc[j];
150 buf[0]=buf[1];buf[1]=acc[j];
154 /* look at local min/max */
155 for(j=0;j<VE_BANDS;j++){
156 float *buf=filters[j].convbuf;
157 if(buf[1]>gi->preecho_thresh[j] && buf[0]<buf[1] && acc[j]<buf[1])ret=1;
158 if(buf[1]<gi->postecho_thresh[j] && buf[0]>buf[1] && acc[j]>buf[1])ret=1;
159 buf[0]=buf[1];buf[1]=acc[j];
165 long _ve_envelope_search(vorbis_dsp_state *v){
166 vorbis_info *vi=v->vi;
167 codec_setup_info *ci=vi->codec_setup;
168 vorbis_info_psy_global *gi=&ci->psy_g_param;
169 envelope_lookup *ve=((backend_lookup_state *)(v->backend_state))->ve;
172 int first=ve->current/ve->searchstep;
173 int last=v->pcm_current/ve->searchstep-VE_DIV;
176 /* make sure we have enough storage to match the PCM */
177 if(last>ve->storage){
179 ve->mark=_ogg_realloc(ve->mark,ve->storage*sizeof(*ve->mark));
182 for(j=first;j<last;j++){
184 for(i=0;i<ve->ch;i++){
185 float *pcm=v->pcm[i]+ve->searchstep*(j+1);
186 ret|=_ve_amp(ve,gi,pcm,ve->band,ve->filter+i*VE_BANDS,j);
188 /* the mark delay is one searchstep because of min/max finder */
192 ve->current=last*ve->searchstep;
195 long centerW=v->centerW;
198 ci->blocksizes[v->W]/4+
204 while(j<ve->current){
205 if(j>=testW)return(1);
206 if(ve->mark[j/ve->searchstep]){
211 if(j>=testW)return(1);
223 int _ve_envelope_mark(vorbis_dsp_state *v){
224 envelope_lookup *ve=((backend_lookup_state *)(v->backend_state))->ve;
225 vorbis_info *vi=v->vi;
226 codec_setup_info *ci=vi->codec_setup;
227 long centerW=v->centerW;
228 long beginW=centerW-ci->blocksizes[v->W]/4;
229 long endW=centerW+ci->blocksizes[v->W]/4;
231 beginW-=ci->blocksizes[v->lW]/4;
232 endW+=ci->blocksizes[v->nW]/4;
234 beginW-=ci->blocksizes[0]/4;
235 endW+=ci->blocksizes[0]/4;
238 if(ve->curmark>=beginW && ve->curmark<endW)return(1);
240 long first=beginW/ve->searchstep;
241 long last=endW/ve->searchstep;
243 for(i=first;i<last;i++)
244 if(ve->mark[i])return(1);
249 void _ve_envelope_shift(envelope_lookup *e,long shift){
250 int smallsize=e->current/e->searchstep;
251 int smallshift=shift/e->searchstep;
254 memmove(e->mark,e->mark+smallshift,(smallsize-smallshift)*sizeof(*e->mark));