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

  1.  
  2. /*
  3.  * August 24, 1998
  4.  * Copyright (C) 1998 Juergen Mueller And Sundry Contributors
  5.  * This source code is freely redistributable and may be used for
  6.  * any purpose.  This copyright notice must be maintained. 
  7.  * Lance Norskog And Sundry Contributors are not responsible for 
  8.  * the consequences of using this software.
  9.  */
  10.  
  11. /*
  12. **     Echo effect. based on:
  13. **
  14. ** echoplex.c - echo generator
  15. **
  16. ** Copyright (C) 1989 by Jef Poskanzer.
  17. **
  18. ** Permission to use, copy, modify, and distribute this software and its
  19. ** documentation for any purpose and without fee is hereby granted, provided
  20. ** that the above copyright notice appear in all copies and that both that
  21. ** copyright notice and this permission notice appear in supporting
  22. ** documentation.  This software is provided "as is" without express or
  23. ** implied warranty.
  24. */
  25.  
  26.  
  27. /*
  28.  * Changes to old "echo.c" now called "reverb.c":
  29.  *
  30.  * The effect name changes from "echo" to "reverb" (see Guitar FX FAQ) for
  31.  * the difference in its defintion.
  32.  * The idea of the echoplexer is modified and enhanceb by an automatic
  33.  * setting of each decay for realistic reverb.
  34.  * Some bugs are fixed concerning malloc and fade-outs.
  35.  * Added an output volume (gain-out) avoiding saturation or clipping.
  36.  *
  37.  *
  38.  * Reverb effect for dsp.
  39.  *
  40.  * Flow diagram scheme for n delays ( 1 <= n <= MAXREVERB )
  41.  *
  42.  *        * gain-in  +---+                        * gain-out
  43.  * ibuff ----------->|   |------------------------------------> obuff
  44.  *                   |   |  * decay 1
  45.  *                   |   |<------------------------+
  46.  *                   | + |  * decay 2              |
  47.  *                   |   |<--------------------+   |
  48.  *                   |   |  * decay n          |   |
  49.  *                   |   |<----------------+   |   |
  50.  *                   +---+                 |   |   |
  51.  *                     |      _________    |   |   |
  52.  *                     |     |         |   |   |   |
  53.  *                     +---->| delay n |---+   |   |
  54.  *                     .     |_________|       |   |
  55.  *                     .                       |   |
  56.  *                     .      _________        |   |
  57.  *                     |     |         |       |   |
  58.  *                     +---->| delay 2 |-------+   |
  59.  *                     |     |_________|           |
  60.  *                     |                           |
  61.  *                     |      _________            |
  62.  *                     |     |         |           |
  63.  *                     +---->| delay 1 |-----------+
  64.  *                           |_________|
  65.  *
  66.  *
  67.  *
  68.  * Usage:
  69.  *   reverb gain-out reverb-time delay-1 [ delay-2 ... delay-n ]
  70.  *
  71.  * Where:
  72.  *   gain-out :  0.0 ...      volume
  73.  *   reverb-time :  > 0.0 msec
  74.  *   delay-1 ... delay-n :  > 0.0 msec
  75.  *
  76.  * Note:
  77.  *   gain-in is automatically adjusted avoiding saturation and clipping of
  78.  *   the output. decay-1 to decay-n are computed such that at reverb-time
  79.  *   the input will be 60 dB of the original input for the given delay-1 
  80.  *   to delay-n. delay-1 to delay-n specify the time when the first bounce
  81.  *   of the input will appear. A proper setting for delay-1 to delay-n 
  82.  *   depends on the choosen reverb-time (see hint).
  83.  *
  84.  * Hint:
  85.  *   a realstic reverb effect can be obtained using for a given reverb-time "t"
  86.  *   delays in the range of "t/2 ... t/4". Each delay should not be an integer
  87.  *   of any other.
  88.  *
  89. */
  90.  
  91. /*
  92.  * Sound Tools reverb effect file.
  93.  */
  94.  
  95. #include <stdlib.h> /* Harmless, and prototypes atof() etc. --dgc */
  96. #ifdef HAVE_MALLOC_H
  97. #include <malloc.h>
  98. #endif
  99. #include <math.h>
  100. #include "st.h"
  101.  
  102. #define REVERB_FADE_THRESH 10
  103. #define DELAY_BUFSIZ ( 50L * MAXRATE )
  104. #define MAXREVERBS 8
  105.  
  106. /* Private data for SKEL file */
  107. typedef struct reverbstuff {
  108.     int    counter;            
  109.     int    numdelays;
  110.     float    *reverbbuf;
  111.     float    in_gain, out_gain, time;
  112.     float    delay[MAXREVERBS], decay[MAXREVERBS];
  113.     long    samples[MAXREVERBS], maxsamples;
  114.     LONG    pl, ppl, pppl;
  115. } *reverb_t;
  116.  
  117. /* Private data for SKEL file */
  118.  
  119. #ifndef abs
  120. #define abs(a) ((a) >= 0 ? (a) : -(a))
  121. #endif
  122.  
  123. LONG reverb_clip24(l)
  124. LONG l;
  125. {
  126.     if (l >= ((LONG)1 << 24))
  127.         return ((LONG)1 << 24) - 1;
  128.     else if (l <= -((LONG)1 << 24))
  129.         return -((LONG)1 << 24) + 1;
  130.     else
  131.         return l;
  132. }
  133.  
  134. /*
  135.  * Process options
  136.  */
  137. void reverb_getopts(effp, n, argv) 
  138. eff_t effp;
  139. int n;
  140. char **argv;
  141. {
  142.     reverb_t reverb = (reverb_t) effp->priv;
  143.     int i;
  144.  
  145.     reverb->numdelays = 0;
  146.     reverb->maxsamples = 0;
  147.  
  148.     if ( n < 3 )
  149.         fail("Usage: reverb gain-out reverb-time delay [ delay ... ]");
  150.  
  151.     if ( n - 2 > MAXREVERBS )
  152.         fail("reverb: to many dalays, use less than %i delays",
  153.             MAXREVERBS);
  154.  
  155.     i = 0;
  156.     sscanf(argv[i++], "%f", &reverb->out_gain);
  157.     sscanf(argv[i++], "%f", &reverb->time);
  158.     while (i < n) {
  159.         /* Linux bug and it's cleaner. */
  160.         sscanf(argv[i++], "%f", &reverb->delay[reverb->numdelays]);
  161.         reverb->numdelays++;
  162.     }
  163. }
  164.  
  165. /*
  166.  * Prepare for processing.
  167.  */
  168. void reverb_start(effp)
  169. eff_t effp;
  170. {
  171.     reverb_t reverb = (reverb_t) effp->priv;
  172.     int i;
  173.  
  174.     reverb->in_gain = 1.0;
  175.  
  176.     if ( reverb->out_gain < 0.0 )
  177.         fail("reverb: gain-out must be positive");
  178.     if ( reverb->out_gain > 1.0 )
  179.         warn("reverb: warnig >>> gain-out can cause saturation of output <<<");
  180.     if ( reverb->time < 0.0 )
  181.         fail("reverb: reverb-time must be positive");
  182.     for(i = 0; i < reverb->numdelays; i++) {
  183.         reverb->samples[i] = reverb->delay[i] * effp->ininfo.rate / 1000.0;
  184.         if ( reverb->samples[i] < 1 )
  185.             fail("reverb: delay must be positive!\n");
  186.         if ( reverb->samples[i] > DELAY_BUFSIZ )
  187.             fail("reverb: delay must be less than %g seconds!\n",
  188.                 DELAY_BUFSIZ / (float) effp->ininfo.rate );
  189.         /* Compute a realistic decay */
  190.         reverb->decay[i] = (float) pow(10.0,(-3.0 * reverb->delay[i] / reverb->time));
  191.         if ( reverb->samples[i] > reverb->maxsamples )
  192.             reverb->maxsamples = reverb->samples[i];
  193.     }
  194.     if (! (reverb->reverbbuf = (float *) malloc(sizeof (float) * reverb->maxsamples)))
  195.         fail("reverb: Cannot malloc %d bytes!\n", 
  196.             sizeof(float) * reverb->maxsamples);
  197.     for ( i = 0; i < reverb->maxsamples; ++i )
  198.         reverb->reverbbuf[i] = 0.0;
  199.     reverb->pppl = reverb->ppl = reverb->pl = 0x7fffff;        /* fade-outs */
  200.     reverb->counter = 0;
  201.     /* Compute the input volume carefully */
  202.     for ( i = 0; i < reverb->numdelays; i++ )
  203.         reverb->in_gain *= 
  204.             ( 1.0 - ( reverb->decay[i] * reverb->decay[i] ));
  205. }
  206.  
  207. /*
  208.  * Processed signed long samples from ibuf to obuf.
  209.  * Return number of samples processed.
  210.  */
  211.  
  212. void reverb_flow(effp, ibuf, obuf, isamp, osamp)
  213. eff_t effp;
  214. LONG *ibuf, *obuf;
  215. int *isamp, *osamp;
  216. {
  217.     reverb_t reverb = (reverb_t) effp->priv;
  218.     int len, done;
  219.     int i, j;
  220.     
  221.     float d_in, d_out;
  222.     LONG out;
  223.  
  224.     i = reverb->counter;
  225.     len = ((*isamp > *osamp) ? *osamp : *isamp);
  226.     for(done = 0; done < len; done++) {
  227.         /* Store delays as 24-bit signed longs */
  228.         d_in = (float) *ibuf++ / 256;
  229.         d_in = d_in * reverb->in_gain;
  230.         /* Mix decay of delay and input as output */
  231.         for ( j = 0; j < reverb->numdelays; j++ )
  232.             d_in +=
  233. reverb->reverbbuf[(i + reverb->maxsamples - reverb->samples[j]) % reverb->maxsamples] * reverb->decay[j];
  234.         d_out = d_in * reverb->out_gain;
  235.         out = reverb_clip24((LONG) d_out);
  236.         *obuf++ = out * 256;
  237.         reverb->reverbbuf[i] = d_in;
  238.         i++;        /* XXX need a % maxsamples here ? */
  239.         i %= reverb->maxsamples;
  240.     }
  241.     reverb->counter = i;
  242.     /* processed all samples */
  243. }
  244.  
  245. /*
  246.  * Drain out reverb lines. 
  247.  */
  248. void reverb_drain(effp, obuf, osamp)
  249. eff_t effp;
  250. LONG *obuf;
  251. int *osamp;
  252. {
  253.     reverb_t reverb = (reverb_t) effp->priv;
  254.     float d_in, d_out;
  255.     LONG out, l;
  256.     int i, j, done;
  257.  
  258.     i = reverb->counter;
  259.     done = 0;
  260.     /* drain out delay samples */
  261.     do {
  262.         d_in = 0;
  263.         d_out = 0;
  264.         for ( j = 0; j < reverb->numdelays; ++j )
  265.             d_in += 
  266. reverb->reverbbuf[(i + reverb->maxsamples - reverb->samples[j]) % reverb->maxsamples] * reverb->decay[j];
  267.         d_out = d_in * reverb->out_gain;
  268.         out = reverb_clip24((LONG) d_out);
  269.         obuf[done++] = out * 256;
  270.         reverb->reverbbuf[i] = d_in;
  271.         l = reverb_clip24((LONG) d_in);
  272.         reverb->pppl = reverb->ppl;
  273.         reverb->ppl = reverb->pl;
  274.         reverb->pl = l;
  275.         i++;        /* need a % maxsamples here ? */
  276.         i %= reverb->maxsamples;
  277.     } while((done < *osamp) && 
  278.         ((abs(reverb->pl) + abs(reverb->ppl) + abs(reverb->pppl)) > REVERB_FADE_THRESH));
  279.     reverb->counter = i;
  280.     *osamp = done;
  281. }
  282.  
  283. /*
  284.  * Clean up reverb effect.
  285.  */
  286. void reverb_stop(effp)
  287. eff_t effp;
  288. {
  289.     reverb_t reverb = (reverb_t) effp->priv;
  290.  
  291.     free((char *) reverb->reverbbuf);
  292.     reverb->reverbbuf = (float *) -1;   /* guaranteed core dump */
  293. }
  294.  
  295.