home *** CD-ROM | disk | FTP | other *** search
/ Esprit de Apple Corps / EDAC-2.iso / Graphics / Apps / Programs / WaveLab / genwave.c next >
Encoding:
C/C++ Source or Header  |  1994-05-22  |  8.0 KB  |  263 lines

  1. /* ---------------------------------------------------------------------
  2.  *
  3.  * Generate a wave for use by the waveLAB program
  4.  *
  5.  *    Written by Dave Tribby  *  All commercial rights reserved
  6.  *    (tribby@cup.hp.com)     *  Freeware: distribute, but not for profit.
  7.  *
  8.  * This program shows how to generate waveforms that can be used by waveLAB
  9.  * in building additional waves. For waveLAB to use it, the file must have
  10.  * these characteristics:
  11.  *
  12.  *    - It consists of 1024 16-bit integers (65816 integer format).
  13.  *
  14.  *    - Each integer is in the range 1 to 255 (high-order byte is 0).
  15.  *      The closer you can get the maximum value to 255, and the
  16.  *      minimum to 1, the better the resulting sound.
  17.  *
  18.  *    - In order to reduce clicking and popping, try to have the wave
  19.  *      start and stop at the midpoint value, 128. In one example,
  20.  *      the code detects this mid-point and moves the wave values.
  21.  *
  22.  *    - File name is "special1" or "special2" and is placed in the "@"
  23.  *      directory (either the one waveLAB is executed from or the user
  24.  *    directory on the file server).
  25.  *
  26.  * Hints...
  27.  *
  28.  *    - If the wave can be reflected around a particular point, you only
  29.  *      need to generate part of the wave and then copy the results.
  30.  *
  31.  *    - If a wave results in a sound that seems too soft, try working
  32.  *      with the inverse of the original values (256-y instead of y).
  33.  *
  34.  *    - It may take several test runs to determine the starting and
  35.  *    stopping x-values that produce the best waveform. You can also
  36.  *    use a plotting program such as MathGraphics by Dirk Frohling
  37.  *    ($15 shareware) to select good ranges.
  38.  * 
  39.  * The two examples are written so they could be easily moved individually
  40.  * to separate programs.
  41.  *
  42.  * This program has been compiled under ORCA/C for the Apple IIGS.
  43.  *
  44.  * ---------------------------------------------------------------------
  45.  */
  46.  
  47. #include <math.h>
  48. #include <stdio.h>
  49. #include <string.h>
  50. #include <stdlib.h>
  51. #include <orca.h>
  52.  
  53. #pragma lint -1
  54. #pragma optimize -1
  55.  
  56. #define BUILD_WAVE_SIZE 1024
  57. int    *user_wave = NULL;
  58.  
  59.  
  60. /* --------------------------------------------------------------------- */
  61. /* Abnormal termination
  62. /* --------------------------------------------------------------------- */
  63. void AbEnd(char *msg)
  64.    {
  65.    int   error;
  66.    error = toolerror();
  67.    fprintf(stderr,  "\n%s:\n Tool error $%04X",  msg, error);
  68.    exit (-1);                             
  69.    }    /* AbEnd */
  70.  
  71.  
  72. /* -------------------------------------------------------------------- */
  73. /* Example 1:
  74. /*     Create a non-symmetric wave that is known to start at a midpoint
  75. /* -------------------------------------------------------------------- */
  76.  
  77. /* Range of X values (chosen such that f1()=128) */
  78. #define MinX1 -11.0
  79. #define MaxX1 4.1
  80.  
  81. /* Function 1 (must return value in range 1-255)   */
  82. /* Polynomial: 0.77*x*x*x + 8.0*x*x - 16.0*x + 8.5 */
  83. int f1(extended x)
  84.    {
  85.    /* Use parenthesized terms to reduce number of multiplies */
  86.    return ((0.77*x + 8.0)*x - 16.0)*x + 8.5;
  87.    }
  88.  
  89. void GenerateWave1(char *wavename)
  90.    {
  91.    int         i;
  92.    int        *pnt;        /* Pointer into wave */
  93.    extended     x;              /* Goes from -MaxX to +MaxX */
  94.    extended    x_step;        /* Step for x values */
  95.    extended    slices;         /* # elements as extended num */
  96.    int        min=256, max=0;    /* Minumum and maximum Y values */
  97.    FILE *userfile;
  98.                  
  99.    /* Get the memory for the wave */
  100.    if ( (user_wave = malloc(BUILD_WAVE_SIZE*2)) == NULL)  {
  101.       AbEnd("Allocating memory to hold wave");
  102.       }
  103.  
  104.    fprintf(stderr, "Generating wave");
  105.    slices = BUILD_WAVE_SIZE;
  106.    x_step = (MaxX1-MinX1)/slices;
  107.    x = MinX1;
  108.    pnt = user_wave;
  109.  
  110.    for (i=0; i<=BUILD_WAVE_SIZE; i++)  {
  111.       *pnt = f1(x);
  112.       /* Check for minimum and maximum */
  113.       if ( (*pnt) < min )   min = *pnt;
  114.       if ( (*pnt) > max )   max = *pnt;
  115.       x += x_step;
  116.       pnt++;
  117.       if (i%100 == 0) fprintf(stderr, ".");
  118.       }                      
  119.  
  120.    /* Write the file */
  121.    userfile = fopen(wavename, "wb");
  122.    (void) fwrite(user_wave, BUILD_WAVE_SIZE*2, 1, userfile);
  123.    fclose(userfile);
  124.  
  125.    fprintf(stderr, " DONE!\n");
  126.    fprintf(stderr, "Minimum value = %d; maximum = %d\n", min,max);
  127.    if ( min < 1 )
  128.       fprintf(stderr, "ERROR: minimum cannot be less than 1!\n");
  129.    else if ( min != 1 )
  130.       fprintf(stderr, "Note: for best results, minimum should be equal to 1\n");
  131.    if ( max > 255 )
  132.       fprintf(stderr, "ERROR: maximum cannot be greater than 255!\n");
  133.    else if ( max != 255 )
  134.       fprintf(stderr, "Note: for best results, maximum should be equal to 255\n");
  135.    }   /* GenerateWave1 */
  136.  
  137.  
  138.  
  139.  
  140. /* -------------------------------------------------------------------- */
  141. /* Example 2:
  142. /*     Create a symmetric wave that does not start at a midpoint
  143. /* -------------------------------------------------------------------- */
  144.  
  145. /* Range of X values goes from -MaxX2 to MaxX2 */
  146. #define MaxX2 6.23
  147.  
  148. /* Function 2 (must return value in range 1-255)    */
  149. int f2(extended x)
  150.    {
  151.    return 256 - cosh(x);
  152.    }
  153.  
  154. void GenerateWave2(char *wavename)
  155.    {                     
  156.    int         i;
  157.    int        mp;        /* Index of mid-point */
  158.    int        mpdelta;    /* Diff between mp value and 128 */
  159.    int        *pnt, *pnt2;    /* Pointer into waves */
  160.    extended     x;              /* Goes from -MaxX2 to +MaxX2 */
  161.    extended    x_step;        /* Step for x values */
  162.    extended    slices;         /* # elements as extended num */
  163.    int        min=256, max=0;    /* Minumum and maximum Y values */
  164.    FILE *userfile;
  165.                  
  166.    /* Get the memory for the wave */
  167.    if ( (user_wave = malloc(BUILD_WAVE_SIZE*2)) == NULL)  {
  168.       AbEnd("Allocating memory to hold wave");
  169.       }
  170.  
  171.    fprintf(stderr, "Generating wave");
  172.    slices = BUILD_WAVE_SIZE;
  173.    x_step = MaxX2*2/slices;
  174.  
  175.    pnt = user_wave;
  176.  
  177.    x = -MaxX2;
  178.  
  179.    /* Set up for mid-point search */
  180.    mp = 0;
  181.    mpdelta = abs(f2(x) - 128);
  182.  
  183.    /* Calculate first half of waveform */
  184.    for (i=0; i<=(BUILD_WAVE_SIZE/2+1); i++)  {
  185.       *pnt = f2(x);
  186.       /* Check for minimum and maximum */
  187.       if ( (*pnt) < min )   min = *pnt;
  188.       if ( (*pnt) > max )   max = *pnt;
  189.  
  190.       /* Check for mid-point (value is 128) */
  191.       if ( abs(*pnt - 128) < mpdelta )   {
  192.          mp = i;
  193.          mpdelta = abs(*pnt - 128);
  194.          }
  195.       x += x_step;
  196.       pnt++;            
  197.       if (i%100 == 0) fprintf(stderr, ".");
  198.       }                      
  199.  
  200.    fprintf(stderr,"\nUsing mid-point at offset %d; y differs from 128 by %d\n",
  201.                mp,mpdelta);
  202.  
  203.    /* Move values so mid-point (value=128) is on the end */
  204.    pnt2 = user_wave;
  205.    pnt = &user_wave[BUILD_WAVE_SIZE-mp];
  206.    for (i=0; i<mp; i++)   {
  207.       *pnt = *pnt2;
  208.       pnt++;
  209.       pnt2++;
  210.       }
  211.    pnt = user_wave;
  212.    for (i=mp; i<=(BUILD_WAVE_SIZE/2+1); i++)   {
  213.       *pnt = *pnt2;
  214.       pnt++;
  215.       pnt2++;
  216.       }
  217.  
  218.    fprintf(stderr, "Reflecting...");
  219.  
  220.    /* Reflect first half onto second half */
  221.    pnt2 = pnt--;
  222.    for (i=0; i<BUILD_WAVE_SIZE/2; i++)  {
  223.       *pnt = *pnt2;
  224.       pnt++;
  225.       if (pnt2 == user_wave)
  226.          pnt2=&user_wave[BUILD_WAVE_SIZE-1];
  227.       else
  228.          pnt2--;
  229.       }
  230.  
  231.    /* Write the file */
  232.    userfile = fopen(wavename, "wb");
  233.    (void) fwrite(user_wave, BUILD_WAVE_SIZE*2, 1, userfile);
  234.    fclose(userfile);
  235.  
  236.    fprintf(stderr, " DONE!\n");
  237.    fprintf(stderr, "Minimum value = %d; maximum = %d\n", min,max);
  238.    if ( min < 1 )
  239.       fprintf(stderr, "ERROR: minimum cannot be less than 1!\n");
  240.    else if ( min != 1 )
  241.       fprintf(stderr, "Note: for best results, minimum should be equal to 1\n");
  242.    if ( max > 255 )
  243.       fprintf(stderr, "ERROR: maximum cannot be greater than 255!\n");
  244.    else if ( max != 255 )
  245.       fprintf(stderr, "Note: for best results, maximum should be equal to 255\n");
  246.    }   /* GenerateWave2 */
  247.  
  248.  
  249.  
  250. /* -------------------------------------------------------------------- */
  251. /* Beginning of main program                        */
  252. /* -------------------------------------------------------------------- */
  253. int main (int argc, char *argv[])
  254. {
  255. fprintf(stderr, "Program to show how to create base waves for waveLAB\n");
  256.  
  257. fprintf(stderr, "\nExample wave 1: polynomial\n");
  258. GenerateWave1("@:special1");
  259.  
  260. fprintf(stderr, "\n\nExample wave 2: symmetric\n");
  261. GenerateWave2("@:special2");
  262. }
  263.