/* ------------------------------------------------------------------------ */
/*  @@ Source Documentation                         *** C Version ***       */
/*                                                                          */
/*  TITLE  : DEMOPAN.C                                                      */
/*                                                                          */
/*  DESCRIPTION :                                                           */
/*      This program demostrates how to use the AUXDRV.DRV driver to        */
/*      perform panning effect and volume control on the playing voice      */
/*      file.                                                               */
/*                                                                          */
/*      Note that the BLASTER environment has to be set before executing    */
/*      this program.                                                       */
/*                                                                          */
/*  Copyright (c) Creative Technology Ltd, 1993. All rights reserved.       */
/*                                                                          */
/* ------------------------------------------------------------------------ */

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

#include "sbkvoice.h"
#include "sbkaux.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.
## Since this program use default DMA, increse DMA_UNIT cause no effect.
 */
#define DMA_UNIT    1
#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) to allocate 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     32
#define DD_SIZE     ((DD_UNIT * TWO_KBYTES * 2l) + PARA_ADJ)


/* Local functions */
int PrepareCTVDSKDrv (char * BlasterEnv) ;
int PrepareCTAUXDrv (char * BlasterEnv) ;
void SoundEffect (WORD wIOHandle) ;
void WaitEffectEnd (WORD wIOHandle) ;
int OutputVoice (int Handle) ;
void ShowError (void) ;

/* Global variable */
WORD  volatile ct_voice_status ;        /* Voice output status */
WORD  volatile wPanStatus ;             /* Panning effect status */
char  far * lpVdskOrigin ;              /* Original buffer for CTVDSK.DRV */
char  far * lpAuxOrigin ;               /* Original buffer for AUXDRV.DRV */

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


    printf("\nOutput voice with panning effect.") ;

    if (argc < 2)
    {
        printf("\nUsage : DEMOPAN voc_filename\n") ;
        exit (0) ;
    }

    /* Retrieve the BLASTER environment settings */
    if ((BlasterEnv = getenv("BLASTER")) != NULL)
    {
        /* Loads CTVDSK.DRV into memory */
        if (!PrepareCTVDSKDrv(BlasterEnv))
        {
            /* Loads AUXDRV.DRV into memory */
            if (!PrepareCTAUXDrv(BlasterEnv))
            {
                /* Initialises CTVDSK.DRV */
                if (!ctvdInit())
                {
                    /* Open voice file */
                    if ((iFileHandle = sbkDosOpen(argv[1])) != -1)
                    {
                        /* Output voice file */
                        wIOHandle = (WORD)OutputVoice(iFileHandle) ;
                        if ((int)wIOHandle != -1)
                        {
                            /* Adds on sound effect */
                            SoundEffect(wIOHandle) ;
                        }
                        sbkDosClose(iFileHandle) ;
                    }
                    /* Terminates CTVDSK.DRV */
                    ctvdTerminate() ;
                }
                else
                    ShowError() ;
            }
        }
    }
    else
        printf("BLASTER environment not set.\n");

    return 0 ;
}


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

int PrepareCTVDSKDrv(char * BlasterEnv)
{
    DWORD   dwVersion ;

    /* Load driver with embedded buffer */
    if ((ctvdsk_drv = sbkLoadDriver("CTVDSK.DRV",UNUSED,
                            (char far **)&lpVdskOrigin)) != NULL)
    {
        /* Retrieves CTVDSK.DRV version */
        if (!ctvdGetParam(CTVOC_DRIVERVERSION,(DWORD far *)&dwVersion))
        {
            if ((dwVersion & 0xffff) >= 0x0304)
            {
                /* Passes BLASTER environment settings to driver */
                if (!ctvdGetEnvSettings((char far *)BlasterEnv))
                    return(0) ;
                else
                    printf("\nBLASTER environment is not valid");
            }
            else
            {
                printf("\nInvalid CTVDSK.DRV - ") ;
                printf("I need CTVDSK.DRV version 3.04 or higher.\n") ;
            }
        }
        else
            printf("\nUnrecognized CTVDSK.DRV\n");
    }
    return(1) ;
}

