home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 3 / AACD03.BIN / AACD / Sound / SoX / Source / deemphas.c < prev    next >
C/C++ Source or Header  |  1999-07-18  |  6KB  |  202 lines

  1. /*
  2.  * July 5, 1991
  3.  * Copyright 1991 Lance Norskog And Sundry Contributors
  4.  * This source code is freely redistributable and may be used for
  5.  * any purpose.  This copyright notice must be maintained.
  6.  * Lance Norskog And Sundry Contributors are not responsible for
  7.  * the consequences of using this software.
  8.  *
  9.  * Fixed deemphasis filter for processing pre-emphasized audio cd samples
  10.  * 09/02/98 (c) Heiko Eißfeldt
  11.  * License: GPL (Gnu Public License)
  12.  *
  13.  * This implements the inverse filter of the optional pre-emphasis stage as
  14.  * defined by ISO 908 (describing the audio cd format).
  15.  *
  16.  * Background:
  17.  * In the early days of audio cds, there were recording problems
  18.  * with noise (for example in classical recordings). The high dynamics
  19.  * of audio cds exposed these recording errors a lot.
  20.  *
  21.  * The commonly used solution at that time was to 'pre-emphasize' the
  22.  * trebles to have a better signal-noise-ratio. That is trebles were
  23.  * amplified before recording, so that they would give a stronger
  24.  * signal compared to the underlying (tape)noise.
  25.  *
  26.  * For that purpose the audio signal was prefiltered with the following
  27.  * frequency response (simple first order filter):
  28.  *
  29.  * V (in dB)
  30.  * ^
  31.  * |
  32.  * |                         _________________
  33.  * |                        /
  34.  * |                       / |
  35.  * |     20 dB / decade ->/  |
  36.  * |                     /   |
  37.  * |____________________/_ _ |_ _ _ _ _ _ _ _ _ _ _ _ _ lg f
  38.  * |0 dB                |    |
  39.  * |                    |    |
  40.  * |                    |    |
  41.  *                 3.1KHz    ca. 10KHz
  42.  *
  43.  * So the recorded audio signal has amplified trebles compared to the
  44.  * original.
  45.  * HiFi cd players do correct this by applying an inverse filter
  46.  * automatically, the cd-rom drives or cd burners used by digital
  47.  * sampling programs (like cdda2wav) however do not.
  48.  *
  49.  * So, this is what this effect does.
  50.  *
  51.  * Here is the gnuplot file for the frequency response
  52.    of the deemphasis. The error is below +-0.1dB
  53.  
  54. -------- Start of gnuplot file ---------------------
  55. # first define the ideal filter. We use the tenfold sampling frequency.
  56. T=1./441000.
  57. OmegaU=1./15E-6
  58. OmegaL=15./50.*OmegaU
  59. V0=OmegaL/OmegaU
  60. H0=V0-1.
  61. B=V0*tan(OmegaU*T/2.)
  62. # the coefficients follow
  63. a1=(B - 1.)/(B + 1.)
  64. b0=(1.0 + (1.0 - a1) * H0/2.)
  65. b1=(a1 + (a1 - 1.0) * H0/2.)
  66. # helper variables
  67. D=b1/b0
  68. o=2*pi*T
  69. H2(f)=b0*sqrt((1+2*cos(f*o)*D+D*D)/(1+2*cos(f*o)*a1+a1*a1))
  70. #
  71. # now approximate the ideal curve with a fitted one for sampling
  72. frequency
  73. # of 44100 Hz. Fitting parameters are
  74. # amplification at high frequencies V02
  75. # and tau of the upper edge frequency OmegaU2 = 2 *pi * f(upper)
  76. T2=1./44100.
  77. V02=0.3365
  78. OmegaU2=1./19E-6
  79. B2=V02*tan(OmegaU2*T2/2.)
  80. # the coefficients follow
  81. a12=(B2 - 1.)/(B2 + 1.)
  82. b02=(1.0 + (1.0 - a12) * (V02-1.)/2.)
  83. b12=(a12 + (a12 - 1.0) * (V02-1.)/2.)
  84. # helper variables
  85. D2=b12/b02
  86. o2=2*pi*T2
  87. H(f)=b02*sqrt((1+2*cos(f*o2)*D2+D2*D2)/(1+2*cos(f*o2)*a12+a12*a12))
  88. # plot best, real, ideal, level with halved attenuation,
  89. #      level at full attentuation, 10fold magnified error
  90. set logscale x
  91. set grid xtics ytics mxtics mytics
  92. plot [f=1000:20000] [-12:2] 20*log10(H(f)),20*log10(H2(f)),
  93. 20*log10(OmegaL/(2*
  94. pi*f)), 0.5*20*log10(V0), 20*log10(V0), 200*log10(H(f)/H2(f))
  95. pause -1 "Hit return to continue"
  96. -------- End of gnuplot file ---------------------
  97.  
  98.  */
  99.  
  100. /*
  101.  * adapted from Sound Tools skeleton effect file.
  102.  */
  103.  
  104. #include <math.h>
  105. #include "st.h"
  106.  
  107. /* Private data for deemph file */
  108. typedef struct deemphstuff {
  109.      LONG lastin;
  110.      double    lastout;
  111. } *deemph_t;
  112.  
  113. /*
  114.  * Process options
  115.  *
  116.  * Don't do initialization now.
  117.  * The 'info' fields are not yet filled in.
  118.  */
  119. void deemph_getopts(effp, n, argv)
  120. eff_t effp;
  121. int n;
  122. char **argv;
  123. {
  124.      if (n)
  125.           fail("Deemphasis filtering effect takes no options.\n");
  126.      if (sizeof(double)*PRIVSIZE < sizeof(struct deemphstuff))
  127.           fail("Internal error: PRIVSIZE too small.\n");
  128. }
  129.  
  130. /*
  131.  * Prepare processing.
  132.  * Do all initializations.
  133.  */
  134. void deemph_start(effp)
  135. eff_t effp;
  136. {
  137.      /* check the input format */
  138.      if (effp->ininfo.style != SIGN2
  139.          || effp->ininfo.rate != 44100
  140.          || effp->ininfo.size != WORD)
  141.           fail("The deemphasis effect works only with audio cd like samples.\nThe input format however has %d Hz sample rate and %d-byte%s signed linearly coded samples.",
  142.             effp->ininfo.rate, effp->ininfo.size,
  143.             effp->ininfo.style != SIGN2 ? ", but not" : "");
  144.      {
  145.           deemph_t deemph = (deemph_t) effp->priv;
  146.  
  147.           deemph->lastin = 0;
  148.           deemph->lastout = 0.0;
  149.      }
  150. }
  151.  
  152. /*
  153.  * Processed signed long samples from ibuf to obuf.
  154.  * Return number of samples processed.
  155.  */
  156.  
  157. /* filter coefficients */
  158. #define a1      -0.62786881719628784282
  159. #define b0      0.45995451989513153057
  160. #define b1      -0.08782333709141937339
  161.  
  162. void deemph_flow(effp, ibuf, obuf, isamp, osamp)
  163. eff_t effp;
  164. LONG *ibuf, *obuf;
  165. int *isamp, *osamp;
  166. {
  167.      deemph_t deemph = (deemph_t) effp->priv;
  168.      int len, done;
  169.  
  170.      len = ((*isamp > *osamp) ? *osamp : *isamp);
  171.      for(done = len; done; done--) {
  172.           deemph->lastout = *ibuf * b0 +
  173.                          deemph->lastin * b1 -
  174.                          deemph->lastout * a1;
  175.           deemph->lastin = *ibuf++;
  176.           *obuf++ = deemph->lastout > 0.0 ?
  177.                     deemph->lastout + 0.5 :
  178.                     deemph->lastout - 0.5;
  179.      }
  180. }
  181.  
  182. /*
  183.  * Drain out remaining samples if the effect generates any.
  184.  */
  185.  
  186. void deemph_drain(effp, obuf, osamp)
  187. LONG *obuf;
  188. int *osamp;
  189. {
  190.      /* nothing to do */
  191. }
  192.  
  193. /*
  194.  * Do anything required when you stop reading samples.
  195.  *   (free allocated memory, etc.)
  196.  */
  197. void deemph_stop(effp)
  198. eff_t effp;
  199. {
  200.      /* nothing to do */
  201. }
  202.