octal-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Octal-dev] SoX flanger


From: Avelino
Subject: [Octal-dev] SoX flanger
Date: Mon, 26 Jun 2000 19:31:38 +0100 (BST)

        Sox flanger sounds great!
        I have test it with this configuration:

        dtosquare --> svfilter --> soxflanger --> delay --> master

... and sounds very nice   ;-)

                                        Bye.

-------------------------------------------------------------------------------
Avelino Herrera Morales. E-Mail: address@hidden
                                 address@hidden
                         HTTP: http://www.avelino.turincon.com
                               http://www.geocities.com/avelinoherrera/
                         Powered by SunOS 5.7
                         Centro Superior de Informatica
                         UNIVERSIDAD DE LA LAGUNA.
-------------------------------------------------------------------------------


Received: from mta5.snfc21.pbi.net (mta5.snfc21.pbi.net [206.13.28.241])
        by mescaline.gnu.org (8.9.1a/8.9.1) with ESMTP id XAA25210
        for <address@hidden>; Mon, 26 Jun 2000 23:17:06 -0400
Received: from pacbell.net ([206.170.64.80])
 by mta5.snfc21.pbi.net (Sun Internet Mail Server sims.3.5.2000.01.05.12.18.p9)
 with ESMTP id <address@hidden> for address@hidden; Mon,
 26 Jun 2000 18:33:07 -0700 (PDT)
Date: Mon, 26 Jun 2000 18:31:06 -0700
From: Neil Nelson <address@hidden>
To: address@hidden
Message-id: <address@hidden>
MIME-version: 1.0
X-Mailer: Mozilla 4.72 [en] (X11; U; Linux 2.2.14-5.0 i686)
Content-type: multipart/alternative;
 boundary="------------24819DF4628C2DE0E67AAF2F"
X-Accept-Language: en
Subject: [Octal-dev] soxchorus.c - SoX chorus.c converted to Octal
Sender: address@hidden
Errors-To: address@hidden
X-BeenThere: address@hidden
X-Mailman-Version: 1.2 (beta 1)
Precedence: bulk
Reply-To: address@hidden
List-Id: OCTAL tracker http://www.gnu.org/software/octal <octal-dev.gnu.org>

--------------24819DF4628C2DE0E67AAF2F
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

After working most of the day to eliminate clicks on some settings
associated with
the cycle speed of a voice and not being successful, I have released
this version
so that anyone else may work on the problem.  I had this similar problem
with the
soxflanger.c but was able to overcome it.  We could use an ability to
write the
final audio output to disk in, say, the signed, 16-bit, little-endian
audio format
seen in output.c.

Additionally, I have made a number of changes to flanger.c but will wait
to release
that code to avoid posting too many copies quickly.

/*   SOXCHORUS.C
*
* This code has been adapted from the SoX chorus.c code:
* August 24, 1998
*
* Copyright (C) 1998 Juergen Mueller And Sundry Contributors
* This source code is freely redistributable and may be used for
* any purpose.  This copyright notice must be maintained.
* Juergen Mueller And Sundry Contributors are not responsible for
* the consequences of using this software.
*
* Conversion to Octal made by:
*
* Copyright 2000 Neil Nelson <address@hidden> June 26, 2000.
*
* This software is distributed under the terms of the
* GNU General Public License (GPL). Read the included file
* COPYING for more information.
*
*
*  Chorus effect.
*
* Flow diagram scheme for n delays ( 1 <= n <= max_chorus ):
*
*        * gain-in                                           ___
* ibuff -----+--------------------------------------------->|   |
*            |      _________                               |   |
*            |     |         |                   * decay 1  |   |
*            +---->| delay 1 |----------------------------->|   |
*            |     |_________|                              |   |
*            |        /|\                                   |   |
*            :         |                                    |   |
*            : +-----------------+   +--------------+       | + |
*            : | Delay control 1 |<--| mod. speed 1 |       |   |
*            : +-----------------+   +--------------+       |   |
*            |      _________                               |   |
*            |     |         |                   * decay n  |   |
*            +---->| delay n |----------------------------->|   |
*                  |_________|                              |   |
*                     /|\                                   |___|
*                      |                                      |
*              +-----------------+   +--------------+         | *
gain-out
*              | Delay control n |<--| mod. speed n |         |
*              +-----------------+   +--------------+
+----->obuff
*
*
* The delay i is controled by a sine or triangle modulation i ( 1 <= i
<= n).
*
* Usage: // SoX command line format.
*   chorus gain-in gain-out delay-1 decay-1 speed-1 depth-1 -s1|t1 [
*       delay-2 decay-2 speed-2 depth-2 -s2|-t2 ... ]
*
* Where:
*   gain-in, decay-1 ... decay-n :  0.0 ... 1.0      volume
*   gain-out :  0.0 ...      volume
*   delay-1 ... delay-n :  20.0 ... 100.0 msec
*   speed-1 ... speed-n :  0.1 ... 5.0 Hz       modulation 1 ... n
*   depth-1 ... depth-n :  0.0 ... 10.0 msec    modulated delay 1 ... n
*   -s1 ... -sn : modulation by sine 1 ... n
*   -t1 ... -tn : modulation by triangle 1 ... n
*
* Note:
*   when decay is close to 1.0, the samples can begin clipping and the
output
*   can saturate!
*
* Hint:
*   1 / out-gain < gain-in ( 1 + decay-1 + ... + decay-n )
*
* Potential Improvements:
*  (1) Except for the expected fixed number of sxc_params, this program
*      could handle an arbitrary number of chorus voices.  What trouble
*      would it be to provide for an arbitrary number of sxc_params?
*
*/

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "util.h"
#include "machine.h"

#define PI2 (6.28318530717958465692)
#define MOD_SINE 0
#define MOD_TRIANGLE 1
#define MOD_SILENT 2

#define DYN_RANGE 10
#define max_chorus 3

/*  The parameters are:  */
enum {
   ix_gain_in, ix_gain_out,
   ix_sxcdecay, ix_sxcdelay, ix_speed, ix_depth, ix_mod_type,
   ix_sxcdecay_1, ix_sxcdelay_1, ix_speed_1, ix_depth_1, ix_mod_type_1,
   ix_sxcdecay_2, ix_sxcdelay_2, ix_speed_2, ix_depth_2, ix_mod_type_2
} param_index;

param_spec sxc_params[] = {
   /*  Param 1: gain_in. */
   {
   small,
   slider,
   "Gain In",
   "Gain In",
   0,           /* 0 gain */
   255,         /* No attenuation */
   200          /* Approx. 80% of dynamic range */
   },

   /*  Param 2: gain_out. */
   {
   small,
   slider,
   "Gain Out",
   "Gain Out",
   0,           /* 0 gain */
   255,         /* No attenuation */
   255
   },

   /*  Param 3: sxcdecay[0]. */
   {
   small,
   slider,
   "Decay 0",
   "Decay of 0th chorus voice.",
   0,
   255,         /* 1 */
   200          /* Approx. 80% of dynamic range */
   },

   /*  Param 4: sxcdelay[0]. */
   {
   small,
   slider,
   "Delay 0",
   "Delay: 20 to 100 msec., for 0th voice.",
   0,           /* Minimum 20 msec. delay  */
   255,         /* Maximum 100 msec. delay */
   128          /* Approx. 60 msec. delay */
   },

   /*  Param 5: speed[0]. */
   {
   small,
   slider,
   "Speed 0",
   "Modulation Speed: 0.1 to 5 Hz., for 0th voice.",
   0,           /* 0.1 Hz */
   255,         /* 5 Hz */
   128          /* Approx. 2.5 Hz */
   },

   /*  Param 6: depth[0]. */
   {
   small,
   slider,
   "Depth 0",
   "Depth Modulation Speed: 0 to 10 msec., for 0th voice.",
   0,           /* 0 msec. depth  */
   255,         /* Maximum 10 msec. depth */
   128          /* Approx. 5 msec. depth */
   },

   /*  Param 7: mod_type[0]. */
   {
   small,
   slider,
   "Modulation 0"
   "Modulation Type: 0=sine (default), 1=triangle, 2=voice off, for 0th
voice.",
   0,           /* Sine  */
   2,           /* Voice off  */
   0            /* Sine by default */
   },

   /*  Param 8: sxcdecay[1]). */
   {
   small,
   slider,
   "Decay 1",
   "Decay of 1st chorus voice.",
   0,
   255,         /* 1 */
   200          /* Approx. 80% of dynamic range */
   },

   /*  Param 9: sxcdelay[1]. */
   {
   small,
   slider,
   "Delay 1",
   "Delay: 20 to 100 msec., for 1st voice.",
   0,           /* Minimum 20 msec. delay  */
   255,         /* Maximum 100 msec. delay */
   128          /* Approx. 60 msec. delay */
   },

   /*  Param 10: speed[1]. */
   {
   small,
   slider,
   "Speed 1",
   "Modulation Speed: 0.1 to 5 Hz., for 1st voice.",
   0,           /* 0.1 Hz */
   255,         /* 5 Hz */
   128          /* Approx. 2.5 Hz */
   },

   /*  Param 11: depth[1]. */
   {
   small,
   slider,
   "Depth 1",
   "Depth Modulation Speed: 0 to 10 msec., for 1st voice.",
   0,           /* 0 msec. depth  */
   255,         /* Maximum 10 msec. depth */
   128          /* Approx. 5 msec. depth */
   },

   /*  Param 12: mod_type[1]. */
   {
   small,
   slider,
   "Modulation 1"
   "Modulation Type: 0=sine (default), 1=triangle, 2=voice off, for 1st
voice.",
   0,           /* Sine  */
   2,           /* Voice off  */
   0            /* Sine by default */
   },

   /*  Param 13: sxcdecay[2]. */
   {
   small,
   slider,
   "Decay 2",
   "Decay of 2nd chorus voice.",
   0,
   255,         /* 1 */
   200          /* Approx. 80% of dynamic range */
   },

   /*  Param 14: sxcdelay[2]. */
   {
   small,
   slider,
   "Delay 2",
   "Delay: 20 to 100 msec., for 2nd voice.",
   0,           /* Minimum 20 msec. delay  */
   255,         /* Maximum 100 msec. delay */
   128          /* Approx. 60 msec. delay */
   },

   /*  Param 15: speed[2]. */
   {
   small,
   slider,
   "Speed 2",
   "Modulation Speed: 0.1 to 5 Hz., for 2nd voice.",
   0,           /* 0.1 Hz */
   255,         /* 5 Hz */
   128          /* Approx. 2.5 Hz */
   },

   /*  Param 16: depth[2]. */
   {
   small,
   slider,
   "Depth 2",
   "Depth Modulation Speed: 0 to 10 msec., for 2nd voice.",
   0,           /* 0 msec. depth  */
   255,         /* Maximum 10 msec. depth */
   128          /* Approx. 5 msec. depth */
   },

   /*  Param 17: mod_type[2]. */
   {
   small,
   slider,
   "Modulation 2"
   "Modulation Type: 0=sine (default), 1=triangle, 2=voice off, for 2nd
voice.",
   0,           /* Sine  */
   2,           /* Voice off  */
   0            /* Sine by default */
   },
};

/*  State of the soxchorus. */

typedef struct {
   float   in_gain, out_gain;
   float   sxcdecay[max_chorus];
   float   sxcdelay[max_chorus];
   float   speed[max_chorus];
   float   depth[max_chorus];
   int     mod_type[max_chorus];
   long    depth_smpls[max_chorus];
   long    ttlchrssmpls[max_chorus];
   int     offset[max_chorus];
   int     phase[max_chorus];
   long    phz_width[max_chorus];
   samp*   chorusbuf;
   float   maxchrsdelay;
   long    maxttlchrssmpls;
   long    maxchrssmpls;
   int     chorus_cntr;
   int     chorus_voices;
   double  unit_vol_scale;
   double  exp_fract_vol;
//   float   clip; // Put in after clipping issue decided.
} sxc_state;

int ox_init(machine_type *t) {
   t->long_name = "soxchorus (Mueller, Nelson, et al.)";
   t->short_name = "soxchorus";
   t->max_tracks = 1;
   t->input_channels = 1;
   t->output_channels = 1;
   t->num_params = 16;
   t->param_specs = sxc_params;

   return 1;
}

void ox_create(machine *m) {
   sxc_state *s;
   int i;

   s = (sxc_state*) malloc(sizeof(sxc_state));

   s->chorus_voices = max_chorus;

   s->unit_vol_scale = exp((double)DYN_RANGE / 3.0) - 1.0;
   s->exp_fract_vol = ((double)DYN_RANGE / 3) / 255.0;

   /* Set defaults */
//   s->in_gain    = 128.0/255.0;   /* Approx. 0.5 (old) */
   s->in_gain  = ((float)exp(200.0 * s->exp_fract_vol) - 1.0)
                 / s->unit_vol_scale;
   s->out_gain   = 1.0;           /* No attenuation */

   s->maxttlchrssmpls = 0;

   s->sxcdecay[0] = ((float)exp(200.0 * s->exp_fract_vol) - 1.0)
                    / s->unit_vol_scale;
   s->sxcdelay[0] = 128.0/255.0 * 80.0 + 20.0; /* Approx. 60 msec. */
   s->speed[0]    = 128.0/255.0 * 4.9 + 0.1;   /* Approx. 2.5 Hz */
   s->depth[0]    = 128.0/255.0 * 10.0;        /* Approx. 5 msec. */
   s->mod_type[0] = 0;                         /* Sine */

   s->sxcdecay[1] = ((float)exp(200.0 * s->exp_fract_vol) - 1.0)
                    / s->unit_vol_scale;
   s->sxcdelay[1] = 0.0/255.0 * 80.0 + 20.0;   /* Approx. 20 msec. */
   s->speed[1]    = 255.0/255.0 * 4.9 + 0.1;   /* 5 Hz */
   s->depth[1]    = 32.0/255.0 * 10.0;         /* Approx. 1.7 msec. */
   s->mod_type[1] = 1;                         /* Triangle */

   s->sxcdecay[2] = ((float)exp(200.0 * s->exp_fract_vol) - 1.0)
                    / s->unit_vol_scale;
   s->sxcdelay[2] = 255.0/255.0 * 80.0 + 20.0; /* Approx. 100 msec. */
   s->speed[2]    = 25.0/255.0 * 4.9 + 0.1;    /* Approx. 0.5 Hz */
   s->depth[2]    = 255.0/255.0 * 10.0;        /* Approx. 10 msec. */
   s->mod_type[2] = 0;                         /* Sine */

   for(i = 0; i < s->chorus_voices; i++) {
//      s->sxcdecay[i] = 128.0/255.0;               /* Approx. 0.5 (old)
*/
//      s->sxcdecay[i] = ((float)exp(200.0 * s->exp_fract_vol) - 1.0)
//                       / s->unit_vol_scale;
//      s->sxcdelay[i] = 128.0/255.0 * 80.0 + 20.0; /* Approx. 60 msec.
*/
//      s->speed[i]    = 128.0/255.0 * 4.9 + 0.1;   /* Approx. 2.5 Hz */

//      s->depth[i]    = 128.0/255.0 * 10.0;        /* Approx. 5 msec.
*/
//      s->mod_type[i] = 0;                         /* Sine */

      s->depth_smpls[i] = (long)(s->depth[i] * ((float)OX_SAMPLING_RATE)
/ 1000.0
                                 + 0.5);
      s->ttlchrssmpls[i] = (long)((s->sxcdelay[i] + s->depth[i])
                         * ((float)OX_SAMPLING_RATE) / 1000.0 + 0.5);

      if (s->ttlchrssmpls[i] > s->maxttlchrssmpls)
         s->maxttlchrssmpls = s->ttlchrssmpls[i];
//         s->maxttlchrssmpls = s->ttlchrssmpls[i] + 11;

      if (s->mod_type[i] == 0)
         s->offset[i] = (int)((s->ttlchrssmpls[i] -1) -
s->depth_smpls[i]);
      else if (s->mod_type[i] == 1)
         s->offset[i] = (int)((s->ttlchrssmpls[i] -1) - 2 *
s->depth_smpls[i]);
      else // if (s->mod_type[i] == 2)
         s->offset[i] = 0;

      s->phz_width[i] = (long)(((float)OX_SAMPLING_RATE) / s->speed[i] +
0.5);
      s->phase[i] = 0;
   }

   s->maxchrsdelay = 120.0;  /* 120 msecs, only 110 msecs obtainable in
program */
   s->maxchrssmpls = (long)(s->maxchrsdelay * ((float)OX_SAMPLING_RATE)
                     / 1000.0 + 0.5);

// s->chorus_cntr = 1; /* Start at 1 to account for add of 1 in phase
shift below */
   s->chorus_cntr = 0;

//   s->clip = ?; // Put in after clipping issue decided.

   s->chorusbuf = (samp*) malloc(s->maxchrssmpls * sizeof(samp));
//   memset(s->chorusbuf, 0, s->maxchrssmpls * sizeof(samp)); //
Unnecessary

   m->state = (void *) s;
   return;
}