/****************************************************************************/
/*  @@ Usage                                                                */
/*                                                                          */
/*  PrepareCTAUXDrv(char * BlasterEnv)                                      */
/*                                                                          */
/*  Description :                                                           */
/*      Load and endorse AUXDRV.DRV for it to be effective.                 */
/*                                                                          */
/*  Entry :                                                                 */
/*      BlasterEnv - pointer of the BLASTER environment string.             */
/*                                                                          */
/*  Exit :                                                                  */
/*      zero if sucessful, non-zero otherwise.                              */
/*                                                                          */
/****************************************************************************/

int PrepareCTAUXDrv(char * BlasterEnv)
{
    if ((CTAuxDrv = sbkLoadDriver("AUXDRV.DRV",UNUSED,
                        (char far **)&lpAuxOrigin)) != NULL)
    {
        /* Retrieves AUXDRV.DRV version */
        if (ctadGetDrvVer() >= 0x0303)
        {
            /* Passes BLASTER environment settings to the driver */
            if (!ctadGetEnvSettings((char far *)BlasterEnv))
                return(0) ;
            else
                printf("\nBLASTER environment is not valid");
        }
        else
        {
            printf("\nInvalid AUXDRV.DRV - ") ;
            printf("I need AUXDRV.DRV version 3.03 or higher.\n") ;
        }
    }
    return(1) ;
}


/* ------------------------------------------------------------------------ */
/*  @@ Usage                                                                */
/*                                                                          */
/*   SoundEffect (WORD wIOHandle)                                           */
/*                                                                          */
/*   DESCRIPTION:                                                           */
/*       Add panning effect on the playback digitized sound.                */
/*                                                                          */
/*   ENTRY:                                                                 */
/*       wIOHandle - i/o voice handle.                                      */
/*                                                                          */
/*   EXIT:                                                                  */
/*       None                                                               */
/*                                                                          */
/* ------------------------------------------------------------------------ */

void SoundEffect (WORD wIOHandle)
{
    unsigned    wPrevVol;


    ctadInit() ;

    /* preserve the previous voice volume settings */
    wPrevVol = ctadGetVolume(MIXERVOL_VOICE) ;

    /* set voice left/right volume to 0 */
    ctadSetVolume(MIXERVOL_VOICE, 0x0000) ;

    /* set address of the pan status */
    ctadSetPanStAddx((WORD far *)&wPanStatus) ;

    /* Setup digitized sound for panning in mode 1  */
    /* repeat for 3 times                           */
    ctadPan(MIXERVOL_VOICE, 50, 200, 5000, 1, 2) ;
    ctadStartCtrl() ;
    WaitEffectEnd(wIOHandle) ;

    /* set voice left/right volume back to previous status */
    ctadSetVolume((WORD)MIXERVOL_VOICE, (WORD)wPrevVol) ;

    ctadTerminate() ;
    ctvdSetSpeaker(0) ;

}


/* ------------------------------------------------------------------------ */
/*  @@ Usage                                                                */
/*                                                                          */
/*   WaitEffectEnd (WORD wIOHandle)                                         */
/*                                                                          */
/*   DESCRIPTION:                                                           */
/*       Control Panning effect of the digitized sound.                     */
/*                                                                          */
/*   ENTRY:                                                                 */
/*       wIOHandle - i/o voice handle.                                      */
/*                                                                          */
/*   EXIT:                                                                  */
/*       None                                                               */
/*                                                                          */
/* ------------------------------------------------------------------------ */

