DECLARE SUB SENDBYTE (PA$)
DECLARE SUB playwav (NA$, FREQ&)
DECLARE SUB linenoise (BYTE)
DECLARE SUB innoise (BYTE)
DECLARE SUB micnoise (BYTE)
DECLARE SUB SHOWREGISTERS ()
DECLARE SUB DELAY (LENGHT&, FREQ&)
'----------------------------------------------
' DMA Play
' By Mike Huff (1996)
' Audio file player that plays using the DMA channels.
' Runs in QBASIC, QuickBASIC, PDS, VBDOS, and even GW-BASIC!!! (If you add
' line numbers and remove the SUBs, FUNCTIONS, and do a few other things.)
' Use DMADone% to detect the end of a transfer.
' Tested on a 486DX4-120mHz with a Reveal Sound FX card.
' tested on Cyrix 100Mhz with Orchid ESS Audiodrive (SBPro)
'        -setting master volume to 13 got rid ofjunk noise at end
' Program downloaded from http://www.ocf.berkeley.edu/~horie
DECLARE FUNCTION SPEAKERSTATUS% ()
DECLARE FUNCTION DMAStatus% ()
DECLARE FUNCTION DMADone% ()
DECLARE FUNCTION ResetDSP% ()
DECLARE SUB FMVolume (Right%, Left%, Getvol%)
DECLARE SUB VocVolume (Right%, Left%, Getvol%)
DECLARE SUB MasterVolume (Right%, Left%, Getvol%)
DECLARE SUB MicVolume (Gain%, Getvol%)
DECLARE SUB LineVolume (Right%, Left%, Getvol%)
DECLARE SUB CDVolume (Right%, Left%, Getvol%)
DECLARE SUB InputSource (InputSrc%, GetSrc%)
DECLARE SUB WriteDSP (BYTE%)
DECLARE SUB SetStereo (OnOff%)
DECLARE FUNCTION ReadDSP% ()
DECLARE SUB WriteDAC (BYTE%)
DECLARE SUB SpeakerState (OnOff%)
DECLARE SUB DMAState (StopGo%)
DECLARE FUNCTION ReadDAC% ()
DECLARE SUB DMAPlay (Segment&, Offset&, length&, FREQ&)
DECLARE SUB DMARecord (Segment&, Offset&, length&, FREQ&)
DECLARE SUB getblaster (dma%, baseport%, IRQ%)
DECLARE SUB speak (phr$, FREQ&)
DECLARE FUNCTION DSPVersion! ()
COMMON SHARED baseport%, LENPORT%, channel%
COMMON SHARED BlasterAddr%, dma%, repeats%

CONST baseaddr1 = &H220
CONST CommAddr = baseaddr1 + &HC, DataAddr = baseaddr1 + &HA
CONST ResetAddr = baseaddr1 + &H6



SCREEN 2

OUT ResetAddr, 1        'RESETS THE
OUT ResetAddr, 0        'SOUND BLASTER

DIM Sample(0 TO 200), length(0 TO 1), Saved(0 TO 1, 0 TO 100)
DIM Score(0 TO 2), SampleTmp(0 TO 200), START(6)

CLS

PRINT "DMAPlay"
PRINT "By Mike Huff"
PRINT "Modified By Martin Rampersad (To play entire file instead of first 32k)"
PRINT "Comments, etc. can be sent to MHuff@gnn.com or to Rampersad@Globalserve.net"
getblaster channel%, baseport%, IRQ% ' Parses BLASTER environment
PRINT STRING$(80, 196)

 REM *** callabrate ***
IF ResetDSP% THEN 'resets DSP (returns true if sucessful)
   PRINT "DSP reset sucessfully!"
ELSE
   PRINT "DSP failed to reset, try another port."
END IF
DO
CALL SHOWREGISTERS


ke$ = INKEY$
LOOP UNTIL ke$ = CHR$(27)

CLS







6000  REM THIS IS A tape storage utility
     '  Written by scott W Gates
     '   1999 july 31
     '
6010 '
6020 CLS :  LOCATE 10, 10: PRINT "tape storage utility,": LOCATE 11, 11: PRINT "BY SCOTT GATES INC."
6030 LOCATE 12, 12: PRINT "PRESS <S> TO START."
6040 ke$ = INKEY$: IF ke$ = "S" THEN 6070
6050 IF ke$ = "B" THEN PRINT "BACKING UP TYPER": REM SAVE "TYPER": PRINT "DONE": BEEP
6060 GOTO 6040
6070 SOUND 2000, 3
6100 X = 1
6110 CLS
6130 PRINT
6190
6220 PRINT "PRESS <P> TO PRINT,<S> TO SAVE"
    PRINT ",<L> TO LOAD,<N> TO START A NEW FILE"
    INPUT "<->"; CH$
    IF CH$ = "" THEN SOUND 255, 4: GOTO 6220


    CH$ = UCASE$(CH$)
6230 IF CH$ = "B" OR CH$ = "b" THEN CHDIR "C:\UTIL": RUN "START"
6240 IF CH$ = "DIR" THEN
    
     FILES
     PRINT " < - > WHEN DONE"
     INPUT "NEW DIRECTORY"; DR$
    
    
     IF DR$ = "-" THEN DIR$ = ""
     
     IF DR$ <> "-" THEN SHELL DR$
      
END IF
6270 IF CH$ = "S" THEN LINE INPUT "NAME OF FILE TO BE SAVED."; NA$: IF NA$ = "" THEN BEEP: GOTO 6220 ELSE OPEN "O", #1, NA$: PA$(0) = STR$(XL): PRINT #1, PA$(0): FOR Y1 = 1 TO XL: PRINT #1, PA$(Y1): NEXT Y1: CLOSE #1: PRINT "DONE": SOUND 255, 4

6290 IF CH$ = "R" THEN FOR Y3 = 1 TO X: PRINT PA$(Y3): NEXT Y3: GOTO 6130

6310 IF CH$ = "D" THEN CHDIR "C:\": PRINT "RETURNING TO DOS": SYSTEM

