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: simple utility that runs audio through the psychoacoustics
15 last mod: $Id: psytune.c,v 1.15 2001/05/27 06:44:00 xiphmont Exp $
17 ********************************************************************/
24 #include "vorbis/codec.h"
34 static vorbis_info_psy _psy_set0={
43 /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 */
44 /* x: 63 88 125 175 250 350 500 700 1k 1.4k 2k 2.8k 4k 5.6k 8k 11.5k 16k Hz */
45 /* y: 0 10 20 30 40 50 60 70 80 90 100 dB */
47 /* 0 10 20 30 40 50 60 70 80 90 100 */
49 {-999.f,-999.f,-999.f,-999.f,-999.f,-999.f,-999.f,-999.f,-999.f,-999.f,-999.f}, /*63*/
50 {-999.f,-999.f,-999.f,-999.f,-999.f,-999.f,-999.f,-999.f,-999.f,-999.f,-999.f}, /*88*/
51 {-999.f,-999.f,-999.f,-999.f,-999.f,-999.f,-999.f,-999.f,-999.f,-999.f,-999.f}, /*125*/
53 {-35.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*175*/
54 {-35.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*250*/
55 {-35.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*350*/
56 {-35.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*500*/
57 {-35.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*700*/
59 {-35.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*1000*/
60 {-35.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*1400*/
61 {-40.f,-40.f,-40.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*2000*/
62 {-40.f,-40.f,-40.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*2800*/
63 {-35.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*4000*/
64 {-35.f,-35.f,-35.f,-40.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*5600*/
66 {-30.f,-30.f,-33.f,-35.f,-40.f,-50.f,-60.f,-70.f,-80.f,-90.f,-100.f}, /*8000*/
67 {-30.f,-30.f,-33.f,-35.f,-35.f,-45.f,-50.f,-60.f,-70.f,-90.f,-100.f}, /*11500*/
68 {-24.f,-24.f,-26.f,-32.f,-32.f,-42.f,-50.f,-60.f,-70.f,-90.f,-100.f}, /*16000*/
73 {{-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-24.f,-24.f,-24.f},/*63*/
74 {-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-24.f,-24.f,-24.f},/*88*/
75 {-14.f,-16.f,-18.f,-19.f,-20.f,-21.f,-22.f,-22.f,-24.f,-24.f,-24.f},/*125*/
76 {-10.f,-10.f,-10.f,-10.f,-16.f,-16.f,-18.f,-20.f,-24.f,-24.f,-24.f},/*175*/
77 {-10.f,-10.f,-10.f,-10.f,-16.f,-16.f,-18.f,-20.f,-24.f,-24.f,-24.f},/*250*/
78 {-10.f,-10.f,-10.f,-10.f,-16.f,-16.f,-18.f,-20.f,-22.f,-24.f,-24.f},/*350*/
79 {-10.f,-10.f,-10.f,-10.f,-16.f,-16.f,-18.f,-20.f,-22.f,-24.f,-24.f},/*500*/
80 {-10.f,-10.f,-10.f,-10.f,-14.f,-14.f,-16.f,-20.f,-22.f,-24.f,-24.f},/*700*/
81 {-10.f,-10.f,-10.f,-10.f,-14.f,-14.f,-16.f,-20.f,-22.f,-24.f,-24.f},/*1000*/
82 {-10.f,-10.f,-10.f,-10.f,-14.f,-14.f,-16.f,-20.f,-22.f,-24.f,-24.f},/*1400*/
83 {-10.f,-10.f,-10.f,-10.f,-14.f,-14.f,-16.f,-20.f,-22.f,-24.f,-24.f},/*2000*/
84 {-10.f,-10.f,-10.f,-12.f,-16.f,-16.f,-16.f,-20.f,-22.f,-24.f,-24.f},/*2400*/
85 {-10.f,-10.f,-10.f,-12.f,-16.f,-16.f,-16.f,-20.f,-22.f,-24.f,-24.f},/*4000*/
86 {-10.f,-10.f,-10.f,-12.f,-12.f,-14.f,-16.f,-18.f,-22.f,-24.f,-24.f},/*5600*/
87 {-10.f,-10.f,-10.f,-10.f,-10.f,-14.f,-16.f,-18.f,-22.f,-24.f,-24.f},/*8000*/
88 {-10.f,-10.f,-10.f,-10.f,-10.f,-14.f,-16.f,-18.f,-22.f,-24.f,-24.f},/*11500*/
89 {-10.f,-10.f,-10.f,-10.f,-10.f,-12.f,-16.f,-18.f,-22.f,-24.f,-24.f},/*16000*/
93 -24.f, /* suppress any noise curve over maxspec+n */
95 .5f, /* high window */
113 .900f, 0.f, /*11500*/
114 .900f, 1.f, /*16000*/
117 95.f, /* even decade + 5 is important; saves an rint() later in a
124 void analysis(char *base,int i,float *v,int n,int bark,int dB){
129 sprintf(buffer,"%s_%d.m",base,i);
130 of=fopen(buffer,"w");
137 fprintf(of,"%g ",toBARK(22050.f*j/n));
139 fprintf(of,"%g ",(float)j);
142 fprintf(of,"%g\n",todB(fabs(v+j)));
144 fprintf(of,"%g\n",v[j]);
154 /****************************************************************/
156 int main(int argc,char *argv[]){
161 float ampmax=-9999,newmax;
166 float ampmax_att_per_sec=-10.;
168 float *pcm[2],*out[2],*window,*lpc,*flr,*mask;
169 signed char *buffer,*buffer2;
173 vorbis_look_psy p_look;
187 order=atoi(argv[0]+2);
199 order=atoi(argv[0]+2);
205 framesize=atoi(argv[0]);
209 mask=_ogg_malloc(framesize*sizeof(float));
210 pcm[0]=_ogg_malloc(framesize*sizeof(float));
211 pcm[1]=_ogg_malloc(framesize*sizeof(float));
212 out[0]=_ogg_calloc(framesize/2,sizeof(float));
213 out[1]=_ogg_calloc(framesize/2,sizeof(float));
214 flr=_ogg_malloc(framesize*sizeof(float));
215 lpc=_ogg_malloc(order*sizeof(float));
216 buffer=_ogg_malloc(framesize*4);
217 buffer2=buffer+framesize*2;
218 window=_vorbis_window(0,framesize,framesize/2,framesize/2);
219 mdct_init(&m_look,framesize);
220 drft_init(&f_look,framesize);
221 drft_init(&f_look2,framesize/2);
222 _vp_psy_init(&p_look,&_psy_set0,framesize/2,44100);
224 for(i=0;i<P_BANDS;i++)
225 for(j=0;j<P_LEVELS;j++)
226 analysis("Ptonecurve",i*100+j,p_look.tonecurves[i][j],EHMER_MAX,0,0);
228 /* we cheat on the WAV header; we just bypass 44 bytes and never
229 verify that it matches 16bit/stereo/44.1kHz. */
231 fread(buffer,1,44,stdin);
232 fwrite(buffer,1,44,stdout);
233 memset(buffer,0,framesize*2);
235 analysis("window",0,window,framesize,0,0);
237 fprintf(stderr,"Processing for frame size %d...\n",framesize);
240 long bytes=fread(buffer2,1,framesize*2,stdin);
241 if(bytes<framesize*2)
242 memset(buffer2+bytes,0,framesize*2-bytes);
246 /* uninterleave samples */
247 for(i=0;i<framesize;i++){
248 pcm[0][i]=((buffer[i*4+1]<<8)|
249 (0x00ff&(int)buffer[i*4]))/32768.f;
250 pcm[1][i]=((buffer[i*4+3]<<8)|
251 (0x00ff&(int)buffer[i*4+2]))/32768.f;
255 float secs=framesize/44100.;
257 ampmax+=secs*ampmax_att_per_sec;
258 if(ampmax<-9999)ampmax=-9999;
265 analysis("pre",frameno,pcm[i],framesize,0,0);
266 memcpy(mask,pcm[i],sizeof(float)*framesize);
268 /* do the psychacoustics */
269 for(j=0;j<framesize;j++)
270 mask[j]=pcm[i][j]*=window[j];
272 drft_forward(&f_look,mask);
274 mask[0]/=(framesize/4.);
275 for(j=1;j<framesize-1;j+=2)
276 mask[(j+1)>>1]=4*hypot(mask[j],mask[j+1])/framesize;
278 mdct_forward(&m_look,pcm[i],pcm[i]);
279 memcpy(mask+framesize/2,pcm[i],sizeof(float)*framesize/2);
280 analysis("mdct",frameno,pcm[i],framesize/2,0,1);
281 analysis("fft",frameno,mask,framesize/2,0,1);
285 ret=_vp_compute_mask(&p_look,mask,mask+framesize/2,flr,NULL,ampmax);
286 if(ret>newmax)newmax=ret;
289 analysis("mask",frameno,flr,framesize/2,0,0);
291 mask[framesize-1]=0.;
293 for(j=1;j<framesize-1;j+=2){
294 mask[j]=todB(pcm[i]+((j+1)>>1));
298 analysis("lfft",frameno,mask,framesize,0,0);
299 drft_backward(&f_look,mask);
301 analysis("cep",frameno,mask,framesize,0,0);
302 analysis("logcep",frameno,mask,framesize,0,1);
306 /*for(j=0;j<framesize/2;j++){
307 float val=fromdB(flr[j]);
308 int p=rint(pcm[i][j]/val);
312 /*for(j=0;j<framesize/2;j++){
313 float val=todB(pcm[i]+j);
318 for(j=0;j<framesize/2;j++){
319 float val=rint(todB(pcm[i]+j)/6);
321 pcm[i][j]=fromdB(val*6);
323 pcm[i][j]=-fromdB(val*6);
327 analysis("final",frameno,pcm[i],framesize/2,0,1);
329 /* take it back to time */
330 mdct_backward(&m_look,pcm[i],pcm[i]);
331 for(j=0;j<framesize/2;j++)
332 out[i][j]+=pcm[i][j]*window[j];
338 /* write data. Use the part of buffer we're about to shift out */
340 char *ptr=buffer+i*2;
342 for(j=0;j<framesize/2;j++){
343 int val=mono[j]*32767.;
344 /* might as well guard against clipping */
345 if(val>32767)val=32767;
346 if(val<-32768)val=-32768;
348 ptr[1]=(val>>8)&0xff;
354 fwrite(buffer,1,framesize*2,stdout);
355 memmove(buffer,buffer2,framesize*2);
358 for(j=0,k=framesize/2;j<framesize/2;j++,k++)
359 out[i][j]=pcm[i][k]*window[k];
364 fprintf(stderr,"average raw bits of entropy: %.03g/sample\n",acc/tot);
365 fprintf(stderr,"average nonzero samples: %.03g/%d\n",nonz/tot*framesize/2,
367 fprintf(stderr,"Done\n\n");