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