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

  1. /*
  2.  * August 24, 1998
  3.  * Copyright (C) 1998 Juergen Mueller 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.  * Juergen Mueller And Sundry Contributors are not responsible for 
  7.  * the consequences of using this software.
  8.  */
  9.  
  10. /*
  11.  * Echos effect for dsp.
  12.  * 
  13.  * Flow diagram scheme for n delays ( 1 <= n <= MAX_ECHOS ):
  14.  *
  15.  *                                                    * gain-in  ___
  16.  * ibuff --+--------------------------------------------------->|   |
  17.  *         |                                          * decay 1 |   |
  18.  *         |               +----------------------------------->|   |
  19.  *         |               |                          * decay 2 | + |
  20.  *         |               |             +--------------------->|   |
  21.  *         |               |             |            * decay n |   |
  22.  *         |    _________  |  _________  |     _________   +--->|___|
  23.  *         |   |         | | |         | |    |         |  |      | 
  24.  *         +-->| delay 1 |-+-| delay 2 |-+...-| delay n |--+      | * gain-out
  25.  *             |_________|   |_________|      |_________|         |
  26.  *                                                                +----->obuff
  27.  *
  28.  * Usage: 
  29.  *   echos gain-in gain-out delay-1 decay-1 [delay-2 decay-2 ... delay-n decay-n]
  30.  *
  31.  * Where:
  32.  *   gain-in, decay-1 ... decay-n :  0.0 ... 1.0      volume
  33.  *   gain-out :  0.0 ...      volume
  34.  *   delay-1 ... delay-n :  > 0.0 msec
  35.  *
  36.  * Note:
  37.  *   when decay is close to 1.0, the samples can begin clipping and the output
  38.  *   can saturate! 
  39.  *
  40.  * Hint:
  41.  *   1 / out-gain > gain-in ( 1 + decay-1 + ... + decay-n )
  42.  *
  43. */
  44.  
  45. /*
  46.  * Sound Tools reverb effect file.
  47.  */
  48.  
  49. #include <stdlib.h> /* Harmless, and prototypes atof() etc. --dgc */
  50. #ifdef HAVE_MALLOC_H
  51. #include <malloc.h>
  52. #endif
  53. #include <math.h>
  54. #include "st.h"
  55.  
  56. #define DELAY_BUFSIZ ( 50L * MAXRATE )
  57. #define MAX_ECHOS 7    /* 24 bit x ( 1 + MAX_ECHOS ) = */
  58.             /* 24 bit x 8 = 32 bit !!!    */
  59.  
  60. /* Private data for SKEL file */
  61. typedef struct echosstuff {
  62.     int    counter[MAX_ECHOS];            
  63.     int    num_delays;
  64.     double    *delay_buf;
  65.     float    in_gain, out_gain;
  66.     float    delay[MAX_ECHOS], decay[MAX_ECHOS];
  67.     long    samples[MAX_ECHOS], pointer[MAX_ECHOS], sumsamples;
  68. } *echos_t;
  69.  
  70. /* Private data for SKEL file */
  71.  
  72.  
  73. /* If we are not carefull with the output volume */
  74. LONG echos_clip24(l)
  75. LONG l;
  76. {
  77.     if (l >= ((LONG)1 << 24))
  78.         return ((LONG)1 << 24) - 1;
  79.     else if (l <= -((LONG)1 << 24))
  80.         return -((LONG)1 << 24) + 1;
  81.     else
  82.         return l;
  83. }
  84.  
  85.  
  86.  
  87. /*
  88.  * Process options
  89.  */
  90. void echos_getopts(effp, n, argv) 
  91. eff_t effp;
  92. int n;
  93. char **argv;
  94. {
  95.     echos_t echos = (echos_t) effp->priv;
  96.     int i;
  97.  
  98.     echos->num_delays = 0;
  99.  
  100.     if ((n < 4) || (n % 2))
  101.         fail("Usage: echos gain-in gain-out delay decay [ delay decay ... ]");
  102.  
  103.     i = 0;
  104.     sscanf(argv[i++], "%f", &echos->in_gain);
  105.     sscanf(argv[i++], "%f", &echos->out_gain);
  106.     while (i < n) {
  107.         /* Linux bug and it's cleaner. */
  108.         sscanf(argv[i++], "%f", &echos->delay[echos->num_delays]);
  109.         sscanf(argv[i++], "%f", &echos->decay[echos->num_delays]);
  110.         echos->num_delays++;
  111.         if ( echos->num_delays > MAX_ECHOS )
  112.             fail("echos: to many delays, use less than %i delays",
  113.                 MAX_ECHOS);
  114.     }
  115.     echos->sumsamples = 0;
  116. }
  117.  
  118. /*
  119.  * Prepare for processing.
  120.  */
  121. void echos_start(effp)
  122. eff_t effp;
  123. {
  124.     echos_t echos = (echos_t) effp->priv;
  125.     int i;
  126.     float sum_in_volume;
  127.     long j;
  128.  
  129.     if ( echos->in_gain < 0.0 )
  130.         fail("echos: gain-in must be positive!\n");
  131.     if ( echos->in_gain > 1.0 )
  132.         fail("echos: gain-in must be less than 1.0!\n");
  133.     if ( echos->out_gain < 0.0 )
  134.         fail("echos: gain-in must be positive!\n");
  135.     for ( i = 0; i < echos->num_delays; i++ ) {
  136.         echos->samples[i] = echos->delay[i] * effp->ininfo.rate / 1000.0;
  137.         if ( echos->samples[i] < 1 )
  138.             fail("echos: delay must be positive!\n");
  139.         if ( echos->samples[i] > DELAY_BUFSIZ )
  140.             fail("echos: delay must be less than %g seconds!\n",
  141.                 DELAY_BUFSIZ / (float) effp->ininfo.rate );
  142.         if ( echos->decay[i] < 0.0 )
  143.             fail("echos: decay must be positive!\n" );
  144.         if ( echos->decay[i] > 1.0 )
  145.             fail("echos: decay must be less than 1.0!\n" );
  146.         echos->counter[i] = 0;
  147.         echos->pointer[i] = echos->sumsamples;
  148.         echos->sumsamples += echos->samples[i];
  149.     }
  150.     if (! (echos->delay_buf = (double *) malloc(sizeof (double) * echos->sumsamples)))
  151.         fail("echos: Cannot malloc %d bytes!\n", 
  152.             sizeof(long) * echos->sumsamples);
  153.     for ( j = 0; j < echos->samples[i]; ++j )
  154.         echos->delay_buf[j] = 0.0;
  155.     /* Be nice and check the hint with warning, if... */
  156.     sum_in_volume = 1.0;
  157.     for ( i = 0; i < echos->num_delays; i++ ) 
  158.         sum_in_volume += echos->decay[i];
  159.     if ( sum_in_volume * echos->in_gain > 1.0 / echos->out_gain )
  160.         warn("echos: warning >>> gain-out can cause saturation of output <<<");
  161. }
  162.  
  163. /*
  164.  * Processed signed long samples from ibuf to obuf.
  165.  * Return number of samples processed.
  166.  */
  167.  
  168. void echos_flow(effp, ibuf, obuf, isamp, osamp)
  169. eff_t effp;
  170. LONG *ibuf, *obuf;
  171. int *isamp, *osamp;
  172. {
  173.     echos_t echos = (echos_t) effp->priv;
  174.     int len, done;
  175.     int j;
  176.     
  177.     double d_in, d_out;
  178.     LONG out;
  179.  
  180.     len = ((*isamp > *osamp) ? *osamp : *isamp);
  181.     for(done = 0; done < len; done++) {
  182.         /* Store delays as 24-bit signed longs */
  183.         d_in = (double) *ibuf++ / 256;
  184.         /* Compute output first */
  185.         d_out = d_in * echos->in_gain;
  186.         for ( j = 0; j < echos->num_delays; j++ ) {
  187.             d_out += echos->delay_buf[echos->counter[j] + echos->pointer[j]] * echos->decay[j];
  188.         }
  189.         /* Adjust the output volume and size to 24 bit */
  190.         d_out = d_out * echos->out_gain;
  191.         out = echos_clip24((LONG) d_out);
  192.         *obuf++ = out * 256;
  193.         /* Mix decay of delays and input */
  194.         for ( j = 0; j < echos->num_delays; j++ ) {
  195.             if ( j == 0 )
  196.                 echos->delay_buf[echos->counter[j] + echos->pointer[j]] = d_in;
  197.             else
  198.                 echos->delay_buf[echos->counter[j] + echos->pointer[j]] = 
  199.                    echos->delay_buf[echos->counter[j-1] + echos->pointer[j-1]] + d_in;
  200.         }
  201.         /* Adjust the counters */
  202.         for ( j = 0; j < echos->num_delays; j++ )
  203.             echos->counter[j] = 
  204.                ( echos->counter[j] + 1 ) % echos->samples[j];
  205.     }
  206.     /* processed all samples */
  207. }
  208.  
  209. /*
  210.  * Drain out reverb lines. 
  211.  */
  212. void echos_drain(effp, obuf, osamp)
  213. eff_t effp;
  214. LONG *obuf;
  215. int *osamp;
  216. {
  217.     echos_t echos = (echos_t) effp->priv;
  218.     double d_in, d_out;
  219.     LONG out;
  220.     int j;
  221.     long done;
  222.  
  223.     done = 0;
  224.     /* drain out delay samples */
  225.     while ( ( done < *osamp ) && ( done < echos->sumsamples ) ) {
  226.         d_in = 0;
  227.         d_out = 0;
  228.         for ( j = 0; j < echos->num_delays; j++ ) {
  229.             d_out += echos->delay_buf[echos->counter[j] + echos->pointer[j]] * echos->decay[j];
  230.         }
  231.         /* Adjust the output volume and size to 24 bit */
  232.         d_out = d_out * echos->out_gain;
  233.         out = echos_clip24((LONG) d_out);
  234.         *obuf++ = out * 256;
  235.         /* Mix decay of delays and input */
  236.         for ( j = 0; j < echos->num_delays; j++ ) {
  237.             if ( j == 0 )
  238.                 echos->delay_buf[echos->counter[j] + echos->pointer[j]] = d_in;
  239.             else
  240.                 echos->delay_buf[echos->counter[j] + echos->pointer[j]] = 
  241.                    echos->delay_buf[echos->counter[j-1] + echos->pointer[j-1]];
  242.         }
  243.         /* Adjust the counters */
  244.         for ( j = 0; j < echos->num_delays; j++ )
  245.             echos->counter[j] = 
  246.                ( echos->counter[j] + 1 ) % echos->samples[j];
  247.         done++;
  248.         echos->sumsamples--;
  249.     };
  250.     /* samples played, it remains */
  251.     *osamp = done;
  252. }
  253.  
  254. /*
  255.  * Clean up reverb effect.
  256.  */
  257. void echos_stop(effp)
  258. eff_t effp;
  259. {
  260.     echos_t echos = (echos_t) effp->priv;
  261.  
  262.     free((char *) echos->delay_buf);
  263.     echos->delay_buf = (double *) -1;   /* guaranteed core dump */
  264. }
  265.  
  266.