6320 IF CH$ = "N" THEN PRINT "EXISTING DATA DELETED.": SOUND 360, 10: GOTO 6000
6330 IF CH$ = "C" THEN INPUT "TYPE IN LETTER OF DRIVE YOU WANT TO USE."; DR$: CHDIR DR$ + ":\TYPER": PRINT "SWITCH TO "; DR$; " DRIVE AT TYPER"
6356 IF CH$ = "L" THEN PRINT "ERROR FREE DOCUMENT LOAD SECTION": GOSUB 9010
6360 GOTO 6220



9010 '  DO

79999    REM LOADING ALGORITHM
80000    INPUT "NAME OF FILE TO LOAD "; DOCUMENT$
     IF DOCUMENT$ = "" THEN
      BEEP: INPUT "GO BACK TO MAIN MENU <M> OR CONTINUE <C>"; CHO$
      IF CHO$ = "C" THEN GOTO 80000
     END IF
           
            IF CHO$ = "M" THEN CHO$ = "": GOTO 6220
      CLOSE #1
        LINECOUNT = 1
        PRINT "OPENING-"; DR$ + DOCUMENT$
        OPEN LD$ + DOCUMENT$ FOR INPUT AS #1
     DO
        LINE INPUT #1, PA$
         CALL SENDBYTE(PA$)
         
    LOOP UNTIL (EOF(1))
    CLOSE #1
    PRINT "DONE"
    SLEEP
      RETURN






 CALL DELAY(length&, FREQ&)
 
 PRINT "SPEECH FRAGMENT PLEASE"
  INPUT "<-> "; phr$
  INPUT "frequency "; FREQ&
  CALL speak(phr$, FREQ&)














END

'; example of calling plaw wav
'CALL playwav("c:\windows\sound\bit.wav", 21000)

SUB CDVolume (Right%, Left%, Getvol%)
OUT baseport% + 4, &H28
IF Getvol% THEN
   Left% = INP(baseport% + 5) \ 16
   Right% = INP(baseport% + 5) AND &HF
   EXIT SUB
ELSE
   OUT baseport% + 5, (Right% + Left% * 16) AND &HFF
END IF
END SUB

SUB DELAY (length&, FREQ&)
CALL getblaster(dma%, baseport%, IRQ%)

SENTV = 1
DO
PRINT dma%, baseport%, IRQ%, SENTV
 SENTV = INP(baseport + 20)

LOOP UNTIL SENTV = 255
END SUB

FUNCTION DMADone%
Count% = INP(LENPORT%)
Count2% = INP(LENPORT%)
Count& = CLNG(Count% + 1) * CLNG(Count2% + 1)
IF (Count& - 1) >= &HFFFF& THEN junk% = INP(DSPDataAvail%): DMADone% = -1
END FUNCTION

SUB DMAPlay (Segment&, Offset&, length&, FREQ&)
' Transfers and plays the contents of the buffer.
length& = length& - 1
Page% = 0
MEMLOC& = Segment& * 16 + Offset&
SELECT CASE channel%
    CASE 0
       PgPort% = &H87
       AddPort% = &H0
       LENPORT% = &H1
       ModeReg% = &H48
    CASE 1
       PgPort% = &H83
       AddPort% = &H2
       LENPORT% = &H3
       ModeReg% = &H49
    CASE 2
       PgPort% = &H81
       AddPort% = &H4
       LENPORT% = &H5
       ModeReg% = &H4A
    CASE 3
       PgPort% = &H82
       AddPort% = &H6
       LENPORT% = &H7
       ModeReg% = &H4B
    CASE ELSE
       PRINT "DMA channels 0-3 only are supported."
       EXIT SUB
END SELECT

OUT &HA, &H4 + channel%
OUT &HC, &H0
OUT &HB, ModeReg%
OUT AddPort%, MEMLOC& AND &HFF
OUT AddPort%, (MEMLOC& AND &HFFFF&) \ &H100
IF (MEMLOC& AND 65536) THEN Page% = Page% + 1
IF (MEMLOC& AND 131072) THEN Page% = Page% + 2
IF (MEMLOC& AND 262144) THEN Page% = Page% + 4
IF (MEMLOC& AND 524288) THEN Page% = Page% + 8
OUT PgPort%, Page%
OUT LENPORT%, length& AND &HFF
OUT LENPORT%, (length& AND &HFFFF&) \ &H100
OUT &HA, channel%

IF FREQ& < 23000 THEN
   TimeConst% = 256 - 1000000 \ FREQ&
   WriteDSP &H40
   WriteDSP TimeConst%
   WriteDSP &H14
   WriteDSP (length& AND &HFF)
   WriteDSP ((length& AND &HFFFF&) \ &H100)
ELSE
   IF DSPVersion! >= 3 THEN
      TimeConst% = ((65536 - 256000000 \ FREQ&) AND &HFFFF&) \ &H100
      WriteDSP &H40
      WriteDSP TimeConst%
      WriteDSP (length& AND &HFF)
      WriteDSP ((length& AND &HFFFF&) \ &H100)
      WriteDSP &H91
   ELSE
      PRINT "You need a Sound Blaster with a DSP v3.x+ to play at high speed."
      EXIT SUB
   END IF
END IF
END SUB

SUB DMARecord (Segment&, Offset&, length&, FREQ&)
length& = length& - 1
MEMLOC& = Segment& * 16 + Offset&
Page% = 0
SELECT CASE channel%
    CASE 0
       PgPort% = &H87
       AddPort% = &H0
       LENPORT% = &H1
       ModeReg% = &H44
    CASE 1
       PgPort% = &H83
       AddPort% = &H2
       LENPORT% = &H3
       ModeReg% = &H45
    CASE 2
       PgPort% = &H81
       AddPort% = &H4
       LENPORT% = &H5
       ModeReg% = &H46
    CASE 3
       PgPort% = &H82
       AddPort% = &H6
       LENPORT% = &H7
       ModeReg% = &H47
    CASE ELSE
       EXIT SUB
END SELECT

