
DECLARE SUB phonix (phr$)
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 SUB Intro (start%())
DECLARE SUB happy ()
DECLARE SUB sad ()
DECLARE SUB GetWords (length%(), Saved%())
DECLARE SUB Compare (y%, yp%, Sample%(), Saved%(), length%(), Score%(), samplen%, SampleTmp%())
DECLARE FUNCTION GetBlasterAddr% ()
DECLARE FUNCTION SBreset% ()

COMMON SHARED BlasterAddr%, dma%, repeats%

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

DEFINT A-Z

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)

speak ("hello")

CALL GetWords(length(), Saved())
SCREEN 9, 0, 1
10
CLS
delay1 = 20
Linedelay = 50
Starty = 0
y = 100
Sct = 0
yp = 4

COLOR 15
LOCATE 5, 30: PRINT "Say Happy or Sad..."
PCOPY 1, 0

FOR a = 1 TO 20000: OUT CommAddr, &H20: s = INP(DataAddr): NEXT a

'CLS
DO
  OUT CommAddr, &H20
 
  Byte = INP(DataAddr)
  Byte = Byte - 128

  IF Byte < 5 AND Byte > -5 THEN Byte = 0 ELSE Starty = 1: Nullfor = 0
  IF Byte = 0 AND Starty = 1 THEN Nullfor = Nullfor + 1
 
  IF Starty = 1 THEN i& = i& + 1: j = i& / delay1
                
  IF Starty = 1 AND Nullfor >= 1500 THEN
        CALL Compare(y, yp, Sample(), Saved(), length(), Score(), Sct - 1, SampleTmp())
        'DO: LOOP WHILE INKEY$ = ""
        FOR a = 0 TO 1: Score(a) = 0: NEXT a
        Starty = 0: y = y + 100: i& = 0: j = 0: Nullfor = 0
        'yp = yp + 6
        'IF y > 400 THEN CLS : y = 100: yp = 4
        Sct = 0: ct = 0
  END IF

  IF Starty = 1 THEN ct = ct + 1
  IF Starty = 1 AND ct > Linedelay THEN
        Sample(Sct) = m: Sct = Sct + 1
        IF Sct > 200 THEN Sct = 200
        maxold = max: max = m: ct = 0: m = 0
        ELSE
        IF Byte > m THEN m = Byte
  END IF
        
LOOP WHILE INKEY$ = ""
SYSTEM
END

happy:
DATA 8
DATA 11
DATA 14
DATA 15
DATA 20
DATA 23
DATA 25
DATA 25
DATA 23
DATA 22
DATA 23
DATA 24
DATA 17

sad:
DATA 6
DATA 4
DATA 4
DATA 1
DATA 4
DATA 4
DATA 6
DATA 6
DATA 14
DATA 17
DATA 19
DATA 21
DATA 18
DATA 18
DATA 17
DATA 15
DATA 14
DATA 14
DATA 11
DATA 11
DATA 11
DATA 11
DATA 11
DATA 10
DATA 9
DATA 8
DATA 6
DATA 3

c:
DATA 10,0
DATA 50,0
DATA 60,10
DATA 60,20
DATA 50,20
DATA 40,10
DATA 20,10
DATA 10,20
DATA 10,60
DATA 20,70
DATA 40,70
DATA 50,60
DATA 50,60
DATA 60,60
DATA 60,70
DATA 50,80
DATA 10,80
DATA 0,70
DATA 0,10
DATA 10,0

e:
DATA 0,0
DATA 50,0
DATA 50,10
DATA 10,10
DATA 10,35
DATA 30,35
DATA 30,45
DATA 10,45
DATA 10,70
DATA 50,70
DATA 50,80
DATA 0,80
DATA 0,0

n:
DATA 0,0
DATA 40,50
DATA 40,0
DATA 50,0
DATA 50,80
DATA 10,30
DATA 10,80
DATA 0,80
DATA 0,0

t:
DATA 0,0
DATA 50,0
DATA 50,10
DATA 30,10
DATA 30,80
DATA 20,80
DATA 20,10
DATA 0,10
DATA 0,0

m:
DATA 0,0
DATA 10,0
DATA 25,20
DATA 40,0
DATA 50,0
DATA 50,80
DATA 40,80
DATA 40,20
DATA 25,40
DATA 10,20
DATA 10,80
DATA 0,80
DATA 0,0

