envelope.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  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.21.2.2.2.2 2000/09/26 18:45:33 jack Exp $
  15. Preecho calculation.
  16. ********************************************************************/
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #include <stdio.h>
  20. #include <math.h>
  21. #include <ogg/ogg.h>
  22. #include "vorbis/codec.h"
  23. #include "os.h"
  24. #include "scales.h"
  25. #include "envelope.h"
  26. #include "misc.h"
  27. /* We use a Chebyshev bandbass for the preecho trigger bandpass; it's
  28. close enough for sample rates 32000-48000 Hz (corner frequencies at
  29. 6k/14k assuming sample rate of 44.1kHz) */
  30. /* Digital filter designed by mkfilter/mkshape/gencode A.J. Fisher
  31. Command line: /www/usr/fisher/helpers/mkfilter -Ch \
  32. -6.0000000000e+00 -Bp -o 5 -a 1.3605442177e-01 3.1746031746e-01 -l */
  33. #if 0
  34. static int cheb_bandpass_stages=10;
  35. static float cheb_bandpass_gain=5.589612458e+01;
  36. static float cheb_bandpass_B[]={-1.,0.,5.,0.,-10.,0.,10.,0.,-5.,0.,1};
  37. static float cheb_bandpass_A[]={
  38. -0.1917409386,
  39. 0.0078657069,
  40. -0.7126903444,
  41. 0.0266343467,
  42. -1.4047174730,
  43. 0.0466964232,
  44. -1.9032773429,
  45. 0.0451493360,
  46. -1.4471447397,
  47. 0.0303413711};
  48. #endif
  49. static int cheb_highpass_stages=10;
  50. static float cheb_highpass_gain= 5.291963434e+01;
  51. /* z^-stage, z^-stage+1... */
  52. static float cheb_highpass_B[]={1,-10,45,-120,210,-252,210,-120,45,-10,1};
  53. static float cheb_highpass_A[]={
  54. -0.1247628029,
  55. 0.1334086523,
  56. -0.3997715614,
  57. 0.3213011089,
  58. -1.1131924119,
  59. 1.7692446626,
  60. -3.6241199038,
  61. 4.1950871291,
  62. -4.2771757867,
  63. 2.3920318913};
  64. void _ve_envelope_init(envelope_lookup *e,vorbis_info *vi){
  65. int ch=vi->channels;
  66. int window=vi->envelopesa;
  67. int i;
  68. e->winlength=window;
  69. e->minenergy=fromdB(vi->preecho_minenergy);
  70. e->iir=calloc(ch,sizeof(IIR_state));
  71. e->filtered=calloc(ch,sizeof(float *));
  72. e->ch=ch;
  73. e->storage=128;
  74. for(i=0;i<ch;i++){
  75. IIR_init(e->iir+i,cheb_highpass_stages,cheb_highpass_gain,
  76. cheb_highpass_A,cheb_highpass_B);
  77. e->filtered[i]=calloc(e->storage,sizeof(float));
  78. }
  79. drft_init(&e->drft,window);
  80. e->window=malloc(e->winlength*sizeof(float));
  81. /* We just use a straight sin(x) window for this */
  82. for(i=0;i<e->winlength;i++)
  83. e->window[i]=sin((i+.5)/e->winlength*M_PI);
  84. }
  85. void _ve_envelope_clear(envelope_lookup *e){
  86. int i;
  87. for(i=0;i<e->ch;i++){
  88. IIR_clear((e->iir+i));
  89. free(e->filtered[i]);
  90. }
  91. drft_clear(&e->drft);
  92. free(e->window);
  93. free(e->filtered);
  94. memset(e,0,sizeof(envelope_lookup));
  95. }
  96. static float _ve_deltai(envelope_lookup *ve,IIR_state *iir,
  97. float *pre,float *post){
  98. long n2=ve->winlength*2;
  99. long n=ve->winlength;
  100. float *workA=alloca(sizeof(float)*n2),A=0.;
  101. float *workB=alloca(sizeof(float)*n2),B=0.;
  102. long i;
  103. /*_analysis_output("A",granulepos,pre,n,0,0);
  104. _analysis_output("B",granulepos,post,n,0,0);*/
  105. for(i=0;i<n;i++){
  106. workA[i]=pre[i]*ve->window[i];
  107. workB[i]=post[i]*ve->window[i];
  108. }
  109. /*_analysis_output("Awin",granulepos,workA,n,0,0);
  110. _analysis_output("Bwin",granulepos,workB,n,0,0);*/
  111. drft_forward(&ve->drft,workA);
  112. drft_forward(&ve->drft,workB);
  113. /* we want to have a 'minimum bar' for energy, else we're just
  114. basing blocks on quantization noise that outweighs the signal
  115. itself (for low power signals) */
  116. {
  117. float min=ve->minenergy;
  118. for(i=0;i<n;i++){
  119. if(fabs(workA[i])<min)workA[i]=min;
  120. if(fabs(workB[i])<min)workB[i]=min;
  121. }
  122. }
  123. /*_analysis_output("Afft",granulepos,workA,n,0,0);
  124. _analysis_output("Bfft",granulepos,workB,n,0,0);*/
  125. for(i=0;i<n;i++){
  126. A+=workA[i]*workA[i];
  127. B+=workB[i]*workB[i];
  128. }
  129. A=todB(A);
  130. B=todB(B);
  131. return(B-A);
  132. }
  133. long _ve_envelope_search(vorbis_dsp_state *v,long searchpoint){
  134. vorbis_info *vi=v->vi;
  135. envelope_lookup *ve=v->ve;
  136. long i,j;
  137. /* make sure we have enough storage to match the PCM */
  138. if(v->pcm_storage>ve->storage){
  139. ve->storage=v->pcm_storage;
  140. for(i=0;i<ve->ch;i++)
  141. ve->filtered[i]=realloc(ve->filtered[i],ve->storage*sizeof(float));
  142. }
  143. /* catch up the highpass to match the pcm */
  144. for(i=0;i<ve->ch;i++){
  145. float *filtered=ve->filtered[i];
  146. float *pcm=v->pcm[i];
  147. IIR_state *iir=ve->iir+i;
  148. for(j=ve->current;j<v->pcm_current;j++)
  149. filtered[j]=IIR_filter(iir,pcm[j]);
  150. }
  151. ve->current=v->pcm_current;
  152. /* Now search through our cached highpass data for breaking points */
  153. /* starting point */
  154. if(v->W)
  155. j=v->centerW+vi->blocksizes[1]/4-vi->blocksizes[0]/4;
  156. else
  157. j=v->centerW;
  158. while(j+ve->winlength<=v->pcm_current){
  159. for(i=0;i<ve->ch;i++){
  160. float *filtered=ve->filtered[i]+j;
  161. IIR_state *iir=ve->iir+i;
  162. float m=_ve_deltai(ve,iir,filtered-ve->winlength,filtered);
  163. if(m>vi->preecho_thresh){
  164. /*granulepos++;*/
  165. return(0);
  166. }
  167. /*granulepos++;*/
  168. }
  169. j+=vi->blocksizes[0]/2;
  170. if(j>=searchpoint)return(1);
  171. }
  172. return(-1);
  173. }
  174. void _ve_envelope_shift(envelope_lookup *e,long shift){
  175. int i;
  176. for(i=0;i<e->ch;i++)
  177. memmove(e->filtered[i],e->filtered[i]+shift,(e->current-shift)*
  178. sizeof(float));
  179. e->current-=shift;
  180. }