OUT &HA, &H4 + channel%
OUT &HC, &H0
OUT &HB, ModeReg%
OUT AddPort%, MEMLOC& AND &HFF
OUT AddPort%, (MEMLOC& AND &HFFFF&) \ &H100
IF (LongByte& AND 65536) THEN Page% = Page% + 1
IF (LongByte& AND 131072) THEN Page% = Page% + 2
IF (LongByte& AND 262144) THEN Page% = Page% + 4
IF (LongByte& AND 524288) THEN Page% = Page% + 8
OUT PgPort%, Page%
OUT LENPORT%, length& AND &HFF
OUT LENPORT%, (length& AND &HFFFF&) \ &H100
OUT &HA, channel%

IF FREQ& <= 23000 THEN
   TimeConst% = 256 - 1000000 \ FREQ&
   WriteDSP &H40
   WriteDSP TimeConst%
   WriteDSP &H24
   WriteDSP (length& AND &HFF)
   WriteDSP ((length& AND &HFFFF&) \ &H100)
ELSE
   IF DSPVersion! >= 3 THEN
      TimeConst% = ((65536 - 256000000 / FREQ&) AND &HFFFF&) \ &H100
      WriteDSP &H40
      WriteDSP TimeConst%
      WriteDSP (length& AND &HFF)
      WriteDSP ((length& AND &HFFFF&) \ &H100)
      WriteDSP &H99
   ELSE
      PRINT "You need a Sound Blaster with a DSP 3.x+ to record at high speed."
      EXIT SUB
   END IF
END IF

END SUB

SUB DMAState (StopGo%)
' Stops or continues DMA play.
IF StopGo% THEN WriteDSP &HD4 ELSE WriteDSP &HD0

END SUB

FUNCTION DSPVersion!
' Gets the DSP version.
WriteDSP &HE1
Temp% = ReadDSP%
Temp2% = ReadDSP%
DSPVersion! = VAL(STR$(Temp%) + "." + STR$(Temp2%))
END FUNCTION

SUB FMVolume (Right%, Left%, Getvol%)
OUT baseport% + 4, &H26
IF Getvol% THEN
   Left% = INP(baseport% + 5) \ 16
   Right% = INP(baseport% + 5) AND &HF
   EXIT SUB
ELSE
   OUT baseport% + 5, (Right% + Left% * 16) AND &HFF
END IF
END SUB

SUB getblaster (dma%, baseport%, IRQ%)
' This subroutine parses the BLASTER environment string and returns settings.
IF LEN(ENVIRON$("BLASTER")) = 0 THEN PRINT "BLASTER environment variable not set.": EXIT SUB
FOR length% = 1 TO LEN(ENVIRON$("BLASTER"))
   SELECT CASE MID$(ENVIRON$("BLASTER"), length%, 1)
      CASE "A"
        baseport% = VAL("&H" + MID$(ENVIRON$("BLASTER"), length% + 1, 3))
      CASE "I"
        IRQ% = VAL(MID$(ENVIRON$("BLASTER"), length% + 1, 1))
      CASE "D"
        dma% = VAL(MID$(ENVIRON$("BLASTER"), length% + 1, 1))
   END SELECT
NEXT

END SUB

SUB innoise (BYTE)

        OUT CommAddr, &H20
        BYTE = INP(DataAddr)
'

END SUB

SUB InputSource (InputSrc%, GetSrc%)
OUT baseport% + 4, &HC
IF GetSrc% THEN
   InputSrc% = INP(baseport% + 5) AND 2 + INP(baseport% + 5) AND 4
ELSE
   OUT baseport% + 5, InputSrc% AND 7
END IF
END SUB

SUB linenoise (BYTE)
CALL InputSource(&H2E, GetSrc%)
CALL innoise(BYTE)
LOCATE 4, 6: PRINT "selected noise "; BYTE

END SUB

SUB LineVolume (Right%, Left%, Getvol%)
OUT baseport% + 4, &H2E
nn = INP(&H2E)
PRINT nn
IF Getvol% THEN
   Left% = INP(baseport% + 5) \ 16
   Right% = INP(baseport% + 5) AND &HF
   EXIT SUB
ELSE
   OUT baseport% + 5, (Right% + Left% * 16) AND &HFF
END IF
END SUB

SUB MasterVolume (Right%, Left%, Getvol%)
OUT baseport% + 4, &H22
'PRINT BasePort%
IF Getvol% THEN
   Left% = INP(baseport% + 5) \ 16
   Right% = INP(baseport% + 5) AND &HF
   EXIT SUB
ELSE
   OUT baseport% + 5, (Right% + Left% * 16) AND &HFF
END IF
END SUB

SUB micnoise (BYTE)
CALL InputSource(&H220, GetSrc%)
        OUT CommAddr, &H20
        BYTE = INP(DataAddr)


END SUB

SUB MicVolume (Volume%, Getvol%)
OUT baseport% + 4, &HA
IF Getvol% THEN
   Volume% = INP(baseport% + 5) AND &HF
   EXIT SUB
ELSE
   OUT baseport% + 5, Volume% AND &HF
END IF
END SUB

SUB playwav (NA$, FREQ&)
DIM WavBuffer(1 TO 1) AS STRING * 32767 'Make a 32k buffer for file.


CURRENTPLAY = 0

SpeakerState 1 'turn the speaker on
PRINT "Sound Card DSP version:"; DSPVersion!

MasterVolume Right%, Left%, -1 'this puts the mixer volumes in Right% and Left%
PRINT "Master volume is set at: Right-"; Right%; " Left-"; Left%
MasterVolume 13, 13, 0 '15,15,0 cranks the master volume all the way up.

OPEN NA$ FOR BINARY AS #1
'INPUT "Frequency to play at: (1000-41000Hz)", freq&

DO

GET #1, 44 + (32767 * CURRENTPLAY!), WavBuffer(1)'Get 32k from file (skip header on WAV)
'PRINT SENTV
CURRENTPLAY! = CURRENTPLAY! + 1

length& = LOF(1) - 44
IF length& > 32767 THEN length& = 32767 'Adjust length if needed to 32k
DMAPlay VARSEG(WavBuffer(1)), VARPTR(WavBuffer(1)), length&, FREQ&
DO UNTIL A = 11500: A = A + 1: LOOP: A = 0
LOOP UNTIL EOF(1)

