/* ------------------------------------------------------------------------ */
/*  @@ Source Documentation                         *** C Version ***       */
/*                                                                          */
/*  TITLE : DEMOWDR.C                                                       */
/*                                                                          */
/*  DESCRIPTION :                                                           */
/*      This program demostrates how to perform Wave recording using        */
/*      the CTWDSK.DRV driver. The Wave recording is using the Disk         */
/*      Double Buffering method. The input sources are CD and MIC.          */
/*      You can specify the Wave input format i.e ALAW, MULAW or CT.        */
/*                                                                          */
/*      The program retrieves BLASTER environment for the Card settings     */
/*      and passes it to the driver.                                        */
/*                                                                          */
/*      Note that the program included the module LOADDRV.C to load         */
/*      the loadable CTWDSK.DRV into memory.                                */
/*                                                                          */
/*  Copyright (c) Creative Technology Ltd, 1993. All rights reserved.       */
/*                                                                          */
/* ------------------------------------------------------------------------ */

#include <dos.h>
#include <bios.h>
#include <stdio.h>
#include <fcntl.h>
#include <conio.h>
#include <dos.h>

#include "sbkwave.h"
#include "sbkmacro.h"
#include "sbkx.h"
#include "loaddrv.c"

#define TWO_KBYTES  2048l
#define PARA_ADJ    15l  /* 15 bytes for paragraph adjustment */

/*
## DMA_UNIT is unit of half embedded DMA in size of 2 kbytes .
## Change this value (from 1 - 16) if allocating own DMA buffer.
## This value effect the smoothy of sound output proportionally.
## Increase this value will be more efficient compare to DD_UNIT.
*/
#define DMA_UNIT    4
#define DMA_SIZE    ((DMA_UNIT * TWO_KBYTES * 2l) + PARA_ADJ)

/*
## DD_UNIT is unit of half double disk buffer in size of 2 kbytes.
## Change this value (from 2 - 32) when allocating dd buffer.
## It is recommended that this unit is at least double the DMA_UNIT.
## This value effect the smoothy of sound output proportionally.
*/
#define DD_UNIT     16
#define DD_SIZE     ((DD_UNIT * TWO_KBYTES * 2l) + PARA_ADJ)


/* Local function prototype */
int PrepareCTWDSKDrv(char * BlasterEnv) ;
int SetInputParam(void) ;
void RecordUntilStopped (WORD wIOHandle,char * szFilename) ;
void ShowError(void) ;

/* Global variable */
volatile WORD ct_wave_status ;      /* wave i/o status */
DWORD dwWaveFormat = 0 ;
char far * lpOrigin ;               /* original pointer of driver buffer */


main (int argc, char * argv[])
{
    char * BlasterEnv ;
    int  wIOHandle ;

    if (argc < 2)
    {
        printf("\nUsage : DEMOWDR wav_filename compress_method") ;
        printf("\nwhere compress_method can be ALAW, MULAW or CT") ;
        exit (0) ;
    }

    if (argc > 2)
    {
        strupr(argv[2]) ;

        if (!strcmp("CT",argv[2]))
            dwWaveFormat = WAVE_FORMAT_CREATIVE_ADPCM ;
        else if (!strcmp("ALAW",argv[2]))
            dwWaveFormat = WAVE_FORMAT_ALAW ;
        else if (!strcmp("MULAW",argv[2]))
            dwWaveFormat = WAVE_FORMAT_MULAW ;
        else
        {
            printf("\nUnknown '%s' compression method.",argv[2]) ;
            exit(1) ;
        }
    }

    printf ("\nRecord %s through double disk buffer.",argv[1]) ;

    /* Retrieve the BLASTER environment settings */
    if ((BlasterEnv = getenv("BLASTER")) != NULL)
    {
        if (!PrepareCTWDSKDrv(BlasterEnv))
        {
            if (!ctwdInit())
            {
                if ((wIOHandle = SetInputParam()) >= 0)
                    RecordUntilStopped((WORD)wIOHandle,argv[1]) ;

                ctwdTerminate() ;
            }
            else
                ShowError() ;
        }
    }
    else
        printf("BLASTER environment not set or incomplete or invalid.\n");

    return 0 ;
}