o1:
DATA 10,0
DATA 40,0
DATA 50,10
DATA 50,70
DATA 40,80
DATA 10,80
DATA 0,70
DATA 0,10
DATA 10,0

o2:
DATA 20,10
DATA 30,10
DATA 40,20
DATA 40,60
DATA 30,70
DATA 20,70
DATA 10,60
DATA 10,20
DATA 20,10

SUB Compare (y, yp, Sample(), Saved(), length(), Score(), samplen, SampleTmp())

FOR a = 0 TO 1

        FOR b = 0 TO 200: SampleTmp(b) = 0: NEXT b

        Started = 0                                   'TAKE AWAY ENDING BLANK
        FOR b = samplen TO 0 STEP -1
        IF Started = 0 AND Sample(b) = 0 THEN samplen = samplen - 1 ELSE Started = 1
        NEXT b
       
        IF samplen <= 0 THEN samplen = 1

        Squish! = samplen / length(a)
        ct = 0
        FOR a! = 0 TO length(a) * Squish! STEP Squish!   'MAKE SAME DURATION
        SampleTmp(ct) = Sample(CINT(a!))                 'AS SAVED SAMPLE
        ct = ct + 1
        NEXT a!

        'IF a = 0 THEN col = 9 ELSE col = 5
        'FOR b = 0 TO Length(a) - 1
        'LINE (((a + 1) * 170) + (b * 5), y - Saved(a, b))-(((a + 1) * 170) + ((b * 5) + 5), y - Saved(a, b + 1)), col
        'LINE (((a + 1) * 170) + (b * 5), y - SampleTmp(b))-(((a + 1) * 170) + ((b * 5) + 5), y - SampleTmp(b + 1)), 14
        'NEXT b

        FOR b = 0 TO length(a)
                adder = SampleTmp(b) - Saved(a, b)
                IF adder < 0 THEN adder = adder * -1
                Score(a) = Score(a) + adder
        NEXT b
NEXT a




IF Score(0) < Score(1) THEN CALL happy
IF Score(1) < Score(0) THEN CALL sad
'IF Score(0) < Score(1) THEN COLOR 9: PRINT "You said HAPPY"
'IF Score(1) <= Score(0) THEN COLOR 4: PRINT "You said SAD"
'PRINT
COLOR 15
LOCATE 5, 30: PRINT "Say Happy or Sad..."
PCOPY 1, 0
END SUB

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

'------------------------------------------------------------------------------
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

SUB GetWords (length(), Saved())

delay1 = 20
Linedelay = 50

SCREEN 12
CLS

y = 170
filenum = -1
20
filenum = filenum + 1
IF filenum = 2 THEN 131
IF filenum = 0 THEN LOCATE 2, 7: COLOR 7: PRINT "Say "; CHR$(34): COLOR 15: LOCATE 2, 12: PRINT "HAPPY": COLOR 7: LOCATE 2, 17: PRINT CHR$(34); " now please..."
IF filenum = 1 THEN LOCATE 16, 7: COLOR 7: PRINT "Say "; CHR$(34): COLOR 15: LOCATE 16, 12: PRINT "SAD": COLOR 7: LOCATE 16, 15: PRINT CHR$(34); " now please..."

FOR a = 1 TO 5000              'delay MIC INPUT TO GET RID OF SPIKE
OUT CommAddr, &H20
Byte = INP(DataAddr)
NEXT a