'Use DMARecord to record in the background.
'and use DMAPlay to playback the same buffer you recorded to or you could
'even write the buffer to a file.
'DMARecord VARSEG(WavBuffer(1)), VARPTR(WavBuffer(1)), Length&, Freq&
 CALL DELAY(length&, FREQ&)
CLOSE #1



END SUB

FUNCTION ReadDAC%
' Reads a byte from the DAC.
WriteDSP &H20
ReadDAC% = ReadDSP%

END FUNCTION

FUNCTION ReadDSP%
' Reads a byte from the DSP
DO
LOOP UNTIL INP(baseport% + 14) AND &H80
ReadDSP% = INP(baseport% + 10)
END FUNCTION

FUNCTION ResetDSP%
' Resets the DSP
OUT baseport% + 6, 1
FOR Count% = 1 TO 4
   junk% = INP(baseport% + 6)
NEXT
OUT baseport% + 6, 0
IF INP(baseport% + 14) AND &H80 = &H80 AND INP(baseport% + 10) = &HAA THEN
   ResetDSP% = -1
ELSE
   ResetDSP% = 0
END IF
END FUNCTION

SUB SENDBYTE (PA$)
'
'SEND BINARY INFORMATION TO LINE OUT (SPEAKERS)
'
  DIM BIT(10)
FOR OUPL = 1 TO LEN(PA$)

   CH$ = MID$(PA$, OUPL, 1)
   BYTEVAL = ASC(CH$)
   'PRINT "< "; BYTEVAL; " >";
            
FOR K = 10 TO 0 STEP -1
 IF (BYTEVAL AND 2 ^ K) <> 0 THEN BIT(K) = 1 ELSE BIT(K) = 0
 IF BIT(0) = 1 THEN BIT0$ = "1" ELSE BIT0$ = "0"
 IF BIT(1) = 1 THEN BIT1$ = "1" ELSE BIT1$ = "0"
 IF BIT(2) = 1 THEN BIT2$ = "1" ELSE BIT2$ = "0"
 IF BIT(3) = 1 THEN BIT3$ = "1" ELSE BIT3$ = "0"
 IF BIT(4) = 1 THEN BIT4$ = "1" ELSE BIT4$ = "0"
 IF BIT(5) = 1 THEN BIT5$ = "1" ELSE BIT5$ = "0"
 IF BIT(6) = 1 THEN BIT6$ = "1" ELSE BIT6$ = "0"
 IF BIT(7) = 1 THEN BIT7$ = "1" ELSE BIT7$ = "0"
 IF BIT(8) = 1 THEN BIT8$ = "1" ELSE BIT8$ = "0"
 IF BIT(9) = 1 THEN BIT9$ = "1" ELSE BIT9$ = "0"
 IF BIT(10) = 1 THEN BIT10$ = "1" ELSE BIT10$ = "0"




NEXT K
    



   BYTE$ = BIT10$ + BIT9$ + BIT8$ + BIT7$ + BIT6$ + BIT5$ + BIT4$ + BIT3$ + BIT2$ + BIT1$ + BIT0$
 
 

    PRINT BYTE$; " - "; BYTEVAL;
    SLEEP


    BYTE$ = ""








NEXT OUPL




END SUB

SUB SetStereo (OnOff%)
OUT baseport% + 4, &HE
IF OnOff% THEN OUT baseport% + 5, 2 ELSE OUT baseport% + 5, 0
END SUB

SUB SHOWREGISTERS

REM GET ALL CURRENT REGISTERS OF IMPORTANCE
REM SHOW THEIR CURRENT STATUS
REM CODING UTILITY SBLASTER
CALL getblaster(dma%, baseport%, IRQ%)

LOCATE 8, 1: PRINT "BASEPORT% "; baseport%
LOCATE 9, 6: PRINT "DMA% "; dma%
LOCATE 10, 6: PRINT "IRC% "; IRQ%
CALL linenoise(BYTE)

LOCATE 11, 6: PRINT "line "; BYTE

CALL micnoise(BYTE)
LOCATE 12, 5: PRINT "( mic ) ;"; BYTE

PRINT getscr%
CALL linenoise(BYTE)

END SUB

DEFINT A-Z
SUB speak (phr$, FREQ&)

DIM WavBuffer(1 TO 1) AS STRING * 32767 'Make a 32k buffer for file.


SpeakerState 1 'turn the speaker on
PRINT "Sound Card DSP version:"; DSPVersion!

MasterVolume Right%, Left%, -1 'this puts the mixer volumes in Right% and Left%
PRINT "Master volume is set at: Right-"; Right%; " Left-"; Left%
MasterVolume 13, 13, 0 '15,15,0 cranks the master volume all the way up.
'PRINT FREQ&
'
' version 1.4
' up dates to this program are frequently made
' don't hesatae to get your latest version
' contact me at << swg3681@ircc.net>>
' i will be pleased to send you the latest version
' please specify your version in case it may be the current one
' if you make an improvement to this code and want it to be known
' don't hesatate to submit it to me at the above e-mail
'   @@@@@@@@
' speech macro written by Scott W Gates
' all the below string expressings apply just to examining the text at character & ASCII Level
' such as Chr(32) 'Spacebar'
' Reader is the reader status 1 if on 0 if off 'when speech is taking place
' lsize is the character size of the phrase len(phr$)
' Lc is used to count through the phrase to pick out the word$ (words)
'   using a Chr$(32) 'space' as a seperator
' Letr$ is used to assmeble word$
' Phr$ = the complete phrase typed in
' wc = the cuurent character being examined
' rword$ is the word being read without Chr$(32)
' moc moves the wc character marker :0 = inactive(idle) >0 will sum moc with wc
' word$ is the word with safety chr$(32) put in for nltr$ and pltr$ to work
' ltr$ return the current character being read
' Ltva is the number value of ltr$ hence Ltva = val(ltr$)
' nltr$ returns the next letter following the current wc position
' Nlltr$ returns the next to last letter (call) would give l
' Nltv returns the number value of the next character
' pltr$ returns the previous letter befor the current wc position
' Pltv returns the number value of the previous character
' wc is the marker indicating the current character being read
' lsize is the size of the phrase including chr$(32) or spaces
' rword$ is just the word being read no chr$(32) 'spaces
' rsword is len(rword$)
' ntv 'checks if current letter mid(word$,wc,1) is next to a vowel 'a,e,i,o,u'
' lv means long vowel 1 if true 0 if false
' cfv mean check for vowel 1 if true 0 if false :note this may not be directly of use to you
' wpb is the begging of the word len wize in phr$
' wpl is the words length wpl = len(word$) 'note its value is put in
' ch$ returns the character to be added when assembling  word$
' Pronum$ returns the condition of proper number pronunceation from
' Dormant if off
' Active if on
' vowels returns the number of vowels in word

 IF phr$ = "" THEN phr$ = "speech error"

 rword$ = ""
 phr$ = phr$ + " "
 phr$ = LCASE$(phr$)
 reader = 0: wpb = 1: wpl = 1
