psytune.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  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. function: simple utility that runs audio through the psychoacoustics
  14. without encoding
  15. last mod: $Id: psytune.c,v 1.3.2.1 2000/05/24 21:17:02 xiphmont Exp $
  16. ********************************************************************/
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include <math.h>
  21. #include "vorbis/codec.h"
  22. #include "os.h"
  23. #include "psy.h"
  24. #include "mdct.h"
  25. #include "window.h"
  26. #include "scales.h"
  27. #include "lpc.h"
  28. static vorbis_info_psy _psy_set0={
  29. 1,/*athp*/
  30. 1,/*decayp*/
  31. 1,/*smoothp*/
  32. 0,8,0.,
  33. -130.,
  34. 1,/* tonemaskp */
  35. {-80.,-80.,-80.,-80.,-100.}, /* remember that el 0,2 is a 80 dB curve */
  36. {-35.,-40.,-60.,-80.,-80.}, /* remember that el 4 is an 80 dB curve, not 100 */
  37. {-35.,-40.,-60.,-80.,-100.},
  38. {-35.,-40.,-60.,-80.,-100.},
  39. {-35.,-40.,-60.,-80.,-100.},
  40. {-35.,-40.,-60.,-80.,-100.},
  41. {-35.,-40.,-60.,-80.,-100.},
  42. 1,/* peakattp */
  43. {-12.,-12.,-12.,-16.,-18.},
  44. {-12.,-12.,-12.,-16.,-18.},
  45. {-12.,-12.,-12.,-16.,-18.},
  46. {-12.,-12.,-12.,-16.,-18.},
  47. {-12.,-12.,-12.,-16.,-18.},
  48. {-8.,-10.,-12.,-16.,-18.},
  49. {-6.,-8.,-10.,-12.,-12.},
  50. 1,/*noisemaskp */
  51. {-100.,-100.,-100.,-200.,-200.},
  52. {-100.,-100.,-100.,-200.,-200.},
  53. {-100.,-100.,-100.,-200.,-200.},
  54. {-60.,-60.,-60.,-80.,-80.},
  55. {-60.,-60.,-60.,-80.,-80.},
  56. {-60.,-60.,-60.,-80.,-80.},
  57. {-55.,-55.,-60.,-80.,-80.},
  58. 100.,
  59. .9998, .9999 /* attack/decay control */
  60. };
  61. static int noisy=0;
  62. void analysis(char *base,int i,double *v,int n,int bark,int dB){
  63. if(noisy){
  64. int j;
  65. FILE *of;
  66. char buffer[80];
  67. sprintf(buffer,"%s_%d.m",base,i);
  68. of=fopen(buffer,"w");
  69. for(j=0;j<n;j++){
  70. if(dB && v[j]==0)
  71. fprintf(of,"\n\n");
  72. else{
  73. if(bark)
  74. fprintf(of,"%g ",toBARK(22050.*j/n));
  75. else
  76. fprintf(of,"%g ",(double)j);
  77. if(dB){
  78. fprintf(of,"%g\n",todB(fabs(v[j])));
  79. }else{
  80. fprintf(of,"%g\n",v[j]);
  81. }
  82. }
  83. }
  84. fclose(of);
  85. }
  86. }
  87. typedef struct {
  88. long n;
  89. int ln;
  90. int m;
  91. int *linearmap;
  92. vorbis_info_floor0 *vi;
  93. lpc_lookup lpclook;
  94. } vorbis_look_floor0;
  95. extern double _curve_to_lpc(double *curve,double *lpc,vorbis_look_floor0 *l,
  96. long frameno);
  97. extern void _lpc_to_curve(double *curve,double *lpc,double amp,
  98. vorbis_look_floor0 *l,char *name,long frameno);
  99. long frameno=0;
  100. /* hacked from floor0.c */
  101. static void floorinit(vorbis_look_floor0 *look,int n,int m,int ln){
  102. int j;
  103. double scale;
  104. look->m=m;
  105. look->n=n;
  106. look->ln=ln;
  107. lpc_init(&look->lpclook,look->ln,look->m);
  108. scale=look->ln/toBARK(22050.);
  109. look->linearmap=malloc(look->n*sizeof(int));
  110. for(j=0;j<look->n;j++){
  111. int val=floor( toBARK(22050./n*j) *scale);
  112. if(val>look->ln)val=look->ln;
  113. look->linearmap[j]=val;
  114. }
  115. }
  116. int main(int argc,char *argv[]){
  117. int eos=0;
  118. double nonz=0.;
  119. double acc=0.;
  120. double tot=0.;
  121. int framesize=2048;
  122. int order=32;
  123. int map=256;
  124. double *pcm[2],*out[2],*window,*decay[2],*lpc,*floor;
  125. signed char *buffer,*buffer2;
  126. mdct_lookup m_look;
  127. vorbis_look_psy p_look;
  128. long i,j,k;
  129. vorbis_look_floor0 floorlook;
  130. int ath=0;
  131. int decayp=0;
  132. argv++;
  133. while(*argv){
  134. if(*argv[0]=='-'){
  135. /* option */
  136. if(argv[0][1]=='v'){
  137. noisy=0;
  138. }
  139. if(argv[0][1]=='A'){
  140. ath=0;
  141. }
  142. if(argv[0][1]=='D'){
  143. decayp=0;
  144. }
  145. if(argv[0][1]=='X'){
  146. ath=0;
  147. decayp=0;
  148. }
  149. }else
  150. if(*argv[0]=='+'){
  151. /* option */
  152. if(argv[0][1]=='v'){
  153. noisy=1;
  154. }
  155. if(argv[0][1]=='A'){
  156. ath=1;
  157. }
  158. if(argv[0][1]=='D'){
  159. decayp=1;
  160. }
  161. if(argv[0][1]=='X'){
  162. ath=1;
  163. decayp=1;
  164. }
  165. }else
  166. framesize=atoi(argv[0]);
  167. argv++;
  168. }
  169. pcm[0]=malloc(framesize*sizeof(double));
  170. pcm[1]=malloc(framesize*sizeof(double));
  171. out[0]=calloc(framesize/2,sizeof(double));
  172. out[1]=calloc(framesize/2,sizeof(double));
  173. decay[0]=calloc(framesize/2,sizeof(double));
  174. decay[1]=calloc(framesize/2,sizeof(double));
  175. floor=malloc(framesize*sizeof(double));
  176. lpc=malloc(order*sizeof(double));
  177. buffer=malloc(framesize*4);
  178. buffer2=buffer+framesize*2;
  179. window=_vorbis_window(0,framesize,framesize/2,framesize/2);
  180. mdct_init(&m_look,framesize);
  181. _vp_psy_init(&p_look,&_psy_set0,framesize/2,44100);
  182. floorinit(&floorlook,framesize/2,order,map);
  183. for(i=0;i<13;i++)
  184. for(j=0;j<9;j++)
  185. analysis("Ptonecurve",i*10+j,p_look.tonecurves[i][j],EHMER_MAX,0,1);
  186. for(i=0;i<13;i++)
  187. for(j=0;j<9;j++)
  188. analysis("Pnoisecurve",i*10+j,p_look.noisecurves[i][j],EHMER_MAX,0,1);
  189. /* we cheat on the WAV header; we just bypass 44 bytes and never
  190. verify that it matches 16bit/stereo/44.1kHz. */
  191. fread(buffer,1,44,stdin);
  192. fwrite(buffer,1,44,stdout);
  193. memset(buffer,0,framesize*2);
  194. analysis("window",0,window,framesize,0,0);
  195. fprintf(stderr,"Processing for frame size %d...\n",framesize);
  196. while(!eos){
  197. long bytes=fread(buffer2,1,framesize*2,stdin);
  198. if(bytes<framesize*2)
  199. memset(buffer2+bytes,0,framesize*2-bytes);
  200. if(bytes!=0){
  201. /* uninterleave samples */
  202. for(i=0;i<framesize;i++){
  203. pcm[0][i]=((buffer[i*4+1]<<8)|
  204. (0x00ff&(int)buffer[i*4]))/32768.;
  205. pcm[1][i]=((buffer[i*4+3]<<8)|
  206. (0x00ff&(int)buffer[i*4+2]))/32768.;
  207. }
  208. for(i=0;i<2;i++){
  209. double amp;
  210. analysis("pre",frameno,pcm[i],framesize,0,0);
  211. /* do the psychacoustics */
  212. for(j=0;j<framesize;j++)
  213. pcm[i][j]*=window[j];
  214. mdct_forward(&m_look,pcm[i],pcm[i]);
  215. analysis("mdct",frameno,pcm[i],framesize/2,1,1);
  216. _vp_compute_mask(&p_look,pcm[i],floor,decay[i]);
  217. analysis("prefloor",frameno,floor,framesize/2,1,1);
  218. analysis("decay",frameno,decay[i],framesize/2,1,1);
  219. for(j=0;j<framesize/2;j++)floor[j]=todB(floor[j])+150;
  220. amp=_curve_to_lpc(floor,lpc,&floorlook,frameno);
  221. _lpc_to_curve(floor,lpc,sqrt(amp),&floorlook,"Ffloor",frameno);
  222. for(j=0;j<framesize/2;j++)floor[j]=fromdB(floor[j]-150);
  223. analysis("floor",frameno,floor,framesize/2,1,1);
  224. _vp_apply_floor(&p_look,pcm[i],floor);
  225. analysis("quant",frameno,pcm[i],framesize/2,1,1);
  226. /* re-add floor */
  227. for(j=0;j<framesize/2;j++){
  228. double val=rint(pcm[i][j]);
  229. tot++;
  230. if(val){
  231. nonz++;
  232. acc+=log(fabs(val)*2.+1.)/log(2);
  233. pcm[i][j]=val*floor[j];
  234. }else{
  235. pcm[i][j]=0;
  236. }
  237. }
  238. analysis("final",frameno,pcm[i],framesize/2,1,1);
  239. /* take it back to time */
  240. mdct_backward(&m_look,pcm[i],pcm[i]);
  241. for(j=0;j<framesize/2;j++)
  242. out[i][j]+=pcm[i][j]*window[j];
  243. frameno++;
  244. }
  245. /* write data. Use the part of buffer we're about to shift out */
  246. for(i=0;i<2;i++){
  247. char *ptr=buffer+i*2;
  248. double *mono=out[i];
  249. for(j=0;j<framesize/2;j++){
  250. int val=mono[j]*32767.;
  251. /* might as well guard against clipping */
  252. if(val>32767)val=32767;
  253. if(val<-32768)val=-32768;
  254. ptr[0]=val&0xff;
  255. ptr[1]=(val>>8)&0xff;
  256. ptr+=4;
  257. }
  258. }
  259. fwrite(buffer,1,framesize*2,stdout);
  260. memmove(buffer,buffer2,framesize*2);
  261. for(i=0;i<2;i++){
  262. for(j=0,k=framesize/2;j<framesize/2;j++,k++)
  263. out[i][j]=pcm[i][k]*window[k];
  264. }
  265. }else
  266. eos=1;
  267. }
  268. fprintf(stderr,"average raw bits of entropy: %.03g/sample\n",acc/tot);
  269. fprintf(stderr,"average nonzero samples: %.03g/%d\n",nonz/tot*framesize/2,
  270. framesize/2);
  271. fprintf(stderr,"Done\n\n");
  272. return 0;
  273. }