annotate src/libvorbis-1.3.3/lib/envelope.c @ 169:223a55898ab9 tip default

Add null config files
author Chris Cannam <cannam@all-day-breakfast.com>
date Mon, 02 Mar 2020 14:03:47 +0000
parents 98c1576536ae
children
rev   line source
cannam@86 1 /********************************************************************
cannam@86 2 * *
cannam@86 3 * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
cannam@86 4 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
cannam@86 5 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
cannam@86 6 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
cannam@86 7 * *
cannam@86 8 * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009 *
cannam@86 9 * by the Xiph.Org Foundation http://www.xiph.org/ *
cannam@86 10 * *
cannam@86 11 ********************************************************************
cannam@86 12
cannam@86 13 function: PCM data envelope analysis
cannam@86 14 last mod: $Id: envelope.c 16227 2009-07-08 06:58:46Z xiphmont $
cannam@86 15
cannam@86 16 ********************************************************************/
cannam@86 17
cannam@86 18 #include <stdlib.h>
cannam@86 19 #include <string.h>
cannam@86 20 #include <stdio.h>
cannam@86 21 #include <math.h>
cannam@86 22 #include <ogg/ogg.h>
cannam@86 23 #include "vorbis/codec.h"
cannam@86 24 #include "codec_internal.h"
cannam@86 25
cannam@86 26 #include "os.h"
cannam@86 27 #include "scales.h"
cannam@86 28 #include "envelope.h"
cannam@86 29 #include "mdct.h"
cannam@86 30 #include "misc.h"
cannam@86 31
cannam@86 32 void _ve_envelope_init(envelope_lookup *e,vorbis_info *vi){
cannam@86 33 codec_setup_info *ci=vi->codec_setup;
cannam@86 34 vorbis_info_psy_global *gi=&ci->psy_g_param;
cannam@86 35 int ch=vi->channels;
cannam@86 36 int i,j;
cannam@86 37 int n=e->winlength=128;
cannam@86 38 e->searchstep=64; /* not random */
cannam@86 39
cannam@86 40 e->minenergy=gi->preecho_minenergy;
cannam@86 41 e->ch=ch;
cannam@86 42 e->storage=128;
cannam@86 43 e->cursor=ci->blocksizes[1]/2;
cannam@86 44 e->mdct_win=_ogg_calloc(n,sizeof(*e->mdct_win));
cannam@86 45 mdct_init(&e->mdct,n);
cannam@86 46
cannam@86 47 for(i=0;i<n;i++){
cannam@86 48 e->mdct_win[i]=sin(i/(n-1.)*M_PI);
cannam@86 49 e->mdct_win[i]*=e->mdct_win[i];
cannam@86 50 }
cannam@86 51
cannam@86 52 /* magic follows */
cannam@86 53 e->band[0].begin=2; e->band[0].end=4;
cannam@86 54 e->band[1].begin=4; e->band[1].end=5;
cannam@86 55 e->band[2].begin=6; e->band[2].end=6;
cannam@86 56 e->band[3].begin=9; e->band[3].end=8;
cannam@86 57 e->band[4].begin=13; e->band[4].end=8;
cannam@86 58 e->band[5].begin=17; e->band[5].end=8;
cannam@86 59 e->band[6].begin=22; e->band[6].end=8;
cannam@86 60
cannam@86 61 for(j=0;j<VE_BANDS;j++){
cannam@86 62 n=e->band[j].end;
cannam@86 63 e->band[j].window=_ogg_malloc(n*sizeof(*e->band[0].window));
cannam@86 64 for(i=0;i<n;i++){
cannam@86 65 e->band[j].window[i]=sin((i+.5)/n*M_PI);
cannam@86 66 e->band[j].total+=e->band[j].window[i];
cannam@86 67 }
cannam@86 68 e->band[j].total=1./e->band[j].total;
cannam@86 69 }
cannam@86 70
cannam@86 71 e->filter=_ogg_calloc(VE_BANDS*ch,sizeof(*e->filter));
cannam@86 72 e->mark=_ogg_calloc(e->storage,sizeof(*e->mark));
cannam@86 73
cannam@86 74 }
cannam@86 75
cannam@86 76 void _ve_envelope_clear(envelope_lookup *e){
cannam@86 77 int i;
cannam@86 78 mdct_clear(&e->mdct);
cannam@86 79 for(i=0;i<VE_BANDS;i++)
cannam@86 80 _ogg_free(e->band[i].window);
cannam@86 81 _ogg_free(e->mdct_win);
cannam@86 82 _ogg_free(e->filter);
cannam@86 83 _ogg_free(e->mark);
cannam@86 84 memset(e,0,sizeof(*e));
cannam@86 85 }
cannam@86 86
cannam@86 87 /* fairly straight threshhold-by-band based until we find something
cannam@86 88 that works better and isn't patented. */
cannam@86 89
cannam@86 90 static int _ve_amp(envelope_lookup *ve,
cannam@86 91 vorbis_info_psy_global *gi,
cannam@86 92 float *data,
cannam@86 93 envelope_band *bands,
cannam@86 94 envelope_filter_state *filters){
cannam@86 95 long n=ve->winlength;
cannam@86 96 int ret=0;
cannam@86 97 long i,j;
cannam@86 98 float decay;
cannam@86 99
cannam@86 100 /* we want to have a 'minimum bar' for energy, else we're just
cannam@86 101 basing blocks on quantization noise that outweighs the signal
cannam@86 102 itself (for low power signals) */
cannam@86 103
cannam@86 104 float minV=ve->minenergy;
cannam@86 105 float *vec=alloca(n*sizeof(*vec));
cannam@86 106
cannam@86 107 /* stretch is used to gradually lengthen the number of windows
cannam@86 108 considered prevoius-to-potential-trigger */
cannam@86 109 int stretch=max(VE_MINSTRETCH,ve->stretch/2);
cannam@86 110 float penalty=gi->stretch_penalty-(ve->stretch/2-VE_MINSTRETCH);
cannam@86 111 if(penalty<0.f)penalty=0.f;
cannam@86 112 if(penalty>gi->stretch_penalty)penalty=gi->stretch_penalty;
cannam@86 113
cannam@86 114 /*_analysis_output_always("lpcm",seq2,data,n,0,0,
cannam@86 115 totalshift+pos*ve->searchstep);*/
cannam@86 116
cannam@86 117 /* window and transform */
cannam@86 118 for(i=0;i<n;i++)
cannam@86 119 vec[i]=data[i]*ve->mdct_win[i];
cannam@86 120 mdct_forward(&ve->mdct,vec,vec);
cannam@86 121
cannam@86 122 /*_analysis_output_always("mdct",seq2,vec,n/2,0,1,0); */
cannam@86 123
cannam@86 124 /* near-DC spreading function; this has nothing to do with
cannam@86 125 psychoacoustics, just sidelobe leakage and window size */
cannam@86 126 {
cannam@86 127 float temp=vec[0]*vec[0]+.7*vec[1]*vec[1]+.2*vec[2]*vec[2];
cannam@86 128 int ptr=filters->nearptr;
cannam@86 129
cannam@86 130 /* the accumulation is regularly refreshed from scratch to avoid
cannam@86 131 floating point creep */
cannam@86 132 if(ptr==0){
cannam@86 133 decay=filters->nearDC_acc=filters->nearDC_partialacc+temp;
cannam@86 134 filters->nearDC_partialacc=temp;
cannam@86 135 }else{
cannam@86 136 decay=filters->nearDC_acc+=temp;
cannam@86 137 filters->nearDC_partialacc+=temp;
cannam@86 138 }
cannam@86 139 filters->nearDC_acc-=filters->nearDC[ptr];
cannam@86 140 filters->nearDC[ptr]=temp;
cannam@86 141
cannam@86 142 decay*=(1./(VE_NEARDC+1));
cannam@86 143 filters->nearptr++;
cannam@86 144 if(filters->nearptr>=VE_NEARDC)filters->nearptr=0;
cannam@86 145 decay=todB(&decay)*.5-15.f;
cannam@86 146 }
cannam@86 147
cannam@86 148 /* perform spreading and limiting, also smooth the spectrum. yes,
cannam@86 149 the MDCT results in all real coefficients, but it still *behaves*
cannam@86 150 like real/imaginary pairs */
cannam@86 151 for(i=0;i<n/2;i+=2){
cannam@86 152 float val=vec[i]*vec[i]+vec[i+1]*vec[i+1];
cannam@86 153 val=todB(&val)*.5f;
cannam@86 154 if(val<decay)val=decay;
cannam@86 155 if(val<minV)val=minV;
cannam@86 156 vec[i>>1]=val;
cannam@86 157 decay-=8.;
cannam@86 158 }
cannam@86 159
cannam@86 160 /*_analysis_output_always("spread",seq2++,vec,n/4,0,0,0);*/
cannam@86 161
cannam@86 162 /* perform preecho/postecho triggering by band */
cannam@86 163 for(j=0;j<VE_BANDS;j++){
cannam@86 164 float acc=0.;
cannam@86 165 float valmax,valmin;
cannam@86 166
cannam@86 167 /* accumulate amplitude */
cannam@86 168 for(i=0;i<bands[j].end;i++)
cannam@86 169 acc+=vec[i+bands[j].begin]*bands[j].window[i];
cannam@86 170
cannam@86 171 acc*=bands[j].total;
cannam@86 172
cannam@86 173 /* convert amplitude to delta */
cannam@86 174 {
cannam@86 175 int p,this=filters[j].ampptr;
cannam@86 176 float postmax,postmin,premax=-99999.f,premin=99999.f;
cannam@86 177
cannam@86 178 p=this;
cannam@86 179 p--;
cannam@86 180 if(p<0)p+=VE_AMP;
cannam@86 181 postmax=max(acc,filters[j].ampbuf[p]);
cannam@86 182 postmin=min(acc,filters[j].ampbuf[p]);
cannam@86 183
cannam@86 184 for(i=0;i<stretch;i++){
cannam@86 185 p--;
cannam@86 186 if(p<0)p+=VE_AMP;
cannam@86 187 premax=max(premax,filters[j].ampbuf[p]);
cannam@86 188 premin=min(premin,filters[j].ampbuf[p]);
cannam@86 189 }
cannam@86 190
cannam@86 191 valmin=postmin-premin;
cannam@86 192 valmax=postmax-premax;
cannam@86 193
cannam@86 194 /*filters[j].markers[pos]=valmax;*/
cannam@86 195 filters[j].ampbuf[this]=acc;
cannam@86 196 filters[j].ampptr++;
cannam@86 197 if(filters[j].ampptr>=VE_AMP)filters[j].ampptr=0;
cannam@86 198 }
cannam@86 199
cannam@86 200 /* look at min/max, decide trigger */
cannam@86 201 if(valmax>gi->preecho_thresh[j]+penalty){
cannam@86 202 ret|=1;
cannam@86 203 ret|=4;
cannam@86 204 }
cannam@86 205 if(valmin<gi->postecho_thresh[j]-penalty)ret|=2;
cannam@86 206 }
cannam@86 207
cannam@86 208 return(ret);
cannam@86 209 }
cannam@86 210
cannam@86 211 #if 0
cannam@86 212 static int seq=0;
cannam@86 213 static ogg_int64_t totalshift=-1024;
cannam@86 214 #endif
cannam@86 215
cannam@86 216 long _ve_envelope_search(vorbis_dsp_state *v){
cannam@86 217 vorbis_info *vi=v->vi;
cannam@86 218 codec_setup_info *ci=vi->codec_setup;
cannam@86 219 vorbis_info_psy_global *gi=&ci->psy_g_param;
cannam@86 220 envelope_lookup *ve=((private_state *)(v->backend_state))->ve;
cannam@86 221 long i,j;
cannam@86 222
cannam@86 223 int first=ve->current/ve->searchstep;
cannam@86 224 int last=v->pcm_current/ve->searchstep-VE_WIN;
cannam@86 225 if(first<0)first=0;
cannam@86 226
cannam@86 227 /* make sure we have enough storage to match the PCM */
cannam@86 228 if(last+VE_WIN+VE_POST>ve->storage){
cannam@86 229 ve->storage=last+VE_WIN+VE_POST; /* be sure */
cannam@86 230 ve->mark=_ogg_realloc(ve->mark,ve->storage*sizeof(*ve->mark));
cannam@86 231 }
cannam@86 232
cannam@86 233 for(j=first;j<last;j++){
cannam@86 234 int ret=0;
cannam@86 235
cannam@86 236 ve->stretch++;
cannam@86 237 if(ve->stretch>VE_MAXSTRETCH*2)
cannam@86 238 ve->stretch=VE_MAXSTRETCH*2;
cannam@86 239
cannam@86 240 for(i=0;i<ve->ch;i++){
cannam@86 241 float *pcm=v->pcm[i]+ve->searchstep*(j);
cannam@86 242 ret|=_ve_amp(ve,gi,pcm,ve->band,ve->filter+i*VE_BANDS);
cannam@86 243 }
cannam@86 244
cannam@86 245 ve->mark[j+VE_POST]=0;
cannam@86 246 if(ret&1){
cannam@86 247 ve->mark[j]=1;
cannam@86 248 ve->mark[j+1]=1;
cannam@86 249 }
cannam@86 250
cannam@86 251 if(ret&2){
cannam@86 252 ve->mark[j]=1;
cannam@86 253 if(j>0)ve->mark[j-1]=1;
cannam@86 254 }
cannam@86 255
cannam@86 256 if(ret&4)ve->stretch=-1;
cannam@86 257 }
cannam@86 258
cannam@86 259 ve->current=last*ve->searchstep;
cannam@86 260
cannam@86 261 {
cannam@86 262 long centerW=v->centerW;
cannam@86 263 long testW=
cannam@86 264 centerW+
cannam@86 265 ci->blocksizes[v->W]/4+
cannam@86 266 ci->blocksizes[1]/2+
cannam@86 267 ci->blocksizes[0]/4;
cannam@86 268
cannam@86 269 j=ve->cursor;
cannam@86 270
cannam@86 271 while(j<ve->current-(ve->searchstep)){/* account for postecho
cannam@86 272 working back one window */
cannam@86 273 if(j>=testW)return(1);
cannam@86 274
cannam@86 275 ve->cursor=j;
cannam@86 276
cannam@86 277 if(ve->mark[j/ve->searchstep]){
cannam@86 278 if(j>centerW){
cannam@86 279
cannam@86 280 #if 0
cannam@86 281 if(j>ve->curmark){
cannam@86 282 float *marker=alloca(v->pcm_current*sizeof(*marker));
cannam@86 283 int l,m;
cannam@86 284 memset(marker,0,sizeof(*marker)*v->pcm_current);
cannam@86 285 fprintf(stderr,"mark! seq=%d, cursor:%fs time:%fs\n",
cannam@86 286 seq,
cannam@86 287 (totalshift+ve->cursor)/44100.,
cannam@86 288 (totalshift+j)/44100.);
cannam@86 289 _analysis_output_always("pcmL",seq,v->pcm[0],v->pcm_current,0,0,totalshift);
cannam@86 290 _analysis_output_always("pcmR",seq,v->pcm[1],v->pcm_current,0,0,totalshift);
cannam@86 291
cannam@86 292 _analysis_output_always("markL",seq,v->pcm[0],j,0,0,totalshift);
cannam@86 293 _analysis_output_always("markR",seq,v->pcm[1],j,0,0,totalshift);
cannam@86 294
cannam@86 295 for(m=0;m<VE_BANDS;m++){
cannam@86 296 char buf[80];
cannam@86 297 sprintf(buf,"delL%d",m);
cannam@86 298 for(l=0;l<last;l++)marker[l*ve->searchstep]=ve->filter[m].markers[l]*.1;
cannam@86 299 _analysis_output_always(buf,seq,marker,v->pcm_current,0,0,totalshift);
cannam@86 300 }
cannam@86 301
cannam@86 302 for(m=0;m<VE_BANDS;m++){
cannam@86 303 char buf[80];
cannam@86 304 sprintf(buf,"delR%d",m);
cannam@86 305 for(l=0;l<last;l++)marker[l*ve->searchstep]=ve->filter[m+VE_BANDS].markers[l]*.1;
cannam@86 306 _analysis_output_always(buf,seq,marker,v->pcm_current,0,0,totalshift);
cannam@86 307 }
cannam@86 308
cannam@86 309 for(l=0;l<last;l++)marker[l*ve->searchstep]=ve->mark[l]*.4;
cannam@86 310 _analysis_output_always("mark",seq,marker,v->pcm_current,0,0,totalshift);
cannam@86 311
cannam@86 312
cannam@86 313 seq++;
cannam@86 314
cannam@86 315 }
cannam@86 316 #endif
cannam@86 317
cannam@86 318 ve->curmark=j;
cannam@86 319 if(j>=testW)return(1);
cannam@86 320 return(0);
cannam@86 321 }
cannam@86 322 }
cannam@86 323 j+=ve->searchstep;
cannam@86 324 }
cannam@86 325 }
cannam@86 326
cannam@86 327 return(-1);
cannam@86 328 }
cannam@86 329
cannam@86 330 int _ve_envelope_mark(vorbis_dsp_state *v){
cannam@86 331 envelope_lookup *ve=((private_state *)(v->backend_state))->ve;
cannam@86 332 vorbis_info *vi=v->vi;
cannam@86 333 codec_setup_info *ci=vi->codec_setup;
cannam@86 334 long centerW=v->centerW;
cannam@86 335 long beginW=centerW-ci->blocksizes[v->W]/4;
cannam@86 336 long endW=centerW+ci->blocksizes[v->W]/4;
cannam@86 337 if(v->W){
cannam@86 338 beginW-=ci->blocksizes[v->lW]/4;
cannam@86 339 endW+=ci->blocksizes[v->nW]/4;
cannam@86 340 }else{
cannam@86 341 beginW-=ci->blocksizes[0]/4;
cannam@86 342 endW+=ci->blocksizes[0]/4;
cannam@86 343 }
cannam@86 344
cannam@86 345 if(ve->curmark>=beginW && ve->curmark<endW)return(1);
cannam@86 346 {
cannam@86 347 long first=beginW/ve->searchstep;
cannam@86 348 long last=endW/ve->searchstep;
cannam@86 349 long i;
cannam@86 350 for(i=first;i<last;i++)
cannam@86 351 if(ve->mark[i])return(1);
cannam@86 352 }
cannam@86 353 return(0);
cannam@86 354 }
cannam@86 355
cannam@86 356 void _ve_envelope_shift(envelope_lookup *e,long shift){
cannam@86 357 int smallsize=e->current/e->searchstep+VE_POST; /* adjust for placing marks
cannam@86 358 ahead of ve->current */
cannam@86 359 int smallshift=shift/e->searchstep;
cannam@86 360
cannam@86 361 memmove(e->mark,e->mark+smallshift,(smallsize-smallshift)*sizeof(*e->mark));
cannam@86 362
cannam@86 363 #if 0
cannam@86 364 for(i=0;i<VE_BANDS*e->ch;i++)
cannam@86 365 memmove(e->filter[i].markers,
cannam@86 366 e->filter[i].markers+smallshift,
cannam@86 367 (1024-smallshift)*sizeof(*(*e->filter).markers));
cannam@86 368 totalshift+=shift;
cannam@86 369 #endif
cannam@86 370
cannam@86 371 e->current-=shift;
cannam@86 372 if(e->curmark>=0)
cannam@86 373 e->curmark-=shift;
cannam@86 374 e->cursor-=shift;
cannam@86 375 }