'' ------------------------------------------------------------------------ ''
''  @@ Source Documentation                     *** Basic Version ***       ''
''                                                                          ''
''  TITLE : DEMOPAN.BAS                                                     ''
''                                                                          ''
''  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.                                                        ''
''                                                                          ''
''  Note :                                                                  ''
''     Use switch /Fs for Microsoft Basic PDS 7.1 compiler.                 ''
''                                                                          ''
''  Copyright (c) Creative Technology Ltd, 1993. All rights reserved.       ''
''                                                                          ''
'' ------------------------------------------------------------------------ ''

'$INCLUDE: 'SBKVOICE.BI'
'$INCLUDE: 'SBKAUX.BI'
'$INCLUDE: 'SBKX.BI'

DECLARE FUNCTION PrepareCTVDSKDrv%(BlasterAddx AS LONG)
DECLARE FUNCTION PrepareCTAUXDrv%(BlasterAddx AS LONG)
DECLARE SUB SoundEffect(wIOHandle%)
DECLARE SUB WaitEffectEnd(wIOHandle%)
DECLARE FUNCTION OutputVoice%(iHandle AS INTEGER)
DECLARE SUB ShowError()

CONST DRIVERxSIZE1 = 10240&
CONST DRIVERxSIZE2 = 51200&

CONST TWOxKBYTES   = 2048&
CONST PARAxADJ     = 15&       '* 15 bytes for paragraph adjustment *'

'*
'## DMAxUNIT 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 DDxUNIT.
'## Since this program use default DMA, increse DMAxUNIT cause no effect.
'*
CONST DMAxUNIT     = 1
CONST DMAxSIZE     = ((DMAxUNIT * TWOxKBYTES * 2&) + PARAxADJ)

'*
'## DDxUNIT 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 DMAxUNIT.
'## This value effect the smoothy of sound output proportionally.
'*
CONST DDxUNIT      = 32
CONST DDxSIZE      = ((DDxUNIT * TWOxKBYTES * 2&) + PARAxADJ)


REM $DYNAMIC
CLEAR

' Set memory buffers for AUXDRV.DRV and CTVDSK.DRV and
' double disk buffer respectively
DIMMY = SETMEM(-DRIVERxSIZE1)
DUMMY = SETMEM(-DRIVERxSIZE2)
DUMMY = SETMEM(-DDxSIZE)

    DIM wIOHandle AS INTEGER            ' Voice I/O handle
    DIM SHARED CtVoiceStatus AS INTEGER ' Voice output status
    DIM SHARED wPanStatus AS INTEGER    ' Panning effect status
    DIM BlasterEnv AS STRING
    DIM iHandle AS INTEGER
    DIM dwValue AS LONG
    DIM NumArg AS INTEGER
    DIM szCmdArg(1 TO 1) AS STRING

    PRINT "Output voice with panning effect."

    ' get command line argument
    CALL sbkGetCmdLine(NumArg,szCmdArg(),1)
    IF NumArg < 1 THEN
        PRINT "Usage : DEMOPAN voc_filename"
        SYSTEM
    END IF

    ' Retrieve the BLASTER environment settings
    BlasterEnv = ENVIRON$("BLASTER")
    IF BlasterEnv <> "" THEN

        ' Convert BLASTER string to null terminated string and
        ' return the far address of the BLASTER string
        dwValue = sbkMakeAsciizString&(BlasterEnv)

        ' Loads CTVDSK.DRV into memory
        IF PrepareCTVDSKDrv%(dwValue) <> 0 THEN

            ' Loads AUXDRV.DRV into memory
            IF PrepareCTAUXdrv%(dwValue) <> 0 THEN

                ' Initialises CTVDSK.DRV
                IF ctvdInit% = 0 THEN

                    ' Open voice file
                    dwValue = sbkMakeAsciizString&(szCmdArg(1))
                    iHandle = sbkDosOpen%(dwValue)
                    IF iHandle <> -1 THEN

                        ' Output voice file
                        wIOHandle = OutputVoice%(iHandle)
                        IF wIOHandle >= 0 THEN

                            ' Adds on sound effect
                            CALL SoundEffect(wIOHandle)
                        END IF

                        CALL sbkDosClose(iHandle)
                    ELSE
                        PRINT "Error open ";sbkMakeBasicString$(dwValue)
                    END IF

                    ' Terminates CTVDSK.DRV
                    CALL ctvdTerminate
                ELSE
                    CALL ShowError
                END IF
            END IF
        END IF
    ELSE
        PRINT "BLASTER environment not set."
    END IF

' Returns memory to system
DUMMY = SETMEM(DDxSIZE)
DUMMY = SETMEM(DRIVERxSIZE2)
DUMMY = SETMEM(DRIVERxSIZE1)

END


