envelope.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  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: PCM data envelope analysis and manipulation
  14. last mod: $Id: envelope.c,v 1.19.2.1 2000/06/23 08:36:36 xiphmont Exp $
  15. Preecho calculation.
  16. ********************************************************************/
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #include <stdio.h>
  20. #include <math.h>
  21. #include "vorbis/codec.h"
  22. #include "os.h"
  23. #include "scales.h"
  24. #include "smallft.h"
  25. #include "envelope.h"
  26. #include "bitwise.h"
  27. #include "window.h"
  28. #include "misc.h"
  29. void _ve_envelope_init(envelope_lookup *e,int samples_per){
  30. int i;
  31. e->winlen=samples_per*2;
  32. e->window=malloc(e->winlen*sizeof(double));
  33. e->fft=calloc(1,sizeof(drft_lookup));
  34. drft_init(e->fft,samples_per*2);
  35. /* We just use a straight sin(x) window for this */
  36. for(i=0;i<e->winlen;i++)
  37. e->window[i]=sin((i+.5)/e->winlen*M_PI);
  38. }
  39. void _ve_envelope_clear(envelope_lookup *e){
  40. drft_clear(e->fft);
  41. free(e->fft);
  42. if(e->window)free(e->window);
  43. memset(e,0,sizeof(envelope_lookup));
  44. }
  45. static void smooth_noise(long n,double *f,double *noise){
  46. long i;
  47. long lo=0,hi=0;
  48. double acc=0.;
  49. for(i=0;i<n;i++){
  50. /* not exactly correct, (the center frequency should be centered
  51. on a *log* scale), but not worth quibbling */
  52. long newhi=i*1.0442718740+5;
  53. long newlo=i*.8781245150-5;
  54. if(newhi>n)newhi=n;
  55. for(;lo<newlo;lo++)
  56. acc-=todB(f[lo]); /* yeah, this ain't RMS */
  57. for(;hi<newhi;hi++)
  58. acc+=todB(f[hi]);
  59. noise[i]=acc/(hi-lo);
  60. }
  61. }
  62. /* use FFT for spectral power estimation */
  63. static int frameno=0;
  64. static int frameno2=0;
  65. static void _ve_deltas(double *deltas,double *pcm,int n,double *window,
  66. int samples_per,drft_lookup *l){
  67. int i,j;
  68. double *out=alloca(sizeof(double)*samples_per*2);
  69. double *cache=alloca(sizeof(double)*samples_per*2);
  70. for(j=-1;j<n;j++){
  71. memcpy(out,pcm+(j+1)*samples_per,samples_per*2*sizeof(double));
  72. for(i=0;i<samples_per*2;i++)
  73. out[i]*=window[i];
  74. _analysis_output("Dpcm",frameno*1000+frameno2,out,samples_per*2,0,0);
  75. drft_forward(l,out);
  76. for(i=1;i<samples_per;i++)
  77. out[i]=hypot(out[i*2],out[i*2-1]);
  78. _analysis_output("Dfft",frameno*1000+frameno2,out,samples_per,0,1);
  79. smooth_noise(samples_per,out,out+samples_per);
  80. if(j==-1){
  81. for(i=samples_per/10;i<samples_per;i++)
  82. cache[i]=out[i+samples_per];
  83. }else{
  84. double max=0;
  85. _analysis_output("Dcache",frameno*1000+frameno2,cache,samples_per,0,0);
  86. for(i=samples_per/10;i<samples_per;i++){
  87. double val=fabs(out[i+samples_per]-cache[i]);
  88. cache[i]=out[i+samples_per];
  89. max+=val;
  90. }
  91. max/=samples_per;
  92. if(deltas[j]<max)deltas[j]=max;
  93. }
  94. _analysis_output("Dnoise",frameno*1000+frameno2++,out+samples_per,samples_per,0,0);
  95. }
  96. }
  97. void _ve_envelope_deltas(vorbis_dsp_state *v){
  98. vorbis_info *vi=v->vi;
  99. int step=vi->envelopesa;
  100. int dtotal=v->pcm_current/vi->envelopesa-1;
  101. int dcurr=v->envelope_current;
  102. int pch;
  103. if(dtotal>dcurr){
  104. double *mult=v->multipliers+dcurr;
  105. memset(mult,0,sizeof(double)*(dtotal-dcurr));
  106. for(pch=0;pch<vi->channels;pch++){
  107. double *pcm=v->pcm[pch]+(dcurr-1)*step;
  108. _ve_deltas(mult,pcm,dtotal-dcurr,v->ve.window,step,v->ve.fft);
  109. {
  110. double *multexp=alloca(sizeof(double)*v->pcm_current);
  111. int i,j,k;
  112. memset(multexp,0,sizeof(double)*v->pcm_current);
  113. j=0;
  114. for(i=0;i<dtotal;i++)
  115. for(k=0;k<step;k++)
  116. multexp[j++]=v->multipliers[i];
  117. _analysis_output("Apcm",frameno,v->pcm[pch],v->pcm_current,0,0);
  118. _analysis_output("Amult",frameno++,multexp,v->pcm_current,0,0);
  119. }
  120. }
  121. v->envelope_current=dtotal;
  122. }
  123. }