DECLARE SUB MicVolume (volume%, Getvol%)
DECLARE SUB LineVolume (Right%, Left%, Getvol%)
DECLARE SUB MasterVolume (Right%, Left%, Getvol%)
DECLARE SUB WriteDSP (BYTE%)
DECLARE SUB speakerstate (OnOff%)
DECLARE FUNCTION speakerstatus% ()
DECLARE SUB SHOWREGISTERS ()
DECLARE SUB SENDBYTE (PA$)
DECLARE SUB getblaster (dma%, baseport%, IRQ%)
DECLARE SUB innoise (BYTE!)
DECLARE SUB micnoise (BYTE!)
DECLARE SUB InputSource (InputSrc%, GetSrc%)
DECLARE SUB linenoise (BYTE!)
DECLARE SUB SHOEREGISTERS
' when using this program be sure to use the qbasic/h option to get the best
'  veiw of the source code
'
DECLARE SUB PLAYWAV (wavefile$)
DECLARE SUB ValidWavHeader (file$, LenHeader%, dataLen&, nChannels%, nSamplesPerSec&, nAvgBytesPerSec&, ok%)
DECLARE SUB WriteToDSP (v%)
DECLARE SUB PlayBack (buffer$, size%, freq&, BytesPerSec&, chans%, num%)
DECLARE SUB delay (tdelay!)
DECLARE SUB speak (phr$)
DECLARE FUNCTION GetBlasterAddr% ()
DECLARE FUNCTION SBreset% ()

COMMON SHARED baseport%, LENPORT%, channel%
COMMON SHARED BlasterAddr%, dma%, repeats%

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

CLEAR 33000



SCREEN 12

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)
getblaster channel%, baseport%, IRQ% ' Parses BLASTER environment
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.
CALL LineVolume(Right%, Left%, Getvol%)

volume% = 31
CALL MicVolume(volume%, Getvol%)
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
CLS




DO

CALL SHOWREGISTERS
   PRINT "PRESS <C>"

LOOP UNTIL KE$ = "C"



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 #2
      

PRINT "Sound Card DSP version:"; DSPVersion!
      
      
        LINECOUNT = 1
        PRINT "OPENING-"; DR$ + DOCUMENT$
        OPEN LD$ + DOCUMENT$ FOR INPUT AS #2
     DO
        LINE INPUT #2, PA$
         CALL SENDBYTE(PA$)
        
    LOOP UNTIL (EOF(1))
    CLOSE #2
    PRINT "DONE"
    SLEEP
      RETURN






 'CALL delay(length&, freq&)

 PRINT "SPEECH FRAGMENT PLEASE"
  INPUT "<-> "; phr$
  INPUT "frequency "; freq&
  CALL speak(phr$)














END

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




END 'end of tapeutil.bas

DEFINT A-Z
'------------------------------------------------------------------------------
SUB delay (tdelay!)
time1! = TIMER
DO
LOOP WHILE (TIMER - time1! < tdelay!) OR (time1! > TIMER)
END SUB

DEFSNG A-Z
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

DEFINT A-Z
'------------------------------------------------------------------------------
FUNCTION GetBlasterAddr%
'Get Blaster Address and DMA channel from Environment Variable
tmp% = 0  'No Environment Variable Set...default
blast$ = UCASE$(ENVIRON$("BLASTER"))
IF LEN(blast$) THEN
   tmp% = INSTR(blast$, "A")
   tmp1$ = MID$(blast$, tmp% + 1, 3)
   tmp% = VAL("&H" + tmp1$)
   IF tmp% = 203 THEN tmp% = -1    'If there is no value assigned
   IF tmp% > 0 THEN
      tmp2% = INSTR(blast$, "D")
      dma% = VAL(MID$(blast$, tmp2% + 1))        'dma% is a global variable
      IF dma% < 0 OR dma% > 7 THEN tmp% = -2
   END IF
END IF
GetBlasterAddr% = tmp%
END FUNCTION

DEFSNG A-Z
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