/* ------------------------------------------------------------------------ */
/*  @@ Usage                                                                */
/*                                                                          */
/*  PrepareCTWDSKDrv(char * BlasterEnv)                                     */
/*                                                                          */
/*  Description :                                                           */
/*      Load and endorse CTWDSK.DRV.                                        */
/*                                                                          */
/*  Entry :                                                                 */
/*      BlasterEnv - pointer to the BLASTER environment.                    */
/*                                                                          */
/*  Exit :                                                                  */
/*      zero if sucessful, non-zero otherwise.                              */
/*                                                                          */
/* ------------------------------------------------------------------------ */

int PrepareCTWDSKDrv(char * BlasterEnv)
{
    DWORD   dwVersion = 0 ;


    if ((CTwdskDrv = sbkLoadDriver("CTWDSK.DRV",UNUSED,
                        (char far **)&lpOrigin)) != NULL)
    {
        /* Retrieves CTWDSK.DRV version */
        if (!ctwdGetParam(CTWAV_DRIVERVERSION,(DWORD far *)&dwVersion))

        {
            if ((dwVersion & 0xffff) >= 0x0305)
            {
                /* Passes BLASTER environment settings to driver */
                if (!ctwdGetEnvSettings((const char far *)BlasterEnv))
                    return(0) ;
                else
                    printf("\nDriver : BLASTER environment is not valid");
            }
            else
            {
                printf("\nInvalid CTWDSK.DRV - ") ;
                printf("I need CTWDSK.DRV version 3.05 or higher.\n") ;
            }
        }
        else
            printf("\nDriver : Unrecognized CTWDSK.DRV\n");
    }
    return(1) ;
}


/* ------------------------------------------------------------------------ */
/*  @@ Usage                                                                */
/*                                                                          */
/*   SetInputParam (void)                                                   */
/*                                                                          */
/*   DESCRIPTION:                                                           */
/*       Set the necessary input parameters.                                */
/*                                                                          */
/*   ENTRY:                                                                 */
/*       none.                                                              */
/*                                                                          */
/*   EXIT:                                                                  */
/*       i/o wave handle if successful otherwise return -1.                 */
/*                                                                          */
/* ------------------------------------------------------------------------ */

int SetInputParam(void)
{
    WORD   wIOHandle ;
    DWORD  dwValue ;
    BYTE   far * lpDiskBuf, far * lpDmaBuf ;
    int    retVal;


    retVal = -1 ;

    /* Allocate double disk buffer */
    if ((lpDiskBuf = (BYTE far *)sbkAllocMem((DWORD)DD_SIZE)) == NULL)
    {
        printf("\nDOS : Error allocating Double Disk buffer.") ;
        return (retVal) ;
    }

    /* Allocate two DMA buffer. The 2nd buffer is used when
      the 1st buffer crosses the 64k boundary */
    if ((lpDmaBuf = (BYTE far *)sbkAllocMem((DWORD)(DMA_SIZE * 2))) == NULL)
    {
        printf("\nDOS : Error allocating DMA buffer.") ;
        return (retVal) ;
    }

    if (!ctwdGetParam(CTWAV_IOHANDLES,(DWORD far *)&dwValue))
    {
        if (dwValue)
        {   /* wave i/o handle */
            wIOHandle = (WORD)(dwValue - 1) ;

            if (!ctwdSetDiskBuffer(wIOHandle,lpDiskBuf,(WORD)DD_UNIT))
            {
                if (!ctwdSetIOParam(wIOHandle,CTWAV_IO_LPSTATUSWORD,
                                    (DWORD)(WORD far *)&ct_wave_status))
                {
                    /* convert to 32-bit linear address */
                    dwValue = (DWORD)((DWORD)FPSEG(lpDmaBuf) << 4)
                                       + FPOFF(lpDmaBuf) ;

                    /* Set up DMA buffer. If failed, the DMA buffer
                       may have crossed the 64 k boundary, thus use
                       the 2nd Dma buffer */
                    if (ctwdSetDMABuffer(wIOHandle,dwValue,(WORD)DMA_UNIT))
                    {
                        dwValue += (DWORD)DMA_SIZE ;

                        if (ctwdSetDMABuffer(wIOHandle,dwValue,(WORD)DMA_UNIT))
                            printf ("\nDriver : Error setting DMA buffer.");
                        else
                            retVal = wIOHandle ;
                    }
                    else
                        retVal = wIOHandle ;

                    /* Set stereo mode input */
                    ctwdSetIOParam(wIOHandle,CTWAV_IN_NCHANNELS,2);

                    /* Set CD and MIC as input source */
                    ctwdSetIOParam(wIOHandle,CTWAV_IN_LEFTINPUTS,
                                        MIXERSWI_CD_L | MIXERSWI_MIC) ;
                    ctwdSetIOParam(wIOHandle,CTWAV_IN_RIGHTINPUTS,
                                        MIXERSWI_CD_R | MIXERSWI_MIC) ;

                    ctwdSetIOParam(wIOHandle,CTWAV_IN_SAMPLESPERSEC,22050);

                    if (dwWaveFormat)
                        ctwdSetIOParam(wIOHandle,CTWAV_IN_FORMAT,dwWaveFormat);

                    /* By defaults : sampling rate  : 11025 Hz
                                     Wave format    : 8 bits unsigned PCM
                                     bit per sample : 8 bits  */

                }
                else
                    printf("\nError setting ct_wave_status.") ;
            }
            else
                printf("\nDriver : Error setting Double Disk buffer.") ;
        }
        else
            printf("\nI/O wave handle unavailable.") ;
    }
    else
        printf("\nError retrieving I/O wave handles.") ;

    return (retVal) ;

}