'---------------------------------------------------------------------------'
'   @@ Usage                                                                '
'                                                                           '
'   FUNCTION PrepareCTVDSKDrv%(BlasterAddx AS LONG)                         '
'                                                                           '
'   Description :                                                           '
'      Load and endorse CTVDSK.DRV driver.                                  '
'                                                                           '
'   Entry :                                                                 '
'      BlasterAddx - Far address of the BLASTER setting.                    '
'                                                                           '
'   Exit :                                                                  '
'      segment of the driver if sucessful else return 0.                    '
'                                                                           '
'---------------------------------------------------------------------------'

FUNCTION PrepareCTVDSKDrv%(BlasterAddx AS LONG)

    DIM dwVersion AS LONG
    DIM ctvdskdrv AS INTEGER

    ' load driver with embedded DMA buffer
    ctvdskdrv = sbkLoadDriver%("CTVDSK.DRV",UNUSED)
    IF ctvdskdrv <> 0 THEN

        ' Initialises the CTVDSK.DRV driver entry point
        CALL ctvdSetDriverEntry((ctvdskdrv))

        ' Retrieves CTVDSK.DRV version
        IF ctvdGetParam%(CTVOCxDRIVERVERSION,dwVersion) = 0 THEN
            IF dwVersion >= &H0304 THEN

                ' Passes BLASTER environment settings to driver
                IF ctvdGetEnvSettings%((BlasterAddx)) = 0 THEN
                    PrepareCTVDSKDrv% = ctvdskdrv
                    EXIT FUNCTION
                ELSE
                    PRINT "BLASTER environment is not valid"
                END IF
            ELSE
                PRINT "Invalid CTVDSK.DRV - ";
                PRINT "I need CTVDSK.DRV version 3.04 or higher."
            END IF
        ELSE
            PRINT "Unrecognized CTVDSK.DRV."
        END IF

        CALL sbkFreeMem(ctvdskdrv)
    ELSE
        PRINT "Error loading CTVDSK.DRV or CTVDSK.DRV not found."
    END IF

    PrepareCTVDSKDrv% = 0

END FUNCTION


'---------------------------------------------------------------------------'
'   @@ Usage                                                                '
'                                                                           '
'   FUNCTION PrepareCTAUXDrv%(BlasterAddx AS LONG)                          '
'                                                                           '
'   Description :                                                           '
'       Load and endorse AUXDRV.DRV driver.                                 '
'                                                                           '
'   Entry :                                                                 '
'       BlasterAddx - Far address of the BLASTER setting.                   '
'                                                                           '
'   Exit :                                                                  '
'       segment of the driver if sucessful else return 0.                   '
'                                                                           '
'---------------------------------------------------------------------------'

FUNCTION PrepareCTAUXDrv%(BlasterAddx AS LONG)

    DIM CTAuxDrv AS INTEGER


    CTAuxDrv = sbkLoadDriver%("AUXDRV.DRV",UNUSED)
    IF CTAuxDrv <> 0 THEN

        ' Initialises the CTAUX.DRV driver entry point
        CALL ctadSetDriverEntry((CTAuxDrv))

        ' Retrieves AUXDRV.DRV version
        IF ctadGetDrvVer% >= &H0302 THEN

            ' Passes BLASTER environment settings to the driver
            IF ctadGetEnvSettings%((BlasterAddx)) = 0 THEN
                PrepareCTAUXDrv% = CTAuxDrv
                EXIT FUNCTION
            ELSE
                PRINT "BLASTER environment is not valid"
            END IF
        ELSE
            PRINT "Invalid AUXDRV.DRV - ";
            PRINT "I need AUXDRV.DRV version 3.02 or higher."
        END IF

        CALL sbkFreeMem(CTAuxDrv)
    ELSE
        PRINT "Error loading AUXDRV.DRV or AUXDRV.DRV not found."
    END IF

    PrepareCTAUXDrv% = 0

END FUNCTION


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

SUB SoundEffect(wIOHandle%)

    SHARED wPanStatus AS INTEGER
    DIM wPrevVol AS INTEGER
    DIM retVal AS INTEGER

    CALL ctadInit

    ' preserve the previous voice volume settings
    wPrevVol = ctadGetVolume%(MIXERVOLxVOICE)

    ' set voice left/right volume to 0
    retVal = ctadSetVolume%(MIXERVOLxVOICE, &H0000)

    ' set address of the pan status
    CALL ctadSetPanStAddx(wPanStatus)

    ' Setup digitized sound for panning in mode 1
    ' repeat for 5 times
    retVal = ctadPan%(MIXERVOLxVOICE, 0, 255, 2000, 1, 5)
    retVal = ctadStartCtrl%
    CALL WaitEffectEnd(wIOHandle%)

    ' set voice left/right volume back to previous status
    retVal = ctadSetVolume%(MIXERVOLxVOICE, wPrevVol)

    ' turn off the DAC speaker
    CALL ctvdSetSpeaker(0)
    ' terminate the AUXDRV driver
    CALL ctadTerminate