void ox_destroy(machine *m) {
   free( ((sxc_state*)(m->state)) -> chorusbuf);
   free(m->state);
   m->state = NULL;
   return;
}

void ox_update(machine *m) {
   sxc_state *s = (sxc_state *) m->state;
   param temp;
   int i, y;

   temp = m->params[0][ix_gain_in];
   if (temp != nochange) {
      if      (temp < 0)   temp = 0;
      else if (temp > 255) temp = 255;
      s->in_gain = ((float)temp) / 255.0;
   }

   temp = m->params[0][ix_gain_out];
   if (temp != nochange) {
      if      (temp < 0)   temp = 0;
      else if (temp > 255) temp = 255;
      s->out_gain = ((float)temp) / 255.0;
   }

   s->maxttlchrssmpls = 0;

   for(i = 0; i < s->chorus_voices; i++) {
      temp = m->params[0][ix_sxcdecay + i * 5];
      if (temp != nochange) {
         if      (temp < 0)   temp = 0;
         else if (temp > 255) temp = 255;

//         s->sxcdecay[i] = ((float)temp) / 255.0; // Old, linear.
         s->sxcdecay[i] = ((float)exp((double)temp * s->exp_fract_vol) -
1.0)
                          / s->unit_vol_scale;
      }

      temp = m->params[0][ix_sxcdelay + i * 5];
      if (temp != nochange) {
         if      (temp < 1)   temp = 1;
         else if (temp > 255) temp = 255;

         s->sxcdelay[i] = ((float)temp) / 255.0 * 5.0;
         s->ttlchrssmpls[i] = (long)(s->sxcdelay[i] *
((float)OX_SAMPLING_RATE)
                               / 1000.0 + 0.5);
      }

      temp = m->params[0][ix_speed + i * 5];
      if (temp != nochange) {
         if      (temp < 10)  temp = 10;
         else if (temp > 255) temp = 255;

         s->speed[i] = ((float)temp) / 255.0 * 2.0;
         s->phz_width[i] = (long)(((float)OX_SAMPLING_RATE) /
s->speed[i] + 0.5);
      }

      temp = m->params[0][ix_depth + i * 5];
      if (temp != nochange) {
         if      (temp < 0)  temp = 0;
         else if (temp > 255) temp = 255;

         s->depth[i] = ((float)temp) / 255.0 * 10.0;
         s->depth_smpls[i] = (long)(s->depth[i] *
((float)OX_SAMPLING_RATE) / 1000.0
                                    + 0.5);
      }

      temp = m->params[0][ix_mod_type + i * 5];
      if (temp != nochange) {
         if (temp > 2 || temp < 0) temp = 2; // If out-of-range, turn
off voice.
         s->mod_type[i] = temp;
      }

      s->ttlchrssmpls[i] = (long)((s->sxcdelay[i] + s->depth[i])
                         * ((float)OX_SAMPLING_RATE) / 1000.0 + 0.5);

      if (s->ttlchrssmpls[i] > s->maxttlchrssmpls)
         s->maxttlchrssmpls = s->ttlchrssmpls[i];
//         s->maxttlchrssmpls = s->ttlchrssmpls[i] + 11;

      if (s->mod_type[i] == 0)
         s->offset[i] = (int)((s->ttlchrssmpls[i] - 1) -
s->depth_smpls[i]);
      else if (s->mod_type[i] == 1)
         s->offset[i] = (int)((s->ttlchrssmpls[i] - 1) - 2 *
s->depth_smpls[i]);
      else // if (s->mod_type[i] == 2)
         s->offset[i] = 0;

   }

   return;
}