DEFINT A-Z
'------------------------------------------------------------------------------
SUB PlayBack (buffer$, size%, freq&, BytesPerSec&, chans%, num%)
size% = size% - 1
segment& = VARSEG(buffer$)
offset& = SADD(buffer$)
IF segment& < 0 THEN segment& = segment& + 65536
IF offset& < 0 THEN offset& = offset& + 65536
baseaddr& = segment& * 16 + offset&
look1% = VARPTR(baseaddr&)
look2% = VARPTR(size%)
SELECT CASE dma%
   CASE 0
      dmapage% = &H87   '135 decimal
      dmaaddr% = 0
      dmalen% = 1
   CASE 1
      dmapage% = &H83   '131 decimal
      dmaaddr% = 2
      dmalen% = 3
   CASE 2
      dmapage% = &H81
      dmaaddr% = 4
      dmalen% = 5
   CASE 3
      dmapage% = &H82
      dmaaddr% = 6
      dmalen% = 7
   CASE 4
      dmapage% = &H8F
      dmaaddr% = &HC0
      dmalen% = &HC2
   CASE 5
      dmapage% = &H8B
      dmaaddr% = &HC4
      dmalen% = &HC6
   CASE 6
      dmapage% = &H89
      dmaaddr% = &HC8
      dmalen% = &HCA
   CASE 7
      dmapage% = &H8A
      dmaaddr% = &HCC
      dmalen% = &HCE
END SELECT
SELECT CASE dma%
   CASE 0 TO 3
      dmamask% = &HA
      dmamode% = &HB
      dmaclear% = &HC
      dmastatus% = &H8
   CASE 4 TO 7
      dmamask% = &HD4
      dmamode% = &HD6
      dmaclear% = &HD8
      dmastatus% = &HD0
END SELECT
SELECT CASE dma%
   CASE 0, 4
      dmaterminal% = 1   'bit 0 of status register (&H08 or &HD0)
   CASE 1, 5
      dmaterminal% = 2   'bit 1
   CASE 2, 6
      dmaterminal% = 4   'bit 2
   CASE 3, 7
      dmaterminal% = 8   'bit 3
END SELECT

OUT dmamask%, dma% + 4   'mask the dma channel
OUT dmaclear%, &H0       '(clear the internal DMA flip/flop)
OUT dmamode%, 72 + dma%  '  72=010010XX where XX=dmachannel%
OUT dmaaddr%, PEEK(look1%)      'bits 0-7 of  the 20bit address
OUT dmaaddr%, PEEK(look1% + 1)  'bits 8-15 of the 20bit address
OUT dmapage%, PEEK(look1% + 2)  'bits 16-19 of the 20 bit address
OUT dmalen%, PEEK(look2%)       'bits 0-7 of size%
OUT dmalen%, PEEK(look2% + 1)   'bits 8-15  of size%
OUT dmamask%, dma%              'enable channel

IF num% = 1 THEN  'only need to Write out time constant once
   timeconst% = 256 - 1000000 / (freq& * chans%)
   CALL WriteToDSP(&H40)
   CALL WriteToDSP(timeconst%)
   'Reset Mixer    DSPmixeraddress = Blasteraddr% + &H4
   OUT BlasterAddr% + &H4, &H0
   OUT BlasterAddr% + &H4 + 1, 0
   'Set Volume to Maximum...255
   OUT BlasterAddr% + &H4, &H22
   OUT BlasterAddr% + &H4 + 1, 255
   IF chans% = 2 THEN
      'Set mixer to Stereo Output
      OUT BlasterAddr% + &H4, &HE
      OUT BlasterAddr% + &H4 + 1, 34      '34=2^5+2^1
   END IF
END IF
IF BytesPerSec& > 22000 THEN
   CALL WriteToDSP(&H48)   'Set Block Size
ELSE
   CALL WriteToDSP(&H14)   'DMA Mode 8-bit DAC
END IF
CALL WriteToDSP(PEEK(look2%))      'Lo byte of address
CALL WriteToDSP(PEEK(look2% + 1))  'High byte of address
IF BytesPerSec& > 22000 THEN CALL WriteToDSP(&H91)  'High Speed DMA mode 8-bit
dummy% = INP(dmastatus%)    'Read status byte once to make sure DMA is going.
WAIT dmastatus%, dmaterminal%   'Loop until terminal count bit set in DMA status register
'DMA Transfer is Now Complete
'Acknowledge the DSP interrupt by reading the DATA AVAILABLE port once
dummy% = INP(BlasterAddr% + &HE)    'DSP Available address
END SUB

DEFSNG A-Z
SUB PLAYWAV (wavefile$)


