1 /********************************************************************
3 * THIS FILE IS PART OF THE Ogg Vorbis SOFTWARE CODEC SOURCE CODE. *
4 * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY *
5 * THE GNU PUBLIC LICENSE 2, WHICH IS INCLUDED WITH THIS SOURCE. *
6 * PLEASE READ THESE TERMS DISTRIBUTING. *
8 * THE OggSQUISH SOURCE CODE IS (C) COPYRIGHT 1994-2000 *
9 * by Monty <monty@xiph.org> and The XIPHOPHORUS Company *
10 * http://www.xiph.org/ *
12 ********************************************************************
14 function: PCM data envelope analysis and manipulation
15 last mod: $Id: envelope.c,v 1.19 2000/06/18 12:33:47 xiphmont Exp $
19 ********************************************************************/
25 #include "vorbis/codec.h"
35 void _ve_envelope_init(envelope_lookup *e,int samples_per){
37 e->winlen=samples_per*2;
38 e->window=malloc(e->winlen*sizeof(double));
40 e->fft=calloc(1,sizeof(drft_lookup));
41 drft_init(e->fft,samples_per*2);
43 /* We just use a straight sin(x) window for this */
44 for(i=0;i<e->winlen;i++)
45 e->window[i]=sin((i+.5)/e->winlen*M_PI);
48 void _ve_envelope_clear(envelope_lookup *e){
51 if(e->window)free(e->window);
52 memset(e,0,sizeof(envelope_lookup));
55 static void smooth_noise(long n,double *f,double *noise){
61 /* not exactly correct, (the center frequency should be centered
62 on a *log* scale), but not worth quibbling */
63 long newhi=i*1.0442718740+5;
64 long newlo=i*.8781245150-5;
68 acc-=todB(f[lo]); /* yeah, this ain't RMS */
75 /* use FFT for spectral power estimation */
77 static int frameno2=0;
79 static void _ve_deltas(double *deltas,double *pcm,int n,double *window,
80 int samples_per,drft_lookup *l){
82 double *out=alloca(sizeof(double)*samples_per*2);
83 double *cache=alloca(sizeof(double)*samples_per*2);
87 memcpy(out,pcm+(j+1)*samples_per,samples_per*2*sizeof(double));
88 for(i=0;i<samples_per*2;i++)
91 _analysis_output("Dpcm",frameno*1000+frameno2,out,samples_per*2,0,0);
95 for(i=1;i<samples_per;i++)
96 out[i]=hypot(out[i*2],out[i*2-1]);
97 _analysis_output("Dfft",frameno*1000+frameno2,out,samples_per,0,1);
98 smooth_noise(samples_per,out,out+samples_per);
101 for(i=samples_per/10;i<samples_per;i++)
102 cache[i]=out[i+samples_per];
105 _analysis_output("Dcache",frameno*1000+frameno2,cache,samples_per,0,0);
106 for(i=samples_per/10;i<samples_per;i++){
107 double val=out[i+samples_per]-cache[i];
108 cache[i]=out[i+samples_per];
112 if(deltas[j]<max)deltas[j]=max;
114 _analysis_output("Dnoise",frameno*1000+frameno2++,out+samples_per,samples_per,0,0);
118 void _ve_envelope_deltas(vorbis_dsp_state *v){
119 vorbis_info *vi=v->vi;
120 int step=vi->envelopesa;
122 int dtotal=v->pcm_current/vi->envelopesa-1;
123 int dcurr=v->envelope_current;
127 double *mult=v->multipliers+dcurr;
128 memset(mult,0,sizeof(double)*(dtotal-dcurr));
130 for(pch=0;pch<vi->channels;pch++){
131 double *pcm=v->pcm[pch]+(dcurr-1)*step;
132 _ve_deltas(mult,pcm,dtotal-dcurr,v->ve.window,step,v->ve.fft);
135 double *multexp=alloca(sizeof(double)*v->pcm_current);
138 memset(multexp,0,sizeof(double)*v->pcm_current);
140 for(i=0;i<dtotal;i++)
142 multexp[j++]=v->multipliers[i];
144 _analysis_output("Apcm",frameno,v->pcm[pch],v->pcm_current,0,0);
145 _analysis_output("Amult",frameno++,multexp,v->pcm_current,0,0);
149 v->envelope_current=dtotal;