const char *ox_desc(int which_param, param value) {
   static char temp_string[80];
   float user_value;
   int i, percent;

   sprintf(temp_string, "ERROR");

   if (which_param == ix_gain_in || which_param == ix_gain_out) {
      if (value < 0) sprintf(temp_string, "Gain must not be less than
0.");
      else {
         user_value = ((float)value) / 255.0;
         percent = (int)(user_value * 100.0 + 0.5);
         if (user_value > 1.0)
            sprintf(temp_string, "Gain must be not greater than 100%.");

         else sprintf(temp_string, "%3.0f%%", percent);
      }
   }

   else {

      for(i = 0; i < max_chorus; i++) {
         if (which_param == (ix_sxcdecay + i * 5)) {
            if (value < 0) sprintf(temp_string, "%s%d%s", "Decay ", i,
                                   " must not be less than 0.");
            else {
               user_value = (float)value / 255.0;
               percent = (int)(user_value * 100.0 + 0.5);
               if (user_value > 1.0)
                  sprintf(temp_string, "%s%d%s", "Decay ", i,
                          "must be not greater than 100%.");

               else sprintf(temp_string, "%3.0f%%", percent);
            }
         }

         else if (which_param == (ix_sxcdelay + i * 5)) {
            if (value < 0) sprintf(temp_string, "%s%d%s", "Delay ", i,
                                   " must not be less than 0 (20
msec.");
            else {
               user_value = (float)value / 255.0 * 80.0 + 20.0;
               if (user_value > 100.0)
                  sprintf(temp_string, "%s%d%s", "Delay ", i,
                          " must be not greater than 100 msec.");

               else sprintf(temp_string, "%3.0f", user_value);
            }
         }

         else if (which_param == ix_speed + i * 5) {
            if (value < 0) sprintf(temp_string, "%s%d%s", "Speed ", i,
                                   " must not be less than 0 (0.1
Hz).");
            else {
               user_value = ((float) value) / 255.0 * 5.0;
               if (user_value > 5.0)
                  sprintf(temp_string, "%s%d%s", "Speed ", i,
                          " must be not greater than 5 Hz.");

               else sprintf(temp_string, "%3.2f", user_value);
            }
         }

         else if (which_param == ix_depth + i * 5) {
            if (value < 0) sprintf(temp_string, "%s%d%s", "Depth ", i,
                                   " must not be less than 0 msec.");
            else {
               user_value = ((float) value) / 255.0 * 10.0;
               if (user_value > 10.0)
                  sprintf(temp_string, "%s%d%s", "Depth ", i,
                          " must be not greater than 10 msec.");

               else sprintf(temp_string, "%3.1f", user_value);
            }
         }

         else if (which_param == ix_mod_type + i * 5) {
            switch (value) {
               case 0  : sprintf(temp_string, "Sine"); break;
               case 1  : sprintf(temp_string, "Triangle"); break;
               default : sprintf(temp_string, "%s%d%s", "Error:
Modulation", i,
                           "type must be 0 = sine, 1 = triangle, or 2 =
voice off.");
            }
         }
      }
   }

/* SoX: Clipping - Be nice and check the hint with warning, if...
   if ( flanger->in_gain * ( 1.0 + flanger->sxcdecay ) > 1.0 /
flanger->out_gain )
      warn("flanger: warning >>> gain-out can cause saturation or
clipping of output <<<");
*/

}

int ox_work(machine *m, int block_size) {
   sxc_state *s = (sxc_state *) m->state;
   int i, j, x_phz, ytemp;
   float x_flt, ingain, outgain; // dcy, phzdepth, phz2depth, phz2width;

   samp* mlout;
//   samp* mrout;
   samp* mlin;
   samp* chrsbuf;

   mlout    = m->lout;
//   mrout    = m->rout;
   mlin     = m->lin;

   ingain   = s->in_gain;
   outgain  = s->out_gain;
   chrsbuf  = s->chorusbuf;

   for(i = 0; i < block_size; i++) {

      /* Compute output first */
      mlout[i] = mlin[i] * ingain;

      for ( j = 0; j < s->chorus_voices; j++ ) {

         if (s->mod_type[j] != MOD_SILENT) { // Start no indent
         if (s->mod_type[j] == MOD_SINE) {

            // Get sine phase shift. 1 added to correct noise at 0.
            x_flt = (float)
sin((double)s->phase[j]/(double)s->phz_width[j] * PI2);
            x_phz = s->offset[j] + (int) (x_flt *
(double)s->depth_smpls[j] + 0.5);
//                    + 1;
         }

         else { // s->mod_type[j] == MOD_TRIANGLE

            // Compute triangle - ramp up and down.
            if (s->phase[j] < (s->phz_width[j] / 2)) { // Ramp up
               x_flt = (float)s->phase[j] * 2.0 /
(float)s->phz_width[j];
               x_phz = s->offset[j] + (int) (x_flt * 2.0 *
(float)s->depth_smpls[j]
                                             + 0.5);
            }

            else { // Ramp down
               x_flt = (float)(s->phz_width[j] - s->phase[j]) * 2.0
                       / (float)s->phz_width[j];
               x_phz = s->offset[j] + (int) (x_flt * 2.0 *
(float)s->depth_smpls[j]
                                             + 0.5);
            }
         }

         mlout[i] += chrsbuf[(s->maxttlchrssmpls + s->chorus_cntr
                                - x_phz) % s->maxttlchrssmpls] *
s->sxcdecay[j];
         } // End no indent
      }

      /* Adjust the output volume. */
      mlout[i] *= outgain;

      /* Check for clipping.  Not implemented. */
//      if      (mlout[i] > hig_clip)  mlout[i] = hig_clip;
//      else if (mlout[i] < low_clip)  mlout[i] = low_clip;

      /* Mix decay of delay and input */
      chrsbuf[s->chorus_cntr] = mlin[i];

      s->chorus_cntr = ( s->chorus_cntr + 1 ) % s->maxttlchrssmpls;

      for ( j = 0; j < s->chorus_voices; j++ )
         s->phase[j] = ( s->phase[j] + 1 ) % s->phz_width[j];
   }

   /* Save speedup variables to state. */

   return 1;
}

void ox_track(machine *m, int change) {
}


--------------24819DF4628C2DE0E67AAF2F
Content-Type: text/html; charset=us-ascii
Content-Transfer-Encoding: 7bit

<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
<html>
After working most of the day to eliminate clicks on some settings associated
with
<br>the cycle speed of a voice and not being successful, I have released
this version
<br>so that anyone else may work on the problem.&nbsp; I had this similar
problem with the
<br>soxflanger.c but was able to overcome it.&nbsp; We could use an ability
to write the
<br>final audio output to disk in, say, the signed, 16-bit, little-endian
audio format
<br>seen in output.c.
<p>Additionally, I have made a number of changes to flanger.c but will
wait to release
<br>that code to avoid posting too many copies quickly.<tt></tt>
<p><tt>/*&nbsp;&nbsp; SOXCHORUS.C</tt>
<br><tt>*</tt>
<br><tt>* This code has been adapted from the SoX chorus.c code:</tt>
<br><tt>* August 24, 1998</tt>
<br><tt>*</tt>
<br><tt>* Copyright (C) 1998 Juergen Mueller And Sundry Contributors</tt>
<br><tt>* This source code is freely redistributable and may be used for</tt>
<br><tt>* any purpose.&nbsp; This copyright notice must be maintained.</tt>
<br><tt>* Juergen Mueller And Sundry Contributors are not responsible for</tt>
<br><tt>* the consequences of using this software.</tt>
<br><tt>*</tt>
<br><tt>* Conversion to Octal made by:</tt>
<br><tt>*</tt>
<br><tt>* Copyright 2000 Neil Nelson &lt;address@hidden> June 26,
2000.</tt>
<br><tt>*</tt>
<br><tt>* This software is distributed under the terms of the</tt>
<br><tt>* GNU General Public License (GPL). Read the included file</tt>
<br><tt>* COPYING for more information.</tt>
<br><tt>*</tt>
<br><tt>*</tt>
<br><tt>*&nbsp; Chorus effect.</tt>
<br><tt>*</tt>
<br><tt>* Flow diagram scheme for n delays ( 1 &lt;= n &lt;= max_chorus
):</tt>
<br><tt>*</tt>
<br><tt>*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * 
gain-in&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
___</tt>
<br><tt>* ibuff 
-----+--------------------------------------------->|&nbsp;&nbsp;
|</tt>
<br><tt>*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
_________&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
|&nbsp;&nbsp; |</tt>
<br><tt>*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
|&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
* decay 1&nbsp; |&nbsp;&nbsp; |</tt>
<br><tt>*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+---->| delay 1 |----------------------------->|&nbsp;&nbsp; |</tt>
<br><tt>*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
|&nbsp;&nbsp;&nbsp;&nbsp; 
|_________|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
|&nbsp;&nbsp; |</tt>
<br><tt>*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
/|\&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
|&nbsp;&nbsp; |</tt>
<br><tt>*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
|&nbsp;&nbsp; |</tt>
<br><tt>*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
: +-----------------+&nbsp;&nbsp; 
+--------------+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
| + |</tt>
<br><tt>*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
: | Delay control 1 |&lt;--| mod. speed 1 |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
|&nbsp;&nbsp; |</tt>
<br><tt>*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
: +-----------------+&nbsp;&nbsp; 
+--------------+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
|&nbsp;&nbsp; |</tt>
<br><tt>*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
_________&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
|&nbsp;&nbsp; |</tt>
<br><tt>*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
|&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
* decay n&nbsp; |&nbsp;&nbsp; |</tt>
<br><tt>*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+---->| delay n |----------------------------->|&nbsp;&nbsp; |</tt>
<br><tt>*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
|_________|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
|&nbsp;&nbsp; |</tt>
<br><tt>*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/|\&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
|___|</tt>
<br><tt>*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
|</tt>
<br><tt>*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+-----------------+&nbsp;&nbsp; 
+--------------+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
| * gain-out</tt>
<br><tt>*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
| Delay control n |&lt;--| mod. speed n 
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
|</tt>
<br><tt>*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+-----------------+&nbsp;&nbsp; 
+--------------+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+----->obuff</tt>
<br><tt>*</tt>
<br><tt>*</tt>
<br><tt>* The delay i is controled by a sine or triangle modulation i (
1 &lt;= i &lt;= n).</tt>
<br><tt>*</tt>
<br><tt>* Usage: // SoX command line format.</tt>
<br><tt>*&nbsp;&nbsp; chorus gain-in gain-out delay-1 decay-1 speed-1 depth-1
-s1|t1 [</tt>
<br><tt>*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; delay-2 decay-2 speed-2 depth-2
-s2|-t2 ... ]</tt>
<br><tt>*</tt>
<br><tt>* Where:</tt>
<br><tt>*&nbsp;&nbsp; gain-in, decay-1 ... decay-n :&nbsp; 0.0 ... 
1.0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
volume</tt>
<br><tt>*&nbsp;&nbsp; gain-out :&nbsp; 0.0 ...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
volume</tt>
<br><tt>*&nbsp;&nbsp; delay-1 ... delay-n :&nbsp; 20.0 ... 100.0 msec</tt>
<br><tt>*&nbsp;&nbsp; speed-1 ... speed-n :&nbsp; 0.1 ... 5.0 
Hz&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
modulation 1 ... n</tt>
<br><tt>*&nbsp;&nbsp; depth-1 ... depth-n :&nbsp; 0.0 ... 10.0 
msec&nbsp;&nbsp;&nbsp;
modulated delay 1 ... n</tt>
<br><tt>*&nbsp;&nbsp; -s1 ... -sn : modulation by sine 1 ... n</tt>
<br><tt>*&nbsp;&nbsp; -t1 ... -tn : modulation by triangle 1 ... n</tt>
<br><tt>*</tt>
<br><tt>* Note:</tt>
<br><tt>*&nbsp;&nbsp; when decay is close to 1.0, the samples can begin
clipping and the output</tt>
<br><tt>*&nbsp;&nbsp; can saturate!</tt>
<br><tt>*</tt>
<br><tt>* Hint:</tt>
<br><tt>*&nbsp;&nbsp; 1 / out-gain &lt; gain-in ( 1 + decay-1 + ... + decay-n
)</tt>
<br><tt>*</tt>
<br><tt>* Potential Improvements:</tt>
<br><tt>*&nbsp; (1) Except for the expected fixed number of sxc_params,
this program</tt>
<br><tt>*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; could handle an arbitrary number
of chorus voices.&nbsp; What trouble</tt>
<br><tt>*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; would it be to provide for an arbitrary
number of sxc_params?</tt>
<br><tt>*</tt>
<br><tt>*/</tt><tt></tt>
<p><tt>#include &lt;stdio.h></tt>
<br><tt>#include &lt;stdlib.h></tt>
<br><tt>#include &lt;math.h></tt>
<br><tt>#include "util.h"</tt>
<br><tt>#include "machine.h"</tt><tt></tt>
<p><tt>#define PI2 (6.28318530717958465692)</tt>
<br><tt>#define MOD_SINE 0</tt>
<br><tt>#define MOD_TRIANGLE 1</tt>
<br><tt>#define MOD_SILENT 2</tt><tt></tt>
<p><tt>#define DYN_RANGE 10</tt>
<br><tt>#define max_chorus 3</tt><tt></tt>
<p><tt>/*&nbsp; The parameters are:&nbsp; */</tt>
<br><tt>enum {</tt>
<br><tt>&nbsp;&nbsp; ix_gain_in, ix_gain_out,</tt>
<br><tt>&nbsp;&nbsp; ix_sxcdecay, ix_sxcdelay, ix_speed, ix_depth, 
ix_mod_type,</tt>
<br><tt>&nbsp;&nbsp; ix_sxcdecay_1, ix_sxcdelay_1, ix_speed_1, ix_depth_1,
ix_mod_type_1,</tt>
<br><tt>&nbsp;&nbsp; ix_sxcdecay_2, ix_sxcdelay_2, ix_speed_2, ix_depth_2,
ix_mod_type_2</tt>
<br><tt>} param_index;</tt><tt></tt>
<p><tt>param_spec sxc_params[] = {</tt>
<br><tt>&nbsp;&nbsp; /*&nbsp; Param 1: gain_in. */</tt>
<br><tt>&nbsp;&nbsp; {</tt>
<br><tt>&nbsp;&nbsp; small,</tt>
<br><tt>&nbsp;&nbsp; slider,</tt>
<br><tt>&nbsp;&nbsp; "Gain In",</tt>
<br><tt>&nbsp;&nbsp; "Gain In",</tt>
<br><tt>&nbsp;&nbsp; 
0,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* 0 gain */</tt>
<br><tt>&nbsp;&nbsp; 255,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* No attenuation */</tt>
<br><tt>&nbsp;&nbsp; 200&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* Approx. 80% of dynamic range */</tt>
<br><tt>&nbsp;&nbsp; },</tt><tt></tt>
<p><tt>&nbsp;&nbsp; /*&nbsp; Param 2: gain_out. */</tt>
<br><tt>&nbsp;&nbsp; {</tt>
<br><tt>&nbsp;&nbsp; small,</tt>
<br><tt>&nbsp;&nbsp; slider,</tt>
<br><tt>&nbsp;&nbsp; "Gain Out",</tt>
<br><tt>&nbsp;&nbsp; "Gain Out",</tt>
<br><tt>&nbsp;&nbsp; 
0,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* 0 gain */</tt>
<br><tt>&nbsp;&nbsp; 255,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* No attenuation */</tt>
<br><tt>&nbsp;&nbsp; 255</tt>
<br><tt>&nbsp;&nbsp; },</tt><tt></tt>
<p><tt>&nbsp;&nbsp; /*&nbsp; Param 3: sxcdecay[0]. */</tt>
<br><tt>&nbsp;&nbsp; {</tt>
<br><tt>&nbsp;&nbsp; small,</tt>
<br><tt>&nbsp;&nbsp; slider,</tt>
<br><tt>&nbsp;&nbsp; "Decay 0",</tt>
<br><tt>&nbsp;&nbsp; "Decay of 0th chorus voice.",</tt>
<br><tt>&nbsp;&nbsp; 0,</tt>
<br><tt>&nbsp;&nbsp; 255,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* 1 */</tt>
<br><tt>&nbsp;&nbsp; 200&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* Approx. 80% of dynamic range */</tt>
<br><tt>&nbsp;&nbsp; },</tt><tt></tt>
<p><tt>&nbsp;&nbsp; /*&nbsp; Param 4: sxcdelay[0]. */</tt>
<br><tt>&nbsp;&nbsp; {</tt>
<br><tt>&nbsp;&nbsp; small,</tt>
<br><tt>&nbsp;&nbsp; slider,</tt>
<br><tt>&nbsp;&nbsp; "Delay 0",</tt>
<br><tt>&nbsp;&nbsp; "Delay: 20 to 100 msec., for 0th voice.",</tt>
<br><tt>&nbsp;&nbsp; 
0,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* Minimum 20 msec. delay&nbsp; */</tt>
<br><tt>&nbsp;&nbsp; 255,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* Maximum 100 msec. delay */</tt>
<br><tt>&nbsp;&nbsp; 128&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* Approx. 60 msec. delay */</tt>
<br><tt>&nbsp;&nbsp; },</tt><tt></tt>
<p><tt>&nbsp;&nbsp; /*&nbsp; Param 5: speed[0]. */</tt>
<br><tt>&nbsp;&nbsp; {</tt>
<br><tt>&nbsp;&nbsp; small,</tt>
<br><tt>&nbsp;&nbsp; slider,</tt>
<br><tt>&nbsp;&nbsp; "Speed 0",</tt>
<br><tt>&nbsp;&nbsp; "Modulation Speed: 0.1 to 5 Hz., for 0th voice.",</tt>
<br><tt>&nbsp;&nbsp; 
0,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* 0.1 Hz */</tt>
<br><tt>&nbsp;&nbsp; 255,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* 5 Hz */</tt>
<br><tt>&nbsp;&nbsp; 128&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* Approx. 2.5 Hz */</tt>
<br><tt>&nbsp;&nbsp; },</tt><tt></tt>
<p><tt>&nbsp;&nbsp; /*&nbsp; Param 6: depth[0]. */</tt>
<br><tt>&nbsp;&nbsp; {</tt>
<br><tt>&nbsp;&nbsp; small,</tt>
<br><tt>&nbsp;&nbsp; slider,</tt>
<br><tt>&nbsp;&nbsp; "Depth 0",</tt>
<br><tt>&nbsp;&nbsp; "Depth Modulation Speed: 0 to 10 msec., for 0th 
voice.",</tt>
<br><tt>&nbsp;&nbsp; 
0,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* 0 msec. depth&nbsp; */</tt>
<br><tt>&nbsp;&nbsp; 255,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* Maximum 10 msec. depth */</tt>
<br><tt>&nbsp;&nbsp; 128&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* Approx. 5 msec. depth */</tt>
<br><tt>&nbsp;&nbsp; },</tt><tt></tt>
<p><tt>&nbsp;&nbsp; /*&nbsp; Param 7: mod_type[0]. */</tt>
<br><tt>&nbsp;&nbsp; {</tt>
<br><tt>&nbsp;&nbsp; small,</tt>
<br><tt>&nbsp;&nbsp; slider,</tt>
<br><tt>&nbsp;&nbsp; "Modulation 0"</tt>
<br><tt>&nbsp;&nbsp; "Modulation Type: 0=sine (default), 1=triangle, 2=voice
off, for 0th voice.",</tt>
<br><tt>&nbsp;&nbsp; 
0,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* Sine&nbsp; */</tt>
<br><tt>&nbsp;&nbsp; 
2,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* Voice off&nbsp; */</tt>
<br><tt>&nbsp;&nbsp; 
0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* Sine by default */</tt>
<br><tt>&nbsp;&nbsp; },</tt><tt></tt>
<p><tt>&nbsp;&nbsp; /*&nbsp; Param 8: sxcdecay[1]). */</tt>
<br><tt>&nbsp;&nbsp; {</tt>
<br><tt>&nbsp;&nbsp; small,</tt>
<br><tt>&nbsp;&nbsp; slider,</tt>
<br><tt>&nbsp;&nbsp; "Decay 1",</tt>
<br><tt>&nbsp;&nbsp; "Decay of 1st chorus voice.",</tt>
<br><tt>&nbsp;&nbsp; 0,</tt>
<br><tt>&nbsp;&nbsp; 255,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* 1 */</tt>
<br><tt>&nbsp;&nbsp; 200&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* Approx. 80% of dynamic range */</tt>
<br><tt>&nbsp;&nbsp; },</tt><tt></tt>
<p><tt>&nbsp;&nbsp; /*&nbsp; Param 9: sxcdelay[1]. */</tt>
<br><tt>&nbsp;&nbsp; {</tt>
<br><tt>&nbsp;&nbsp; small,</tt>
<br><tt>&nbsp;&nbsp; slider,</tt>
<br><tt>&nbsp;&nbsp; "Delay 1",</tt>
<br><tt>&nbsp;&nbsp; "Delay: 20 to 100 msec., for 1st voice.",</tt>
<br><tt>&nbsp;&nbsp; 
0,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* Minimum 20 msec. delay&nbsp; */</tt>
<br><tt>&nbsp;&nbsp; 255,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* Maximum 100 msec. delay */</tt>
<br><tt>&nbsp;&nbsp; 128&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* Approx. 60 msec. delay */</tt>
<br><tt>&nbsp;&nbsp; },</tt><tt></tt>
<p><tt>&nbsp;&nbsp; /*&nbsp; Param 10: speed[1]. */</tt>
<br><tt>&nbsp;&nbsp; {</tt>
<br><tt>&nbsp;&nbsp; small,</tt>
<br><tt>&nbsp;&nbsp; slider,</tt>
<br><tt>&nbsp;&nbsp; "Speed 1",</tt>
<br><tt>&nbsp;&nbsp; "Modulation Speed: 0.1 to 5 Hz., for 1st voice.",</tt>
<br><tt>&nbsp;&nbsp; 
0,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* 0.1 Hz */</tt>
<br><tt>&nbsp;&nbsp; 255,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* 5 Hz */</tt>
<br><tt>&nbsp;&nbsp; 128&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* Approx. 2.5 Hz */</tt>
<br><tt>&nbsp;&nbsp; },</tt><tt></tt>
<p><tt>&nbsp;&nbsp; /*&nbsp; Param 11: depth[1]. */</tt>
<br><tt>&nbsp;&nbsp; {</tt>
<br><tt>&nbsp;&nbsp; small,</tt>
<br><tt>&nbsp;&nbsp; slider,</tt>
<br><tt>&nbsp;&nbsp; "Depth 1",</tt>
<br><tt>&nbsp;&nbsp; "Depth Modulation Speed: 0 to 10 msec., for 1st 
voice.",</tt>
<br><tt>&nbsp;&nbsp; 
0,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* 0 msec. depth&nbsp; */</tt>
<br><tt>&nbsp;&nbsp; 255,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* Maximum 10 msec. depth */</tt>
<br><tt>&nbsp;&nbsp; 128&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* Approx. 5 msec. depth */</tt>
<br><tt>&nbsp;&nbsp; },</tt><tt></tt>
<p><tt>&nbsp;&nbsp; /*&nbsp; Param 12: mod_type[1]. */</tt>
<br><tt>&nbsp;&nbsp; {</tt>
<br><tt>&nbsp;&nbsp; small,</tt>
<br><tt>&nbsp;&nbsp; slider,</tt>
<br><tt>&nbsp;&nbsp; "Modulation 1"</tt>
<br><tt>&nbsp;&nbsp; "Modulation Type: 0=sine (default), 1=triangle, 2=voice
off, for 1st voice.",</tt>
<br><tt>&nbsp;&nbsp; 
0,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* Sine&nbsp; */</tt>
<br><tt>&nbsp;&nbsp; 
2,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* Voice off&nbsp; */</tt>
<br><tt>&nbsp;&nbsp; 
0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* Sine by default */</tt>
<br><tt>&nbsp;&nbsp; },</tt><tt></tt>
<p><tt>&nbsp;&nbsp; /*&nbsp; Param 13: sxcdecay[2]. */</tt>
<br><tt>&nbsp;&nbsp; {</tt>
<br><tt>&nbsp;&nbsp; small,</tt>
<br><tt>&nbsp;&nbsp; slider,</tt>
<br><tt>&nbsp;&nbsp; "Decay 2",</tt>
<br><tt>&nbsp;&nbsp; "Decay of 2nd chorus voice.",</tt>
<br><tt>&nbsp;&nbsp; 0,</tt>
<br><tt>&nbsp;&nbsp; 255,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* 1 */</tt>
<br><tt>&nbsp;&nbsp; 200&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* Approx. 80% of dynamic range */</tt>
<br><tt>&nbsp;&nbsp; },</tt><tt></tt>
<p><tt>&nbsp;&nbsp; /*&nbsp; Param 14: sxcdelay[2]. */</tt>
<br><tt>&nbsp;&nbsp; {</tt>
<br><tt>&nbsp;&nbsp; small,</tt>
<br><tt>&nbsp;&nbsp; slider,</tt>
<br><tt>&nbsp;&nbsp; "Delay 2",</tt>
<br><tt>&nbsp;&nbsp; "Delay: 20 to 100 msec., for 2nd voice.",</tt>
<br><tt>&nbsp;&nbsp; 
0,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* Minimum 20 msec. delay&nbsp; */</tt>
<br><tt>&nbsp;&nbsp; 255,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* Maximum 100 msec. delay */</tt>
<br><tt>&nbsp;&nbsp; 128&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* Approx. 60 msec. delay */</tt>
<br><tt>&nbsp;&nbsp; },</tt><tt></tt>
<p><tt>&nbsp;&nbsp; /*&nbsp; Param 15: speed[2]. */</tt>
<br><tt>&nbsp;&nbsp; {</tt>
<br><tt>&nbsp;&nbsp; small,</tt>
<br><tt>&nbsp;&nbsp; slider,</tt>
<br><tt>&nbsp;&nbsp; "Speed 2",</tt>
<br><tt>&nbsp;&nbsp; "Modulation Speed: 0.1 to 5 Hz., for 2nd voice.",</tt>
<br><tt>&nbsp;&nbsp; 
0,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* 0.1 Hz */</tt>
<br><tt>&nbsp;&nbsp; 255,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* 5 Hz */</tt>
<br><tt>&nbsp;&nbsp; 128&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* Approx. 2.5 Hz */</tt>
<br><tt>&nbsp;&nbsp; },</tt><tt></tt>
<p><tt>&nbsp;&nbsp; /*&nbsp; Param 16: depth[2]. */</tt>
<br><tt>&nbsp;&nbsp; {</tt>
<br><tt>&nbsp;&nbsp; small,</tt>
<br><tt>&nbsp;&nbsp; slider,</tt>
<br><tt>&nbsp;&nbsp; "Depth 2",</tt>
<br><tt>&nbsp;&nbsp; "Depth Modulation Speed: 0 to 10 msec., for 2nd 
voice.",</tt>
<br><tt>&nbsp;&nbsp; 
0,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* 0 msec. depth&nbsp; */</tt>
<br><tt>&nbsp;&nbsp; 255,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* Maximum 10 msec. depth */</tt>
<br><tt>&nbsp;&nbsp; 128&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* Approx. 5 msec. depth */</tt>
<br><tt>&nbsp;&nbsp; },</tt><tt></tt>
<p><tt>&nbsp;&nbsp; /*&nbsp; Param 17: mod_type[2]. */</tt>
<br><tt>&nbsp;&nbsp; {</tt>
<br><tt>&nbsp;&nbsp; small,</tt>
<br><tt>&nbsp;&nbsp; slider,</tt>
<br><tt>&nbsp;&nbsp; "Modulation 2"</tt>
<br><tt>&nbsp;&nbsp; "Modulation Type: 0=sine (default), 1=triangle, 2=voice
off, for 2nd voice.",</tt>
<br><tt>&nbsp;&nbsp; 
0,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* Sine&nbsp; */</tt>
<br><tt>&nbsp;&nbsp; 
2,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* Voice off&nbsp; */</tt>
<br><tt>&nbsp;&nbsp; 
0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* Sine by default */</tt>
<br><tt>&nbsp;&nbsp; },</tt>
<br><tt>};</tt><tt></tt>
<p><tt>/*&nbsp; State of the soxchorus. */</tt><tt></tt>
<p><tt>typedef struct {</tt>
<br><tt>&nbsp;&nbsp; float&nbsp;&nbsp; in_gain, out_gain;</tt>
<br><tt>&nbsp;&nbsp; float&nbsp;&nbsp; sxcdecay[max_chorus];</tt>
<br><tt>&nbsp;&nbsp; float&nbsp;&nbsp; sxcdelay[max_chorus];</tt>
<br><tt>&nbsp;&nbsp; float&nbsp;&nbsp; speed[max_chorus];</tt>
<br><tt>&nbsp;&nbsp; float&nbsp;&nbsp; depth[max_chorus];</tt>
<br><tt>&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp; mod_type[max_chorus];</tt>
<br><tt>&nbsp;&nbsp; long&nbsp;&nbsp;&nbsp; depth_smpls[max_chorus];</tt>
<br><tt>&nbsp;&nbsp; long&nbsp;&nbsp;&nbsp; ttlchrssmpls[max_chorus];</tt>
<br><tt>&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp; offset[max_chorus];</tt>
<br><tt>&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp; phase[max_chorus];</tt>
<br><tt>&nbsp;&nbsp; long&nbsp;&nbsp;&nbsp; phz_width[max_chorus];</tt>
<br><tt>&nbsp;&nbsp; samp*&nbsp;&nbsp; chorusbuf;</tt>
<br><tt>&nbsp;&nbsp; float&nbsp;&nbsp; maxchrsdelay;</tt>
<br><tt>&nbsp;&nbsp; long&nbsp;&nbsp;&nbsp; maxttlchrssmpls;</tt>
<br><tt>&nbsp;&nbsp; long&nbsp;&nbsp;&nbsp; maxchrssmpls;</tt>
<br><tt>&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp; chorus_cntr;</tt>
<br><tt>&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp; chorus_voices;</tt>
<br><tt>&nbsp;&nbsp; double&nbsp; unit_vol_scale;</tt>
<br><tt>&nbsp;&nbsp; double&nbsp; exp_fract_vol;</tt>
<br><tt>//&nbsp;&nbsp; float&nbsp;&nbsp; clip; // Put in after clipping
issue decided.</tt>
<br><tt>} sxc_state;</tt><tt></tt>
<p><tt>int ox_init(machine_type *t) {</tt>
<br><tt>&nbsp;&nbsp; t->long_name = "soxchorus (Mueller, Nelson, et al.)";</tt>
<br><tt>&nbsp;&nbsp; t->short_name = "soxchorus";</tt>
<br><tt>&nbsp;&nbsp; t->max_tracks = 1;</tt>
<br><tt>&nbsp;&nbsp; t->input_channels = 1;</tt>
<br><tt>&nbsp;&nbsp; t->output_channels = 1;</tt>
<br><tt>&nbsp;&nbsp; t->num_params = 16;</tt>
<br><tt>&nbsp;&nbsp; t->param_specs = sxc_params;</tt><tt></tt>
<p><tt>&nbsp;&nbsp; return 1;</tt>
<br><tt>}</tt><tt></tt>
<p><tt>void ox_create(machine *m) {</tt>
<br><tt>&nbsp;&nbsp; sxc_state *s;</tt>
<br><tt>&nbsp;&nbsp; int i;</tt><tt></tt>
<p><tt>&nbsp;&nbsp; s = (sxc_state*) malloc(sizeof(sxc_state));</tt><tt></tt>
<p><tt>&nbsp;&nbsp; s->chorus_voices = max_chorus;</tt><tt></tt>
<p><tt>&nbsp;&nbsp; s->unit_vol_scale = exp((double)DYN_RANGE / 3.0) -
1.0;</tt>
<br><tt>&nbsp;&nbsp; s->exp_fract_vol = ((double)DYN_RANGE / 3) / 
255.0;</tt><tt></tt>
<p><tt>&nbsp;&nbsp; /* Set defaults */</tt>
<br><tt>//&nbsp;&nbsp; s->in_gain&nbsp;&nbsp;&nbsp; = 128.0/255.0;&nbsp;&nbsp;
/* Approx. 0.5 (old) */</tt>
<br><tt>&nbsp;&nbsp; s->in_gain&nbsp; = ((float)exp(200.0 * s->exp_fract_vol)
- 1.0)</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/ s->unit_vol_scale;</tt>
<br><tt>&nbsp;&nbsp; s->out_gain&nbsp;&nbsp; = 
1.0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* No attenuation */</tt><tt></tt>
<p><tt>&nbsp;&nbsp; s->maxttlchrssmpls = 0;</tt><tt></tt>
<p><tt>&nbsp;&nbsp; s->sxcdecay[0] = ((float)exp(200.0 * s->exp_fract_vol)
- 1.0)</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/ s->unit_vol_scale;</tt>
<br><tt>&nbsp;&nbsp; s->sxcdelay[0] = 128.0/255.0 * 80.0 + 20.0; /* Approx.
60 msec. */</tt>
<br><tt>&nbsp;&nbsp; s->speed[0]&nbsp;&nbsp;&nbsp; = 128.0/255.0 * 4.9
+ 0.1;&nbsp;&nbsp; /* Approx. 2.5 Hz */</tt>
<br><tt>&nbsp;&nbsp; s->depth[0]&nbsp;&nbsp;&nbsp; = 128.0/255.0 * 
10.0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* Approx. 5 msec. */</tt>
<br><tt>&nbsp;&nbsp; s->mod_type[0] = 
0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* Sine */</tt><tt></tt>
<p><tt>&nbsp;&nbsp; s->sxcdecay[1] = ((float)exp(200.0 * s->exp_fract_vol)
- 1.0)</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/ s->unit_vol_scale;</tt>
<br><tt>&nbsp;&nbsp; s->sxcdelay[1] = 0.0/255.0 * 80.0 + 20.0;&nbsp;&nbsp;
/* Approx. 20 msec. */</tt>
<br><tt>&nbsp;&nbsp; s->speed[1]&nbsp;&nbsp;&nbsp; = 255.0/255.0 * 4.9
+ 0.1;&nbsp;&nbsp; /* 5 Hz */</tt>
<br><tt>&nbsp;&nbsp; s->depth[1]&nbsp;&nbsp;&nbsp; = 32.0/255.0 * 
10.0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* Approx. 1.7 msec. */</tt>
<br><tt>&nbsp;&nbsp; s->mod_type[1] = 
1;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* Triangle */</tt><tt></tt>
<p><tt>&nbsp;&nbsp; s->sxcdecay[2] = ((float)exp(200.0 * s->exp_fract_vol)
- 1.0)</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/ s->unit_vol_scale;</tt>
<br><tt>&nbsp;&nbsp; s->sxcdelay[2] = 255.0/255.0 * 80.0 + 20.0; /* Approx.
100 msec. */</tt>
<br><tt>&nbsp;&nbsp; s->speed[2]&nbsp;&nbsp;&nbsp; = 25.0/255.0 * 4.9 +
0.1;&nbsp;&nbsp;&nbsp; /* Approx. 0.5 Hz */</tt>
<br><tt>&nbsp;&nbsp; s->depth[2]&nbsp;&nbsp;&nbsp; = 255.0/255.0 * 
10.0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* Approx. 10 msec. */</tt>
<br><tt>&nbsp;&nbsp; s->mod_type[2] = 
0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* Sine */</tt><tt></tt>
<p><tt>&nbsp;&nbsp; for(i = 0; i &lt; s->chorus_voices; i++) {</tt>
<br><tt>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s->sxcdecay[i] = 
128.0/255.0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* Approx. 0.5 (old) */</tt>
<br><tt>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s->sxcdecay[i] = ((float)exp(200.0
* s->exp_fract_vol) - 1.0)</tt>
<br><tt>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/ s->unit_vol_scale;</tt>
<br><tt>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s->sxcdelay[i] = 128.0/255.0 *
80.0 + 20.0; /* Approx. 60 msec. */</tt>
<br><tt>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s->speed[i]&nbsp;&nbsp;&nbsp;
= 128.0/255.0 * 4.9 + 0.1;&nbsp;&nbsp; /* Approx. 2.5 Hz */</tt>
<br><tt>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s->depth[i]&nbsp;&nbsp;&nbsp;
= 128.0/255.0 * 10.0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Approx.
5 msec. */</tt>
<br><tt>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s->mod_type[i] = 
0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* Sine */</tt><tt></tt>
<p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s->depth_smpls[i] = (long)(s->depth[i]
* ((float)OX_SAMPLING_RATE) / 1000.0</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ 0.5);</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s->ttlchrssmpls[i] = 
(long)((s->sxcdelay[i]
+ s->depth[i])</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
* ((float)OX_SAMPLING_RATE) / 1000.0 + 0.5);</tt><tt></tt>
<p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (s->ttlchrssmpls[i] > 
s->maxttlchrssmpls)</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s->maxttlchrssmpls
= s->ttlchrssmpls[i];</tt>
<br><tt>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s->maxttlchrssmpls
= s->ttlchrssmpls[i] + 11;</tt><tt></tt>
<p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (s->mod_type[i] == 0)</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s->offset[i] =
(int)((s->ttlchrssmpls[i] -1) - s->depth_smpls[i]);</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else if (s->mod_type[i] == 1)</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s->offset[i] =
(int)((s->ttlchrssmpls[i] -1) - 2 * s->depth_smpls[i]);</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else // if (s->mod_type[i] == 2)</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s->offset[i] =
0;</tt><tt></tt>
<p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s->phz_width[i] = 
(long)(((float)OX_SAMPLING_RATE)
/ s->speed[i] + 0.5);</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s->phase[i] = 0;</tt>
<br><tt>&nbsp;&nbsp; }</tt><tt></tt>
<p><tt>&nbsp;&nbsp; s->maxchrsdelay = 120.0;&nbsp; /* 120 msecs, only 110
msecs obtainable in program */</tt>
<br><tt>&nbsp;&nbsp; s->maxchrssmpls = (long)(s->maxchrsdelay * 
((float)OX_SAMPLING_RATE)</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/ 1000.0 + 0.5);</tt><tt></tt>
<p><tt>// s->chorus_cntr = 1; /* Start at 1 to account for add of 1 in
phase shift below */</tt>
<br><tt>&nbsp;&nbsp; s->chorus_cntr = 0;</tt><tt></tt>
<p><tt>//&nbsp;&nbsp; s->clip = ?; // Put in after clipping issue 
decided.</tt><tt></tt>
<p><tt>&nbsp;&nbsp; s->chorusbuf = (samp*) malloc(s->maxchrssmpls * 
sizeof(samp));</tt>
<br><tt>//&nbsp;&nbsp; memset(s->chorusbuf, 0, s->maxchrssmpls * sizeof(samp));
// Unnecessary</tt><tt></tt>
<p><tt>&nbsp;&nbsp; m->state = (void *) s;</tt>
<br><tt>&nbsp;&nbsp; return;</tt>
<br><tt>}</tt><tt></tt>
<p><tt>void ox_destroy(machine *m) {</tt>
<br><tt>&nbsp;&nbsp; free( ((sxc_state*)(m->state)) -> chorusbuf);</tt>
<br><tt>&nbsp;&nbsp; free(m->state);</tt>
<br><tt>&nbsp;&nbsp; m->state = NULL;</tt>
<br><tt>&nbsp;&nbsp; return;</tt>
<br><tt>}</tt><tt></tt>
<p><tt>void ox_update(machine *m) {</tt>
<br><tt>&nbsp;&nbsp; sxc_state *s = (sxc_state *) m->state;</tt>
<br><tt>&nbsp;&nbsp; param temp;</tt>
<br><tt>&nbsp;&nbsp; int i, y;</tt><tt></tt>
<p><tt>&nbsp;&nbsp; temp = m->params[0][ix_gain_in];</tt>
<br><tt>&nbsp;&nbsp; if (temp != nochange) {</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
(temp &lt; 0)&nbsp;&nbsp; temp = 0;</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else if (temp > 255) temp = 255;</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s->in_gain = ((float)temp) / 255.0;</tt>
<br><tt>&nbsp;&nbsp; }</tt><tt></tt>
<p><tt>&nbsp;&nbsp; temp = m->params[0][ix_gain_out];</tt>
<br><tt>&nbsp;&nbsp; if (temp != nochange) {</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
(temp &lt; 0)&nbsp;&nbsp; temp = 0;</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else if (temp > 255) temp = 255;</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s->out_gain = ((float)temp) / 255.0;</tt>
<br><tt>&nbsp;&nbsp; }</tt><tt></tt>
<p><tt>&nbsp;&nbsp; s->maxttlchrssmpls = 0;</tt><tt></tt>
<p><tt>&nbsp;&nbsp; for(i = 0; i &lt; s->chorus_voices; i++) {</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; temp = m->params[0][ix_sxcdecay
+ i * 5];</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (temp != nochange) {</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
if&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
(temp &lt; 0)&nbsp;&nbsp; temp = 0;</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else if (temp
> 255) temp = 255;</tt><tt></tt>
<p><tt>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s->sxcdecay[i]
= ((float)temp) / 255.0; // Old, linear.</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s->sxcdecay[i]
= ((float)exp((double)temp * s->exp_fract_vol) - 1.0)</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/ s->unit_vol_scale;</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</tt><tt></tt>
<p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; temp = m->params[0][ix_sxcdelay +
i * 5];</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (temp != nochange) {</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
if&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
(temp &lt; 1)&nbsp;&nbsp; temp = 1;</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else if (temp
> 255) temp = 255;</tt><tt></tt>
<p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s->sxcdelay[i]
= ((float)temp) / 255.0 * 5.0;</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s->ttlchrssmpls[i]
= (long)(s->sxcdelay[i] * ((float)OX_SAMPLING_RATE)</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/ 1000.0 + 0.5);</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</tt><tt></tt>
<p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; temp = m->params[0][ix_speed + i
* 5];</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (temp != nochange) {</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
if&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
(temp &lt; 10)&nbsp; temp = 10;</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else if (temp
> 255) temp = 255;</tt><tt></tt>
<p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s->speed[i] = 
((float)temp)
/ 255.0 * 2.0;</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s->phz_width[i]
= (long)(((float)OX_SAMPLING_RATE) / s->speed[i] + 0.5);</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</tt><tt></tt>
<p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; temp = m->params[0][ix_depth + i
* 5];</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (temp != nochange) {</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
if&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
(temp &lt; 0)&nbsp; temp = 0;</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else if (temp
> 255) temp = 255;</tt><tt></tt>
<p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s->depth[i] = 
((float)temp)
/ 255.0 * 10.0;</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s->depth_smpls[i]
= (long)(s->depth[i] * ((float)OX_SAMPLING_RATE) / 1000.0</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ 0.5);</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</tt><tt></tt>
<p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; temp = m->params[0][ix_mod_type +
i * 5];</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (temp != nochange) {</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (temp > 2 ||
temp &lt; 0) temp = 2; // If out-of-range, turn off voice.</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s->mod_type[i]
= temp;</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</tt><tt></tt>
<p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s->ttlchrssmpls[i] = 
(long)((s->sxcdelay[i]
+ s->depth[i])</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
* ((float)OX_SAMPLING_RATE) / 1000.0 + 0.5);</tt><tt></tt>
<p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (s->ttlchrssmpls[i] > 
s->maxttlchrssmpls)</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s->maxttlchrssmpls
= s->ttlchrssmpls[i];</tt>
<br><tt>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s->maxttlchrssmpls
= s->ttlchrssmpls[i] + 11;</tt><tt></tt>
<p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (s->mod_type[i] == 0)</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s->offset[i] =
(int)((s->ttlchrssmpls[i] - 1) - s->depth_smpls[i]);</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else if (s->mod_type[i] == 1)</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s->offset[i] =
(int)((s->ttlchrssmpls[i] - 1) - 2 * s->depth_smpls[i]);</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else // if (s->mod_type[i] == 2)</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s->offset[i] =
0;</tt><tt></tt>
<p><tt>&nbsp;&nbsp; }</tt><tt></tt>
<p><tt>&nbsp;&nbsp; return;</tt>
<br><tt>}</tt><tt></tt>
<p><tt>const char *ox_desc(int which_param, param value) {</tt>
<br><tt>&nbsp;&nbsp; static char temp_string[80];</tt>
<br><tt>&nbsp;&nbsp; float user_value;</tt>
<br><tt>&nbsp;&nbsp; int i, percent;</tt><tt></tt>
<p><tt>&nbsp;&nbsp; sprintf(temp_string, "ERROR");</tt><tt></tt>
<p><tt>&nbsp;&nbsp; if (which_param == ix_gain_in || which_param == ix_gain_out)
{</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (value &lt; 0) sprintf(temp_string,
"Gain must not be less than 0.");</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else {</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; user_value = 
((float)value)
/ 255.0;</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; percent = 
(int)(user_value
* 100.0 + 0.5);</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (user_value
> 1.0)</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
sprintf(temp_string, "Gain must be not greater than 100%.");</tt><tt></tt>
<p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else 
sprintf(temp_string,
"%3.0f%%", percent);</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</tt>
<br><tt>&nbsp;&nbsp; }</tt><tt></tt>
<p><tt>&nbsp;&nbsp; else {</tt><tt></tt>
<p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(i = 0; i &lt; max_chorus; i++)
{</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (which_param
== (ix_sxcdecay + i * 5)) {</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
if (value &lt; 0) sprintf(temp_string, "%s%d%s", "Decay ", i,</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
" must not be less than 0.");</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
else {</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
user_value = (float)value / 255.0;</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
percent = (int)(user_value * 100.0 + 0.5);</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
if (user_value > 1.0)</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
sprintf(temp_string, "%s%d%s", "Decay ", i,</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
"must be not greater than 100%.");</tt><tt></tt>
<p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
else sprintf(temp_string, "%3.0f%%", percent);</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
}</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</tt><tt></tt>
<p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else if (which_param
== (ix_sxcdelay + i * 5)) {</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
if (value &lt; 0) sprintf(temp_string, "%s%d%s", "Delay ", i,</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
" must not be less than 0 (20 msec.");</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
else {</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
user_value = (float)value / 255.0 * 80.0 + 20.0;</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
if (user_value > 100.0)</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
sprintf(temp_string, "%s%d%s", "Delay ", i,</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
" must be not greater than 100 msec.");</tt><tt></tt>
<p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
else sprintf(temp_string, "%3.0f", user_value);</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
}</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</tt><tt></tt>
<p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else if (which_param
== ix_speed + i * 5) {</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
if (value &lt; 0) sprintf(temp_string, "%s%d%s", "Speed ", i,</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
" must not be less than 0 (0.1 Hz).");</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
else {</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
user_value = ((float) value) / 255.0 * 5.0;</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
if (user_value > 5.0)</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
sprintf(temp_string, "%s%d%s", "Speed ", i,</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
" must be not greater than 5 Hz.");</tt><tt></tt>
<p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
else sprintf(temp_string, "%3.2f", user_value);</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
}</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</tt><tt></tt>
<p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else if (which_param
== ix_depth + i * 5) {</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
if (value &lt; 0) sprintf(temp_string, "%s%d%s", "Depth ", i,</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
" must not be less than 0 msec.");</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
else {</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
user_value = ((float) value) / 255.0 * 10.0;</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
if (user_value > 10.0)</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
sprintf(temp_string, "%s%d%s", "Depth ", i,</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
" must be not greater than 10 msec.");</tt><tt></tt>
<p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
else sprintf(temp_string, "%3.1f", user_value);</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
}</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</tt><tt></tt>
<p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else if (which_param
== ix_mod_type + i * 5) {</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
switch (value) {</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
case 0&nbsp; : sprintf(temp_string, "Sine"); break;</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
case 1&nbsp; : sprintf(temp_string, "Triangle"); break;</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
default : sprintf(temp_string, "%s%d%s", "Error: Modulation", i,</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
"type must be 0 = sine, 1 = triangle, or 2 = voice off.");</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
}</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</tt>
<br><tt>&nbsp;&nbsp; }</tt><tt></tt>
<p><tt>/* SoX: Clipping - Be nice and check the hint with warning, if...</tt>
<br><tt>&nbsp;&nbsp; if ( flanger->in_gain * ( 1.0 + flanger->sxcdecay
) > 1.0 / flanger->out_gain )</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; warn("flanger: warning >>> gain-out
can cause saturation or clipping of output &lt;&lt;&lt;");</tt>
<br><tt>*/</tt><tt></tt>
<p><tt>}</tt><tt></tt>
<p><tt>int ox_work(machine *m, int block_size) {</tt>
<br><tt>&nbsp;&nbsp; sxc_state *s = (sxc_state *) m->state;</tt>
<br><tt>&nbsp;&nbsp; int i, j, x_phz, ytemp;</tt>
<br><tt>&nbsp;&nbsp; float x_flt, ingain, outgain; // dcy, phzdepth, phz2depth,
phz2width;</tt><tt></tt>
<p><tt>&nbsp;&nbsp; samp* mlout;</tt>
<br><tt>//&nbsp;&nbsp; samp* mrout;</tt>
<br><tt>&nbsp;&nbsp; samp* mlin;</tt>
<br><tt>&nbsp;&nbsp; samp* chrsbuf;</tt><tt></tt>
<p><tt>&nbsp;&nbsp; mlout&nbsp;&nbsp;&nbsp; = m->lout;</tt>
<br><tt>//&nbsp;&nbsp; mrout&nbsp;&nbsp;&nbsp; = m->rout;</tt>
<br><tt>&nbsp;&nbsp; mlin&nbsp;&nbsp;&nbsp;&nbsp; = m->lin;</tt><tt></tt>
<p><tt>&nbsp;&nbsp; ingain&nbsp;&nbsp; = s->in_gain;</tt>
<br><tt>&nbsp;&nbsp; outgain&nbsp; = s->out_gain;</tt>
<br><tt>&nbsp;&nbsp; chrsbuf&nbsp; = s->chorusbuf;</tt><tt></tt>
<p><tt>&nbsp;&nbsp; for(i = 0; i &lt; block_size; i++) {</tt><tt></tt>
<p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Compute output first */</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mlout[i] = mlin[i] * 
ingain;</tt><tt></tt>
<p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for ( j = 0; j &lt; s->chorus_voices;
j++ ) {</tt><tt></tt>
<p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (s->mod_type[j]
!= MOD_SILENT) { // Start no indent</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (s->mod_type[j]
== MOD_SINE) {</tt><tt></tt>
<p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
// Get sine phase shift. 1 added to correct noise at 0.</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
x_flt = (float) sin((double)s->phase[j]/(double)s->phz_width[j] * PI2);</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
x_phz = s->offset[j] + (int) (x_flt * (double)s->depth_smpls[j] + 0.5);</tt>
<br><tt>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ 1;</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</tt><tt></tt>
<p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else { // s->mod_type[j]
== MOD_TRIANGLE</tt><tt></tt>
<p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
// Compute triangle - ramp up and down.</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
if (s->phase[j] &lt; (s->phz_width[j] / 2)) { // Ramp up</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
x_flt = (float)s->phase[j] * 2.0 / (float)s->phz_width[j];</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
x_phz = s->offset[j] + (int) (x_flt * 2.0 * (float)s->depth_smpls[j]</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ 0.5);</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
}</tt><tt></tt>
<p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
else { // Ramp down</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
x_flt = (float)(s->phz_width[j] - s->phase[j]) * 2.0</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/ (float)s->phz_width[j];</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
x_phz = s->offset[j] + (int) (x_flt * 2.0 * (float)s->depth_smpls[j]</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ 0.5);</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
}</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</tt><tt></tt>
<p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mlout[i] += 
chrsbuf[(s->maxttlchrssmpls
+ s->chorus_cntr</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- x_phz) % s->maxttlchrssmpls] * s->sxcdecay[j];</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } // End no indent</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</tt><tt></tt>
<p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Adjust the output volume. */</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mlout[i] *= outgain;</tt><tt></tt>
<p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Check for clipping.&nbsp; Not
implemented. */</tt>
<br><tt>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
(mlout[i] > hig_clip)&nbsp; mlout[i] = hig_clip;</tt>
<br><tt>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else if (mlout[i] &lt; low_clip)&nbsp;
mlout[i] = low_clip;</tt><tt></tt>
<p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Mix decay of delay and input */</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; chrsbuf[s->chorus_cntr] = 
mlin[i];</tt><tt></tt>
<p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s->chorus_cntr = ( s->chorus_cntr
+ 1 ) % s->maxttlchrssmpls;</tt><tt></tt>
<p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for ( j = 0; j &lt; s->chorus_voices;
j++ )</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s->phase[j] =
( s->phase[j] + 1 ) % s->phz_width[j];</tt>
<br><tt>&nbsp;&nbsp; }</tt><tt></tt>
<p><tt>&nbsp;&nbsp; /* Save speedup variables to state. */</tt><tt></tt>
<p><tt>&nbsp;&nbsp; return 1;</tt>
<br><tt>}</tt><tt></tt>
<p><tt>void ox_track(machine *m, int change) {</tt>
<br><tt>}</tt>
<br><tt></tt>&nbsp;</html>

--------------24819DF4628C2DE0E67AAF2F--


Received: from mta6.snfc21.pbi.net (mta6.snfc21.pbi.net [206.13.28.240])
        by mescaline.gnu.org (8.9.1a/8.9.1) with ESMTP id OAA02904
        for <address@hidden>; Tue, 27 Jun 2000 14:21:37 -0400
Received: from pacbell.net ([207.214.184.75])
 by mta6.snfc21.pbi.net (Sun Internet Mail Server sims.3.5.2000.01.05.12.18.p9)
 with ESMTP id <address@hidden> for address@hidden; Tue,
 27 Jun 2000 10:24:28 -0700 (PDT)
Date: Tue, 27 Jun 2000 10:22:33 -0700
From: Neil Nelson <address@hidden>
To: address@hidden
Message-id: <address@hidden>
MIME-version: 1.0
X-Mailer: Mozilla 4.72 [en] (X11; U; Linux 2.2.14-5.0 i686)
Content-type: multipart/alternative;
 boundary="------------801DEC9FA1F1642AE599CEF4"
X-Accept-Language: en
Subject: [Octal-dev] soxecho.c - SoX echo.c converted to Octal
Sender: address@hidden
Errors-To: address@hidden
X-BeenThere: address@hidden
X-Mailman-Version: 1.2 (beta 1)
Precedence: bulk
Reply-To: address@hidden
List-Id: OCTAL tracker http://www.gnu.org/software/octal <octal-dev.gnu.org>

--------------801DEC9FA1F1642AE599CEF4
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

No clicks in this one.  Contains log volume (gain) controls.

/*   SOXECHO.C
*
* This code has been adapted from the SoX echo.c code:
*
* August 24, 1998
* Copyright (C) 1998 Juergen Mueller And Sundry Contributors
* This source code is freely redistributable and may be used for
* any purpose.  This copyright notice must be maintained.
* Juergen Mueller And Sundry Contributors are not responsible for
* the consequences of using this software.
*
* Conversion to Octal made by:
*
* Copyright 2000 Neil Nelson <address@hidden> June 27, 2000.
*
* This software is distributed under the terms of the
* GNU General Public License (GPL). Read the included file
* COPYING for more information.
*
*
* From SoX:
* This is the "echo.c" while the old "echo.c" from version 12 moves to
* "reverb.c" satisfying the defintions made in the Guitar FX FAQ.
*
*
* Echo effect for dsp.
*
* Flow diagram scheme for n delays ( 1 <= n <= MAX_ECHOS ):
*
*        * gain-in                                              ___
* ibuff -----------+------------------------------------------>|   |
*                  |       _________                           |   |
*                  |      |         |                * decay 1 |   |
*                  +----->| delay 1 |------------------------->|   |
*                  |      |_________|                          |   |
*                  |            _________                      | + |
*                  |           |         |           * decay 2 |   |
*                  +---------->| delay 2 |-------------------->|   |
*                  |           |_________|                     |   |
*                  :                 _________                 |   |
*                  |                |         |      * decay n |   |
*                  +--------------->| delay n |--------------->|___|
*                                   |_________|                  |
*                                                                | *
gain-out
*                                                                |
*
+----->obuff
*
* Usage:
*   echo gain-in gain-out delay-1 decay-1 [delay-2 decay-2 ... delay-n
decay-n]
*
* Where:
*   gain-in, decay-1 ... decay-n :  0.0 ... 1.0      volume
*   gain-out :  0.0 ...      volume
*   delay-1 ... delay-n :  > 0.0 msec
*
* Note:
*   when decay is close to 1.0, the samples can begin clipping and the
output
*   can saturate!
*
* Hint:
*   1 / out-gain > gain-in ( 1 + decay-1 + ... + decay-n )
*
*/

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "util.h"
#include "machine.h"

#define DYN_RANGE 10
#define MAX_ECHOS 7
#define MAX_DELAY 500 // msec
// #define DELAY_LOG_RANGE 2 // Higher number skews toward selecting
shorter delays.

/*  The parameters are:  gain_in, gain_out, decay, delay, ... 6 more
times */
enum {
   ix_gain_in, ix_gain_out,
   ix_sxedecay, ix_sxedelay,
   ix_sxedecay_1, ix_sxedelay_1,
   ix_sxedecay_2, ix_sxedelay_2,
   ix_sxedecay_3, ix_sxedelay_3,
   ix_sxedecay_4, ix_sxedelay_4,
   ix_sxedecay_5, ix_sxedelay_5,
   ix_sxedecay_6, ix_sxedelay_6
} param_index;

param_spec sxe_params[] = {
   /*  Param 1: gain_in. */
   {
   small,
   slider,
   "Gain In",
   "Gain In",
   0,           /* 0 gain */
   255,         /* No attenuation */
   70           /* Approx. 70/255 of dynamic range */
   },

   /*  Param 2: gain_out. */
   {
   small,
   slider,
   "Gain Out",
   "Gain Out",
   0,           /* 0 gain */
   255,         /* No attenuation */
   100          /* Approx. 100/255 of dynamic range */
   },

   /*  Param 3: sxedecay[0]. */
   {
   small,
   slider,
   "Decay 0",
   "Decay of Delay 0.",
   0,
   255,         /* 1 */
   220          /* 220/255 of dynamic range */
   },

   /*  Param 4: sxedelay[0]. */
   {
   small,
   slider,
   "Delay 0",
   "Delay 0 time: 0 to maximum.",
   0,           /* 0 msec. delay  */
   255,         /* Highest delay of range */
   35           /* 35/255 of MAX_DELAY msec */
   },

   /*  Param 5: sxedecay[1]. */
   {
   small,
   slider,
   "Decay 1",
   "Decay of Delay 1.",
   0,
   255,         /* 1 */
   220          /* 220/255 of dynamic range */
   },

   /*  Param 6: sxedelay[1]. */
   {
   small,
   slider,
   "Delay 1",
   "Delay 1 time: 0 to maximum.",
   0,           /* 0 msec. delay  */
   255,         /* Highest delay of range */
   70           /* 70/255 of MAX_DELAY msec */
   },

   /*  Param 7: sxedecay[2]. */
   {
   small,
   slider,
   "Decay 2",
   "Decay of Delay 2.",
   0,
   255,         /* 1 */
   220          /* 220/255 of dynamic range */
   },

   /*  Param 8: sxedelay[2]. */
   {
   small,
   slider,
   "Delay 2",
   "Delay 2 time: 0 to maximum.",
   0,           /* 0 msec. delay  */
   255,         /* Highest delay of range */
   105          /* 105/255 of MAX_DELAY msec */
   },

   /*  Param 9: sxedecay[3]. */
   {
   small,
   slider,
   "Decay 3",
   "Decay of Delay 3.",
   0,
   255,         /* 1 */
   220          /* 220/255 of dynamic range */
   },

   /*  Param 10: sxedelay[3]. */
   {
   small,
   slider,
   "Delay 3",
   "Delay 3 time: 0 to maximum.",
   0,           /* 0 msec. delay  */
   255,         /* Highest delay of range */
   140          /* 140/255 of MAX_DELAY msec */
   },

   /*  Param 11: sxedecay[4]. */
   {
   small,
   slider,
   "Decay 4",
   "Decay of Delay 4.",
   0,
   255,         /* 1 */
   220          /* 220/255 of dynamic range */
   },

   /*  Param 12: sxedelay[4]. */
   {
   small,
   slider,
   "Delay 4",
   "Delay 4 time: 0 to maximum.",
   0,           /* 0 msec. delay  */
   255,         /* Highest delay of range */
   175          /* 175/255 of MAX_DELAY msec */
   },

   /*  Param 13: sxedecay[5]. */
   {
   small,
   slider,
   "Decay 5",
   "Decay of Delay 5.",
   0,
   255,         /* 1 */
   220          /* 220/255 of dynamic range */
   },

   /*  Param 14: sxedelay[5]. */
   {
   small,
   slider,
   "Delay 5",
   "Delay 5 time: 0 to maximum.",
   0,           /* 0 msec. delay  */
   255,         /* Highest delay of range */
   210          /* 210/255 of MAX_DELAY msec */
   },

   /*  Param 15: sxedecay[6]. */
   {
   small,
   slider,
   "Decay 6",
   "Decay of Delay 6.",
   0,
   255,         /* 1 */
   220          /* 220/255 of dynamic range */
   },

   /*  Param 16: sxedelay[6]. */
   {
   small,
   slider,
   "Delay 6",
   "Delay 6 time: 0 to maximum.",
   0,           /* 0 msec. delay  */
   255,         /* Highest delay of range */
   255
   },
};

/*  State of the soxflanger. */

typedef struct {
   float   in_gain, out_gain;
   float   sxedecay[MAX_ECHOS];
   float   sxedelay[MAX_ECHOS];
   long    sxesamples[MAX_ECHOS];
   samp*   delaybuf;
   long    maxsxesamples;
   float   maxanydelay;
   long    maxanysmpls;
   int     echo_cntr;
   int     num_delays;
   double  unit_vol_scale;
   double  exp_fract_vol;
//   double  unit_delay_scale;
//   double  exp_fract_delay;
//   float   clip; // Put in after clipping issue decided.
} sxe_state;

int ox_init(machine_type *t) {
   t->long_name = "soxecho (Mueller, Nelson, et al.)";
   t->short_name = "soxecho";
   t->max_tracks = 1;
   t->input_channels = 1;
   t->output_channels = 1;
   t->num_params = 15;
   t->param_specs = sxe_params;

   return 1;
}

void ox_create(machine *m) {
   sxe_state *s;
   int i;

   s = (sxe_state*) malloc(sizeof(sxe_state));
   m->state = (void *) s;

   s->num_delays = MAX_ECHOS;

   s->unit_vol_scale = exp((double)DYN_RANGE / 3.0) - 1.0;
   s->exp_fract_vol = ((double)DYN_RANGE / 3) / 255.0;

//   s->unit_delay_scale = (exp((double)DELAY_LOG_RANGE) - 1.0) /
(double)MAX_DELAY;
//   s->exp_fract_delay = ((double)DELAY_LOG_RANGE) / 255.0;

   /* Set defaults */
//   s->in_gain    = 128.0/255.0;   /* Approx. 0.5 (old) */
   s->in_gain  = ((float)exp(70.0 * s->exp_fract_vol) - 1.0)
                 / s->unit_vol_scale;
//   s->out_gain   = 1.0;           /* No attenuation */
   s->out_gain  = ((float)exp(100.0 * s->exp_fract_vol) - 1.0)
                 / s->unit_vol_scale;

   s->sxedecay[0] = ((float)exp(220.0 * s->exp_fract_vol) - 1.0)
                    / s->unit_vol_scale;
   s->sxedelay[0] = 35.0/255.0 * (float)MAX_DELAY;
//   s->sxedelay[0] = ((float)exp(35.0 * s->exp_fract_delay) - 1.0)
//                    / s->unit_delay_scale;

   s->sxedecay[1] = ((float)exp(220.0 * s->exp_fract_vol) - 1.0)
                    / s->unit_vol_scale;
   s->sxedelay[1] = 70.0/255.0 * (float)MAX_DELAY;
//   s->sxedelay[1] = ((float)exp(70.0 * s->exp_fract_delay) - 1.0)
//                    / s->unit_delay_scale;

   s->sxedecay[2] = ((float)exp(220.0 * s->exp_fract_vol) - 1.0)
                    / s->unit_vol_scale;
   s->sxedelay[2] = 105.0/255.0 * (float)MAX_DELAY;
//   s->sxedelay[2] = ((float)exp(105.0 * s->exp_fract_delay) - 1.0)
//                    / s->unit_delay_scale;

   s->sxedecay[3] = ((float)exp(220.0 * s->exp_fract_vol) - 1.0)
                    / s->unit_vol_scale;
   s->sxedelay[3] = 140.0/255.0 * (float)MAX_DELAY;
//   s->sxedelay[3] = ((float)exp(140.0 * s->exp_fract_delay) - 1.0)
//                    / s->unit_delay_scale;

   s->sxedecay[4] = ((float)exp(220.0 * s->exp_fract_vol) - 1.0)
                    / s->unit_vol_scale;
   s->sxedelay[4] = 175.0/255.0 * (float)MAX_DELAY;
//   s->sxedelay[4] = ((float)exp(175.0 * s->exp_fract_delay) - 1.0)
//                    / s->unit_delay_scale;

   s->sxedecay[5] = ((float)exp(220.0 * s->exp_fract_vol) - 1.0)
                    / s->unit_vol_scale;
   s->sxedelay[5] = 210.0/255.0 * (float)MAX_DELAY;
//   s->sxedelay[5] = ((float)exp(210.0 * s->exp_fract_delay) - 1.0)
//                    / s->unit_delay_scale;

   s->sxedecay[6] = ((float)exp(220.0 * s->exp_fract_vol) - 1.0)
                    / s->unit_vol_scale;
   s->sxedelay[6] = 255.0/255.0 * (float)MAX_DELAY;
//   s->sxedelay[6] = ((float)exp(255.0 * s->exp_fract_delay) - 1.0)
//                    / s->unit_delay_scale;

   s->maxsxesamples = 0; // Accumulated in following loop.

   for(i = 0; i < s->num_delays; i++) {

      s->sxesamples[i] = (long)(s->sxedelay[i] *
((float)OX_SAMPLING_RATE) / 1000.0
                                + 0.5);

      if (s->sxesamples[i] > s->maxsxesamples)
         s->maxsxesamples = s->sxesamples[i];
   }

   s->maxanydelay = MAX_DELAY;
   s->maxanysmpls = (long)(s->maxanydelay * ((float)OX_SAMPLING_RATE) /
1000.0
                     + 10.0); // Add an extra 10 to avoid possible exp
overflow.

   if (s->maxsxesamples > s->maxanysmpls)
      printf("%s\n",
             "soxecho create error: delay sample requirement exceeds
allocation.");

   s->echo_cntr = 0;

//   s->clip = ?; // Put in after clipping issue decided.

   s->delaybuf = (samp*) malloc(s->maxanysmpls * sizeof(samp));

//   memset(s->delaybuf, 0, s->maxanysmpls * sizeof(samp)); //
Unnecessary
//   for (i=0, i < s->maxanysmpls, i++) s->delaybuf[i] = 0; // Speed
this up.

   return;
}

void ox_destroy(machine *m) {
   free( ((sxe_state*)(m->state)) -> delaybuf);
   free(m->state);
   m->state = NULL;
   return;
}

void ox_update(machine *m) {
   sxe_state *s = (sxe_state *) m->state;
   param temp;
   int i;

   temp = m->params[0][ix_gain_in];
   if (temp != nochange) {
      if      (temp < 0)   temp = 0;
      else if (temp > 255) temp = 255;
      s->in_gain = ((float)temp) / 255.0;
   }

   temp = m->params[0][ix_gain_out];
   if (temp != nochange) {
      if      (temp < 0)   temp = 0;
      else if (temp > 255) temp = 255;
      s->out_gain = ((float)temp) / 255.0;
   }

   s->maxsxesamples = 0; // Accumulated in following loop.

   for(i = 0; i < s->num_delays; i++) {
      temp = m->params[0][ix_sxedecay + i * 2];
      if (temp != nochange) {
         if      (temp < 0)   temp = 0;
         else if (temp > 255) temp = 255;

//         s->sxedecay[i] = ((float)temp) / 255.0; // Old, linear.
         s->sxedecay[i] = ((float)exp((double)temp * s->exp_fract_vol) -
1.0)
                          / s->unit_vol_scale;
      }

      temp = m->params[0][ix_sxedelay + i * 2];
      if (temp != nochange) {
         if      (temp < 1)   temp = 0;
         else if (temp > 255) temp = 255;

         s->sxedelay[i] = (float)temp/255.0 * (float)MAX_DELAY;
//         s->sxedelay[i] = ((float)exp((double)temp *
s->exp_fract_delay) - 1.0)
//                          / s->unit_delay_scale;

         s->sxesamples[i] = (long)(s->sxedelay[i] *
((float)OX_SAMPLING_RATE)
                                   / 1000.0 + 0.5);
      }

      if (s->sxesamples[i] > s->maxsxesamples) s->maxsxesamples =
s->sxesamples[i];
   }

   return;
}

const char *ox_desc(int which_param, param value) {
   static char temp_string[80];
   float user_value;
   int i, percent;

   sprintf(temp_string, "ERROR");

   if (which_param == ix_gain_in || which_param == ix_gain_out) {
      if (value < 0) sprintf(temp_string, "Gain must not be less than
0.");
      else {
         user_value = ((float)value) / 255.0;
         percent = (int)(user_value * 100.0 + 0.5);
         if (user_value > 1.0)
            sprintf(temp_string, "Gain must be not greater than 100%.");

         else sprintf(temp_string, "%3.0f%%", percent);
      }
   }

   else {

      for(i = 0; i < MAX_ECHOS; i++) {
         if (which_param == (ix_sxedecay + i * 2)) {
            if (value < 0) sprintf(temp_string, "%s%d%s", "Decay ", i,
                           " must not be less than 0.  0 removes this
delay");
            else {
               user_value = (float)value / 255.0;
               percent = (int)(user_value * 100.0 + 0.5);
               if (user_value > 1.0)
                  sprintf(temp_string, "%s%d%s", "Decay ", i,
                          "must be not greater than 100%.");

               else sprintf(temp_string, "%3.0f%%", percent);
            }
         }

         else if (which_param == (ix_sxedelay + i * 2)) {
            if (value < 0) sprintf(temp_string, "%s%d%s", "Delay ", i,
                                   " must not be less than 0.");
            else {
               user_value = (float)value / 255.0 * (float)MAX_DELAY;
               if (user_value > (float)MAX_DELAY)
                  sprintf(temp_string, "%s%d%s%d%s", "Delay ", i,
                          " must be not greater than ", MAX_DELAY, "
msec.");

               else sprintf(temp_string, "%3.0f", user_value);
            }
         }
      }
   }
/*
 *** Be nice and check the hint with warning, if...
 sum_in_volume = 1.0;
 for ( i = 0; i < echo->num_delays; i++ )
  sum_in_volume += echo->decay[i];
 if ( sum_in_volume * echo->in_gain > 1.0 / echo->out_gain )
  warn("echo: warning >>> gain-out can cause saturation of output <<<");

*/

}

int ox_work(machine *m, int block_size) {
   sxe_state *s = (sxe_state *) m->state;

   samp* mlout;
//   samp* mrout;
   samp* mlin;
   samp* dlybf;
   int i, j, dlyctr, numdlys;
   long mxsmpls;
   long* sxsmpls;
   float ingain, outgain;
   float* sxdecy;

//   float hig_clip, low_clip;

//   hig_clip = s->clip;
//   low_clip = 0.0 - s->clip;

   /* Speed-up variables */
   mlout    = m->lout;
//   mrout    = m->rout;
   mlin     = m->lin;

   ingain   = s->in_gain;
   outgain  = s->out_gain;

   dlybf    = s->delaybuf;
   dlyctr   = s->echo_cntr;
   mxsmpls  = s->maxsxesamples;
   sxsmpls  = (long*)s->sxesamples;
   sxdecy   = (float*)s->sxedecay;
   numdlys  = s->num_delays;

   for(i = 0; i < block_size; i++) {

      /* Compute output first */
      mlout[i] = mlin[i] * ingain;

      for (j = 0; j < numdlys; j++) {
         if (sxdecy[j])
            mlout[i] += dlybf[(mxsmpls + dlyctr - sxsmpls[j]) % mxsmpls]
* sxdecy[j];
      }

      /* Adjust the output volume */
      mlout[i] *= outgain;

      /* Check for clipping.  Not implemented. */
//      if      (mlout[i] > hig_clip)  mlout[i] = hig_clip;
//      else if (mlout[i] < low_clip)  mlout[i] = low_clip;

      /* Store input in delay buffer */
      dlybf[dlyctr] = mlin[i];

      /* Adjust the counter */
      dlyctr = ( dlyctr + 1 ) % mxsmpls;

   }

   /* Save speed-up variables to state. */
   s->echo_cntr = dlyctr;

   return 1;
}

void ox_track(machine *m, int change) {
}


--------------801DEC9FA1F1642AE599CEF4
Content-Type: text/html; charset=us-ascii
Content-Transfer-Encoding: 7bit

<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
<html>
No clicks in this one.&nbsp; Contains log volume (gain) controls.<tt></tt>
<p><tt>/*&nbsp;&nbsp; SOXECHO.C</tt>
<br><tt>*</tt>
<br><tt>* This code has been adapted from the SoX echo.c code:</tt>
<br><tt>*</tt>
<br><tt>* August 24, 1998</tt>
<br><tt>* Copyright (C) 1998 Juergen Mueller And Sundry Contributors</tt>
<br><tt>* This source code is freely redistributable and may be used for</tt>
<br><tt>* any purpose.&nbsp; This copyright notice must be maintained.</tt>
<br><tt>* Juergen Mueller And Sundry Contributors are not responsible for</tt>
<br><tt>* the consequences of using this software.</tt>
<br><tt>*</tt>
<br><tt>* Conversion to Octal made by:</tt>
<br><tt>*</tt>
<br><tt>* Copyright 2000 Neil Nelson &lt;address@hidden> June 27,
2000.</tt>
<br><tt>*</tt>
<br><tt>* This software is distributed under the terms of the</tt>
<br><tt>* GNU General Public License (GPL). Read the included file</tt>
<br><tt>* COPYING for more information.</tt>
<br><tt>*</tt>
<br><tt>*</tt>
<br><tt>* From SoX:</tt>
<br><tt>* This is the "echo.c" while the old "echo.c" from version 12 moves
to</tt>
<br><tt>* "reverb.c" satisfying the defintions made in the Guitar FX FAQ.</tt>
<br><tt>*</tt>
<br><tt>*</tt>
<br><tt>* Echo effect for dsp.</tt>
<br><tt>*</tt>
<br><tt>* Flow diagram scheme for n delays ( 1 &lt;= n &lt;= MAX_ECHOS
):</tt>
<br><tt>*</tt>
<br><tt>*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * 
gain-in&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
___</tt>
<br><tt>* ibuff 
-----------+------------------------------------------>|&nbsp;&nbsp;
|</tt>
<br><tt>*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
_________&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
|&nbsp;&nbsp; |</tt>
<br><tt>*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
* decay 1 |&nbsp;&nbsp; |</tt>
<br><tt>*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+----->| delay 1 |------------------------->|&nbsp;&nbsp; |</tt>
<br><tt>*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
|_________|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
|&nbsp;&nbsp; |</tt>
<br><tt>*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
_________&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
| + |</tt>
<br><tt>*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * decay 2
|&nbsp;&nbsp; |</tt>
<br><tt>*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+---------->| delay 2 |-------------------->|&nbsp;&nbsp; |</tt>
<br><tt>*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
|_________|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
|&nbsp;&nbsp; |</tt>
<br><tt>*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
_________&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
|&nbsp;&nbsp; |</tt>
<br><tt>*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
* decay n |&nbsp;&nbsp; |</tt>
<br><tt>*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+--------------->| delay n |--------------->|___|</tt>
<br><tt>*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
|_________|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
|</tt>
<br><tt>*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
| * gain-out</tt>
<br><tt>*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
|</tt>
<br><tt>*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+----->obuff</tt>
<br><tt>*</tt>
<br><tt>* Usage:</tt>
<br><tt>*&nbsp;&nbsp; echo gain-in gain-out delay-1 decay-1 [delay-2 decay-2
... delay-n decay-n]</tt>
<br><tt>*</tt>
<br><tt>* Where:</tt>
<br><tt>*&nbsp;&nbsp; gain-in, decay-1 ... decay-n :&nbsp; 0.0 ... 
1.0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
volume</tt>
<br><tt>*&nbsp;&nbsp; gain-out :&nbsp; 0.0 ...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
volume</tt>
<br><tt>*&nbsp;&nbsp; delay-1 ... delay-n :&nbsp; > 0.0 msec</tt>
<br><tt>*</tt>
<br><tt>* Note:</tt>
<br><tt>*&nbsp;&nbsp; when decay is close to 1.0, the samples can begin
clipping and the output</tt>
<br><tt>*&nbsp;&nbsp; can saturate!</tt>
<br><tt>*</tt>
<br><tt>* Hint:</tt>
<br><tt>*&nbsp;&nbsp; 1 / out-gain > gain-in ( 1 + decay-1 + ... + decay-n
)</tt>
<br><tt>*</tt>
<br><tt>*/</tt><tt></tt>
<p><tt>#include &lt;stdio.h></tt>
<br><tt>#include &lt;stdlib.h></tt>
<br><tt>#include &lt;math.h></tt>
<br><tt>#include "util.h"</tt>
<br><tt>#include "machine.h"</tt><tt></tt>
<p><tt>#define DYN_RANGE 10</tt>
<br><tt>#define MAX_ECHOS 7</tt>
<br><tt>#define MAX_DELAY 500 // msec</tt>
<br><tt>// #define DELAY_LOG_RANGE 2 // Higher number skews toward selecting
shorter delays.</tt><tt></tt>
<p><tt>/*&nbsp; The parameters are:&nbsp; gain_in, gain_out, decay, delay,
... 6 more times */</tt>
<br><tt>enum {</tt>
<br><tt>&nbsp;&nbsp; ix_gain_in, ix_gain_out,</tt>
<br><tt>&nbsp;&nbsp; ix_sxedecay, ix_sxedelay,</tt>
<br><tt>&nbsp;&nbsp; ix_sxedecay_1, ix_sxedelay_1,</tt>
<br><tt>&nbsp;&nbsp; ix_sxedecay_2, ix_sxedelay_2,</tt>
<br><tt>&nbsp;&nbsp; ix_sxedecay_3, ix_sxedelay_3,</tt>
<br><tt>&nbsp;&nbsp; ix_sxedecay_4, ix_sxedelay_4,</tt>
<br><tt>&nbsp;&nbsp; ix_sxedecay_5, ix_sxedelay_5,</tt>
<br><tt>&nbsp;&nbsp; ix_sxedecay_6, ix_sxedelay_6</tt>
<br><tt>} param_index;</tt><tt></tt>
<p><tt>param_spec sxe_params[] = {</tt>
<br><tt>&nbsp;&nbsp; /*&nbsp; Param 1: gain_in. */</tt>
<br><tt>&nbsp;&nbsp; {</tt>
<br><tt>&nbsp;&nbsp; small,</tt>
<br><tt>&nbsp;&nbsp; slider,</tt>
<br><tt>&nbsp;&nbsp; "Gain In",</tt>
<br><tt>&nbsp;&nbsp; "Gain In",</tt>
<br><tt>&nbsp;&nbsp; 
0,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* 0 gain */</tt>
<br><tt>&nbsp;&nbsp; 255,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* No attenuation */</tt>
<br><tt>&nbsp;&nbsp; 
70&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* Approx. 70/255 of dynamic range */</tt>
<br><tt>&nbsp;&nbsp; },</tt><tt></tt>
<p><tt>&nbsp;&nbsp; /*&nbsp; Param 2: gain_out. */</tt>
<br><tt>&nbsp;&nbsp; {</tt>
<br><tt>&nbsp;&nbsp; small,</tt>
<br><tt>&nbsp;&nbsp; slider,</tt>
<br><tt>&nbsp;&nbsp; "Gain Out",</tt>
<br><tt>&nbsp;&nbsp; "Gain Out",</tt>
<br><tt>&nbsp;&nbsp; 
0,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* 0 gain */</tt>
<br><tt>&nbsp;&nbsp; 255,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* No attenuation */</tt>
<br><tt>&nbsp;&nbsp; 100&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* Approx. 100/255 of dynamic range */</tt>
<br><tt>&nbsp;&nbsp; },</tt><tt></tt>
<p><tt>&nbsp;&nbsp; /*&nbsp; Param 3: sxedecay[0]. */</tt>
<br><tt>&nbsp;&nbsp; {</tt>
<br><tt>&nbsp;&nbsp; small,</tt>
<br><tt>&nbsp;&nbsp; slider,</tt>
<br><tt>&nbsp;&nbsp; "Decay 0",</tt>
<br><tt>&nbsp;&nbsp; "Decay of Delay 0.",</tt>
<br><tt>&nbsp;&nbsp; 0,</tt>
<br><tt>&nbsp;&nbsp; 255,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* 1 */</tt>
<br><tt>&nbsp;&nbsp; 220&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* 220/255 of dynamic range */</tt>
<br><tt>&nbsp;&nbsp; },</tt><tt></tt>
<p><tt>&nbsp;&nbsp; /*&nbsp; Param 4: sxedelay[0]. */</tt>
<br><tt>&nbsp;&nbsp; {</tt>
<br><tt>&nbsp;&nbsp; small,</tt>
<br><tt>&nbsp;&nbsp; slider,</tt>
<br><tt>&nbsp;&nbsp; "Delay 0",</tt>
<br><tt>&nbsp;&nbsp; "Delay 0 time: 0 to maximum.",</tt>
<br><tt>&nbsp;&nbsp; 
0,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* 0 msec. delay&nbsp; */</tt>
<br><tt>&nbsp;&nbsp; 255,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* Highest delay of range */</tt>
<br><tt>&nbsp;&nbsp; 
35&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* 35/255 of MAX_DELAY msec */</tt>
<br><tt>&nbsp;&nbsp; },</tt><tt></tt>
<p><tt>&nbsp;&nbsp; /*&nbsp; Param 5: sxedecay[1]. */</tt>
<br><tt>&nbsp;&nbsp; {</tt>
<br><tt>&nbsp;&nbsp; small,</tt>
<br><tt>&nbsp;&nbsp; slider,</tt>
<br><tt>&nbsp;&nbsp; "Decay 1",</tt>
<br><tt>&nbsp;&nbsp; "Decay of Delay 1.",</tt>
<br><tt>&nbsp;&nbsp; 0,</tt>
<br><tt>&nbsp;&nbsp; 255,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* 1 */</tt>
<br><tt>&nbsp;&nbsp; 220&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* 220/255 of dynamic range */</tt>
<br><tt>&nbsp;&nbsp; },</tt><tt></tt>
<p><tt>&nbsp;&nbsp; /*&nbsp; Param 6: sxedelay[1]. */</tt>
<br><tt>&nbsp;&nbsp; {</tt>
<br><tt>&nbsp;&nbsp; small,</tt>
<br><tt>&nbsp;&nbsp; slider,</tt>
<br><tt>&nbsp;&nbsp; "Delay 1",</tt>
<br><tt>&nbsp;&nbsp; "Delay 1 time: 0 to maximum.",</tt>
<br><tt>&nbsp;&nbsp; 
0,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* 0 msec. delay&nbsp; */</tt>
<br><tt>&nbsp;&nbsp; 255,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* Highest delay of range */</tt>
<br><tt>&nbsp;&nbsp; 
70&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* 70/255 of MAX_DELAY msec */</tt>
<br><tt>&nbsp;&nbsp; },</tt><tt></tt>
<p><tt>&nbsp;&nbsp; /*&nbsp; Param 7: sxedecay[2]. */</tt>
<br><tt>&nbsp;&nbsp; {</tt>
<br><tt>&nbsp;&nbsp; small,</tt>
<br><tt>&nbsp;&nbsp; slider,</tt>
<br><tt>&nbsp;&nbsp; "Decay 2",</tt>
<br><tt>&nbsp;&nbsp; "Decay of Delay 2.",</tt>
<br><tt>&nbsp;&nbsp; 0,</tt>
<br><tt>&nbsp;&nbsp; 255,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* 1 */</tt>
<br><tt>&nbsp;&nbsp; 220&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* 220/255 of dynamic range */</tt>
<br><tt>&nbsp;&nbsp; },</tt><tt></tt>
<p><tt>&nbsp;&nbsp; /*&nbsp; Param 8: sxedelay[2]. */</tt>
<br><tt>&nbsp;&nbsp; {</tt>
<br><tt>&nbsp;&nbsp; small,</tt>
<br><tt>&nbsp;&nbsp; slider,</tt>
<br><tt>&nbsp;&nbsp; "Delay 2",</tt>
<br><tt>&nbsp;&nbsp; "Delay 2 time: 0 to maximum.",</tt>
<br><tt>&nbsp;&nbsp; 
0,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* 0 msec. delay&nbsp; */</tt>
<br><tt>&nbsp;&nbsp; 255,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* Highest delay of range */</tt>
<br><tt>&nbsp;&nbsp; 105&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* 105/255 of MAX_DELAY msec */</tt>
<br><tt>&nbsp;&nbsp; },</tt><tt></tt>
<p><tt>&nbsp;&nbsp; /*&nbsp; Param 9: sxedecay[3]. */</tt>
<br><tt>&nbsp;&nbsp; {</tt>
<br><tt>&nbsp;&nbsp; small,</tt>
<br><tt>&nbsp;&nbsp; slider,</tt>
<br><tt>&nbsp;&nbsp; "Decay 3",</tt>
<br><tt>&nbsp;&nbsp; "Decay of Delay 3.",</tt>
<br><tt>&nbsp;&nbsp; 0,</tt>
<br><tt>&nbsp;&nbsp; 255,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* 1 */</tt>
<br><tt>&nbsp;&nbsp; 220&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* 220/255 of dynamic range */</tt>
<br><tt>&nbsp;&nbsp; },</tt><tt></tt>
<p><tt>&nbsp;&nbsp; /*&nbsp; Param 10: sxedelay[3]. */</tt>
<br><tt>&nbsp;&nbsp; {</tt>
<br><tt>&nbsp;&nbsp; small,</tt>
<br><tt>&nbsp;&nbsp; slider,</tt>
<br><tt>&nbsp;&nbsp; "Delay 3",</tt>
<br><tt>&nbsp;&nbsp; "Delay 3 time: 0 to maximum.",</tt>
<br><tt>&nbsp;&nbsp; 
0,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* 0 msec. delay&nbsp; */</tt>
<br><tt>&nbsp;&nbsp; 255,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* Highest delay of range */</tt>
<br><tt>&nbsp;&nbsp; 140&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* 140/255 of MAX_DELAY msec */</tt>
<br><tt>&nbsp;&nbsp; },</tt><tt></tt>
<p><tt>&nbsp;&nbsp; /*&nbsp; Param 11: sxedecay[4]. */</tt>
<br><tt>&nbsp;&nbsp; {</tt>
<br><tt>&nbsp;&nbsp; small,</tt>
<br><tt>&nbsp;&nbsp; slider,</tt>
<br><tt>&nbsp;&nbsp; "Decay 4",</tt>
<br><tt>&nbsp;&nbsp; "Decay of Delay 4.",</tt>
<br><tt>&nbsp;&nbsp; 0,</tt>
<br><tt>&nbsp;&nbsp; 255,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* 1 */</tt>
<br><tt>&nbsp;&nbsp; 220&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* 220/255 of dynamic range */</tt>
<br><tt>&nbsp;&nbsp; },</tt><tt></tt>
<p><tt>&nbsp;&nbsp; /*&nbsp; Param 12: sxedelay[4]. */</tt>
<br><tt>&nbsp;&nbsp; {</tt>
<br><tt>&nbsp;&nbsp; small,</tt>
<br><tt>&nbsp;&nbsp; slider,</tt>
<br><tt>&nbsp;&nbsp; "Delay 4",</tt>
<br><tt>&nbsp;&nbsp; "Delay 4 time: 0 to maximum.",</tt>
<br><tt>&nbsp;&nbsp; 
0,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* 0 msec. delay&nbsp; */</tt>
<br><tt>&nbsp;&nbsp; 255,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* Highest delay of range */</tt>
<br><tt>&nbsp;&nbsp; 175&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* 175/255 of MAX_DELAY msec */</tt>
<br><tt>&nbsp;&nbsp; },</tt><tt></tt>
<p><tt>&nbsp;&nbsp; /*&nbsp; Param 13: sxedecay[5]. */</tt>
<br><tt>&nbsp;&nbsp; {</tt>
<br><tt>&nbsp;&nbsp; small,</tt>
<br><tt>&nbsp;&nbsp; slider,</tt>
<br><tt>&nbsp;&nbsp; "Decay 5",</tt>
<br><tt>&nbsp;&nbsp; "Decay of Delay 5.",</tt>
<br><tt>&nbsp;&nbsp; 0,</tt>
<br><tt>&nbsp;&nbsp; 255,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* 1 */</tt>
<br><tt>&nbsp;&nbsp; 220&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* 220/255 of dynamic range */</tt>
<br><tt>&nbsp;&nbsp; },</tt><tt></tt>
<p><tt>&nbsp;&nbsp; /*&nbsp; Param 14: sxedelay[5]. */</tt>
<br><tt>&nbsp;&nbsp; {</tt>
<br><tt>&nbsp;&nbsp; small,</tt>
<br><tt>&nbsp;&nbsp; slider,</tt>
<br><tt>&nbsp;&nbsp; "Delay 5",</tt>
<br><tt>&nbsp;&nbsp; "Delay 5 time: 0 to maximum.",</tt>
<br><tt>&nbsp;&nbsp; 
0,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* 0 msec. delay&nbsp; */</tt>
<br><tt>&nbsp;&nbsp; 255,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* Highest delay of range */</tt>
<br><tt>&nbsp;&nbsp; 210&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* 210/255 of MAX_DELAY msec */</tt>
<br><tt>&nbsp;&nbsp; },</tt><tt></tt>
<p><tt>&nbsp;&nbsp; /*&nbsp; Param 15: sxedecay[6]. */</tt>
<br><tt>&nbsp;&nbsp; {</tt>
<br><tt>&nbsp;&nbsp; small,</tt>
<br><tt>&nbsp;&nbsp; slider,</tt>
<br><tt>&nbsp;&nbsp; "Decay 6",</tt>
<br><tt>&nbsp;&nbsp; "Decay of Delay 6.",</tt>
<br><tt>&nbsp;&nbsp; 0,</tt>
<br><tt>&nbsp;&nbsp; 255,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* 1 */</tt>
<br><tt>&nbsp;&nbsp; 220&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* 220/255 of dynamic range */</tt>
<br><tt>&nbsp;&nbsp; },</tt><tt></tt>
<p><tt>&nbsp;&nbsp; /*&nbsp; Param 16: sxedelay[6]. */</tt>
<br><tt>&nbsp;&nbsp; {</tt>
<br><tt>&nbsp;&nbsp; small,</tt>
<br><tt>&nbsp;&nbsp; slider,</tt>
<br><tt>&nbsp;&nbsp; "Delay 6",</tt>
<br><tt>&nbsp;&nbsp; "Delay 6 time: 0 to maximum.",</tt>
<br><tt>&nbsp;&nbsp; 
0,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* 0 msec. delay&nbsp; */</tt>
<br><tt>&nbsp;&nbsp; 255,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* Highest delay of range */</tt>
<br><tt>&nbsp;&nbsp; 255</tt>
<br><tt>&nbsp;&nbsp; },</tt>
<br><tt>};</tt><tt></tt>
<p><tt>/*&nbsp; State of the soxflanger. */</tt><tt></tt>
<p><tt>typedef struct {</tt>
<br><tt>&nbsp;&nbsp; float&nbsp;&nbsp; in_gain, out_gain;</tt>
<br><tt>&nbsp;&nbsp; float&nbsp;&nbsp; sxedecay[MAX_ECHOS];</tt>
<br><tt>&nbsp;&nbsp; float&nbsp;&nbsp; sxedelay[MAX_ECHOS];</tt>
<br><tt>&nbsp;&nbsp; long&nbsp;&nbsp;&nbsp; sxesamples[MAX_ECHOS];</tt>
<br><tt>&nbsp;&nbsp; samp*&nbsp;&nbsp; delaybuf;</tt>
<br><tt>&nbsp;&nbsp; long&nbsp;&nbsp;&nbsp; maxsxesamples;</tt>
<br><tt>&nbsp;&nbsp; float&nbsp;&nbsp; maxanydelay;</tt>
<br><tt>&nbsp;&nbsp; long&nbsp;&nbsp;&nbsp; maxanysmpls;</tt>
<br><tt>&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp; echo_cntr;</tt>
<br><tt>&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp; num_delays;</tt>
<br><tt>&nbsp;&nbsp; double&nbsp; unit_vol_scale;</tt>
<br><tt>&nbsp;&nbsp; double&nbsp; exp_fract_vol;</tt>
<br><tt>//&nbsp;&nbsp; double&nbsp; unit_delay_scale;</tt>
<br><tt>//&nbsp;&nbsp; double&nbsp; exp_fract_delay;</tt>
<br><tt>//&nbsp;&nbsp; float&nbsp;&nbsp; clip; // Put in after clipping
issue decided.</tt>
<br><tt>} sxe_state;</tt><tt></tt>
<p><tt>int ox_init(machine_type *t) {</tt>
<br><tt>&nbsp;&nbsp; t->long_name = "soxecho (Mueller, Nelson, et al.)";</tt>
<br><tt>&nbsp;&nbsp; t->short_name = "soxecho";</tt>
<br><tt>&nbsp;&nbsp; t->max_tracks = 1;</tt>
<br><tt>&nbsp;&nbsp; t->input_channels = 1;</tt>
<br><tt>&nbsp;&nbsp; t->output_channels = 1;</tt>
<br><tt>&nbsp;&nbsp; t->num_params = 15;</tt>
<br><tt>&nbsp;&nbsp; t->param_specs = sxe_params;</tt><tt></tt>
<p><tt>&nbsp;&nbsp; return 1;</tt>
<br><tt>}</tt><tt></tt>
<p><tt>void ox_create(machine *m) {</tt>
<br><tt>&nbsp;&nbsp; sxe_state *s;</tt>
<br><tt>&nbsp;&nbsp; int i;</tt><tt></tt>
<p><tt>&nbsp;&nbsp; s = (sxe_state*) malloc(sizeof(sxe_state));</tt>
<br><tt>&nbsp;&nbsp; m->state = (void *) s;</tt><tt></tt>
<p><tt>&nbsp;&nbsp; s->num_delays = MAX_ECHOS;</tt><tt></tt>
<p><tt>&nbsp;&nbsp; s->unit_vol_scale = exp((double)DYN_RANGE / 3.0) -
1.0;</tt>
<br><tt>&nbsp;&nbsp; s->exp_fract_vol = ((double)DYN_RANGE / 3) / 
255.0;</tt><tt></tt>
<p><tt>//&nbsp;&nbsp; s->unit_delay_scale = (exp((double)DELAY_LOG_RANGE)
- 1.0) / (double)MAX_DELAY;</tt>
<br><tt>//&nbsp;&nbsp; s->exp_fract_delay = ((double)DELAY_LOG_RANGE) /
255.0;</tt><tt></tt>
<p><tt>&nbsp;&nbsp; /* Set defaults */</tt>
<br><tt>//&nbsp;&nbsp; s->in_gain&nbsp;&nbsp;&nbsp; = 128.0/255.0;&nbsp;&nbsp;
/* Approx. 0.5 (old) */</tt>
<br><tt>&nbsp;&nbsp; s->in_gain&nbsp; = ((float)exp(70.0 * s->exp_fract_vol)
- 1.0)</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/ s->unit_vol_scale;</tt>
<br><tt>//&nbsp;&nbsp; s->out_gain&nbsp;&nbsp; = 
1.0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* No attenuation */</tt>
<br><tt>&nbsp;&nbsp; s->out_gain&nbsp; = ((float)exp(100.0 * s->exp_fract_vol)
- 1.0)</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/ s->unit_vol_scale;</tt><tt></tt>
<p><tt>&nbsp;&nbsp; s->sxedecay[0] = ((float)exp(220.0 * s->exp_fract_vol)
- 1.0)</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/ s->unit_vol_scale;</tt>
<br><tt>&nbsp;&nbsp; s->sxedelay[0] = 35.0/255.0 * (float)MAX_DELAY;</tt>
<br><tt>//&nbsp;&nbsp; s->sxedelay[0] = ((float)exp(35.0 * s->exp_fract_delay)
- 1.0)</tt>
<br><tt>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/ s->unit_delay_scale;</tt><tt></tt>
<p><tt>&nbsp;&nbsp; s->sxedecay[1] = ((float)exp(220.0 * s->exp_fract_vol)
- 1.0)</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/ s->unit_vol_scale;</tt>
<br><tt>&nbsp;&nbsp; s->sxedelay[1] = 70.0/255.0 * (float)MAX_DELAY;</tt>
<br><tt>//&nbsp;&nbsp; s->sxedelay[1] = ((float)exp(70.0 * s->exp_fract_delay)
- 1.0)</tt>
<br><tt>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/ s->unit_delay_scale;</tt><tt></tt>
<p><tt>&nbsp;&nbsp; s->sxedecay[2] = ((float)exp(220.0 * s->exp_fract_vol)
- 1.0)</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/ s->unit_vol_scale;</tt>
<br><tt>&nbsp;&nbsp; s->sxedelay[2] = 105.0/255.0 * (float)MAX_DELAY;</tt>
<br><tt>//&nbsp;&nbsp; s->sxedelay[2] = ((float)exp(105.0 * s->exp_fract_delay)
- 1.0)</tt>
<br><tt>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/ s->unit_delay_scale;</tt><tt></tt>
<p><tt>&nbsp;&nbsp; s->sxedecay[3] = ((float)exp(220.0 * s->exp_fract_vol)
- 1.0)</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/ s->unit_vol_scale;</tt>
<br><tt>&nbsp;&nbsp; s->sxedelay[3] = 140.0/255.0 * (float)MAX_DELAY;</tt>
<br><tt>//&nbsp;&nbsp; s->sxedelay[3] = ((float)exp(140.0 * s->exp_fract_delay)
- 1.0)</tt>
<br><tt>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/ s->unit_delay_scale;</tt><tt></tt>
<p><tt>&nbsp;&nbsp; s->sxedecay[4] = ((float)exp(220.0 * s->exp_fract_vol)
- 1.0)</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/ s->unit_vol_scale;</tt>
<br><tt>&nbsp;&nbsp; s->sxedelay[4] = 175.0/255.0 * (float)MAX_DELAY;</tt>
<br><tt>//&nbsp;&nbsp; s->sxedelay[4] = ((float)exp(175.0 * s->exp_fract_delay)
- 1.0)</tt>
<br><tt>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/ s->unit_delay_scale;</tt><tt></tt>
<p><tt>&nbsp;&nbsp; s->sxedecay[5] = ((float)exp(220.0 * s->exp_fract_vol)
- 1.0)</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/ s->unit_vol_scale;</tt>
<br><tt>&nbsp;&nbsp; s->sxedelay[5] = 210.0/255.0 * (float)MAX_DELAY;</tt>
<br><tt>//&nbsp;&nbsp; s->sxedelay[5] = ((float)exp(210.0 * s->exp_fract_delay)
- 1.0)</tt>
<br><tt>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/ s->unit_delay_scale;</tt><tt></tt>
<p><tt>&nbsp;&nbsp; s->sxedecay[6] = ((float)exp(220.0 * s->exp_fract_vol)
- 1.0)</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/ s->unit_vol_scale;</tt>
<br><tt>&nbsp;&nbsp; s->sxedelay[6] = 255.0/255.0 * (float)MAX_DELAY;</tt>
<br><tt>//&nbsp;&nbsp; s->sxedelay[6] = ((float)exp(255.0 * s->exp_fract_delay)
- 1.0)</tt>
<br><tt>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/ s->unit_delay_scale;</tt><tt></tt>
<p><tt>&nbsp;&nbsp; s->maxsxesamples = 0; // Accumulated in following 
loop.</tt><tt></tt>
<p><tt>&nbsp;&nbsp; for(i = 0; i &lt; s->num_delays; i++) {</tt><tt></tt>
<p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s->sxesamples[i] = (long)(s->sxedelay[i]
* ((float)OX_SAMPLING_RATE) / 1000.0</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ 0.5);</tt><tt></tt>
<p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (s->sxesamples[i] > 
s->maxsxesamples)</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s->maxsxesamples
= s->sxesamples[i];</tt>
<br><tt>&nbsp;&nbsp; }</tt><tt></tt>
<p><tt>&nbsp;&nbsp; s->maxanydelay = MAX_DELAY;</tt>
<br><tt>&nbsp;&nbsp; s->maxanysmpls = (long)(s->maxanydelay * 
((float)OX_SAMPLING_RATE)
/ 1000.0</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ 10.0); // Add an extra 10 to avoid possible exp overflow.</tt><tt></tt>
<p><tt>&nbsp;&nbsp; if (s->maxsxesamples > s->maxanysmpls)</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("%s\n",</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
"soxecho create error: delay sample requirement exceeds 
allocation.");</tt><tt></tt>
<p><tt>&nbsp;&nbsp; s->echo_cntr = 0;</tt><tt></tt>
<p><tt>//&nbsp;&nbsp; s->clip = ?; // Put in after clipping issue 
decided.</tt><tt></tt>
<p><tt>&nbsp;&nbsp; s->delaybuf = (samp*) malloc(s->maxanysmpls * 
sizeof(samp));</tt><tt></tt>
<p><tt>//&nbsp;&nbsp; memset(s->delaybuf, 0, s->maxanysmpls * sizeof(samp));
// Unnecessary</tt>
<br><tt>//&nbsp;&nbsp; for (i=0, i &lt; s->maxanysmpls, i++) s->delaybuf[i]
= 0; // Speed this up.</tt><tt></tt>
<p><tt>&nbsp;&nbsp; return;</tt>
<br><tt>}</tt><tt></tt>
<p><tt>void ox_destroy(machine *m) {</tt>
<br><tt>&nbsp;&nbsp; free( ((sxe_state*)(m->state)) -> delaybuf);</tt>
<br><tt>&nbsp;&nbsp; free(m->state);</tt>
<br><tt>&nbsp;&nbsp; m->state = NULL;</tt>
<br><tt>&nbsp;&nbsp; return;</tt>
<br><tt>}</tt><tt></tt>
<p><tt>void ox_update(machine *m) {</tt>
<br><tt>&nbsp;&nbsp; sxe_state *s = (sxe_state *) m->state;</tt>
<br><tt>&nbsp;&nbsp; param temp;</tt>
<br><tt>&nbsp;&nbsp; int i;</tt><tt></tt>
<p><tt>&nbsp;&nbsp; temp = m->params[0][ix_gain_in];</tt>
<br><tt>&nbsp;&nbsp; if (temp != nochange) {</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
(temp &lt; 0)&nbsp;&nbsp; temp = 0;</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else if (temp > 255) temp = 255;</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s->in_gain = ((float)temp) / 255.0;</tt>
<br><tt>&nbsp;&nbsp; }</tt><tt></tt>
<p><tt>&nbsp;&nbsp; temp = m->params[0][ix_gain_out];</tt>
<br><tt>&nbsp;&nbsp; if (temp != nochange) {</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
(temp &lt; 0)&nbsp;&nbsp; temp = 0;</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else if (temp > 255) temp = 255;</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s->out_gain = ((float)temp) / 255.0;</tt>
<br><tt>&nbsp;&nbsp; }</tt><tt></tt>
<p><tt>&nbsp;&nbsp; s->maxsxesamples = 0; // Accumulated in following 
loop.</tt><tt></tt>
<p><tt>&nbsp;&nbsp; for(i = 0; i &lt; s->num_delays; i++) {</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; temp = m->params[0][ix_sxedecay
+ i * 2];</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (temp != nochange) {</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
if&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
(temp &lt; 0)&nbsp;&nbsp; temp = 0;</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else if (temp
> 255) temp = 255;</tt><tt></tt>
<p><tt>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s->sxedecay[i]
= ((float)temp) / 255.0; // Old, linear.</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s->sxedecay[i]
= ((float)exp((double)temp * s->exp_fract_vol) - 1.0)</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/ s->unit_vol_scale;</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</tt><tt></tt>
<p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; temp = m->params[0][ix_sxedelay +
i * 2];</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (temp != nochange) {</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
if&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
(temp &lt; 1)&nbsp;&nbsp; temp = 0;</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else if (temp
> 255) temp = 255;</tt><tt></tt>
<p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s->sxedelay[i]
= (float)temp/255.0 * (float)MAX_DELAY;</tt>
<br><tt>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s->sxedelay[i]
= ((float)exp((double)temp * s->exp_fract_delay) - 1.0)</tt>
<br><tt>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/ s->unit_delay_scale;</tt><tt></tt>
<p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s->sxesamples[i]
= (long)(s->sxedelay[i] * ((float)OX_SAMPLING_RATE)</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/ 1000.0 + 0.5);</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</tt><tt></tt>
<p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (s->sxesamples[i] > s->maxsxesamples)
s->maxsxesamples = s->sxesamples[i];</tt>
<br><tt>&nbsp;&nbsp; }</tt><tt></tt>
<p><tt>&nbsp;&nbsp; return;</tt>
<br><tt>}</tt><tt></tt>
<p><tt>const char *ox_desc(int which_param, param value) {</tt>
<br><tt>&nbsp;&nbsp; static char temp_string[80];</tt>
<br><tt>&nbsp;&nbsp; float user_value;</tt>
<br><tt>&nbsp;&nbsp; int i, percent;</tt><tt></tt>
<p><tt>&nbsp;&nbsp; sprintf(temp_string, "ERROR");</tt><tt></tt>
<p><tt>&nbsp;&nbsp; if (which_param == ix_gain_in || which_param == ix_gain_out)
{</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (value &lt; 0) sprintf(temp_string,
"Gain must not be less than 0.");</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else {</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; user_value = 
((float)value)
/ 255.0;</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; percent = 
(int)(user_value
* 100.0 + 0.5);</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (user_value
> 1.0)</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
sprintf(temp_string, "Gain must be not greater than 100%.");</tt><tt></tt>
<p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else 
sprintf(temp_string,
"%3.0f%%", percent);</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</tt>
<br><tt>&nbsp;&nbsp; }</tt><tt></tt>
<p><tt>&nbsp;&nbsp; else {</tt><tt></tt>
<p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(i = 0; i &lt; MAX_ECHOS; i++)
{</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (which_param
== (ix_sxedecay + i * 2)) {</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
if (value &lt; 0) sprintf(temp_string, "%s%d%s", "Decay ", i,</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
" must not be less than 0.&nbsp; 0 removes this delay");</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
else {</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
user_value = (float)value / 255.0;</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
percent = (int)(user_value * 100.0 + 0.5);</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
if (user_value > 1.0)</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
sprintf(temp_string, "%s%d%s", "Decay ", i,</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
"must be not greater than 100%.");</tt><tt></tt>
<p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
else sprintf(temp_string, "%3.0f%%", percent);</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
}</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</tt><tt></tt>
<p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else if (which_param
== (ix_sxedelay + i * 2)) {</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
if (value &lt; 0) sprintf(temp_string, "%s%d%s", "Delay ", i,</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
" must not be less than 0.");</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
else {</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
user_value = (float)value / 255.0 * (float)MAX_DELAY;</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
if (user_value > (float)MAX_DELAY)</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
sprintf(temp_string, "%s%d%s%d%s", "Delay ", i,</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
" must be not greater than ", MAX_DELAY, " msec.");</tt><tt></tt>
<p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
else sprintf(temp_string, "%3.0f", user_value);</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
}</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</tt>
<br><tt>&nbsp;&nbsp; }</tt>
<br><tt>/*</tt>
<br><tt>&nbsp;*** Be nice and check the hint with warning, if...</tt>
<br><tt>&nbsp;sum_in_volume = 1.0;</tt>
<br><tt>&nbsp;for ( i = 0; i &lt; echo->num_delays; i++ )</tt>
<br><tt>&nbsp; sum_in_volume += echo->decay[i];</tt>
<br><tt>&nbsp;if ( sum_in_volume * echo->in_gain > 1.0 / echo->out_gain
)</tt>
<br><tt>&nbsp; warn("echo: warning >>> gain-out can cause saturation of
output &lt;&lt;&lt;");</tt>
<br><tt>*/</tt><tt></tt>
<p><tt>}</tt><tt></tt>
<p><tt>int ox_work(machine *m, int block_size) {</tt>
<br><tt>&nbsp;&nbsp; sxe_state *s = (sxe_state *) m->state;</tt><tt></tt>
<p><tt>&nbsp;&nbsp; samp* mlout;</tt>
<br><tt>//&nbsp;&nbsp; samp* mrout;</tt>
<br><tt>&nbsp;&nbsp; samp* mlin;</tt>
<br><tt>&nbsp;&nbsp; samp* dlybf;</tt>
<br><tt>&nbsp;&nbsp; int i, j, dlyctr, numdlys;</tt>
<br><tt>&nbsp;&nbsp; long mxsmpls;</tt>
<br><tt>&nbsp;&nbsp; long* sxsmpls;</tt>
<br><tt>&nbsp;&nbsp; float ingain, outgain;</tt>
<br><tt>&nbsp;&nbsp; float* sxdecy;</tt><tt></tt>
<p><tt>//&nbsp;&nbsp; float hig_clip, low_clip;</tt><tt></tt>
<p><tt>//&nbsp;&nbsp; hig_clip = s->clip;</tt>
<br><tt>//&nbsp;&nbsp; low_clip = 0.0 - s->clip;</tt><tt></tt>
<p><tt>&nbsp;&nbsp; /* Speed-up variables */</tt>
<br><tt>&nbsp;&nbsp; mlout&nbsp;&nbsp;&nbsp; = m->lout;</tt>
<br><tt>//&nbsp;&nbsp; mrout&nbsp;&nbsp;&nbsp; = m->rout;</tt>
<br><tt>&nbsp;&nbsp; mlin&nbsp;&nbsp;&nbsp;&nbsp; = m->lin;</tt><tt></tt>
<p><tt>&nbsp;&nbsp; ingain&nbsp;&nbsp; = s->in_gain;</tt>
<br><tt>&nbsp;&nbsp; outgain&nbsp; = s->out_gain;</tt><tt></tt>
<p><tt>&nbsp;&nbsp; dlybf&nbsp;&nbsp;&nbsp; = s->delaybuf;</tt>
<br><tt>&nbsp;&nbsp; dlyctr&nbsp;&nbsp; = s->echo_cntr;</tt>
<br><tt>&nbsp;&nbsp; mxsmpls&nbsp; = s->maxsxesamples;</tt>
<br><tt>&nbsp;&nbsp; sxsmpls&nbsp; = (long*)s->sxesamples;</tt>
<br><tt>&nbsp;&nbsp; sxdecy&nbsp;&nbsp; = (float*)s->sxedecay;</tt>
<br><tt>&nbsp;&nbsp; numdlys&nbsp; = s->num_delays;</tt><tt></tt>
<p><tt>&nbsp;&nbsp; for(i = 0; i &lt; block_size; i++) {</tt><tt></tt>
<p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Compute output first */</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mlout[i] = mlin[i] * 
ingain;</tt><tt></tt>
<p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (j = 0; j &lt; numdlys; j++)
{</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (sxdecy[j])</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
mlout[i] += dlybf[(mxsmpls + dlyctr - sxsmpls[j]) % mxsmpls] * sxdecy[j];</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</tt><tt></tt>
<p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Adjust the output volume */</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mlout[i] *= outgain;</tt><tt></tt>
<p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Check for clipping.&nbsp; Not
implemented. */</tt>
<br><tt>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
(mlout[i] > hig_clip)&nbsp; mlout[i] = hig_clip;</tt>
<br><tt>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else if (mlout[i] &lt; low_clip)&nbsp;
mlout[i] = low_clip;</tt><tt></tt>
<p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Store input in delay buffer */</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dlybf[dlyctr] = mlin[i];</tt><tt></tt>
<p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Adjust the counter */</tt>
<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dlyctr = ( dlyctr + 1 ) % 
mxsmpls;</tt><tt></tt>
<p><tt>&nbsp;&nbsp; }</tt><tt></tt>
<p><tt>&nbsp;&nbsp; /* Save speed-up variables to state. */</tt>
<br><tt>&nbsp;&nbsp; s->echo_cntr = dlyctr;</tt><tt></tt>
<p><tt>&nbsp;&nbsp; return 1;</tt>
<br><tt>}</tt><tt></tt>
<p><tt>void ox_track(machine *m, int change) {</tt>
<br><tt>}</tt>
<br><tt></tt>&nbsp;</html>

--------------801DEC9FA1F1642AE599CEF4--



reply via email to

[Prev in Thread] Current Thread [Next in Thread]