home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Digispeech DS201A Drivers
/
dsapi_v120.zip
/
SOURCE
/
CALLBACK.C
next >
Wrap
C/C++ Source or Header
|
1993-08-13
|
10KB
|
351 lines
/* CALLBACK.C */
/****************************************************************************/
/* */
/* Abstract: DIGIAPI SDK Illustration of Driver Callback techniques. */
/* */
/* Language: Microsoft C, v6.00a Model: LARGE Machine type: IBM PC */
/* */
/****************************************************************************/
/*
REV DATE AUTHOR DESCRIPTION
1.0 04-20-92 Lee Mulcahy Initial version.
--- 07-20-93 Lee Mulcahy Latest change.
*/
#include <stdio.h>
#include <signal.h>
#include <io.h>
#include <dos.h>
/****************************************************************************/
/* */
/* Literals, etc. */
/* */
/****************************************************************************/
#include "digi.h"
#define ESC_KEY 0x1B
#define BUFFER_CNT 8 // Number of audio buffers
#define BUFFER_LEN 2048
typedef struct _buffer
{
int status;
int length;
BYTE buf[ BUFFER_LEN];
} BUFFER;
typedef struct _bufInfo
{
int error; // Buffer overrun/underrun error flag.
int bufferIndex; // Buffer index, used by callback routine
int nextIndex; // Buffer index, used by callback routine
} BUF_INFO;
/* Structure used by a callback routine */
typedef struct _bufCtl
{
BYTE _far *ptr; // Must be first element of structure
WORD length; // Must be second element of structure
} BUF_CTL;
static BUF_CTL far *bufCtl;
static BUFFER buffer [BUFFER_CNT];
static BUF_INFO bufInfo;
/** KeyPressed **************************************************************/
/* */
/* If a key was pressed, return the key, else return FALSE. */
/* */
/****************************************************************************/
int KeyPressed ( void )
{
int key;
/* Check for ESC key. */
key = 0;
if ( kbhit())
{
key = getch();
/* If NULL, get another key and */
/* discard it (IBM PC oddity). */
if ( key == 0)
getch();
}
return( key );
}
/** OurCallback *************************************************************/
/* */
/* The foreground application's callback routine. */
/* */
/****************************************************************************/
#pragma check_stack( off ) // No stack checking in callback function.
int far OurCallback ( void )
{
_asm
{
; Establish local DS by using the segment
; of a known local variable. Since this
; is SMALL model, this should work without
; any problems.
mov ax, seg buffer
mov ds, ax
; ES:DI contains the address of the driver
; buffer staructure array member that we
; must load in this callback.
mov word ptr bufCtl + 2, ES ; Segment address of bufCtl
mov word ptr bufCtl + 0, DI ; Offset address of bufCtl
}
/* Indicate that previous buffer is empty. */
buffer[ bufInfo.bufferIndex].status = 0;
/* Advance buffer index, with wrap-around. */
if ( ++bufInfo.bufferIndex == BUFFER_CNT)
bufInfo.bufferIndex = 0;
/* Compute index of next buffer to be sent to the driver. */
bufInfo.nextIndex = bufInfo.bufferIndex + 1;
if ( bufInfo.nextIndex == BUFFER_CNT)
bufInfo.nextIndex = 0;
/* If next buffer is not yet filled with data, set error flag. */
if ( buffer[ bufInfo.nextIndex ].status == 0)
bufInfo.error = TRUE;
/* Update driver buffer structure. */
bufCtl->ptr = (char far *)buffer[ bufInfo.nextIndex ].buf;
bufCtl->length = buffer[ bufInfo.nextIndex ].length;
/* Determine return value. */
if ( bufCtl->length == 0 )
{
/* This is the last callback, and all the data has */
/* been played at this point. */
return( 0 );
}
/* 1 indicates that there is more audio data. */
return( 1 );
}
#pragma check_stack // Allow stack checking outside callback function
/** main ********************************************************************/
/* */
/* The foreground application. */
/* */
/****************************************************************************/
int main ( int argc, char *argv[] )
{
FILE *fin;
int status, count, i, fillIndex, stopPlay;
DWORD audioPosition;
if ( argc < 2 )
{
printf( "Usage: CALLBACK <file name>\n");
exit(1);
}
if ( !DriverInstalled() )
{
printf("Cannot find Audio driver\n" );
exit(1);
}
/* Open input file. */
if (( fin = fopen( argv[1], "rb")) == NULL )
{
printf( "Error: cannot open %s\n", argv[1]);
exit(1);
}
/* IGNORE ^C */
signal( SIGINT, SIG_IGN );
status = DSReset();
/* Fill buffers pool with audio data. */
memset( buffer, 0, sizeof( buffer) );
for ( i = 0; i < BUFFER_CNT; i++)
{
buffer[ i].length = fread( buffer[ i].buf, 1, BUFFER_LEN, fin );
buffer[ i].status = TRUE;
}
/* Init stuff. */
fillIndex = 0;
bufInfo.bufferIndex = 0;
bufInfo.error = FALSE;
/* Send address of buffer #0 to the driver. */
status = DSSetBuffer( 0, buffer[ 0].length, (char far *)buffer[ 0].buf );
if (status)
{
printf( "SetBuffer 0 failed: %04X\n", status );
exit(1);
}
/* Send address of buffer #1 to the driver. */
status = DSSetBuffer( 1, buffer[ 1].length, (char far *)buffer[ 1].buf );
if (status)
{
printf( "SetBuffer 1 failed: %04X\n", status);
exit(1);
}
/* Send address of callback function to the driver. */
DSSetCallback( &OurCallback );
/* Start appropriate background process. */
/* We pass StartPlay a length of FFFFFFFF */
/* so that it will play a loooonnng time. */
/* The callback routine is responsible for */
/* informing the driver when it must stop. */
status = StartPlay( DF_PCM8, 8000, 1, 0xFFFFFFFF );
if (status)
{
printf( "StartPlay failed: %04x\n", status);
DSReset();
fcloseall();
exit(1);
}
/* Buffering and foreground process. */
stopPlay = FALSE;
for ( ;; )
{
/* Display buffer fill error, if detected. */
if ( bufInfo.error )
{
bufInfo.error = FALSE;
printf( "*** Buffer errors detected ***\n" );
}
/* Check for user intervention. */
switch ( KeyPressed() )
{
case 'p':
case 'P':
status = DSPause();
printf( "-- Pause ('R' resumes play) : " );
break;
case 'r':
case 'R':
status = DSResume();
printf( "-- Resume\n" );
break;
case ESC_KEY:
stopPlay = TRUE;
break;
default:
break;
}
/* Wait till next buffer is ready. */
status = DSGetStatus();
if ( stopPlay )
break;
/* Skip rest if paused. */
if (status == E_PAUSE)
continue;
/* Exit if error or end of action. */
if (( status != E_BUF0) && ( status != E_BUF1))
break;
/* Display current file position. */
DSGetByteCount( &audioPosition );
printf( "Total bytes = %lu\r", audioPosition );
/* Check if OK to fill next buffer. */
if ( buffer[ fillIndex].status == 0)
{
/* Fill buffer. */
count = fread( buffer[ fillIndex].buf, 1, BUFFER_LEN, fin);
/* Update buffer data stats. */
buffer[ fillIndex].length = count;
buffer[ fillIndex].status = 1;
/* Tell user what we did. */
printf(
"\nBuffer #%d filled with %d bytes\n",
fillIndex,
buffer[ fillIndex].length
);
/* Cycle to next buffer. */
if ( ++fillIndex == BUFFER_CNT )
fillIndex = 0;
}
}
/* Display final stats. */
DSGetByteCount( &audioPosition );
printf( "Total bytes = %lu\n", audioPosition );
DSReset();
printf( "Last status: %04X\n", status );
fcloseall();
exit(0);
}