Useful util while I beef up psychoacoustics.
[platform/upstream/libvorbis.git] / lib / psytune.c
1 /********************************************************************
2  *                                                                  *
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.                            *
7  *                                                                  *
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/                                             *
11  *                                                                  *
12  ********************************************************************
13
14  function: simple utility that runs audio through the psychoacoustics
15            without encoding
16  last mod: $Id: psytune.c,v 1.1 2000/02/25 11:05:32 xiphmont Exp $
17
18  ********************************************************************/
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <math.h>
24
25 #include "vorbis/codec.h"
26 #include "psy.h"
27 #include "mdct.h"
28 #include "window.h"
29
30 static vorbis_info_psy _psy_set0={
31   {-20, -20, -14, -14, -14, -14, -14, -14, -14, -14,
32    -14, -14, -16, -16, -16, -16, -18, -18, -16, -16,
33    -12, -10, -6, -3, -1, -1, -0}, 0., (.6/1024), 10,4
34 };
35
36 int main(int argc,char *argv[]){
37   int eos=0;
38   double acc=0.;
39   double tot=0.;
40   int framesize=argv[1]?atoi(argv[1]):2048;
41   double *pcm[2],*out[2],*window,*mask,*decay[2];
42   signed char *buffer,*buffer2;
43   mdct_lookup m_look;
44   vorbis_look_psy p_look;
45
46   pcm[0]=malloc(framesize*sizeof(double));
47   pcm[1]=malloc(framesize*sizeof(double));
48   out[0]=calloc(framesize/2,sizeof(double));
49   out[1]=calloc(framesize/2,sizeof(double));
50   decay[0]=calloc(framesize/2,sizeof(double));
51   decay[1]=calloc(framesize/2,sizeof(double));
52   mask=malloc(framesize/2*sizeof(double));
53   buffer=malloc(framesize*4);
54   buffer2=buffer+framesize*2;
55   window=_vorbis_window(0,framesize,framesize/2,framesize/2);
56   mdct_init(&m_look,framesize);
57   _vp_psy_init(&p_look,&_psy_set0,framesize/2,44100);
58
59   /* we cheat on the WAV header; we just bypass 44 bytes and never
60      verify that it matches 16bit/stereo/44.1kHz. */
61   
62   fread(buffer,1,44,stdin);
63   fwrite(buffer,1,44,stdout);
64   memset(buffer,0,framesize*2);
65
66   fprintf(stderr,"Processing for frame size %d...\n",framesize);
67
68   while(!eos){
69     long i,j,k;
70     long bytes=fread(buffer2,1,framesize*2,stdin); 
71     if(bytes<framesize*2)
72       memset(buffer2+bytes,0,framesize*2-bytes);
73     
74     if(bytes!=0){
75
76       /* uninterleave samples */
77       for(i=0;i<framesize;i++){
78         pcm[0][i]=((buffer[i*4+1]<<8)|
79                       (0x00ff&(int)buffer[i*4]))/32768.;
80         pcm[1][i]=((buffer[i*4+3]<<8)|
81                    (0x00ff&(int)buffer[i*4+2]))/32768.;
82       }
83       
84       for(i=0;i<2;i++){
85         for(j=0;j<framesize;j++)
86           pcm[i][j]*=window[j];
87
88         mdct_forward(&m_look,pcm[i],pcm[i]);
89
90         /* do the psychacoustics */
91
92         memset(mask,0,sizeof(double)*framesize/2);
93         _vp_mask_floor(&p_look,pcm[i],mask,decay[i],1);
94
95         /* quantize according to masking */
96         for(j=0;j<framesize/2;j++){
97           double val;
98           if(mask[j]==0)
99             val=0;
100           else
101             val=rint(pcm[i][j]/mask[j]);
102           acc+=log(fabs(val)*2.+1.)/log(2);
103           tot++;
104           pcm[i][j]=val*mask[j];
105         }
106
107         /* take it back to time */
108         mdct_backward(&m_look,pcm[i],pcm[i]);
109         for(j=0;j<framesize/2;j++)
110           out[i][j]+=pcm[i][j]*window[j];
111       }
112            
113       /* write data.  Use the part of buffer we're about to shift out */
114       for(i=0;i<2;i++){
115         char *ptr=buffer+i*2;
116         double  *mono=out[i];
117         for(j=0;j<framesize/2;j++){
118           int val=mono[j]*32767.;
119           /* might as well guard against clipping */
120           if(val>32767)val=32767;
121           if(val<-32768)val=-32768;
122           ptr[0]=val&0xff;
123           ptr[1]=(val>>8)&0xff;
124           ptr+=4;
125         }
126       }
127  
128       fwrite(buffer,1,framesize*2,stdout);
129       memmove(buffer,buffer2,framesize*2);
130
131       for(i=0;i<2;i++){
132         for(j=0,k=framesize/2;j<framesize/2;j++,k++)
133           out[i][j]=pcm[i][k]*window[k];
134       }
135     }else
136       eos=1;
137   }
138   fprintf(stderr,"average raw bits of entropy: %.03g/sample\n",acc/tot);
139   fprintf(stderr,"Done\n\n");
140   return 0;
141 }