envelope.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. /********************************************************************
  2. * *
  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. *
  7. * *
  8. * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2001 *
  9. * by the XIPHOPHORUS Company http://www.xiph.org/ *
  10. ********************************************************************
  11. function: PCM data envelope analysis and manipulation
  12. last mod: $Id: envelope.c,v 1.36 2001/05/27 06:43:59 xiphmont Exp $
  13. Preecho calculation.
  14. ********************************************************************/
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include <stdio.h>
  18. #include <math.h>
  19. #include <ogg/ogg.h>
  20. #include "vorbis/codec.h"
  21. #include "codec_internal.h"
  22. #include "os.h"
  23. #include "scales.h"
  24. #include "envelope.h"
  25. #include "misc.h"
  26. #include "iir.c" /* Yes, ugly, but needed for inlining */
  27. /* Digital filter designed by mkfilter/mkshape/gencode A.J. Fisher */
  28. static int cheb_highpass_stages=6;
  29. static float cheb_highpass_B[]={1.f,-6.f,15.f,-20.f,15.f,-6.f,1.f};
  30. static int cheb_bandpass_stages=6;
  31. static float cheb_bandpass_B[]={-1.f,0.f,3.f,0.f,-3.f,0.f,1.f};
  32. /* 10kHz Chebyshev highpass */
  33. static float cheb_highpass10k_gain= 54.34519586f;
  34. static float cheb_highpass10k_A[]={
  35. -0.2064797169f,
  36. -0.5609713214f,
  37. -1.1352465327f,
  38. -1.4495555418f,
  39. -1.7938140760f,
  40. -0.9473564683f};
  41. /* 6kHz-10kHz Chebyshev bandpass */
  42. static float cheb_bandpass6k_gain=113.4643935f;
  43. static float cheb_bandpass6k_A[]={
  44. -0.5712621337f,
  45. 1.5626130710f,
  46. -3.3348854983f,
  47. 4.0471340821f,
  48. -4.0051680331f,
  49. 2.2786325610f};
  50. /* 3kHz-6kHz Chebyshev bandpass */
  51. static float cheb_bandpass3k_gain= 248.8359377f;
  52. static float cheb_bandpass3k_A[]={
  53. -0.6564230022f,
  54. 3.3747911257f,
  55. -8.0098635981f,
  56. 11.0040876874f,
  57. -9.2250963484f,
  58. 4.4760355389f};
  59. /* 1.5kHz-3kHz Chebyshev bandpass */
  60. static float cheb_bandpass1k_gain= 1798.537183f;
  61. static float cheb_bandpass1k_A[]={
  62. -0.8097527363f,
  63. 4.7725742682f,
  64. -11.9800219408f,
  65. 16.3770336223f,
  66. -12.8553129536f,
  67. 5.4948074309f};
  68. void _ve_envelope_init(envelope_lookup *e,vorbis_info *vi){
  69. codec_setup_info *ci=vi->codec_setup;
  70. int ch=vi->channels;
  71. int window=ci->envelopesa;
  72. int i;
  73. e->winlength=window;
  74. e->minenergy=fromdB(ci->preecho_minenergy);
  75. e->iir=_ogg_calloc(ch*4,sizeof(IIR_state));
  76. e->filtered=_ogg_calloc(ch*4,sizeof(float *));
  77. e->ch=ch;
  78. e->storage=128;
  79. for(i=0;i<ch*4;i+=4){
  80. IIR_init(e->iir+i,cheb_highpass_stages,cheb_highpass10k_gain,
  81. cheb_highpass10k_A,cheb_highpass_B);
  82. IIR_init(e->iir+i+1,cheb_bandpass_stages,cheb_bandpass6k_gain,
  83. cheb_bandpass6k_A,cheb_bandpass_B);
  84. IIR_init(e->iir+i+2,cheb_bandpass_stages,cheb_bandpass3k_gain,
  85. cheb_bandpass3k_A,cheb_bandpass_B);
  86. IIR_init(e->iir+i+3,cheb_bandpass_stages,cheb_bandpass1k_gain,
  87. cheb_bandpass1k_A,cheb_bandpass_B);
  88. e->filtered[i]=_ogg_calloc(e->storage,sizeof(float));
  89. e->filtered[i+1]=_ogg_calloc(e->storage,sizeof(float));
  90. e->filtered[i+2]=_ogg_calloc(e->storage,sizeof(float));
  91. e->filtered[i+3]=_ogg_calloc(e->storage,sizeof(float));
  92. }
  93. }
  94. void _ve_envelope_clear(envelope_lookup *e){
  95. int i;
  96. for(i=0;i<e->ch*4;i++){
  97. IIR_clear((e->iir+i));
  98. _ogg_free(e->filtered[i]);
  99. }
  100. _ogg_free(e->filtered);
  101. _ogg_free(e->iir);
  102. memset(e,0,sizeof(envelope_lookup));
  103. }
  104. /* straight threshhold based until we find something that works better
  105. and isn't patented */
  106. static float _ve_deltai(envelope_lookup *ve,float *pre,float *post){
  107. long n=ve->winlength;
  108. long i;
  109. /* we want to have a 'minimum bar' for energy, else we're just
  110. basing blocks on quantization noise that outweighs the signal
  111. itself (for low power signals) */
  112. float min=ve->minenergy;
  113. float A=min*min*n;
  114. float B=A;
  115. for(i=0;i<n;i++){
  116. A+=pre[i]*pre[i];
  117. B+=post[i]*post[i];
  118. }
  119. A=todB(&A);
  120. B=todB(&B);
  121. return(B-A);
  122. }
  123. long _ve_envelope_search(vorbis_dsp_state *v,long searchpoint){
  124. vorbis_info *vi=v->vi;
  125. codec_setup_info *ci=vi->codec_setup;
  126. envelope_lookup *ve=((backend_lookup_state *)(v->backend_state))->ve;
  127. long i,j,k,l;
  128. float *work=alloca(sizeof(float)*ve->winlength*2);
  129. static int seq=0;
  130. /* make sure we have enough storage to match the PCM */
  131. if(v->pcm_storage>ve->storage){
  132. ve->storage=v->pcm_storage;
  133. for(i=0;i<ve->ch*4;i++)
  134. ve->filtered[i]=_ogg_realloc(ve->filtered[i],ve->storage*sizeof(float));
  135. }
  136. /* catch up the highpass to match the pcm */
  137. for(i=0;i<ve->ch;i++){
  138. float *pcm=v->pcm[i];
  139. float *filtered0=ve->filtered[i*4];
  140. float *filtered1=ve->filtered[i*4+1];
  141. float *filtered2=ve->filtered[i*4+2];
  142. float *filtered3=ve->filtered[i*4+3];
  143. IIR_state *iir0=ve->iir+i*4;
  144. IIR_state *iir1=ve->iir+i*4+1;
  145. IIR_state *iir2=ve->iir+i*4+2;
  146. IIR_state *iir3=ve->iir+i*4+3;
  147. int flag=1;
  148. for(j=ve->current;j<v->pcm_current;j++){
  149. filtered0[j]=IIR_filter(iir0,pcm[j]);
  150. filtered1[j]=IIR_filter_Band(iir1,pcm[j]);
  151. filtered2[j]=IIR_filter_Band(iir2,pcm[j]);
  152. filtered3[j]=IIR_filter_Band(iir3,pcm[j]);
  153. if(pcm[j])flag=0;
  154. }
  155. if(flag && ve->current+64<v->pcm_current){
  156. IIR_reset(iir0);
  157. IIR_reset(iir1);
  158. IIR_reset(iir2);
  159. IIR_reset(iir3);
  160. }
  161. }
  162. ve->current=v->pcm_current;
  163. /* Now search through our cached highpass data for breaking points */
  164. /* starting point */
  165. if(v->W)
  166. j=v->centerW+ci->blocksizes[1]/4-ci->blocksizes[0]/4;
  167. else
  168. j=v->centerW;
  169. if(j<ve->lastmark)j=ve->lastmark;
  170. while(j+ve->winlength<=v->pcm_current){
  171. if(j>=searchpoint)return(1);
  172. ve->lastmark=j;
  173. for(i=0;i<ve->ch;i++){
  174. for(k=0;k<4;k++){
  175. float *filtered=ve->filtered[i*4+k]+j;
  176. float m=_ve_deltai(ve,filtered-ve->winlength,filtered);
  177. if(m>ci->preecho_thresh[k])return(0);
  178. if(m<ci->postecho_thresh[k])return(0);
  179. }
  180. }
  181. j+=min(ci->blocksizes[0],ve->winlength)/2;
  182. }
  183. if(j>=searchpoint)return(1);
  184. return(-1);
  185. }
  186. void _ve_envelope_shift(envelope_lookup *e,long shift){
  187. int i;
  188. for(i=0;i<e->ch*4;i++)
  189. memmove(e->filtered[i],e->filtered[i]+shift,(e->current-shift)*
  190. sizeof(float));
  191. e->current-=shift;
  192. e->lastmark-=shift;
  193. }