'Get phrase size and check all letters
   lsize = LEN(phr$)

   FOR lc = 1 TO lsize
   LETR$ = MID$(phr$, lc, 1)
   IF LETR$ = CHR$(32) OR lc = (lsize) THEN word$ = MID$(phr$, wpb, wpl): reader = 1
    rword$ = ""
    FOR chc = 1 TO LEN(word$): CH$ = MID$(word$, chc, 1): IF CH$ <> CHR$(32) THEN rword$ = rword$ + CH$
    NEXT chc
  
      wpl = wpl + 1 ' needed to prevent contiuous loop
' show Reader status in
'   IF reader = 0 THEN PRINT "Idle"

'   IF reader = 1 THEN PRINT "Reading"
WHILE reader = 1
    IF wpl > 2 THEN lltr$ = MID$(rword$, wpl - 2, 1)
   IF wpl > 2 THEN nlltr$ = MID$(rword$, wpl - 2, 1):

   word$ = word$ + " ": word$ = " " + word$
   ' Show the word being read in cell "e:6"

   FOR wc = 2 TO wpl + 1 ' Read entire word compinsating for character placement
   IF wpl > 2 THEN pltr$ = MID$(word$, wc - 1, 1)
   ltr$ = MID$(word$, wc, 1): nltr$ = MID$(word$, wc + 1, 1)
   ltva = VAL(ltr$)
' sgl stands for single letter
' the below 'if then' statement test to see if the word is a single letter
' sgl returns a 1 if true 0 if false
   pltv = VAL(pltr$): nltv = VAL(nltr$) ' get the number values of the character if present
   IF pltr$ = CHR$(32) AND nltr$ = CHR$(32) THEN sgl = 1 ELSE sgl = 0
   IF wpl - wc >= 3 THEN L3tr$ = MID$(word$, wc + 2, 1)
' show l3tr$ in cell ("b:3")


' below section of this macro accesses the speech fragments
' it is concerned with assembling speech for numbers
' and commonly used words under united states English
   lv = 0
  'check to see if word has long vowels "a,e,i,o,u"
   IF ltr$ = "a" OR ltr$ = "e" OR ltr$ = "i" OR ltr$ = "o" OR ltr$ = "u" OR ltr$ = "y" THEN cfv = 1: vowels = vowels + 1
    IF cfv = 1 THEN IF nltr$ = "a" OR nltr$ = "e" OR nltr$ = "i" OR nltr$ = "o" OR nltr$ = "u" THEN lv = 1: ntv = 1: moc = 1
     IF cfv = 1 THEN IF lltr$ = "a" OR lltr$ = "e" OR lltr$ = "i" OR lltr$ = "o" OR lltr$ = "u" OR lltr$ = "y" THEN lv = 1
      IF cfv = 1 AND wc < wpl - 3 THEN IF ltr$ <> "o" AND nlltr$ = "a" OR nlltr$ = "e" OR nlltr$ = "i" OR nlltr$ = "o" OR nlltr$ = "u" THEN lv = 1
       'return check for vowel to zero hence cfv=0
        'cfv =1 if true 0 if false


   cfv = 0
   IF rsword = 1 THEN ltr$ = rword$

   '         [[[[[[[[   ]]]]]]]]
   ' [[[[[[[[  standard letters ]]]]]]]
   '         [[[[[[[[   ]]]]]]]]

' PRINT ltr$ 'for testing purposes only

'scope of "a"

   IF ltr$ = "a" AND sgl = 1 THEN say$ = "a": ltr$ = ""

    ' a cont aeiou section
' Scope of "b"
   IF ltr$ = "b" AND sgl = 1 THEN say$ = "b"
      IF ltr$ = "b" AND sgl = 0 THEN say$ = "bb"
'scope of "c"
IF ltr$ = "c" AND rword$ = "nice" THEN say$ = "ss": ltr$ = ""
 IF ltr$ = "c" AND rword$ = "space" THEN say$ = "ss": ltr$ = ""
  IF ltr$ = "c" AND rword$ = "come" THEN say$ = "kk": ltr$ = ""
   IF ltr$ = "c" AND sgl = 1 THEN say$ = "c": ltr$ = ""
    IF ltr$ = "c" AND nltr$ = "h" THEN say$ = "ch": ltr$ = "": moc = 1' ch as in church
     IF ltr$ = "c" AND nltr$ = "k" THEN moc = 1: say$ = "kk": ltr$ = ""
      IF ltr$ = "c" AND rword$ = "cell" THEN say$ = "ss": ltr$ = ""
       IF ltr$ = "c" AND ntv = 1 THEN say$ = "ss": ltr$ = ""
        IF ltr$ = "c" AND sgl = 0 AND ntv = 0 THEN say$ = "Cc": ltr$ = ""
         IF ltr$ = "c" AND ntv = 1 THEN say$ = "kk": ltr$ = ""
          IF ltr$ = "c" AND sgl = 0 AND L3tr$ <> "t" THEN say$ = "ss": ltr$ = ""
           IF ltr$ = "c" AND nltr$ = "c" THEN moc = 1: say$ = "kk"