repeats% = 1
BlasterAddr% = GetBlasterAddr%
SELECT CASE BlasterAddr%
   CASE -2
      PRINT "Bad DMA Channel specified!"
      END
   CASE -1
      PRINT "No Port Base Address Given!"
      END
   CASE 0
      PRINT "No BLASTER Environment Variable Set!"
      END
   CASE ELSE
      'Assume a valid Address Exists
'      PRINT "Blaster Address = "; HEX$(BlasterAddr%)
END SELECT
IF NOT SBreset% THEN
   PRINT "SoundBlaster Card Would Not Reset!"
   END
END IF

sp% = INSTR(Spec$, " ")
IF sp% THEN
   wavefile$ = LEFT$(Spec$, sp% - 1)
   repeats% = VAL(RIGHT$(Spec$, LEN(Spec$) - sp%))
   IF repeats% = 0 THEN repeats% = 1
ELSE
   IF LEN(Spec$) THEN
      wavefile$ = Spec$
      repeats% = 1
   END IF
END IF

IF LEN(wavefile$) = 0 THEN
END IF
'wavefile$ = "C:\QBASIC\THEME.WAV"
CALL ValidWavHeader(wavefile$, LenHeader%, WavLen&, Channels%, Sampling&, bytes&, ok%)

IF NOT ok% THEN
   PRINT "Bad Wave File Format"
   END
END IF

MaxBuffer% = 7053

CALL WriteToDSP(&HD1)  'Speaker ON
FOR repeat% = 1 TO repeats%    'This can loop to play the file ii% times]
filenum% = FREEFILE
   OPEN wavefile$ FOR BINARY AS filenum%
      num% = 0
      SEEK filenum%, LenHeader% + 1
      Remaining& = WavLen&
      DO
         num% = num% + 1
         IF Remaining& > MaxBuffer% THEN
            BufferLen% = MaxBuffer%
         ELSE
            BufferLen% = Remaining&
         END IF
         Remaining& = Remaining& - BufferLen%
         buffer$ = SPACE$(BufferLen%)
         GET filenum%, , buffer$
         CALL PlayBack(buffer$, BufferLen%, Sampling&, bytes&, Channels%, num%)
      LOOP WHILE Remaining& > 0
      OUT &H20, &H20   'Reset Normal Interrupt Service
   CLOSE filenum%
NEXT repeat%
CALL WriteToDSP(&HD3)  'Speaker OFF

END SUB

DEFINT A-Z
'------------------------------------------------------------------------------
FUNCTION SBreset%
'DSPreset% = address% + &H6
'DSPread% = address% + &HA
'DSPwrite% = address% + &HC
'DSPavail% = address% + &HE
'DSPmixer% = address% + &H4
OUT BlasterAddr% + &H6, 1   'Reset address
delay .1
OUT BlasterAddr% + &H6, 0
time1! = TIMER: noreset% = 0
DO
   'Read Data Available port until bit 7 is set
   'This should take about 100 micro seconds...give it 1 full second
   IF TIMER - time1! > 1! THEN noreset% = -1
LOOP UNTIL ((INP(BlasterAddr% + &HE) AND 128) = 128) OR noreset%
IF NOT noreset% THEN
   IF INP(BlasterAddr% + &HA) = &HAA THEN
      SBreset% = -1
   ELSE
      SBreset% = 0
   END IF
ELSE
   SBreset% = 0
END IF
END FUNCTION

DEFSNG A-Z
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$; " . ";
   
       L = LEN(BYTE$)
     
       FOR CC = 1 TO (L)
     
       BIT$ = MID$(BYTE$, CC, 1)
      
        IF BIT$ = "1" THEN
      
         CALL PLAYWAV("C:\WINDOWS\SOUND\BIT.WAV")

      
        END IF

        IF BIT$ = "0" THEN

         CALL PLAYWAV("C:\WINDOWS\SOUND\NOBIT.WAV")



        END IF



       NEXT CC
    BYTE$ = ""








NEXT OUPL




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 1, 1: PRINT "BASEPORT% "; baseport%
LOCATE 2, 6: PRINT "DMA% "; dma%
LOCATE 3, 6: PRINT "IRC% "; IRQ%
CALL linenoise(BYTE)

LOCATE 6, 6: PRINT "line "; BYTE

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