END SUB


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

SUB WaitEffectEnd(wIOHandle%)

    DIM retVal AS INTEGER, pause AS INTEGER


    PRINT "Panning effect...."
    PRINT ""
    PRINT TAB(4)"[Esc] - to stop"
    PRINT TAB(4)"[P  ] - to pause"
    PRINT TAB(4)"[C  ] - to continue"

    pause = 0

    ' End of sound effect process ?
    WHILE (wPanStatus)

        ' Stop effect if no voice process
        IF CtVoiceStatus = 0 THEN
            retVal = ctadStopCtrl%
        END IF

        c$ = INKEY$
        IF c$ <> "" THEN
            userkey% = INT(ASC(LEFT$(c$,1)))

            SELECT CASE userkey%
                CASE ASC("S"),ASC("s"),27
                    retVal = ctadStopCtrl%
                    retVal = ctvdStop%(wIOHandle%)

                CASE ASC("P"),ASC("p")
                    IF pause = 0 THEN
                        PRINT "Effect pause..."
                        retVal = ctadPauseCtrl%
                        retVal = ctvdPause%(wIOHandle%)
                        pause = 1
                    END IF

                CASE ASC("C"),ASC("c")
                    IF pause <> 0 THEN
                        PRINT "Effect continue..."
                        retVal = ctadStartCtrl%
                        retVal = ctvdContinue%(wIOHandle%)
                        pause = 0
                    END IF
            END SELECT
        END IF
    WEND

    PRINT "End of panning effect..."

END SUB


'---------------------------------------------------------------------------'
'  @@ Usage                                                                 '
'                                                                           '
'   FUNCTION OutputVoice% (iHandle AS INTEGER)                              '
'                                                                           '
'   DESCRIPTION:                                                            '
'       Output voice with the file handle specified.                        '
'                                                                           '
'   ENTRY:                                                                  '
'       iHandle : handle of a file to be outputted.                         '
'                                                                           '
'   EXIT:                                                                   '
'       i/o voice handle if successful, else return -1.                     '
'                                                                           '
'---------------------------------------------------------------------------'

FUNCTION OutputVoice%(iHandle AS INTEGER)

    DIM wIOHandle AS INTEGER, wDiskBuf AS INTEGER
    DIM dwValue AS LONG


    OutputVoice% = -1

    ' Get voice IO handles supported by the driver
    IF ctvdGetParam%(CTVOCxIOHANDLES,dwValue) = 0 THEN

        IF dwValue <> 0 THEN

            ' wIOHandle - i/o voice handle to be used
            wIOHandle = ABS(INT(dwValue - 1))

            ' allocate memory for double disk buffer
            wDiskBuf = sbkAllocMem%(INT(DDxSIZE \ 16))

            IF wDiskBuf <> 0 THEN
                ' convert to 32-bit logical address
                dwValue = sbkMakeDWord((wDiskBuf),0)
                ' set double disk buffer
                IF ctvdSetDiskBuffer%(wIOHandle,dwValue,DDxUNIT) = 0 THEN

                    ' get i/o voice status address
                    dwValue = sbkMakeDWord&((VARSEG(CtVoiceStatus)),_
                                           (VARPTR(CtVoiceStatus)))
                    ' set i/o voice status
                    IF ctvdSetIoParam%(wIOHandle,CTVOCxIOxLPSTATUSWORD,_
                                                dwValue) = 0 THEN
                        ' turn on DAC speaker
                        CALL ctvdSetSpeaker(1)

                        ' Output voice
                        IF ctvdOutput%(wIOHandle,iHandle) = 0 THEN
                            OutputVoice% = wIOHandle
                        ELSE
                            PRINT "Driver : Error output voice."
                            CALL ShowError
                        END IF
                    ELSE
                        PRINT "Error setting CtVoiceStatus."
                    END IF
                ELSE
                    PRINT "Driver : Error setting double disk buffer."
                END IF
            ELSE
                PRINT "Dos : Error allocating memory for double disk buffer."
            END IF
        ELSE
            PRINT "I/O voice handle not available."
        END IF
    ELSE
        PRINT "Error geting Voice IO Handles."
    END IF

END FUNCTION


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

SUB ShowError

   DIM wError AS INTEGER


    ' Show the driver error and the DOS extended error code
    wError = ctvdGetDrvError%

    PRINT USING "Driver error = ##";wError

    wError = ctvdGetExtError%
    if wError <> 0 THEN
        PRINT "DOS error = ##";wError
    END IF

END SUB
' End Of File
