home *** CD-ROM | disk | FTP | other *** search
/ Digispeech DS201A Drivers / dsapi_v120.zip / SOURCE / EMULATE.C < prev    next >
C/C++ Source or Header  |  1993-08-13  |  27KB  |  800 lines

  1. /* EMULATE.C */
  2. /****************************************************************************/
  3. /*                                                                          */
  4. /*  Abstract: Synthesizer Emulator demonstration.                           */
  5. /*                                                                          */
  6. /*  Language: Microsoft C, v6.00a  Model: LARGE    Machine type: IBM PC     */
  7. /*                                                                          */
  8. /****************************************************************************/
  9. /*
  10.  
  11.  REV  DATE       AUTHOR          DESCRIPTION
  12.  1.0  08-01-92   Lee Mulcahy     Initial version.
  13.  ---  08-13-93   Lee Mulcahy     Latest change.
  14.  
  15. */
  16.  
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include <signal.h>
  21. #include <conio.h>
  22. #include <io.h>
  23. #include <dos.h>
  24. #include <sys\types.h>
  25. #include <sys\timeb.h>
  26.  
  27.  
  28. /****************************************************************************/
  29. /*                                                                          */
  30. /*  Literals, etc.                                                          */
  31. /*                                                                          */
  32. /****************************************************************************/
  33.  
  34. #include "digi.h"
  35.  
  36. #define E_NOEMULATE     (E_CHANNELS + 1)    // Define our own error message
  37.  
  38. #define SYNTH_INIT      0
  39. #define SYNTH_READ      1
  40. #define SYNTH_WRITE     2
  41. #define SYNTH_RESET     3
  42.  
  43. #define KEY_ON          0x20        // Key-on bit for REG_FMSB
  44.  
  45. #define REG_SOUND       0x20        // Sound Characteristics register
  46. #define REG_KSLTL       0x40        // KSL / Total Level register
  47. #define REG_ARDR        0x60        // Attack Rate / Decay Rate register
  48. #define REG_SLRR        0x80        // Sustain Level / Release Rate register
  49. #define REG_FLSB        0xA0        // Frequency LSB register
  50. #define REG_FMSB        0xB0        // Frequency MSB register + key-on bit
  51. #define REG_MOD         0xC0        // Modulation mode / feedback register
  52. #define REG_WAVE        0xE0        // Wave Select register
  53.  
  54. #define NOT_FORCED          -2
  55.  
  56. #define ESC_KEY             0x1B
  57.  
  58. #define PLAY_UNSUPPORTED    0xFF
  59.  
  60. #define EXIT_BAD_USAGE      1
  61. #define EXIT_FILE_ERR       2
  62. #define EXIT_BAD_STATUS     3
  63. #define EXIT_NOT_SUPPORTED  4
  64.  
  65. static int note = 0;
  66. static int octave = 0;
  67.  
  68. static int paused = FALSE;
  69.  
  70. static char *notes [] =
  71.     {
  72.     "C ",
  73.     "C#",
  74.     "D ",
  75.     "D#",
  76.     "E ",
  77.     "F ",
  78.     "F#",
  79.     "G ",
  80.     "G#",
  81.     "A ",
  82.     "A#",
  83.     "B "
  84.     };
  85.  
  86.  
  87.     /* OKI ADPCM play rates.    */
  88.  
  89. static int playRates [4] = { 8000, 9000, 10000, 11000 };
  90.  
  91. static char *formatMsgs [] =
  92.     {
  93.     "Linear 8 bit PCM",         //  DF_PCM8         0
  94.     "Mu-Law PCM",               //  DF_PCMMU        1
  95.     "A-Law PCM",                //  DF_PCMA         2
  96.     "Linear 16 bit PCM",        //  DF_PCM16        3
  97.     "SB ADPCM 2 bit",           //  DF_SB2          4
  98.     "SB ADPCM 2.6 bit",         //  DF_SB3          5
  99.     "SB ADPCM 4 bit",           //  DF_SB4          6
  100.     "OKI ADPCM 4 bit",          //  DF_OKI4         7
  101.     "DVI ADPCM 4 bit",          //  DF_DVI4         8
  102.     "Digispeech Realtime",      //  DF_DIGIREAL     9
  103.     "Digispeech STD",           //  DF_DIGISTD      10
  104.     "Digispeech FIX",           //  DF_DIGIFIX      11
  105.     "",
  106.     "",
  107.     "CVSD",                     //  DF_CVSD         14
  108.     NULL
  109.     };
  110.  
  111.     /* Driver information.  */
  112.  
  113. static WORD support = 0;
  114.  
  115.     /* Synthesizer entry point pointer. */
  116.  
  117. static int  (_far *Emulate)( int function, BYTE addr, BYTE value );
  118.  
  119. static BYTE freqLSB;
  120. static BYTE freqMSB;
  121.  
  122.     /* BIOS Timer Tick Counter location.    */
  123.  
  124. static long far *tTickCount = (long far *)0x0040006CL;
  125.  
  126.     /* Global audio file information.   */
  127.  
  128. static WORD rate;
  129. static WORD format;
  130. static WORD headerLen;
  131. static DWORD length;
  132.  
  133.     /* Audio data buffers.  */
  134.  
  135. static char buf0[16384];
  136. static char buf1[16384];
  137.  
  138. static void Usage ( void );
  139. static int KeyPressed ( void );
  140. static void DSExit ( int status );
  141. static void LoadInstrument ( void );
  142. static int DSSetup ( void );
  143. static void PlayNote ( int note, int octave );
  144. static void Pause ( void );
  145. static void Resume ( void );
  146. static void ParseFileHeader ( FILE *fd );
  147. static void PlayScales ( void );
  148. static void PlayRandom ( void );
  149. static int PlayManager ( FILE *fd );
  150. static int ParseCommandLine ( int argc, char *argv[] );
  151. int main ( int argc, char *argv [] );
  152.  
  153.  
  154. /****************************************************************************/
  155. /*                                                                          */
  156. /*  Default Instrument Table                                                */
  157. /*                                                                          */
  158. /****************************************************************************/
  159.  
  160. typedef struct _instrumentDef
  161.     {
  162.     BYTE    mSoundChar;         // Modulator sound characteristic
  163.     BYTE    cSoundChar;         // Carrier sound characteristic
  164.     BYTE    mScaling;           // Modulator Scaling and Output level
  165.     BYTE    cScaling;           // Carrier Scaling and Output level
  166.     BYTE    mAttackDecay;       // Modulator Attack and Decay rates
  167.     BYTE    cAttackDecay;       // Carrier Attack and Decay rates
  168.     BYTE    mSustainRelease;    // Modulator Sustain and Release rates
  169.     BYTE    cSustainRelease;    // Carrier Sustain and Release rates
  170.     BYTE    mWaveSelect;        // Modulator Wave Select
  171.     BYTE    cWaveSelect;        // Carrier Wave Select
  172.     BYTE    feedback;           // Feedback / connection
  173.     BYTE    reserved [5];       // Reserved for future use.
  174.     } IDEF;
  175.  
  176. static IDEF testInstrument =
  177.     {
  178.     0x21, 0x31,     // MOD/CAR  0x2x    Sound Characteristic
  179.     0x00, 0x90,     // MOD/CAR  0x4x    Scaling / Output Level
  180.     0x81, 0xF1,     // MOD/CAR  0x6x    Attack / Decay
  181.     0x03, 0x05,     // MOD/CAR  0x8x    Sustain / Release
  182.     0x00, 0x00,     // MOD/CAR  0xEx    Wave Select
  183.     0x02,           //          0xCx    Feedback / Connection
  184.  
  185.     0x00, 0x00, 0x00, 0x00, 0x00        // Unused
  186.     };
  187.  
  188. static WORD freqTable [12] =
  189.     {
  190. //  C       C#      D       D#      E       F       F#      G
  191.     0x0157, 0x016B, 0x0181, 0x0198, 0x01B0, 0x01CA, 0x01E5, 0x0202,
  192. //  G#      A       A#      B
  193.     0x0220, 0x0241, 0x0263, 0x0287
  194.     };
  195.  
  196.  
  197. /** Usage *******************************************************************/
  198. /*                                                                          */
  199. /*  Display the program syntax and parameter list.                          */
  200. /*                                                                          */
  201. /****************************************************************************/
  202.  
  203. static void Usage ( void )
  204.     {
  205.  
  206.     puts( "  Usage: EMULATE <switches> filename \n" );
  207.     puts( "  Demonstrates use of PDIGI /X emulator interface.\n" );
  208.     puts( "  Plays a PCM Mu-Law or Linear file simultaneously" );
  209.     puts( "  with synthesized sound.\n" );
  210.     puts( "  /rx   - Force playback rate to x (default 8000)" );
  211.  
  212.     exit( EXIT_BAD_USAGE );
  213.     }
  214.  
  215.  
  216. /** KeyPressed **************************************************************/
  217. /*                                                                          */
  218. /*  If a key was pressed, return the key, else return FALSE.                */
  219. /*                                                                          */
  220. /****************************************************************************/
  221.  
  222. int KeyPressed ( void )
  223.     {
  224.     int key;
  225.  
  226.         /* Check for ESC key.   */
  227.  
  228.     key = 0;
  229.     if ( kbhit())
  230.         {
  231.         key = getch();
  232.  
  233.             /* If NULL, get another key and */
  234.             /* discard it (IBM PC oddity).  */
  235.  
  236.         if ( key == 0)
  237.             getch();
  238.         }
  239.  
  240.     return( key );
  241.     }
  242.  
  243.  
  244. /** DSExit ******************************************************************/
  245. /*                                                                          */
  246. /*  Print error message, status code, and then exit with error code.        */
  247. /*                                                                          */
  248. /*  Quite a few of the error messages listed here will never be encountered */
  249. /*  by this program, but are included 'cause I wanted all of 'em.           */
  250. /*                                                                          */
  251. /****************************************************************************/
  252.  
  253. static void DSExit ( int status )
  254.     {
  255.     char *ptr;
  256.  
  257.         /* If status is 0, this is actually a 'good' exit.  */
  258.  
  259.     if ( status == 0 )
  260.         exit( 0 );
  261.  
  262.     ptr = NULL;
  263.  
  264.     switch ( status )
  265.         {
  266.         case E_UNDEFINED:   ptr = "Undefined command.";                     break;
  267.         case E_BUF0:        ptr = "Current buffer is 0.";                   break;
  268.         case E_BUF1:        ptr = "Current buffer is 1.";                   break;
  269.         case E_MUSIC:       ptr = "Driver is in 3-tone gen mode.";          break;
  270.         case E_COM:         ptr = "Communication error.";                   break;
  271.         case E_LPC:         ptr = "LPC index out of range.";                break;
  272.         case E_CVSDSPEED:   ptr = "CVSD speed is invalid.";                 break;
  273.         case E_TIMEOUT:     ptr = "Audio Unit not responding.";             break;
  274.         case E_ERR:         ptr = "Audio Unit reported an error.";          break;
  275.  
  276.         case E_PAUSE:       ptr = "Audio is paused.";                       break;
  277.         case E_GAIN:        ptr = "Invalid gain index.";                    break;
  278.         case E_INDEX:       ptr = "Buffer index is invalid.";               break;
  279.         case E_LENGTH:      ptr = "Buffer length is invalid.";              break;
  280.         case E_NOBUFFER:    ptr = "No buffers were defined.";               break;
  281.         case E_IGNORED:     ptr = "Command ignored.";                       break;
  282.         case E_INVALID:     ptr = "Bad tone index specified.";              break;
  283.         case E_BUSY:        ptr = "Driver or device is busy";               break;
  284.         case E_SYNTH:       ptr = "Driver is in synthesizer mode";          break;
  285.  
  286.         case E_RATE:        ptr = "Invalid RATE argument.";                 break;
  287.         case E_FORMAT:      ptr = "Invalid FORMAT argument.";               break;
  288.         case E_MODE:        ptr = "Invalid MODE argument (REC/PLAY).";      break;
  289.         case E_VXD:         ptr = "Windows VxD Request error.";             break;
  290.         case E_CHANNELS:    ptr = "Invalid channel count.";                 break;
  291.         case E_NOEMULATE:   ptr = "No Synth Emulator, use PDIGI /X";        break;
  292.  
  293.         default:
  294.             printf(
  295.                 "\nUnknown Driver Error: 0x%04X\n\n",
  296.                 status
  297.                 );
  298.             break;
  299.         }
  300.  
  301.         /* Recognized the error code, so print the message. */
  302.  
  303.     if ( ptr != NULL )
  304.         printf( "\n%s\n\n", ptr );
  305.  
  306.     exit( EXIT_BAD_STATUS );
  307.     }
  308.  
  309.  
  310. /** LoadInstrument **********************************************************/
  311. /*                                                                          */
  312. /*  Program the emulator for a single instrument on voice cell 0.           */
  313. /*                                                                          */
  314. /****************************************************************************/
  315.  
  316. static void LoadInstrument ( void )
  317.     {
  318.  
  319.     Emulate( SYNTH_WRITE, REG_SOUND,     testInstrument.mSoundChar );
  320.     Emulate( SYNTH_WRITE, REG_SOUND + 3, testInstrument.cSoundChar );
  321.     Emulate( SYNTH_WRITE, REG_KSLTL,     testInstrument.mScaling );
  322.     Emulate( SYNTH_WRITE, REG_KSLTL + 3, testInstrument.cScaling );
  323.     Emulate( SYNTH_WRITE, REG_ARDR,      testInstrument.mAttackDecay );
  324.     Emulate( SYNTH_WRITE, REG_ARDR + 3,  testInstrument.cAttackDecay );
  325.     Emulate( SYNTH_WRITE, REG_SLRR,      testInstrument.mSustainRelease );
  326.     Emulate( SYNTH_WRITE, REG_SLRR + 3,  testInstrument.cSustainRelease );
  327.  
  328.     Emulate( SYNTH_WRITE, REG_WAVE,      testInstrument.mWaveSelect );
  329.     Emulate( SYNTH_WRITE, REG_WAVE + 3,  testInstrument.cWaveSelect );
  330.  
  331.     Emulate( SYNTH_WRITE, REG_MOD, testInstrument.feedback );
  332.     }
  333.  
  334.  
  335. /** DSSetup *****************************************************************/
  336. /*                                                                          */
  337. /*  Do some driver housekeeping.                                            */
  338. /*                                                                          */
  339. /****************************************************************************/
  340.  
  341. static int DSSetup ( void )
  342.     {
  343.     DWORD   support;
  344.     int     status;
  345.  
  346.         /* Setup driver stuff.  */
  347.  
  348.     if (( status = DSReset()) != E_OK )
  349.         DSExit( status );
  350.     if (( status = DSSetBuffer( 0, sizeof(buf0), (char far *)buf0)) != E_OK )
  351.         DSExit( status );
  352.     if (( status = DSSetBuffer( 1, sizeof(buf1), (char far *)buf1)) != E_OK )
  353.         DSExit( status );
  354.     if (( status = DSSetGain( 21 )) != E_OK )
  355.         DSExit( status );
  356.  
  357.     DSQuery( NULL, NULL, &support );
  358.  
  359.         /* Get the emulator entry point, init the synthesizer,  */
  360.         /* and load an instrument.                              */
  361.  
  362.     Emulate = DSGetEntry();
  363.     if ( Emulate == NULL )
  364.         DSExit( E_NOEMULATE );
  365.     if (( status = Emulate( SYNTH_INIT, 0, 0 )) != E_OK )
  366.         DSExit( status );
  367.     LoadInstrument();
  368.  
  369.     return( (int)support );     // We don't care about upper bits.
  370.     }
  371.  
  372.  
  373. /** PlayNote ****************************************************************/
  374. /*                                                                          */
  375. /*  Program the emulator to play a single note on voice cell 0.             */
  376. /*                                                                          */
  377. /****************************************************************************/
  378.  
  379. static void PlayNote ( int note, int octave )
  380.     {
  381.     WORD freq;
  382.  
  383.     octave = ( octave << 10 ) & 0x1C00;     // move to correct position
  384.     
  385.         /* Determine frequency value.   */
  386.  
  387.     freq = freqTable[ note] | octave;
  388.     freqLSB = (BYTE)freq;
  389.     freqMSB = (BYTE)((freq & 0xFF00) >> 8);
  390.  
  391.         /* Write frequency with key-on bit set. */
  392.  
  393.     Emulate( SYNTH_WRITE, REG_FLSB, freqLSB );
  394.     Emulate( SYNTH_WRITE, REG_FMSB, (BYTE)(freqMSB | KEY_ON) );
  395.     }
  396.  
  397.  
  398. /** Pause *******************************************************************/
  399. /*                                                                          */
  400. /*  Pause the driver.  This involves turning off the current synthesizer    */
  401. /*  note and then calling the driver pause function.                        */
  402. /*                                                                          */
  403. /****************************************************************************/
  404.  
  405. static void Pause ( void )
  406.     {
  407.  
  408.         /* Leave if already in paused state.    */
  409.  
  410.     if ( paused )
  411.         return;
  412.  
  413.         /* Set Sustain Level / Release Rate to diminishing sound.   */
  414.  
  415.     Emulate( SYNTH_WRITE, REG_SLRR + 3, 0x13 );
  416.  
  417.         /* Write the same frequency, but with the KEYON bit cleared.    */
  418.  
  419.     Emulate( SYNTH_WRITE, REG_FLSB, freqLSB );
  420.     Emulate( SYNTH_WRITE, REG_FMSB, freqMSB );
  421.  
  422.         /* We must wait for a short period of time to   */
  423.         /* allow the synthesizers commands to be sent   */
  424.         /* to the PORT*ABLE Sound before going on.      */
  425.         /* This is because the DSPause() routine is     */
  426.         /* immediate and may prevent these commands     */
  427.         /* from reaching the unit.                      */
  428.  
  429.     _Wait( 120 );
  430.  
  431.         /* Now send a pause to the digitized portion of the driver. */
  432.  
  433.     DSPause();
  434.     printf( "\n-- Pause ('R' resumes play) : " );
  435.     paused = TRUE;
  436.     }
  437.  
  438.  
  439. /** Resume ******************************************************************/
  440. /*                                                                          */
  441. /*  Allow the driver to continue.                                           */
  442. /*                                                                          */
  443. /****************************************************************************/
  444.  
  445. static void Resume ( void )
  446.     {
  447.  
  448.         /* Leave if not in paused state.    */
  449.  
  450.     if ( !paused )
  451.         return;
  452.  
  453.         /* Restore the previous sustain level   */
  454.         /* and release rate for the voice.      */
  455.  
  456.     Emulate( SYNTH_WRITE, REG_SLRR + 3, testInstrument.cSustainRelease );
  457.  
  458.         /* Let rest of driver resume.   */
  459.  
  460.     DSResume();
  461.     printf( "-- Resume\n" );
  462.     paused = FALSE;
  463.     }
  464.  
  465.  
  466. /** ParseFileHeader *********************************************************/
  467. /*                                                                          */
  468. /*  Determine file type and audio characteristics from file header.         */
  469. /*                                                                          */
  470. /*  Exits program if illegal file type encountered.                         */
  471. /*                                                                          */
  472. /****************************************************************************/
  473.  
  474. static void ParseFileHeader ( FILE *fd )
  475.     {
  476.     char    fileHead[10];
  477.  
  478.     length = filelength( fileno( fd ));     // Length of sound data.
  479.  
  480.         /* First byte of file should determine its type.    */
  481.  
  482.     format = fgetc( fd );
  483.     rewind( fd );
  484.  
  485.         /* Parse headers by file type.  */
  486.  
  487.     headerLen = 0;
  488.     switch ( format & 0xFF )
  489.         {
  490.         case H_PCMRAW:
  491.             format = DF_PCM8;
  492.             headerLen = 1;
  493.             length--;
  494.  
  495.             if ( rate == NOT_FORCED)
  496.                 rate = 8000;
  497.  
  498.             if (( support & CAPS_EPCM ) == 0 )
  499.                 format = PLAY_UNSUPPORTED;
  500.             break;
  501.  
  502.         case H_PCMMU:
  503.             format = DF_PCMMU;
  504.             headerLen = 1;
  505.             length--;
  506.  
  507.             if ( rate == NOT_FORCED)
  508.                 rate = 8000;
  509.  
  510.             if (( support & CAPS_EPCM ) == 0 )
  511.                 format = PLAY_UNSUPPORTED;
  512.             break;
  513.  
  514.         default:
  515.             printf( "\nMust be PCM8 or PCMMU format digitized audio.\n" );
  516.             DSReset();
  517.             fclose( fd );
  518.             exit( EXIT_FILE_ERR );
  519.             break;
  520.         }
  521.  
  522.     if ( format == PLAY_UNSUPPORTED )
  523.         {
  524.         printf( "\nAudio device or driver does not support requested function." );
  525.         exit( EXIT_NOT_SUPPORTED );
  526.         }
  527.  
  528.         /* Display format and rate. */
  529.  
  530.     printf(
  531.         "\nData Format:\t%s\nSample Rate:\t%u\n",
  532.         formatMsgs[ format],
  533.         rate
  534.         );
  535.     }
  536.  
  537.  
  538. /** PlayScales **************************************************************/
  539. /*                                                                          */
  540. /*  Play a 12 note scale through 8 octaves.  Allows the user to break the   */
  541. /*  sequence by pressing any key.                                           */
  542. /*                                                                          */
  543. /****************************************************************************/
  544.  
  545. static void PlayScales ( void )
  546.     {
  547.  
  548.     for ( octave = 0; octave < 8; octave++ )
  549.         {
  550.         for ( note = 0; note < 12; note++ )
  551.             {
  552.             printf( "Note: %s   Octave: %d\r", notes[ note], octave + 1 );
  553.             PlayNote( note, octave );
  554.             _Wait( 250 );
  555.             if ( kbhit())
  556.                 break;
  557.             }
  558.         if ( kbhit())
  559.             break;
  560.         }
  561.  
  562.         /* Get rid of any keystrokes and reset note index.  */
  563.  
  564.     while ( kbhit())
  565.         getch();
  566.     printf( "\n\n" );
  567.     note = 0;
  568.     octave = 0;
  569.     }
  570.  
  571.  
  572. /** PlayRandom **************************************************************/
  573. /*                                                                          */
  574. /*  Play a random note from one of the 8 octaves.                           */
  575. /*                                                                          */
  576. /****************************************************************************/
  577.  
  578. static void PlayRandom ( void )
  579.     {
  580.     static int noteDelay = 0;
  581.  
  582.     if (( ++noteDelay % 500) == 0 )
  583.         {
  584.         printf( "Note: %s   Octave: %d\n", notes[ note], octave + 1 );
  585.         PlayNote( note, octave );
  586.         note = (WORD)((++note + (*tTickCount ^ 0x55)) % 12);
  587.         octave = (WORD)((++octave + (*tTickCount ^ 0x55)) % 8);
  588.         }
  589.     }
  590.  
  591.  
  592. /** PlayManager *************************************************************/
  593. /*                                                                          */
  594. /*  Manage the background play operation.                                   */
  595. /*                                                                          */
  596. /****************************************************************************/
  597.  
  598. static int PlayManager ( FILE *fd )
  599.     {
  600.     int stopPlay, bufferIndex, status;
  601.  
  602.         /* Discard header and fill first two buffers.   */
  603.  
  604.     rewind( fd );
  605.     fread( buf0, 1, headerLen, fd );
  606.     fread( buf0, 1, sizeof(buf0), fd );
  607.     fread( buf1, 1, sizeof(buf1), fd );
  608.  
  609.         /* Start and manage appropriate background process. */
  610.  
  611.     status = StartPlay( format, rate, 1, length );
  612.     if ( status != E_OK )
  613.         return( status );
  614.  
  615.         /* Monitor background process.  */
  616.  
  617.     stopPlay = FALSE;
  618.     bufferIndex = 0;
  619.     for ( ;; )
  620.         {
  621.             /* Check for user intervention. */
  622.  
  623.         switch ( KeyPressed() )
  624.             {
  625.             case 'p':
  626.             case 'P':
  627.                 Pause();
  628.                 break;
  629.  
  630.             case 'r':
  631.             case 'R':
  632.                 Resume();
  633.                 break;
  634.  
  635.             case ESC_KEY:
  636.                 stopPlay = TRUE;
  637.                 break;
  638.  
  639.             default:
  640.                 break;
  641.             }
  642.  
  643.         status = DSGetStatus();
  644.         if ( stopPlay )
  645.             break;
  646.  
  647.             /* Skip rest if paused. */
  648.  
  649.         if (status == E_PAUSE)
  650.             continue;
  651.  
  652.         PlayRandom();
  653.  
  654.             /* Skip rest if buffers are still busy. */
  655.  
  656.         if ((status == E_BUF0) && bufferIndex == 0)
  657.             continue;
  658.         if ((status == E_BUF1) && bufferIndex == 1)
  659.             continue;
  660.  
  661.             /* Exit if error or end of action.  */
  662.  
  663.         if (( status != E_BUF0) && ( status != E_BUF1))
  664.             break;
  665.  
  666.             /* Fill empty buffer.   */
  667.  
  668.         if ( bufferIndex == 0)
  669.             {
  670.             status = fread( buf0, 1, sizeof(buf0), fd );
  671.             bufferIndex = 1;
  672.             }
  673.         else
  674.             {
  675.             status = fread( buf1, 1, sizeof(buf1), fd );
  676.             bufferIndex = 0;
  677.             }
  678.         }
  679.  
  680.         /* E_SYNTH just means that the synthesizer  */
  681.         /* is active, it is not an actual error.    */
  682.  
  683.     if ( status == E_SYNTH )
  684.         status = E_OK;
  685.  
  686.     return( status );
  687.     }
  688.  
  689.  
  690. /** ParseCommandLine ********************************************************/
  691. /*                                                                          */
  692. /*  Parse the command line (duh!).                                          */
  693. /*                                                                          */
  694. /****************************************************************************/
  695.  
  696. static int ParseCommandLine ( int argc, char *argv[] )
  697.     {
  698.     int annette, fileArg;
  699.  
  700.         /* Parse any parameters.    */
  701.  
  702.     rate = NOT_FORCED;
  703.     fileArg = -1;
  704.     for ( annette = 1; annette < argc; annette++ )
  705.         {
  706.             /* Parse switches.  */
  707.  
  708.         if (( *argv[ annette] == '/' ) || ( *argv[ annette] == '-' ))
  709.             {
  710.             argv[ annette]++;
  711.             switch ( *argv[ annette] )
  712.                 {
  713.                 case 'r':
  714.                 case 'R':
  715.                     argv[ annette]++;           // Get past switch character.
  716.                     if ( *argv[ annette] )
  717.                         rate = atoi( argv[ annette] );
  718.                     break;
  719.  
  720.                 default:
  721.                     Usage();
  722.                     break;
  723.                 }
  724.             }
  725.         else
  726.             fileArg = annette;
  727.         }
  728.  
  729.         /* Must specify a sound file.   */
  730.  
  731.     if ( fileArg == -1 )
  732.         Usage();
  733.  
  734.     return( fileArg );
  735.     }
  736.  
  737.  
  738. /** main ********************************************************************/
  739. /*                                                                          */
  740. /*  Play a sound file through DIGI driver.                                  */
  741. /*                                                                          */
  742. /****************************************************************************/
  743.  
  744. int main ( int argc, char *argv [] )
  745.     {
  746.     FILE    *fd;
  747.     int     fileArg, status;
  748.  
  749.     puts( "\nEmulator Interface Demonstration, v1.00" );
  750.     puts( "Copyright 1993, DSP Solutions, Inc.\n" );
  751.  
  752.     fileArg = ParseCommandLine( argc, argv );
  753.  
  754.         /* Start up appropriate drivers.    */
  755.  
  756.     if ( !DriverInstalled() )
  757.         {
  758.         printf( "Cannot find Audio Driver");
  759.         exit( EXIT_BAD_STATUS );
  760.         }
  761.  
  762.     signal( SIGINT, SIG_IGN );          // Ignore Ctrl-Break
  763.  
  764.         /* File housekeeping.   */
  765.  
  766.     fd = fopen( argv[ fileArg], "rb" );
  767.     if ( fd == NULL )
  768.         {
  769.         printf( "\nCould not open %s \n\n", argv[ fileArg] );
  770.         exit( EXIT_FILE_ERR );
  771.         }
  772.  
  773.         /* Get audio driver capabilities, then get audio    */
  774.         /* data information from file header.               */
  775.  
  776.     support = DSSetup();
  777.  
  778.     PlayScales();
  779.  
  780.         /* Find out what type of digitized audio file we have.  */
  781.  
  782.     ParseFileHeader( fd );
  783.  
  784.         /* Start and manage appropriate background process. */
  785.  
  786.     status = PlayManager( fd );
  787.  
  788.         /* Stop the synthesizer.    */
  789.  
  790.     Emulate( SYNTH_RESET, 0, 0 );
  791.  
  792.         /* Clean up and go home.    */
  793.  
  794.     DSReset();
  795.     fclose( fd );
  796.     DSExit( status );
  797.     }
  798.  
  799.  
  800.