PRINT getscr%
CALL linenoise(BYTE)

END SUB

DEFINT A-Z
' version 1.2
' 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
'
SUB speak (phr$)

 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
IF ltr$ = "y" AND nltr$ = CHR$(32) THEN say$ = "e": ltr$ = ""
'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"
      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$ = "k"
' 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 sgl = 0 THEN say$ = "ww"
' scope of "x"
   IF ltr$ = "x" THEN say$ = "x"
' scope of "y"
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"

' 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 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"
' 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$ = "0" THEN speak ("zero")
IF ltr$ = "9" THEN speak ("nine")
IF ltr$ = "8" THEN speak ("ate")
IF ltr$ = "7" THEN speak ("seven")
IF ltr$ = "6" THEN speak ("six")
IF ltr$ = "5" THEN speak ("five")
IF ltr$ = "4" THEN speak ("for")
IF ltr$ = "3" THEN speak ("three")
IF ltr$ = "2" THEN speak ("to")
IF ltr$ = "1" THEN speak ("wun")
' end of numbers
  IF wc >= wpl THEN reader = 0: ltr$ = "": rword$ = ""
  IF wpl = 1 THEN word$ = "": rword$ = "": ltr$ = ""

  ltr$ = ""
 IF say$ <> "" THEN PLAYWAV "c:\windows\sound\qbspeech\" + say$ + ".wav"
'  PRINT say$
  say$ = ""
NEXT wc

 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

DEFINT A-Z
'------------------------------------------------------------------------------
SUB ValidWavHeader (file$, LenHeader%, dataLen&, nChannels%, nSamplesPerSec&, nAvgBytesPerSec&, ok%)
rID$ = SPACE$(4)
wID$ = SPACE$(4)
fID$ = SPACE$(4)
dat$ = SPACE$(4)
dummy$ = SPACE$(1)

filenum% = FREEFILE
OPEN file$ FOR BINARY AS filenum%
  GET filenum%, , rID$
  GET filenum%, , rLen&
  GET filenum%, , wID$
  GET filenum%, , fID$
  GET filenum%, , fLen&
  GET filenum%, , wFormatTag%       '2 bytes
  GET filenum%, , nChannels%        '2 bytes
  GET filenum%, , nSamplesPerSec&   '4 bytes
  GET filenum%, , nAvgBytesPerSec&  '4 bytes
  GET filenum%, , nBlockAlign%      '2 bytes
  GET filenum%, , FormatSpecific%   '2 bytes
  'Read bytes until have read fLen& total bytes.
  'I have no idea what these next bytes are used for (if they even exist).
  FOR i% = 1 TO fLen& - 16          '16 bytes is what we have read in so far
     GET filenum%, , dummy$         'read in 1 byte at a time
  NEXT i%
  GET filenum%, , dat$
  IF UCASE$(dat$) = "FACT" THEN
     'funny format...
     GET filenum%, , dummy&
     GET filenum%, , dummy&
     GET filenum%, , dat$
  END IF
  GET filenum%, , dataLen&
  LenHeader% = LOC(1)
CLOSE filenum%
'  PRINT rID$;
'  PRINT rLen&;
'  PRINT wID$;
'  PRINT fID$;
'  PRINT fLen&;
'  PRINT wFormatTag%;       '2 bytes
'  PRINT nChannels%;        '2 bytes
'  PRINT nSamplesPerSec&;   '4 bytes
'  PRINT nAvgBytesPerSec&;  '4 bytes
'  PRINT nBlockAlign%;      '2 bytes
'  PRINT FormatSpecific%;   '2 bytes
'  PRINT dat$;
'  PRINT dataLen&;
'  PRINT LenHeader%
IF UCASE$(rID$) = "RIFF" THEN
   IF UCASE$(wID$) = "WAVE" THEN
      IF UCASE$(dat$) = "DATA" THEN
         IF UCASE$(fID$) = "FMT " THEN
           IF FormatSpecific% = 8 THEN ok% = -1
         END IF
      END IF
   END IF
END IF
END SUB

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

DEFINT A-Z
'------------------------------------------------------------------------------
SUB WriteToDSP (v%)
DO
LOOP UNTIL (INP(BlasterAddr% + &HC) AND 128) = 0
OUT BlasterAddr% + &HC, v%
END SUB

