home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 3 / AACD03.BIN / AACD / Sound / SoX / Source / chorus.c < prev    next >
C/C++ Source or Header  |  1999-07-18  |  11KB  |  360 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.  *     Chorus effect.
  12.  * 
  13.  * Flow diagram scheme for n delays ( 1 <= n <= MAX_CHORUS ):
  14.  *
  15.  *        * gain-in                                           ___
  16.  * ibuff -----+--------------------------------------------->|   |
  17.  *            |      _________                               |   |
  18.  *            |     |         |                   * decay 1  |   |
  19.  *            +---->| delay 1 |----------------------------->|   |
  20.  *            |     |_________|                              |   |
  21.  *            |        /|\                                   |   |
  22.  *            :         |                                    |   |
  23.  *            : +-----------------+   +--------------+       | + |
  24.  *            : | Delay control 1 |<--| mod. speed 1 |       |   |
  25.  *            : +-----------------+   +--------------+       |   |
  26.  *            |      _________                               |   |
  27.  *            |     |         |                   * decay n  |   |
  28.  *            +---->| delay n |----------------------------->|   |
  29.  *                  |_________|                              |   |
  30.  *                     /|\                                   |___|
  31.  *                      |                                      |  
  32.  *              +-----------------+   +--------------+         | * gain-out
  33.  *              | Delay control n |<--| mod. speed n |         |
  34.  *              +-----------------+   +--------------+         +----->obuff
  35.  *
  36.  *
  37.  * The delay i is controled by a sine or triangle modulation i ( 1 <= i <= n).
  38.  *
  39.  * Usage: 
  40.  *   chorus gain-in gain-out delay-1 decay-1 speed-1 depth-1 -s1|t1 [
  41.  *       delay-2 decay-2 speed-2 depth-2 -s2|-t2 ... ]
  42.  *
  43.  * Where:
  44.  *   gain-in, decay-1 ... decay-n :  0.0 ... 1.0      volume
  45.  *   gain-out :  0.0 ...      volume
  46.  *   delay-1 ... delay-n :  20.0 ... 100.0 msec
  47.  *   speed-1 ... speed-n :  0.1 ... 5.0 Hz       modulation 1 ... n
  48.  *   depth-1 ... depth-n :  0.0 ... 10.0 msec    modulated delay 1 ... n
  49.  *   -s1 ... -sn : modulation by sine 1 ... n
  50.  *   -t1 ... -tn : modulation by triangle 1 ... n
  51.  *
  52.  * Note:
  53.  *   when decay is close to 1.0, the samples can begin clipping and the output
  54.  *   can saturate! 
  55.  *
  56.  * Hint:
  57.  *   1 / out-gain < gain-in ( 1 + decay-1 + ... + decay-n )
  58.  *
  59. */
  60.  
  61. /*
  62.  * Sound Tools chorus effect file.
  63.  */
  64.  
  65. #include <stdlib.h> /* Harmless, and prototypes atof() etc. --dgc */
  66. #ifdef HAVE_MALLOC_H
  67. #include <malloc.h>
  68. #endif
  69. #include <math.h>
  70. #include <string.h>
  71. #include "st.h"
  72.  
  73. #define MOD_SINE    0
  74. #define MOD_TRIANGLE    1
  75. #define MAX_CHORUS    7
  76.  
  77. /* Private data for SKEL file */
  78. typedef struct chorusstuff {
  79.     int    num_chorus;
  80.     int    modulation[MAX_CHORUS];
  81.     int    counter;            
  82.     long    phase[MAX_CHORUS];
  83.     float    *chorusbuf;
  84.     float    in_gain, out_gain;
  85.     float    delay[MAX_CHORUS], decay[MAX_CHORUS];
  86.     float    speed[MAX_CHORUS], depth[MAX_CHORUS];
  87.     long    length[MAX_CHORUS];
  88.     int    *lookup_tab[MAX_CHORUS];
  89.     int    depth_samples[MAX_CHORUS], samples[MAX_CHORUS];
  90.     int    maxsamples, fade_out;
  91. } *chorus_t;
  92.  
  93. /* Private data for SKEL file */
  94.  
  95. LONG chorus_clip24(l)
  96. LONG l;
  97. {
  98.     if (l >= ((LONG)1 << 24))
  99.         return ((LONG)1 << 24) - 1;
  100.     else if (l <= -((LONG)1 << 24))
  101.         return -((LONG)1 << 24) + 1;
  102.     else
  103.         return l;
  104. }
  105.  
  106. /* This was very painful.  We need a sine library. */
  107.  
  108. void chorus_sine(buf, len, max, depth)
  109. int *buf;
  110. long len;
  111. int max;
  112. int depth;
  113. {
  114.     long i;
  115.     int offset;
  116.     double val;
  117.  
  118.     offset = max - depth;
  119.     for (i = 0; i < len; i++) {
  120.         val = sin((double)i/(double)len * 2.0 * M_PI);
  121.         buf[i] = offset + (int) (val * (double)depth);
  122.     }
  123. }
  124.  
  125. void chorus_triangle(buf, len, max, depth)
  126. int *buf;
  127. long len;
  128. int max;
  129. int depth;
  130. {
  131.     long i;
  132.     int offset;
  133.     double val;
  134.  
  135.     offset = max - 2 * depth;
  136.     for (i = 0; i < len / 2; i++) {
  137.         val = i * 2.0 / len;
  138.         buf[i] = offset + (int) (val * 2.0 * (double)depth);
  139.     }
  140.     for (i = len / 2; i < len ; i++) {
  141.         val = (len - i) * 2.0 / len;
  142.         buf[i] = offset + (int) (val * 2.0 * (double)depth);
  143.     }
  144. }
  145.  
  146. /*
  147.  * Process options
  148.  */
  149. void chorus_getopts(effp, n, argv) 
  150. eff_t effp;
  151. int n;
  152. char **argv;
  153. {
  154.     chorus_t chorus = (chorus_t) effp->priv;
  155.     int i;
  156.  
  157.     chorus->num_chorus = 0;
  158.     i = 0;
  159.  
  160.     if ( ( n < 7 ) || (( n - 2 ) % 5 ) )
  161.         fail("Usage: chorus gain-in gain-out delay decay speed depth [ -s | -t ]");
  162.  
  163.     sscanf(argv[i++], "%f", &chorus->in_gain);
  164.     sscanf(argv[i++], "%f", &chorus->out_gain);
  165.     while ( i < n ) {
  166.         if ( chorus->num_chorus > MAX_CHORUS )
  167.             fail("chorus: to many delays, use less than %i delays", MAX_CHORUS);
  168.         sscanf(argv[i++], "%f", &chorus->delay[chorus->num_chorus]);
  169.         sscanf(argv[i++], "%f", &chorus->decay[chorus->num_chorus]);
  170.         sscanf(argv[i++], "%f", &chorus->speed[chorus->num_chorus]);
  171.         sscanf(argv[i++], "%f", &chorus->depth[chorus->num_chorus]);
  172.         if ( !strcmp(argv[i], "-s"))
  173.             chorus->modulation[chorus->num_chorus] = MOD_SINE;
  174.         else if ( ! strcmp(argv[i], "-t"))
  175.             chorus->modulation[chorus->num_chorus] = MOD_TRIANGLE;
  176.         else
  177.                 fail("Usage: chorus gain-in gain-out delay decay speed [ -s | -t ]");
  178.         i++;
  179.         chorus->num_chorus++;
  180.     }
  181. }
  182.  
  183. /*
  184.  * Prepare for processing.
  185.  */
  186. void chorus_start(effp)
  187. eff_t effp;
  188. {
  189.     chorus_t chorus = (chorus_t) effp->priv;
  190.     int i;
  191.     float sum_in_volume;
  192.  
  193.     chorus->maxsamples = 0;
  194.  
  195.     if ( chorus->in_gain < 0.0 )
  196.         fail("chorus: gain-in must be positive!\n");
  197.     if ( chorus->in_gain > 1.0 )
  198.         fail("chorus: gain-in must be less than 1.0!\n");
  199.     if ( chorus->out_gain < 0.0 )
  200.         fail("chorus: gain-out must be positive!\n");
  201.     for ( i = 0; i < chorus->num_chorus; i++ ) {
  202.         chorus->samples[i] = (int) ( ( chorus->delay[i] + 
  203.             chorus->depth[i] ) * effp->ininfo.rate / 1000.0);
  204.         chorus->depth_samples[i] = (int) (chorus->depth[i] * 
  205.             effp->ininfo.rate / 1000.0);
  206.  
  207.         if ( chorus->delay[i] < 20.0 )
  208.                 fail("chorus: delay must be more than 20.0 msec!\n");
  209.         if ( chorus->delay[i] > 100.0 )
  210.                 fail("chorus: delay must be less than 100.0 msec!\n");
  211.         if ( chorus->speed[i] < 0.1 )
  212.                 fail("chorus: speed must be more than 0.1 Hz!\n");
  213.         if ( chorus->speed[i] > 5.0 )
  214.                 fail("chorus: speed must be less than 5.0 Hz!\n");
  215.         if ( chorus->depth[i] < 0.0 )
  216.                 fail("chorus: delay must be more positive!\n");
  217.         if ( chorus->depth[i] > 10.0 )
  218.                 fail("chorus: delay must be less than 10.0 msec!\n");
  219.         if ( chorus->decay[i] < 0.0 )
  220.                 fail("chorus: decay must be positive!\n" );
  221.         if ( chorus->decay[i] > 1.0 )
  222.                 fail("chorus: decay must be less that 1.0!\n" );
  223.         chorus->length[i] = effp->ininfo.rate / chorus->speed[i];
  224.         if (! (chorus->lookup_tab[i] = 
  225.             (int *) malloc(sizeof (int) * chorus->length[i])))
  226.             fail("chorus: Cannot malloc %d bytes!\n", 
  227.                 sizeof(int) * chorus->length[i]);
  228.         if ( chorus->modulation[i] == MOD_SINE )
  229.             chorus_sine(chorus->lookup_tab[i], chorus->length[i], 
  230.                 chorus->samples[i] - 1, chorus->depth_samples[i]);
  231.         else
  232.             chorus_triangle(chorus->lookup_tab[i], chorus->length[i], 
  233.                 chorus->samples[i] - 1, chorus->depth_samples[i]);
  234.         chorus->phase[i] = 0;
  235.  
  236.         if ( chorus->samples[i] > chorus->maxsamples )
  237.             chorus->maxsamples = chorus->samples[i];
  238.     }
  239.  
  240.     /* Be nice and check the hint with warning, if... */
  241.     sum_in_volume = 1.0;
  242.     for ( i = 0; i < chorus->num_chorus; i++ )
  243.         sum_in_volume += chorus->decay[i];
  244.     if ( chorus->in_gain * ( sum_in_volume ) > 1.0 / chorus->out_gain )
  245.     warn("chorus: warning >>> gain-out can cause saturation or clipping of output <<<");
  246.  
  247.  
  248.     if (! (chorus->chorusbuf = 
  249.         (float *) malloc(sizeof (float) * chorus->maxsamples)))
  250.         fail("chorus: Cannot malloc %d bytes!\n", 
  251.             sizeof(float) * chorus->maxsamples);
  252.     for ( i = 0; i < chorus->maxsamples; i++ )
  253.         chorus->chorusbuf[i] = 0.0;
  254.  
  255.     chorus->counter = 0;
  256.     chorus->fade_out = chorus->maxsamples;
  257. }
  258.  
  259. /*
  260.  * Processed signed long samples from ibuf to obuf.
  261.  * Return number of samples processed.
  262.  */
  263.  
  264. void chorus_flow(effp, ibuf, obuf, isamp, osamp)
  265. eff_t effp;
  266. LONG *ibuf, *obuf;
  267. int *isamp, *osamp;
  268. {
  269.     chorus_t chorus = (chorus_t) effp->priv;
  270.     int len, done;
  271.     int i;
  272.     
  273.     float d_in, d_out;
  274.     LONG out;
  275.  
  276.     len = ((*isamp > *osamp) ? *osamp : *isamp);
  277.     for(done = 0; done < len; done++) {
  278.         /* Store delays as 24-bit signed longs */
  279.         d_in = (float) *ibuf++ / 256;
  280.         /* Compute output first */
  281.         d_out = d_in * chorus->in_gain;
  282.         for ( i = 0; i < chorus->num_chorus; i++ )
  283.             d_out += chorus->chorusbuf[(chorus->maxsamples + 
  284.                 chorus->counter - chorus->lookup_tab[i][chorus->phase[i]]) % 
  285.             chorus->maxsamples] * chorus->decay[i];
  286.         /* Adjust the output volume and size to 24 bit */
  287.         d_out = d_out * chorus->out_gain;
  288.         out = chorus_clip24((LONG) d_out);
  289.         *obuf++ = out * 256;
  290.         /* Mix decay of delay and input */
  291.         chorus->chorusbuf[chorus->counter] = d_in;
  292.         chorus->counter = 
  293.             ( chorus->counter + 1 ) % chorus->maxsamples;
  294.         for ( i = 0; i < chorus->num_chorus; i++ )
  295.             chorus->phase[i]  = 
  296.                 ( chorus->phase[i] + 1 ) % chorus->length[i];
  297.     }
  298.     /* processed all samples */
  299. }
  300.  
  301. /*
  302.  * Drain out reverb lines. 
  303.  */
  304. void chorus_drain(effp, obuf, osamp)
  305. eff_t effp;
  306. LONG *obuf;
  307. int *osamp;
  308. {
  309.     chorus_t chorus = (chorus_t) effp->priv;
  310.     int done;
  311.     int i;
  312.     
  313.     float d_in, d_out;
  314.     LONG out;
  315.  
  316.     done = 0;
  317.     while ( ( done < *osamp ) && ( done < chorus->fade_out ) ) {
  318.         d_in = 0;
  319.         d_out = 0;
  320.         /* Compute output first */
  321.         for ( i = 0; i < chorus->num_chorus; i++ )
  322.             d_out += chorus->chorusbuf[(chorus->maxsamples + 
  323.         chorus->counter - chorus->lookup_tab[i][chorus->phase[i]]) % 
  324.         chorus->maxsamples] * chorus->decay[i];
  325.         /* Adjust the output volume and size to 24 bit */
  326.         d_out = d_out * chorus->out_gain;
  327.         out = chorus_clip24((LONG) d_out);
  328.         *obuf++ = out * 256;
  329.         /* Mix decay of delay and input */
  330.         chorus->chorusbuf[chorus->counter] = d_in;
  331.         chorus->counter = 
  332.             ( chorus->counter + 1 ) % chorus->maxsamples;
  333.         for ( i = 0; i < chorus->num_chorus; i++ )
  334.             chorus->phase[i]  = 
  335.                 ( chorus->phase[i] + 1 ) % chorus->length[i];
  336.         done++;
  337.         chorus->fade_out--;
  338.     }
  339.     /* samples played, it remains */
  340.     *osamp = done;
  341. }
  342.  
  343. /*
  344.  * Clean up chorus effect.
  345.  */
  346. void chorus_stop(effp)
  347. eff_t effp;
  348. {
  349.     chorus_t chorus = (chorus_t) effp->priv;
  350.     int i;
  351.  
  352.     free((char *) chorus->chorusbuf);
  353.     chorus->chorusbuf = (float *) -1;   /* guaranteed core dump */
  354.     for ( i = 0; i < chorus->num_chorus; i++ ) {
  355.         free((char *) chorus->lookup_tab[i]);
  356.         chorus->lookup_tab[i] = (int *) -1;   /* guaranteed core dump */
  357.     }
  358. }
  359.  
  360.