' scope of "d"
   IF ltr$ = "d" AND sgl = 1 THEN say$ = "d"
     IF ltr$ = "d" AND sgl = 0 THEN say$ = "dd"
' scope of "e"
   IF ltr$ = "e" AND sgl = 1 THEN say$ = "e": ltr$ = ""
     ' e phonix at aeiou section
' scope of "f"
   IF ltr$ = "f" AND sgl = 1 THEN say$ = "f"
      IF ltr$ = "f" AND sgl = 0 THEN say$ = "ff"
' scope of "g"
  'PRINT ltr$
 IF ltr$ = "g" AND rword$ = "sign" THEN say$ = "": ltr$ = ""
  IF ltr$ = "g" AND pltr$ = "e" THEN say$ = "gg": ltr$ = ""
   IF ltr$ = "g" AND nltr$ = "r" THEN say$ = "gg": ltr$ = ""
    IF ltr$ = "g" AND pltr$ <> CHR$(32) AND nltr$ <> CHR$(32) THEN say$ = "JJ": ltr$ = ""
     IF ltr$ = "g" AND sgl = 1 THEN say$ = "g"
      IF ltr$ = "g" AND sgl = 0 THEN say$ = "gg"
' scope of "h"
   IF ltr$ = "h" AND sgl = 1 THEN say$ = "h"
      IF ltr$ = "h" AND sgl = 0 THEN say$ = "hh" 'h as in horse
' scope of "i"
   IF ltr$ = "i" AND sgl = 1 THEN say$ = "i": ltr$ = ""
' scope of "j"
   IF ltr$ = "j" AND sgl = 1 THEN say$ = "j"
      IF ltr$ = "j" AND sgl = 0 THEN say$ = "jj"
' scope of "k"
   IF ltr$ = "k" AND sgl = 1 THEN say$ = "k"
      IF ltr$ = "k" AND sgl = 0 THEN say$ = "kk"
' scope of "l"
   IF ltr$ = "l" AND sgl = 1 THEN say$ = "l"
      IF ltr$ = "l" AND sgl = 0 THEN say$ = "ll": REM  If nltr$ = "l" Then moc = 2
' scope of "m"
   IF ltr$ = "m" AND sgl = 1 THEN say$ = "m": ltr$ = ""
      IF ltr$ = "m" AND agl = 0 THEN say$ = "mm" ' m as in mouse
' scope of "n"
   IF ltr$ = "n" AND sgl = 1 THEN say$ = "n"
      IF ltr$ = "n" AND sgl = 0 THEN say$ = "nn"
' scope of "o"
   IF ltr$ = "o" AND sgl = 1 THEN say$ = "o"
      ' o's phonixe cont at aeiou section
' scope of "p"
   IF ltr$ = "p" AND sgl = 1 THEN say$ = "p"
      IF ltr$ = "p" AND sgl = 0 THEN say$ = "pp"
' scope of "q"
   IF ltr$ = "q" AND sgl = 1 THEN say$ = "q"
      IF ltr$ = "q" AND sgl = 0 THEN say$ = "kk"
' scope of "r"
   IF ltr$ = "r" AND sgl = 1 THEN say$ = "r"
      IF ltr$ = "r" AND sgl = 0 THEN say$ = "rr"
       IF ltr$ = "r" AND nltr$ = "r" THEN moc = 1
' scope of "s"

   IF ltr$ = "s" AND sgl = 1 THEN say$ = "s"
     IF ltr$ = "s" AND nltr$ = "h" THEN say$ = "sh": moc = 1: ltr$ = "" ' sh as in shack
      IF ltr$ = "s" AND sgl = 0 THEN say$ = "ss"

' scope of "t"
   IF ltr$ = "t" AND sgl = 1 THEN say$ = "t"
    ' "th" as in the
     IF ltr$ = "t" AND nltr$ = "h" THEN moc = 1: say$ = "th": ltr$ = ""' rem th
      IF ltr$ = "t" AND sgl = 0 THEN say$ = "tt"
       IF ltr$ = "t" AND nltr$ = "t" THEN moc = 1: ltr$ = ""
 
' scope of "u"
   IF ltr$ = "u" AND sgl = 1 THEN say$ = "u": ltr$ = ""
' scope of "v"
   IF ltr$ = "v" AND sgl = 1 THEN say$ = "v"
      IF ltr$ = "v" AND sgl = 0 THEN say$ = "vv"
' scope of "w"
   IF ltr$ = "w" AND sgl = 1 THEN say$ = "w"
     IF ltr$ = "w" AND rword$ = "why" THEN say$ = "y": ltr$ = "": rword$ = "": wc = wpl: ' force word to null and move on to next word
      IF ltr$ = "w" AND sgl = 0 THEN say$ = "ww"

' scope of "x"
   IF ltr$ = "x" THEN say$ = "x"
    IF ltr$ = "x" AND nltr$ = CHR$(32) AND pltr$ <> CHR$(32) THEN say$ = "": CALL speak("cs", FREQ&)
' scope of "y"
IF ltr$ = "y" AND sgl = 1 THEN say$ = "y": ltr$ = ""
 IF ltr$ = "y" AND rword$ = "my" THEN say$ = "i": ltr$ = ""
  IF ltr$ = "y" AND rword$ = "by" THEN say$ = "i": ltr$ = ""
   IF ltr$ = "y" AND nltr$ = "" THEN say$ = "e": ltr$ = ""
    IF ltr$ = "y" AND nltr$ = "e" THEN say$ = "yy": ltr$ = ""
     IF ltr$ = "y" AND rword$ = "you" THEN say$ = "U": ltr$ = "": wc = lsize: word$ = ""
      IF ltr$ = "y" AND nltr$ = "o" THEN say$ = "yy": ltr$ = ""
       IF ltr$ = "y" AND pltr$ = "n" THEN say$ = "E": ltr$ = ""
        IF ltr$ = "y" AND rword$ = "byte" THEN say$ = "i": ltr$ = ""
         IF ltr$ = "y" AND sgl = 0 AND lv = 0 THEN say$ = "yy": ltr$ = ""
          IF ltr$ = "y" AND sgl = 1 THEN say$ = "y"
           IF ltr$ = "y" AND pltr$ <> CHR$(32) THEN say$ = "e"
            IF ltr$ = "y" AND nltr$ = CHR$(32) THEN say$ = "e": ltr$ = ""