DO
 'CALL GetByte(Byte, start, Nullfor)
        LOCATE 1, 1
        PRINT Byte
        PRINT start
        PRINT Nullfor
        OUT CommAddr, &H20
        Byte = INP(DataAddr)
        Byte = Byte - 128
        IF Byte < 5 AND Byte > -5 THEN Byte = 0 ELSE start = 1: Nullfor = 0
        IF Byte = 0 AND start = 1 THEN Nullfor = Nullfor + 1


 IF start = 1 THEN x& = x& + 1: Xscreen = (x& / delay1) + 50
 IF x& > 5900 THEN x& = 5900
 IF start = 1 AND Nullfor >= 1500 THEN
        'CALL Done(Sample(), Temp(), filenum)
                ct = 0
                Started = 0
                FOR a = 0 TO 100                  'TAKE AWAY BEGINNING BLANK
                IF Started = 0 THEN
                        IF Saved(filenum, a) > 0 THEN Saved(filenum, ct) = Saved(filenum, a): ct = ct + 1: Started = 1
                ELSE
                        Saved(filenum, ct) = Saved(filenum, a): ct = ct + 1
                END IF
                NEXT a
                length(filenum) = ct - 1
                Started = 0
                FOR a = length(filenum) TO 0 STEP -1          'TAKE AWAY ENDING BLANK
                        IF Started = 0 AND Saved(filenum, a) = 0 THEN length(filenum) = length(filenum) - 1 ELSE Started = 1
                NEXT a
           
        y = y + 190
        start = 0
        m = 0
        x& = 0
        Xscreen = 0
        Nullfor = 0
        Sct = 0
        ct = 0
        GOTO 20
 END IF

 IF start = 1 THEN ct = ct + 1
 IF start = 1 AND ct > Linedelay THEN
   Saved(filenum, Sct) = m: Sct = Sct + 1
   IF Sct > 100 THEN Sct = 100
   maxold = max: max = m: ct = 0: m = 0
  ELSE
   IF Byte > m THEN m = Byte
 END IF
        
 IF Xscreen > 5 THEN
        PSET (Xscreen, Byte + y)
        IF ct = 0 THEN LINE (Xscreen - (Linedelay / delay1), y - maxold)-(Xscreen, y - max), 14
 END IF
LOOP WHILE INKEY$ = ""

131
y = 170

'PRINT length(0), length(1)

FOR a = 0 TO 1
        IF a = 1 THEN y = y + 190
        y1 = Saved(a, 0)
        x = 400
        IF length(a) < 1 THEN 12
        FOR b = 1 TO length(a)
                y2 = Saved(a, b)
                LINE (x, y - y1)-(x + (200 / length(a)), y - y2), 2
                IF length(a) > 0 THEN x = x + (200 / length(a))
                y1 = y2
        NEXT b
12
NEXT a

LOCATE 28, 1
COLOR 15: PRINT "Voice prints memorised...press any key to continue"
DO: LOOP WHILE INKEY$ = ""



END SUB

SUB happy


CLS
COLOR 14: LOCATE 7, 38: PRINT "HAPPY": COLOR 15
CIRCLE (320, 175), 80, 14
LINE (280, 150)-(300, 160), 14
LINE (360, 150)-(340, 160), 14
CIRCLE (320, 179), 6, 4
PAINT (320, 179), 4
CIRCLE (320, 185), 50, 14, 4.2, 0
CIRCLE (368, 200), 20, 14, 1.1, 1.9

PCOPY 1, 0

t! = TIMER: DO: LOOP UNTIL TIMER - t! > .6
CLS
PCOPY 1, 0
END SUB

DEFSNG A-Z
SUB phonix (phr$)

 rword$ = ""
 phr$ = phr$ + " "
 phr$ = LCASE$(phr$)


   lsize = LEN(phr$)
 
   WHILE lp = 0

 
   FOR lc = 1 TO lsize
   IF lc = lsize THEN lp = 1
   LETR$ = MID$(phr$, lc, 1)
 
   IF LETR$ = "," THEN CALL playwav("c:\windows\sound\qbspeech\" + PH$ + ".WAV"): PH$ = "": LETR$ = ""
 
   IF PH$ <> CHR$(32) THEN PH$ = PH$ + LETR$


 
   NEXT lc

 WEND
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
SUB sad


CLS
COLOR 14: LOCATE 7, 39: PRINT "SAD": COLOR 15
CIRCLE (320, 175), 80, 14
LINE (280, 150)-(310, 170), 14
LINE (360, 150)-(330, 170), 14
CIRCLE (320, 179), 6, 4
PAINT (320, 179), 4
CIRCLE (320, 205), 50, 14, 0, 3.14, .2

PCOPY 1, 0

t! = TIMER: DO: LOOP UNTIL TIMER - t! > .6
CLS
PCOPY 1, 0

END SUB

'------------------------------------------------------------------------------
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

' 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
'
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

'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")
' 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")
IF ltr$ = "+" THEN CALL speak("PLUS")
IF ltr$ = "-" THEN CALL speak("miin us")
IF ltr$ = "*" THEN CALL speak("tiims")
IF ltr$ = "/" THEN CALL speak("diviid ed by")
IF ltr$ = "=" THEN CALL speak("e qwuals")
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

'------------------------------------------------------------------------------
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

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