/* ------------------------------------------------------------------------ */
/*  @@ Usage                                                                */
/*                                                                          */
/*   RecordUntilStopped (WORD wIOHandle, char * szFilename)                 */
/*                                                                          */
/*   DESCRIPTION:                                                           */
/*       Starts Wave recording. Press ESC key to terminate the recording.   */
/*                                                                          */
/*   ENTRY:                                                                 */
/*       wIOHandle  - i/o wave handle.                                      */
/*       szFilename - file name to store the input                          */
/*                                                                          */
/*   EXIT:                                                                  */
/*       None.                                                              */
/*                                                                          */
/* ------------------------------------------------------------------------ */

void RecordUntilStopped (WORD wIOHandle,char * szFilename)
{
    WORD wKey ;
    int  iFileHandle ;


    /* create and record a Wave file */
    if ((iFileHandle = sbkDosCreate(szFilename)) != -1)
    {
        ctwdSetSpeaker(0) ;

        if (!ctwdInput(wIOHandle,(WORD)iFileHandle))
        {
            printf ("\nStart recording....Press [ESC] to stop...") ;

            /* Polls for hot key while recording Wave file */
            while (ct_wave_status)
            {
                /* if (sbkBiosKeybrd(KEYBRD_READY)) */
                if (kbhit())
                {
                    /* wKey = (WORD)(sbkBiosKeybrd((WORD)KEYBRD_READ) & 0xff) ; */
                    wKey = getch() & 0xff ;

                    /* check for ESC key */
                    if ( wKey == 0x1b )
                        ctwdStop(wIOHandle) ;
                }
            }
            sbkDosClose(iFileHandle) ;
            printf("\nWave recording end.") ;
        }
        else
            ShowError() ;
    }
    else
        printf ("Create %s file error\n", szFilename ) ;

}


/* ------------------------------------------------------------------------ */
/*  @@ Usage                                                                */
/*                                                                          */
/*   ShowError (void)                                                       */
/*                                                                          */
/*   DESCRIPTION:                                                           */
/*       Display error occurred during the process of wave i/o.             */
/*                                                                          */
/*   ENTRY:                                                                 */
/*       None.                                                              */
/*                                                                          */
/*   EXIT:                                                                  */
/*       None.                                                              */
/*                                                                          */
/* ------------------------------------------------------------------------ */

void ShowError (void)
{
    int     Err ;


    /* Show the driver error and the DOS extended error code */
    Err = ctwdGetDrvError() ;

    printf("\nDriver error = %2d", Err) ;

    Err = ctwdGetExtError();
    if ( Err != 0 )
        printf ("\nDOS error = %2d\n", Err) ;
}
/* End of file */