' scope of "z"
   IF ltr$ = "z" AND sgl = 1 THEN say$ = "z"
      IF ltr$ = "z" AND sgl = 0 THEN say$ = "zz"
' end of standard letters

' special phonix section 'a,e,i,o,u'
' vowel "a"
  IF ltr$ = "a" AND rword$ = "gates" THEN say$ = "a": ltr$ = ""
   IF ltr$ = "a" AND rword$ = "have" THEN say$ = "AA": ltr$ = ""
    IF ltr$ = "a" AND rword$ = "start" THEN say$ = "R": ltr$ = ""
     IF ltr$ = "a" AND rword$ = "are" THEN say$ = "r": ltr$ = "": word$ = "" 'force "R" for "are"
      IF ltr$ = "a" AND rword$ = "happy" THEN say$ = "aa": ltr$ = ""
       IF ltr$ = "a" AND lv = 1 AND nltr$ <> "r" THEN say$ = "a": ltr$ = ""
        IF ltr$ = "a" AND nltr$ = "r" AND lv = 1 THEN say$ = "r": ltr$ = "": moc = 1
         IF ltr$ = "a" AND lv = 0 THEN say$ = "aa": ltr$ = ""
          IF ltr$ = "a" AND lltr$ = "e" THEN say$ = "a": ltr$ = ""
           IF ltr$ = "a" AND sgl = 0 AND lltr$ <> "e" THEN say$ = "a": ltr$ = ""
            IF ltr$ = "a" AND lv = 0 THEN say$ = "aa": ltr$ = ""



' vowel "e
IF ltr$ = "e" AND rword$ = "the" THEN say$ = "e": ltr$ = ""
 IF ltr$ = "e" AND rword$ = "zero" THEN say$ = "e": ltr$ = ""
  IF ltr$ = "e" AND rword$ = "error" THEN say$ = "a": ltr$ = ""
   IF ltr$ = "e" AND nltr$ = CHR$(32) AND lv = 1 THEN say$ = "": ltr$ = ""
    IF ltr$ = "e" AND nltr$ = CHR$(32) THEN say$ = "e": ltr$ = ""
     IF ltr$ = "e" AND nltr$ = "r" THEN say$ = "": ltr$ = ""
      IF ltr$ = "e" AND lltr$ = "y" THEN say$ = "EE": ltr$ = ""
       IF ltr$ = "e" AND ntv = 0 AND nltr$ <> CHR$(32) THEN say$ = "ee": ltr$ = ""
        IF ltr$ = "e" AND nltr$ = "n" THEN say$ = "ii": ltr$ = ""
         IF ltr$ = "e" AND rword$ = "welcome" AND pltr$ = "w" THEN say$ = "ee": ltr$ = ""
          IF ltr$ = "e" AND rword$ = "byte" THEN say$ = "": ltr$ = ""
           IF ltr$ = "e" AND rword$ = "here" AND pltr$ <> "r" THEN say$ = "e"
            IF ltr$ = "e" AND rword$ = "come" THEN say$ = "": ltr$ = ""
             IF ltr$ = "e" AND rword$ = "there" THEN say$ = "eee": ltr$ = ""
              IF ltr$ = "e" AND rword$ = "the" THEN say$ = "e": ltr$ = "":    ' force long e for "the"
               IF ltr$ = "e" AND nltr$ = "r" THEN say$ = "e": ltr$ = ""
                IF ltr$ = "e" AND wc < wpl AND pltr$ <> "p" AND lltr$ <> "o" AND lv = 1 THEN say$ = "e":  ltr$ = ""
                 IF ltr$ = "e" AND lv = 1 AND ntv = 1 AND wc < wpl AND pltr$ <> "P" AND lltr$ <> "o" THEN say$ = "e": ltr$ = ""
                  IF ltr$ = "e" AND lv = 1 AND sgl = 0 AND pltr$ <> "p" AND wc < wpl THEN say$ = "ee": ltr$ = ""
                   IF ltr$ = "e" AND lv = 0 THEN say$ = "e": ltr$ = ""
                    IF ltr$ = "e" AND lv = 1 THEN say$ = "e": ltr$ = ""
                    
                       'when all else fails long "e"




  ' vowel "i"
 IF ltr$ = "i" AND rword$ = "sign" THEN say$ = "i": ltr$ = ""
  IF ltr$ = "i" AND rword$ = "hi" THEN say$ = "i": ltr$ = "" ' force long i as in "hi"
   IF ltr$ = "i" AND ntv = 0 AND lv = 0 THEN say$ = "ii": ltr$ = ""
      IF ltr$ = "i" AND lv = 1 THEN say$ = "i": ltr$ = ""