void WaitEffectEnd (WORD wIOHandle)
{
    int pause = 0 ;


    printf("\nPanning effect....\n\n");
    printf("\t[Esc] - to stop\n");
    printf("\t[P  ] - to pause\n");
    printf("\t[C  ] - to continue\n");

    /* End of sound effect process ? */
    while(wPanStatus || ct_voice_status)
    {
        /* Stop effect if no voice process */
        if ( !ct_voice_status )
            ctadStopCtrl();

        if (sbkBiosKeybrd(KEYBRD_READY))
        {
            switch (sbkBiosKeybrd(KEYBRD_READ) & 0xff)
            {
                case 0x1b :
                    ctadStopCtrl() ;
                    ctvdStop(wIOHandle) ;
                    break ;

                case 'P' :
                case 'p' :
                    if (pause == 0 )
                    {
                        printf("\nEffect pause...") ;
                        ctadPauseCtrl() ;
                        ctvdPause(wIOHandle) ;
                        pause = 1 ;
                    }
                    break ;


                case 'C' :
                case 'c' :
                    if (pause != 0 )
                    {
                        printf("\nEffect continue...") ;
                        ctadStartCtrl() ;
                        ctvdContinue(wIOHandle) ;
                        pause = 0 ;
                    }
                    break ;

            }
        }
    }
    printf("\nEnd of panning effect...\n");
}


/* ------------------------------------------------------------------------ */
/*  @@ Usage                                                                */
/*                                                                          */
/*   OutputVoice (int iFileHandle)                                          */
/*                                                                          */
/*   DESCRIPTION:                                                           */
/*       Output voice with the file handle specified.                       */
/*                                                                          */
/*   ENTRY:                                                                 */
/*       iFileHandle : handle of a file to be outputted.                    */
/*                                                                          */
/*   EXIT:                                                                  */
/*       i/o voice handle if successful, else return -1.                    */
/*                                                                          */
/* ------------------------------------------------------------------------ */

int OutputVoice (int iFileHandle)
{
    WORD    wIOHandle ;
    DWORD   dwParam ;
    BYTE    far * lpDiskBuf ;


    /* Get voice IO handles supported by the driver */
    if(!ctvdGetParam(CTVOC_IOHANDLES,(DWORD far *)&dwParam))
    {
        if (dwParam)
        {
            wIOHandle = (WORD)(dwParam - 1) ;

            if ((lpDiskBuf = (BYTE far *)sbkAllocMem((DWORD)DD_SIZE)) != NULL)
            {
                /* set double disk buffer */
                if (!ctvdSetDiskBuffer(wIOHandle,lpDiskBuf,(WORD)DD_UNIT))
                {
                    /* Set voice output status address */
                    if (!ctvdSetIOParam(wIOHandle,CTVOC_IO_LPSTATUSWORD,
                                    (DWORD)(WORD far *)&ct_voice_status))
                    {
                        /* turn on speaker */
                        ctvdSetSpeaker(1) ;

                        /* Output voice */
                        if (!ctvdOutput(wIOHandle,(WORD)iFileHandle))
                            return (wIOHandle) ;
                        else
                            ShowError () ;
                    }
                    else
                        printf("\nError setting ct_voice_status.");
                }
                else
                    printf("\nDriver : Error setting double disk buffer.") ;
            }
            else
                printf("\nDos : Error allocating double disk buffer.") ;
        }
        else
            printf("\nI/O voice handle not available.") ;
    }
    else
        printf("\nError geting Voice IO Handles.") ;

    return (-1);

}


/* ------------------------------------------------------------------------ */
/*  @@ Usage                                                                */
/*                                                                          */
/*   ShowError (void)                                                       */
/*                                                                          */
/*   DESCRIPTION:                                                           */
/*       Display error occurred during the process of voice I/O.            */
/*                                                                          */
/*   ENTRY:                                                                 */
/*       None.                                                              */
/*                                                                          */
/*   EXIT:                                                                  */
/*       None.                                                              */
/*                                                                          */
/* ------------------------------------------------------------------------ */

void ShowError (void)
{
    int     Err ;


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

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

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