home *** CD-ROM | disk | FTP | other *** search
/ Digispeech DS201A Drivers / dsapi_v120.zip / SOURCE / CALLBACK.C next >
C/C++ Source or Header  |  1993-08-13  |  10KB  |  351 lines

  1. /* CALLBACK.C */
  2. /****************************************************************************/
  3. /*                                                                          */
  4. /*  Abstract: DIGIAPI SDK Illustration of Driver Callback techniques.       */
  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  04-20-92   Lee Mulcahy     Initial version.
  13.  ---  07-20-93   Lee Mulcahy     Latest change.
  14.  
  15. */
  16.  
  17. #include <stdio.h>
  18. #include <signal.h>
  19. #include <io.h>
  20. #include <dos.h>
  21.  
  22.  
  23. /****************************************************************************/
  24. /*                                                                          */
  25. /*  Literals, etc.                                                          */
  26. /*                                                                          */
  27. /****************************************************************************/
  28.  
  29. #include "digi.h"
  30.  
  31. #define ESC_KEY     0x1B
  32.  
  33. #define BUFFER_CNT  8               // Number of audio buffers
  34. #define BUFFER_LEN  2048
  35.  
  36. typedef struct _buffer
  37.     {
  38.     int     status;
  39.     int     length;
  40.     BYTE    buf[ BUFFER_LEN];
  41.     } BUFFER;
  42.  
  43. typedef struct _bufInfo
  44.     {
  45.     int error;              // Buffer overrun/underrun error flag.
  46.     int bufferIndex;        // Buffer index, used by callback routine
  47.     int nextIndex;          // Buffer index, used by callback routine
  48.     } BUF_INFO;
  49.  
  50.     /* Structure used by a callback routine */
  51.  
  52. typedef struct _bufCtl
  53.     {
  54.     BYTE _far   *ptr;           // Must be first element of structure
  55.     WORD        length;         // Must be second element of structure
  56.  
  57.     } BUF_CTL;
  58.  
  59. static BUF_CTL far *bufCtl;
  60. static BUFFER buffer [BUFFER_CNT];
  61. static BUF_INFO bufInfo;
  62.  
  63.  
  64. /** KeyPressed **************************************************************/
  65. /*                                                                          */
  66. /*  If a key was pressed, return the key, else return FALSE.                */
  67. /*                                                                          */
  68. /****************************************************************************/
  69.  
  70. int KeyPressed ( void )
  71.     {
  72.     int key;
  73.  
  74.         /* Check for ESC key.   */
  75.  
  76.     key = 0;
  77.     if ( kbhit())
  78.         {
  79.         key = getch();
  80.  
  81.             /* If NULL, get another key and */
  82.             /* discard it (IBM PC oddity).  */
  83.  
  84.         if ( key == 0)
  85.             getch();
  86.         }
  87.  
  88.     return( key );
  89.     }
  90.  
  91.  
  92. /** OurCallback *************************************************************/
  93. /*                                                                          */
  94. /*  The foreground application's callback routine.                          */
  95. /*                                                                          */
  96. /****************************************************************************/
  97.  
  98. #pragma check_stack( off )      // No stack checking in callback function.
  99.  
  100. int far OurCallback ( void )
  101.     {
  102.  
  103.     _asm
  104.         {
  105.             ; Establish local DS by using the segment
  106.             ; of a known local variable.  Since this
  107.             ; is SMALL model, this should work without
  108.             ; any problems.
  109.  
  110.         mov        ax, seg buffer
  111.         mov     ds, ax
  112.  
  113.             ; ES:DI contains the address of the driver
  114.             ; buffer staructure array member that we
  115.             ; must load in this callback.
  116.  
  117.         mov     word ptr bufCtl + 2, ES    ; Segment address of bufCtl
  118.         mov     word ptr bufCtl + 0, DI    ; Offset  address of bufCtl
  119.         }
  120.  
  121.         /* Indicate that previous buffer is empty.  */
  122.  
  123.     buffer[ bufInfo.bufferIndex].status = 0;
  124.  
  125.         /* Advance buffer index, with wrap-around.  */
  126.  
  127.     if ( ++bufInfo.bufferIndex == BUFFER_CNT)
  128.         bufInfo.bufferIndex = 0;
  129.  
  130.         /* Compute index of next buffer to be sent to the driver.   */
  131.  
  132.     bufInfo.nextIndex = bufInfo.bufferIndex + 1;
  133.     if ( bufInfo.nextIndex == BUFFER_CNT)
  134.         bufInfo.nextIndex = 0;
  135.  
  136.         /* If next buffer is not yet filled with data, set error flag.  */
  137.  
  138.     if ( buffer[ bufInfo.nextIndex ].status == 0)
  139.         bufInfo.error = TRUE;
  140.  
  141.         /* Update driver buffer structure.  */
  142.  
  143.     bufCtl->ptr = (char far *)buffer[ bufInfo.nextIndex ].buf;
  144.     bufCtl->length  = buffer[ bufInfo.nextIndex ].length;
  145.  
  146.         /* Determine return value.  */
  147.  
  148.     if ( bufCtl->length == 0 )
  149.         {
  150.             /* This is the last callback, and all the data has  */
  151.             /* been played at this point.                       */
  152.  
  153.         return( 0 );
  154.         }
  155.  
  156.         /* 1 indicates that there is more audio data.   */
  157.  
  158.     return( 1 );
  159.     }
  160. #pragma check_stack     // Allow stack checking outside callback function
  161.  
  162.  
  163. /** main ********************************************************************/
  164. /*                                                                          */
  165. /*  The foreground application.                                             */
  166. /*                                                                          */
  167. /****************************************************************************/
  168.  
  169. int main ( int argc, char *argv[] )
  170.     {
  171.     FILE    *fin;
  172.     int     status, count, i, fillIndex, stopPlay;
  173.     DWORD   audioPosition;
  174.  
  175.     if ( argc < 2 )
  176.         {
  177.         printf( "Usage: CALLBACK <file name>\n");
  178.         exit(1);
  179.         }
  180.  
  181.     if ( !DriverInstalled() )
  182.         {
  183.         printf("Cannot find Audio driver\n" );
  184.         exit(1);
  185.         }
  186.  
  187.         /* Open input file. */
  188.  
  189.     if (( fin = fopen( argv[1], "rb")) == NULL )
  190.         {
  191.         printf( "Error: cannot open %s\n", argv[1]);
  192.         exit(1);
  193.         }
  194.  
  195.         /* IGNORE ^C */
  196.  
  197.     signal( SIGINT, SIG_IGN );
  198.  
  199.     status = DSReset();
  200.  
  201.         /* Fill buffers pool with audio data.   */
  202.  
  203.     memset( buffer, 0, sizeof( buffer) );
  204.     for ( i = 0; i < BUFFER_CNT; i++) 
  205.         {
  206.         buffer[ i].length = fread( buffer[ i].buf, 1, BUFFER_LEN, fin );
  207.         buffer[ i].status = TRUE;
  208.         }
  209.  
  210.         /* Init stuff.  */
  211.  
  212.     fillIndex = 0;
  213.     bufInfo.bufferIndex = 0;
  214.     bufInfo.error = FALSE;
  215.  
  216.         /* Send address of buffer #0 to the driver. */
  217.  
  218.     status = DSSetBuffer( 0, buffer[ 0].length, (char far *)buffer[ 0].buf );
  219.     if (status)
  220.         {
  221.         printf( "SetBuffer 0 failed: %04X\n", status );
  222.         exit(1);
  223.         }
  224.  
  225.         /* Send address of buffer #1 to the driver. */
  226.  
  227.     status = DSSetBuffer( 1, buffer[ 1].length, (char far *)buffer[ 1].buf );
  228.     if (status)
  229.         {
  230.         printf( "SetBuffer 1 failed: %04X\n", status);
  231.         exit(1);
  232.         }
  233.  
  234.         /* Send address of callback function to the driver. */
  235.  
  236.     DSSetCallback( &OurCallback );
  237.  
  238.  
  239.         /* Start appropriate background process.    */
  240.         /* We pass StartPlay a length of FFFFFFFF   */
  241.         /* so that it will play a loooonnng time.   */
  242.         /* The callback routine is responsible for  */
  243.         /* informing the driver when it must stop.  */
  244.  
  245.     status = StartPlay( DF_PCM8, 8000, 1, 0xFFFFFFFF );
  246.     if (status)
  247.         {
  248.         printf( "StartPlay failed: %04x\n", status);
  249.         DSReset();
  250.         fcloseall();
  251.         exit(1);
  252.         }
  253.  
  254.         /* Buffering and foreground process.    */
  255.  
  256.     stopPlay = FALSE;
  257.     for ( ;; )
  258.         {
  259.             /* Display buffer fill error, if detected.  */
  260.  
  261.         if ( bufInfo.error )
  262.             {
  263.             bufInfo.error = FALSE;
  264.             printf( "*** Buffer errors detected ***\n" );
  265.             }
  266.  
  267.             /* Check for user intervention. */
  268.  
  269.         switch ( KeyPressed() )
  270.             {
  271.             case 'p':
  272.             case 'P':
  273.                 status = DSPause();
  274.                 printf( "-- Pause ('R' resumes play) : " );
  275.                 break;
  276.  
  277.             case 'r':
  278.             case 'R':
  279.                 status = DSResume();
  280.                 printf( "-- Resume\n" );
  281.                 break;
  282.  
  283.             case ESC_KEY:
  284.                 stopPlay = TRUE;
  285.                 break;
  286.  
  287.             default:
  288.                 break;
  289.             }
  290.  
  291.             /* Wait till next buffer is ready.  */
  292.  
  293.         status = DSGetStatus();
  294.         if ( stopPlay )
  295.             break;
  296.  
  297.             /* Skip rest if paused. */
  298.  
  299.         if (status == E_PAUSE)
  300.             continue;
  301.  
  302.             /* Exit if error or end of action.  */
  303.  
  304.         if (( status != E_BUF0) && ( status != E_BUF1))
  305.             break;
  306.  
  307.             /* Display current file position.   */
  308.  
  309.         DSGetByteCount( &audioPosition );
  310.         printf( "Total bytes = %lu\r", audioPosition );
  311.  
  312.             /* Check if OK to fill next buffer. */
  313.  
  314.         if ( buffer[ fillIndex].status == 0)
  315.             {
  316.                 /* Fill buffer. */
  317.  
  318.             count = fread( buffer[ fillIndex].buf, 1, BUFFER_LEN, fin);
  319.  
  320.                 /* Update buffer data stats.    */
  321.  
  322.             buffer[ fillIndex].length = count;
  323.             buffer[ fillIndex].status = 1;
  324.  
  325.                 /* Tell user what we did.   */
  326.  
  327.             printf(
  328.                 "\nBuffer #%d filled with %d bytes\n",
  329.                 fillIndex,
  330.                 buffer[ fillIndex].length
  331.                 );
  332.  
  333.                 /* Cycle to next buffer.    */
  334.  
  335.             if ( ++fillIndex == BUFFER_CNT )
  336.                 fillIndex = 0;
  337.             }
  338.         }
  339.  
  340.         /* Display final stats. */
  341.  
  342.     DSGetByteCount( &audioPosition );
  343.     printf( "Total bytes = %lu\n", audioPosition );
  344.  
  345.     DSReset();
  346.     printf( "Last status: %04X\n", status );
  347.     fcloseall();
  348.     exit(0);
  349.     }
  350.  
  351.