' vowel "o"
  IF ltr$ = "o" AND rword$ = "do" THEN say$ = "oo": ltr$ = ""
   IF ltr$ = "o" AND nltr$ = "u" AND lltr$ <> "d" THEN say$ = "oo": moc = 1: ltr$ = ""
    IF ltr$ = "o" AND nltr$ = "u" THEN say$ = "aa": ltr$ = ""
     ' "OU" AS IN FOUND OR SOUND = FORCES AA.WAV
      IF ltr$ = "o" AND pltr$ = "c" AND lv = 0 THEN say$ = "aaa": ltr$ = ""
       IF ltr$ = "o" AND nltr$ = "m" THEN say$ = "uu": ltr$ = ""
        IF ltr$ = "o" AND rword$ = "come" THEN say$ = "o"
         IF ltr$ = "o" AND rword$ = "tron" THEN say$ = "aaa": ltr$ = ""
          IF ltr$ = "o" AND nltr$ = "w" THEN say$ = "aaa": ltr$ = ""
           IF ltr$ = "o" AND plltr$ = "z" THEN say$ = "o": ltr$ = ""
            IF ltr$ = "o" AND nltr$ = "o" THEN say$ = "oo": ltr$ = ""
             IF ltr$ = "o" AND lv = 1 THEN say$ = "o": ltr$ = ""

               IF ltr$ = "o" AND nltr$ = "n" THEN say$ = "aaa": ltr$ = ""
           
              IF ltr$ = "o" AND pltr$ = "t" THEN say$ = "oo": ltr$ = ""
               IF ltr$ = "o" AND nltr$ = CHR$(32) AND lv = 1 THEN say$ = "o": ltr$ = ""
                ' o as in 'on'
               
                 'IF ltr$ = "o" AND pltr$ = CHR$(32) THEN say$ = "aaa": ltr$ = ""
                
                  IF ltr$ = "o" AND lv = 1 AND nltr$ <> "o" AND ntv = 1 THEN say$ = "o": ltr$ = ""
                   IF ltr$ = "o" THEN say$ = "o"
                    IF ltr$ = "o" AND sgl = 0 AND lv = 0 THEN say$ = "aaa": ltr$ = ""
                     IF ltr$ = "o" AND lv = 1 THEN say$ = "o"

' vowel "u"

 IF ltr$ = "u" AND rword$ = "stupid" THEN say$ = "oo": ltr$ = ""
  IF ltr$ = "u" AND rword$ = "user" THEN say$ = "u": ltr$ = ""
   IF ltr$ = "u" AND lv = 0 THEN say$ = "uu"
     IF ltr$ = "u" AND lv = 1 THEN say$ = "oo": 'leave open for next test of "u"
  
  
  
  
  
  
'   end of vowel section
  
     IF moc > 0 THEN wc = wc + moc: moc = 0
     IF wc > wpl THEN word$ = ""
   lv = 0
' end of special vowel "a,e,i,o,u" section
' Numbers this should be self explanatory...

IF ltr$ = "\" THEN CALL speak("SLASH", FREQ&)
IF ltr$ = "+" THEN CALL speak("PLUS", FREQ&)
IF ltr$ = "-" THEN CALL speak("miin us", FREQ&)
IF ltr$ = "*" THEN CALL speak("tiims", FREQ&)
IF ltr$ = "/" THEN CALL speak("diviid ed by", FREQ&)
IF ltr$ = "=" THEN CALL speak("e qwuals", FREQ&)
IF ltr$ = "0" THEN CALL speak("zero", FREQ&)
IF ltr$ = "9" THEN CALL speak("nine", FREQ&)
IF ltr$ = "8" THEN CALL speak("ate", FREQ&)
IF ltr$ = "7" THEN CALL speak("seven", FREQ&)
IF ltr$ = "6" THEN CALL speak("six", FREQ&)
IF ltr$ = "5" THEN CALL speak("five", FREQ&)
IF ltr$ = "4" THEN CALL speak("for", FREQ&)
IF ltr$ = "3" THEN CALL speak("three", FREQ&)
IF ltr$ = "2" THEN CALL speak("to", FREQ&)
IF ltr$ = "1" THEN CALL speak("wun", FREQ&)
' end of numbers
  IF wc >= wpl THEN reader = 0: ltr$ = "": rword$ = ""
  IF wpl = 1 THEN word$ = "": rword$ = "": ltr$ = ""

  ltr$ = ""
  A = 0
  CURRENTPLAY! = 0
  
WHILE say$ <> ""

 IF say$ <> "" THEN filename$ = "c:\windows\sound\qbspeech\" + say$ + ".wav"
CURRENTPLAY = 0
OPEN filename$ FOR BINARY AS #1
'INPUT "Frequency to play at: (1000-41000Hz)", freq&

DO

GET #1, 44 + (32767 * CURRENTPLAY!), WavBuffer(1)'Get 32k from file (skip header on WAV)
'PRINT SENTV
CURRENTPLAY! = CURRENTPLAY! + 1

length& = LOF(1) - 44
IF length& > 32767 THEN length& = 32767 'Adjust length if needed to 32k
DMAPlay VARSEG(WavBuffer(1)), VARPTR(WavBuffer(1)), length&, FREQ&
DO UNTIL A = 11500: A = A + 1: LOOP: A = 0
LOOP UNTIL EOF(1)

'Use DMARecord to record in the background.
'and use DMAPlay to playback the same buffer you recorded to or you could
'even write the buffer to a file.
'DMARecord VARSEG(WavBuffer(1)), VARPTR(WavBuffer(1)), Length&, Freq&
 CALL DELAY(length&, FREQ&)
CLOSE #1

'  PRINT say$
  say$ = ""
WEND
NEXT wc
 CALL DELAY(LENGHT&, FREQ&)
 nlltr$ = "": wpl = 1: wpb = lc: ntv = 0: vowels = 0: lv = 0: L3tr$ = ""
 WEND
  NEXT lc






 END SUB

DEFSNG A-Z
SUB SpeakerState (OnOff%)
' Turns speaker on or off.
IF OnOff% THEN WriteDSP &HD1 ELSE WriteDSP &HD3
END SUB

FUNCTION SPEAKERSTATUS%
OUT baseport% + 4, &HD8
IF INP(baseport% + 5) = &HFF THEN SPEAKERSTATUS% = -1 ELSE SPEAKERSTATUS% = 0
END FUNCTION

SUB VocVolume (Right%, Left%, Getvol%)
OUT baseport% + 4, &H4
IF Getvol% THEN
   Left% = INP(baseport% + 5) \ 16
   Right% = INP(baseport% + 5) AND &HF
   EXIT SUB
ELSE
   OUT baseport% + 5, (Right% + Left% * 16) AND &HFF
END IF
END SUB

SUB WriteDAC (BYTE%)
' Writes a byte to the DAC.
WriteDSP &H10
WriteDSP BYTE%
END SUB

SUB WriteDSP (BYTE%)
' Writes a byte to the DSP
DO
LOOP WHILE INP(baseport% + 12) AND &H80
OUT baseport% + 12, BYTE%
END SUB

