Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
SAM native QB64PE speech synthesizer, port from C (v0.2.1), fixed design-time errors
#1
I did some editing and at least got the IDE to stop complaining with design-time errors.
There are a zillion things to fix and figure out before it's working though, but it's a step closer.
I leave this is the capable hands of anyone looking for a challenge! LOL

The original C project this is attempting to recreate: which is a fork of
Earlier posts:
The latest code is below. Attached ZIP file contains some assets (text files) some of the test routines use (haven't figured that part out yet). 

Code: (Select All)
' ################################################################################################################################################################
' SAM "SOFTWARE AUTOMATIC MOUTH"
' A native speech synthesizer for QB64PE
' version 0.2.1

' Translated by from C to QB64, from the bit-hack project at:
'
'     https://github.com/bit-hack/SAM
'
' which is a fork of Sebastian Macke's project at:
'   
'     https://github.com/s-macke/SAM

' TO DO:
' * Initial translation was done by free ai, so lots of errors and bugs to fix!
' * Replace sound generation code with QB64PE sound commands
' * Get it working (TBD?)

' ################################################################################################################################################################

' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' FROM sam.c

' Global variables (equivalent to C globals)

'Declare arrays -  Need to determine actual sizes from original C code or context
Const cMaxPhonemes = 256 ' Example size, adjust as needed

Dim Shared m_ProgramPath$: m_ProgramPath$ = Left$(Command$(0), _InStrRev(Command$(0), "\"))
Dim Shared m_ProgramName$: m_ProgramName$ = Mid$(Command$(0), _InStrRev(Command$(0), "\") + 1)

Dim Shared A As _Unsigned _Byte ' or is it _BYTE ?
Dim Shared X As _Byte
Dim Shared Y As _Byte

' TODO: NEED TO RECONCILE inputtemp() vs TempInput$
'       BECAUSE NOT SURE IF Gemini CONVERTED CORRECTLY
'       IN SOME PLACES WE HAVE inputtemp LOOKING LIKE A STRING:
'           A = ASC(MID$(inputtemp, X + 1, 1))  ' Corrected index
'           inputtemp = SPACE$(256) ' Assuming inputtemp is a string, adjust size as needed
'           inputtemp = " " + inputtemp[0] = 0x20; // '
'       SO WE REPLACED inputtemp WITH TempInput$
'       IT IS REFERENCED IN
'           FUNCTION TextToPhonemes& (sInput AS STRING, max_size AS LONG)
'       WHICH CALLS ROUTINE
'           Function TestFlagDec~% (mem59 As Integer, mask As Long)
'       WHICH REFERENCES IT
'           A = ASC(MID$(TempInput$, X + 1, 1))  'QB64: Access char in string, ASC gets ASCII value
'       BUT IT'S NOT A PARAMETER OR DECLARED, SO DO WE ASSUME GLOBAL?
'       BUT THEN IN OTHER PLACES WE HAVE
'           A = inputtemp(X)
'       WHICH LOOKS LIKE inputtemp IS A NUMERIC ARRAY ?
'       SO TOTALLY CONFUSED ABOUT
'       - WHAT TYPE IT IS
'       - WHETHER IT'S ONE VARIABLE OR 2 OR MORE DIFFERENT VARIABLES
'       - WHETHER IT'S GLOBAL OR LOCAL IN SCOPE
Dim Shared TempInput$

Dim Shared bDebug As Integer ' FROM debug.h, int32_t becomes INTEGER in QB64

ReDim arrAmp1Data(78) As _Byte
ReDim arrAmp2Data(78) As _Byte
ReDim arrAmp3Data(78) As _Byte
ReDim arrAmplitudeRescale As _Byte ' Equivalent to uint8_t[]
ReDim arrBlendRank As _Byte ' Equivalent to uint8_t[]
ReDim arrFlags1(0 To 66) As _Unsigned _Byte
ReDim arrFlags2(0 To 61) As _Unsigned _Byte
ReDim arrFreq1Data(71) As _Unsigned _Byte ' ReDim arrFreq1Data(53) As _Byte
ReDim arrFreq2Data(79) As _Unsigned _Byte ' ReDim arrFreq2Data(53) As _Byte
ReDim arrFreq3Data(62) As _Unsigned _Byte
ReDim arrInBlendLength(95) As _Unsigned _Byte
ReDim arrInput1(256) As _Byte ' [256]  'int8_t becomes _BYTE in QB64
ReDim arrMouthFormants48_53(5) As _Byte
ReDim arrMouthFormants5_29(29) As _Byte
ReDim arrMultTable(255) As _Byte ' QB64 uses byte for unsigned 8-bit
ReDim arrOutBlendLength(95) As _Unsigned _Byte
ReDim arrPhoIndexOutput(59) As _Byte ' [60] 'uint8_t to _BYTE
ReDim arrPhoLengthOutput(59) As _Byte ' [60] 'uint8_t to _BYTE
ReDim arrPhoLengthTable(0 To 61) As _Unsigned _Byte
ReDim arrPhonemeIndex(cMaxPhonemes) As _Unsigned _Byte ' DIM arrPhonemeIndex[256] AS _BYTE ' uint8_t to _BYTE
ReDim arrPhonemeLength(cMaxPhonemes) As _Byte ' [256] 'uint8_t to _BYTE
ReDim arrPhoStressedLengthTable(0 To 61) As _Unsigned _Byte
ReDim arrPitches(255) As _Byte ' Assuming a maximum size of 255 for pitches
ReDim arrRectangle(143) As _Unsigned _Byte
ReDim arrRules(0 To 150) As String
ReDim arrRuleTab(0 To 27) As Integer
ReDim arrSampledConsonantFlags(79) As _Unsigned _Byte
ReDim arrSampleTable(0 To 1279) As _Byte '0x500 = 1280
ReDim arrSignInputTable1(89) As String ' _Unsigned _Byte
ReDim arrSignInputTable2(55) As String ' _Unsigned _Byte
ReDim arrSinus(180) As _Unsigned _Byte
ReDim arrStress1(cMaxPhonemes) As _Unsigned _Byte ' DIM arrStress1 AS _BYTE ' [256] 'uint8_t to _BYTE
ReDim arrStressInputTable(9) As String ' DIM stressInputTable AS STRING * 9 ' Fixed-length string to hold the characters
ReDim arrStressOutput(59) As _Byte ' [60] 'uint8_t to _BYTE
ReDim arrTab36376(0 To 288) As _Unsigned _Byte
ReDim arrTab47492 As _Byte ' Equivalent to uint8_t[]
ReDim arrTab48426(4) As _Byte ' Equivalent to uint8_t[5]
ReDim arrThroatFormants48_53(5) As _Byte
ReDim arrThroatFormants5_29(29) As _Byte
Dim buffer As _Offset ' Final sound buffer, int8_t* to _OFFSET (pointer)
Dim bufferPos As Integer ' Final sound buffer, int32_t to Integer
Dim iIndex As Long
Dim iSize As Integer
Dim mem39 As _Byte
Dim mem44 As _Byte
Dim mem47 As _Byte
Dim mem48 As _Byte
Dim mem49 As _Byte 'uint8_t to _BYTE
Dim mem50 As _Byte
Dim mem51 As _Byte
Dim mem53 As _Byte
Dim mem56 As _Byte 'uint8_t to _BYTE
Dim mem59 As _Byte 'uint8_t to _BYTE
Dim mouth As _Byte 'uint8_t becomes _BYTE
Dim phase1 As _Byte
Dim pitch As _Byte 'uint8_t becomes _BYTE
Dim singmode As Integer 'int32_t becomes Integer
Dim speed As _Byte 'uint8_t becomes _BYTE
Dim tab40682$
Dim tab40763$
Dim throat As _Byte 'uint8_t becomes _BYTE

' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' BEGIN reciter_tabs.h
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' Some flags
'
'  0x01        numeric
'  0x02        rule set 2
'  0x04        D J L N
'  0x08        B D G J L M N R V W Z
'  0x10        C G J S X Z R S T Z
'  0x20        B C D F G H J K L M N P Q R S T V X Y Z
'  0x40        is vowel + Y
'  0x80        alpha or '

' Not sure this was converted right,
' the values assigned to array arrTab36376()
' in the original C code are below,
' not sure what notation that is
' or what the equivalent in QB64 should be?

' Value                                | ASCII character
' ------------------------------------ | ---------------
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (space char)
' 0 | 0x02                             | !
' 0 | 0x02                             | "
' 0 | 0x02                             | #
' 0 | 0x02                             | $
' 0 | 0x02                             | %
' 0 | 0x02                             | &
' 0 | 0x80 | 0x02                      | '
' 0                                    | (
' 0                                    | )
' 0 | 0x02                             | *
' 0 | 0x02                             | +
' 0 | 0x02                             | ,
' 0 | 0x02                             | -
' 0 | 0x02                             | .
' 0 | 0x02                             | /
' 0 | 0x02 | 0x01                      | 0
' 0 | 0x02 | 0x01                      | 1
' 0 | 0x02 | 0x01                      | 2
' 0 | 0x02 | 0x01                      | 3
' 0 | 0x02 | 0x01                      | 4
' 0 | 0x02 | 0x01                      | 5
' 0 | 0x02 | 0x01                      | 6
' 0 | 0x02 | 0x01                      | 7
' 0 | 0x02 | 0x01                      | 8
' 0 | 0x02 | 0x01                      | 9
' 0 | 0x02                             | :
' 0 | 0x02                             | ;
' 0 | 0x02                             | <
' 0 | 0x02                             | =
' 0 | 0x02                             | >
' 0 | 0x02                             | ?
' 0 | 0x02                             | @
' 0 | 0x80 | 0x40                      | A
' 0 | 0x80 | 0x20 | 0x08               | B
' 0 | 0x80 | 0x20 | 0x10               | C
' 0 | 0x80 | 0x20 | 0x08 | 0x04        | D
' 0 | 0x80 | 0x40                      | E
' 0 | 0x80 | 0x20                      | F
' 0 | 0x80 | 0x20 | 0x10 | 0x08        | G
' 0 | 0x80 | 0x20                      | H
' 0 | 0x80 | 0x40                      | I
' 0 | 0x80 | 0x20 | 0x10 | 0x08 | 0x04 | J
' 0 | 0x80 | 0x20                      | K
' 0 | 0x80 | 0x20 | 0x08 | 0x04        | L
' 0 | 0x80 | 0x20 | 0x08               | M
' 0 | 0x80 | 0x20 | 0x08 | 0x04        | N
' 0 | 0x80 | 0x40                      | O
' 0 | 0x80 | 0x20                      | P
' 0 | 0x80 | 0x20                      | Q
' 0 | 0x80 | 0x20 | 0x08 | 0x04        | R
' 0 | 0x80 | 0x20 | 0x10 | 0x04        | S
' 0 | 0x80 | 0x20 | 0x04               | T
' 0 | 0x80 | 0x40                      | U
' 0 | 0x80 | 0x20 | 0x08               | V
' 0 | 0x80 | 0x20 | 0x08               | W
' 0 | 0x80 | 0x20 | 0x10               | X
' 0 | 0x80 | 0x40                      | Y
' 0 | 0x80 | 0x20 | 0x10 | 0x08 | 0x04 | Z
' 0                                    | [
' 0                                    | \
' 0                                    | ]
' 0 | 0x02                             | ^
' 0                                    | _
' 0 | 0x20 | 0x02                      | `

Data 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Data 0,0,0,0,0,0,0,0,2,0,2,0,2,0,2,0,2,130,0,0,2,0,2,0
Data 2,0,2,2,1,2,1,2,1,2,1,2,1,2,2,0,2,0,2,0,2,0,2,0
Data 130,64,130,32,8,130,32,16,130,32,8,4,130,64,130,32,130
Data 32,16,8,130,64,130,32,8,4,130,64,130,32,16,8,4,130,32,4
Data 130,32,8,130,32,8,4,130,64,130,32,130,32,4,130,32,8,4
Data 130,32,16,4,130,64,130,32,130,32,8,130,32,8,130,32,4,130
Data 64,130,32,8,4,130,32,16,4,130,64,130,32,16,8,4,130,64,130
Data 32,8,4,130,32,4,130,64,130,32,8,130,32,8,130,32,16,130,64
Data 130,32,16,8,4,130,64,130,32,16,8,4,130,32,4,130,64,130,32
Data 8,130,32,8,130,32,16,130,64,130,32,16,8,4,130,0,0,0,2,0
Data 32,2

For iIndex = 0 To 288
    'redim _preserve arrTab36376( ubound(tab36376)+1 )
    Read arrTab36376(iIndex)
Next iIndex

ReDim arrRules(0 To 150) As String
arrRules(0) = "]\xc1" ' "]A"
arrRules(1) = " (A.)=EH4Y.\xa0" ' " (A.)=EH4Y. "
arrRules(2) = "(A) =A\xc8" ' "(A) =AH"
arrRules(3) = " (ARE) =AA\xd2" ' " (ARE) =AAR"
arrRules(4) = " (AR)O=AX\xd2" ' " (AR)O=AXR"
arrRules(5) = "(AR)#=EH4\xd2" ' "(AR)#=EH4R"
arrRules(6) = " ^(AS)#=EY4\xd3" ' " ^(AS)#=EY4S"
arrRules(7) = "(A)WA=A\xd8" ' "(A)WA=AX"
arrRules(8) = "(AW)=AO\xb5" ' "(AW)=AO5"
arrRules(9) = " :(ANY)=EH4NI\xd9" ' " :(ANY)=EH4NIY"
arrRules(10) = "(A)^+#=EY\xb5" ' "(A)^+#=EY5"
arrRules(11) = "#:(ALLY)=ULI\xd9" ' "#:(ALLY)=ULIY"
arrRules(12) = " (AL)#=U\xcc" ' " (AL)#=UL"
arrRules(13) = "(AGAIN)=AXGEH4\xce" ' "(AGAIN)=AXGEH4N"
arrRules(14) = "#:(AG)E=IH\xca" ' "#:(AG)E=IHJ"
arrRules(15) = "(A)^%=E\xd9" ' "(A)^%=EY"
arrRules(16) = "(A)^+:#=A\xc5" ' "(A)^+:#=AE"
arrRules(17) = " :(A)^+ =EY\xb4" ' " :(A)^+ =EY4"
arrRules(18) = " (ARR)=AX\xd2" ' " (ARR)=AXR"
arrRules(19) = "(ARR)=AE4\xd2" ' "(ARR)=AE4R"
arrRules(20) = " ^(AR) =AA5\xd2" ' " ^(AR) =AA5R"
arrRules(21) = "(AR)=AA5\xd2" ' "(AR)=AA5R"
arrRules(22) = "(AIR)=EH4\xd2" ' "(AIR)=EH4R"
arrRules(23) = "(AI)=EY\xb4" ' "(AI)=EY4"
arrRules(24) = "(AY)=EY\xb5" ' "(AY)=EY5"
arrRules(25) = "(AU)=AO\xb4" ' "(AU)=AO4"
arrRules(26) = "#:(AL) =U\xcc" ' "#:(AL) =UL"
arrRules(27) = "#:(ALS) =UL\xda" ' "#:(ALS) =ULZ"
arrRules(28) = "(ALK)=AO4\xcb" ' "(ALK)=AO4K"
arrRules(29) = "(AL)^=AO\xcc" ' "(AL)^=AOL"
arrRules(30) = " :(ABLE)=EY4BU\xcc" ' " :(ABLE)=EY4BUL"
arrRules(31) = "(ABLE)=AXBU\xcc" ' "(ABLE)=AXBUL"
arrRules(32) = "(A)VO=EY\xb4" ' "(A)VO=EY4"
arrRules(33) = "(ANG)+=EY4N\xca" ' "(ANG)+=EY4NJ"
arrRules(34) = "(ATARI)=AHTAA4RI\xd9" ' "(ATARI)=AHTAA4RIY"
arrRules(35) = "(A)TOM=A\xc5" ' "(A)TOM=AE"
arrRules(36) = "(A)TTI=A\xc5" ' "(A)TTI=AE"
arrRules(37) = " (AT) =AE\xd4" ' " (AT) =AET"
arrRules(38) = " (A)T=A\xc8" ' " (A)T=AH"
arrRules(39) = "(A)=A\xc5" ' "(A)=AE"
arrRules(40) = "]\xc2" ' "]B"
arrRules(41) = " (B) =BIY\xb4" ' " (B) =BIY4"
arrRules(42) = " (BE)^#=BI\xc8" ' " (BE)^#=BIH"
arrRules(43) = "(BEING)=BIY4IHN\xd8" ' "(BEING)=BIY4IHNX"
arrRules(44) = " (BOTH) =BOW4T\xc8" ' " (BOTH) =BOW4TH"
arrRules(45) = " (BUS)#=BIH4\xda" ' " (BUS)#=BIH4Z"
arrRules(46) = "(BREAK)=BREY5\xcb" ' "(BREAK)=BREY5K"
arrRules(47) = "(BUIL)=BIH4\xcc" ' "(BUIL)=BIH4L"
arrRules(48) = "(B)=\xc2" ' "(B)=B"
arrRules(49) = "]\xc3" ' "]C"
arrRules(50) = " (C) =SIY\xb4" ' " (C) =SIY4"
arrRules(51) = " (CH)^=\xcb" ' " (CH)^=K"
arrRules(52) = "^E(CH)=\xcb" ' "^E(CH)=K"
arrRules(53) = "(CHA)R#=KEH\xb5" ' "(CHA)R#=KEH5"
arrRules(54) = "(CH)=C\xc8" ' "(CH)=CH"
arrRules(55) = " S(CI)#=SAY\xb4" ' " S(CI)#=SAY4"
arrRules(56) = "(CI)A=S\xc8" ' "(CI)A=SH"
arrRules(57) = "(CI)O=S\xc8" ' "(CI)O=SH"
arrRules(58) = "(CI)EN=S\xc8" ' "(CI)EN=SH"
arrRules(59) = "(CITY)=SIHTI\xd9" ' "(CITY)=SIHTIY"
arrRules(60) = "(C)+=\xd3" ' "(C)+=S"
arrRules(61) = "(CK)=\xcb" ' "(CK)=K"
arrRules(62) = "(COMMODORE)=KAA4MAHDOH\xd2" ' "(COMMODORE)=KAA4MAHDOHR"
arrRules(63) = "(COM)=KAH\xcd" ' "(COM)=KAHM"
arrRules(64) = "(CUIT)=KIH\xd4" ' "(CUIT)=KIHT"
arrRules(65) = "(CREA)=KRIYE\xd9" ' "(CREA)=KRIYEY"
arrRules(66) = "(C)=\xcb" ' "(C)=K"
arrRules(67) = "]\xc4" ' "]D"
arrRules(68) = " (D) =DIY\xb4" ' " (D) =DIY4"
arrRules(69) = " (DR.) =DAA4KTE\xd2" ' " (DR.) =DAA4KTER"
arrRules(70) = "#:(DED) =DIH\xc4" ' "#:(DED) =DIHD"
arrRules(71) = ".E(D) =\xc4" ' ".E(D) =D"
arrRules(72) = "#:^E(D) =\xd4" ' "#:^E(D) =T"
arrRules(73) = " (DE)^#=DI\xc8" ' " (DE)^#=DIH"
arrRules(74) = " (DO) =DU\xd7" ' " (DO) =DUW"
arrRules(75) = " (DOES)=DAH\xda" ' " (DOES)=DAHZ"
arrRules(76) = "(DONE) =DAH5\xce" ' "(DONE) =DAH5N"
arrRules(77) = "(DOING)=DUW4IHN\xd8" ' "(DOING)=DUW4IHNX"
arrRules(78) = " (DOW)=DA\xd7" ' " (DOW)=DAW"
arrRules(79) = "#(DU)A=JU\xd7" ' "#(DU)A=JUW"
arrRules(80) = "#(DU)^#=JA\xd8" ' "#(DU)^#=JAX"
arrRules(81) = "(D)=\xc4" ' "(D)=D"
arrRules(82) = "]\xc5" ' "]E"
arrRules(83) = " (E) =IYIY\xb4" ' " (E) =IYIY4"
arrRules(84) = "#:(E) \xbd" ' "#:(E) ="
arrRules(85) = "\\':^(E) \xbd" ' "\\':^(E) ="
arrRules(86) = " :(E) =I\xd9" ' " :(E) =IY"
arrRules(87) = "#(ED) =\xc4" ' "#(ED) =D"
arrRules(88) = "#:(E)D \xbd" ' "#:(E)D ="
arrRules(89) = "(EV)ER=EH4\xd6" ' "(EV)ER=EH4V"
arrRules(90) = "(E)^%=IY\xb4" ' "(E)^%=IY4"
arrRules(91) = "(ERI)#=IY4RI\xd9" ' "(ERI)#=IY4RIY"
arrRules(92) = "(ERI)=EH4RI\xc8" ' "(ERI)=EH4RIH"
arrRules(93) = "#:(ER)#=E\xd2" ' "#:(ER)#=ER"
arrRules(94) = "(ERROR)=EH4ROH\xd2" ' "(ERROR)=EH4ROHR"
arrRules(95) = "(ERASE)=IHREY5\xd3" ' "(ERASE)=IHREY5S"
arrRules(96) = "(ER)#=EH\xd2" ' "(ER)#=EHR"
arrRules(97) = "(ER)=E\xd2" ' "(ER)=ER"
arrRules(98) = " (EVEN)=IYVEH\xce" ' " (EVEN)=IYVEHN"
arrRules(99) = "#:(E)W\xbd" ' "#:(E)W="
arrRules(100) = "@(EW)=U\xd7" ' "@(EW)=UW"
arrRules(101) = "(EW)=YU\xd7" ' "(EW)=YUW"
arrRules(102) = "(E)O=I\xd9" ' "(E)O=IY"
arrRules(103) = "#:&(ES) =IH\xda" ' "#:&(ES) =IHZ"
arrRules(104) = "#:(E)S \xbd" ' "#:(E)S ="
arrRules(105) = "#:(ELY) =LI\xd9" ' "#:(ELY) =LIY"
arrRules(106) = "#:(EMENT)=MEHN\xd4" ' "#:(EMENT)=MEHNT"
arrRules(107) = "(EFUL)=FUH\xcc" ' "(EFUL)=FUHL"
arrRules(108) = "(EE)=IY\xb4" ' "(EE)=IY4"
arrRules(109) = "(EARN)=ER5\xce" ' "(EARN)=ER5N"
arrRules(110) = " (EAR)^=ER\xb5" ' " (EAR)^=ER5"
arrRules(111) = "(EAD)=EH\xc4" ' "(EAD)=EHD"
arrRules(112) = "#:(EA) =IYA\xd8" ' "#:(EA) =IYAX"
arrRules(113) = "(EA)SU=EH\xb5" ' "(EA)SU=EH5"
arrRules(114) = "(EA)=IY\xb5" ' "(EA)=IY5"
arrRules(115) = "(EIGH)=EY\xb4" ' "(EIGH)=EY4"
arrRules(116) = "(EI)=IY\xb4" ' "(EI)=IY4"
arrRules(117) = " (EYE)=AY\xb4" ' " (EYE)=AY4"
arrRules(118) = "(EY)=I\xd9" ' "(EY)=IY"
arrRules(119) = "(EU)=YUW\xb5" ' "(EU)=YUW5"
arrRules(120) = "(EQUAL)=IY4KWU\xcc" ' "(EQUAL)=IY4KWUL"
arrRules(121) = "(E)=E\xc8" ' "(E)=EH"
arrRules(122) = "]\xc6" ' "]F"
arrRules(123) = " (F) =EH4\xc6" ' " (F) =EH4F"
arrRules(124) = "(FUL)=FUH\xcc" ' "(FUL)=FUHL"
arrRules(125) = "(FRIEND)=FREH5N\xc4" ' "(FRIEND)=FREH5ND"
arrRules(126) = "(FATHER)=FAA4DHE\xd2" ' "(FATHER)=FAA4DHER"
arrRules(127) = "(F)F\xbd" ' "(F)F="
arrRules(128) = "(F)=\xc6" ' "(F)=F"
arrRules(129) = "]\xc7" ' "]G"
arrRules(130) = " (G) =JIY\xb4" ' " (G) =JIY4"
arrRules(131) = "(GIV)=GIH5\xd6" ' "(GIV)=GIH5V"
arrRules(132) = " (G)I^=\xc7" ' " (G)I^=G"
arrRules(133) = "(GE)T=GEH\xb5" ' "(GE)T=GEH5"
arrRules(134) = "SU(GGES)=GJEH4\xd3" ' "SU(GGES)=GJEH4S"
arrRules(135) = "(GG)=\xc7" ' "(GG)=G"
arrRules(136) = " B#(G)=\xc7" ' " B#(G)=G"
arrRules(137) = "(G)+=\xca" ' "(G)+=J"
arrRules(138) = "(GREAT)=GREY4\xd4" ' "(GREAT)=GREY4T"
arrRules(139) = "(GON)E=GAO5\xce" ' "(GON)E=GAO5N"
arrRules(140) = "#(GH)\xbd" ' "#(GH)="
arrRules(141) = " (GN)=\xce" ' " (GN)=N"
arrRules(142) = "(G)=\xc7" ' "(G)=G"
arrRules(143) = "]\xc8" ' "]H"
arrRules(144) = " (H) =EY4C\xc8" ' " (H) =EY4CH"
arrRules(145) = " (HAV)=/HAE6\xd6" ' " (HAV)=/HAE6V"
arrRules(146) = " (HERE)=/HIY\xd2" ' " (HERE)=/HIYR"
arrRules(147) = " (HOUR)=AW5E\xd2" ' " (HOUR)=AW5ER"
arrRules(148) = "(HOW)=/HA\xd7" ' "(HOW)=/HAW"
arrRules(149) = "(H)#=/\xc8" ' "(H)#=/H"
arrRules(150) = "(H)\xbd" ' "(H)="
arrRules(151) = "]\xc9" ' "]I"
arrRules(152) = " (IN)=IH\xce" ' " (IN)=IHN"
arrRules(153) = " (I) =AY\xb4" ' " (I) =AY4"
arrRules(154) = "(I) =A\xd9" ' "(I) =AY"
arrRules(155) = "(IN)D=AY5\xce" ' "(IN)D=AY5N"
arrRules(156) = "SEM(I)=I\xd9" ' "SEM(I)=IY"
arrRules(157) = " ANT(I)=A\xd9" ' " ANT(I)=AY"
arrRules(158) = "(IER)=IYE\xd2" ' "(IER)=IYER"
arrRules(159) = "#:R(IED) =IY\xc4" ' "#:R(IED) =IYD"
arrRules(160) = "(IED) =AY5\xc4" ' "(IED) =AY5D"
arrRules(161) = "(IEN)=IYEH\xce" ' "(IEN)=IYEHN"
arrRules(162) = "(IE)T=AY4E\xc8" ' "(IE)T=AY4EH"
arrRules(163) = "(I\\')=AY\xb5" ' "(I\\')=AY5"
arrRules(164) = " :(I)^%=AY\xb5" ' " :(I)^%=AY5"
arrRules(165) = " :(IE) =AY\xb4" ' " :(IE) =AY4"
arrRules(166) = "(I)%=I\xd9" ' "(I)%=IY"
arrRules(167) = "(IE)=IY\xb4" ' "(IE)=IY4"
arrRules(168) = " (IDEA)=AYDIY5A\xc8" ' " (IDEA)=AYDIY5AH"
arrRules(169) = "(I)^+:#=I\xc8" ' "(I)^+:#=IH"
arrRules(170) = "(IR)#=AY\xd2" ' "(IR)#=AYR"
arrRules(171) = "(IZ)%=AY\xda" ' "(IZ)%=AYZ"
arrRules(172) = "(IS)%=AY\xda" ' "(IS)%=AYZ"
arrRules(173) = "I^(I)^#=I\xc8" ' "I^(I)^#=IH"
arrRules(174) = "+^(I)^+=A\xd9" ' "+^(I)^+=AY"
arrRules(175) = "#:^(I)^+=I\xc8" ' "#:^(I)^+=IH"
arrRules(176) = "(I)^+=A\xd9" ' "(I)^+=AY"
arrRules(177) = "(IR)=E\xd2" ' "(IR)=ER"
arrRules(178) = "(IGH)=AY\xb4" ' "(IGH)=AY4"
arrRules(179) = "(ILD)=AY5L\xc4" ' "(ILD)=AY5LD"
arrRules(180) = " (IGN)=IHG\xce" ' " (IGN)=IHGN"
arrRules(181) = "(IGN) =AY4\xce" ' "(IGN) =AY4N"
arrRules(182) = "(IGN)^=AY4\xce" ' "(IGN)^=AY4N"
arrRules(183) = "(IGN)%=AY4\xce" ' "(IGN)%=AY4N"
arrRules(184) = "(ICRO)=AY4KRO\xc8" ' "(ICRO)=AY4KROH"
arrRules(185) = "(IQUE)=IY4\xcb" ' "(IQUE)=IY4K"
arrRules(186) = "(I)=I\xc8" ' "(I)=IH"
arrRules(187) = "]\xca" ' "]J"
arrRules(188) = " (J) =JEY\xb4" ' " (J) =JEY4"
arrRules(189) = "(J)=\xca" ' "(J)=J"
arrRules(190) = "]\xcb" ' "]K"
arrRules(191) = " (K) =KEY\xb4" ' " (K) =KEY4"
arrRules(192) = " (K)N\xbd" ' " (K)N="
arrRules(193) = "(K)=\xcb" ' "(K)=K"
arrRules(194) = "]\xcc" ' "]L"
arrRules(195) = " (L) =EH4\xcc" ' " (L) =EH4L"
arrRules(196) = "(LO)C#=LO\xd7" ' "(LO)C#=LOW"
arrRules(197) = "L(L)\xbd" ' "L(L)="
arrRules(198) = "#:^(L)%=U\xcc" ' "#:^(L)%=UL"
arrRules(199) = "(LEAD)=LIY\xc4" ' "(LEAD)=LIYD"
arrRules(200) = " (LAUGH)=LAE4\xc6" ' " (LAUGH)=LAE4F"
arrRules(201) = "(L)=\xcc" ' "(L)=L"
arrRules(202) = "]\xcd" ' "]M"
arrRules(203) = " (M) =EH4\xcd" ' " (M) =EH4M"
arrRules(204) = " (MR.) =MIH4STE\xd2" ' " (MR.) =MIH4STER"
arrRules(205) = " (MS.)=MIH5\xda" ' " (MS.)=MIH5Z"
arrRules(206) = " (MRS.) =MIH4SIX\xda" ' " (MRS.) =MIH4SIXZ"
arrRules(207) = "(MOV)=MUW4\xd6" ' "(MOV)=MUW4V"
arrRules(208) = "(MACHIN)=MAHSHIY5\xce" ' "(MACHIN)=MAHSHIY5N"
arrRules(209) = "M(M)\xbd" ' "M(M)="
arrRules(210) = "(M)=\xcd" ' "(M)=M"
arrRules(211) = "]\xce" ' "]N"
arrRules(212) = " (N) =EH4\xce" ' " (N) =EH4N"
arrRules(213) = "E(NG)+=N\xca" ' "E(NG)+=NJ"
arrRules(214) = "(NG)R=NX\xc7" ' "(NG)R=NXG"
arrRules(215) = "(NG)#=NX\xc7" ' "(NG)#=NXG"
arrRules(216) = "(NGL)%=NXGU\xcc" ' "(NGL)%=NXGUL"
arrRules(217) = "(NG)=N\xd8" ' "(NG)=NX"
arrRules(218) = "(NK)=NX\xcb" ' "(NK)=NXK"
arrRules(219) = " (NOW) =NAW\xb4" ' " (NOW) =NAW4"
arrRules(220) = "N(N)\xbd" ' "N(N)="
arrRules(221) = "(NON)E=NAH4\xce" ' "(NON)E=NAH4N"
arrRules(222) = "(N)=\xce" ' "(N)=N"
arrRules(223) = "]\xcf" ' "]O"
arrRules(224) = " (O) =OH4\xd7" ' " (O) =OH4W"
arrRules(225) = "(OF) =AH\xd6" ' "(OF) =AHV"
arrRules(226) = " (OH) =OW\xb5" ' " (OH) =OW5"
arrRules(227) = "(OROUGH)=ER4O\xd7" ' "(OROUGH)=ER4OW"
arrRules(228) = "#:(OR) =E\xd2" ' "#:(OR) =ER"
arrRules(229) = "#:(ORS) =ER\xda" ' "#:(ORS) =ERZ"
arrRules(230) = "(OR)=AO\xd2" ' "(OR)=AOR"
arrRules(231) = " (ONE)=WAH\xce" ' " (ONE)=WAHN"
arrRules(232) = "#(ONE) =WAH\xce" ' "#(ONE) =WAHN"
arrRules(233) = "(OW)=O\xd7" ' "(OW)=OW"
arrRules(234) = " (OVER)=OW5VE\xd2" ' " (OVER)=OW5VER"
arrRules(235) = "PR(O)V=UW\xb4" ' "PR(O)V=UW4"
arrRules(236) = "(OV)=AH4\xd6" ' "(OV)=AH4V"
arrRules(237) = "(O)^%=OW\xb5" ' "(O)^%=OW5"
arrRules(238) = "(O)^EN=O\xd7" ' "(O)^EN=OW"
arrRules(239) = "(O)^I#=OW\xb5" ' "(O)^I#=OW5"
arrRules(240) = "(OL)D=OW4\xcc" ' "(OL)D=OW4L"
arrRules(241) = "(OUGHT)=AO5\xd4" ' "(OUGHT)=AO5T"
arrRules(242) = "(OUGH)=AH5\xc6" ' "(OUGH)=AH5F"
arrRules(243) = " (OU)=A\xd7" ' " (OU)=AW"
arrRules(244) = "H(OU)S#=AW\xb4" ' "H(OU)S#=AW4"
arrRules(245) = "(OUS)=AX\xd3" ' "(OUS)=AXS"
arrRules(246) = "(OUR)=OH\xd2" ' "(OUR)=OHR"
arrRules(247) = "(OULD)=UH5\xc4" ' "(OULD)=UH5D"
arrRules(248) = "(OU)^L=AH\xb5" ' "(OU)^L=AH5"
arrRules(249) = "(OUP)=UW5\xd0" ' "(OUP)=UW5P"
arrRules(250) = "(OU)=A\xd7" ' "(OU)=AW"
arrRules(251) = "(OY)=O\xd9" ' "(OY)=OY"
arrRules(252) = "(OING)=OW4IHN\xd8" ' "(OING)=OW4IHNX"
arrRules(253) = "(OI)=OY\xb5" ' "(OI)=OY5"
arrRules(254) = "(OOR)=OH5\xd2" ' "(OOR)=OH5R"
arrRules(255) = "(OOK)=UH5\xcb" ' "(OOK)=UH5K"
arrRules(256) = "F(OOD)=UW5\xc4" ' "F(OOD)=UW5D"
arrRules(257) = "L(OOD)=AH5\xc4" ' "L(OOD)=AH5D"
arrRules(258) = "M(OOD)=UW5\xc4" ' "M(OOD)=UW5D"
arrRules(259) = "(OOD)=UH5\xc4" ' "(OOD)=UH5D"
arrRules(260) = "F(OOT)=UH5\xd4" ' "F(OOT)=UH5T"
arrRules(261) = "(OO)=UW\xb5" ' "(OO)=UW5"
arrRules(262) = "(O\\')=O\xc8" ' "(O\\')=OH"
arrRules(263) = "(O)E=O\xd7" ' "(O)E=OW"
arrRules(264) = "(O) =O\xd7" ' "(O) =OW"
arrRules(265) = "(OA)=OW\xb4" ' "(OA)=OW4"
arrRules(266) = " (ONLY)=OW4NLI\xd9" ' " (ONLY)=OW4NLIY"
arrRules(267) = " (ONCE)=WAH4N\xd3" ' " (ONCE)=WAH4NS"
arrRules(268) = "(ON\\'T)=OW4N\xd4" ' "(ON\\'T)=OW4NT"
arrRules(269) = "C(O)N=A\xc1" ' "C(O)N=AA"
arrRules(270) = "(O)NG=A\xcf" ' "(O)NG=AO"
arrRules(271) = " :^(O)N=A\xc8" ' " :^(O)N=AH"
arrRules(272) = "I(ON)=U\xce" ' "I(ON)=UN"
arrRules(273) = "#:(ON)=U\xce" ' "#:(ON)=UN"
arrRules(274) = "#^(ON)=U\xce" ' "#^(ON)=UN"
arrRules(275) = "(O)ST=O\xd7" ' "(O)ST=OW"
arrRules(276) = "(OF)^=AO4\xc6" ' "(OF)^=AO4F"
arrRules(277) = "(OTHER)=AH5DHE\xd2" ' "(OTHER)=AH5DHER"
arrRules(278) = "R(O)B=RA\xc1" ' "R(O)B=RAA"
arrRules(279) = "^R(O):#=OW\xb5" ' "^R(O):#=OW5"
arrRules(280) = "(OSS) =AO5\xd3" ' "(OSS) =AO5S"
arrRules(281) = "#:^(OM)=AH\xcd" ' "#:^(OM)=AHM"
arrRules(282) = "(O)=A\xc1" ' "(O)=AA"
arrRules(283) = "]\xd0" ' "]P"
arrRules(284) = " (P) =PIY\xb4" ' " (P) =PIY4"
arrRules(285) = "(PH)=\xc6" ' "(PH)=F"
arrRules(286) = "(PEOPL)=PIY5PU\xcc" ' "(PEOPL)=PIY5PUL"
arrRules(287) = "(POW)=PAW\xb4" ' "(POW)=PAW4"
arrRules(288) = "(PUT) =PUH\xd4" ' "(PUT) =PUHT"
arrRules(289) = "(P)P\xbd" ' "(P)P="
arrRules(290) = "(P)S\xbd" ' "(P)S="
arrRules(291) = "(P)N\xbd" ' "(P)N="
arrRules(292) = "(PROF.)=PROHFEH4SE\xd2" ' "(PROF.)=PROHFEH4SER"
arrRules(293) = "(P)=\xd0" ' "(P)=P"
arrRules(294) = "]\xd1" ' "]Q"
arrRules(295) = " (Q) =KYUW\xb4" ' " (Q) =KYUW4"
arrRules(296) = "(QUAR)=KWOH5\xd2" ' "(QUAR)=KWOH5R"
arrRules(297) = "(QU)=K\xd7" ' "(QU)=KW"
arrRules(298) = "(Q)=\xcb" ' "(Q)=K"
arrRules(299) = "]\xd2" ' "]R"
arrRules(300) = " (R) =AA5\xd2" ' " (R) =AA5R"
arrRules(301) = " (RE)^#=RI\xd9" ' " (RE)^#=RIY"
arrRules(302) = "(R)R\xbd" ' "(R)R="
arrRules(303) = "(R)=\xd2" ' "(R)=R"
arrRules(304) = "]\xd3" ' "]S"
arrRules(305) = " (S) =EH4\xd3" ' " (S) =EH4S"
arrRules(306) = "(SH)=S\xc8" ' "(SH)=SH"
arrRules(307) = "#(SION)=ZHU\xce" ' "#(SION)=ZHUN"
arrRules(308) = "(SOME)=SAH\xcd" ' "(SOME)=SAHM"
arrRules(309) = "#(SUR)#=ZHE\xd2" ' "#(SUR)#=ZHER"
arrRules(310) = "(SUR)#=SHE\xd2" ' "(SUR)#=SHER"
arrRules(311) = "#(SU)#=ZHU\xd7" ' "#(SU)#=ZHUW"
arrRules(312) = "#(SSU)#=SHU\xd7" ' "#(SSU)#=SHUW"
arrRules(313) = "#(SED)=Z\xc4" ' "#(SED)=ZD"
arrRules(314) = "#(S)#=\xda" ' "#(S)#=Z"
arrRules(315) = "(SAID)=SEH\xc4" ' "(SAID)=SEHD"
arrRules(316) = "^(SION)=SHU\xce" ' "^(SION)=SHUN"
arrRules(317) = "(S)S\xbd" ' "(S)S="
arrRules(318) = ".(S) =\xda" ' ".(S) =Z"
arrRules(319) = "#:.E(S) =\xda" ' "#:.E(S) =Z"
arrRules(320) = "#:^#(S) =\xd3" ' "#:^#(S) =S"
arrRules(321) = "U(S) =\xd3" ' "U(S) =S"
arrRules(322) = " :#(S) =\xda" ' " :#(S) =Z"
arrRules(323) = "##(S) =\xda" ' "##(S) =Z"
arrRules(324) = " (SCH)=S\xcb" ' " (SCH)=SK"
arrRules(325) = "(S)C+\xbd" ' "(S)C+="
arrRules(326) = "#(SM)=ZU\xcd" ' "#(SM)=ZUM"
arrRules(327) = "#(SN)\\'=ZU\xcd" ' "#(SN)\\'=ZUM"
arrRules(328) = "(STLE)=SU\xcc" ' "(STLE)=SUL"
arrRules(329) = "(S)=\xd3" ' "(S)=S"
arrRules(330) = "]\xd4" ' "]T"
arrRules(331) = " (T) =TIY\xb4" ' " (T) =TIY4"
arrRules(332) = " (THE) #=DHI\xd9" ' " (THE) #=DHIY"
arrRules(333) = " (THE) =DHA\xd8" ' " (THE) =DHAX"
arrRules(334) = "(TO) =TU\xd8" ' "(TO) =TUX"
arrRules(335) = " (THAT)=DHAE\xd4" ' " (THAT)=DHAET"
arrRules(336) = " (THIS) =DHIH\xd3" ' " (THIS) =DHIHS"
arrRules(337) = " (THEY)=DHE\xd9" ' " (THEY)=DHEY"
arrRules(338) = " (THERE)=DHEH\xd2" ' " (THERE)=DHEHR"
arrRules(339) = "(THER)=DHE\xd2" ' "(THER)=DHER"
arrRules(340) = "(THEIR)=DHEH\xd2" ' "(THEIR)=DHEHR"
arrRules(341) = " (THAN) =DHAE\xce" ' " (THAN) =DHAEN"
arrRules(342) = " (THEM) =DHAE\xce" ' " (THEM) =DHAEN"
arrRules(343) = "(THESE) =DHIY\xda" ' "(THESE) =DHIYZ"
arrRules(344) = " (THEN)=DHEH\xce" ' " (THEN)=DHEHN"
arrRules(345) = "(THROUGH)=THRUW\xb4" ' "(THROUGH)=THRUW4"
arrRules(346) = "(THOSE)=DHOH\xda" ' "(THOSE)=DHOHZ"
arrRules(347) = "(THOUGH) =DHO\xd7" ' "(THOUGH) =DHOW"
arrRules(348) = "(TODAY)=TUXDE\xd9" ' "(TODAY)=TUXDEY"
arrRules(349) = "(TOMO)RROW=TUMAA\xb5" ' "(TOMO)RROW=TUMAA5"
arrRules(350) = "(TO)TAL=TOW\xb5" ' "(TO)TAL=TOW5"
arrRules(351) = " (THUS)=DHAH4\xd3" ' " (THUS)=DHAH4S"
arrRules(352) = "(TH)=T\xc8" ' "(TH)=TH"
arrRules(353) = "#:(TED)=TIX\xc4" ' "#:(TED)=TIXD"
arrRules(354) = "S(TI)#N=C\xc8" ' "S(TI)#N=CH"
arrRules(355) = "(TI)O=S\xc8" ' "(TI)O=SH"
arrRules(356) = "(TI)A=S\xc8" ' "(TI)A=SH"
arrRules(357) = "(TIEN)=SHU\xce" ' "(TIEN)=SHUN"
arrRules(358) = "(TUR)#=CHE\xd2" ' "(TUR)#=CHER"
arrRules(359) = "(TU)A=CHU\xd7" ' "(TU)A=CHUW"
arrRules(360) = " (TWO)=TU\xd7" ' " (TWO)=TUW"
arrRules(361) = "&(T)EN \xbd" ' "&(T)EN ="
arrRules(362) = "(T)=\xd4" ' "(T)=T"
arrRules(363) = "]\xd5" ' "]U"
arrRules(364) = " (U) =YUW\xb4" ' " (U) =YUW4"
arrRules(365) = " (UN)I=YUW\xce" ' " (UN)I=YUWN"
arrRules(366) = " (UN)=AH\xce" ' " (UN)=AHN"
arrRules(367) = " (UPON)=AXPAO\xce" ' " (UPON)=AXPAON"
arrRules(368) = "@(UR)#=UH4\xd2" ' "@(UR)#=UH4R"
arrRules(369) = "(UR)#=YUH4\xd2" ' "(UR)#=YUH4R"
arrRules(370) = "(UR)=E\xd2" ' "(UR)=ER"
arrRules(371) = "(U)^ =A\xc8" ' "(U)^ =AH"
arrRules(372) = "(U)^^=AH\xb5" ' "(U)^^=AH5"
arrRules(373) = "(UY)=AY\xb5" ' "(UY)=AY5"
arrRules(374) = " G(U)#\xbd" ' " G(U)#="
arrRules(375) = "G(U)%\xbd" ' "G(U)%="
arrRules(376) = "G(U)#=\xd7" ' "G(U)#=W"
arrRules(377) = "#N(U)=YU\xd7" ' "#N(U)=YUW"
arrRules(378) = "@(U)=U\xd7" ' "@(U)=UW"
arrRules(379) = "(U)=YU\xd7" ' "(U)=YUW"
arrRules(380) = "]\xd6" ' "]V"
arrRules(381) = " (V) =VIY\xb4" ' " (V) =VIY4"
arrRules(382) = "(VIEW)=VYUW\xb5" ' "(VIEW)=VYUW5"
arrRules(383) = "(V)=\xd6" ' "(V)=V"
arrRules(384) = "]\xd7" ' "]W"
arrRules(385) = " (W) =DAH4BULYU\xd7" ' " (W) =DAH4BULYUW"
arrRules(386) = " (WERE)=WE\xd2" ' " (WERE)=WER"
arrRules(387) = "(WA)SH=WA\xc1" ' "(WA)SH=WAA"
arrRules(388) = "(WA)ST=WE\xd9" ' "(WA)ST=WEY"
arrRules(389) = "(WA)S=WA\xc8" ' "(WA)S=WAH"
arrRules(390) = "(WA)T=WA\xc1" ' "(WA)T=WAA"
arrRules(391) = "(WHERE)=WHEH\xd2" ' "(WHERE)=WHEHR"
arrRules(392) = "(WHAT)=WHAH\xd4" ' "(WHAT)=WHAHT"
arrRules(393) = "(WHOL)=/HOW\xcc" ' "(WHOL)=/HOWL"
arrRules(394) = "(WHO)=/HU\xd7" ' "(WHO)=/HUW"
arrRules(395) = "(WH)=W\xc8" ' "(WH)=WH"
arrRules(396) = "(WAR)#=WEH\xd2" ' "(WAR)#=WEHR"
arrRules(397) = "(WAR)=WAO\xd2" ' "(WAR)=WAOR"
arrRules(398) = "(WOR)^=WE\xd2" ' "(WOR)^=WER"
arrRules(399) = "(WR)=\xd2" ' "(WR)=R"
arrRules(400) = "(WOM)A=WUH\xcd" ' "(WOM)A=WUHM"
arrRules(401) = "(WOM)E=WIH\xcd" ' "(WOM)E=WIHM"
arrRules(402) = "(WEA)R=WE\xc8" ' "(WEA)R=WEH"
arrRules(403) = "(WANT)=WAA5N\xd4" ' "(WANT)=WAA5NT"
arrRules(404) = "ANS(WER)=E\xd2" ' "ANS(WER)=ER"
arrRules(405) = "(W)=\xd7" ' "(W)=W"
arrRules(406) = "]\xd8" ' "]X"
arrRules(407) = " (X) =EH4K\xd2" ' " (X) =EH4KR"
arrRules(408) = " (X)=\xda" ' " (X)=Z"
arrRules(409) = "(X)=K\xd3" ' "(X)=KS"
arrRules(410) = "]\xd9" ' "]Y"
arrRules(411) = " (Y) =WAY\xb4" ' " (Y) =WAY4"
arrRules(412) = "(YOUNG)=YAHN\xd8" ' "(YOUNG)=YAHNX"
arrRules(413) = " (YOUR)=YOH\xd2" ' " (YOUR)=YOHR"
arrRules(414) = " (YOU)=YU\xd7" ' " (YOU)=YUW"
arrRules(415) = " (YES)=YEH\xd3" ' " (YES)=YEHS"
arrRules(416) = " (Y)=\xd9" ' " (Y)=Y"
arrRules(417) = "F(Y)=A\xd9" ' "F(Y)=AY"
arrRules(418) = "PS(YCH)=AY\xcb" ' "PS(YCH)=AYK"
arrRules(419) = "#:^(Y)=I\xd9" ' "#:^(Y)=IY"
arrRules(420) = "#:^(Y)I=I\xd9" ' "#:^(Y)I=IY"
arrRules(421) = " :(Y) =A\xd9" ' " :(Y) =AY"
arrRules(422) = " :(Y)#=A\xd9" ' " :(Y)#=AY"
arrRules(423) = " :(Y)^+:#=I\xc8" ' " :(Y)^+:#=IH"
arrRules(424) = " :(Y)^#=A\xd9" ' " :(Y)^#=AY"
arrRules(425) = "(Y)=I\xc8" ' "(Y)=IH"
arrRules(426) = "]\xda" ' "]Z"
arrRules(427) = " (Z) =ZIY\xb4" ' " (Z) =ZIY4"
arrRules(428) = "(Z)=\xda" ' "(Z)=Z"
arrRules(429) = "]\xb0" ' "]0"
arrRules(430) = "(A)\xbd" ' "(A)="
arrRules(431) = "(!)=\xae" ' "(!)=."
arrRules(432) = "(\" + Chr$(34) + ") =-AH5NKWOWT\xad" ' "(\") =-AH5NKWOWT-"
arrRules(433) = "(\" + Chr$(34) + ")=KWOW4T\xad" ' "(\")=KWOW4T-"
arrRules(434) = "(#)= NAH4MBE\xd2" ' "(#)= NAH4MBER"
arrRules(435) = "($)= DAA4LE\xd2" ' "($)= DAA4LER"
arrRules(436) = "(%)= PERSEH4N\xd4" ' "(%)= PERSEH4NT"
arrRules(437) = "(&)= AEN\xc4" ' "(&)= AEND"
arrRules(438) = "(\\)\xbd" ' "(\\)="
arrRules(439) = "(*)= AE4STERIHS\xcb" ' "(*)= AE4STERIHSK"
arrRules(440) = "(+)= PLAH4\xd3" ' "(+)= PLAH4S"
arrRules(441) = "(,)=\xac" ' "(,)=,"
arrRules(442) = " (-) =\xad" ' " (-) =-"
arrRules(443) = "(-)\xbd" ' "(-)="
arrRules(444) = "(.)= POYN\xd4" ' "(.)= POYNT"
arrRules(445) = "(/)= SLAE4S\xc8" ' "(/)= SLAE4SH"
arrRules(446) = "(0)= ZIY4RO\xd7" ' "(0)= ZIY4ROW"
arrRules(447) = " (1ST)=FER4S\xd4" ' " (1ST)=FER4ST"
arrRules(448) = " (10TH)=TEH4NT\xc8" ' " (10TH)=TEH4NTH"
arrRules(449) = "(1)= WAH4\xce" ' "(1)= WAH4N"
arrRules(450) = " (2ND)=SEH4KUN\xc4" ' " (2ND)=SEH4KUND"
arrRules(451) = "(2)= TUW\xb4" ' "(2)= TUW4"
arrRules(452) = " (3RD)=THER4\xc4" ' " (3RD)=THER4D"
arrRules(453) = "(3)= THRIY\xb4" ' "(3)= THRIY4"
arrRules(454) = "(4)= FOH4\xd2" ' "(4)= FOH4R"
arrRules(455) = " (5TH)=FIH4FT\xc8" ' " (5TH)=FIH4FTH"
arrRules(456) = "(5)= FAY4\xd6" ' "(5)= FAY4V"
arrRules(457) = " (64) =SIH4KSTIY FOH\xd2" ' " (64) =SIH4KSTIY FOHR"
arrRules(458) = "(6)= SIH4K\xd3" ' "(6)= SIH4KS"
arrRules(459) = "(7)= SEH4VU\xce" ' "(7)= SEH4VUN"
arrRules(460) = " (8TH)=EY4T\xc8" ' " (8TH)=EY4TH"
arrRules(461) = "(8)= EY4\xd4" ' "(8)= EY4T"
arrRules(462) = "(9)= NAY4\xce" ' "(9)= NAY4N"
arrRules(463) = "(:)=\xae" ' "(:)=."
arrRules(464) = "(;)=\xae" ' "(;)=."
arrRules(465) = "(<)= LEH4S DHAE\xce" ' "(<)= LEH4S DHAEN"
arrRules(466) = "(=)= IY4KWUL\xda" ' "(=)= IY4KWULZ"
arrRules(467) = "(>)= GREY4TER DHAE\xce" ' "(>)= GREY4TER DHAEN"
arrRules(468) = "(?)=\xbf" ' "(?)=?"
arrRules(469) = "(@)= AE6\xd4" ' "(@)= AE6T"
arrRules(470) = "(^)= KAE4RIX\xd4" ' "(^)= KAE4RIXT"
arrRules(471) = "(')\xbd" ' "(')="
arrRules(472) = "(`)\xbd" ' "(`)="
arrRules(473) = "]\xb1" ' "]1'


ReDim arrRuleTab(0 To 27) As Integer
arrRuleTab(0) = &H00
arrRuleTab(1) = &H195
arrRuleTab(2) = &H1F7
arrRuleTab(3) = &H2A2
arrRuleTab(4) = &H33F
arrRuleTab(5) = &H4C6
arrRuleTab(6) = &H507
arrRuleTab(7) = &H57F
arrRuleTab(8) = &H5C8
arrRuleTab(9) = &H728
arrRuleTab(10) = &H739
arrRuleTab(11) = &H750
arrRuleTab(12) = &H793
arrRuleTab(13) = &H7F3
arrRuleTab(14) = &H857
arrRuleTab(15) = &HAA5
arrRuleTab(16) = &HB02
arrRuleTab(17) = &HB28
arrRuleTab(18) = &HB49
arrRuleTab(19) = &HC32
arrRuleTab(20) = &HDAC
arrRuleTab(21) = &HE3B
arrRuleTab(22) = &HE58
arrRuleTab(23) = &HF33
arrRuleTab(24) = &HF4C
arrRuleTab(25) = &HFDF
arrRuleTab(26) = &HFF0
arrRuleTab(27) = &H11B7
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' END reciter_tabs.h
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' BEGIN sam_tabs.h
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

'tab40672
arrStressInputTable(0) = "*"
arrStressInputTable(1) = "1"
arrStressInputTable(2) = "2"
arrStressInputTable(3) = "3"
arrStressInputTable(4) = "4"
arrStressInputTable(5) = "5"
arrStressInputTable(6) = "6"
arrStressInputTable(7) = "7"
arrStressInputTable(8) = "8"




' BEGIN tab40682
'arrSignInputTable1 = " .?,--IIEAAAAUAIEOURLWYWR LWYMNNNDQSSFT//ZZVDC*J* *EAOAOUB* *D* *G* *GP* *T* *K* *K* *UUU" ' Initialize the string directly
tab40682$ = " .?,--IIEAAAAUAIEOURLWYWR LWYMNNNDQSSFT//ZZVDC*J* *EAOAOUB* *D* *G* *GP* *T* *K* *K* *UUU" ' Initialize the string directly
iSize = Len(tab40682$)
ReDim arrSignInputTable1(0 To iSize - 1) As String ' _Unsigned _Byte
For iIndex = 0 To iSize - 1
    arrSignInputTable1(iIndex) = Mid$(tab40682$, iIndex + 1, 1)
Next iIndex
' END tab40682

' BEGIN tab40763
'arrSignInputTable2 = "**** *YHH EAHOHXXRXHXXXXH* *****XXX* H*HHHX* HHH* *YYYYWWW* ***** * * *X* * *LMN" ' Initialize the string directly
tab40763$ = "**** *YHH EAHOHXXRXHXXXXH* *****XXX* H*HHHX* HHH* *YYYYWWW* ***** * * *X* * *LMN" ' Initialize the string directly
iSize = Len(tab40763$)
ReDim arrSignInputTable2(0 To iSize - 1) As String ' _Unsigned _Byte
For iIndex = 0 To iSize - 1
    arrSignInputTable2(iIndex) = Mid$(tab40763$, iIndex + 1, 1)
Next iIndex
' END tab40763

' BEGIN loc_9F8C
ReDim arrFlags1(0 To 66) As _Unsigned _Byte
Data &H00,&H00,&H00,&H00,&H00,&HA4,&HA4,&HA4
Data &HA4,&HA4,&HA4,&H84,&H84,&HA4,&HA4,&H84
Data &H84,&H84,&H84,&H84,&H84,&H84,&H44,&H44
Data &H44,&H44,&H44,&H4C,&H4C,&H4C,&H48,&H4C
Data &H40,&H40,&H40,&H40,&H40,&H40,&H44,&H44
Data &H44,&H44,&H48,&H40,&H4C,&H44,&H00,&H00
Data &HB4,&HB4,&HB4,&H94,&H94,&H94,&H4E,&H4E
Data &H4E,&H4E,&H4E,&H4E,&H4E,&H4E,&H4E,&H4E
Data &H4E,&H4E,&H4B,&H4B,&H4B,&H4B,&H4B,&H4B
Data &H4B,&H4B,&H4B,&H4B,&H4B,&H4B,&H80,&HC1
Data &HC1
For iIndex = 0 To 66
    Read arrFlags1(iIndex)
Next iIndex
'END loc_9F8C

'??? flags overlap arrFlags2  'Comment retained from original code
'loc_9FDA
ReDim arrFlags2(0 To 61) As _Unsigned _Byte
Data &H80,&HC1,&HC1,&HC1,&HC1,&H00,&H00,&H00
Data &H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00
Data &H00,&H00,&H00,&H00,&H00,&H00,&H00,&H10
Data &H10,&H10,&H10,&H08,&H0C,&H08,&H04,&H40
Data &H24,&H20,&H20,&H24,&H00,&H00,&H24,&H20
Data &H20,&H24,&H20,&H20,&H00,&H20,&H00,&H00
Data &H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00
Data &H00,&H04,&H04,&H04,&H00,&H00,&H00,&H00
Data &H00,&H00,&H00,&H00,&H00,&H04,&H04,&H04
Data &H00,&H00,&H00,&H00,&H00,&H00
For iIndex = 0 To 61
    Read arrFlags2(iIndex)
Next iIndex

'tab45616???
ReDim arrPhoStressedLengthTable(0 To 61) As _Unsigned _Byte
Data &H00,&H12,&H12,&H12,8,&HB,9,&HB
Data &HE,&HF,&HB,&H10,&HC,6,6,&HE
Data &HC,&HE,&HC,&HB,8,8,&HB,&HA
Data 9,8,8,8,8,8,3,5
Data 2,2,2,2,2,2,6,6
Data 8,6,6,2,9,4,2,1
Data &HE,&HF,&HF,&HF,&HE,&HE,8,2
Data 2,7,2,1,7,2,2,7
Data 2,2,8,2
Data 2,6,2,2
Data 7,2,4,7,1,4,5,5
For iIndex = 0 To 61
    Read arrPhoStressedLengthTable(iIndex)
Next iIndex

'tab45536???
ReDim arrPhoLengthTable(0 To 61) As _Unsigned _Byte

Data 0,&H12,&H12,&H12,8,8,8,8
Data 8,&HB,6,&HC,&HA,5,5,&HB
Data &HA,&HA,&HA,9,8,7,9,7
Data 6,8,6,7,7,7,2,5
Data 2,2,2,2,2,2,6,6
Data 7,6,6,2,8,3,1,&H1E
Data &HD,&HC,&HC,&HC,&HE,9,6,1
Data 2,5,1,1,6,1,2,6
Data 1,2,8,2
Data 2,4,2,2
Data 6,1,4,6,1,4,&HC7,&HFF

For iIndex = 0 To 61
    Read arrPhoLengthTable(iIndex)
Next iIndex

' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' END sam_tabs.h
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' BEGIN render_tabs.h
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

' The following constants are defined as byte arrays:
' uint8_t tab48426[5]
' uint8_t tab47492[]
' uint8_t amplitudeRescale[]
' uint8_t blendRank[]


' Initialize tab48426
ReDim arrTab48426(4) As _Byte ' Equivalent to uint8_t[5]
arrTab48426(0) = &H18
arrTab48426(1) = &H1A
arrTab48426(2) = &H17
arrTab48426(3) = &H17
arrTab48426(4) = &H17

' Initialize tab47492
ReDim arrTab47492(10) ' 11 elements
arrTab47492(0) = 0
arrTab47492(1) = 0
arrTab47492(2) = &HE0
arrTab47492(3) = &HE6
arrTab47492(4) = &HEC
arrTab47492(5) = &HF3
arrTab47492(6) = &HF9
arrTab47492(7) = 0
arrTab47492(8) = 6
arrTab47492(9) = &HC
arrTab47492(10) = 6

' Initialize amplitudeRescale
ReDim arrAmplitudeRescale(16) ' 17 elements
arrAmplitudeRescale(0) = 0
arrAmplitudeRescale(1) = 1
arrAmplitudeRescale(2) = 2
arrAmplitudeRescale(3) = 2
arrAmplitudeRescale(4) = 2
arrAmplitudeRescale(5) = 3
arrAmplitudeRescale(6) = 3
arrAmplitudeRescale(7) = 4
arrAmplitudeRescale(8) = 4
arrAmplitudeRescale(9) = 5
arrAmplitudeRescale(10) = 6
arrAmplitudeRescale(11) = 8
arrAmplitudeRescale(12) = 9
arrAmplitudeRescale(13) = &HB
arrAmplitudeRescale(14) = &HD
arrAmplitudeRescale(15) = &HF
arrAmplitudeRescale(16) = 0

' Initialize blendRank
ReDim arrBlendRank(62) ' 63 elements
arrBlendRank(0) = 0
arrBlendRank(1) = &H1F
arrBlendRank(2) = &H1F
arrBlendRank(3) = &H1F
arrBlendRank(4) = &H1F
arrBlendRank(5) = 2
arrBlendRank(6) = 2
arrBlendRank(7) = 2
arrBlendRank(8) = 2
arrBlendRank(9) = 2
arrBlendRank(10) = 2
arrBlendRank(11) = 2
arrBlendRank(12) = 2
arrBlendRank(13) = 2
arrBlendRank(14) = 5
arrBlendRank(15) = 5
arrBlendRank(16) = 2
arrBlendRank(17) = &HA
arrBlendRank(18) = 2
arrBlendRank(19) = 8
arrBlendRank(20) = 5
arrBlendRank(21) = 5
arrBlendRank(22) = &HB
arrBlendRank(23) = &HA
arrBlendRank(24) = 9
arrBlendRank(25) = 8
arrBlendRank(26) = 8
arrBlendRank(27) = &HA0
arrBlendRank(28) = 8
arrBlendRank(29) = 8
arrBlendRank(30) = &H17
arrBlendRank(31) = &H1F
arrBlendRank(32) = &H12
arrBlendRank(33) = &H12
arrBlendRank(34) = &H12
arrBlendRank(35) = &H12
arrBlendRank(36) = &H1E
arrBlendRank(37) = &H1E
arrBlendRank(38) = &H14
arrBlendRank(39) = &H14
arrBlendRank(40) = &H14
arrBlendRank(41) = &H14
arrBlendRank(42) = &H17
arrBlendRank(43) = &H17
arrBlendRank(44) = &H1A
arrBlendRank(45) = &H1A
arrBlendRank(46) = &H1D
arrBlendRank(47) = &H1D
arrBlendRank(48) = 2
arrBlendRank(49) = 2
arrBlendRank(50) = 2
arrBlendRank(51) = 2
arrBlendRank(52) = 2
arrBlendRank(53) = 2
arrBlendRank(54) = &H1A
arrBlendRank(55) = &H1D
arrBlendRank(56) = &H1B
arrBlendRank(57) = &H1A
arrBlendRank(58) = &H1D
arrBlendRank(59) = &H1B
arrBlendRank(60) = &H1A
arrBlendRank(61) = &H1D
arrBlendRank(62) = &H1B
arrBlendRank(63) = &H1A ' Note: There's an extra element in the C code
arrBlendRank(64) = &H1D
arrBlendRank(65) = &H1B
arrBlendRank(66) = &H17
arrBlendRank(67) = &H1D
arrBlendRank(68) = &H17
arrBlendRank(69) = &H17
arrBlendRank(70) = &H1D
arrBlendRank(71) = &H17
arrBlendRank(72) = &H17
arrBlendRank(73) = &H1D
arrBlendRank(74) = &H17
arrBlendRank(75) = &H17
arrBlendRank(76) = &H1D
arrBlendRank(77) = &H17
arrBlendRank(78) = &H17
arrBlendRank(79) = &H17


' Example of accessing the arrays:
' PRINT arrTab48426(0)
' PRINT arrTab47492(5)
' PRINT arrAmplitudeRescale(10)
' PRINT arrBlendRank(25)

'BEGIN PART 1a2
ReDim arrOutBlendLength(95) As _Unsigned _Byte
Data 0,2,2,2,2,4,4,4,4,4,4,4,4,4,4,4,4,4,3,2,4,4,2,2
Data 2,2,2,1,1,1,1,1,1,1,1,1,1,1,2,2,2,1,0,1,0,1,0,5
Data 5,5,5,5,4,4,2,0,1,2,0,1,2,0,1,2,0,1,2,0,2,2,0,1
Data 3,0,2,3,0,2,160,160  '0xA0 = 160

For iIndex = 0 To 95
    Read arrOutBlendLength(iIndex)
Next iIndex

' Number of frames at beginning of a phoneme devoted to interpolating to phoneme's final value
' tab45776
ReDim arrInBlendLength(95) As _Unsigned _Byte
Data 0,2,2,2,2,4,4,4,4,4,4,4,4,4,4,4,4,4,3,3,4,4,3,3
Data 3,3,3,1,2,3,2,1,3,3,3,3,1,1,3,3,3,2,2,3,2,3,0,0
Data 5,5,5,5,4,4,2,0,2,2,0,3,2,0,4,2,0,3,2,0,2,2,0,2
Data 3,0,3,3,0,3,176,160  '0xB0 = 176,&HA0 = 160

For iIndex = 0 To 95
    Read arrInBlendLength(iIndex)
Next iIndex


ReDim arrSampledConsonantFlags(79) As _Unsigned _Byte
Data 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Data 0,0,0,0,0,0,0,0,241,226,211,187,124,149,1,2,3,3,0,114,0,2,0,0
Data 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,27
Data 0,0,25,0,0,0,0,0,0,0,0,0

For iIndex = 0 To 79
    Read arrSampledConsonantFlags(iIndex)
Next iIndex


'tab45056
'note: non const


ReDim arrFreq1Data(71) As _Unsigned _Byte
Data &H00,&H13,&H13,&H13,&H13,&HA,&HE,&H12,&H18,&H1A,&H16,&H14,&H10,&H14,&HE,&H12,&HE,&H12,&H12,&H10,&HC,&HE,&HA,&H12,&HE,&HA,8,6,6,6,6,&H11,6,6,6,6,&HE,&H10,9,&HA,8,&HA,6,6,6,5,6,0,&H12,&H1A,&H14,&H1A,&H12,&HC,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,&HA,&HA,6,6,6,&H2C,&H13
For iIndex = 0 To 71
    Read arrFreq1Data(iIndex)
Next iIndex

'tab451356
' note: non const

ReDim arrFreq2Data(79) As _Unsigned _Byte
Data &H00,&H43,&H43,&H43,&H43,&H54,&H48,&H42,&H3E,&H28,&H2C,&H1E,&H24,&H2C,&H48,&H30,&H24,&H1E,&H32,&H24,&H1C,&H44,&H18,&H32,&H1E,&H18,&H52,&H2E,&H36,&H56,&H36,&H43,&H49,&H4F,&H1A,&H42,&H49,&H25,&H33,&H42,&H28,&H2F,&H4F,&H4F,&H42,&H4F,&H6E,&H00,&H48,&H26,&H1E,&H2A,&H1E,&H22,&H1A,&H1A,&H1A,&H42,&H42,&H42,&H6E,&H6E,&H6E,&H54,&H54,&H54
For iIndex = 0 To 59
    Read arrFreq2Data(iIndex)
Next iIndex

Data &H1A,&H1A,&H1A,&H42,&H42,&H42,&H6D,&H56,&H6D,&H54,&H54,&H54,&H7F,&H7F
For iIndex = 60 To 79
    Read arrFreq2Data(iIndex)
Next iIndex

'tab45216

ReDim arrFreq3Data(62) As _Unsigned _Byte
Data &H00,&H5B,&H5B,&H5B,&H5B,&H6E,&H5D,&H5B,&H58,&H59,&H57,&H58,&H52,&H59,&H5D,&H3E,&H52,&H58,&H3E,&H6E,&H50,&H5D,&H5A,&H3C,&H6E,&H5A,&H6E,&H51,&H79,&H65,&H79,&H5B,&H63,&H6A,&H51,&H79,&H5D,&H52,&H5D,&H67,&H4C,&H5D,&H65,&H65,&H79,&H65,&H79,&H00,&H5A,&H58,&H58,&H58,&H58,&H52,&H51,&H51,&H51,&H79,&H79,&H79,&H70,&H6E,&H6E,&H5E,&H5E,&H5E,&H51,&H51
For iIndex = 0 To 59
    Read arrFreq3Data(iIndex)
Next iIndex

Data &H51,&H79,&H79,&H79,&H65,&H65,&H70,&H5E,&H5E,&H5E,&H08,&H01
For iIndex = 60 To 61
    Read arrFreq3Data(iIndex)
Next iIndex


ReDim arrAmp1Data(78) As _Byte
Data 0,0,0,0,0,&HD,&HD,&HE,&HF,&HF,&HF,&HF,&HF,&HC,&HD,&HC
Data &HF,&HF,&HD,&HD,&HD,&HE,&HD,&HC,&HD,&HD,&HD,&HC,9,9,0,0
Data 0,0,0,0,0,0,&HB,&HB,&HB,&HB,0,0,1,&HB,0,2
Data &HE,&HF,&HF,&HF,&HF,&HD,2,4,0,2,4,0,1,4,0,1
Data 4,0,0,0,0,0,0,0,0,&HC,0,0,0,0,&HF,&HF


ReDim arrAmp2Data(78) As _Byte
Data 0,0,0,0,0,&HA,&HB,&HD,&HE,&HD,&HC,&HC,&HB,9,&HB,&HB
Data &HC,&HC,&HC,8,8,&HC,8,&HA,8,8,&HA,3,9,6,0,0
Data 0,0,0,0,0,0,3,5,3,4,0,0,0,5,&HA,2
Data &HE,&HD,&HC,&HD,&HC,8,0,1,0,0,1,0,0,1,0,0
Data 1,0,0,0,0,0,0,0,0,&HA,0,0,&HA,0,0,0



ReDim arrAmp3Data(78) As _Byte
Data 0,0,0,0,0,8,7,8,8,1,1,0,1,0,7,5
Data 1,0,6,1,0,7,0,5,1,0,8,0,0,3,0,0
Data 0,0,0,0,0,0,0,1,0,0,0,0,0,1,&HE,1
Data 9,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0
Data 0,0,0,0,0,0,0,0,0,7,0,0,5,0,&H13,&H10


ReDim arrSinus(180) As _Unsigned _Byte

' Initialize the sinus array with the given values
Data 0,0,0,16,16,16,16,16,16,32,32,32,32,32,32,48,48,48,48,48,48,48,64,64,64,64,64,64,64,80,80,80,80,80,80,80,80,96,96,96,96,96,96,96,96,96,96,96,96,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,96,96,96,96,96,96,96,96,96,96,96,96,80,80,80,80,80,80,80,80,64,64,64,64,64,64,64,48,48,48,48,48,48,48,32,32,32,32,32,32,16,16,16,16,16,16,0,0,0,240,240,240,240,240,240,224,224,224,224,224,224,208,208,208,208,208,208,208,192,192,192,192,192,192,192,176,176,176,176,176,176,176,176,160,160,160,160,160,160,160,160,160,160,160,160,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,160,160,160,160,160,160,160,160,160,160,160,160,176,176,176,176,176,176,176,176,192,192,192,192,192,192,192,208,208,208,208,208,208,208,224,224,224,224,224,224,240,240,240,240,240,240,0,0

For iIndex = 1 To 181
    Read arrSinus(iIndex)
Next iIndex


ReDim arrRectangle(143) As _Unsigned _Byte

' Initialize the array with the given values
Data &H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90
Data &H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90
Data &H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90
Data &H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90
Data &H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90
Data &H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90
Data &H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90
Data &H90,&H90,&H90,&H90,&H90,&H90,&H90,&H90,&H70,&H70,&H70,&H70,&H70,&H70,&H70,&H70
Data &H70,&H70,&H70,&H70,&H70,&H70,&H70,&H70,&H70,&H70,&H70,&H70,&H70,&H70,&H70,&H70
Data &H70,&H70,&H70,&H70,&H70,&H70,&H70,&H70,&H70,&H70,&H70,&H70,&H70,&H70,&H70,&H70
Data &H70,&H70,&H70,&H70,&H70,&H70,&H70,&H70,&H70,&H70,&H70,&H70,&H70,&H70,&H70,&H70
Data &H70,&H70,&H70,&H70,&H70,&H70,&H70,&H70,&H70,&H70,&H70,&H70,&H70,&H70,&H70,&H70
Data &H70,&H70,&H70,&H70,&H70,&H70,&H70,&H70,&H70,&H70,&H70,&H70,&H70,&H70,&H70,&H70

For iIndex = 0 To 143
    Read arrRectangle(iIndex)
Next iIndex

ReDim arrMultTable(255) As _Byte ' QB64 uses byte for unsigned 8-bit

Data 0,0,0,0,0,0,0,0
Data 0,0,0,0,0,0,0,0
Data 0,0,1,1,2,2,3,3
Data 4,4,5,5,6,6,7,7
Data 0,1,2,3,4,5,6,7
Data 8,9,10,11,12,13,14,15  '0xA to 0xF
Data 0,1,3,4,6,7,9,10   '0xA
Data 12,13,15,16,18,19,21,22  '0x10 to 0x16
Data 0,2,4,6,8,10,12,14   '0xA,&HC,&HE
Data 16,18,20,22,24,26,28,30   '0x10 to 0x1E
Data 0,2,5,7,10,12,15,17    '0xA,&HC,&HF,&H11
Data 20,22,25,27,30,32,35,37   '0x14 to 0x25
Data 0,3,6,9,12,15,18,21   '0xC,&HF,&H12,&H15
Data 24,27,30,33,36,39,42,45   '0x18 to 0x2D
Data 0,3,7,10,14,17,21,24   '0x03 to 0x18
Data 28,31,35,38,42,45,49,52   '0x1C to 0x34
Data 0,252,248,244,240,236,232,228  '0xFC to 0xE4
Data 224,220,216,212,208,204,200,196 '0xE0 to 0xC4
Data 0,252,249,245,242,238,235,231  '0xFC to 0xE7
Data 228,224,221,217,214,210,207,203 '0xE4 to 0xCB
Data 0,253,250,247,244,241,238,235  '0xFD to 0xEB
Data 232,229,226,223,220,217,214,211 '0xE8 to 0xD3
Data 0,253,251,248,246,243,241,238  '0xFD to 0xEE
Data 236,233,231,228,226,223,221,218 '0xEC to 0xDA
Data 0,254,252,250,248,246,244,242  '0xFE to 0xF2
Data 240,238,236,234,232,230,228,226 '0xF0 to 0xE2
Data 0,254,253,251,250,248,247,245  '0xFE to 0xF5
Data 244,242,241,239,238,236,235,233 '0xF4 to 0xE9
Data 0,255,254,253,252,251,250,249  '0xFF to 0xF9
Data 248,247,246,245,244,243,242,241 '0xF8 to 0xF1
Data 0,255,255,254,254,253,253,252  '0xFF to 0xFC
Data 252,251,251,250,250,249,249,248 '0xFC to 0xF8

For iIndex = 0 To 255
    Read arrMultTable(iIndex)
Next iIndex

'END PART 3  (Comment in original file)
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
'Converted from render_tabs.h.4.txt

ReDim arrSampleTable(0 To 1279) As _Byte '0x500 = 1280

' Initialize the sample table

' SAMPLE DATA
Restore SampleTableData
For iIndex = 0 To 1279
    Read arrSampleTable(iIndex)
Next iIndex

SampleTableData:

' 00
Data &H38,&H84,&H6B,&H19,&HC6,&H63,&H18,&H86,&H73,&H98,&HC6,&HB1,&H1C,&HCA,&H31,&H8C,&HC7,&H31,&H88,&HC2,&H30,&H98,&H46,&H31,&H18,&HC6,&H35,&HC,&HCA,&H31,&HC,&HC6

' 20
Data &H21,&H10,&H24,&H69,&H12,&HC2,&H31,&H14,&HC4,&H71,&H08,&H4A,&H22,&H49,&HAB,&H6A,&HA8,&HAC,&H49,&H51,&H32,&HD5,&H52,&H88,&H93,&H6C,&H94,&H22,&H15,&H54,&HD2,&H25

' 40
Data &H96,&HD4,&H50,&HA5,&H46,&H21,&H08,&H85,&H6B,&H18,&HC4,&H63,&H10,&HCE,&H6B,&H18,&H8C,&H71,&H19,&H8C,&H63,&H35,&HC,&HC6,&H33,&H99,&HCC,&H6C,&HB5,&H4E,&HA2,&H99

' 60
Data &H46,&H21,&H28,&H82,&H95,&H2E,&HE3,&H30,&H9C,&HC5,&H30,&H9C,&HA2,&HB1,&H9C,&H67,&H31,&H88,&H66,&H59,&H2C,&H53,&H18,&H84,&H67,&H50,&HCA,&HE3,&HA,&HAC,&HAB,&H30

' 80
Data &HAC,&H62,&H30,&H8C,&H63,&H10,&H94,&H62,&HB1,&H8C,&H82,&H28,&H96,&H33,&H98,&HD6,&HB5,&H4C,&H62,&H29,&HA5,&H4A,&HB5,&H9C,&HC6,&H31,&H14,&HD6,&H38,&H9C,&H4B,&HB4

' A0
Data &H86,&H65,&H18,&HAE,&H67,&H1C,&HA6,&H63,&H19,&H96,&H23,&H19,&H84,&H13,&H08,&HA6,&H52,&HAC,&HCA,&H22,&H89,&H6E,&HAB,&H19,&H8C,&H62,&H34,&HC4,&H62,&H19,&H86,&H63

' C0
Data &H18,&HC4,&H23,&H58,&HD6,&HA3,&H50,&H42,&H54,&H4A,&HAD,&H4A,&H25,&H11,&H6B,&H64,&H89,&H4A,&H63,&H39,&H8A,&H23,&H31,&H2A,&HEA,&HA2,&HA9,&H44,&HC5,&H12,&HCD,&H42

' E0
Data &H34,&H8C,&H62,&H18,&H8C,&H63,&H11,&H48,&H66,&H31,&H9D,&H44,&H33,&H1D,&H46,&H31,&H9C,&HC6,&HB1,&HC,&HCD,&H32,&H88,&HC4,&H73,&H18,&H86,&H73,&H08,&HD6,&H63,&H58

' 100
Data &H07,&H81,&HE0,&HF0,&H3C,&H07,&H87,&H90,&H3C,&H7C,&HF,&HC7,&HC0,&HC0,&HF0,&H7C,&H1E,&H07,&H80,&H80,&H00,&H1C,&H78,&H70,&HF1,&HC7,&H1F,&HC0,&HC,&HFE,&H1C,&H1F

' 120
Data &H1F,&HE,&HA,&H7A,&HC0,&H71,&HF2,&H83,&H8F,&H03,&HF,&HF,&HC,&H00,&H79,&HF8,&H61,&HE0,&H43,&HF,&H83,&HE7,&H18,&HF9,&HC1,&H13,&HDA,&HE9,&H63,&H8F,&HF,&H83

' 140
Data &H83,&H87,&HC3,&H1F,&H3C,&H70,&HF0,&HE1,&HE1,&HE3,&H87,&HB8,&H71,&HE,&H20,&HE3,&H8D,&H48,&H78,&H1C,&H93,&H87,&H30,&HE1,&HC1,&HC1,&HE4,&H78,&H21,&H83,&H83,&HC3

' 160
Data &H87,&H06,&H39,&HE5,&HC3,&H87,&H07,&HE,&H1C,&H1C,&H70,&HF4,&H71,&H9C,&H60,&H36,&H32,&HC3,&H1E,&H3C,&HF3,&H8F,&HE,&H3C,&H70,&HE3,&HC7,&H8F,&HF,&HF,&HE,&H3C

' 180
Data &H78,&HF0,&HE3,&H87,&H06,&HF0,&HE3,&H07,&HC1,&H99,&H87,&HF,&H18,&H78,&H70,&H70,&HFC,&HF3,&H10,&HB1,&H8C,&H8C,&H31,&H7C,&H70,&HE1,&H86,&H3C,&H64,&H6C,&HB0,&HE1

' 1A0
Data &HE3,&HF,&H23,&H8F,&HF,&H1E,&H3E,&H38,&H3C,&H38,&H7B,&H8F,&H07,&HE,&H3C,&HF4,&H17,&H1E,&H3C,&H78,&HF2,&H9E,&H72,&H49,&HE3,&H25,&H36,&H38,&H58,&H39,&HE2,&HDE

' 1C0
Data &H3C,&H78,&H78,&HE1,&HC7,&H61,&HE1,&HE1,&HB0,&HF0,&HF0,&HC3,&HC7,&HE,&H38,&HC0,&HF0,&HCE,&H73,&H73,&H18,&H34,&HB0,&HE1,&HC7,&H8E,&H1C,&H3C,&HF8,&H38,&HF0,&HE1

' 1E0
Data &HC1,&H8B,&H86,&H8F,&H1C,&H78,&H70,&HF0,&H78,&HAC,&HB1,&H8F,&H39,&H31,&HDB,&H38,&H61,&HC3,&HE,&HE,&H38,&H78,&H73,&H17,&H1E,&H39,&H1E,&H38,&H64,&HE1,&HF1,&HC1

' 200
Data &H4E,&HF,&H40,&HA2,&H02,&HC5,&H8F,&H81,&HA1,&HFC,&H12,&H08,&H64,&HE0,&H3C,&H22,&HE0,&H45,&H07,&H8E,&HC,&H32,&H90,&HF0,&H1F,&H20,&H49,&HE0,&HF8,&HC,&H60,&HF0

' 220
Data &H17,&H1A,&H41,&HAA,&HA4,&HD0,&H8D,&H12,&H82,&H1E,&H1E,&H03,&HF8,&H3E,&H03,&HC,&H73,&H80,&H70,&H44,&H26,&H03,&H24,&HE1,&H3E,&H04,&H4E,&H04,&H1C,&HC1,&H09,&HCC

' 240
Data &H9E,&H90,&H21,&H07,&H90,&H43,&H64,&HC0,&HF,&HC6,&H90,&H9C,&HC1,&H5B,&H03,&HE2,&H1D,&H81,&HE0,&H5E,&H1D,&H03,&H84,&HB8,&H2C,&HF,&H80,&HB1,&H83,&HE0,&H30,&H41

' 260
Data &H1E,&H43,&H89,&H83,&H50,&HFC,&H24,&H2E,&H13,&H83,&HF1,&H7C,&H4C,&H2C,&HC9,&HD,&H83,&HB0,&HB5,&H82,&HE4,&HE8,&H06,&H9C,&H07,&HA0,&H99,&H1D,&H07,&H3E,&H82,&H8F

' 280
Data &H70,&H30,&H74,&H40,&HCA,&H10,&HE4,&HE8,&HF,&H92,&H14,&H3F,&H06,&HF8,&H84,&H88,&H43,&H81,&HA,&H34,&H39,&H41,&HC6,&HE3,&H1C,&H47,&H03,&HB0,&HB8,&H13,&HA,&HC2

' 2A0
Data &H64,&HF8,&H18,&HF9,&H60,&HB3,&HC0,&H65,&H20,&H60,&HA6,&H8C,&HC3,&H81,&H20,&H30,&H26,&H1E,&H1C,&H38,&HD3,&H01,&HB0,&H26,&H40,&HF4,&HB,&HC3,&H42,&H1F,&H85,&H32

' 2C0
Data &H26,&H60,&H40,&HC9,&HCB,&H01,&HEC,&H11,&H28,&H40,&HFA,&H04,&H34,&HE0,&H70,&H4C,&H8C,&H1D,&H07,&H69,&H03,&H16,&HC8,&H04,&H23,&HE8,&HC6,&H9A,&HB,&H1A,&H03,&HE0

' 2E0
Data &H76,&H06,&H05,&HCF,&H1E,&HBC,&H58,&H31,&H71,&H66,&H00,&HF8,&H3F,&H04,&HFC,&HC,&H74,&H27,&H8A,&H80,&H71,&HC2,&H3A,&H26,&H06,&HC0,&H1F,&H05,&HF,&H98,&H40,&HAE

' 300
Data &H01,&H7F,&HC0,&H07,&HFF,&H00,&HE,&HFE,&H00,&H03,&HDF,&H80,&H03,&HEF,&H80,&H1B,&HF1,&HC2,&H00,&HE7,&HE0,&H18,&HFC,&HE0,&H21,&HFC,&H80,&H3C,&HFC,&H40,&HE,&H7E

' 320
Data &H00,&H3F,&H3E,&H00,&HF,&HFE,&H00,&H1F,&HFF,&H00,&H3E,&HF0,&H07,&HFC,&H00,&H7E,&H10,&H3F,&HFF,&H00,&H3F,&H38,&HE,&H7C,&H01,&H87,&HC,&HFC,&HC7,&H00,&H3E,&H04

' 340
Data &HF,&H3E,&H1F,&HF,&HF,&H1F,&HF,&H02,&H83,&H87,&HCF,&H03,&H87,&HF,&H3F,&HC0,&H07,&H9E,&H60,&H3F,&HC0,&H03,&HFE,&H00,&H3F,&HE0,&H77,&HE1,&HC0,&HFE,&HE0,&HC3

' 360
Data &HE0,&H01,&HDF,&HF8,&H03,&H07,&H00,&H7E,&H70,&H00,&H7C,&H38,&H18,&HFE,&HC,&H1E,&H78,&H1C,&H7C,&H3E,&HE,&H1F,&H1E,&H1E,&H3E,&H00,&H7F,&H83,&H07,&HDB,&H87,&H83

' 380
Data &H07,&HC7,&H07,&H10,&H71,&HFF,&H00,&H3F,&HE2,&H01,&HE0,&HC1,&HC3,&HE1,&H00,&H7F,&HC0,&H05,&HF0,&H20,&HF8,&HF0,&H70,&HFE,&H78,&H79,&HF8,&H02,&H3F,&HC,&H8F,&H03

' 3a0
Data &HF,&H9F,&HE0,&HC1,&HC7,&H87,&H03,&HC3,&HC3,&HB0,&HE1,&HE1,&HC1,&HE3,&HE0,&H71,&HF0,&H00,&HFC,&H70,&H7C,&HC,&H3E,&H38,&HE,&H1C,&H70,&HC3,&HC7,&H03,&H81,&HC1

' 3c0
Data &HC7,&HE7,&H00,&HF,&HC7,&H87,&H19,&H09,&HEF,&HC4,&H33,&HE0,&HC1,&HFC,&HF8,&H70,&HF0,&H78,&HF8,&HF0,&H61,&HC7,&H00,&H1F,&HF8,&H01,&H7C,&HF8,&HF0,&H78,&H70,&H3C

' 3e0
Data &H7C,&HCE,&HE,&H21,&H83,&HCF,&H08,&H07,&H8F,&H08,&HC1,&H87,&H8F,&H80,&HC7,&HE3,&H00,&H07,&HF8,&HE0,&HEF,&H00,&H39,&HF7,&H80,&HE,&HF8,&HE1,&HE3,&HF8,&H21,&H9F

' 400
Data &HC0,&HFF,&H03,&HF8,&H07,&HC0,&H1F,&HF8,&HC4,&H04,&HFC,&HC4,&HC1,&HBC,&H87,&HF0,&HF,&HC0,&H7F,&H05,&HE0,&H25,&HEC,&HC0,&H3E,&H84,&H47,&HF0,&H8E,&H03,&HF8,&H03

' 420
Data &HFB,&HC0,&H19,&HF8,&H07,&H9C,&HC,&H17,&HF8,&H07,&HE0,&H1F,&HA1,&HFC,&HF,&HFC,&H01,&HF0,&H3F,&H00,&HFE,&H03,&HF0,&H1F,&H00,&HFD,&H00,&HFF,&H88,&HD,&HF9,&H01

' 440
Data &HFF,&H00,&H70,&H07,&HC0,&H3E,&H42,&HF3,&HD,&HC4,&H7F,&H80,&HFC,&H07,&HF0,&H5E,&HC0,&H3F,&H00,&H78,&H3F,&H81,&HFF,&H01,&HF8,&H01,&HC3,&HE8,&HC,&HE4,&H64,&H8F

' 460
Data &HE4,&HF,&HF0,&H07,&HF0,&HC2,&H1F,&H00,&H7F,&HC0,&H6F,&H80,&H7E,&H03,&HF8,&H07,&HF0,&H3F,&HC0,&H78,&HF,&H82,&H07,&HFE,&H22,&H77,&H70,&H02,&H76,&H03,&HFE,&H00

' 480
Data &HFE,&H67,&H00,&H7C,&HC7,&HF1,&H8E,&HC6,&H3B,&HE0,&H3F,&H84,&HF3,&H19,&HD8,&H03,&H99,&HFC,&H09,&HB8,&HF,&HF8,&H00,&H9D,&H24,&H61,&HF9,&HD,&H00,&HFD,&H03,&HF0

' 4a0
Data &H1F,&H90,&H3F,&H01,&HF8,&H1F,&HD0,&HF,&HF8,&H37,&H01,&HF8,&H07,&HF0,&HF,&HC0,&H3F,&H00,&HFE,&H03,&HF8,&HF,&HC0,&H3F,&H00,&HFA,&H03,&HF0,&HF,&H80,&HFF,&H01

' 4c0
Data &HB8,&H07,&HF0,&H01,&HFC,&H01,&HBC,&H80,&H13,&H1E,&H00,&H7F,&HE1,&H40,&H7F,&HA0,&H7F,&HB0,&H00,&H3F,&HC0,&H1F,&HC0,&H38,&HF,&HF0,&H1F,&H80,&HFF,&H01,&HFC,&H03

' 4e0
Data &HF1,&H7E,&H01,&HFE,&H01,&HF0,&HFF,&H00,&H7F,&HC0,&H1D,&H07,&HF0,&HF,&HC0,&H7E,&H06,&HE0,&H07,&HE0,&HF,&HF8,&H06,&HC1,&HFE,&H01,&HFC,&H03,&HE0,&HF,&H00,&HFC

' END PART 4
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' END render_tabs.h
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' BEGIN render.c
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

' Initialize arrays
' mouth formants (F1) 5..29
Data 0,0,0,0,0,10,14,19,24,27,23,21,16,20,14,18,14,18,18,16,13,15,11,18,14,11,9,6,6,6
For iIndex = 5 To 29
    Read arrMouthFormants5_29(iIndex)
Next iIndex

' throat formants (F2) 5..29
Data 255,255,255,255,255,84,73,67,63,40,44,31,37,45,73,49,36,30,51,37,29,69,24,50,30,24,83,46,54,86
For iIndex = 5 To 29
    Read arrThroatFormants5_29(iIndex)
Next iIndex

' formant 1 frequencies (mouth) 48..53
Data 19,27,21,27,18,13
For iIndex = 0 To 5
    Read arrMouthFormants48_53(iIndex)
Next iIndex

' formant 2 frequencies (throat) 48..53
Data 72,39,31,43,30,34
For iIndex = 0 To 5
    Read arrThroatFormants48_53(iIndex)
Next iIndex

' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' END render.c
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++



' *** HERE IS WHERE THE MAIN EXECUTION (MENU ETC.) WOULD GO #MAIN

' For now we'll hardcode the test routines to run...
TestHello

TestPhonemes

' *** END MAIN EXECUTION @MAIN












' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' Begin test_hello.c
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

' Main program
Sub TestHello
    Dim in$
    Input "Enter text to speak (all caps, include phonemes like '[')", in$

    ' Set the input (assuming SetInput$ function exists)
    ' in$ = "HELLO WORLD ["  ' Hardcoded input replaced by user input
    ' SetInput in$

    ' Simulate SetInput (replace with actual QB64 implementation if available)
    Print "Setting input to: "; in$

    ' Run SAMMain (assuming SAMMain function exists and returns 0 for false, non-zero for true)
    ' samResult = SAMMain()
    ' IF samResult = 0 THEN
    '    PRINT "SAMMain failed"
    '    SYSTEM
    ' END IF

    'Simulate SAMMain (replace with actual QB64 implementation)
    Print "Simulating SAMMain..."
    samResult = -1 ' Simulate success

    If samResult = 0 Then
        Print "SAMMain failed"
        End
    End If

    ' Get the buffer and its length (assuming these functions exist)
    ' buffer$ = GetBuffer$()
    ' bufferLength = GetBufferLength()

    'Simulate GetBuffer and GetBufferLength
    buffer$ = "Simulated speech data"
    bufferLength = 1000

    ' Call WriteWav
    wavResult = WriteWav(buffer$, bufferLength \ 50) ' Integer division in QB64 is '\'

    Print "WriteWav returned: "; wavResult

    Print "Done!"
    Sleep
    'END

End Sub ' TestHello

' Stub for WriteWav (since the C version just returns 0)
Function WriteWav% (buffer As String, bufferlength As Integer)
    WriteWav = 0
End Function


' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' End test_hello.c
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++






' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' Begin test_phonemes.c
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Sub TestPhonemes
    'Constants
    Const END_MARKER = "0,0" ' Using a string to represent the end marker
    Const C_SIZE = 1024
   
    'Test State
    Type TestState
        fails As Long
        passes As Long
    End Type
   
    'Data Structure
    Type TestCase
        testInput As String
        expected As String
    End Type
   
    Dim sTemp As String ' * C_SIZE  ' Fixed-length string
    Dim test_case(1 To 20) As TestCase ' Adjust size as needed based on your test data
    Dim test_state As TestState
    Dim state As TestState
    Dim iIndex As Integer
    Dim bResult As Integer
   
    ' *** NOTE
    ' PROBABLY NEED TO CALL Init BEFORE ANYTHING ?
   
   
    ' Initialize test cases (manually, since we can't directly translate C's array initialization)
    '------------------------------------------------------------------------------------------
    ' Manually populate the test cases.  This is tedious, but necessary in QB64.
    ' Note:  The index in QB64 starts at 1 by default, so adjust accordingly.
    ' Also, QB64 doesn't have direct equivalent for C's string literals with embedded newlines.
    '      We'll use multiline strings (might need QB64PE specific syntax) or concatenation.

    test_case(1).testInput = "HELLO"
    test_case(1).expected = " /HEHLOW"

    test_case(2).testInput = "WIZARD"
    test_case(2).expected = " WIHZAA5RD"

    test_case(3).testInput = "TWO THINGS"
    test_case(3).expected = " TUW THIHNXZ"

    test_case(4).testInput = "ANOTHER TRAVELER"
    test_case(4).expected = " AENAH5DHER TRAEVIY4LER"

    test_case(5).testInput = "HELLO, MY NAME IS SAM."
    test_case(5).expected = " /HEHLOW, MAY NEYM IHZ SAEM."

    test_case(6).testInput = "THE SKY ABOVE THE PORT WAS THE COLOR OF TELEVISION, TUNED TO A DEAD CHANNEL."
    test_case(6).expected = " DHAX SKAY AEBAH4V DHAX PAORT WAHZ DHAX KAALER AHV TEHLEHVIHZHUN, TUWND TUX AH DEHDCHAENEHL."

    test_case(7).testInput = "IT'S NOT LIKE I'M USING, CASE HEARD SOMEONE SAY, AS HE SHOULDERED HIS WAY THROUGH THE CROWD AROUND THE DOOR OF THE CHAT."
    test_case(7).expected = " IHTS NAAT LAY5K IHM YUWZIHNX, KEY4S /HIY5RD SAHMWAHN SEY5, AEZ /HIY SHUH5DIY4RD /HIHSWEY5 THRUW4 DHAX KROWD AXRAWND DHAX DOH5R AHV DHAX CHAET."

    test_case(8).testInput = "ITS LIKE MY BODYS DEVELOPED THIS MASSIVE DRUG DEFICIENCY."
    test_case(8).expected = " IHTS LAY5K MAY BAADIYS DIHVEHLOW5PT DHIHS MAESIHV DRAHG DIHFIHSHEHNSIY."

    test_case(9).testInput = "IT WAS A SPRAWL VOICE AND A SPRAWL JOKE."
    test_case(9).expected = " IHT WAHZ AH SPRAO5L VOY5S AEND AH SPRAO5L JOW5K."

    test_case(10).testInput = "THE CHATSUBO WAS A BAR FOR PROFESSIONAL EXPATRIATES YOU COULD DRINK THERE FOR A WEEK AND NEVER HEAR TWO WORDS IN JAPANESE."
    test_case(10).expected = " DHAX CHAETSUWBOW WAHZ AH BAA5R FAOR PROW5FEHSHUNUL EHKSPAETRIHEYTS YUW KUH5D DRIHNXK DHEHRFER AH WIY4K AEND NEH4VER /HIY5R TUW WERDZ IHN JAEPEYNIY4Z."

    test_case(11).testInput = "RATZ WAS TENDING BAR, HIS PROSTHETIC ARM JERKING MONOTONOUSLY AS HE FILLED A TRAY OF GLASSES WITH DRAFT KIRIN."
    test_case(11).expected = " RAETZ WAHZ TEHNDIHNX BAA5R, /HIHZ PROWSTHEHTIHK AA5RM JERKIHNX MAHNAATUNAXSLIY AEZ /HIY FIHLEHDAH TREY5 AHV GLAESIHZ WIHTH"

    test_case(12).testInput = "HE SAW CASE AND SMILED, HIS TEETH A WEB WORK OF EAST EUROPEAN STEEL AND BROWN DECAY."
    test_case(12).expected = " /HIY SAO5 KEY4S AEND SMAY5LD, /HIHZ TIY4TH AH WEHB WERK AHV IY5ST YUW5RAAPIY5N STIY4L AENDBROWN DIHKEY5."

    test_case(13).testInput = "CASE FOUND A PLACE AT THE BAR, BETWEEN THE UNLIKELY TAN ON ONE OF LONNY ZONE'S WHORES AND THE CRISP NAVAL UNIFORM OF A TALL AFRICAN WHOSE CHEEKBONES WERE RIDGED WITH PRECISE ROWS OF TRIBAL SCARS."
    test_case(13).expected = " KEY4S FAWND AH PLEYS AET DHAX BAA5R, BEHTWIY4N DHIY AHNLIHKLIY TAEN AAN WAHN AHV LAHNIYZUNEHS /HUWRZ AEND DHAX KRIHSP NAEVUL YUWNIHFAORM AHV AH TAOL AEFRIHKAEN /HUWZEHKIY4KBOW5NZ WER RIHDJD WIHTH PREHSAYZ ROWZ AHV TRIHBUL SKAA5RZ."

    test_case(14).testInput = "WAGE WAS IN HERE EARLY, WITH TWO JOE BOYS, RATZ SAID, SHOVING A DRAFT ACROSS THE BAR WITH HIS GOOD HAND."
    test_case(14).expected = " WEYJ WAHZ IHN /HIYR ER5LIY, WIHTH TUW JOW BOYZ, RAETZ SEHD, SHAH4VIHNX AH DRAEFTAEKRAO5S DHAX BAA5R WIHTH /HIHZ GUH5D /HAEND."

    test_case(15).testInput = "MAYBE SOME BUSINESS WITH YOU, CASE. CASE SHRUGGED."
    test_case(15).expected = " MEY5B SAHM BIH4ZIHNEHS WIHTH YUW, KEY4S. KEY4S SHRAH5GD."

    test_case(16).testInput = "THE GIRL TO HIS RIGHT GIGGLED AND NUDGED HIM."
    test_case(16).expected = " DHAX GERL TUX /HIHZ RAY4T GIHGULD AEND NAH5DJD /HIHM."

    ' Assuming END is a sentinel value, find the end of the data.
    last_test_case = 16 'Hardcoded for now, find a better way if possible

    'Main Program
    'No direct equivalent to C's main, so the following code is the main logic

    For iIndex = 1 To last_test_case
        ' call sam to process input, store in sTemp
        ' MOCKING sam and reciter calls for now
        sTemp = "MOCKED OUTPUT FOR: " + test_case(iIndex).testInput ' Replace with actual SAM and reciter calls

        'trim ' Remove any trailing garbage from sTemp
        sTemp = _Trim$(sTemp)
       
        If compare%(sTemp, test_case(iIndex).expected) Then
            test_state.passes = test_state.passes + 1
            Print "PASS: "; test_case(iIndex).testInput
        Else
            test_state.fails = test_state.fails + 1
            Print "FAIL: "; test_case(iIndex).testInput
            Print "  Expected: "; test_case(iIndex).expected
            Print "  Actual:   "; sTemp
        End If

    Next iIndex

    Print
    Print "--- SUMMARY ---"
    Print "Passes: "; test_state.passes
    Print "Fails:  "; test_state.fails

    'END 'End of main program

    ' Main program starts here
    ' Initialize state
    state.fails = 0
    state.passes = 0

    ' Verify reciter tables
    ReciterVerify

    ' Test cases (need to be adapted based on how test_case is structured)
    ' Example data - adjust as needed:
    Data "test1","expected1","test2","expected2",""
    Read test_case1$, test_case2$
    Do While Len(test_case1$) > 0
        If try_test$(test_case1$, test_case2$) = "0" Then
            Print "x";
            state.fails = state.fails + 1
        Else
            Print ".";
            state.passes = state.passes + 1
        End If
        Read test_case1$, test_case2$
    Loop

    ' Input test files (assuming SAM_TEST_DIR is a constant)
    ' *** NOT SURE WHAT file_test$ IS OR DOES ??? ***
    bResult = file_test%(m_ProgramPath$ + "words.txt", state) '  Need to adjust path as needed
    If bResult = _FALSE Then Print "File " + Chr$(34) + "words.txt" + Chr$(34) + " not found."
   
    bResult = file_test%(m_ProgramPath$ + "sentences.txt", state) ' Need to adjust path as needed
    If bResult = _FALSE Then Print "File " + Chr$(34) + "sentences.txt" + Chr$(34) + " not found."
   
    ' Print summary
    Print
    Print "total : "; state.fails + state.passes
    Print "failed: "; state.fails
    Print "passed: "; state.passes
   
    If state.fails > 0 Then
        Input "Press Enter to continue", a$
    End If
   
    'SYSTEM '  End program
   
End Sub ' TestPhonemes

'Function Definitions
Function compare% (sVal1 As String, sVal2 As String)
    Dim iPos1 As Integer
    Dim iPos2 As Integer
    Dim iLen1 As Integer
    Dim iLen2 As Integer
   
    compare% = _TRUE ' Default to true
    iLen1 = Len(sVal1)
    iLen2 = Len(sVal2)
   
    iPos1 = 1
    iPos2 = 1
   
    Do While iPos1 <= iLen1 And iPos2 <= iLen2
       
        If Mid$(sVal2, iPos2, 1) > Chr$(127) Then 'Simulate checking for 0x80 (not directly possible)
            Exit Do
        End If
       
        If Mid$(sVal1, iPos1, 1) <> Mid$(sVal2, iPos2, 1) Then
            compare% = _FALSE
            Exit Function
        End If
        iPos1 = iPos1 + 1
        iPos2 = iPos2 + 1
    Loop
   
    If iPos1 <= iLen1 Or (iPos2 <= iLen2 And Asc(Mid$(sVal2, iPos2, 1)) < 128) Then ' Check if either string has leftover
        compare% = _FALSE
    End If
   
End Function ' compare%



'SUB trim
'    FOR i = 1 TO LEN(temp)
'        IF ASC(MID$(temp, i, 1)) > 127 THEN  'Simulate checking for 0x80
'            temp = LEFT$(temp, i - 1)
'            EXIT SUB
'        END IF
'    NEXT i
'END SUB

' Function: try_test
' Tests a given input string against an expected phoneme output.
' Parameters:
'   in$ - The input string to convert to phonemes.
'   match$ - The expected phoneme output.
' Returns:
'   1 if the actual output matches the expected output, 0 otherwise.
Function try_test$ (in$, match$)
    ' Assuming C_SIZE is defined as a constant elsewhere (e.g., CONST C_SIZE = 256)
    Dim sTemp As String ' * 256 ' Adjust size as needed, using a fixed-length string

    sTemp = String$(256, 128) ' Initialize with ASCII 128 (0x80) -  QBasic/QB64 doesn't have memset like C
    sTemp = in$
    sTemp = sTemp + "["

    'max_size = 250
    If TextToPhonemes(sTemp, 250) < 1 Then
        try_test$ = "0"
        Exit Function
    End If
    sTemp = Left$(sTemp, 255) ' QB64 string length is limited; ensure null termination isn't an issue
    sTemp = _Trim$(sTemp) '  Need to implement a trim$ function in QB64

    'IF StrComp(match$, sTemp, 0) <> 0 THEN
    If compare%(match$, sTemp) <> 0 Then
        Print
        Print "sent"
        Print "'" + in$ + "'"
        Print "expected"
        Print "'" + match$ + "'"
        Print "got"
        Print "'" + sTemp + "'"
        try_test$ = "0"
        Exit Function
    End If

    try_test$ = "1"
End Function ' try_test$


' Function: read_line
' Reads a line from a file.
' Parameters:
'   fd - The file handle.
'   dst$ - The string to store the read line.
'   max_len - The maximum number of characters to read.  Not directly used in QB64 implementation
' Returns:
'   The length of the read line.
Function read_line% (fd As Long, dst$) ' QB64 doesn't have size_t, using INTEGER
    Dim ptr As Long
    Dim size As Integer
    Dim ch As String * 1

    size = 0
    Do
        If EOF(fd) Then
            read_line% = 0
            Exit Function
        End If
        Get #fd, , ch
        If Len(ch) = 0 Then
            read_line% = 0
            Exit Function
        End If
        If ch = Chr$(10) Then
            Exit Do
        End If
        If ch = Chr$(13) Then

        Else
            dst$ = dst$ + UCase$(ch) ' QB64 UCASE$ for toupper
            size = size + 1
        End If
    Loop
    read_line% = size
End Function

' Function: file_test
' Tests phoneme conversion on lines from a file.
' Parameters:
'   path$ - The path to the test file.
'   state - A structure to track test results.  Must be adapted for QB64
' Returns:
'   1 if the test completes successfully, 0 otherwise.
Function file_test% (path$, state As TestState)
    Dim fd As Long
    Dim sTemp1 As String
    Dim sTemp2 As String
    Dim iLen As Integer
   
    Open path$ For Binary As #fd
    If LOF(fd) = 0 Then ' Instead of fd = 0
        file_test% = _FALSE
        Exit Function
    End If
    Do
        iLen = read_line%(fd, sTemp1)
        If iLen = 0 Then
            Exit Do
        End If
        sTemp1 = sTemp1 + "["
        sTemp2 = sTemp1
       
        'max_size = 250
        If TextToPhonemes(sTemp1, 250) > 0 Then
            Print ".";
            state.passes = state.passes + 1
        Else
            Print "x";
            Print
            Print sTemp2
            state.fails = state.fails + 1
        End If
        sTemp1 = "" '  Reset sTemp1 for next loop
    Loop
    Close #fd
    file_test% = _TRUE
End Function ' file_test%

' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' End test_phonemes.c
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' BEGIN sam.c
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Sub Init
    Dim i As Integer
    Call SetMouthThroat(mouth, throat)
    bufferPos = 0

    'Allocate memory - QB64 uses _NEW for this (similar to malloc)
    'Note:  _NEW returns a pointer, and we need to allocate enough space for bytes (_BYTE)
    'TODO: do we need to do _MEM stuff here?
    'buffer = _NEW _BYTE[22050 * 10]

    'The original C code had commented-out assignments to memory locations.
    'It's likely these are related to how the original C code interfaced with memory.
    'We'll leave them commented out in QB64, as we don't have the context to translate them directly.
    'If you have more information on what these memory locations represent, we can refine this.

    'freq2data = &mem[45136]
    'freq1data = &mem[45056]
    'freq3data = &mem[45216]
    'pitches = &mem[43008]
    'frequency1 = &mem[43264]
    'frequency2 = &mem[43520]
    'frequency3 = &mem[43776]
    'amplitude1 = &mem[44032]
    'amplitude2 = &mem[44288]
    'amplitude3 = &mem[44544]
    'phoneme = &mem[39904]
    'ampl1data = &mem[45296]
    'ampl2data = &mem[45376]
    'ampl3data = &mem[45456]

    For i = 0 To 255
        arrStress1(i) = 0
        arrPhonemeLength(i) = 0
    Next i

    For i = 0 To 59
        arrPhoIndexOutput(i) = 0
        arrStressOutput(i) = 0
        arrPhoLengthOutput(i) = 0
    Next i

    arrPhonemeIndex(255) = 255 'Prevent buffer overflow
End Sub

Function Main% ()
    Init
    arrPhonemeIndex(255) = 32 '//to prevent buffer overflow

    If Parser1% = _FALSE Then
        Main% = _FALSE
        Exit Function
    End If

    If (bDebug) Then
        PrintPhonemes arrPhonemeIndex(), arrPhonemeLength(), arrStress1()
    End If

    Parser2
    CopyStress
    SetPhonemeLength
    AdjustLengths
    Code41240

    Do
        A = arrPhonemeIndex(X)
        If (A > 80) Then
            arrPhonemeIndex(X) = 255
            Exit Do '// error: delete all behind it
        End If
        X = X + 1
    Loop Until X = 0

    '//pos39848:
    InsertBreath

    '//mem(40158) = 255
    If (bDebug) Then
        PrintPhonemes arrPhonemeIndex(), arrPhonemeLength(), arrStress1()
    End If

    PrepareOutput
    Main% = _TRUE
End Function ' Main

Sub SetInput (inputString As String)
    'Converts a QB64 String to a _BYTE array
    Dim i As Integer
    Dim l As Integer
    l = Len(inputString)
    If l > 254 Then l = 254

    For i = 1 To l
        arrInput1(i - 1) = Asc(Mid$(inputString, i, 1))
    Next i
    arrInput1(l) = 0 'Null terminate (C-style strings)
End Sub

Sub SetSpeed (inputSpeed As _Byte)
    speed = inputSpeed
End Sub

Sub SetPitch (inputPitch As _Byte)
    pitch = inputPitch
End Sub

Sub SetMouth (inputMouth As _Byte)
    mouth = inputMouth
End Sub

Sub SetThroat (inputThroat As _Byte)
    throat = inputThroat
End Sub

Sub EnableSingmode
    singmode = 1
End Sub

Function GetBuffer$ ()
    'Need to convert the _OFFSET to a QB64 String
    Dim result As String
   
    If buffer = 0 Then Exit Function 'Handle null pointer

    For i = 0 To bufferPos - 1
        result = result + Chr$(buffer(i))
    Next i

    GetBuffer$ = result
End Function

Function GetBufferLength% ()
    GetBufferLength = bufferPos
End Function


Sub PrepareOutput ()
    Dim iTemp As Integer
    A = 0
    X = 0
    Y = 0

    '//pos48551:
    Do While -1 '// Infinite loop, equivalent to while(1)
        A = arrPhonemeIndex(X)
        If (A = 255) Then
            A = 255
            arrPhoIndexOutput(Y) = 255
            Render
            Exit Sub
        End If
        If (A = 254) Then
            X = X + 1
            iTemp = X '// Local variable to mimic C's temp
            '//mem(48546) = X
            arrPhoIndexOutput(Y) = 255
            Render
            '//X = mem(48546)
            X = iTemp
            Y = 0
            _Continue
        End If

        If (A = 0) Then
            X = X + 1
            _Continue
        End If

        arrPhoIndexOutput(Y) = A
        arrPhoLengthOutput(Y) = arrPhonemeLength(X)
        arrStressOutput(Y) = arrStress1(X)
        X = X + 1
        Y = Y + 1
    Loop
End Sub ' PrepareOutput

Sub InsertBreath ()
    Dim mem54 As _Byte
    Dim mem55 As _Byte
    Dim index As _Byte 'variable Y
    Dim mem66 As _Byte
   
    mem54 = 255
    X = X + 1
    mem55 = 0
    mem66 = 0
    Do
        'pos48440:
        X = mem66
        index = arrPhonemeIndex(X)
        If index = 255 Then
            Exit Sub
        End If
        mem55 = mem55 + arrPhonemeLength(X)

        If mem55 < 232 Then
            If index <> 254 Then ' ML : Prevents an index out of bounds problem
                A = arrFlags2(index) And 1
                If A <> 0 Then
                    X = X + 1
                    mem55 = 0
                    Call Insert(X, 254, mem59, 0)
                    mem66 = mem66 + 1
                    mem66 = mem66 + 1
                    _Continue
                End If
            End If
            If index = 0 Then
                mem54 = X
            End If
            mem66 = mem66 + 1
        Else
            X = mem54
            arrPhonemeIndex(X) = 31 ' 'Q*' glottal stop
            arrPhonemeLength(X) = 4
            arrStress1(X) = 0
            X = X + 1
            mem55 = 0
            Call Insert(X, 254, mem59, 0)
            X = X + 1
            mem66 = X
        End If
       
    Loop
End Sub ' InsertBreath

Sub CopyStress ()
    ' loop thought all the phonemes to be output
    Dim iPos As Integer ' _BYTE
    iPos = 0 'mem66
    Do
        ' get the phomene
        Y = arrPhonemeIndex(iPos)
        ' exit at end of buffer
        If Y = 255 Then
            Exit Sub
        End If
        ' if CONSONANT_FLAG set, skip - only vowels get stress
        If (arrFlags1(Y) And 64) = 0 Then
            iPos = iPos + 1
            _Continue
        End If
        ' get the next phoneme
        Y = arrPhonemeIndex(iPos + 1)
        If Y = 255 Then 'prevent buffer overflow
            iPos = iPos + 1
            _Continue
        Else
            ' if the following phoneme is a vowel, skip
            If (arrFlags1(Y) And 128) = 0 Then
                iPos = iPos + 1
                _Continue
            End If
        End If

        ' get the stress value at the next position
        Y = arrStress1(iPos + 1)
        ' if next phoneme is not stressed, skip
        If Y = 0 Then
            iPos = iPos + 1
            _Continue
        End If

        ' if next phoneme is not a VOWEL OR ER, skip
        If (Y And 128) <> 0 Then
            iPos = iPos + 1
            _Continue
        End If

        ' copy stress from prior phoneme to this one
        arrStress1(iPos) = Y + 1
        ' advance pointer
        iPos = iPos + 1
       
    Loop
End Sub ' CopyStress

Sub Insert (position As _Byte, mem60 As _Byte, mem59 As _Byte, mem58 As _Byte)
    Dim i As Integer
    For i = 253 To position Step -1 ' ML : always keep last safe-guarding 255
        arrPhonemeIndex(i + 1) = arrPhonemeIndex(i)
        arrPhonemeLength(i + 1) = arrPhonemeLength(i)
        arrStress1(i + 1) = arrStress1(i)
    Next i

    arrPhonemeIndex(position) = mem60
    arrPhonemeLength(position) = mem59
    arrStress1(position) = mem58
End Sub ' Insert

'--------------------------------------------------------------------------------------------------------------------
' Parser1 Function
'--------------------------------------------------------------------------------------------------------------------

Function Parser1% ()
    Dim iIndex As Integer
    Dim sign1 As _Unsigned _Byte
    Dim sign2 As _Unsigned _Byte
    Dim position As _Unsigned _Byte
    position = 0
    X = 0
    A = 0
    Y = 0

    ' CLEAR THE STRESS TABLE
    For iIndex = 0 To 255
        arrStress1(iIndex) = 0
    Next iIndex

    ' THIS CODE MATCHES THE PHONEME LETTERS TO THE TABLE
    Do
        ' GET THE FIRST CHARACTER FROM THE PHONEME BUFFER
        sign1 = arrInput1(X) ' Assuming arrInput1 is 1-based array

        ' TEST FOR 155 () END OF LINE MARKER
        If sign1 = 155 Then
            ' MARK ENDPOINT AND RETURN
            arrPhonemeIndex(position) = 255
            'mark endpoint
            ' REACHED END OF PHONEMES, SO EXIT
            Parser1% = _TRUE ' all ok
            Exit Function
        End If

        ' GET THE NEXT CHARACTER FROM THE BUFFER
        X = X + 1
        sign2 = arrInput1(X)

        ' NOW sign1 = FIRST CHARACTER OF PHONEME, AND sign2 = SECOND CHARACTER OF PHONEME

        ' TRY TO MATCH PHONEMES ON TWO TWO-CHARACTER NAME
        ' IGNORE PHONEMES IN TABLE ENDING WITH WILDCARDS

        ' SET INDEX TO 0
        Y = 0

        Do
            ' GET FIRST CHARACTER AT POSITION Y IN signInputTable
            ' --> should change name to PhonemeNameTable1
            A = arrSignInputTable1(Y) ' Assuming arrSignInputTable1 is 0-based

            ' FIRST CHARACTER MATCHES?
            If A = sign1 Then
                ' GET THE CHARACTER FROM THE PhonemeSecondLetterTable
                A = arrSignInputTable2(Y)

                ' NOT A SPECIAL AND MATCHES SECOND CHARACTER?
                If (A <> Asc("*")) And (A = sign2) Then 'QB64 uses ASC() for character to ASCII
                    ' STORE THE INDEX OF THE PHONEME INTO THE phomeneIndexTable
                    arrPhonemeIndex(position) = Y

                    ' ADVANCE THE POINTER TO THE phonemeIndexTable
                    position = position + 1

                    ' ADVANCE THE POINTER TO the phonemeInputBuffer
                    X = X + 1

                    ' CONTINUE PARSING
                    _Continue
                End If
            End If

            ' NO MATCH, TRY TO MATCH ON FIRST CHARACTER TO WILDCARD NAMES (ENDING WITH '*')

            ' ADVANCE TO THE NEXT POSITION
            Y = Y + 1

            ' IF NOT END OF TABLE, CONTINUE
            If Y <> 81 Then
                'GOTO pos41095  ' QB64 doesn't encourage GOTO, using DO...LOOP
                _Continue
            End If

            ' REACHED END OF TABLE WITHOUT AN EXACT (2 CHARACTER) MATCH.
            ' THIS TIME, SEARCH FOR A 1 CHARACTER MATCH AGAINST THE WILDCARDS

            ' RESET THE INDEX TO POINT TO THE START OF THE PHONEME NAME TABLE
            Y = 0

            Do
                ' DOES THE PHONEME IN THE TABLE END WITH '*'?
                If arrSignInputTable2(Y) = Asc("*") Then
                    ' DOES THE FIRST CHARACTER MATCH THE FIRST LETTER OF THE PHONEME
                    If arrSignInputTable1(Y) = sign1 Then
                        ' SAVE THE POSITION AND MOVE AHEAD
                        arrPhonemeIndex(position) = Y

                        ' ADVANCE THE POINTER
                        position = position + 1

                        ' CONTINUE THROUGH THE LOOP
                        _Continue
                    End If
                End If
                Y = Y + 1
                If Y <> 81 Then
                    'GOTO pos41134
                    _Continue
                End If
            Loop

            '81 is size of PHONEME NAME table

            ' FAILED TO MATCH WITH A WILDCARD.
            ' ASSUME THIS IS A STRESS
            ' CHARACTER.
            ' SEARCH THROUGH THE STRESS TABLE

            ' SET INDEX TO POSITION 8 (END OF STRESS TABLE)
            Y = 8

            ' WALK BACK THROUGH TABLE LOOKING FOR A MATCH
            Do While (sign1 <> arrStressInputTable(Y)) And (Y > 0)
                ' DECREMENT INDEX
                Y = Y - 1
            Loop

            ' REACHED THE END OF THE SEARCH WITHOUT BREAKING OUT OF LOOP?
            If Y = 0 Then
                'mem[39444] = X
                '41181: JSR 42043 //Error
                ' FAILED TO MATCH ANYTHING, RETURN 0 ON FAILURE
                Parser1% = _FALSE
                Exit Function
            End If
            ' SET THE STRESS FOR THE PRIOR PHONEME
            arrStress1(position - 1) = Y
        Loop
    Loop
End Function ' Parser1%


'--------------------------------------------------------------------------------------------------------------------
' SetPhonemeLength Subroutine
'--------------------------------------------------------------------------------------------------------------------
Sub SetPhonemeLength
    Dim A As _Unsigned _Byte
    Dim position As Integer
    position = 0

    Do While arrPhonemeIndex(position) <> 255
        A = arrStress1(position)

        '41218: BMI 41229  ' BMI is Branch if Minus (negative) -  QB64 doesn't have direct BMI, emulate with sign check
        If (A = 0) Or ((A And 128) <> 0) Then 'bitwise AND to check high bit (sign)
            arrPhonemeLength(position) = arrPhoLengthTable(arrPhonemeIndex(position))
        Else
            arrPhonemeLength(position) = arrPhoStressedLengthTable(arrPhonemeIndex(position))
        End If
        position = position + 1
    Loop
End Sub

'--------------------------------------------------------------------------------------------------------------------
' Code41240 Subroutine
'--------------------------------------------------------------------------------------------------------------------
Sub Code41240
    Dim iPos As Integer ' _UNSIGNED _BYTE
    iPos = 0

    Do While arrPhonemeIndex(iPos) <> 255
        Dim index As _Unsigned _Byte 'register AC
        X = iPos
        index = arrPhonemeIndex(iPos)

        If (arrFlags1(index) And 2) = 0 Then ' Bitwise AND
            iPos = iPos + 1
            _Continue
        ElseIf (arrFlags1(index) And 1) = 0 Then ' Bitwise AND
            Insert iPos + 1, index + 1, arrPhoLengthTable(index + 1), arrStress1(iPos)
            Insert iPos + 2, index + 2, arrPhoLengthTable(index + 2), arrStress1(iPos)
            iPos = iPos + 3
            _Continue
        End If

        Do
            X = X + 1
            A = arrPhonemeIndex(X)
        Loop Until A <> 0

        If A <> 255 Then
            If (arrFlags1(A) And 8) <> 0 Then
                iPos = iPos + 1
                _Continue
            End If
            If (A = 36) Or (A = 37) Then
                iPos = iPos + 1
                _Continue
            End If ' '/H' '/X'
        End If

        Insert iPos + 1, index + 1, arrPhoLengthTable(index + 1), arrStress1(iPos)
        Insert iPos + 2, index + 2, arrPhoLengthTable(index + 2), arrStress1(iPos)
        iPos = iPos + 3
    Loop
End Sub




' BEGIN Parser2 PART 1
Sub Parser2 ()
    Dim iPos As Integer
   
    'void Parser2()
    ' {
    '  if (debug)
    '   printf("Parser2\n");
    If bDebug Then
        Print "Parser2"
    End If
    ' uint8_t pos = 0; //mem66;
    iPos = 0
    ' uint8_t mem58 = 0;
    mem58 = 0
    ' Loop through phonemes
    Do
        ' SET X TO THE CURRENT POSITION
        X = iPos ' Assuming X is an integer
        ' GET THE PHONEME AT THE CURRENT POSITION
        A = arrPhonemeIndex(iPos) ' Assuming A and arrPhonemeIndex are integers
        ' DEBUG: Print phoneme and index
        If bDebug And A <> 255 Then
            Print X; ": "; arrSignInputTable1(A); arrSignInputTable2(A) ' Assuming arrSignInputTable1 and arrSignInputTable2 are string arrays
        End If
        ' Is phoneme pause?
        If A = 0 Then ' Assuming 0 represents a pause
            '  Move ahead to the
            iPos = iPos + 1
            _Continue ' QB64 equivalent of continue
        End If
        ' If end of phonemes flag reached, exit routine
        If A = 255 Then
            Exit Do ' QB64 equivalent of return
        End If
        ' Copy the current phoneme index to Y
        Y = A ' Assuming Y is an integer
        ' Check for DIPHTONG
        If (arrFlags1(A) And 16) = 0 Then ' Assuming flags is an integer array
            GoTo pos41457
        End If
        ' Not a diphthong. Get the stress
        mem58 = arrStress1(iPos) ' Assuming stress is an integer array
        ' End in IY sound?
        A = arrFlags1(Y) And 32
        ' If ends with IY, use YX, else use WX
        If A = 0 Then
            A = 20
        Else
            A = 21
        End If ' 'WX' = 20 'YX' = 21
        'pos41443:
        ' Insert at WX or YX following, copying the stress
        If bDebug Then
            If A = 20 Then
                Print "RULE: insert WX following diphtong NOT ending in IY sound"
            End If
        End If
        If bDebug Then
            If A = 21 Then
                Print "RULE: insert YX following diphtong ending in IY sound"
            End If
        End If
        Insert iPos + 1, A, mem59, mem58 ' Assuming Insert is a SUB and mem59 is an integer
        X = iPos
        ' Jump to ???
        GoTo pos41749
        pos41457:
        ' Get phoneme
        A = arrPhonemeIndex(X)
        ' Skip this rule if phoneme is not UL
        If A <> 78 Then ' Assuming 78 is the value for UL
            GoTo pos41487
        End If
        ' 'UL'
        A = 24 ' Assuming 24 is the value for 'L
        ' 'L'                 'change 'UL' to 'AX L'
        If bDebug Then
            Print "RULE: UL -> AX L"
        End If
        pos41466:
        ' Get current phoneme stress
        mem58 = arrStress1(X)
        ' Change UL to AX
        arrPhonemeIndex(X) = 13 ' Assuming 13 is the value for AX
        ' 'AX'
        ' Perform insert. Note code below may jump up here with different values
        Insert X + 1, A, mem59, mem58
        iPos = iPos + 1
        ' Move to next phoneme
        _Continue
        pos41487:
        ' Skip rule if phoneme != UM
        If A <> 79 Then ' Assuming 79 is the value for UM
            GoTo pos41495
        End If
        ' 'UM'
        ' Jump up to branch - replaces current phoneme with AX and continues
        A = 27 ' Assuming 27 is the value for M
        ' 'M'  'change 'UM' to  'AX M'
        If bDebug Then
            Print "RULE: UM -> AX M"
        End If
        GoTo pos41466
        pos41495:
        ' Skip rule if phoneme != UN
        If A <> 80 Then ' Assuming 80 is the value for UN
            GoTo pos41503
        End If
        ' 'UN'
        ' Jump up to branch - replaces current phoneme with AX and continues
        A = 28 ' Assuming 28 is the value for N
        ' 'N' 'change UN to 'AX N'
        If bDebug Then
            Print "RULE: UN -> AX N"
        End If
        GoTo pos41466
        pos41503:
        Y = A

        ' VOWEL set?
        A = arrFlags1(A) And 128 'Assumes flags is an array

        ' Skip if not a vowel
        If A <> 0 Then
            ' Get the stress
            A = arrStress1(X) ' Assumes stress is an array

            ' If stressed...
            If A <> 0 Then
                ' Get the following phoneme
                X = X + 1
                A = arrPhonemeIndex(X) ' Assumes arrPhonemeIndex is an array

                ' If following phoneme is a pause
                If A = 0 Then
                    ' Get the phoneme following pause
                    X = X + 1
                    Y = arrPhonemeIndex(X)

                    ' Check for end of buffer flag
                    If Y = 255 Then 'buffer overflow
                        ' ??? Not sure about these flags
                        A = 65 And 128
                    Else
                        ' And VOWEL flag to current phoneme's flags
                        A = arrFlags1(Y) And 128
                    End If

                    ' If following phonemes is not a pause
                    If A <> 0 Then
                        ' If the following phoneme is not stressed
                        A = arrStress1(X)
                        If A <> 0 Then
                            ' Insert a glottal stop and move forward
                            If bDebug Then 'Assumes debug is a variable
                                Print "RULE: Insert glottal stop between two stressed vowels with space between them"
                            End If
                            ' 31 = 'Q'
                            Call Insert(X, 31, mem59, 0) ' Assumes Insert is a SUB
                            iPos = iPos + 1
                            _Continue
                        End If
                    End If
                End If
            End If
        End If

        ' RULES FOR PHONEMES BEFORE R
        '       T R -> CH R
        ' Example: TRACK

        ' Get current position and phoneme
        X = iPos
        A = arrPhonemeIndex(iPos)
        If A <> 23 Then GoTo pos41611 ' 'R'

        ' Look at prior phoneme
        X = X - 1
        A = arrPhonemeIndex(iPos - 1)
        'pos41567:
        If A = 69 Then ' 'T'
            ' Change T to CH
            If bDebug Then
                Print "RULE: T R -> CH R"
            End If
            arrPhonemeIndex(iPos - 1) = 42
            GoTo pos41779
        End If

        ' RULES FOR PHONEMES BEFORE R
        '       D R -> J R
        ' Example: DRY

        ' Prior phonemes D?
        If A = 57 Then ' 'D'
            ' Change D to J
            arrPhonemeIndex(iPos - 1) = 44
            If bDebug Then
                Print "RULE: D R -> J R"
            End If
            GoTo pos41788
        End If

        ' RULES FOR PHONEMES BEFORE R
        '       <VOWEL> R -> <VOWEL> RX
        ' Example: ART

        ' If vowel flag is set change R to RX
        A = arrFlags1(A) And 128
        If bDebug Then
            Print "RULE: R -> RX"
        End If
        If A <> 0 Then
            arrPhonemeIndex(iPos) = 18 ' 'RX'
        End If

        ' continue to next phoneme
        iPos = iPos + 1



        pos41611:
        ' Is phoneme L?
        If A = 24 Then '// 'L'
            ' If prior phoneme does not have VOWEL flag set, move to next phoneme
            If (arrFlags1(arrPhonemeIndex(iPos - 1)) And 128) = 0 Then
                iPos = iPos + 1
                'goto pos41611
                _Continue
            End If
            ' Prior phoneme has VOWEL flag set, so change L to LX and move to next phoneme
            If bDebug Then
                Print "RULE: <VOWEL> L -> <VOWEL> LX"
            End If
            arrPhonemeIndex(X) = 19 '// 'LX'
            iPos = iPos + 1
            'goto pos41611
            _Continue
        End If

        ' Is current phoneme S?
        If A = 32 Then '// 'S'
            ' If prior phoneme is not G, move to next phoneme
            If arrPhonemeIndex(iPos - 1) <> 60 Then
                iPos = iPos + 1
                'goto pos41611
                _Continue
            End If
            ' Replace S with Z and move on
            If bDebug Then
                Print "RULE: G S -> G Z"
            End If
            arrPhonemeIndex(iPos) = 38 '// 'Z'
            iPos = iPos + 1
            'goto pos41611
            _Continue
        End If

        ' Is current phoneme K?
        If A = 72 Then '// 'K'
            ' Get next phoneme
            Y = arrPhonemeIndex(iPos + 1)
            ' If at end, replace current phoneme with KX
            If Y = 255 Then
                arrPhonemeIndex(iPos) = 75
                ' ML : prevents an index out of bounds problem
            Else
                ' VOWELS AND DIPHTONGS ENDING WITH IY SOUND flag set?
                A = arrFlags1(Y) And 32
                If bDebug Then
                    If A = 0 Then
                        Print "RULE: K <VOWEL OR DIPHTONG NOT ENDING WITH IY> -> KX <VOWEL OR DIPHTONG NOT ENDING WITH IY>"
                    End If
                End If
                ' Replace with KX
                If A = 0 Then
                    arrPhonemeIndex(iPos) = 75
                End If
                ' 'KX'
            End If
        Else

            ' Is int8_tacter a G?
            If A = 60 Then '// 'G'
                ' Get the following int8_tacter
                Dim index As _Byte
                index = arrPhonemeIndex(iPos + 1)
                ' At end of buffer?
                If index = 255 Then '//prevent buffer overflow
                    iPos = iPos + 1
                    'goto pos41611
                    _Continue
                Else
                    ' If diphtong ending with YX, move continue processing next phoneme
                    If (arrFlags1(index) And 32) <> 0 Then
                        iPos = iPos + 1
                        'goto pos41611
                        _Continue
                    End If
                    ' replace G with GX and continue processing next phoneme
                    If bDebug Then
                        Print "RULE: G <VOWEL OR DIPHTONG NOT ENDING WITH IY> -> GX <VOWEL OR DIPHTONG NOT ENDING WITH IY>"
                    End If
                    arrPhonemeIndex(iPos) = 63 '// 'GX'
                    iPos = iPos + 1
                    'goto pos41611
                    _Continue
                End If
            End If
        End If

        Y = arrPhonemeIndex(iPos)
        'pos41719:
        ' Replace with softer version?
        A = arrFlags1(Y) And 1
        If A = 0 Then
            GoTo pos41749
        End If
        A = arrPhonemeIndex(iPos - 1)
        If A <> 32 Then '// 'S'
            A = Y
            GoTo pos41812
        End If
        ' Replace with softer version
        If bDebug Then
            Print "RULE: S* "; Chr$(arrSignInputTable1(Y)); Chr$(arrSignInputTable2(Y)); " -> S* "; Chr$(arrSignInputTable1(Y - 12)); Chr$(arrSignInputTable2(Y - 12))
        End If
        arrPhonemeIndex(iPos) = Y - 12
        iPos = iPos + 1
        'goto pos41611
        _Continue

        pos41749:

        '       UW -> UX
        A = arrPhonemeIndex(X)
        If A = 53 Then '// 'UW'
            ' ALVEOLAR flag set?
            Y = arrPhonemeIndex(X - 1)
            A = arrFlags2(Y) And 4
            ' If not set, continue processing next phoneme
            If A = 0 Then
                iPos = iPos + 1
                'goto pos41611
                _Continue
            End If
            If bDebug Then
                Print "RULE: <ALVEOLAR> UW -> <ALVEOLAR> UX"
            End If
            arrPhonemeIndex(X) = 16
            iPos = iPos + 1
            'goto pos41611
            _Continue
        End If



        pos41779:

        If A = 42 Then '// 'CH'
            '       pos41783:
            If bDebug Then
                Print "CH -> CH CH+1"
            End If
            Call Insert(X + 1, A + 1, mem59, arrStress1(X))
            iPos = iPos + 1
            _Continue
        End If

        pos41788:

        If A = 44 Then '// 'J'
            If bDebug Then
                Print "J -> J J+1"
            End If
            Call Insert(X + 1, A + 1, mem59, arrStress1(X))
            iPos = iPos + 1
            _Continue
        End If

        ' Jump here to continue
        pos41812:

        ' Past this point, only process if phoneme is T or D
        If A <> 69 Then '// 'T'
            If A <> 57 Then
                iPos = iPos + 1
                _Continue
            End If '// 'D'
        End If
        'pos41825:

        ' If prior phoneme is not a vowel, continue processing phonemes
        If (arrFlags1(arrPhonemeIndex(X - 1)) And 128) = 0 Then
            iPos = iPos + 1
            _Continue
        End If

        ' Get next phoneme
        X = X + 1
        A = arrPhonemeIndex(X)
        'pos41841
        ' Is the next phoneme a pause?
        If A <> 0 Then
            ' If next phoneme is not a pause, continue processing phonemes
            If (arrFlags1(A) And 128) = 0 Then
                iPos = iPos + 1
                _Continue
            End If
            ' If next phoneme is stressed, continue processing phonemes
            ' FIXME: How does a pause get stressed?
            If arrStress1(X) <> 0 Then
                iPos = iPos + 1
                _Continue
            End If
            'pos41856:
            ' Set phonemes to DX
            If bDebug Then
                Print "RULE: Soften T or D following vowel or ER and preceding a pause -> DX"
            End If
            arrPhonemeIndex(iPos) = 30 '// 'DX'
        Else
            A = arrPhonemeIndex(X + 1)
            If A = 255 Then '//prevent buffer overflow
                A = 65 And 128
            Else
                ' Is next phoneme a vowel or ER?
                A = arrFlags1(A) And 128
            End If
            If bDebug Then
                If A <> 0 Then
                    Print "RULE: Soften T or D following vowel or ER and preceding a pause -> DX"
                End If
            End If
            If A <> 0 Then
                arrPhonemeIndex(iPos) = 30
            End If '// 'DX'
        End If

        iPos = iPos + 1
    Loop '// while
End Sub ' Parser2


Sub AdjustLengths ()

    ' loop index
    Dim X As Integer
    Dim index As _Byte
    Dim A As Integer
    Dim loopIndex As _Byte
    Dim mem56 As Integer
    Dim debugX As Integer

    ' iterate through the phoneme list
    loopIndex = 0
    Do
        ' get a phoneme
        X = loopIndex
        index = arrPhonemeIndex(X)

        ' exit loop if end on buffer token
        If index = 255 Then
            Exit Do
        End If

        ' not punctuation?
        If (arrFlags2(index) And 1) = 0 Then
            ' skip
            X = X + 1
            _Continue
        End If

        ' hold index
        loopIndex = X

        ' Loop backwards from this point
        pos48644:

        ' back up one phoneme
        X = X - 1

        ' stop once the beginning is reached
        If X = 0 Then
            Exit Do
        End If

        ' get the preceding phoneme
        index = arrPhonemeIndex(X)

        If index <> 255 Then 'inserted to prevent access overrun
            If (arrFlags1(index) And 128) = 0 Then
                GoTo pos48644 ' if not a vowel, continue looping
            End If
        End If

        'pos48657:
        Do
            ' test for vowel
            index = arrPhonemeIndex(X)
            If index <> 255 Then 'inserted to prevent access overrun
                ' test for fricative/unvoiced or not voiced
                If ((arrFlags2(index) And 32) = 0) Or ((arrFlags1(index) And 4) <> 0) Then 'nochmal berprfen
                    'A = arrFlags1(Y) & 4;
                    'if(A == 0) goto pos48688;

                    ' get the phoneme length
                    A = arrPhonemeLength(X)
                    ' change phoneme length to (length * 1.5) + 1
                    A = (A \ 2) + A + 1
                    If bDebug Then
                        Print "RULE: Lengthen <FRICATIVE> or <VOICED> between <VOWEL> and <PUNCTUATION> by 1.5"
                    End If
                    If bDebug Then
                        Print "PRE"
                    End If
                    If bDebug Then
                        Print "phoneme"; X; "("; Chr$(arrSignInputTable1(arrPhonemeIndex(X))); Chr$(arrSignInputTable2(arrPhonemeIndex(X))); ") length"; arrPhonemeLength(X)
                    End If
                    arrPhonemeLength(X) = A

                    If bDebug Then
                        Print "POST"
                    End If
                    If bDebug Then
                        Print "phoneme"; X; "("; Chr$(arrSignInputTable1(arrPhonemeIndex(X))); Chr$(arrSignInputTable2(arrPhonemeIndex(X))); ") length"; arrPhonemeLength(X)
                    End If
                End If
            End If
            ' keep moving forward
            X = X + 1
        Loop Until X = loopIndex
        '    if (X != loopIndex) goto pos48657;
        X = X + 1
    Loop

    ' Similar to the above routine, but shorten vowels under some circumstances

    ' Loop throught all phonemes
    loopIndex = 0

    'pos48697

    Do
        ' get a phoneme
        X = loopIndex
        index = arrPhonemeIndex(X)

        ' exit routine at end token
        If index = 255 Then
            Exit Sub
        End If
        ' vowel?
        A = arrFlags1(index) And 128
        If A <> 0 Then
            ' get next phoneme
            X = X + 1
            index = arrPhonemeIndex(X)

            ' get flags
            If index = 255 Then
                mem56 = 65
            Else
                mem56 = arrFlags1(index)
            End If
            ' use if end marker
            ' not a consonant
            If (arrFlags1(index) And 64) = 0 Then
                ' RX or LX?
                If (index = 18) Or (index = 19) Then ' 'RX' & 'LX'
                    ' get the next phoneme
                    X = X + 1
                    index = arrPhonemeIndex(X)

                    ' next phoneme a consonant?
                    If (arrFlags1(index) And 64) <> 0 Then
                        If bDebug Then
                            Print "RULE: <VOWEL> <RX | LX> <CONSONANT> - decrease length by 1"
                        End If
                        If bDebug Then
                            Print "PRE"
                        End If
                        If bDebug Then
                            Print "phoneme"; loopIndex; "("; Chr$(arrSignInputTable1(arrPhonemeIndex(loopIndex))); Chr$(arrSignInputTable2(arrPhonemeIndex(loopIndex))); ") length"; arrPhonemeLength(loopIndex)
                        End If
                        ' decrease length of vowel by 1 frame
                        arrPhonemeLength(loopIndex) = arrPhonemeLength(loopIndex) - 1
                        If bDebug Then
                            Print "POST"
                        End If
                        If bDebug Then
                            Print "phoneme"; loopIndex; "("; Chr$(arrSignInputTable1(arrPhonemeIndex(loopIndex))); Chr$(arrSignInputTable2(arrPhonemeIndex(loopIndex))); ") length"; arrPhonemeLength(loopIndex)
                        End If
                    End If
                    ' move ahead
                    loopIndex = loopIndex + 1
                    _Continue
                End If
                ' move ahead
                loopIndex = loopIndex + 1
                _Continue
            End If

            ' Got here if not <VOWEL>

            ' not voiced
            If (mem56 And 4) = 0 Then
                ' Unvoiced
                ' *, .*, ?*, ,*, -*, DX, S*, SH, F*, TH, /H, /X, CH, P*, T*, K*,

                ' KX

                ' not an unvoiced plosive?
                If (mem56 And 1) = 0 Then
                    ' move ahead
                    loopIndex = loopIndex + 1
                    _Continue
                End If

                ' P*, T*, K*, KX

                ' move back
                X = X - 1
                If bDebug Then
                    Print "RULE: <VOWEL> <UNVOICED PLOSIVE> - decrease vowel by 1/8th"
                End If
                If bDebug Then
                    Print "PRE"
                End If
                If bDebug Then
                    Print "phoneme"; X; "("; Chr$(arrSignInputTable1(arrPhonemeIndex(X))); Chr$(arrSignInputTable2(arrPhonemeIndex(X))); ") length"; arrPhonemeLength(X)
                End If
                ' decrease length by 1/8th
                mem56 = arrPhonemeLength(X) \ 8
                arrPhonemeLength(X) = arrPhonemeLength(X) - mem56

                If bDebug Then
                    Print "POST"
                End If
                If bDebug Then
                    Print "phoneme"; X; "("; Chr$(arrSignInputTable1(arrPhonemeIndex(X))); Chr$(arrSignInputTable2(arrPhonemeIndex(X))); ") length"; arrPhonemeLength(X)
                End If
                ' move ahead
                loopIndex = loopIndex + 1
                _Continue
            End If

            If bDebug Then
                Print "RULE: <VOWEL> <VOICED CONSONANT> - increase vowel by 1/2 + 1"
            End If
            If bDebug Then
                Print "PRE"
            End If
            If bDebug Then
                Print "phoneme"; X - 1; "("; Chr$(arrSignInputTable1(arrPhonemeIndex(X - 1))); Chr$(arrSignInputTable2(arrPhonemeIndex(X - 1))); ") length"; arrPhonemeLength(X - 1)
            End If
            ' decrease length
            A = arrPhonemeLength(X - 1)
            arrPhonemeLength(X - 1) = (A \ 2) + A + 1
            ' 5/4*A + 1

            If bDebug Then
                Print "POST"
            End If
            If bDebug Then
                Print "phoneme"; X - 1; "("; Chr$(arrSignInputTable1(arrPhonemeIndex(X - 1))); Chr$(arrSignInputTable2(arrPhonemeIndex(X - 1))); ") length"; arrPhonemeLength(X - 1)
            End If
            ' move ahead
            loopIndex = loopIndex + 1
            _Continue
        End If

        ' WH, R*, L*, W*, Y*, Q*, Z*, ZH, V*, DH, J*, **,

        'pos48821:

        ' nasal?
        If (arrFlags2(index) And 8) <> 0 Then
            ' M*, N*, NX,
            ' get the next phoneme
            X = X + 1
            index = arrPhonemeIndex(X)

            ' end of buffer?
            If index = 255 Then
                A = 65 And 2
            Else
                A = arrFlags1(index) And 2
            End If
            'prevent buffer overflow
            ' check for stop consonant

            ' is next phoneme a stop consonant?
            If A <> 0 Then

                ' B*, D*, G*, GX, P*, T*, K*, KX

                If bDebug Then
                    Print "RULE: <NASAL> <STOP CONSONANT> - set nasal = 5, consonant = 6"
                End If
                If bDebug Then
                    Print "POST"
                End If
                If bDebug Then
                    Print "phoneme"; X; "("; Chr$(arrSignInputTable1(arrPhonemeIndex(X))); Chr$(arrSignInputTable2(arrPhonemeIndex(X))); ") length"; arrPhonemeLength(X)
                End If
                If bDebug Then
                    Print "phoneme"; X - 1; "("; Chr$(arrSignInputTable1(arrPhonemeIndex(X - 1))); Chr$(arrSignInputTable2(arrPhonemeIndex(X - 1))); ") length"; arrPhonemeLength(X - 1)
                End If
                ' set stop consonant length to 6
                arrPhonemeLength(X) = 6
                ' set nasal length to 5
                arrPhonemeLength(X - 1) = 5
                If bDebug Then
                    Print "POST"
                End If
                If bDebug Then
                    Print "phoneme"; X; "("; Chr$(arrSignInputTable1(arrPhonemeIndex(X))); Chr$(arrSignInputTable2(arrPhonemeIndex(X))); ") length"; arrPhonemeLength(X)
                End If
                If bDebug Then
                    Print "phoneme"; X - 1; "("; Chr$(arrSignInputTable1(arrPhonemeIndex(X - 1))); Chr$(arrSignInputTable2(arrPhonemeIndex(X - 1))); ") length"; arrPhonemeLength(X - 1)
                End If
            End If
            ' move to next phoneme
            loopIndex = loopIndex + 1
            _Continue
        End If

        If (arrFlags1(index) And 2) <> 0 Then
            ' B*, D*, G*, GX

            ' move past silence
            Do
                ' move ahead
                X = X + 1
                index = arrPhonemeIndex(X)
            Loop Until index = 0

            ' check for end of buffer
            If index = 255 Then 'buffer overflow
                ' ignore, overflow code
                If (65 And 2) = 0 Then
                    loopIndex = loopIndex + 1
                    _Continue
                End If
            ElseIf (arrFlags1(index) And 2) = 0 Then
                ' if another stop consonant, move ahead
                loopIndex = loopIndex + 1
                _Continue
            End If

            If bDebug Then
                Print "RULE: <UNVOICED STOP CONSONANT> {optional silence} <STOP CONSONANT> - shorten both to 1/2 + 1"
            End If
            If bDebug Then
                Print "PRE"
            End If
            If bDebug Then
                Print "phoneme"; X; "("; Chr$(arrSignInputTable1(arrPhonemeIndex(X))); Chr$(arrSignInputTable2(arrPhonemeIndex(X))); ") length"; arrPhonemeLength(X)
            End If
            If bDebug Then
                Print "phoneme"; X - 1; "("; Chr$(arrSignInputTable1(arrPhonemeIndex(X - 1))); Chr$(arrSignInputTable2(arrPhonemeIndex(X - 1))); ") length"; arrPhonemeLength(X - 1)
            End If
            ' X gets overwritten, so hold prior X value for debug statement
            debugX = X
            ' shorten the prior phoneme length to (length/2 + 1)
            arrPhonemeLength(X) = (arrPhonemeLength(X) \ 2) + 1
            X = loopIndex

            ' also shorten this phoneme length to (length/2 +1)
            arrPhonemeLength(loopIndex) = (arrPhonemeLength(loopIndex) \ 2) + 1
            If bDebug Then
                Print "POST"
            End If
            If bDebug Then
                Print "phoneme"; debugX; "("; Chr$(arrSignInputTable1(arrPhonemeIndex(debugX))); Chr$(arrSignInputTable2(arrPhonemeIndex(debugX))); ") length"; arrPhonemeLength(debugX)
            End If
            If bDebug Then
                Print "phoneme"; debugX - 1; "("; Chr$(arrSignInputTable1(arrPhonemeIndex(debugX - 1))); Chr$(arrSignInputTable2(arrPhonemeIndex(debugX - 1))); ") length"; arrPhonemeLength(debugX - 1)
            End If
            ' move ahead
            loopIndex = loopIndex + 1
            _Continue
        End If

        ' WH, R*, L*, W*, Y*, Q*, Z*, ZH, V*, DH, J*, **,

        ' liquic consonant?
        If (arrFlags2(index) And 16) <> 0 Then
            ' R*, L*, W*, Y*

            ' get the prior phoneme
            index = arrPhonemeIndex(X - 1)
            ' prior phoneme a stop consonant>
            If (arrFlags1(index) And 2) <> 0 Then
                If bDebug Then
                    Print "RULE: <LIQUID CONSONANT> <DIPHTONG> - decrease by 2"
                End If
                If bDebug Then
                    Print "PRE"
                End If
                If bDebug Then
                    Print "phoneme"; X; "("; Chr$(arrSignInputTable1(arrPhonemeIndex(X))); Chr$(arrSignInputTable2(arrPhonemeIndex(X))); ") length"; arrPhonemeLength(X)
                End If
                ' decrease the phoneme length by 2 frames (20 ms)
                arrPhonemeLength(X) = arrPhonemeLength(X) - 2
                If bDebug Then
                    Print "POST"
                End If
                If bDebug Then
                    Print "phoneme"; X; "("; Chr$(arrSignInputTable1(arrPhonemeIndex(X))); Chr$(arrSignInputTable2(arrPhonemeIndex(X))); ") length"; arrPhonemeLength(X)
                End If
            End If
        End If

        ' move to next phoneme
        loopIndex = loopIndex + 1
        _Continue
    Loop

End Sub

' -------------------------------------------------------------------------
' ML : Code47503 is division with remainder, and mem50 gets the sign
Sub Code47503 (mem52 As _Byte)
    Dim iTemp As Integer

    Y = 0
    If ((mem53 And 128) <> 0) Then
        mem53 = -mem53
        Y = 128
    End If
    mem50 = Y
    A = 0
    For X = 8 To 1 Step -1
        iTemp = mem53
        mem53 = mem53 * 2 ' QB64PE uses * for left bit shift
        A = A * 2 ' QB64PE uses * for left bit shift
        If (iTemp >= 128) Then
            A = A + 1
        End If
        If (A >= mem52) Then
            A = A - mem52
            mem53 = mem53 + 1
        End If
    Next X
    mem51 = A
    If ((mem50 And 128) <> 0) Then
        mem53 = -mem53
    End If
End Sub

' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' END sam.c
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' BEGIN reciter.c
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

' test the flag bits for a specific char
' this is non ascii layout, but tests ascii chars
'uint32_t TestFlag(uint8_t in, uint8_t mask)
' {
'  assert(in<sizeof(tab36376));
'  const uint8_t val = tab36376[in];
'  return val & mask;
' }
Function TestFlag~% (in As _Unsigned _Byte, mask As _Unsigned _Byte)
    If in > UBound(tab36376) Then Stop 'QB64: Replace assert with STOP
    ' val = arrTab36376(in) 'Not needed, can use array element directly
    TestFlag = arrTab36376(in) And mask 'QB64: AND is bitwise AND
End Function

' test the flag bits for the pervious char in the stream
'uint32_t TestFlagDec(uint8_t mem59, uint8_t mask)
'{
'    X = mem59;
'    X--;
'    A = inputtemp[X];
'    Y = A;
'    assert(Y<sizeof(tab36376));
'    A = tab36376[Y];
'    return A & mask;
'}
Function TestFlagDec~% (mem59 As Integer, mask As Long)
    X = mem59
    X = X - 1
    A = Asc(Mid$(TempInput$, X + 1, 1)) 'QB64: Access char in string, ASC gets ASCII value
    Y = A
    If Y > UBound(tab36376) Then Stop
    A = arrTab36376(Y)
    TestFlagDec = A And mask
End Function

' test the flag bits for the next char in the stream
'uint32_t TestFlagInc(uint8_t mem58, uint8_t mask)
'{
'    X = mem58;
'    X++;
'    A = inputtemp[X];
'    Y = A;
'    assert(Y<sizeof(tab36376));
'    A = tab36376[Y];
'    return A & mask;
'}
Function TestFlagInc~% (mem58 As _Unsigned _Byte, mask As _Unsigned _Byte)
    X = mem58
    X = X + 1
    A = Asc(Mid$(TempInput$, X + 1, 1)) 'QB64: Access char in string, ASC gets ASCII value
    Y = A
    If Y > UBound(tab36376) Then Stop
    A = arrTab36376(Y)
    TestFlagInc = A And mask
End Function

' verify that the reciter tables are well formed
Sub ReciterVerify ()
    Dim iIndex As Integer
    Dim iPos As Integer
   
    For iIndex = 0 To 27 ' Assuming rule_tab is 0-based index and has 28 elements
        iPos = arrRuleTab(iIndex)
        ' Assuming rules is an array and QB64PE arrays are 0-based
        If arrRules(iPos) <> 93 Then ' 93 is the ASCII code for ']'
            Print "Assertion failed: arrRules(" + _Trim$(Str$(iPos)) + ") <> ']'"
            Stop
        End If
    Next iIndex
End Sub

' lookup a byte for a specific rule in the table
Function GetRuleByte% (rule_index As Integer, Y As Integer)
    ' Assuming rules is an array of integers (since C uses uint8_t)
    Dim iEnd As Integer
    Dim index As Integer
   
    iEnd = UBound(rules) 'UBOUND gives the highest index
    index = rule_index + Y
    If index >= iEnd Then
        Print "Assertion failed: index < iEnd"
        Stop
    End If
    GetRuleByte = arrRules(index)
End Function

Sub SecureCopyInput (sInput As String, max_size As Integer)
    ' secure copy of sInput because sInput will be overwritten by phonemes
    X = 1
    Y = 0
    Do While Y < max_size
        A = Asc(Mid$(sInput, Y + 1, 1)) ' QB64PE strings are 1-based index
        Y = Y + 1
        If A < 32 Then '0x20 = 32
            _Continue
        End If
        If A = 96 Then '0x60 = 96
            _Continue
        End If
        If A = 39 Then '0x27 = 39
            _Continue
        End If
        If A >= 126 Then '0x7E = 126
            _Continue
        End If
        TempInput$(X) = Chr$(A)
        X = X + 1
    Loop
   
    '  Null-terminate the input string (important for C compatibility)
    sInput = String$(max_size, 0) ' Fills the string with null characters (ASCII 0)
End Sub ' SecureCopyInput

Function TextToPhonemes& (sInput As String, max_size As Long)
    Const end_token = 155 ' ESC | 0x80
   
    'THIS IS REFERENCED IN OTHER FUNCTIONS, DO WE DIM AS GLOBAL?
    'dim TempInput$
   
    Dim out_pos As Long ' output position for phonemes
    Dim mem57 As Long
    Dim mem58 As Long ' current pos, used mostly in rhs match
    Dim mem59 As Long
    Dim mem60 As Long
    Dim mem61 As Long
    Dim rule_index As Long ' memory position of current rule

    Dim mem64 As Long ' position of '=' or current character
    Dim pos_rparen As Long ' position of ')
    Dim pos_lparen As Long ' position of '(
    Dim mem36653 As Long
   
    'max_size = 250
   
    ' NOT SURE WHAT THIS STUFF IS FOR,
    ' IF WE ONLY OVERWRITE IT WITH sInput ?
    TempInput$ = Space$(256) ' Assuming TempInput$ is a string, adjust size as needed
    TempInput$ = " " + TempInput$ 'inputtemp[0] = 0x20; // '
    'SECURECOPYINPUT in$, sInput, max_size  'Need to implement SecureCopyInput (see below)
    'For simplicity, assuming a direct copy for now.  Adjust as needed for QB64 string handling
    TempInput$ = sInput ' Assuming direct copy; implement SecureCopyInput for safety
   
    Y = 255
    X = 255
    TempInput$ = Left$(TempInput$, X) + Chr$(27) + Mid$(TempInput$, X + 2) 'inputtemp[X] = 27; // ESC
    mem61 = 255

    A = 255
    out_pos = 255

    ' ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    ' START PARSE
    ' ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    L_start_parse:

    Do
        mem61 = mem61 + 1
        X = mem61
        ' if end of input marker
        A = Asc(Mid$(TempInput$, X + 1, 1)) 'A = inputtemp[X];
        mem64 = A
        If A = Asc("[") Then
            out_pos = out_pos + 1
            X = out_pos

            A = end_token
            'arrInput1(X] = A  '  Cannot directly assign to input string like this
            ' Assuming input is passed by reference and we modify it.  Need to convert A back to character
            sInput = Left$(sInput, X) + Chr$(A) + Mid$(sInput, X + 2) ' Modify sInput string

            ' success
            TextToPhonemes = 1
            Exit Function
        End If
        If A = Asc(".") Then
            ' check a flag for next input char?
            X = X + 1

            Y = Asc(Mid$(TempInput$, X + 1, 1)) 'Y = inputtemp[X];
            'A = TestFlag(Y, 1) '  Need to implement TestFlag (see below)
            ' Assuming TestFlag checks bit 0;  using bitwise AND for now
            A = (Y And 1) '  Simple bit check, replace with actual TestFlag if needed
            If A = 0 Then
                ' output a '.'
                out_pos = out_pos + 1
                X = out_pos
                A = Asc(".")
                'arrInput1(X] = A
                sInput = Left$(sInput, X) + Chr$(A) + Mid$(sInput, X + 2) ' Modify sInput string
            Else
                Exit Do
            End If
        Else
            Exit Do
        End If
    Loop 'while

    ' if this character is non alpha
    A = mem64
    Y = A
    'A = TestFlag(A, 255) ' Need to implement TestFlag
    ' Assuming TestFlag checks for non-alpha;  QB64's ASCII range for A-Z is 65-90
    If (A >= 65 And A <= 90) Then
        mem57 = 0 '  If it's A-Z, flag is 0 (not non-alpha)
    Else
        mem57 = 2 '  Otherwise, set flag bit 1 (0x02)
    End If 'Simplified, replace with actual TestFlag

    If (mem57 And 2) Then 'if (A & 0x02)
        rule_index = arrRuleTab(27) ' Assuming rule_tab is an array, and we have 27 elements
        GoTo L_nextrule '  Use GOTO with caution, consider refactoring
    End If

    ' what be this ???
    A = mem57 ' flag for A
    If A = 0 Then
        A = Asc(" ")
        TempInput$ = Left$(TempInput$, X) + Chr$(A) + Mid$(TempInput$, X + 2) 'inputtemp[X] = A;
        out_pos = out_pos + 1
        X = out_pos
        ' hard exit on too long?
        If X > max_size Then
            'arrInput1(max_size - 1] = end_token
            sInput = Left$(sInput, max_size) + Chr$(end_token) + Mid$(sInput, max_size + 2)
            A = mem61
            mem36653 = A
            TextToPhonemes = 0
            Exit Function
        Else
            'arrInput1(X] = A
            sInput = Left$(sInput, X) + Chr$(A) + Mid$(sInput, X + 2)
            GoTo L_start_parse
        End If
    End If

    ' what is A at this point?
    A = mem57 And 128 '0x80 in decimal
    If A = 0 Then
        ' error
        TextToPhonemes = 0
        Exit Function
    End If

    ' go to the right rules for this character.
    X = mem64 - Asc("A")
    'assert(X<26);  ' QB64 doesn't have assert;  can add a check if needed
    If X < 0 Or X > 25 Then
        ' Handle out-of-bounds,  e.g.,  PRINT "Error: Invalid character";  RETURN
        Print "Error: Invalid character";
        TextToPhonemes = 0
        Exit Function
    End If
    rule_index = arrRuleTab(X + 1) ' QB64 arrays are 1-based

    '// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    '// TRY MATCHING NEXT RULE
    '// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    L_nextrule:
    '// find next rule
    '// skip to next rule byte with 0x80 mask
    Y = 0
    Do
        rule_index = rule_index + 1
        A = GetRuleByte(rule_index, Y) '//Need to define GetRuleByte function
    Loop While (A And &H80) = 0 '// (A&0x80)==0
    Y = Y + 1
    '// if there are no more rules in this set
    If GetRuleByte(rule_index, Y) = Asc("]") Then '// GetRuleByte(rule_index, Y)==']'
        TextToPhonemes& = 0
        Exit Function
    End If
    '// identify key points in this rule
    '// find '('
    Do
        '// fixme: fix infinite loop here with ' chars
        A = GetRuleByte(rule_index, Y)
        ' assert((A & 0x80)==0);   '// QB64 doesn't have assert, consider a conditional check
        If (A And &H80) <> 0 Then Stop '//  If assert fails, stop execution
        If A = Asc("(") Then Exit Do '// if (A == '(')
        Y = Y + 1
    Loop
    pos_lparen = Y
    '// find ')'
    Do
        Y = Y + 1
        A = GetRuleByte(rule_index, Y)
    Loop While A <> Asc(")") '// A != ')'
    pos_rparen = Y
    '// find '='
    Do
        Y = Y + 1
        A = GetRuleByte(rule_index, Y)
        A = A And &H7F '// A = A & 0x7F;
    Loop While A <> Asc("=") '// A != '='
    mem64 = Y
    X = mem61
    mem60 = X
    '// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    '// MATCH EXPRESSION IN PARENTHESIS
    '// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    Y = pos_lparen
    Y = Y + 1
    '// pos36759:
    Do
        mem57 = Asc(Mid$(TempInput$, X + 1, 1)) '// mem57 = inputtemp[X];
        A = GetRuleByte(rule_index, Y)
        If A <> mem57 Then '// if (A!=mem57)
            '// no match lets apply next rule
            GoTo L_nextrule
        End If
        Y = Y + 1
        If Y = pos_rparen Then Exit Do '// if (Y==pos_rparen)
        X = X + 1
        mem60 = X
    Loop
    '// the string in the bracket is correct
    '// pos36787:
    A = mem61
    mem59 = mem61

    '---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    'MATCH TO LEFT OF ( IN RULE
    '---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    L_match_left:
    ' scan back to find start?
    Do
        pos_lparen = pos_lparen - 1
        Y = pos_lparen
        A = GetRuleByte(rule_index, Y) 'Need equivalent QB64 function. See below
        mem57 = A
        ' if end of lhs pattern
        If (A And &H80) Then ' Check if the most significant bit is set
            A = mem60
            mem58 = A
            GoTo L_match_right ' QB64 uses GOTO
        End If
        '
        X = A And &H7F ' all but msb
        A = TestFlag(X, &H80) 'Need equivalent QB64 function.  See below
        If (A = 0) Then
            ' parse special escape rule
            Exit Do ' QB64 uses EXIT DO to exit a DO loop
        End If
        X = mem59 - 1
        A = inputtemp(X) ' TODO: NEED TO RECONCILE inputtemp() vs TempInput$ ?
        If (A <> mem57) Then
            GoTo L_nextrule ' QB64 uses GOTO
        End If
        mem59 = X
    Loop

    ' test for special escape chars
    A = mem57
    Select Case A
        Case 32 ' " "
            GoTo pos36895
        Case 35 ' "#"
            GoTo pos36910
        Case 46 ' "."
            GoTo pos36920
        Case 38 ' "&"
            GoTo pos36935
        Case 64 ' "@"
            GoTo pos36967
        Case 94 ' "^"
            GoTo pos37004
        Case 43 ' "+"
            GoTo pos37019
        Case 58 ' ":"
            GoTo pos37040
        Case Else
            ' error
            TextToPhonemes& = 0
            Exit Function
    End Select

    '---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    pos36895: ' handle " "
    A = TestFlagDec(mem59, &H80)
    If (A = 0) Then
        mem59 = X
        GoTo L_match_left
    End If
    GoTo L_nextrule

    '---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    pos36910: ' handle "#"
    A = TestFlagDec(mem59, &H40) 'Need equivalent QB64 function.  See below
    If (A <> 0) Then
        mem59 = X
        GoTo L_match_left
    End If
    GoTo L_nextrule

    '---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    pos36920: ' handle "."
    A = TestFlagDec(mem59, &H08) 'Need equivalent QB64 function.  See below
    If (A <> 0) Then
        mem59 = X
        GoTo L_match_left
    End If
    GoTo L_nextrule


    ' ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    pos36935: ' handle '&
    A = TestFlagDec(mem59, 16) '0x10
    If A <> 0 Then
        mem59 = X
        GoTo L_match_left
    End If
    A = Asc(Mid$(TempInput$, X + 1, 1))
    If A = Asc("H") Then
        X = X - 1
        A = Asc(Mid$(TempInput$, X + 1, 1))
        If (A = Asc("C")) Or (A = Asc("S")) Then
            mem59 = X
            GoTo L_match_left
        End If
    End If
    GoTo L_nextrule

    ' ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    pos36967: ' handle '@
    A = TestFlagDec(mem59, 4) '0x04
    If A <> 0 Then
        mem59 = X
        GoTo L_match_left
    End If
    A = Asc(Mid$(TempInput$, X + 1, 1))
    If (A <> Asc("H")) And (A <> Asc("T")) And (A <> Asc("C")) And (A <> Asc("S")) Then
        GoTo L_nextrule
    End If
    mem59 = X
    GoTo L_match_left

    ' ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    pos37004: ' handle '^
    A = TestFlagDec(mem59, 32) '0x20
    If A <> 0 Then
        mem59 = X
        GoTo L_match_left
    End If
    GoTo L_nextrule


    ' ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    pos37019: ' handle '+
    X = mem59
    X = X - 1
    A = Asc(Mid$(TempInput$, X, 1)) ' Assuming TempInput$ is a string version
    If (A = Asc("E")) Or (A = Asc("I")) Or (A = Asc("Y")) Then
        mem59 = X
        GoTo L_match_left
    End If
    GoTo L_nextrule

    ' ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    pos37040: ' handle ':
    A = TestFlagDec(mem59, &H20) ' Assuming TestFlagDec is a QB64 FUNCTION
    If A <> 0 Then
        mem59 = X
        GoTo pos37040
    End If
    GoTo L_match_left

    ' ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    pos37077: ' handle '%
    X = mem58 + 1
    A = Asc(Mid$(TempInput$, X, 1))
    If A <> Asc("E") Then
        GoTo L_match_ing
    End If
    X = X + 1
    Y = Asc(Mid$(TempInput$, X, 1))
    X = X - 1
    A = TestFlag(Y, &H80) ' Assuming TestFlag is a QB64 FUNCTION
    If A <> 0 Then
        X = X + 1
        A = Asc(Mid$(TempInput$, X, 1))
        If A <> Asc("R") Then
            GoTo pos37113
        End If
    End If
    mem58 = X
    GoTo L_match_right

    '
    '// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    'pos37113: // unknown ???
    pos37113:
    If (A = Asc("S")) Or (A = Asc("D")) Then
        mem58 = X
        GoTo L_match_right
    End If
    If A <> Asc("L") Then
        GoTo pos37135
    End If
    X = X + 1
    A = Asc(Mid$(TempInput$, X + 1, 1))
    If A <> Asc("Y") Then
        GoTo L_nextrule
    End If
    mem58 = X
    GoTo L_match_right

    'pos37135: // match FUV
    pos37135:
    If A <> Asc("F") Then
        GoTo L_nextrule
    End If
    X = X + 1
    A = Asc(Mid$(TempInput$, X + 1, 1))
    If A <> Asc("U") Then
        GoTo L_nextrule
    End If
    X = X + 1
    A = Asc(Mid$(TempInput$, X + 1, 1))
    If A <> Asc("V") Then
        GoTo L_nextrule
    End If
    mem58 = X
    GoTo L_match_right

    'L_match_ing: // match 'ING'
    L_match_ing:
    If A <> Asc("I") Then
        GoTo L_nextrule
    End If
    X = X + 1
    A = Asc(Mid$(TempInput$, X + 1, 1))
    If A <> Asc("N") Then
        GoTo L_nextrule
    End If
    X = X + 1
    A = Asc(Mid$(TempInput$, X + 1, 1))
    If A <> Asc("G") Then
        GoTo L_nextrule
    End If
    mem58 = X
    GoTo L_match_right

    '// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    '// MATCH RIGHT OF ) IN RULE
    '// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    L_match_right:
    Y = pos_rparen + 1
    If Y = mem64 Then
        GoTo L_emitrule
    End If
    pos_rparen = Y
    'A = GetRuleByte(rule_index, Y);
    'Need to define GetRuleByte function
    'A = GetRuleByte(rule_index, Y)
    'For now, placeholder:
    A = 0 ' Placeholder
    mem57 = A
    X = A
    'A = TestFlag(X, 0x80);
    'Need to define TestFlag function
    'A = TestFlag(X, &H80)
    'For now, placeholder:
    A = 0 'Placeholder
    If A = 0 Then
        A = mem57
        Select Case A
            Case Asc(" "): GoTo pos37295
            Case Asc("#"): GoTo pos37310
            Case Asc("."): GoTo pos37320
            Case Asc("&"): GoTo pos37335
            Case Asc("@"): GoTo pos37367
            Case Asc("^"): GoTo pos37404
            Case Asc("+"): GoTo pos37419
            Case Asc(":"): GoTo pos37440
            Case Asc("%"): GoTo pos37077
            Case Else
                '// error
                ' return 0;
                'PRINT "Error"
                'END 'Instead of return, you might want to handle this differently
                'GOTO ExitSub ' Add an exit label
                TextToPhonemes& = -1
        End Select
    Else
        '// what this does ??
        X = mem58 + 1
        A = Asc(Mid$(TempInput$, X + 1, 1))
        If A <> mem57 Then
            GoTo L_nextrule
        End If
        mem58 = X
        GoTo L_match_right
    End If


    ' ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    pos37295: ' handle '
    A = TestFlagInc(mem58, &H80)
    If A <> 0 Then
        GoTo L_nextrule
    End If
    mem58 = X
    GoTo L_match_right

    ' ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    pos37310: ' handle '#
    A = TestFlagInc(mem58, &H40)
    If A <> 0 Then
        mem58 = X
        GoTo L_match_right
    End If
    GoTo L_nextrule

    ' ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    pos37320: ' handle '.
    A = TestFlagInc(mem58, &H08)
    If A = 0 Then
        GoTo L_nextrule
    End If
    mem58 = X
    GoTo L_match_right

    ' ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    pos37335: ' handle '&
    A = TestFlagInc(mem58, &H10)
    If A <> 0 Then
        mem58 = X
        GoTo L_match_right
    End If
    A = Asc(Mid$(TempInput$, X + 1, 1)) ' Corrected index
    If A <> Asc("H") Then
        GoTo L_nextrule
    End If
    ' is this really x++ not x--?
    X = X + 1
    A = Asc(Mid$(TempInput$, X + 1, 1)) ' Corrected index
   
    If (A = Asc("C")) Or (A = Asc("S")) Then
        mem58 = X
        GoTo L_match_right
    End If
    GoTo L_nextrule

    ' ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    pos37367: ' handle '@'
    A = TestFlagInc(mem58, 4) ' 0x04
    If A <> 0 Then
        mem58 = X
        GoTo L_match_right
    End If
    A = inputtemp(X)
    If (A <> Asc("H")) And (A <> Asc("T")) And (A <> Asc("C")) And (A <> Asc("S")) Then
        GoTo L_nextrule
    End If
    mem58 = X
    GoTo L_match_right

    ' ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    pos37404: ' handle '^'
    A = TestFlagInc(mem58, 32) ' 0x20
    If A = 0 Then
        GoTo L_nextrule
    End If
    mem58 = X
    GoTo L_match_right

    ' ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    pos37419: ' handle '+'
    X = mem58
    X = X + 1
    A = inputtemp(X)
    If (A = Asc("E")) Or (A = Asc("I")) Or (A = Asc("Y")) Then
        mem58 = X
        GoTo L_match_right
    End If
    GoTo L_nextrule

    ' ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    pos37440: ' handle ':'
    Do
        A = TestFlagInc(mem58, 32) ' 0x20
        If A = 0 Then
            GoTo L_match_right
        End If
        mem58 = X
    Loop
    GoTo L_emitrule

    '// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    '// EMIT RULE
    '// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    L_emitrule:
    Y = mem64
    mem61 = mem60

    'if bDebug then  ' Assuming 'debug' is a global variable.
    '  PrintRule rule_index '  Assuming PrintRule is a function.
    'end if

    Do
        Y = Y + 1
        'A = GetRuleByte(rule_index, Y) ' Assuming GetRuleByte is a function.
        ' Placeholder for GetRuleByte
        ' A = GetRuleByte(rule_index, Y)  ' Needs QB64 Implementation
        ' Need to know how GetRuleByte works

        mem57 = A
        ' mask out parity
        A = A And 127 '// 0x7f

        If A <> Asc("=") Then
            out_pos = out_pos + 1
            X = out_pos
            'arrInput1(X] = A  ' Since 'input' is a string, we can't directly assign an integer to an index.
            Mid$(sInput, X + 1, 1) = Chr$(A) ' QB64 strings are 1-based index, C arrays are 0-based.
        End If

        ' if has parity set
        If (mem57 And 128) <> 0 Then ' //0x80
            GoTo L_start_parse
        End If
    Loop


    TextToPhonemes = out_pos
End Function ' TextToPhonemes&

' RENDER THE PHONEMES IN THE LIST
'
' The phoneme list is converted into sound through the steps:
'
' 1. Copy each phoneme <length> number of times into the frames list,
'    where each frame represents 10 milliseconds of sound.
'
' 2. Determine the transitions lengths between phonemes, and linearly
'    interpolate the values across the frames.
'
' 3. Offset the pitches by the fundamental frequency.
'
' 4. Render the each frame.

Sub Render
    Dim phase1 As _Unsigned _Byte ' mem43
    Dim phase2 As _Unsigned _Byte
    Dim phase3 As _Unsigned _Byte
    Dim mem66 As _Unsigned _Byte
    Dim mem38 As _Unsigned _Byte
    Dim mem40 As _Unsigned _Byte
    Dim speedcounter As _Unsigned _Byte ' mem45
    Dim mem48 As _Unsigned _Byte
    Dim i As Integer
    Dim carry As Integer

    If arrPhoIndexOutput(0) = 255 Then
        Exit Sub 'exit if no data
    End If

    A = 0
    X = 0
    mem44 = 0

    ' CREATE FRAMES
    '
    ' The length parameter in the list corresponds to the number of frames
    ' to expand the phoneme to.
    ' Each frame represents 10 milliseconds of time.
    ' So a phoneme with a length of 7 = 7 frames = 70 milliseconds duration.
    '
    ' The parameters are copied from the phoneme to the frame verbatim.

    Do
        ' get the index
        Y = mem44
        ' get the phoneme at the index
        A = arrPhoIndexOutput(mem44)
        mem56 = A
        ' if terminal phoneme, exit the loop
        If A = 255 Then Exit Do

        ' period phoneme *.
        If A = 1 Then
            ' add rising inflection
            A = 1
            mem48 = 1
            'goto pos48376;
            AddInflection mem48, phase1
        End If
        'question mark phoneme?
        If A = 2 Then
            ' create falling inflection
            mem48 = 255
            AddInflection mem48, phase1
        End If
        '    pos47615:

        ' get the stress amount (more stress = higher pitch)
        phase1 = arrTab47492(arrStressOutput(Y) + 1)

        ' get number of frames to write
        phase2 = arrPhoLengthOutput(Y)
        Y = mem56

        ' copy from the source to the frames list
        Do
            frequency1(X) = arrFreq1Data(Y) ' F1 frequency
            frequency2(X) = arrFreq2Data(Y) ' F2 frequency
            frequency3(X) = arrFreq3Data(Y) ' F3 frequency
            amplitude1(X) = arrAmp1Data(Y) ' F1 amplitude
            amplitude2(X) = arrAmp2Data(Y) ' F2 amplitude
            amplitude3(X) = arrAmp3Data(Y) ' F3 amplitude
            sampledConsonantFlag(X) = arrSampledConsonantFlags(Y) ' phoneme data for sampled consonants
            arrPitches(X) = pitch + phase1 ' pitch
            X = X + 1
            phase2 = phase2 - 1
        Loop Until phase2 = 0
        mem44 = mem44 + 1
    Loop Until mem44 = 0


    '// -------------------
    '//pos47694:

    '// CREATE TRANSITIONS
    '{here}

    A = 0
    mem44 = 0
    mem49 = 0 '// mem49 starts at as 0
    X = 0
    While -1 '//while No. 1
        '// get the current and following phoneme
        Y = arrPhoIndexOutput(X)
        A = arrPhoIndexOutput(X + 1)
        X = X + 1

        '// exit loop at end token
        If A = 255 Then
            Exit While
        End If
        '//goto pos47970;

        '// get the ranking of each phoneme
        X = A
        mem56 = arrBlendRank(A)
        A = arrBlendRank(Y)

        '// compare the rank - lower rank value is stronger
        If A = mem56 Then
            '// same rank, so use out blend lengths from each phoneme
            phase1 = arrOutBlendLength(Y)
            phase2 = arrOutBlendLength(X)
        ElseIf A < mem56 Then
            '// first phoneme is stronger, so us it's blend lengths
            phase1 = arrInBlendLength(X)
            phase2 = arrOutBlendLength(X)
        Else
            '// second phoneme is stronger, so use it's blend lengths
            '// note the out/in are swapped
            phase1 = arrOutBlendLength(Y)
            phase2 = arrInBlendLength(Y)
        End If

        Y = mem44
        A = mem49 + arrPhoLengthOutput(mem44)
        '// A is mem49 + length
        mem49 = A
        '// mem49 now holds length + position
        A = A + phase2
        '//Maybe Problem because of carry flag

        '//47776: ADC 42
        speedcounter = A
        mem47 = 168
        phase3 = mem49 - phase1 '// what is mem49
        A = phase1 + phase2
        '// total transition?
        mem38 = A

        X = A
        X = X - 2
        If (X And 128) = 0 Then
            Do '//while No. 2
                '//pos47810:

                '// mem47 is used to index the tables:
                '// 168  pitches[]

                '// 169  frequency1
                '// 170  frequency2
                '// 171  frequency3
                '// 172  amplitude1
                '// 173  amplitude2

                '// 174  amplitude3

                mem40 = mem38
                If mem47 = 168 Then '// pitch
                    '// unlike the other values, the pitches[] interpolates from
                    '// the middle of the current phoneme to the middle of the
                    '// next phoneme

                    Dim mem36 As _Unsigned Integer, mem37 As _Unsigned Integer
                    '// half the width of the current phoneme
                    mem36 = arrPhoLengthOutput(mem44) \ 2
                    '// half the width of the next phoneme
                    mem37 = arrPhoLengthOutput(mem44 + 1) \ 2
                    '// sum the values
                    mem40 = mem36 + mem37
                    '// length of both halves
                    mem37 = mem37 + mem49
                    '// center of next phoneme
                    mem36 = mem49 - mem36
                    '// center index of current phoneme

                    ' ****************************************************************************************************************************************************************
                    ' *** NOT SURE WHAT THIS IS:
                    'A = Read(mem47, mem37)
                    ' ****************************************************************************************************************************************************************

                    '// value at center of next phoneme - end interpolation value
                    '//A = mem[address];
                    Y = mem36 '// start index of interpolation

                    ' ****************************************************************************************************************************************************************
                    ' *** NOT SURE WHAT THIS IS:
                    'mem53 = A - Read(mem47, mem36)
                    ' ****************************************************************************************************************************************************************

                    '// value to center of current phoneme
                Else
                    '// value to interpolate to

                    ' ****************************************************************************************************************************************************************
                    ' *** NOT SURE WHAT THIS IS:
                    'A = Read(mem47, speedcounter)
                    ' ****************************************************************************************************************************************************************

                    '// position to start interpolation from
                    Y = phase3
                    '// value to interpolate from

                    ' ****************************************************************************************************************************************************************
                    ' *** NOT SURE WHAT THIS IS:
                    'mem53 = A - Read(mem47, phase3)
                    ' ****************************************************************************************************************************************************************


                End If

                '//Code47503(mem40);
                '// ML : Code47503 is division with remainder, and mem50 gets the sign

                '// calculate change per frame
                mem50 = IIf(Sgn(mem53) = -1, 128, 0)
                mem51 = Abs(mem53) Mod mem40
                mem53 = mem53 \ mem40
                '// interpolation range
                X = mem40
                '// number of frames to interpolate over
                Y = phase3
                '// starting frame

                '// linearly interpolate values

                mem56 = 0
                '//47907: CLC
                '//pos47908:
                While -1 '//while No. 3

                    ' ****************************************************************************************************************************************************************
                    ' *** NOT SURE WHAT THIS IS:
                    'A = Read(mem47, Y) + mem53
                    ' ****************************************************************************************************************************************************************


                    '//carry alway cleared

                    mem48 = A
                    Y = Y + 1
                    X = X - 1
                    If X = 0 Then
                        Exit While
                    End If
                    mem56 = mem56 + mem51
                    If mem56 >= mem40 Then '//???
                        mem56 = mem56 - mem40
                        '//carry? is set
                        '//if ((mem56 & 128)=0)
                        If (mem50 And 128) = 0 Then
                            '//47935: BIT 50
                            '//47937: BMI 47943
                            If mem48 <> 0 Then
                                mem48 = mem48 + 1
                            End If
                        Else
                            mem48 = mem48 - 1
                        End If
                    End If
                    '//pos47945:
                    Write mem47, Y, mem48
                Wend '//while No. 3

                '//pos47952:
                mem47 = mem47 + 1
                '//if (mem47 != 175) goto pos47810;
            Loop Until mem47 = 175 '//while No. 2
        End If
        '//pos47963:
        mem44 = mem44 + 1
        X = mem44
    Wend '//while No. 1

    '//goto pos47701;
    '//pos47970:

    ' add the length of this phoneme
    mem48 = mem49 + arrPhoLengthOutput(mem44)

    ' ASSIGN PITCH CONTOUR
    '
    ' This subtracts the F1 frequency from the pitch to create a
    ' pitch contour.
    ' Without this, the output would be at a single
    ' pitch level (monotone).
    ' don't adjust pitch if in sing mode
    If singmode = 0 Then
        ' iterate through the buffer
        For i = 0 To 255
            ' subtract half the frequency of the formant 1.
            ' this adds variety to the voice
            arrPitches(i) = arrPitches(i) - (frequency1(i) \ 2)
        Next i
    End If

    phase1 = 0
    phase2 = 0
    phase3 = 0
    mem49 = 0
    speedcounter = 72 'sam standard speed

    ' RESCALE AMPLITUDE
    '
    ' Rescale volume from a linear scale to decibels.
    '
    'amplitude rescaling
    For i = 255 To 0 Step -1
        amplitude1(i) = arrAmplitudeRescale(amplitude1(i))
        amplitude2(i) = arrAmplitudeRescale(amplitude2(i))
        amplitude3(i) = arrAmplitudeRescale(amplitude3(i))
    Next i

    Y = 0
    A = arrPitches(0)
    mem44 = A
    X = A
    mem38 = A - (A \ 4) ' 3/4*A ???
    If bDebug Then
        PrintOutput sampledConsonantFlag, frequency1, frequency2, frequency3, amplitude1, amplitude2, amplitude3, pitches
    End If

    ' PROCESS THE FRAMES
    '
    ' In traditional vocal synthesis, the glottal pulse drives filters, which
    ' are attenuated to the frequencies of the formants.
    '
    ' SAM generates these formants directly with sin and rectangular waves.
    ' To simulate them being driven by the glottal pulse, the waveforms are
    ' reset at the beginning of each glottal pulse.
    'finally the loop for sound output
    'pos48078:
    Do
        ' get the sampled information on the phoneme
        A = sampledConsonantFlag(Y)
        mem39 = A

        ' unvoiced sampled phoneme?
        A = A And 248
        If A <> 0 Then
            ' render the sample for the phoneme
            RenderSample mem66
            ' skip ahead two in the phoneme buffer
            Y = Y + 2
            mem48 = mem48 - 2
        Else
            ' simulate the glottal pulse and formants
            mem56 = arrMultTable(BINAND(arrSinus(phase1), amplitude1(Y)))

            carry = 0
            If (mem56 + arrMultTable(BINAND(arrSinus(phase2), amplitude2(Y)))) > 255 Then
                carry = 1
            End If
            mem56 = mem56 + arrMultTable(BINAND(arrSinus(phase2), amplitude2(Y)))
            A = mem56 + arrMultTable(BINAND(arrRectangle(phase3), amplitude3(Y))) + (IIf(carry = 1, 1, 0))
            A = ((A + 136) And 255) \ 16 'there must be also a carry
            'mem[54296] = A;
            ' output the accumulated value

            ' ****************************************************************************************************************************************************************
            ' *** NOT SURE WHAT THIS IS:
            'Output 0, A
            ' ****************************************************************************************************************************************************************

            speedcounter = speedcounter - 1
            If speedcounter <> 0 Then
                GoTo pos48155
            End If
            Y = Y + 1 'go to next amplitude

            ' decrement the frame count
            mem48 = mem48 - 1
        End If

        ' if the frame count is zero, exit the loop
        If mem48 = 0 Then
            Exit Do
        End If
        speedcounter = speed
        pos48155:

        ' decrement the remaining length of the glottal pulse
        mem44 = mem44 - 1
        ' finished with a glottal pulse?
        If mem44 = 0 Then
            pos48159:
            ' fetch the next glottal pulse length
            A = arrPitches(Y)
            mem44 = A
            A = A - (A \ 4)
            mem38 = A
            ' reset the formant wave generators to keep them in
            ' sync with the glottal pulse
            phase1 = 0
            phase2 = 0
            phase3 = 0

            _Continue
        End If

        ' decrement the count
        mem38 = mem38 - 1
        ' is the count non-zero and the sampled flag is zero?
        If (mem38 <> 0) Or (mem39 = 0) Then
            ' reset the phase of the formants to match the pulse
            phase1 = phase1 + frequency1(Y)
            phase2 = phase2 + frequency2(Y)
            phase3 = phase3 + frequency3(Y)

            _Continue


        End If

        ' voiced sampled phonemes interleave the sample with the
        ' glottal pulse. The sample flag is non-zero, so render
        ' the sample for the phoneme.
        RenderSample mem66
        GoTo pos48159
    Loop 'while

    '#IF 0
    ' The following code is never reached. It's left over from when
    ' the voiced sample code was part of this loop, instead of part
    ' of RenderSample();
    '#ENDIF
    'pos48315:
    '    DIM tempA AS Integer
    '    phase1 = A XOR 255
    '    Y = mem66
    '    DO
    'pos48321:
    '
    '        mem56 = 8
    '        A = Read(mem47, Y)
    '
    'pos48327:
    '        DO
    '            '48327: ASL A
    '            '48328: BCC 48337
    '            tempA = A
    '            A = A SHL 1
    '            IF (tempA AND 128) <> 0 THEN
    '                X = 26
    '                ' mem[54296] = X;
    '                bufferPos = bufferPos + 150
    '                buffer(bufferPos / 50) = (X AND 15) * 16
    '            ELSE
    '                'mem[54296] = 6;
    '                X = 6
    '                bufferPos = bufferPos + 150
    '                buffer(bufferPos / 50) = (X AND 15) * 16
    '            END IF
    '
    '            FOR X = wait2 TO 1 STEP -1
    '                'wait
    '            NEXT X
    '            mem56 = mem56 - 1
    '        LOOP WHILE mem56 <> 0
    '
    '        Y = Y + 1
    '        phase1 = phase1 + 1
    '    LOOP WHILE phase1 <> 0
    '    '    IF phase1 <> 0 GOTO pos48321
    '    A = 1
    '    mem44 = 1
    '    mem66 = Y
    '    Y = mem49
    '    RETURN
    '#IF 0
    'END IF
End Sub ' Render

' SUBROUTINES and FUNCTIONS

Sub AddInflection (mem48 As _Byte, phase1 As _Byte)
    ' store the location of the punctuation
    mem49 = X
    A = X
    Atemp = A

    ' backup 30 frames
    A = A - 30

    ' if index is before buffer, point to start of buffer
    If Atemp <= 30 Then
        A = 0
    End If
    X = A

    ' FIXME: Explain this fix better, it's not obvious
    ' ML : A =, fixes a problem with invalid pitch with '.'
    Do While arrPitches(X) = 127
        X = X + 1
    Loop

    ' add the inflection direction
    A = A + mem48
    phase1 = A

    ' set the inflection
    arrPitches(X) = A

    ' increment the position
    X = X + 1

    ' exit if the punctuation has been reached
    If X = mem49 Then
        Exit Sub
    End If

    'goto pos47615;
    If arrPitches(X) = 255 Then
        GoTo pos48406
    End If
    A = phase1
    GoTo pos48398

    pos48406:

    pos48398:
    '48398: CLC  (Carry flag is handled implicitly in QB64 addition)
    '48399: ADC 48
    ' QB64 doesn't have direct carry flag manipulation like assembly,
    ' so addition handles carries naturally.
End Sub ' AddInflection

Sub SetMouthThroat (mouth As _Byte, throat As _Byte)
    Dim initialFrequency As _Byte, newFrequency As _Byte
    Dim posV As _Byte ' *** original variable name "pos" is reserved in QB64

    ' mouth formants (F1) 5..29  (Data already initialized)

    ' throat formants (F2) 5..29 (Data already initialized)

    ' formant 1 frequencies (mouth) 48..53 (Data already initialized)

    ' formant 2 frequencies (throat) 48..53 (Data already initialized)

    posV = 5
    'pos38942:
    ' recalculate formant frequencies 5..29 for the mouth (F1) and throat (F2)
    Do While posV <> 30
        ' recalculate mouth frequency
        initialFrequency = arrMouthFormants5_29(posV)
        If initialFrequency <> 0 Then
            newFrequency = trans(mouth, initialFrequency)
        End If
        arrFreq1Data(posV) = newFrequency

        ' recalculate throat frequency
        initialFrequency = arrThroatFormants5_29(posV)
        If initialFrequency <> 0 Then
            newFrequency = trans(throat, initialFrequency)
        End If
        arrFreq2Data(posV) = newFrequency
        posV = posV + 1
    Loop

    'pos39059:
    ' recalculate formant frequencies 48..53
    posV = 48
    Y = 0
    Do While posV <> 54
        ' recalculate F1 (mouth formant)
        initialFrequency = arrMouthFormants48_53(Y)
        newFrequency = trans(mouth, initialFrequency)
        arrFreq1Data(posV) = newFrequency

        ' recalculate F2 (throat formant)
        initialFrequency = arrThroatFormants48_53(Y)
        newFrequency = trans(throat, initialFrequency)
        arrFreq2Data(posV) = newFrequency
        Y = Y + 1
        posV = posV + 1
    Loop
End Sub ' SetMouthThroat

'return = (mem39212*mem39213) >> 1
Function trans% (mem39212 As _Byte, mem39213 As _Byte)
    'pos39008:
    Dim carry As _Byte
    Dim temp As Integer ' Using INTEGER for intermediate calculations to avoid overflow
    Dim mem39214 As _Byte, mem39215 As _Byte
    A = 0
    mem39215 = 0
    mem39214 = 0
    X = 8
    Do
        carry = mem39212 And 1
        mem39212 = mem39212 \ 2 ' Integer division for right shift

        If carry <> 0 Then
            carry = 0
            A = mem39215
            temp = A + mem39213
            A = A + mem39213
            If temp > 255 Then
                carry = 1
            End If
            mem39215 = A
        End If
        temp = mem39215 And 1
        mem39215 = (mem39215 \ 2) Or (carry * 128)
        carry = temp
        X = X - 1
    Loop Until X = 0

    temp = mem39214 And 128
    mem39214 = (mem39214 * 2) Or carry
    carry = temp
    temp = mem39215 And 128
    mem39215 = (mem39215 * 2) Or carry
    carry = temp

    trans% = mem39215
End Function ' trans%


' TODO: SOMETHING CALLED RenderSample IS CALLED SEVERAL TIMES IN THE APP
'       BUT THE ACTUAL ROUTINE IS MISSING, SO EITHER Gemini DIDN'T CONVERT IT
'       OR WE MISSED THE C FILE THAT CONTAINS IT AND NEVER CONVERTED IT?
'       SO WE'LL NEED TO FIND & CONVERT THIS:
Sub RenderSample (mem66 As _Byte)
End Sub

' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' END render.c
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' BEGIN debug.c
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Sub PrintPhonemes (phonemeindex As _Unsigned _Byte, arrPhonemeLength As _Unsigned _Byte, stress As _Unsigned _Byte)
    Dim i As Integer
    i = 0
    Print "==========================================="
    Print "Internal Phoneme presentation:"
    Print
    Print " idx    phoneme  length  stress"
    Print "------------------------------"

    Do While (phonemeindex(i) <> 255) And (i < 255) 'UBYTE arrays are indexed from 0 in QB64
        If phonemeindex(i) < 81 Then
            ' Assuming arrSignInputTable1 and arrSignInputTable2 are available
            ' and are also UBYTE arrays
            Print Using " ###      \  \      ###    #"; i; Chr$(arrSignInputTable1(phonemeindex(i))); Chr$(arrSignInputTable2(phonemeindex(i))); arrPhonemeLength(i); arrStress1(i) 'Format output
        Else
            Print Using " ###      ??      ###    #"; phonemeindex(i); arrPhonemeLength(i); arrStress1(i)
        End If
        i = i + 1
    Loop

    Print "==========================================="
    Print
End Sub ' PrintPhonemes

Sub PrintOutput (flag As _Unsigned _Byte, f1 As _Unsigned _Byte, f2 As _Unsigned _Byte, f3 As _Unsigned _Byte, a1 As _Unsigned _Byte, a2 As _Unsigned _Byte, a3 As _Unsigned _Byte, p As _Unsigned _Byte)
    Print "==========================================="
    Print "Final data for speech output:"
    Print
    Print " flags ampl1 freq1 ampl2 freq2 ampl3 freq3 pitch"
    Print "------------------------------------------------"

    Dim i As Integer
    i = 0
    Do While i < 255
        Print Using " ##### ##### ##### ##### ##### ##### ##### #####"; flag(i); a1(i); f1(i); a2(i); f2(i); a3(i); f3(i); p(i)
        i = i + 1
    Loop

    Print "==========================================="
End Sub ' PrintOutput

'extern uint8_t GetRuleByte(uint16_t mem62, uint8_t Y);  =>  Needs declaration if used
'  Assuming GetRuleByte is in another module.
'  TODO:  Add actual DECLARE FUNCTION if this function is needed in this module

Sub PrintRule (offset As Integer)
    Dim i As Integer
    Dim A As _Unsigned _Byte
    i = 1
    Print "Applying rule: ";

    Do
        ' Assuming GetRuleByte returns a UBYTE
        A = GetRuleByte(offset, i) 'Need to ensure GetRuleByte is available
        If (A And 127) = Asc("=") Then 'Bitwise AND and character comparison
            Print " -> ";
        Else
            Print Chr$(A And 127);
        End If
        i = i + 1
    Loop While (A And 128) = 0
    Print
End Sub ' PrintRule
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' END debug.c
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


Attached Files
.zip   SAM-speech-QB64PE-0-21.zip (Size: 1.05 MB / Downloads: 16)
Reply
#2
Why constantly make new topics for this?   Make one topic, update it as you go, and people can FOLLOW TOPIC and keep up with the changes and progress easier.
Reply
#3
If that's the way then sure! Did not think about it, my brain is mush after slogging thru all this code! Will do from now on.
Reply
#4
[Image: image.png]
And, for those who might not know how to do that (it's really a very convenient feature), click my little screen shot above.  See down at the bottom left of the page?  There's a link to email a thread and also SUBSCRIBE TO THIS THREAD, which makes it much easier to keep up with topics which you find interesting so you won't forget about them whenever someone is developing something.  

I tend to use it quite a bit for interesting little things in the "Works in Progress" forum, so I don't lose track of them as quickly.  Wink

Just scroll the page down as far as possible, past the quick reply area, and there's the link.  Enjoy!
Reply
#5
Here is the source C code all in one file, I am using to compare the QB64PE translation to, to suss out any mis-translations or missing pieces. I'm not sure the C code will still compile in this form, it's more just to see what was originally intended in the code to fix things in the QB64PE. For example, Gemini doesn't seem to know how to translate C's treating strings as an array of characters or what to do with pointers or anything that directly references memory (_I_ don't know what to do with those things either, at least yet!)

Some C types, commands, notations, etc. I would need to understand and figure out how to translate to QB64PE:

Code: (Select All)
size_t max_size
char * ptr = dst;
size_t read_line(FILE * fd, char * dst, size_t max)

int8_t
int8_t*
int8_t**
int32_t

uint8_t
uint16_t
uint32_t

size_t

#define END 0,0

#define C_SIZE 1024
static char temp[C_SIZE];
memset(temp, 0x80, C_SIZE);

test_state_t state;
memset(&state, 0, sizeof(test_state_t));

FILE * fd = NULL;
fopen_s(&fd, path, "rb");
if (fd==NULL) { return 0; }

int8_t *GetBuffer() { return buffer; };

buffer = malloc(22050 * 10);
freq2data = &mem[45136];

if ((mem50 & 128) != 0)
assert(Y<sizeof(tab36376));

void WriteWav(int8_t* filename, int8_t* buffer, int32_t bufferlength)
{
#if (_MSC_VER)
    FILE * file = NULL;
    fopen_s(&file, filename, "wb");
#else
    FILE* file = fopen(filename, "wb");
#endif

void MixAudio(void* unused, Uint8* stream, int32_t len)
...
    SDL_AudioSpec fmt;
...
    if (SDL_OpenAudio(&fmt, NULL) < 0) {

int32_t main(int32_t argc, int8_t** argv)
...
    uint8_t* flag,
...

So here is all the C code to compare to the QB64PE... 

Code: (Select All)
// CODE FROM: https://github.com/bit-hack/SAM

#include <assert.h>
#include <ctype.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef USESDL
#include <SDL/SDL.h>
#endif
// BEGIN test_phonemes.c
typedef struct {
    size_t fails_;
    size_t passes_;
} test_state_t;
// END test_phonemes.c
int8_t input[256]; // tab39445
// standard sam sound
uint8_t speed = 72;
uint8_t pitch = 64;
uint8_t mouth = 128;
uint8_t throat = 128;
int32_t singmode = 0;
extern int32_t debug;
uint8_t mem39, mem44, mem47, mem49;
uint8_t mem50, mem51, mem53, mem56;
uint8_t mem59 = 0;
uint8_t A, X, Y;
uint8_t stress[256];        // numbers from 0 to 8
uint8_t phonemeLength[256]; // tab40160
uint8_t phonemeIndex[256];
uint8_t phonemeIndexOutput[60];  // tab47296
uint8_t stressOutput[60];        // tab47365
uint8_t phonemeLengthOutput[60]; // tab47416
// contains the final sound buffer
int32_t bufferPos = 0;
int8_t *buffer = NULL;
// BEGIN sam_tabs.h
//tab40672
const uint8_t stressInputTable[] = {
    '*', '1', '2', '3', '4', '5', '6', '7', '8'
};
//tab40682
const uint8_t signInputTable1[] = {
    ' ', '.', '?', ',', '-', 'I', 'I', 'E',
    'A', 'A', 'A', 'A', 'U', 'A', 'I', 'E',
    'U', 'O', 'R', 'L', 'W', 'Y', 'W', 'R',
    'L', 'W', 'Y', 'M', 'N', 'N', 'D', 'Q',
    'S', 'S', 'F', 'T', '/', '/', 'Z', 'Z',
    'V', 'D', 'C', '*', 'J', '*', '*', '*',
    'E', 'A', 'O', 'A', 'O', 'U', 'B', '*',
    '*', 'D', '*', '*', 'G', '*', '*', 'G',
    '*', '*', 'P', '*', '*', 'T', '*', '*',
    'K', '*', '*', 'K', '*', '*', 'U', 'U',
    'U'
};
//tab40763
const uint8_t signInputTable2[] = {
    '*', '*', '*', '*', '*', 'Y', 'H', 'H',
    'E', 'A', 'H', 'O', 'H', 'X', 'X', 'R',
    'X', 'H', 'X', 'X', 'X', 'X', 'H', '*',
    '*', '*', '*', '*', '*', 'X', 'X', '*',
    '*', 'H', '*', 'H', 'H', 'X', '*', 'H',
    '*', 'H', 'H', '*', '*', '*', '*', '*',
    'Y', 'Y', 'Y', 'W', 'W', 'W', '*', '*',
    '*', '*', '*', '*', '*', '*', '*', 'X',
    '*', '*', '*', '*', '*', '*', '*', '*',
    '*', '*', '*', 'X', '*', '*', 'L', 'M',
    'N'
};
//loc_9F8C
const uint8_t flags[] = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0xA4, 0xA4, 0xA4,
    0xA4, 0xA4, 0xA4, 0x84, 0x84, 0xA4, 0xA4, 0x84,
    0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x44, 0x44,
    0x44, 0x44, 0x44, 0x4C, 0x4C, 0x4C, 0x48, 0x4C,
    0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x44, 0x44,
    0x44, 0x44, 0x48, 0x40, 0x4C, 0x44, 0x00, 0x00,
    0xB4, 0xB4, 0xB4, 0x94, 0x94, 0x94, 0x4E, 0x4E,
    0x4E, 0x4E, 0x4E, 0x4E, 0x4E, 0x4E, 0x4E, 0x4E,
    0x4E, 0x4E, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
    0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x80, 0xC1,
    0xC1
};
//??? flags overlap flags2
//loc_9FDA
const uint8_t flags2[] = {
    0x80, 0xC1, 0xC1, 0xC1, 0xC1, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
    0x10, 0x10, 0x10, 0x08, 0x0C, 0x08, 0x04, 0x40,
    0x24, 0x20, 0x20, 0x24, 0x00, 0x00, 0x24, 0x20,
    0x20, 0x24, 0x20, 0x20, 0x00, 0x20, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
//tab45616???
const uint8_t phonemeStressedLengthTable[] = {
    0x00, 0x12, 0x12, 0x12, 8, 0xB, 9, 0xB,
    0xE, 0xF, 0xB, 0x10, 0xC, 6, 6, 0xE,
    0xC, 0xE, 0xC, 0xB, 8, 8, 0xB, 0xA,
    9, 8, 8, 8, 8, 8, 3, 5,
    2, 2, 2, 2, 2, 2, 6, 6,
    8, 6, 6, 2, 9, 4, 2, 1,
    0xE, 0xF, 0xF, 0xF, 0xE, 0xE, 8, 2,
    2, 7, 2, 1, 7, 2, 2, 7,
    2, 2, 8, 2, 2, 6, 2, 2,
    7, 2, 4, 7, 1, 4, 5, 5
};
//tab45536???
const uint8_t phonemeLengthTable[] = {
    0, 0x12, 0x12, 0x12, 8, 8, 8, 8,
    8, 0xB, 6, 0xC, 0xA, 5, 5, 0xB,
    0xA, 0xA, 0xA, 9, 8, 7, 9, 7,
    6, 8, 6, 7, 7, 7, 2, 5,
    2, 2, 2, 2, 2, 2, 6, 6,
    7, 6, 6, 2, 8, 3, 1, 0x1E,
    0xD, 0xC, 0xC, 0xC, 0xE, 9, 6, 1,
    2, 5, 1, 1, 6, 1, 2, 6,
    1, 2, 8, 2, 2, 4, 2, 2,
    6, 1, 4, 6, 1, 4, 0xC7, 0xFF
};
/*
Ind  | phoneme |  flags   |
-----|---------|----------|
0    |   *     | 00000000 |
1    |  .*     | 00000000 |
2    |  ?*     | 00000000 |
3    |  ,*     | 00000000 |
4    |  -*     | 00000000 |
VOWELS
5    |  IY     | 10100100 |
6    |  IH     | 10100100 |
7    |  EH     | 10100100 |
8    |  AE     | 10100100 |
9    |  AA     | 10100100 |
10   |  AH     | 10100100 |
11   |  AO     | 10000100 |
17   |  OH     | 10000100 |
12   |  UH     | 10000100 |
16   |  UX     | 10000100 |
15   |  ER     | 10000100 |
13   |  AX     | 10100100 |
14   |  IX     | 10100100 |
DIPHTONGS
48   |  EY     | 10110100 |
49   |  AY     | 10110100 |
50   |  OY     | 10110100 |
51   |  AW     | 10010100 |
52   |  OW     | 10010100 |
53   |  UW     | 10010100 |
21   |  YX     | 10000100 |
20   |  WX     | 10000100 |
18   |  RX     | 10000100 |
19   |  LX     | 10000100 |
37   |  /X     | 01000000 |
30   |  DX     | 01001000 |
22   |  WH     | 01000100 |
VOICED CONSONANTS
23   |  R*     | 01000100 |
24   |  L*     | 01000100 |
25   |  W*     | 01000100 |
26   |  Y*     | 01000100 |
27   |  M*     | 01001100 |
28   |  N*     | 01001100 |
29   |  NX     | 01001100 |
54   |  B*     | 01001110 |
57   |  D*     | 01001110 |
60   |  G*     | 01001110 |
44   |  J*     | 01001100 |
38   |  Z*     | 01000100 |
39   |  ZH     | 01000100 |
40   |  V*     | 01000100 |
41   |  DH     | 01000100 |
unvoiced CONSONANTS
32   |  S*     | 01000000 |
33   |  SH     | 01000000 |
34   |  F*     | 01000000 |
35   |  TH     | 01000000 |
66   |  P*     | 01001011 |
69   |  T*     | 01001011 |
72   |  K*     | 01001011 |
42   |  CH     | 01001000 |
36   |  /H     | 01000000 |
43   |  **     | 01000000 |
45   |  **     | 01000100 |
46   |  **     | 00000000 |
47   |  **     | 00000000 |
55   |  **     | 01001110 |
56   |  **     | 01001110 |
58   |  **     | 01001110 |
59   |  **     | 01001110 |
61   |  **     | 01001110 |
62   |  **     | 01001110 |
63   |  GX     | 01001110 |
64   |  **     | 01001110 |
65   |  **     | 01001110 |
67   |  **     | 01001011 |
68   |  **     | 01001011 |
70   |  **     | 01001011 |
71   |  **     | 01001011 |
73   |  **     | 01001011 |
74   |  **     | 01001011 |
75   |  KX     | 01001011 |
76   |  **     | 01001011 |
77   |  **     | 01001011 |
SPECIAL
78   |  UL     | 10000000 |
79   |  UM     | 11000001 |
80   |  UN     | 11000001 |
31   |  Q*     | 01001100 |
*/
#endif
// END sam_tabs.h
// BEGIN reciter.h
//int32_t TextToPhonemes(int8_t *input, int8_t *output);
// parse a string up to '[' marker
int32_t TextToPhonemes(int8_t* input, size_t max_size);
// END reciter.h
// BEGIN reciter_tabs.h
// some flags
//
//  0x01        numeric
//  0x02        rule set 2
//  0x04        D J L N
//  0x08        B D G J L M N R V W Z
//  0x10        C G J S X Z R S T Z
//  0x20        B C D F G H J K L M N P Q R S T V X Y Z
//  0x40        is vowel + Y
//  0x80        alpha or '
const uint8_t tab36376[] = {
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,                                                           // ' '
    0                                           | 0x02,          // '!'
    0                                           | 0x02,          // '"'
    0                                           | 0x02,          // '#'
    0                                           | 0x02,          // '$'
    0                                           | 0x02,          // '%'
    0                                           | 0x02,          // '&'
    0 | 0x80                                    | 0x02,          // '''
    0,                                                           // '('
    0,                                                           // ')'
    0                                           | 0x02,          // '*'
    0                                           | 0x02,          // '+'
    0                                           | 0x02,          // ','
    0                                           | 0x02,          // '-'
    0                                           | 0x02,          // '.'
    0                                           | 0x02,          // '/'
    0                                           | 0x02 | 0x01,   // '0'
    0                                           | 0x02 | 0x01,   // '1'
    0                                           | 0x02 | 0x01,   // '2'
    0                                           | 0x02 | 0x01,   // '3'
    0                                           | 0x02 | 0x01,   // '4'
    0                                           | 0x02 | 0x01,   // '5'
    0                                           | 0x02 | 0x01,   // '6'
    0                                           | 0x02 | 0x01,   // '7'
    0                                           | 0x02 | 0x01,   // '8'
    0                                           | 0x02 | 0x01,   // '9'
    0                                           | 0x02,          // ':'
    0                                           | 0x02,          // ';'
    0                                           | 0x02,          // '<'
    0                                           | 0x02,          // '='
    0                                           | 0x02,          // '>'
    0                                           | 0x02,          // '?'
    0                                           | 0x02,          // '@'
    0 | 0x80 | 0x40,                                             // 'A'
    0 | 0x80        | 0x20        | 0x08,                        // 'B'
    0 | 0x80        | 0x20 | 0x10,                               // 'C'
    0 | 0x80        | 0x20        | 0x08 | 0x04,                 // 'D'
    0 | 0x80 | 0x40,                                             // 'E'
    0 | 0x80        | 0x20,                                      // 'F'
    0 | 0x80        | 0x20 | 0x10 | 0x08,                        // 'G'
    0 | 0x80        | 0x20,                                      // 'H'
    0 | 0x80 | 0x40,                                             // 'I'
    0 | 0x80        | 0x20 | 0x10 | 0x08 | 0x04,                 // 'J'
    0 | 0x80        | 0x20,                                      // 'K'
    0 | 0x80        | 0x20        | 0x08 | 0x04,                 // 'L'
    0 | 0x80        | 0x20        | 0x08,                        // 'M'
    0 | 0x80        | 0x20        | 0x08 | 0x04,                 // 'N'
    0 | 0x80 | 0x40,                                             // 'O'
    0 | 0x80        | 0x20,                                      // 'P'
    0 | 0x80        | 0x20,                                      // 'Q'
    0 | 0x80        | 0x20        | 0x08 | 0x04,                 // 'R'
    0 | 0x80        | 0x20 | 0x10        | 0x04,                 // 'S'
    0 | 0x80        | 0x20               | 0x04,                 // 'T'
    0 | 0x80 | 0x40,                                             // 'U'
    0 | 0x80        | 0x20        | 0x08,                        // 'V'
    0 | 0x80        | 0x20        | 0x08,                        // 'W'
    0 | 0x80        | 0x20 | 0x10,                               // 'X'
    0 | 0x80 | 0x40,                                             // 'Y'
    0 | 0x80        | 0x20 | 0x10 | 0x08 | 0x04,                 // 'Z'
    0,                                                           // '['
    0,                                                           // '\'
    0,                                                           // ']'
    0                                           | 0x02,          // '^'
    0,                                                           // '_'
    0               | 0x20                      | 0x02,          // '`'
  };
 
  const int8_t rules[] = {
    "]\xc1"                                        // ']A'
    " (A.)=EH4Y.\xa0"                              // ' (A.)=EH4Y. '
    "(A) =A\xc8"                                   // '(A) =AH'
    " (ARE) =AA\xd2"                               // ' (ARE) =AAR'
    " (AR)O=AX\xd2"                                // ' (AR)O=AXR'
    "(AR)#=EH4\xd2"                                // '(AR)#=EH4R'
    " ^(AS)#=EY4\xd3"                              // ' ^(AS)#=EY4S'
    "(A)WA=A\xd8"                                  // '(A)WA=AX'
    "(AW)=AO\xb5"                                  // '(AW)=AO5'
    " :(ANY)=EH4NI\xd9"                            // ' :(ANY)=EH4NIY'
    "(A)^+#=EY\xb5"                                // '(A)^+#=EY5'
    "#:(ALLY)=ULI\xd9"                             // '#:(ALLY)=ULIY'
    " (AL)#=U\xcc"                                 // ' (AL)#=UL'
    "(AGAIN)=AXGEH4\xce"                           // '(AGAIN)=AXGEH4N'
    "#:(AG)E=IH\xca"                               // '#:(AG)E=IHJ'
    "(A)^%=E\xd9"                                  // '(A)^%=EY'
    "(A)^+:#=A\xc5"                                // '(A)^+:#=AE'
    " :(A)^+ =EY\xb4"                              // ' :(A)^+ =EY4'
    " (ARR)=AX\xd2"                                // ' (ARR)=AXR'
    "(ARR)=AE4\xd2"                                // '(ARR)=AE4R'
    " ^(AR) =AA5\xd2"                              // ' ^(AR) =AA5R'
    "(AR)=AA5\xd2"                                 // '(AR)=AA5R'
    "(AIR)=EH4\xd2"                                // '(AIR)=EH4R'
    "(AI)=EY\xb4"                                  // '(AI)=EY4'
    "(AY)=EY\xb5"                                  // '(AY)=EY5'
    "(AU)=AO\xb4"                                  // '(AU)=AO4'
    "#:(AL) =U\xcc"                                // '#:(AL) =UL'
    "#:(ALS) =UL\xda"                              // '#:(ALS) =ULZ'
    "(ALK)=AO4\xcb"                                // '(ALK)=AO4K'
    "(AL)^=AO\xcc"                                 // '(AL)^=AOL'
    " :(ABLE)=EY4BU\xcc"                           // ' :(ABLE)=EY4BUL'
    "(ABLE)=AXBU\xcc"                              // '(ABLE)=AXBUL'
    "(A)VO=EY\xb4"                                 // '(A)VO=EY4'
    "(ANG)+=EY4N\xca"                              // '(ANG)+=EY4NJ'
    "(ATARI)=AHTAA4RI\xd9"                         // '(ATARI)=AHTAA4RIY'
    "(A)TOM=A\xc5"                                 // '(A)TOM=AE'
    "(A)TTI=A\xc5"                                 // '(A)TTI=AE'
    " (AT) =AE\xd4"                                // ' (AT) =AET'
    " (A)T=A\xc8"                                  // ' (A)T=AH'
    "(A)=A\xc5"                                    // '(A)=AE'
 
    "]\xc2"                                        // ']B'
    " (B) =BIY\xb4"                                // ' (B) =BIY4'
    " (BE)^#=BI\xc8"                               // ' (BE)^#=BIH'
    "(BEING)=BIY4IHN\xd8"                          // '(BEING)=BIY4IHNX'
    " (BOTH) =BOW4T\xc8"                           // ' (BOTH) =BOW4TH'
    " (BUS)#=BIH4\xda"                             // ' (BUS)#=BIH4Z'
    "(BREAK)=BREY5\xcb"                            // '(BREAK)=BREY5K'
    "(BUIL)=BIH4\xcc"                              // '(BUIL)=BIH4L'
    "(B)=\xc2"                                     // '(B)=B'
 
    "]\xc3"                                        // ']C'
    " (C) =SIY\xb4"                                // ' (C) =SIY4'
    " (CH)^=\xcb"                                  // ' (CH)^=K'
    "^E(CH)=\xcb"                                  // '^E(CH)=K'
    "(CHA)R#=KEH\xb5"                              // '(CHA)R#=KEH5'
    "(CH)=C\xc8"                                   // '(CH)=CH'
    " S(CI)#=SAY\xb4"                              // ' S(CI)#=SAY4'
    "(CI)A=S\xc8"                                  // '(CI)A=SH'
    "(CI)O=S\xc8"                                  // '(CI)O=SH'
    "(CI)EN=S\xc8"                                 // '(CI)EN=SH'
    "(CITY)=SIHTI\xd9"                             // '(CITY)=SIHTIY'
    "(C)+=\xd3"                                    // '(C)+=S'
    "(CK)=\xcb"                                    // '(CK)=K'
    "(COMMODORE)=KAA4MAHDOH\xd2"                   // '(COMMODORE)=KAA4MAHDOHR'
    "(COM)=KAH\xcd"                                // '(COM)=KAHM'
    "(CUIT)=KIH\xd4"                               // '(CUIT)=KIHT'
    "(CREA)=KRIYE\xd9"                             // '(CREA)=KRIYEY'
    "(C)=\xcb"                                     // '(C)=K'
 
    "]\xc4"                                        // ']D'
    " (D) =DIY\xb4"                                // ' (D) =DIY4'
    " (DR.) =DAA4KTE\xd2"                          // ' (DR.) =DAA4KTER'
    "#:(DED) =DIH\xc4"                             // '#:(DED) =DIHD'
    ".E(D) =\xc4"                                  // '.E(D) =D'
    "#:^E(D) =\xd4"                                // '#:^E(D) =T'
    " (DE)^#=DI\xc8"                               // ' (DE)^#=DIH'
    " (DO) =DU\xd7"                                // ' (DO) =DUW'
    " (DOES)=DAH\xda"                              // ' (DOES)=DAHZ'
    "(DONE) =DAH5\xce"                             // '(DONE) =DAH5N'
    "(DOING)=DUW4IHN\xd8"                          // '(DOING)=DUW4IHNX'
    " (DOW)=DA\xd7"                                // ' (DOW)=DAW'
    "#(DU)A=JU\xd7"                                // '#(DU)A=JUW'
    "#(DU)^#=JA\xd8"                               // '#(DU)^#=JAX'
    "(D)=\xc4"                                     // '(D)=D'
 
    "]\xc5"                                        // ']E'
    " (E) =IYIY\xb4"                               // ' (E) =IYIY4'
    "#:(E) \xbd"                                   // '#:(E) ='
    "\\':^(E) \xbd"                                // '\\':^(E) ='
    " :(E) =I\xd9"                                 // ' :(E) =IY'
    "#(ED) =\xc4"                                  // '#(ED) =D'
    "#:(E)D \xbd"                                  // '#:(E)D ='
    "(EV)ER=EH4\xd6"                               // '(EV)ER=EH4V'
    "(E)^%=IY\xb4"                                 // '(E)^%=IY4'
    "(ERI)#=IY4RI\xd9"                             // '(ERI)#=IY4RIY'
    "(ERI)=EH4RI\xc8"                              // '(ERI)=EH4RIH'
    "#:(ER)#=E\xd2"                                // '#:(ER)#=ER'
    "(ERROR)=EH4ROH\xd2"                           // '(ERROR)=EH4ROHR'
    "(ERASE)=IHREY5\xd3"                           // '(ERASE)=IHREY5S'
    "(ER)#=EH\xd2"                                 // '(ER)#=EHR'
    "(ER)=E\xd2"                                   // '(ER)=ER'
    " (EVEN)=IYVEH\xce"                            // ' (EVEN)=IYVEHN'
    "#:(E)W\xbd"                                   // '#:(E)W='
    "@(EW)=U\xd7"                                  // '@(EW)=UW'
    "(EW)=YU\xd7"                                  // '(EW)=YUW'
    "(E)O=I\xd9"                                   // '(E)O=IY'
    "#:&(ES) =IH\xda"                              // '#:&(ES) =IHZ'
    "#:(E)S \xbd"                                  // '#:(E)S ='
    "#:(ELY) =LI\xd9"                              // '#:(ELY) =LIY'
    "#:(EMENT)=MEHN\xd4"                           // '#:(EMENT)=MEHNT'
    "(EFUL)=FUH\xcc"                               // '(EFUL)=FUHL'
    "(EE)=IY\xb4"                                  // '(EE)=IY4'
    "(EARN)=ER5\xce"                               // '(EARN)=ER5N'
    " (EAR)^=ER\xb5"                               // ' (EAR)^=ER5'
    "(EAD)=EH\xc4"                                 // '(EAD)=EHD'
    "#:(EA) =IYA\xd8"                              // '#:(EA) =IYAX'
    "(EA)SU=EH\xb5"                                // '(EA)SU=EH5'
    "(EA)=IY\xb5"                                  // '(EA)=IY5'
    "(EIGH)=EY\xb4"                                // '(EIGH)=EY4'
    "(EI)=IY\xb4"                                  // '(EI)=IY4'
    " (EYE)=AY\xb4"                                // ' (EYE)=AY4'
    "(EY)=I\xd9"                                   // '(EY)=IY'
    "(EU)=YUW\xb5"                                 // '(EU)=YUW5'
    "(EQUAL)=IY4KWU\xcc"                           // '(EQUAL)=IY4KWUL'
    "(E)=E\xc8"                                    // '(E)=EH'
 
    "]\xc6"                                        // ']F'
    " (F) =EH4\xc6"                                // ' (F) =EH4F'
    "(FUL)=FUH\xcc"                                // '(FUL)=FUHL'
    "(FRIEND)=FREH5N\xc4"                          // '(FRIEND)=FREH5ND'
    "(FATHER)=FAA4DHE\xd2"                         // '(FATHER)=FAA4DHER'
    "(F)F\xbd"                                     // '(F)F='
    "(F)=\xc6"                                     // '(F)=F'
 
    "]\xc7"                                        // ']G'
    " (G) =JIY\xb4"                                // ' (G) =JIY4'
    "(GIV)=GIH5\xd6"                               // '(GIV)=GIH5V'
    " (G)I^=\xc7"                                  // ' (G)I^=G'
    "(GE)T=GEH\xb5"                                // '(GE)T=GEH5'
    "SU(GGES)=GJEH4\xd3"                           // 'SU(GGES)=GJEH4S'
    "(GG)=\xc7"                                    // '(GG)=G'
    " B#(G)=\xc7"                                  // ' B#(G)=G'
    "(G)+=\xca"                                    // '(G)+=J'
    "(GREAT)=GREY4\xd4"                            // '(GREAT)=GREY4T'
    "(GON)E=GAO5\xce"                              // '(GON)E=GAO5N'
    "#(GH)\xbd"                                    // '#(GH)='
    " (GN)=\xce"                                   // ' (GN)=N'
    "(G)=\xc7"                                     // '(G)=G'
 
    "]\xc8"                                        // ']H'
    " (H) =EY4C\xc8"                               // ' (H) =EY4CH'
    " (HAV)=/HAE6\xd6"                             // ' (HAV)=/HAE6V'
    " (HERE)=/HIY\xd2"                             // ' (HERE)=/HIYR'
    " (HOUR)=AW5E\xd2"                             // ' (HOUR)=AW5ER'
    "(HOW)=/HA\xd7"                                // '(HOW)=/HAW'
    "(H)#=/\xc8"                                   // '(H)#=/H'
    "(H)\xbd"                                      // '(H)='
 
    "]\xc9"                                        // ']I'
    " (IN)=IH\xce"                                 // ' (IN)=IHN'
    " (I) =AY\xb4"                                 // ' (I) =AY4'
    "(I) =A\xd9"                                   // '(I) =AY'
    "(IN)D=AY5\xce"                                // '(IN)D=AY5N'
    "SEM(I)=I\xd9"                                 // 'SEM(I)=IY'
    " ANT(I)=A\xd9"                                // ' ANT(I)=AY'
    "(IER)=IYE\xd2"                                // '(IER)=IYER'
    "#:R(IED) =IY\xc4"                             // '#:R(IED) =IYD'
    "(IED) =AY5\xc4"                               // '(IED) =AY5D'
    "(IEN)=IYEH\xce"                               // '(IEN)=IYEHN'
    "(IE)T=AY4E\xc8"                               // '(IE)T=AY4EH'
    "(I\\')=AY\xb5"                                // '(I\\')=AY5'
    " :(I)^%=AY\xb5"                               // ' :(I)^%=AY5'
    " :(IE) =AY\xb4"                               // ' :(IE) =AY4'
    "(I)%=I\xd9"                                   // '(I)%=IY'
    "(IE)=IY\xb4"                                  // '(IE)=IY4'
    " (IDEA)=AYDIY5A\xc8"                          // ' (IDEA)=AYDIY5AH'
    "(I)^+:#=I\xc8"                                // '(I)^+:#=IH'
    "(IR)#=AY\xd2"                                 // '(IR)#=AYR'
    "(IZ)%=AY\xda"                                 // '(IZ)%=AYZ'
    "(IS)%=AY\xda"                                 // '(IS)%=AYZ'
    "I^(I)^#=I\xc8"                                // 'I^(I)^#=IH'
    "+^(I)^+=A\xd9"                                // '+^(I)^+=AY'
    "#:^(I)^+=I\xc8"                               // '#:^(I)^+=IH'
    "(I)^+=A\xd9"                                  // '(I)^+=AY'
    "(IR)=E\xd2"                                   // '(IR)=ER'
    "(IGH)=AY\xb4"                                 // '(IGH)=AY4'
    "(ILD)=AY5L\xc4"                               // '(ILD)=AY5LD'
    " (IGN)=IHG\xce"                               // ' (IGN)=IHGN'
    "(IGN) =AY4\xce"                               // '(IGN) =AY4N'
    "(IGN)^=AY4\xce"                               // '(IGN)^=AY4N'
    "(IGN)%=AY4\xce"                               // '(IGN)%=AY4N'
    "(ICRO)=AY4KRO\xc8"                            // '(ICRO)=AY4KROH'
    "(IQUE)=IY4\xcb"                               // '(IQUE)=IY4K'
    "(I)=I\xc8"                                    // '(I)=IH'
 
    "]\xca"                                        // ']J'
    " (J) =JEY\xb4"                                // ' (J) =JEY4'
    "(J)=\xca"                                     // '(J)=J'
 
    "]\xcb"                                        // ']K'
    " (K) =KEY\xb4"                                // ' (K) =KEY4'
    " (K)N\xbd"                                    // ' (K)N='
    "(K)=\xcb"                                     // '(K)=K'
 
    "]\xcc"                                        // ']L'
    " (L) =EH4\xcc"                                // ' (L) =EH4L'
    "(LO)C#=LO\xd7"                                // '(LO)C#=LOW'
    "L(L)\xbd"                                     // 'L(L)='
    "#:^(L)%=U\xcc"                                // '#:^(L)%=UL'
    "(LEAD)=LIY\xc4"                               // '(LEAD)=LIYD'
    " (LAUGH)=LAE4\xc6"                            // ' (LAUGH)=LAE4F'
    "(L)=\xcc"                                     // '(L)=L'
 
    "]\xcd"                                        // ']M'
    " (M) =EH4\xcd"                                // ' (M) =EH4M'
    " (MR.) =MIH4STE\xd2"                          // ' (MR.) =MIH4STER'
    " (MS.)=MIH5\xda"                              // ' (MS.)=MIH5Z'
    " (MRS.) =MIH4SIX\xda"                         // ' (MRS.) =MIH4SIXZ'
    "(MOV)=MUW4\xd6"                               // '(MOV)=MUW4V'
    "(MACHIN)=MAHSHIY5\xce"                        // '(MACHIN)=MAHSHIY5N'
    "M(M)\xbd"                                     // 'M(M)='
    "(M)=\xcd"                                     // '(M)=M'
 
    "]\xce"                                        // ']N'
    " (N) =EH4\xce"                                // ' (N) =EH4N'
    "E(NG)+=N\xca"                                 // 'E(NG)+=NJ'
    "(NG)R=NX\xc7"                                 // '(NG)R=NXG'
    "(NG)#=NX\xc7"                                 // '(NG)#=NXG'
    "(NGL)%=NXGU\xcc"                              // '(NGL)%=NXGUL'
    "(NG)=N\xd8"                                   // '(NG)=NX'
    "(NK)=NX\xcb"                                  // '(NK)=NXK'
    " (NOW) =NAW\xb4"                              // ' (NOW) =NAW4'
    "N(N)\xbd"                                     // 'N(N)='
    "(NON)E=NAH4\xce"                              // '(NON)E=NAH4N'
    "(N)=\xce"                                     // '(N)=N'
 
    "]\xcf"                                        // ']O'
    " (O) =OH4\xd7"                                // ' (O) =OH4W'
    "(OF) =AH\xd6"                                 // '(OF) =AHV'
    " (OH) =OW\xb5"                                // ' (OH) =OW5'
    "(OROUGH)=ER4O\xd7"                            // '(OROUGH)=ER4OW'
    "#:(OR) =E\xd2"                                // '#:(OR) =ER'
    "#:(ORS) =ER\xda"                              // '#:(ORS) =ERZ'
    "(OR)=AO\xd2"                                  // '(OR)=AOR'
    " (ONE)=WAH\xce"                               // ' (ONE)=WAHN'
    "#(ONE) =WAH\xce"                              // '#(ONE) =WAHN'
    "(OW)=O\xd7"                                   // '(OW)=OW'
    " (OVER)=OW5VE\xd2"                            // ' (OVER)=OW5VER'
    "PR(O)V=UW\xb4"                                // 'PR(O)V=UW4'
    "(OV)=AH4\xd6"                                 // '(OV)=AH4V'
    "(O)^%=OW\xb5"                                 // '(O)^%=OW5'
    "(O)^EN=O\xd7"                                 // '(O)^EN=OW'
    "(O)^I#=OW\xb5"                                // '(O)^I#=OW5'
    "(OL)D=OW4\xcc"                                // '(OL)D=OW4L'
    "(OUGHT)=AO5\xd4"                              // '(OUGHT)=AO5T'
    "(OUGH)=AH5\xc6"                               // '(OUGH)=AH5F'
    " (OU)=A\xd7"                                  // ' (OU)=AW'
    "H(OU)S#=AW\xb4"                               // 'H(OU)S#=AW4'
    "(OUS)=AX\xd3"                                 // '(OUS)=AXS'
    "(OUR)=OH\xd2"                                 // '(OUR)=OHR'
    "(OULD)=UH5\xc4"                               // '(OULD)=UH5D'
    "(OU)^L=AH\xb5"                                // '(OU)^L=AH5'
    "(OUP)=UW5\xd0"                                // '(OUP)=UW5P'
    "(OU)=A\xd7"                                   // '(OU)=AW'
    "(OY)=O\xd9"                                   // '(OY)=OY'
    "(OING)=OW4IHN\xd8"                            // '(OING)=OW4IHNX'
    "(OI)=OY\xb5"                                  // '(OI)=OY5'
    "(OOR)=OH5\xd2"                                // '(OOR)=OH5R'
    "(OOK)=UH5\xcb"                                // '(OOK)=UH5K'
    "F(OOD)=UW5\xc4"                               // 'F(OOD)=UW5D'
    "L(OOD)=AH5\xc4"                               // 'L(OOD)=AH5D'
    "M(OOD)=UW5\xc4"                               // 'M(OOD)=UW5D'
    "(OOD)=UH5\xc4"                                // '(OOD)=UH5D'
    "F(OOT)=UH5\xd4"                               // 'F(OOT)=UH5T'
    "(OO)=UW\xb5"                                  // '(OO)=UW5'
    "(O\\')=O\xc8"                                 // '(O\\')=OH'
    "(O)E=O\xd7"                                   // '(O)E=OW'
    "(O) =O\xd7"                                   // '(O) =OW'
    "(OA)=OW\xb4"                                  // '(OA)=OW4'
    " (ONLY)=OW4NLI\xd9"                           // ' (ONLY)=OW4NLIY'
    " (ONCE)=WAH4N\xd3"                            // ' (ONCE)=WAH4NS'
    "(ON\\'T)=OW4N\xd4"                            // '(ON\\'T)=OW4NT'
    "C(O)N=A\xc1"                                  // 'C(O)N=AA'
    "(O)NG=A\xcf"                                  // '(O)NG=AO'
    " :^(O)N=A\xc8"                                // ' :^(O)N=AH'
    "I(ON)=U\xce"                                  // 'I(ON)=UN'
    "#:(ON)=U\xce"                                 // '#:(ON)=UN'
    "#^(ON)=U\xce"                                 // '#^(ON)=UN'
    "(O)ST=O\xd7"                                  // '(O)ST=OW'
    "(OF)^=AO4\xc6"                                // '(OF)^=AO4F'
    "(OTHER)=AH5DHE\xd2"                           // '(OTHER)=AH5DHER'
    "R(O)B=RA\xc1"                                 // 'R(O)B=RAA'
    "^R(O):#=OW\xb5"                               // '^R(O):#=OW5'
    "(OSS) =AO5\xd3"                               // '(OSS) =AO5S'
    "#:^(OM)=AH\xcd"                               // '#:^(OM)=AHM'
    "(O)=A\xc1"                                    // '(O)=AA'
 
    "]\xd0"                                        // ']P'
    " (P) =PIY\xb4"                                // ' (P) =PIY4'
    "(PH)=\xc6"                                    // '(PH)=F'
    "(PEOPL)=PIY5PU\xcc"                           // '(PEOPL)=PIY5PUL'
    "(POW)=PAW\xb4"                                // '(POW)=PAW4'
    "(PUT) =PUH\xd4"                               // '(PUT) =PUHT'
    "(P)P\xbd"                                     // '(P)P='
    "(P)S\xbd"                                     // '(P)S='
    "(P)N\xbd"                                     // '(P)N='
    "(PROF.)=PROHFEH4SE\xd2"                       // '(PROF.)=PROHFEH4SER'
    "(P)=\xd0"                                     // '(P)=P'
 
    "]\xd1"                                        // ']Q'
    " (Q) =KYUW\xb4"                               // ' (Q) =KYUW4'
    "(QUAR)=KWOH5\xd2"                             // '(QUAR)=KWOH5R'
    "(QU)=K\xd7"                                   // '(QU)=KW'
    "(Q)=\xcb"                                     // '(Q)=K'
    "]\xd2"                                        // ']R'
    " (R) =AA5\xd2"                                // ' (R) =AA5R'
    " (RE)^#=RI\xd9"                               // ' (RE)^#=RIY'
    "(R)R\xbd"                                     // '(R)R='
    "(R)=\xd2"                                     // '(R)=R'
 
    "]\xd3"                                        // ']S'
    " (S) =EH4\xd3"                                // ' (S) =EH4S'
    "(SH)=S\xc8"                                   // '(SH)=SH'
    "#(SION)=ZHU\xce"                              // '#(SION)=ZHUN'
    "(SOME)=SAH\xcd"                               // '(SOME)=SAHM'
    "#(SUR)#=ZHE\xd2"                              // '#(SUR)#=ZHER'
    "(SUR)#=SHE\xd2"                               // '(SUR)#=SHER'
    "#(SU)#=ZHU\xd7"                               // '#(SU)#=ZHUW'
    "#(SSU)#=SHU\xd7"                              // '#(SSU)#=SHUW'
    "#(SED)=Z\xc4"                                 // '#(SED)=ZD'
    "#(S)#=\xda"                                   // '#(S)#=Z'
    "(SAID)=SEH\xc4"                               // '(SAID)=SEHD'
    "^(SION)=SHU\xce"                              // '^(SION)=SHUN'
    "(S)S\xbd"                                     // '(S)S='
    ".(S) =\xda"                                   // '.(S) =Z'
    "#:.E(S) =\xda"                                // '#:.E(S) =Z'
    "#:^#(S) =\xd3"                                // '#:^#(S) =S'
    "U(S) =\xd3"                                   // 'U(S) =S'
    " :#(S) =\xda"                                 // ' :#(S) =Z'
    "##(S) =\xda"                                  // '##(S) =Z'
    " (SCH)=S\xcb"                                 // ' (SCH)=SK'
    "(S)C+\xbd"                                    // '(S)C+='
    "#(SM)=ZU\xcd"                                 // '#(SM)=ZUM'
    "#(SN)\\'=ZU\xcd"                              // '#(SN)\\'=ZUM'
    "(STLE)=SU\xcc"                                // '(STLE)=SUL'
    "(S)=\xd3"                                     // '(S)=S'
 
    "]\xd4"                                        // ']T'
    " (T) =TIY\xb4"                                // ' (T) =TIY4'
    " (THE) #=DHI\xd9"                             // ' (THE) #=DHIY'
    " (THE) =DHA\xd8"                              // ' (THE) =DHAX'
    "(TO) =TU\xd8"                                 // '(TO) =TUX'
    " (THAT)=DHAE\xd4"                             // ' (THAT)=DHAET'
    " (THIS) =DHIH\xd3"                            // ' (THIS) =DHIHS'
    " (THEY)=DHE\xd9"                              // ' (THEY)=DHEY'
    " (THERE)=DHEH\xd2"                            // ' (THERE)=DHEHR'
    "(THER)=DHE\xd2"                               // '(THER)=DHER'
    "(THEIR)=DHEH\xd2"                             // '(THEIR)=DHEHR'
    " (THAN) =DHAE\xce"                            // ' (THAN) =DHAEN'
    " (THEM) =DHAE\xce"                            // ' (THEM) =DHAEN'
    "(THESE) =DHIY\xda"                            // '(THESE) =DHIYZ'
    " (THEN)=DHEH\xce"                             // ' (THEN)=DHEHN'
    "(THROUGH)=THRUW\xb4"                          // '(THROUGH)=THRUW4'
    "(THOSE)=DHOH\xda"                             // '(THOSE)=DHOHZ'
    "(THOUGH) =DHO\xd7"                            // '(THOUGH) =DHOW'
    "(TODAY)=TUXDE\xd9"                            // '(TODAY)=TUXDEY'
    "(TOMO)RROW=TUMAA\xb5"                         // '(TOMO)RROW=TUMAA5'
    "(TO)TAL=TOW\xb5"                              // '(TO)TAL=TOW5'
    " (THUS)=DHAH4\xd3"                            // ' (THUS)=DHAH4S'
    "(TH)=T\xc8"                                   // '(TH)=TH'
    "#:(TED)=TIX\xc4"                              // '#:(TED)=TIXD'
    "S(TI)#N=C\xc8"                                // 'S(TI)#N=CH'
    "(TI)O=S\xc8"                                  // '(TI)O=SH'
    "(TI)A=S\xc8"                                  // '(TI)A=SH'
    "(TIEN)=SHU\xce"                               // '(TIEN)=SHUN'
    "(TUR)#=CHE\xd2"                               // '(TUR)#=CHER'
    "(TU)A=CHU\xd7"                                // '(TU)A=CHUW'
    " (TWO)=TU\xd7"                                // ' (TWO)=TUW'
    "&(T)EN \xbd"                                  // '&(T)EN ='
    "(T)=\xd4"                                     // '(T)=T'
 
    "]\xd5"                                        // ']U'
    " (U) =YUW\xb4"                                // ' (U) =YUW4'
    " (UN)I=YUW\xce"                               // ' (UN)I=YUWN'
    " (UN)=AH\xce"                                 // ' (UN)=AHN'
    " (UPON)=AXPAO\xce"                            // ' (UPON)=AXPAON'
    "@(UR)#=UH4\xd2"                               // '@(UR)#=UH4R'
    "(UR)#=YUH4\xd2"                               // '(UR)#=YUH4R'
    "(UR)=E\xd2"                                   // '(UR)=ER'
    "(U)^ =A\xc8"                                  // '(U)^ =AH'
    "(U)^^=AH\xb5"                                 // '(U)^^=AH5'
    "(UY)=AY\xb5"                                  // '(UY)=AY5'
    " G(U)#\xbd"                                   // ' G(U)#='
    "G(U)%\xbd"                                    // 'G(U)%='
    "G(U)#=\xd7"                                   // 'G(U)#=W'
    "#N(U)=YU\xd7"                                 // '#N(U)=YUW'
    "@(U)=U\xd7"                                   // '@(U)=UW'
    "(U)=YU\xd7"                                   // '(U)=YUW'
 
    "]\xd6"                                        // ']V'
    " (V) =VIY\xb4"                                // ' (V) =VIY4'
    "(VIEW)=VYUW\xb5"                              // '(VIEW)=VYUW5'
    "(V)=\xd6"                                     // '(V)=V'
 
    "]\xd7"                                        // ']W'
    " (W) =DAH4BULYU\xd7"                          // ' (W) =DAH4BULYUW'
    " (WERE)=WE\xd2"                               // ' (WERE)=WER'
    "(WA)SH=WA\xc1"                                // '(WA)SH=WAA'
    "(WA)ST=WE\xd9"                                // '(WA)ST=WEY'
    "(WA)S=WA\xc8"                                 // '(WA)S=WAH'
    "(WA)T=WA\xc1"                                 // '(WA)T=WAA'
    "(WHERE)=WHEH\xd2"                             // '(WHERE)=WHEHR'
    "(WHAT)=WHAH\xd4"                              // '(WHAT)=WHAHT'
    "(WHOL)=/HOW\xcc"                              // '(WHOL)=/HOWL'
    "(WHO)=/HU\xd7"                                // '(WHO)=/HUW'
    "(WH)=W\xc8"                                   // '(WH)=WH'
    "(WAR)#=WEH\xd2"                               // '(WAR)#=WEHR'
    "(WAR)=WAO\xd2"                                // '(WAR)=WAOR'
    "(WOR)^=WE\xd2"                                // '(WOR)^=WER'
    "(WR)=\xd2"                                    // '(WR)=R'
    "(WOM)A=WUH\xcd"                               // '(WOM)A=WUHM'
    "(WOM)E=WIH\xcd"                               // '(WOM)E=WIHM'
    "(WEA)R=WE\xc8"                                // '(WEA)R=WEH'
    "(WANT)=WAA5N\xd4"                             // '(WANT)=WAA5NT'
    "ANS(WER)=E\xd2"                               // 'ANS(WER)=ER'
    "(W)=\xd7"                                     // '(W)=W'
 
    "]\xd8"                                        // ']X'
    " (X) =EH4K\xd2"                               // ' (X) =EH4KR'
    " (X)=\xda"                                    // ' (X)=Z'
    "(X)=K\xd3"                                    // '(X)=KS'
 
    "]\xd9"                                        // ']Y'
    " (Y) =WAY\xb4"                                // ' (Y) =WAY4'
    "(YOUNG)=YAHN\xd8"                             // '(YOUNG)=YAHNX'
    " (YOUR)=YOH\xd2"                              // ' (YOUR)=YOHR'
    " (YOU)=YU\xd7"                                // ' (YOU)=YUW'
    " (YES)=YEH\xd3"                               // ' (YES)=YEHS'
    " (Y)=\xd9"                                    // ' (Y)=Y'
    "F(Y)=A\xd9"                                   // 'F(Y)=AY'
    "PS(YCH)=AY\xcb"                               // 'PS(YCH)=AYK'
    "#:^(Y)=I\xd9"                                 // '#:^(Y)=IY'
    "#:^(Y)I=I\xd9"                                // '#:^(Y)I=IY'
    " :(Y) =A\xd9"                                 // ' :(Y) =AY'
    " :(Y)#=A\xd9"                                 // ' :(Y)#=AY'
    " :(Y)^+:#=I\xc8"                              // ' :(Y)^+:#=IH'
    " :(Y)^#=A\xd9"                                // ' :(Y)^#=AY'
    "(Y)=I\xc8"                                    // '(Y)=IH'
 
    "]\xda"                                        // ']Z'
    " (Z) =ZIY\xb4"                                // ' (Z) =ZIY4'
    "(Z)=\xda"                                     // '(Z)=Z'
 
    "]\xb0"                                        // ']0'
    "(A)\xbd"                                      // '(A)='
    "(!)=\xae"                                     // '(!)=.'
    "(\") =-AH5NKWOWT\xad"                         // '(\") =-AH5NKWOWT-'
    "(\")=KWOW4T\xad"                              // '(\")=KWOW4T-'
    "(#)= NAH4MBE\xd2"                             // '(#)= NAH4MBER'
    "($)= DAA4LE\xd2"                              // '($)= DAA4LER'
    "(%)= PERSEH4N\xd4"                            // '(%)= PERSEH4NT'
    "(&)= AEN\xc4"                                 // '(&)= AEND'
    "(\\)\xbd"                                     // '(\\)='
    "(*)= AE4STERIHS\xcb"                          // '(*)= AE4STERIHSK'
    "(+)= PLAH4\xd3"                               // '(+)= PLAH4S'
    "(,)=\xac"                                     // '(,)=,'
    " (-) =\xad"                                   // ' (-) =-'
    "(-)\xbd"                                      // '(-)='
    "(.)= POYN\xd4"                                // '(.)= POYNT'
    "(/)= SLAE4S\xc8"                              // '(/)= SLAE4SH'
    "(0)= ZIY4RO\xd7"                              // '(0)= ZIY4ROW'
    " (1ST)=FER4S\xd4"                             // ' (1ST)=FER4ST'
    " (10TH)=TEH4NT\xc8"                           // ' (10TH)=TEH4NTH'
    "(1)= WAH4\xce"                                // '(1)= WAH4N'
    " (2ND)=SEH4KUN\xc4"                           // ' (2ND)=SEH4KUND'
    "(2)= TUW\xb4"                                 // '(2)= TUW4'
    " (3RD)=THER4\xc4"                             // ' (3RD)=THER4D'
    "(3)= THRIY\xb4"                               // '(3)= THRIY4'
    "(4)= FOH4\xd2"                                // '(4)= FOH4R'
    " (5TH)=FIH4FT\xc8"                            // ' (5TH)=FIH4FTH'
    "(5)= FAY4\xd6"                                // '(5)= FAY4V'
    " (64) =SIH4KSTIY FOH\xd2"                     // ' (64) =SIH4KSTIY FOHR'
    "(6)= SIH4K\xd3"                               // '(6)= SIH4KS'
    "(7)= SEH4VU\xce"                              // '(7)= SEH4VUN'
    " (8TH)=EY4T\xc8"                              // ' (8TH)=EY4TH'
    "(8)= EY4\xd4"                                 // '(8)= EY4T'
    "(9)= NAY4\xce"                                // '(9)= NAY4N'
    "(:)=\xae"                                     // '(:)=.'
    "(;)=\xae"                                     // '(;)=.'
    "(<)= LEH4S DHAE\xce"                          // '(<)= LEH4S DHAEN'
    "(=)= IY4KWUL\xda"                             // '(=)= IY4KWULZ'
    "(>)= GREY4TER DHAE\xce"                       // '(>)= GREY4TER DHAEN'
    "(?)=\xbf"                                     // '(?)=?'
    "(@)= AE6\xd4"                                 // '(@)= AE6T'
    "(^)= KAE4RIX\xd4"                             // '(^)= KAE4RIXT'
    "(')\xbd"                                      // '(')='
    "(`)\xbd"                                      // '(`)='
 
    "]\xb1"                                        // ']1'
  }; // rules[]
 
  const uint16_t rule_tab[] = {
    0x00, 0x195, 0x1f7, 0x2a2, 0x33f, 0x4c6, 0x507, 0x57f,
    0x5c8, 0x728, 0x739, 0x750, 0x793, 0x7f3, 0x857, 0xaa5,
    0xb02, 0xb28, 0xb49, 0xc32, 0xdac, 0xe3b, 0xe58, 0xf33,
    0xf4c, 0xfdf, 0xff0, 0x11b7,
  }; // rule_tab
  #endif
 
  // END reciter_tabs.h
 
// BEGIN reciter.c
#define assert(X) { if (!(X)) __debugbreak(); }
uint32_t A;
uint8_t X;
uint32_t Y;
// secure copy of input because input will be overwritten by phonemes
static uint8_t inputtemp[1024]; // secure copy of input tab36096
// END reciter.c
// BEGIN render_tabs.h
const uint8_t tab48426[5] = { 0x18, 0x1A, 0x17, 0x17, 0x17 };
const uint8_t tab47492[] = {
    0, 0, 0xE0, 0xE6, 0xEC, 0xF3, 0xF9, 0,
    6, 0xC, 6
};
const uint8_t amplitudeRescale[] = {
    0, 1, 2, 2, 2, 3, 3, 4,
    4, 5, 6, 8, 9, 0xB, 0xD, 0xF, 0 //17 elements?
};
// Used to decide which phoneme's blend lengths. The candidate with the lower score is selected.
// tab45856
const uint8_t blendRank[] = {
    0, 0x1F, 0x1F, 0x1F, 0x1F, 2, 2, 2,
    2, 2, 2, 2, 2, 2, 5, 5,
    2, 0xA, 2, 8, 5, 5, 0xB, 0xA,
    9, 8, 8, 0xA0, 8, 8, 0x17, 0x1F,
    0x12, 0x12, 0x12, 0x12, 0x1E, 0x1E, 0x14, 0x14,
    0x14, 0x14, 0x17, 0x17, 0x1A, 0x1A, 0x1D, 0x1D,
    2, 2, 2, 2, 2, 2, 0x1A, 0x1D,
    0x1B, 0x1A, 0x1D, 0x1B, 0x1A, 0x1D, 0x1B, 0x1A,
    0x1D, 0x1B, 0x17, 0x1D, 0x17, 0x17, 0x1D, 0x17,
    0x17, 0x1D, 0x17, 0x17, 0x1D, 0x17, 0x17, 0x17
};
// Number of frames at the end of a phoneme devoted to interpolating to next phoneme's final value
//tab45696
const uint8_t outBlendLength[] = {
    0, 2, 2, 2, 2, 4, 4, 4,
    4, 4, 4, 4, 4, 4, 4, 4,
    4, 4, 3, 2, 4, 4, 2, 2,
    2, 2, 2, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 2, 2,
    2, 1, 0, 1, 0, 1, 0, 5,
    5, 5, 5, 5, 4, 4, 2, 0,
    1, 2, 0, 1, 2, 0, 1, 2,
    0, 1, 2, 0, 2, 2, 0, 1,
    3, 0, 2, 3, 0, 2, 0xA0, 0xA0
};
// Number of frames at beginning of a phoneme devoted to interpolating to phoneme's final value
// tab45776
const uint8_t inBlendLength[] = {
    0, 2, 2, 2, 2, 4, 4, 4,
    4, 4, 4, 4, 4, 4, 4, 4,
    4, 4, 3, 3, 4, 4, 3, 3,
    3, 3, 3, 1, 2, 3, 2, 1,
    3, 3, 3, 3, 1, 1, 3, 3,
    3, 2, 2, 3, 2, 3, 0, 0,
    5, 5, 5, 5, 4, 4, 2, 0,
    2, 2, 0, 3, 2, 0, 4, 2,
    0, 3, 2, 0, 2, 2, 0, 2,
    3, 0, 3, 3, 0, 3, 0xB0, 0xA0
};
// Looks like it's used as bit flags
// High bits masked by 248 (11111000)
//
// 32: S*    241         11110001
// 33: SH    226         11100010
// 34: F*    211         11010011
// 35: TH    187         10111011
// 36: /H    124         01111100
// 37: /X    149         10010101
// 38: Z*    1           00000001
// 39: ZH    2           00000010
// 40: V*    3           00000011
// 41: DH    3           00000011
// 43: **    114         01110010
// 45: **    2           00000010
// 67: **    27          00011011
// 70: **    25          00011001
// tab45936
const uint8_t sampledConsonantFlags[] = {
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0xF1, 0xE2, 0xD3, 0xBB, 0x7C, 0x95, 1, 2,
    3, 3, 0, 0x72, 0, 2, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0x1B, 0, 0, 0x19, 0,
    0, 0, 0, 0, 0, 0, 0, 0
};
//tab45056
//note: non cost
uint8_t freq1data[] = {
    0x00, 0x13, 0x13, 0x13, 0x13, 0xA, 0xE, 0x12, 0x18, 0x1A, 0x16, 0x14, 0x10, 0x14, 0xE, 0x12, 0xE, 0x12, 0x12, 0x10, 0xC, 0xE, 0xA, 0x12, 0xE, 0xA, 8, 6, 6, 6, 6, 0x11, 6, 6, 6, 6, 0xE, 0x10, 9, 0xA, 8, 0xA, 6, 6, 6, 5, 6, 0, 0x12, 0x1A, 0x14, 0x1A, 0x12, 0xC, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 0xA, 0xA, 6, 6, 6, 0x2C, 0x13
};
//tab451356
// note: non const
uint8_t freq2data[] = {
    0x00, 0x43, 0x43, 0x43, 0x43, 0x54, 0x48, 0x42,
    0x3E, 0x28, 0x2C, 0x1E, 0x24, 0x2C, 0x48, 0x30,
    0x24, 0x1E, 0x32, 0x24, 0x1C, 0x44, 0x18, 0x32,
    0x1E, 0x18, 0x52, 0x2E, 0x36, 0x56, 0x36, 0x43,
    0x49, 0x4F, 0x1A, 0x42, 0x49, 0x25, 0x33, 0x42,
    0x28, 0x2F, 0x4F, 0x4F, 0x42, 0x4F, 0x6E, 0x00,
    0x48, 0x26, 0x1E, 0x2A, 0x1E, 0x22, 0x1A, 0x1A,
    0x1A, 0x42, 0x42, 0x42, 0x6E, 0x6E, 0x6E, 0x54,
    0x54, 0x54, 0x1A, 0x1A, 0x1A, 0x42, 0x42, 0x42,
    0x6D, 0x56, 0x6D, 0x54, 0x54, 0x54, 0x7F, 0x7F
};
//tab45216
const uint8_t freq3data[] = {
    0x00, 0x5B, 0x5B, 0x5B, 0x5B, 0x6E, 0x5D, 0x5B,
    0x58, 0x59, 0x57, 0x58, 0x52, 0x59, 0x5D, 0x3E,
    0x52, 0x58, 0x3E, 0x6E, 0x50, 0x5D, 0x5A, 0x3C,
    0x6E, 0x5A, 0x6E, 0x51, 0x79, 0x65, 0x79, 0x5B,
    0x63, 0x6A, 0x51, 0x79, 0x5D, 0x52, 0x5D, 0x67,
    0x4C, 0x5D, 0x65, 0x65, 0x79, 0x65, 0x79, 0x00,
    0x5A, 0x58, 0x58, 0x58, 0x58, 0x52, 0x51, 0x51,
    0x51, 0x79, 0x79, 0x79, 0x70, 0x6E, 0x6E, 0x5E,
    0x5E, 0x5E, 0x51, 0x51, 0x51, 0x79, 0x79, 0x79,
    0x65, 0x65, 0x70, 0x5E, 0x5E, 0x5E, 0x08, 0x01
};
const uint8_t ampl1data[] = {
    0, 0, 0, 0, 0, 0xD, 0xD, 0xE,
    0xF, 0xF, 0xF, 0xF, 0xF, 0xC, 0xD, 0xC,
    0xF, 0xF, 0xD, 0xD, 0xD, 0xE, 0xD, 0xC,
    0xD, 0xD, 0xD, 0xC, 9, 9, 0, 0,
    0, 0, 0, 0, 0, 0, 0xB, 0xB,
    0xB, 0xB, 0, 0, 1, 0xB, 0, 2,
    0xE, 0xF, 0xF, 0xF, 0xF, 0xD, 2, 4,
    0, 2, 4, 0, 1, 4, 0, 1,
    4, 0, 0, 0, 0, 0, 0, 0,
    0, 0xC, 0, 0, 0, 0, 0xF, 0xF
};
const uint8_t ampl2data[] = {
    0, 0, 0, 0, 0, 0xA, 0xB, 0xD,
    0xE, 0xD, 0xC, 0xC, 0xB, 9, 0xB, 0xB,
    0xC, 0xC, 0xC, 8, 8, 0xC, 8, 0xA,
    8, 8, 0xA, 3, 9, 6, 0, 0,
    0, 0, 0, 0, 0, 0, 3, 5,
    3, 4, 0, 0, 0, 5, 0xA, 2,
    0xE, 0xD, 0xC, 0xD, 0xC, 8, 0, 1,
    0, 0, 1, 0, 0, 1, 0, 0,
    1, 0, 0, 0, 0, 0, 0, 0,
    0, 0xA, 0, 0, 0xA, 0, 0, 0
};
const uint8_t ampl3data[] = {
    0, 0, 0, 0, 0, 8, 7, 8,
    8, 1, 1, 0, 1, 0, 7, 5,
    1, 0, 6, 1, 0, 7, 0, 5,
    1, 0, 8, 0, 0, 3, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 1,
    0, 0, 0, 0, 0, 1, 0xE, 1,
    9, 1, 0, 1, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 7, 0, 0, 5, 0, 0x13, 0x10
};
//tab42240
const uint8_t sinus[] = {
    0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10,
    0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30,
    0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x40, 0x40,
    0x40, 0x40, 0x40, 0x40, 0x40, 0x50, 0x50, 0x50,
    0x50, 0x50, 0x50, 0x50, 0x50, 0x60, 0x60, 0x60,
    0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60,
    0x60, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
    0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
    0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
    0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
    0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60,
    0x60, 0x60, 0x60, 0x60, 0x50, 0x50, 0x50, 0x50,
    0x50, 0x50, 0x50, 0x50, 0x40, 0x40, 0x40, 0x40,
    0x40, 0x40, 0x40, 0x30, 0x30, 0x30, 0x30, 0x30,
    0x30, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
    0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00,
    0x00, 0x00, 0x00, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
    0xF0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xD0,
    0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xC0, 0xC0,
    0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xB0, 0xB0, 0xB0,
    0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xA0, 0xA0, 0xA0,
    0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0,
    0xA0, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
    0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0,
    0xA0, 0xA0, 0xA0, 0xA0, 0xB0, 0xB0, 0xB0, 0xB0,
    0xB0, 0xB0, 0xB0, 0xB0, 0xC0, 0xC0, 0xC0, 0xC0,
    0xC0, 0xC0, 0xC0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0,
    0xD0, 0xD0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0,
    0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0x00, 0x00
};
//tab42496
const uint8_t rectangle[] = {
    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
    0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
    0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
    0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
    0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
    0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
    0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
    0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
    0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
    0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
    0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
    0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
    0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
    0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
    0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
    0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
    0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70
};
//tab42752
const uint8_t multtable[] = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 1, 1, 2, 2, 3, 3,
    4, 4, 5, 5, 6, 6, 7, 7,
    0, 1, 2, 3, 4, 5, 6, 7,
    8, 9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF,
    0x00, 1, 3, 4, 6, 7, 9, 0xA,
    0xC, 0xD, 0xF, 0x10, 0x12, 0x13, 0x15, 0x16,
    0x00, 2, 4, 6, 8, 0xA, 0xC, 0xE,
    0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x1E,
    0x00, 2, 5, 7, 0xA, 0xC, 0xF, 0x11,
    0x14, 0x16, 0x19, 0x1B, 0x1E, 0x20, 0x23, 0x25,
    0x00, 3, 6, 9, 0xC, 0xF, 0x12, 0x15,
    0x18, 0x1B, 0x1E, 0x21, 0x24, 0x27, 0x2A, 0x2D,
    0x00, 0x03, 0x07, 0x0A, 0x0E, 0x11, 0x15, 0x18,
    0x1C, 0x1F, 0x23, 0x26, 0x2A, 0x2D, 0x31, 0x34,
    0x00, 0xFC, 0xF8, 0xF4, 0xF0, 0xEC, 0xE8, 0xE4,
    0xE0, 0xDC, 0xD8, 0xD4, 0xD0, 0xCC, 0xC8, 0xC4,
    0x00, 0xFC, 0xF9, 0xF5, 0xF2, 0xEE, 0xEB, 0xE7,
    0xE4, 0xE0, 0xDD, 0xD9, 0xD6, 0xD2, 0xCF, 0xCB,
    0x00, 0xFD, 0xFA, 0xF7, 0xF4, 0xF1, 0xEE, 0xEB,
    0xE8, 0xE5, 0xE2, 0xDF, 0xDC, 0xD9, 0xD6, 0xD3,
    0x00, 0xFD, 0xFB, 0xF8, 0xF6, 0xF3, 0xF1, 0xEE,
    0xEC, 0xE9, 0xE7, 0xE4, 0xE2, 0xDF, 0xDD, 0xDA,
    0x00, 0xFE, 0xFC, 0xFA, 0xF8, 0xF6, 0xF4, 0xF2,
    0xF0, 0xEE, 0xEC, 0xEA, 0xE8, 0xE6, 0xE4, 0xE2,
    0x00, 0xFE, 0xFD, 0xFB, 0xFA, 0xF8, 0xF7, 0xF5,
    0xF4, 0xF2, 0xF1, 0xEF, 0xEE, 0xEC, 0xEB, 0xE9,
    0x00, 0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9,
    0xF8, 0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2, 0xF1,
    0x00, 0xFF, 0xFF, 0xFE, 0xFE, 0xFD, 0xFD, 0xFC,
    0xFC, 0xFB, 0xFB, 0xFA, 0xFA, 0xF9, 0xF9, 0xF8
};
//random data ?
const uint8_t sampleTable[0x500] = {
    //00
    0x38, 0x84, 0x6B, 0x19, 0xC6, 0x63, 0x18, 0x86, 0x73, 0x98, 0xC6, 0xB1, 0x1C, 0xCA, 0x31, 0x8C, 0xC7, 0x31, 0x88, 0xC2, 0x30, 0x98, 0x46, 0x31, 0x18, 0xC6, 0x35, 0xC, 0xCA, 0x31, 0xC, 0xC6
    //20
    ,
    0x21, 0x10, 0x24, 0x69, 0x12, 0xC2, 0x31, 0x14, 0xC4, 0x71, 8, 0x4A, 0x22, 0x49, 0xAB, 0x6A, 0xA8, 0xAC, 0x49, 0x51, 0x32, 0xD5, 0x52, 0x88, 0x93, 0x6C, 0x94, 0x22, 0x15, 0x54, 0xD2, 0x25
    //40
    ,
    0x96, 0xD4, 0x50, 0xA5, 0x46, 0x21, 8, 0x85, 0x6B, 0x18, 0xC4, 0x63, 0x10, 0xCE, 0x6B, 0x18, 0x8C, 0x71, 0x19, 0x8C, 0x63, 0x35, 0xC, 0xC6, 0x33, 0x99, 0xCC, 0x6C, 0xB5, 0x4E, 0xA2, 0x99
    //60
    ,
    0x46, 0x21, 0x28, 0x82, 0x95, 0x2E, 0xE3, 0x30, 0x9C, 0xC5, 0x30, 0x9C, 0xA2, 0xB1, 0x9C, 0x67, 0x31, 0x88, 0x66, 0x59, 0x2C, 0x53, 0x18, 0x84, 0x67, 0x50, 0xCA, 0xE3, 0xA, 0xAC, 0xAB, 0x30
    //80
    ,
    0xAC, 0x62, 0x30, 0x8C, 0x63, 0x10, 0x94, 0x62, 0xB1, 0x8C, 0x82, 0x28, 0x96, 0x33, 0x98, 0xD6, 0xB5, 0x4C, 0x62, 0x29, 0xA5, 0x4A, 0xB5, 0x9C, 0xC6, 0x31, 0x14, 0xD6, 0x38, 0x9C, 0x4B, 0xB4
    //A0
    ,
    0x86, 0x65, 0x18, 0xAE, 0x67, 0x1C, 0xA6, 0x63, 0x19, 0x96, 0x23, 0x19, 0x84, 0x13, 8, 0xA6, 0x52, 0xAC, 0xCA, 0x22, 0x89, 0x6E, 0xAB, 0x19, 0x8C, 0x62, 0x34, 0xC4, 0x62, 0x19, 0x86, 0x63
    //C0
    ,
    0x18, 0xC4, 0x23, 0x58, 0xD6, 0xA3, 0x50, 0x42, 0x54, 0x4A, 0xAD, 0x4A, 0x25, 0x11, 0x6B, 0x64, 0x89, 0x4A, 0x63, 0x39, 0x8A, 0x23, 0x31, 0x2A, 0xEA, 0xA2, 0xA9, 0x44, 0xC5, 0x12, 0xCD, 0x42
    //E0
    ,
    0x34, 0x8C, 0x62, 0x18, 0x8C, 0x63, 0x11, 0x48, 0x66, 0x31, 0x9D, 0x44, 0x33, 0x1D, 0x46, 0x31, 0x9C, 0xC6, 0xB1, 0xC, 0xCD, 0x32, 0x88, 0xC4, 0x73, 0x18, 0x86, 0x73, 8, 0xD6, 0x63, 0x58
    //100
    ,
    7, 0x81, 0xE0, 0xF0, 0x3C, 7, 0x87, 0x90, 0x3C, 0x7C, 0xF, 0xC7, 0xC0, 0xC0, 0xF0, 0x7C, 0x1E, 7, 0x80, 0x80, 0, 0x1C, 0x78, 0x70, 0xF1, 0xC7, 0x1F, 0xC0, 0xC, 0xFE, 0x1C, 0x1F
    //120
    ,
    0x1F, 0xE, 0xA, 0x7A, 0xC0, 0x71, 0xF2, 0x83, 0x8F, 3, 0xF, 0xF, 0xC, 0, 0x79, 0xF8, 0x61, 0xE0, 0x43, 0xF, 0x83, 0xE7, 0x18, 0xF9, 0xC1, 0x13, 0xDA, 0xE9, 0x63, 0x8F, 0xF, 0x83
    //140
    ,
    0x83, 0x87, 0xC3, 0x1F, 0x3C, 0x70, 0xF0, 0xE1, 0xE1, 0xE3, 0x87, 0xB8, 0x71, 0xE, 0x20, 0xE3, 0x8D, 0x48, 0x78, 0x1C, 0x93, 0x87, 0x30, 0xE1, 0xC1, 0xC1, 0xE4, 0x78, 0x21, 0x83, 0x83, 0xC3
    //160
    ,
    0x87, 6, 0x39, 0xE5, 0xC3, 0x87, 7, 0xE, 0x1C, 0x1C, 0x70, 0xF4, 0x71, 0x9C, 0x60, 0x36, 0x32, 0xC3, 0x1E, 0x3C, 0xF3, 0x8F, 0xE, 0x3C, 0x70, 0xE3, 0xC7, 0x8F, 0xF, 0xF, 0xE, 0x3C
    //180
    ,
    0x78, 0xF0, 0xE3, 0x87, 6, 0xF0, 0xE3, 7, 0xC1, 0x99, 0x87, 0xF, 0x18, 0x78, 0x70, 0x70, 0xFC, 0xF3, 0x10, 0xB1, 0x8C, 0x8C, 0x31, 0x7C, 0x70, 0xE1, 0x86, 0x3C, 0x64, 0x6C, 0xB0, 0xE1
    //1A0
    ,
    0xE3, 0xF, 0x23, 0x8F, 0xF, 0x1E, 0x3E, 0x38, 0x3C, 0x38, 0x7B, 0x8F, 7, 0xE, 0x3C, 0xF4, 0x17, 0x1E, 0x3C, 0x78, 0xF2, 0x9E, 0x72, 0x49, 0xE3, 0x25, 0x36, 0x38, 0x58, 0x39, 0xE2, 0xDE
    //1C0
    ,
    0x3C, 0x78, 0x78, 0xE1, 0xC7, 0x61, 0xE1, 0xE1, 0xB0, 0xF0, 0xF0, 0xC3, 0xC7, 0xE, 0x38, 0xC0, 0xF0, 0xCE, 0x73, 0x73, 0x18, 0x34, 0xB0, 0xE1, 0xC7, 0x8E, 0x1C, 0x3C, 0xF8, 0x38, 0xF0, 0xE1
    //1E0
    ,
    0xC1, 0x8B, 0x86, 0x8F, 0x1C, 0x78, 0x70, 0xF0, 0x78, 0xAC, 0xB1, 0x8F, 0x39, 0x31, 0xDB, 0x38, 0x61, 0xC3, 0xE, 0xE, 0x38, 0x78, 0x73, 0x17, 0x1E, 0x39, 0x1E, 0x38, 0x64, 0xE1, 0xF1, 0xC1
    //200
    ,
    0x4E, 0xF, 0x40, 0xA2, 2, 0xC5, 0x8F, 0x81, 0xA1, 0xFC, 0x12, 8, 0x64, 0xE0, 0x3C, 0x22, 0xE0, 0x45, 7, 0x8E, 0xC, 0x32, 0x90, 0xF0, 0x1F, 0x20, 0x49, 0xE0, 0xF8, 0xC, 0x60, 0xF0
    //220
    ,
    0x17, 0x1A, 0x41, 0xAA, 0xA4, 0xD0, 0x8D, 0x12, 0x82, 0x1E, 0x1E, 3, 0xF8, 0x3E, 3, 0xC, 0x73, 0x80, 0x70, 0x44, 0x26, 3, 0x24, 0xE1, 0x3E, 4, 0x4E, 4, 0x1C, 0xC1, 9, 0xCC
    //240
    ,
    0x9E, 0x90, 0x21, 7, 0x90, 0x43, 0x64, 0xC0, 0xF, 0xC6, 0x90, 0x9C, 0xC1, 0x5B, 3, 0xE2, 0x1D, 0x81, 0xE0, 0x5E, 0x1D, 3, 0x84, 0xB8, 0x2C, 0xF, 0x80, 0xB1, 0x83, 0xE0, 0x30, 0x41
    //260
    ,
    0x1E, 0x43, 0x89, 0x83, 0x50, 0xFC, 0x24, 0x2E, 0x13, 0x83, 0xF1, 0x7C, 0x4C, 0x2C, 0xC9, 0xD, 0x83, 0xB0, 0xB5, 0x82, 0xE4, 0xE8, 6, 0x9C, 7, 0xA0, 0x99, 0x1D, 7, 0x3E, 0x82, 0x8F
    //280
    ,
    0x70, 0x30, 0x74, 0x40, 0xCA, 0x10, 0xE4, 0xE8, 0xF, 0x92, 0x14, 0x3F, 6, 0xF8, 0x84, 0x88, 0x43, 0x81, 0xA, 0x34, 0x39, 0x41, 0xC6, 0xE3, 0x1C, 0x47, 3, 0xB0, 0xB8, 0x13, 0xA, 0xC2
    //2A0
    ,
    0x64, 0xF8, 0x18, 0xF9, 0x60, 0xB3, 0xC0, 0x65, 0x20, 0x60, 0xA6, 0x8C, 0xC3, 0x81, 0x20, 0x30, 0x26, 0x1E, 0x1C, 0x38, 0xD3, 1, 0xB0, 0x26, 0x40, 0xF4, 0xB, 0xC3, 0x42, 0x1F, 0x85, 0x32
    //2C0
    ,
    0x26, 0x60, 0x40, 0xC9, 0xCB, 1, 0xEC, 0x11, 0x28, 0x40, 0xFA, 4, 0x34, 0xE0, 0x70, 0x4C, 0x8C, 0x1D, 7, 0x69, 3, 0x16, 0xC8, 4, 0x23, 0xE8, 0xC6, 0x9A, 0xB, 0x1A, 3, 0xE0
    //2E0
    ,
    0x76, 6, 5, 0xCF, 0x1E, 0xBC, 0x58, 0x31, 0x71, 0x66, 0, 0xF8, 0x3F, 4, 0xFC, 0xC, 0x74, 0x27, 0x8A, 0x80, 0x71, 0xC2, 0x3A, 0x26, 6, 0xC0, 0x1F, 5, 0xF, 0x98, 0x40, 0xAE
    //300
    ,
    1, 0x7F, 0xC0, 7, 0xFF, 0, 0xE, 0xFE, 0, 3, 0xDF, 0x80, 3, 0xEF, 0x80, 0x1B, 0xF1, 0xC2, 0, 0xE7, 0xE0, 0x18, 0xFC, 0xE0, 0x21, 0xFC, 0x80, 0x3C, 0xFC, 0x40, 0xE, 0x7E
    //320
    ,
    0, 0x3F, 0x3E, 0, 0xF, 0xFE, 0, 0x1F, 0xFF, 0, 0x3E, 0xF0, 7, 0xFC, 0, 0x7E, 0x10, 0x3F, 0xFF, 0, 0x3F, 0x38, 0xE, 0x7C, 1, 0x87, 0xC, 0xFC, 0xC7, 0, 0x3E, 4
    //340
    ,
    0xF, 0x3E, 0x1F, 0xF, 0xF, 0x1F, 0xF, 2, 0x83, 0x87, 0xCF, 3, 0x87, 0xF, 0x3F, 0xC0, 7, 0x9E, 0x60, 0x3F, 0xC0, 3, 0xFE, 0, 0x3F, 0xE0, 0x77, 0xE1, 0xC0, 0xFE, 0xE0, 0xC3
    //360
    ,
    0xE0, 1, 0xDF, 0xF8, 3, 7, 0, 0x7E, 0x70, 0, 0x7C, 0x38, 0x18, 0xFE, 0xC, 0x1E, 0x78, 0x1C, 0x7C, 0x3E, 0xE, 0x1F, 0x1E, 0x1E, 0x3E, 0, 0x7F, 0x83, 7, 0xDB, 0x87, 0x83
    //380
    ,
    7, 0xC7, 7, 0x10, 0x71, 0xFF, 0, 0x3F, 0xE2, 1, 0xE0, 0xC1, 0xC3, 0xE1, 0, 0x7F, 0xC0, 5, 0xF0, 0x20, 0xF8, 0xF0, 0x70, 0xFE, 0x78, 0x79, 0xF8, 2, 0x3F, 0xC, 0x8F, 3
    //3a0
    ,
    0xF, 0x9F, 0xE0, 0xC1, 0xC7, 0x87, 3, 0xC3, 0xC3, 0xB0, 0xE1, 0xE1, 0xC1, 0xE3, 0xE0, 0x71, 0xF0, 0, 0xFC, 0x70, 0x7C, 0xC, 0x3E, 0x38, 0xE, 0x1C, 0x70, 0xC3, 0xC7, 3, 0x81, 0xC1
    //3c0
    ,
    0xC7, 0xE7, 0, 0xF, 0xC7, 0x87, 0x19, 9, 0xEF, 0xC4, 0x33, 0xE0, 0xC1, 0xFC, 0xF8, 0x70, 0xF0, 0x78, 0xF8, 0xF0, 0x61, 0xC7, 0, 0x1F, 0xF8, 1, 0x7C, 0xF8, 0xF0, 0x78, 0x70, 0x3C
    //3e0
    ,
    0x7C, 0xCE, 0xE, 0x21, 0x83, 0xCF, 8, 7, 0x8F, 8, 0xC1, 0x87, 0x8F, 0x80, 0xC7, 0xE3, 0, 7, 0xF8, 0xE0, 0xEF, 0, 0x39, 0xF7, 0x80, 0xE, 0xF8, 0xE1, 0xE3, 0xF8, 0x21, 0x9F
    //400
    ,
    0xC0, 0xFF, 3, 0xF8, 7, 0xC0, 0x1F, 0xF8, 0xC4, 4, 0xFC, 0xC4, 0xC1, 0xBC, 0x87, 0xF0, 0xF, 0xC0, 0x7F, 5, 0xE0, 0x25, 0xEC, 0xC0, 0x3E, 0x84, 0x47, 0xF0, 0x8E, 3, 0xF8, 3
    //420
    ,
    0xFB, 0xC0, 0x19, 0xF8, 7, 0x9C, 0xC, 0x17, 0xF8, 7, 0xE0, 0x1F, 0xA1, 0xFC, 0xF, 0xFC, 1, 0xF0, 0x3F, 0, 0xFE, 3, 0xF0, 0x1F, 0, 0xFD, 0, 0xFF, 0x88, 0xD, 0xF9, 1
    //440
    ,
    0xFF, 0, 0x70, 7, 0xC0, 0x3E, 0x42, 0xF3, 0xD, 0xC4, 0x7F, 0x80, 0xFC, 7, 0xF0, 0x5E, 0xC0, 0x3F, 0, 0x78, 0x3F, 0x81, 0xFF, 1, 0xF8, 1, 0xC3, 0xE8, 0xC, 0xE4, 0x64, 0x8F
    ////460
    ,
    0xE4, 0xF, 0xF0, 7, 0xF0, 0xC2, 0x1F, 0, 0x7F, 0xC0, 0x6F, 0x80, 0x7E, 3, 0xF8, 7, 0xF0, 0x3F, 0xC0, 0x78, 0xF, 0x82, 7, 0xFE, 0x22, 0x77, 0x70, 2, 0x76, 3, 0xFE, 0
    //480
    ,
    0xFE, 0x67, 0, 0x7C, 0xC7, 0xF1, 0x8E, 0xC6, 0x3B, 0xE0, 0x3F, 0x84, 0xF3, 0x19, 0xD8, 3, 0x99, 0xFC, 9, 0xB8, 0xF, 0xF8, 0, 0x9D, 0x24, 0x61, 0xF9, 0xD, 0, 0xFD, 3, 0xF0
    //4a0
    ,
    0x1F, 0x90, 0x3F, 1, 0xF8, 0x1F, 0xD0, 0xF, 0xF8, 0x37, 1, 0xF8, 7, 0xF0, 0xF, 0xC0, 0x3F, 0, 0xFE, 3, 0xF8, 0xF, 0xC0, 0x3F, 0, 0xFA, 3, 0xF0, 0xF, 0x80, 0xFF, 1
    //4c0
    ,
    0xB8, 7, 0xF0, 1, 0xFC, 1, 0xBC, 0x80, 0x13, 0x1E, 0, 0x7F, 0xE1, 0x40, 0x7F, 0xA0, 0x7F, 0xB0, 0, 0x3F, 0xC0, 0x1F, 0xC0, 0x38, 0xF, 0xF0, 0x1F, 0x80, 0xFF, 1, 0xFC, 3
    //4e0
    ,
    0xF1, 0x7E, 1, 0xFE, 1, 0xF0, 0xFF, 0, 0x7F, 0xC0, 0x1D, 7, 0xF0, 0xF, 0xC0, 0x7E, 6, 0xE0, 7, 0xE0, 0xF, 0xF8, 6, 0xC1, 0xFE, 1, 0xFC, 3, 0xE0, 0xF, 0, 0xFC
};
#endif
// END render_tabs.h
// BEGIN render.c
extern int32_t debug;
uint8_t wait1 = 7;
uint8_t wait2 = 6;
uint8_t A, X, Y;
extern uint8_t mem44;
extern uint8_t mem47;
extern uint8_t mem49;
extern uint8_t mem39;
extern uint8_t mem50;
extern uint8_t mem51;
extern uint8_t mem53;
extern uint8_t mem56;
extern uint8_t speed;
extern uint8_t pitch;
extern int32_t singmode;
extern uint8_t phonemeIndexOutput[60]; //tab47296
extern uint8_t stressOutput[60]; //tab47365
extern uint8_t phonemeLengthOutput[60]; //tab47416
uint8_t pitches[256]; // tab43008
uint8_t frequency1[256];
uint8_t frequency2[256];
uint8_t frequency3[256];
uint8_t amplitude1[256];
uint8_t amplitude2[256];
uint8_t amplitude3[256];
uint8_t sampledConsonantFlag[256]; // tab44800
void AddInflection(uint8_t mem48, uint8_t phase1);
uint8_t trans(uint8_t mem39212, uint8_t mem39213);
// contains the final soundbuffer
extern int32_t bufferPos;
extern int8_t* buffer;
//timetable for more accurate c64 simulation
int32_t timetable[5][5] = {
    { 162, 167, 167, 127, 128 },
    { 226, 60, 60, 0, 0 },
    { 225, 60, 59, 0, 0 },
    { 200, 0, 0, 54, 55 },
    { 199, 0, 0, 54, 54 }
};
// END render.c
// BEGIN test_phonemes.c
#define END 0,0
#define C_SIZE 1024
static char temp[C_SIZE];
static const char * test_case[] = {
#if 1
    // ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
    "HELLO",
    " /HEHLOW",
    // ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
    "WIZARD",
    " WIHZAA5RD",
    // ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
    "TWO THINGS",
    " TUW THIHNXZ",
    // ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
    "ANOTHER TRAVELER",
    " AENAH5DHER TRAEVIY4LER",
    // ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
    "HELLO, MY NAME IS SAM.",
    " /HEHLOW, MAY NEYM IHZ SAEM.",
    // ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
    "THE SKY ABOVE THE PORT WAS THE COLOR OF TELEVISION, TUNED TO A DEAD"
        "CHANNEL.",
    " DHAX SKAY AEBAH4V DHAX PAORT WAHZ DHAX KAALER AHV TEHLEHVIHZHUN, TUWND "
        "TUX AH DEHDCHAENEHL.",
#endif
    // ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
    "IT'S NOT LIKE I'M USING, CASE HEARD SOMEONE SAY, AS HE SHOULDERED HIS"
        "WAY THROUGH THE CROWD AROUND THE DOOR OF THE CHAT.",
    " IHTS NAAT LAY5K IHM YUWZIHNX, KEY4S /HIY5RD SAHMWAHN SEY5, AEZ /HIY "
        "SHUH5DIY4RD /HIHSWEY5 THRUW4 DHAX KROWD AXRAWND DHAX DOH5R AHV DHAX "
        "CHAET.",
    // ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
    "ITS LIKE MY BODYS DEVELOPED THIS MASSIVE DRUG DEFICIENCY.",
    " IHTS LAY5K MAY BAADIYS DIHVEHLOW5PT DHIHS MAESIHV DRAHG DIHFIHSHEHNSIY.",
    // ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
    "IT WAS A SPRAWL VOICE AND A SPRAWL JOKE.",
    " IHT WAHZ AH SPRAO5L VOY5S AEND AH SPRAO5L JOW5K.",
    // ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
    "THE CHATSUBO WAS A BAR FOR PROFESSIONAL EXPATRIATES YOU COULD DRINK THERE"
        "FOR A WEEK AND NEVER HEAR TWO WORDS IN JAPANESE.",
    " DHAX CHAETSUWBOW WAHZ AH BAA5R FAOR PROW5FEHSHUNUL EHKSPAETRIHEYTS YUW "
        "KUH5D DRIHNXK DHEHRFER AH WIY4K AEND NEH4VER /HIY5R TUW WERDZ IHN "
        "JAEPEYNIY4Z.",
    // ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
    "RATZ WAS TENDING BAR, HIS PROSTHETIC ARM JERKING MONOTONOUSLY AS HE FILLED"
        "A TRAY OF GLASSES WITH DRAFT KIRIN.",
    " RAETZ WAHZ TEHNDIHNX BAA5R, /HIHZ PROWSTHEHTIHK AA5RM JERKIHNX "
        "MAHNAATUNAXSLIY AEZ /HIY FIHLEHDAH TREY5 AHV GLAESIHZ WIHTH",
    // ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
    "HE SAW CASE AND SMILED, HIS TEETH A WEB WORK OF EAST EUROPEAN STEEL AND"
        "BROWN DECAY.",
    " /HIY SAO5 KEY4S AEND SMAY5LD, /HIHZ TIY4TH AH WEHB WERK AHV IY5ST "
        "YUW5RAAPIY5N STIY4L AENDBROWN DIHKEY5.",
    // ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
    "CASE FOUND A PLACE AT THE BAR, BETWEEN THE UNLIKELY TAN ON ONE OF LONNY"
        "ZONE'S WHORES AND THE CRISP NAVAL UNIFORM OF A TALL AFRICAN WHOSE"
        "CHEEKBONES WERE RIDGED WITH PRECISE ROWS OF TRIBAL SCARS.",
    " KEY4S FAWND AH PLEYS AET DHAX BAA5R, BEHTWIY4N DHIY AHNLIHKLIY TAEN AAN "
        "WAHN AHV LAHNIYZUNEHS /HUWRZ AEND DHAX KRIHSP NAEVUL YUWNIHFAORM AHV "
        "AH TAOL AEFRIHKAEN /HUWZEHKIY4KBOW5NZ WER RIHDJD WIHTH PREHSAYZ ROWZ "
        "AHV TRIHBUL SKAA5RZ.",
    // ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
    "WAGE WAS IN HERE EARLY, WITH TWO JOE BOYS, RATZ SAID, SHOVING A DRAFT"
        "ACROSS THE BAR WITH HIS GOOD HAND.",
    " WEYJ WAHZ IHN /HIYR ER5LIY, WIHTH TUW JOW BOYZ, RAETZ SEHD, SHAH4VIHNX "
        "AH DRAEFTAEKRAO5S DHAX BAA5R WIHTH /HIHZ GUH5D /HAEND.",
    // ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
    "MAYBE SOME BUSINESS WITH YOU, CASE. CASE SHRUGGED.",
    " MEY5B SAHM BIH4ZIHNEHS WIHTH YUW, KEY4S. KEY4S SHRAH5GD.",
    // ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
    "THE GIRL TO HIS RIGHT GIGGLED AND NUDGED HIM.",
    " DHAX GERL TUX /HIHZ RAY4T GIHGULD AEND NAH5DJD /HIHM.",
    // ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
    END
};
// END test_phonemes.c
// BEGIN debug.h
int32_t debug = 0;
// END debug.h
// BEGIN test_hello.c
// was int32_t main
int32_t test_hello_main(int32_t argc, int8_t** argv)
{
    // note: must be caps
    const char * input = "HELLO WORLD [";
    SetInput(input);
    if (!SAMMain()) {
        return 1;
    }
    return WriteWav(GetBuffer(), GetBufferLength() / 50);
}
int32_t WriteWav(int8_t* buffer, int32_t bufferlength)
{
    return 0;
}
// END test_hello.c
// BEGIN test_phonemes.c
// was int32_t main
int32_t test_phonemes_main(int32_t argc, int8_t** argv)
{
    test_state_t state;
    memset(&state, 0, sizeof(test_state_t));
    // verify the reciter tables are well formed
    ReciterVerify();
    // try expect loop
    for (size_t i = 0; test_case[i]; i += 2) {
        if (!try_test(test_case[i+0], test_case[i+1])) {
            printf("x");
            state.fails_++;
        }
        else {
            printf(".");
            state.passes_++;;
        }
    }
    // input test files
    file_test(SAM_TEST_DIR "\\assets\\words.txt", &state);
    file_test(SAM_TEST_DIR "\\assets\\sentences.txt", &state);
    // print raw summary
    printf("\ntotal : %d", state.fails_ + state.passes_);
    printf("\nfailed: %d", state.fails_);
    printf("\npassed: %d", state.passes_);
    if (state.fails_) {
        getchar();
    }
    return state.fails_;
} // int32_t main
static int compare(const char * a, const char * b) {
    while (*a && !(*b&0x80)) {
        if (*a!=*b) {
            return 0;
        }
        ++a, ++b;
    }
    return 1;
} // static int compare
static void trim() {
    for (size_t i = 0; i<C_SIZE; ++i) {
        if (temp[i] & 0x80) {
            temp[i] = '\0';
            break;
        }
    }
} // static void trim
static int try_test(const char * in, const char * match)
{
    memset(temp, 0x80, C_SIZE);
    strcpy_s(temp, C_SIZE, in);
    strcat_s(temp, C_SIZE, "[");
    if (!TextToPhonemes(temp, C_SIZE)) {
        return 0;
    }
    temp[C_SIZE-1] = '\0';
    trim();
    if (!compare(match, temp)) {
        printf("\nsent\n'%s';\nexpected\n'%s';\ngot\n'%s'\n", in, match, temp);
        return 0;
    }
    return 1;
} // static int try_test
size_t read_line(FILE * fd, char * dst, size_t max)
{
    assert(fd && dst);
    char * ptr = dst;
    const char * end = dst+max;
    size_t size = 0;
    for (; ptr!=end; ++ptr) {
        if (feof(fd)) {
            return 0;
        }
        if (fread(ptr, 1, 1, fd)!=1) {
            return 0;
        }
        if (*ptr=='\n') {
            *ptr = '\0';
            return size;
        }
        if (*ptr=='\r') {
            *ptr = '\0';
        }
        else {
            *ptr = toupper(*ptr);
            ++size;
        }
    }
    return 0;
} // size_t read_line
int file_test(const char * path, test_state_t * state)
{
    assert(state && path);
    FILE * fd = NULL;
    fopen_s(&fd, path, "rb");
    if (fd==NULL) {
        return 0;
    }
    char temp1[C_SIZE] = {'\0'};
    char temp2[C_SIZE] = {'\0'};
    size_t len = 0;
    while (len = read_line(fd, temp1, C_SIZE)) {
        temp1[len+0] = '[';
        temp1[len+1] = '\0';
        strcpy_s(temp2, C_SIZE, temp1);
        if (TextToPhonemes(temp1, C_SIZE)) {
            fputc('.', stdout);
            state->passes_++;
        }
        else {
            fputc('x', stdout);
            printf("\n%s\n", temp2);
            state->fails_++;
        }
    }
    return 1;
} // int file_test
// END test_phonemes.c
// BEGIN sam.c
void SetInput(const int8_t *_input)
{
    int32_t i, l;
    l = strlen(_input);
    if (l > 254)
        l = 254;
    for (i = 0; i < l; i++)
        input[i] = _input[i];
    input[l] = 0;
}
void SetSpeed(uint8_t _speed) { speed = _speed; };
void SetPitch(uint8_t _pitch) { pitch = _pitch; };
void SetMouth(uint8_t _mouth) { mouth = _mouth; };
void SetThroat(uint8_t _throat) { throat = _throat; };
void EnableSingmode() { singmode = 1; };
int8_t *GetBuffer() { return buffer; };
int32_t GetBufferLength() { return bufferPos; };
// 168=pitches
// 169=frequency1
// 170=frequency2
// 171=frequency3
// 172=amplitude1
// 173=amplitude2
// 174=amplitude3
void Init()
{
    int32_t i;
    SetMouthThroat(mouth, throat);
    bufferPos = 0;
    // todo: check for free the memory, 10 seconds of output should be more than enough
    // fixme: we only allocation 10 seconds of audio!!
    // todo: unhardcode sample rate
    buffer = malloc(22050 * 10);
    /*
    freq2data = &mem[45136];
    freq1data = &mem[45056];
    freq3data = &mem[45216];
    */
    // pitches = &mem[43008];
    /*
    frequency1 = &mem[43264];
    frequency2 = &mem[43520];
    frequency3 = &mem[43776];
    */
    /*
    amplitude1 = &mem[44032];
    amplitude2 = &mem[44288];
    amplitude3 = &mem[44544];
    */
    // phoneme = &mem[39904];
    /*
    ampl1data = &mem[45296];
    ampl2data = &mem[45376];
    ampl3data = &mem[45456];
    */
    for (i = 0; i < 256; i++)
    {
        stress[i] = 0;
        phonemeLength[i] = 0;
    }
    for (i = 0; i < 60; i++)
    {
        phonemeIndexOutput[i] = 0;
        stressOutput[i] = 0;
        phonemeLengthOutput[i] = 0;
    }
    // to prevent buffer overflow
    //  ML : changed from 32 to 255 to stop freezing with long inputs
    phonemeIndex[255] = 255;
} // void Init
// int32_t Code39771()
int32_t SAMMain()
{
    Init();
    phonemeIndex[255] = 32; // to prevent buffer overflow
    if (!Parser1())
        return 0;
    if (debug)
        PrintPhonemes(phonemeIndex, phonemeLength, stress);
    Parser2();
    CopyStress();
    SetPhonemeLength();
    AdjustLengths();
    Code41240();
    do
    {
        A = phonemeIndex[X];
        if (A > 80)
        {
            phonemeIndex[X] = 255;
            break; // error: delete all behind it
        }
        X++;
    } while (X != 0);
    // pos39848:
    InsertBreath();
    // mem[40158] = 255;
    if (debug)
    {
        PrintPhonemes(phonemeIndex, phonemeLength, stress);
    }
    PrepareOutput();
    return 1;
} // int32_t SAMMain
// void Code48547()
void PrepareOutput()
{
    A = 0;
    X = 0;
    Y = 0;
    // pos48551:
    while (1)
    {
        A = phonemeIndex[X];
        if (A == 255)
        {
            A = 255;
            phonemeIndexOutput[Y] = 255;
            Render();
            return;
        }
        if (A == 254)
        {
            X++;
            int32_t temp = X;
            // mem[48546] = X;
            phonemeIndexOutput[Y] = 255;
            Render();
            // X = mem[48546];
            X = temp;
            Y = 0;
            continue;
        }
        if (A == 0)
        {
            X++;
            continue;
        }
        phonemeIndexOutput[Y] = A;
        phonemeLengthOutput[Y] = phonemeLength[X];
        stressOutput[Y] = stress[X];
        X++;
        Y++;
    }
} // void PrepareOutput
// void Code48431()
void InsertBreath()
{
    uint8_t mem54;
    uint8_t mem55;
    uint8_t index; // variable Y
    mem54 = 255;
    X++;
    mem55 = 0;
    uint8_t mem66 = 0;
    while (1)
    {
        // pos48440:
        X = mem66;
        index = phonemeIndex[X];
        if (index == 255)
            return;
        mem55 += phonemeLength[X];
        if (mem55 < 232)
        {
            if (index != 254) // ML : Prevents an index out of bounds problem
            {
                A = flags2[index] & 1;
                if (A != 0)
                {
                    X++;
                    mem55 = 0;
                    Insert(X, 254, mem59, 0);
                    mem66++;
                    mem66++;
                    continue;
                }
            }
            if (index == 0)
                mem54 = X;
            mem66++;
            continue;
        }
        X = mem54;
        phonemeIndex[X] = 31; // 'Q*' glottal stop
        phonemeLength[X] = 4;
        stress[X] = 0;
        X++;
        mem55 = 0;
        Insert(X, 254, mem59, 0);
        X++;
        mem66 = X;
    }
} // void InsertBreath
// Iterates through the phoneme buffer, copying the stress value from
// the following phoneme under the following circumstance:
//     1. The current phoneme is voiced, excluding plosives and fricatives
//     2. The following phoneme is voiced, excluding plosives and fricatives, and
//     3. The following phoneme is stressed
//
//  In those cases, the stress value+1 from the following phoneme is copied.
//
// For example, the word LOITER is represented as LOY5TER, with as stress
// of 5 on the diphtong OY. This routine will copy the stress value of 6 (5+1)
// to the L that precedes it.
// void Code41883()
void CopyStress()
{
    // loop thought all the phonemes to be output
    uint8_t pos = 0; // mem66
    while (1)
    {
        // get the phomene
        Y = phonemeIndex[pos];
        // exit at end of buffer
        if (Y == 255)
            return;
        // if CONSONANT_FLAG set, skip - only vowels get stress
        if ((flags[Y] & 64) == 0)
        {
            pos++;
            continue;
        }
        // get the next phoneme
        Y = phonemeIndex[pos + 1];
        if (Y == 255) // prevent buffer overflow
        {
            pos++;
            continue;
        }
        else
            // if the following phoneme is a vowel, skip
            if ((flags[Y] & 128) == 0)
            {
                pos++;
                continue;
            }
        // get the stress value at the next position
        Y = stress[pos + 1];
        // if next phoneme is not stressed, skip
        if (Y == 0)
        {
            pos++;
            continue;
        }
        // if next phoneme is not a VOWEL OR ER, skip
        if ((Y & 128) != 0)
        {
            pos++;
            continue;
        }
        // copy stress from prior phoneme to this one
        stress[pos] = Y + 1;
        // advance pointer
        pos++;
    }
} // void CopyStress
// void Code41014()
void Insert(uint8_t position /*var57*/, uint8_t mem60, uint8_t mem59, uint8_t mem58)
{
    int32_t i;
    for (i = 253; i >= position; i--) // ML : always keep last safe-guarding 255
    {
        phonemeIndex[i + 1] = phonemeIndex[i];
        phonemeLength[i + 1] = phonemeLength[i];
        stress[i + 1] = stress[i];
    }
    phonemeIndex[position] = mem60;
    phonemeLength[position] = mem59;
    stress[position] = mem58;
    return;
} // void Insert(
// The input[] buffer contains a string of phonemes and stress markers along
// the lines of:
//
//     DHAX KAET IHZ AH5GLIY. <0x9B>
//
// The byte 0x9B marks the end of the buffer. Some phonemes are 2 bytes
// long, such as "DH" and "AX". Others are 1 byte long, such as "T" and "Z".
// There are also stress markers, such as "5" and ".".
//
// The first int8_tacter of the phonemes are stored in the table signInputTable1[].
// The second int8_tacter of the phonemes are stored in the table signInputTable2[].
// The stress int8_tacters are arranged in low to high stress order in stressInputTable[].
//
// The following process is used to parse the input[] buffer:
//
// Repeat until the <0x9B> int8_tacter is reached:
//
//        First, a search is made for a 2 int8_tacter match for phonemes that do not
//        end with the '*' (wildcard) int8_tacter. On a match, the index of the phoneme
//        is added to phonemeIndex[] and the buffer position is advanced 2 bytes.
//
//        If this fails, a search is made for a 1 int8_tacter match against all
//        phoneme names ending with a '*' (wildcard). If this succeeds, the
//        phoneme is added to phonemeIndex[] and the buffer position is advanced
//        1 byte.
//
//        If this fails, search for a 1 int8_tacter match in the stressInputTable[].
//        If this succeeds, the stress value is placed in the last stress[] table
//        at the same index of the last added phoneme, and the buffer position is
//        advanced by 1 byte.
//
//        If this fails, return a 0.
//
// On success:
//
//    1. phonemeIndex[] will contain the index of all the phonemes.
//    2. The last index in phonemeIndex[] will be 255.
//    3. stress[] will contain the stress value for each phoneme
// input[] holds the string of phonemes, each two bytes wide
// signInputTable1[] holds the first int8_tacter of each phoneme
// signInputTable2[] holds te second int8_tacter of each phoneme
// phonemeIndex[] holds the indexes of the phonemes after parsing input[]
//
// The parser scans through the input[], finding the names of the phonemes
// by searching signInputTable1[] and signInputTable2[]. On a match, it
// copies the index of the phoneme into the phonemeIndexTable[].
//
// The int8_tacter <0x9B> marks the end of text in input[]. When it is reached,
// the index 255 is placed at the end of the phonemeIndexTable[], and the
// function returns with a 1 indicating success.
int32_t Parser1()
{
    int32_t i;
    uint8_t sign1;
    uint8_t sign2;
    uint8_t position = 0;
    X = 0;
    A = 0;
    Y = 0;
    // CLEAR THE STRESS TABLE
    for (i = 0; i < 256; i++)
        stress[i] = 0;
    // THIS CODE MATCHES THE PHONEME LETTERS TO THE TABLE
    // pos41078:
    while (1)
    {
        // GET THE FIRST CHARACTER FROM THE PHONEME BUFFER
        sign1 = input[X];
        // TEST FOR 155 (�) END OF LINE MARKER
        if (sign1 == 155)
        {
            // MARK ENDPOINT AND RETURN
            phonemeIndex[position] = 255; // mark endpoint
            // REACHED END OF PHONEMES, SO EXIT
            return 1; // all ok
        }
        // GET THE NEXT CHARACTER FROM THE BUFFER
        X++;
        sign2 = input[X];
        // NOW sign1 = FIRST CHARACTER OF PHONEME, AND sign2 = SECOND CHARACTER OF PHONEME
        // TRY TO MATCH PHONEMES ON TWO TWO-CHARACTER NAME
        // IGNORE PHONEMES IN TABLE ENDING WITH WILDCARDS
        // SET INDEX TO 0
        Y = 0;
    pos41095:
        // GET FIRST CHARACTER AT POSITION Y IN signInputTable
        // --> should change name to PhonemeNameTable1
        A = signInputTable1[Y];
        // FIRST CHARACTER MATCHES?
        if (A == sign1)
        {
            // GET THE CHARACTER FROM THE PhonemeSecondLetterTable
            A = signInputTable2[Y];
            // NOT A SPECIAL AND MATCHES SECOND CHARACTER?
            if ((A != '*') && (A == sign2))
            {
                // STORE THE INDEX OF THE PHONEME INTO THE phomeneIndexTable
                phonemeIndex[position] = Y;
                // ADVANCE THE POINTER TO THE phonemeIndexTable
                position++;
                // ADVANCE THE POINTER TO THE phonemeInputBuffer
                X++;
                // CONTINUE PARSING
                continue;
            }
        }
        // NO MATCH, TRY TO MATCH ON FIRST CHARACTER TO WILDCARD NAMES (ENDING WITH '*')
        // ADVANCE TO THE NEXT POSITION
        Y++;
        // IF NOT END OF TABLE, CONTINUE
        if (Y != 81)
            goto pos41095;
        // REACHED END OF TABLE WITHOUT AN EXACT (2 CHARACTER) MATCH.
        // THIS TIME, SEARCH FOR A 1 CHARACTER MATCH AGAINST THE WILDCARDS
        // RESET THE INDEX TO POINT TO THE START OF THE PHONEME NAME TABLE
        Y = 0;
    pos41134:
        // DOES THE PHONEME IN THE TABLE END WITH '*'?
        if (signInputTable2[Y] == '*')
        {
            // DOES THE FIRST CHARACTER MATCH THE FIRST LETTER OF THE PHONEME
            if (signInputTable1[Y] == sign1)
            {
                // SAVE THE POSITION AND MOVE AHEAD
                phonemeIndex[position] = Y;
                // ADVANCE THE POINTER
                position++;
                // CONTINUE THROUGH THE LOOP
                continue;
            }
        }
        Y++;
        if (Y != 81)
            goto pos41134; // 81 is size of PHONEME NAME table
        // FAILED TO MATCH WITH A WILDCARD. ASSUME THIS IS A STRESS
        // CHARACTER. SEARCH THROUGH THE STRESS TABLE
        // SET INDEX TO POSITION 8 (END OF STRESS TABLE)
        Y = 8;
        // WALK BACK THROUGH TABLE LOOKING FOR A MATCH
        while ((sign1 != stressInputTable[Y]) && (Y > 0))
        {
            // DECREMENT INDEX
            Y--;
        }
        // REACHED THE END OF THE SEARCH WITHOUT BREAKING OUT OF LOOP?
        if (Y == 0)
        {
            // mem[39444] = X;
            // 41181: JSR 42043 //Error
            //  FAILED TO MATCH ANYTHING, RETURN 0 ON FAILURE
            return 0;
        }
        // SET THE STRESS FOR THE PRIOR PHONEME
        stress[position - 1] = Y;
    } // while
} // int32_t Parser1()
// change phonemelength depedendent on stress
// void Code41203()
void SetPhonemeLength()
{
    uint8_t A;
    int32_t position = 0;
    while (phonemeIndex[position] != 255)
    {
        A = stress[position];
        // 41218: BMI 41229
        if ((A == 0) || ((A & 128) != 0))
        {
            phonemeLength[position] = phonemeLengthTable[phonemeIndex[position]];
        }
        else
        {
            phonemeLength[position] = phonemeStressedLengthTable[phonemeIndex[position]];
        }
        position++;
    }
} // void SetPhonemeLength()
void Code41240()
{
    uint8_t pos = 0;
    while (phonemeIndex[pos] != 255)
    {
        uint8_t index; // register AC
        X = pos;
        index = phonemeIndex[pos];
        if ((flags[index] & 2) == 0)
        {
            pos++;
            continue;
        }
        else if ((flags[index] & 1) == 0)
        {
            Insert(pos + 1, index + 1, phonemeLengthTable[index + 1], stress[pos]);
            Insert(pos + 2, index + 2, phonemeLengthTable[index + 2], stress[pos]);
            pos += 3;
            continue;
        }
        do
        {
            X++;
            A = phonemeIndex[X];
        } while (A == 0);
        if (A != 255)
        {
            if ((flags[A] & 8) != 0)
            {
                pos++;
                continue;
            }
            if ((A == 36) || (A == 37))
            {
                pos++;
                continue;
            } // '/H' '/X'
        }
        Insert(pos + 1, index + 1, phonemeLengthTable[index + 1], stress[pos]);
        Insert(pos + 2, index + 2, phonemeLengthTable[index + 2], stress[pos]);
        pos += 3;
    };
} // void Code41240()
// Rewrites the phonemes using the following rules:
//
//       <DIPHTONG ENDING WITH WX> -> <DIPHTONG ENDING WITH WX> WX
//       <DIPHTONG NOT ENDING WITH WX> -> <DIPHTONG NOT ENDING WITH WX> YX
//       UL -> AX L
//       UM -> AX M
//       <STRESSED VOWEL> <SILENCE> <STRESSED VOWEL> -> <STRESSED VOWEL> <SILENCE> Q <VOWEL>
//       T R -> CH R
//       D R -> J R
//       <VOWEL> R -> <VOWEL> RX
//       <VOWEL> L -> <VOWEL> LX
//       G S -> G Z
//       K <VOWEL OR DIPHTONG NOT ENDING WITH IY> -> KX <VOWEL OR DIPHTONG NOT ENDING WITH IY>
//       G <VOWEL OR DIPHTONG NOT ENDING WITH IY> -> GX <VOWEL OR DIPHTONG NOT ENDING WITH IY>
//       S P -> S B
//       S T -> S D
//       S K -> S G
//       S KX -> S GX
//       <ALVEOLAR> UW -> <ALVEOLAR> UX
//       CH -> CH CH' (CH requires two phonemes to represent it)
//       J -> J J' (J requires two phonemes to represent it)
//       <UNSTRESSED VOWEL> T <PAUSE> -> <UNSTRESSED VOWEL> DX <PAUSE>
//       <UNSTRESSED VOWEL> D <PAUSE>  -> <UNSTRESSED VOWEL> DX <PAUSE>
// void Code41397()
void Parser2()
{
    if (debug)
        printf("Parser2\n");
    uint8_t pos = 0; // mem66;
    uint8_t mem58 = 0;
    // Loop through phonemes
    while (1)
    {
        // SET X TO THE CURRENT POSITION
        X = pos;
        // GET THE PHONEME AT THE CURRENT POSITION
        A = phonemeIndex[pos];
        // DEBUG: Print phoneme and index
        if (debug && A != 255)
            printf("%d: %c%c\n", X, signInputTable1[A], signInputTable2[A]);
        // Is phoneme pause?
        if (A == 0)
        {
            // Move ahead to the
            pos++;
            continue;
        }
        // If end of phonemes flag reached, exit routine
        if (A == 255)
            return;
        // Copy the current phoneme index to Y
        Y = A;
        // RULE:
        //       <DIPHTONG ENDING WITH WX> -> <DIPHTONG ENDING WITH WX> WX
        //       <DIPHTONG NOT ENDING WITH WX> -> <DIPHTONG NOT ENDING WITH WX> YX
        // Example: OIL, COW
        // Check for DIPHTONG
        if ((flags[A] & 16) == 0)
            goto pos41457;
        // Not a diphthong. Get the stress
        mem58 = stress[pos];
        // End in IY sound?
        A = flags[Y] & 32;
        // If ends with IY, use YX, else use WX
        if (A == 0)
            A = 20;
        else
            A = 21; // 'WX' = 20 'YX' = 21
        // pos41443:
        //  Insert at WX or YX following, copying the stress
        if (debug)
            if (A == 20)
                printf("RULE: insert WX following diphtong NOT ending in IY sound\n");
        if (debug)
            if (A == 21)
                printf("RULE: insert YX following diphtong ending in IY sound\n");
        Insert(pos + 1, A, mem59, mem58);
        X = pos;
        // Jump to ???
        goto pos41749;
    pos41457:
        // RULE:
        //       UL -> AX L
        // Example: MEDDLE
        // Get phoneme
        A = phonemeIndex[X];
        // Skip this rule if phoneme is not UL
        if (A != 78)
            goto pos41487; // 'UL'
        A = 24;            // 'L'                 //change 'UL' to 'AX L'
        if (debug)
            printf("RULE: UL -> AX L\n");
    pos41466:
        // Get current phoneme stress
        mem58 = stress[X];
        // Change UL to AX
        phonemeIndex[X] = 13; // 'AX'
        // Perform insert. Note code below may jump up here with different values
        Insert(X + 1, A, mem59, mem58);
        pos++;
        // Move to next phoneme
        continue;
    pos41487:
        // RULE:
        //       UM -> AX M
        // Example: ASTRONOMY
        // Skip rule if phoneme != UM
        if (A != 79)
            goto pos41495; // 'UM'
        // Jump up to branch - replaces current phoneme with AX and continues
        A = 27; // 'M'  //change 'UM' to  'AX M'
        if (debug)
            printf("RULE: UM -> AX M\n");
        goto pos41466;
    pos41495:
        // RULE:
        //       UN -> AX N
        // Example: FUNCTION
        // Skip rule if phoneme != UN
        if (A != 80)
            goto pos41503; // 'UN'
        // Jump up to branch - replaces current phoneme with AX and continues
        A = 28; // 'N' //change UN to 'AX N'
        if (debug)
            printf("RULE: UN -> AX N\n");
        goto pos41466;
    pos41503:
        // RULE:
        //       <STRESSED VOWEL> <SILENCE> <STRESSED VOWEL> -> <STRESSED VOWEL> <SILENCE> Q <VOWEL>
        // EXAMPLE: AWAY EIGHT
        Y = A;
        // VOWEL set?
        A = flags[A] & 128;
        // Skip if not a vowel
        if (A != 0)
        {
            // Get the stress
            A = stress[X];
            // If stressed...
            if (A != 0)
            {
                // Get the following phoneme
                X++;
                A = phonemeIndex[X];
                // If following phoneme is a pause
                if (A == 0)
                {
                    // Get the phoneme following pause
                    X++;
                    Y = phonemeIndex[X];
                    // Check for end of buffer flag
                    if (Y == 255) // buffer overflow
                        // ??? Not sure about these flags
                        A = 65 & 128;
                    else
                        // And VOWEL flag to current phoneme's flags
                        A = flags[Y] & 128;
                    // If following phonemes is not a pause
                    if (A != 0)
                    {
                        // If the following phoneme is not stressed
                        A = stress[X];
                        if (A != 0)
                        {
                            // Insert a glottal stop and move forward
                            if (debug)
                                printf("RULE: Insert glottal stop between two stressed vowels with space between them\n");
                            // 31 = 'Q'
                            Insert(X, 31, mem59, 0);
                            pos++;
                            continue;
                        }
                    }
                }
            }
        }
        // RULES FOR PHONEMES BEFORE R
        //        T R -> CH R
        // Example: TRACK
        // Get current position and phoneme
        X = pos;
        A = phonemeIndex[pos];
        if (A != 23)
            goto pos41611; // 'R'
        // Look at prior phoneme
        X--;
        A = phonemeIndex[pos - 1];
        // pos41567:
        if (A == 69) // 'T'
        {
            // Change T to CH
            if (debug)
                printf("RULE: T R -> CH R\n");
            phonemeIndex[pos - 1] = 42;
            goto pos41779;
        }
        // RULES FOR PHONEMES BEFORE R
        //        D R -> J R
        // Example: DRY
        // Prior phonemes D?
        if (A == 57) // 'D'
        {
            // Change D to J
            phonemeIndex[pos - 1] = 44;
            if (debug)
                printf("RULE: D R -> J R\n");
            goto pos41788;
        }
        // RULES FOR PHONEMES BEFORE R
        //        <VOWEL> R -> <VOWEL> RX
        // Example: ART
        // If vowel flag is set change R to RX
        A = flags[A] & 128;
        if (debug)
            printf("RULE: R -> RX\n");
        if (A != 0)
            phonemeIndex[pos] = 18; // 'RX'
        // continue to next phoneme
        pos++;
        continue;
    pos41611:
        // RULE:
        //       <VOWEL> L -> <VOWEL> LX
        // Example: ALL
        // Is phoneme L?
        if (A == 24) // 'L'
        {
            // If prior phoneme does not have VOWEL flag set, move to next phoneme
            if ((flags[phonemeIndex[pos - 1]] & 128) == 0)
            {
                pos++;
                continue;
            }
            // Prior phoneme has VOWEL flag set, so change L to LX and move to next phoneme
            if (debug)
                printf("RULE: <VOWEL> L -> <VOWEL> LX\n");
            phonemeIndex[X] = 19; // 'LX'
            pos++;
            continue;
        }
        // RULE:
        //       G S -> G Z
        //
        // Can't get to fire -
        //       1. The G -> GX rule intervenes
        //       2. Reciter already replaces GS -> GZ
        // Is current phoneme S?
        if (A == 32) // 'S'
        {
            // If prior phoneme is not G, move to next phoneme
            if (phonemeIndex[pos - 1] != 60)
            {
                pos++;
                continue;
            }
            // Replace S with Z and move on
            if (debug)
                printf("RULE: G S -> G Z\n");
            phonemeIndex[pos] = 38; // 'Z'
            pos++;
            continue;
        }
        // RULE:
        //             K <VOWEL OR DIPHTONG NOT ENDING WITH IY> -> KX <VOWEL OR DIPHTONG NOT ENDING WITH IY>
        // Example: COW
        // Is current phoneme K?
        if (A == 72) // 'K'
        {
            // Get next phoneme
            Y = phonemeIndex[pos + 1];
            // If at end, replace current phoneme with KX
            if (Y == 255)
                phonemeIndex[pos] = 75; // ML : prevents an index out of bounds problem
            else
            {
                // VOWELS AND DIPHTONGS ENDING WITH IY SOUND flag set?
                A = flags[Y] & 32;
                if (debug)
                    if (A == 0)
                        printf("RULE: K <VOWEL OR DIPHTONG NOT ENDING WITH IY> -> KX <VOWEL OR DIPHTONG NOT ENDING WITH IY>\n");
                // Replace with KX
                if (A == 0)
                    phonemeIndex[pos] = 75; // 'KX'
            }
        }
        else
            // RULE:
            //             G <VOWEL OR DIPHTONG NOT ENDING WITH IY> -> GX <VOWEL OR DIPHTONG NOT ENDING WITH IY>
            // Example: GO
            // Is int8_tacter a G?
            if (A == 60) // 'G'
            {
                // Get the following int8_tacter
                uint8_t index = phonemeIndex[pos + 1];
                // At end of buffer?
                if (index == 255) // prevent buffer overflow
                {
                    pos++;
                    continue;
                }
                else
                    // If diphtong ending with YX, move continue processing next phoneme
                    if ((flags[index] & 32) != 0)
                    {
                        pos++;
                        continue;
                    }
                // replace G with GX and continue processing next phoneme
                if (debug)
                    printf("RULE: G <VOWEL OR DIPHTONG NOT ENDING WITH IY> -> GX <VOWEL OR DIPHTONG NOT ENDING WITH IY>\n");
                phonemeIndex[pos] = 63; // 'GX'
                pos++;
                continue;
            }
        // RULE:
        //      S P -> S B
        //      S T -> S D
        //      S K -> S G
        //      S KX -> S GX
        // Examples: SPY, STY, SKY, SCOWL
        Y = phonemeIndex[pos];
        // pos41719:
        //  Replace with softer version?
        A = flags[Y] & 1;
        if (A == 0)
            goto pos41749;
        A = phonemeIndex[pos - 1];
        if (A != 32) // 'S'
        {
            A = Y;
            goto pos41812;
        }
        // Replace with softer version
        if (debug)
            printf("RULE: S* %c%c -> S* %c%c\n", signInputTable1[Y], signInputTable2[Y], signInputTable1[Y - 12], signInputTable2[Y - 12]);
        phonemeIndex[pos] = Y - 12;
        pos++;
        continue;
    pos41749:
        // RULE:
        //      <ALVEOLAR> UW -> <ALVEOLAR> UX
        //
        // Example: NEW, DEW, SUE, ZOO, THOO, TOO
        //       UW -> UX
        A = phonemeIndex[X];
        if (A == 53) // 'UW'
        {
            // ALVEOLAR flag set?
            Y = phonemeIndex[X - 1];
            A = flags2[Y] & 4;
            // If not set, continue processing next phoneme
            if (A == 0)
            {
                pos++;
                continue;
            }
            if (debug)
                printf("RULE: <ALVEOLAR> UW -> <ALVEOLAR> UX\n");
            phonemeIndex[X] = 16;
            pos++;
            continue;
        }
    pos41779:
        // RULE:
        //       CH -> CH CH' (CH requires two phonemes to represent it)
        // Example: CHEW
        if (A == 42) // 'CH'
        {
            //        pos41783:
            if (debug)
                printf("CH -> CH CH+1\n");
            Insert(X + 1, A + 1, mem59, stress[X]);
            pos++;
            continue;
        }
    pos41788:
        // RULE:
        //       J -> J J' (J requires two phonemes to represent it)
        // Example: JAY
        if (A == 44) // 'J'
        {
            if (debug)
                printf("J -> J J+1\n");
            Insert(X + 1, A + 1, mem59, stress[X]);
            pos++;
            continue;
        }
    // Jump here to continue
    pos41812:
        // RULE: Soften T following vowel
        // NOTE: This rule fails for cases such as "ODD"
        //       <UNSTRESSED VOWEL> T <PAUSE> -> <UNSTRESSED VOWEL> DX <PAUSE>
        //       <UNSTRESSED VOWEL> D <PAUSE>  -> <UNSTRESSED VOWEL> DX <PAUSE>
        // Example: PARTY, TARDY
        // Past this point, only process if phoneme is T or D
        if (A != 69) // 'T'
            if (A != 57)
            {
                pos++;
                continue;
            } // 'D'
        // pos41825:
        // If prior phoneme is not a vowel, continue processing phonemes
        if ((flags[phonemeIndex[X - 1]] & 128) == 0)
        {
            pos++;
            continue;
        }
        // Get next phoneme
        X++;
        A = phonemeIndex[X];
        // pos41841
        //  Is the next phoneme a pause?
        if (A != 0)
        {
            // If next phoneme is not a pause, continue processing phonemes
            if ((flags[A] & 128) == 0)
            {
                pos++;
                continue;
            }
            // If next phoneme is stressed, continue processing phonemes
            // FIXME: How does a pause get stressed?
            if (stress[X] != 0)
            {
                pos++;
                continue;
            }
            // pos41856:
            //  Set phonemes to DX
            if (debug)
                printf("RULE: Soften T or D following vowel or ER and preceding a pause -> DX\n");
            phonemeIndex[pos] = 30; // 'DX'
        }
        else
        {
            A = phonemeIndex[X + 1];
            if (A == 255) // prevent buffer overflow
                A = 65 & 128;
            else
                // Is next phoneme a vowel or ER?
                A = flags[A] & 128;
            if (debug)
                if (A != 0)
                    printf("RULE: Soften T or D following vowel or ER and preceding a pause -> DX\n");
            if (A != 0)
                phonemeIndex[pos] = 30; // 'DX'
        }
        pos++;
    } // while
} // void Parser2()
// Applies various rules that adjust the lengths of phonemes
//
//         Lengthen <FRICATIVE> or <VOICED> between <VOWEL> and <PUNCTUATION> by 1.5
//         <VOWEL> <RX | LX> <CONSONANT> - decrease <VOWEL> length by 1
//         <VOWEL> <UNVOICED PLOSIVE> - decrease vowel by 1/8th
//         <VOWEL> <UNVOICED CONSONANT> - increase vowel by 1/2 + 1
//         <NASAL> <STOP CONSONANT> - set nasal = 5, consonant = 6
//         <VOICED STOP CONSONANT> {optional silence} <STOP CONSONANT> - shorten both to 1/2 + 1
//         <LIQUID CONSONANT> <DIPHTONG> - decrease by 2
// void Code48619()
void AdjustLengths()
{
    // LENGTHEN VOWELS PRECEDING PUNCTUATION
    //
    // Search for punctuation. If found, back up to the first vowel, then
    // process all phonemes between there and up to (but not including) the punctuation.
    // If any phoneme is found that is a either a fricative or voiced, the duration is
    // increased by (length * 1.5) + 1
    // loop index
    X = 0;
    uint8_t index;
    // iterate through the phoneme list
    uint8_t loopIndex = 0;
    while (1)
    {
        // get a phoneme
        index = phonemeIndex[X];
        // exit loop if end on buffer token
        if (index == 255)
            break;
        // not punctuation?
        if ((flags2[index] & 1) == 0)
        {
            // skip
            X++;
            continue;
        }
        // hold index
        loopIndex = X;
    // Loop backwards from this point
    pos48644:
        // back up one phoneme
        X--;
        // stop once the beginning is reached
        if (X == 0)
            break;
        // get the preceding phoneme
        index = phonemeIndex[X];
        if (index != 255) // inserted to prevent access overrun
            if ((flags[index] & 128) == 0)
                goto pos48644; // if not a vowel, continue looping
        // pos48657:
        do
        {
            // test for vowel
            index = phonemeIndex[X];
            if (index != 255) // inserted to prevent access overrun
                // test for fricative/unvoiced or not voiced
                if (((flags2[index] & 32) == 0) || ((flags[index] & 4) != 0)) // nochmal �berpr�fen
                {
                    // A = flags[Y] & 4;
                    // if(A == 0) goto pos48688;
                    // get the phoneme length
                    A = phonemeLength[X];
                    // change phoneme length to (length * 1.5) + 1
                    A = (A >> 1) + A + 1;
                    if (debug)
                        printf("RULE: Lengthen <FRICATIVE> or <VOICED> between <VOWEL> and <PUNCTUATION> by 1.5\n");
                    if (debug)
                        printf("PRE\n");
                    if (debug)
                        printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeIndex[X]], signInputTable2[phonemeIndex[X]], phonemeLength[X]);
                    phonemeLength[X] = A;
                    if (debug)
                        printf("POST\n");
                    if (debug)
                        printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeIndex[X]], signInputTable2[phonemeIndex[X]], phonemeLength[X]);
                }
            // keep moving forward
            X++;
        } while (X != loopIndex);
        //    if (X != loopIndex) goto pos48657;
        X++;
    } // while
    // Similar to the above routine, but shorten vowels under some circumstances
    // Loop throught all phonemes
    loopIndex = 0;
    // pos48697
    while (1)
    {
        // get a phoneme
        X = loopIndex;
        index = phonemeIndex[X];
        // exit routine at end token
        if (index == 255)
            return;
        // vowel?
        A = flags[index] & 128;
        if (A != 0)
        {
            // get next phoneme
            X++;
            index = phonemeIndex[X];
            // get flags
            if (index == 255)
                mem56 = 65; // use if end marker
            else
                mem56 = flags[index];
            // not a consonant
            if ((flags[index] & 64) == 0)
            {
                // RX or LX?
                if ((index == 18) || (index == 19)) // 'RX' & 'LX'
                {
                    // get the next phoneme
                    X++;
                    index = phonemeIndex[X];
                    // next phoneme a consonant?
                    if ((flags[index] & 64) != 0)
                    {
                        // RULE: <VOWEL> RX | LX <CONSONANT>
                        if (debug)
                            printf("RULE: <VOWEL> <RX | LX> <CONSONANT> - decrease length by 1\n");
                        if (debug)
                            printf("PRE\n");
                        if (debug)
                            printf("phoneme %d (%c%c) length %d\n", loopIndex, signInputTable1[phonemeIndex[loopIndex]], signInputTable2[phonemeIndex[loopIndex]], phonemeLength[loopIndex]);
                        // decrease length of vowel by 1 frame
                        phonemeLength[loopIndex]--;
                        if (debug)
                            printf("POST\n");
                        if (debug)
                            printf("phoneme %d (%c%c) length %d\n", loopIndex, signInputTable1[phonemeIndex[loopIndex]], signInputTable2[phonemeIndex[loopIndex]], phonemeLength[loopIndex]);
                    }
                    // move ahead
                    loopIndex++;
                    continue;
                }
                // move ahead
                loopIndex++;
                continue;
            }
            // Got here if not <VOWEL>
            // not voiced
            if ((mem56 & 4) == 0)
            {
                // Unvoiced
                // *, .*, ?*, ,*, -*, DX, S*, SH, F*, TH, /H, /X, CH, P*, T*, K*, KX
                // not an unvoiced plosive?
                if ((mem56 & 1) == 0)
                {
                    // move ahead
                    loopIndex++;
                    continue;
                }
                // P*, T*, K*, KX
                // RULE: <VOWEL> <UNVOICED PLOSIVE>
                // <VOWEL> <P*, T*, K*, KX>
                // move back
                X--;
                if (debug)
                    printf("RULE: <VOWEL> <UNVOICED PLOSIVE> - decrease vowel by 1/8th\n");
                if (debug)
                    printf("PRE\n");
                if (debug)
                    printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeIndex[X]], signInputTable2[phonemeIndex[X]], phonemeLength[X]);
                // decrease length by 1/8th
                mem56 = phonemeLength[X] >> 3;
                phonemeLength[X] -= mem56;
                if (debug)
                    printf("POST\n");
                if (debug)
                    printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeIndex[X]], signInputTable2[phonemeIndex[X]], phonemeLength[X]);
                // move ahead
                loopIndex++;
                continue;
            }
            // RULE: <VOWEL> <VOICED CONSONANT>
            // <VOWEL> <WH, R*, L*, W*, Y*, M*, N*, NX, DX, Q*, Z*, ZH, V*, DH, J*, B*, D*, G*, GX>
            if (debug)
                printf("RULE: <VOWEL> <VOICED CONSONANT> - increase vowel by 1/2 + 1\n");
            if (debug)
                printf("PRE\n");
            if (debug)
                printf("phoneme %d (%c%c) length %d\n", X - 1, signInputTable1[phonemeIndex[X - 1]], signInputTable2[phonemeIndex[X - 1]], phonemeLength[X - 1]);
            // decrease length
            A = phonemeLength[X - 1];
            phonemeLength[X - 1] = (A >> 2) + A + 1; // 5/4*A + 1
            if (debug)
                printf("POST\n");
            if (debug)
                printf("phoneme %d (%c%c) length %d\n", X - 1, signInputTable1[phonemeIndex[X - 1]], signInputTable2[phonemeIndex[X - 1]], phonemeLength[X - 1]);
            // move ahead
            loopIndex++;
            continue;
        }
        // WH, R*, L*, W*, Y*, M*, N*, NX, Q*, Z*, ZH, V*, DH, J*, B*, D*, G*, GX
        // pos48821:
        // RULE: <NASAL> <STOP CONSONANT>
        //       Set punctuation length to 6
        //       Set stop consonant length to 5
        // nasal?
        if ((flags2[index] & 8) != 0)
        {
            // M*, N*, NX,
            // get the next phoneme
            X++;
            index = phonemeIndex[X];
            // end of buffer?
            if (index == 255)
                A = 65 & 2; // prevent buffer overflow
            else
                A = flags[index] & 2; // check for stop consonant
            // is next phoneme a stop consonant?
            if (A != 0)
            // B*, D*, G*, GX, P*, T*, K*, KX
            {
                if (debug)
                    printf("RULE: <NASAL> <STOP CONSONANT> - set nasal = 5, consonant = 6\n");
                if (debug)
                    printf("POST\n");
                if (debug)
                    printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeIndex[X]], signInputTable2[phonemeIndex[X]], phonemeLength[X]);
                if (debug)
                    printf("phoneme %d (%c%c) length %d\n", X - 1, signInputTable1[phonemeIndex[X - 1]], signInputTable2[phonemeIndex[X - 1]], phonemeLength[X - 1]);
                // set stop consonant length to 6
                phonemeLength[X] = 6;
                // set nasal length to 5
                phonemeLength[X - 1] = 5;
                if (debug)
                    printf("POST\n");
                if (debug)
                    printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeIndex[X]], signInputTable2[phonemeIndex[X]], phonemeLength[X]);
                if (debug)
                    printf("phoneme %d (%c%c) length %d\n", X - 1, signInputTable1[phonemeIndex[X - 1]], signInputTable2[phonemeIndex[X - 1]], phonemeLength[X - 1]);
            }
            // move to next phoneme
            loopIndex++;
            continue;
        }
        // WH, R*, L*, W*, Y*, Q*, Z*, ZH, V*, DH, J*, B*, D*, G*, GX
        // RULE: <VOICED STOP CONSONANT> {optional silence} <STOP CONSONANT>
        //       Shorten both to (length/2 + 1)
        // (voiced) stop consonant?
        if ((flags[index] & 2) != 0)
        {
            // B*, D*, G*, GX
            // move past silence
            do
            {
                // move ahead
                X++;
                index = phonemeIndex[X];
            } while (index == 0);
            // check for end of buffer
            if (index == 255) // buffer overflow
            {
                // ignore, overflow code
                if ((65 & 2) == 0)
                {
                    loopIndex++;
                    continue;
                }
            }
            else if ((flags[index] & 2) == 0)
            {
                // if another stop consonant, move ahead
                loopIndex++;
                continue;
            }
            // RULE: <UNVOICED STOP CONSONANT> {optional silence} <STOP CONSONANT>
            if (debug)
                printf("RULE: <UNVOICED STOP CONSONANT> {optional silence} <STOP CONSONANT> - shorten both to 1/2 + 1\n");
            if (debug)
                printf("PRE\n");
            if (debug)
                printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeIndex[X]], signInputTable2[phonemeIndex[X]], phonemeLength[X]);
            if (debug)
                printf("phoneme %d (%c%c) length %d\n", X - 1, signInputTable1[phonemeIndex[X - 1]], signInputTable2[phonemeIndex[X - 1]], phonemeLength[X - 1]);
            // X gets overwritten, so hold prior X value for debug statement
            int32_t debugX = X;
            // shorten the prior phoneme length to (length/2 + 1)
            phonemeLength[X] = (phonemeLength[X] >> 1) + 1;
            X = loopIndex;
            // also shorten this phoneme length to (length/2 +1)
            phonemeLength[loopIndex] = (phonemeLength[loopIndex] >> 1) + 1;
            if (debug)
                printf("POST\n");
            if (debug)
                printf("phoneme %d (%c%c) length %d\n", debugX, signInputTable1[phonemeIndex[debugX]], signInputTable2[phonemeIndex[debugX]], phonemeLength[debugX]);
            if (debug)
                printf("phoneme %d (%c%c) length %d\n", debugX - 1, signInputTable1[phonemeIndex[debugX - 1]], signInputTable2[phonemeIndex[debugX - 1]], phonemeLength[debugX - 1]);
            // move ahead
            loopIndex++;
            continue;
        }
        // WH, R*, L*, W*, Y*, Q*, Z*, ZH, V*, DH, J*, **,
        // RULE: <VOICED NON-VOWEL> <DIPHTONG>
        //       Decrease <DIPHTONG> by 2
        // liquic consonant?
        if ((flags2[index] & 16) != 0)
        {
            // R*, L*, W*, Y*
            // get the prior phoneme
            index = phonemeIndex[X - 1];
            // prior phoneme a stop consonant>
            if ((flags[index] & 2) != 0)
                // Rule: <LIQUID CONSONANT> <DIPHTONG>
                if (debug)
                    printf("RULE: <LIQUID CONSONANT> <DIPHTONG> - decrease by 2\n");
            if (debug)
                printf("PRE\n");
            if (debug)
                printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeIndex[X]], signInputTable2[phonemeIndex[X]], phonemeLength[X]);
            // decrease the phoneme length by 2 frames (20 ms)
            phonemeLength[X] -= 2;
            if (debug)
                printf("POST\n");
            if (debug)
                printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeIndex[X]], signInputTable2[phonemeIndex[X]], phonemeLength[X]);
        }
        // move to next phoneme
        loopIndex++;
        continue;
    }
    //            goto pos48701;
} // void AdjustLengths()
// -------------------------------------------------------------------------
// ML : Code47503 is division with remainder, and mem50 gets the sign
void Code47503(uint8_t mem52)
{
    Y = 0;
    if ((mem53 & 128) != 0)
    {
        mem53 = -mem53;
        Y = 128;
    }
    mem50 = Y;
    A = 0;
    for (X = 8; X > 0; X--)
    {
        int32_t temp = mem53;
        mem53 = mem53 << 1;
        A = A << 1;
        if (temp >= 128)
            A++;
        if (A >= mem52)
        {
            A = A - mem52;
            mem53++;
        }
    }
    mem51 = A;
    if ((mem50 & 128) != 0)
        mem53 = -mem53;
} // void Code47503(uint8_t mem52)
// END sam.c
// BEGIN reciter.c
// test the flag bits for a specific char
// this is non ascii layout, but tests ascii chars
uint32_t TestFlag(uint8_t in, uint8_t mask)
{
    assert(in<sizeof(tab36376));
    const uint8_t val = tab36376[in];
    return val & mask;
} // uint32_t TestFlag
// test the flag bits for the pervious char in the stream
uint32_t TestFlagDec(uint8_t mem59, uint8_t mask)
{
    X = mem59;
    X--;
    A = inputtemp[X];
    Y = A;
    assert(Y<sizeof(tab36376));
    A = tab36376[Y];
    return A & mask;
} // uint32_t TestFlagDec
// test the flag bits for the next char in the stream
uint32_t TestFlagInc(uint8_t mem58, uint8_t mask)
{
    X = mem58;
    X++;
    A = inputtemp[X];
    Y = A;
    assert(Y<sizeof(tab36376));
    A = tab36376[Y];
    return A & mask;
} // uint32_t TestFlagInc
// verify that the reciter tables are well formed
void ReciterVerify()
{
    size_t ix = 0;
    for (ix = 0; ix<28; ++ix) {
        const size_t pos = rule_tab[ix];
        assert(rules[pos]==']');
    }
} // void ReciterVerify
// lookup a byte for a specific rule in the table
uint8_t GetRuleByte(uint32_t rule_index, uint8_t Y)
{
    const size_t end = sizeof(rules);
    const size_t index = rule_index+Y;
    assert(index<end);
    return rules[index];
} // uint8_t GetRuleByte
void SecureCopyInput(int8_t * input, size_t max_size)
{
    // secure copy of input because input will be overwritten by phonemes
    X = 1;
    Y = 0;
    for (;Y<max_size;++Y) {
        A = input[Y];
        if (A<0x20) {
            continue;
        }
        if (A==0x60) {
            continue;
        }
        if (A==0x27) {
            continue;
        }
        if (A>=0x7E) {
            continue;
        }
        inputtemp[X++] = A;
    };
    memset(input, '\0', max_size);
} // void SecureCopyInput
int32_t TextToPhonemes(int8_t* input, size_t max_size)
{
    max_size = 250;
    static const uint8_t end_token = 155; // ESC | 0x80
    uint32_t out_pos; // output position for phonemes
    uint32_t mem57;
    uint32_t mem58; // current pos, used mostly in rhs match
    uint32_t mem59;
    uint32_t mem60;
    uint32_t mem61;
    uint32_t rule_index; // memory position of current rule
    uint32_t mem64; // position of '=' or current character
    uint32_t pos_rparen; // position of ')'
    uint32_t pos_lparen; // position of '('
    uint32_t mem36653;
    inputtemp[0] = 0x20; // ' '
    SecureCopyInput(input, max_size);
    Y = 255;
    X = 255;
    inputtemp[X] = 27; // ESC
    mem61 = 255;
    A = 255;
    out_pos = 255;
// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
// START PARSE
// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
L_start_parse:
    while (1) {
        mem61++;
        X = mem61;
        // if end of input marker
        A = inputtemp[X];
        mem64 = A;
        if (A=='[') {
            out_pos++;
            X = out_pos;
            A = end_token;
            input[X] = A;
            // success
            return 1;
        }
        if (A=='.') {
            // check a flag for next input char?
            X++;
            Y = inputtemp[X];
            A = TestFlag(Y, 0x01);
            if (A==0) {
                // output a '.'
                out_pos++;
                X = out_pos;
                A = '.';
                input[X] = A;
            }
            else {
                break;
            }
        }
        else {
            break;
        }
    } //while
    // if this character is non alpha
    A = mem64;
    Y = A;
    A = TestFlag(A, 0xff);
    mem57 = A;
    if (A & 0x02) {
        rule_index = rule_tab[26]; // rule2
        goto L_nextrule;
    }
    // what be this ???
    A = mem57; // flag for A
    if (A==0) {
        A = ' ';
        inputtemp[X] = A;
        out_pos++;
        X = out_pos;
        // hard exit on too long?
        if (X > max_size) {
            input[max_size-1] = end_token;
            A = mem61;
            mem36653 = A;
            return 0;
        }
        else {
            input[X] = A;
            goto L_start_parse;
        }
    }
    // what is A at this point?
    A = mem57 & 0x80;
    if (A==0) {
        // error
        return 0;
    }
    // go to the right rules for this character.
    X = mem64 - 'A';
    assert(X<26);
    rule_index = rule_tab[X];
// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
// TRY MATCHING NEXT RULE
// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
L_nextrule:
    // find next rule
    // skip to next rule byte with 0x80 mask
    Y = 0;
    do {
        rule_index += 1;
        A = GetRuleByte(rule_index, Y);
    } while ((A&0x80)==0);
    Y++;
    // if there are no more rules in this set
    if (GetRuleByte(rule_index, Y)==']') {
        return 0;
    }
    // identify key points in this rule
    // find '('
    while (1) {
        // fixme: fix infinite loop here with ' chars
        A = GetRuleByte(rule_index, Y);
        assert((A & 0x80)==0);
        if (A == '(')
            break;
        Y++;
    }
    pos_lparen = Y;
    // find ')'
    do {
        Y++;
        A = GetRuleByte(rule_index, Y);
    } while (A != ')');
    pos_rparen = Y;
    // find '='
    do {
        Y++;
        A = GetRuleByte(rule_index, Y);
        A = A & 0x7F;
    } while (A != '=');
    mem64 = Y;
    X = mem61;
    mem60 = X;
// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
// MATCH EXPRESSION IN PARENTHESIS
// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    Y = pos_lparen;
    Y++;
    // pos36759:
    while (1) {
        mem57 = inputtemp[X];
        A = GetRuleByte(rule_index, Y);
        if (A!=mem57) {
            // no match lets apply next rule
            goto L_nextrule;
        }
        Y++;
        if (Y==pos_rparen) {
            break;
        }
        X++;
        mem60 = X;
    }
    // the string in the bracket is correct
    // pos36787:
    A = mem61;
    mem59 = mem61;
// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
// MATCH TO LEFT OF ( IN RULE
// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
L_match_left:
    // scan back to find start?
    for (;;) {
        pos_lparen--;
        Y = pos_lparen;
        A = GetRuleByte(rule_index, Y);
        mem57 = A;
        // if end of lhs pattern
        if (A & 0x80) {
            A = mem60;
            mem58 = A;
            goto L_match_right;
        }
        //
        X = A & 0x7f;            // all but msb
        A = TestFlag(X, 0x80);
        if (A==0) {
            // parse special escape rule
            break;
        }
        X = mem59 - 1;
        A = inputtemp[X];
        if (A!=mem57) {
            goto L_nextrule;
        }
        mem59 = X;
    }
    // test for special escape chars
    A = mem57;
    switch (A) {
    case (' '): goto pos36895;
    case ('#'): goto pos36910;
    case ('.'): goto pos36920;
    case ('&'): goto pos36935;
    case ('@'): goto pos36967;
    case ('^'): goto pos37004;
    case ('+'): goto pos37019;
    case (':'): goto pos37040;
    default:
        // error
        return 0;
    }
// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
pos36895: // handle ' '
    A = TestFlagDec(mem59, 0x80);
    if (A == 0) {
        mem59 = X;
        goto L_match_left;
    }
    goto L_nextrule;
// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
pos36910: // handle '#'
    A = TestFlagDec(mem59, 0x40);
    if (A!=0) {
        mem59 = X;
        goto L_match_left;
    }
    goto L_nextrule;
// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
pos36920: // handle '.'
    A = TestFlagDec(mem59, 0x08);
    if (A!=0) {
        mem59 = X;
        goto L_match_left;
    }
    goto L_nextrule;
// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
pos36935: // handle '&'
    A = TestFlagDec(mem59, 0x10);
    if (A!=0) {
        mem59 = X;
        goto L_match_left;
    }
    A = inputtemp[X];
    if (A=='H') {
        X--;
        A = inputtemp[X];
        if ((A=='C')||(A=='S')) {
            mem59 = X;
            goto L_match_left;
        }
    }
    goto L_nextrule;
// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
pos36967: // handle '@'
    A = TestFlagDec(mem59, 0x04);
    if (A!=0) {
        mem59 = X;
        goto L_match_left;
    }
    A = inputtemp[X];
    if ((A!='H')&&(A!='T')&&(A!='C')&&(A!='S')) {
        goto L_nextrule;
    }
    mem59 = X;
    goto L_match_left;
// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
pos37004: // handle '^'
    A = TestFlagDec(mem59, 0x20);
    if (A!=0) {
        mem59 = X;
        goto L_match_left;
    }
    goto L_nextrule;
// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
pos37019: // handle '+'
    X = mem59;
    X--;
    A = inputtemp[X];
    if ((A=='E')||(A=='I')||(A=='Y')) {
        mem59 = X;
        goto L_match_left;
    }
    goto L_nextrule;
// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
pos37040: // handle ':'
    A = TestFlagDec(mem59, 0x20);
    if (A!=0) {
        mem59 = X;
        goto pos37040;
    }
    goto L_match_left;
// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
pos37077: // handle '%'
    X = mem58 + 1;
    A = inputtemp[X];
    if (A!='E') {
        goto L_match_ing;
    }
    X++;
    Y = inputtemp[X];
    X--;
    A = TestFlag(Y, 0x80);
    if (A!=0) {
        X++;
        A = inputtemp[X];
        if (A!='R') {
            goto pos37113;
        }
    }
    mem58 = X;
    goto L_match_right;
// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
pos37113: // unknown ???
    if ((A=='S') || (A=='D')) {
        mem58 = X;
        goto L_match_right;
    }
    if (A!='L') {
        goto pos37135;
    }
    X++;
    A = inputtemp[X];
    if (A!='Y') {
        goto L_nextrule;
    }
    mem58 = X;
    goto L_match_right;
pos37135: // match FUV
    if (A!='F') {
        goto L_nextrule;
    }
    X++;
    A = inputtemp[X];
    if (A!='U') {
        goto L_nextrule;
    }
    X++;
    A = inputtemp[X];
    if (A!='V') {
        goto L_nextrule;
    }
    mem58 = X;
    goto L_match_right;
L_match_ing: // match 'ING'
    if (A!='I') {
        goto L_nextrule;
    }
    X++;
    A = inputtemp[X];
    if (A!='N') {
        goto L_nextrule;
    }
    X++;
    A = inputtemp[X];
    if (A!='G') {
        goto L_nextrule;
    }
    mem58 = X;
    goto L_match_right;
// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
// MATCH RIGHT OF ) IN RULE
// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
L_match_right:
    Y = pos_rparen + 1;
    if (Y==mem64) {
        goto L_emitrule;
    }
    pos_rparen = Y;
    A = GetRuleByte(rule_index, Y);
    mem57 = A;
    X = A;
    A = TestFlag(X, 0x80);
    if (A==0) {
        A = mem57;
        switch (A) {
        case (' '): goto pos37295;
        case ('#'): goto pos37310;
        case ('.'): goto pos37320;
        case ('&'): goto pos37335;
        case ('@'): goto pos37367;
        case ('^'): goto pos37404;
        case ('+'): goto pos37419;
        case (':'): goto pos37440;
        case ('%'): goto pos37077;
        default:
            // error
            return 0;
        }
    }
    else {
        // what this does ??
        X = mem58+1;
        A = inputtemp[X];
        if (A!=mem57) {
            goto L_nextrule;
        }
        mem58 = X;
        goto L_match_right;
    }
// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
pos37295: // handle ' '
    A = TestFlagInc(mem58, 0x80);
    if (A!=0) {
        goto L_nextrule;
    }
    mem58 = X;
    goto L_match_right;
// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
pos37310: // handle '#'
    A = TestFlagInc(mem58, 0x40);
    if (A!=0) {
        mem58 = X;
        goto L_match_right;
    }
    goto L_nextrule;
// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
pos37320: // handle '.'
    A = TestFlagInc(mem58, 0x08);
    if (A == 0)
        goto L_nextrule;
    mem58 = X;
    goto L_match_right;
// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
pos37335: // handle '&'
    A = TestFlagInc(mem58, 0x10);
    if (A!=0) {
        mem58 = X;
        goto L_match_right;
    }
    A = inputtemp[X];
    if (A!='H') {
        goto L_nextrule;
    }
    // is this really x++ not x--?
    X++;
    A = inputtemp[X];
    if ((A=='C')||(A=='S')) {
        mem58 = X;
        goto L_match_right;
    }
    goto L_nextrule;
// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
pos37367: // handle '@'
    A = TestFlagInc(mem58, 0x04);
    if (A!=0) {
        mem58 = X;
        goto L_match_right;
    }
    A = inputtemp[X];
    if ((A!='H')&&(A!='T')&&(A!='C')&&(A!='S')) {
        goto L_nextrule;
    }
    mem58 = X;
    goto L_match_right;
// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
pos37404: // handle '^'
    A = TestFlagInc(mem58, 0x20);
    if (A==0) {
        goto L_nextrule;
    }
    mem58 = X;
    goto L_match_right;
// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
pos37419: // handle '+'
    X = mem58;
    X++;
    A = inputtemp[X];
    if ((A=='E')||(A=='I')||(A=='Y')) {
        mem58 = X;
        goto L_match_right;
    }
    goto L_nextrule;
// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
pos37440: // handle ':'
    for (;;) {
        A = TestFlagInc(mem58, 0x20);
        if (A==0) {
            goto L_match_right;
        }
        mem58 = X;
    }
    goto L_emitrule;
// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
// EMIT RULE
// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
L_emitrule:
    Y = mem64;
    mem61 = mem60;
    if (debug) {
        PrintRule(rule_index);
    }
    for (;; ++Y) {
        A = GetRuleByte(rule_index, Y);
        mem57 = A;
        // mask out parity
        A = A & 0x7f;
        if (A != '=') {
            out_pos++;
            X = out_pos;
            input[X] = A;
        }
        // if has parity set
        if (mem57 & 0x80) {
            goto L_start_parse;
        }
    }
} // int32_t TextToPhonemes
// END reciter.c
// BEGIN render.c
void Output(int32_t index, uint8_t A)
{
    static uint32_t oldtimetableindex = 0;
    int32_t k;
    bufferPos += timetable[oldtimetableindex][index];
    oldtimetableindex = index;
    // write a little bit in advance
    for (k = 0; k < 5; k++)
        buffer[bufferPos / 50 + k] = (A & 15) * 16;
} // void Output
//written by me because of different table positions.
// mem[47] = ...
// 168=pitches
// 169=frequency1
// 170=frequency2
// 171=frequency3
// 172=amplitude1
// 173=amplitude2
// 174=amplitude3
uint8_t Read(uint8_t p, uint8_t Y)
{
    switch (p) {
    case 168:
        return pitches[Y];
    case 169:
        return frequency1[Y];
    case 170:
        return frequency2[Y];
    case 171:
        return frequency3[Y];
    case 172:
        return amplitude1[Y];
    case 173:
        return amplitude2[Y];
    case 174:
        return amplitude3[Y];
    }
    printf("Error reading to tables");
    return 0;
} // uint8_t Read
void Write(uint8_t p, uint8_t Y, uint8_t value)
{
    switch (p) {
    case 168:
        pitches[Y] = value;
        return;
    case 169:
        frequency1[Y] = value;
        return;
    case 170:
        frequency2[Y] = value;
        return;
    case 171:
        frequency3[Y] = value;
        return;
    case 172:
        amplitude1[Y] = value;
        return;
    case 173:
        amplitude2[Y] = value;
        return;
    case 174:
        amplitude3[Y] = value;
        return;
    default:
        printf("Error writing to tables\n");
    }
} // void Write
// -------------------------------------------------------------------------
//Code48227
// Render a sampled sound from the sampleTable.
//
//   Phoneme   Sample Start   Sample End
//   32: S*    15             255
//   33: SH    257            511
//   34: F*    559            767
//   35: TH    583            767
//   36: /H    903            1023
//   37: /X    1135           1279
//   38: Z*    84             119
//   39: ZH    340            375
//   40: V*    596            639
//   41: DH    596            631
//
//   42: CH
//   43: **    399            511
//
//   44: J*
//   45: **    257            276
//   46: **
//
//   66: P*
//   67: **    743            767
//   68: **
//
//   69: T*
//   70: **    231            255
//   71: **
//
// The SampledPhonemesTable[] holds flags indicating if a phoneme is
// voiced or not. If the upper 5 bits are zero, the sample is voiced.
//
// Samples in the sampleTable are compressed, with bits being converted to
// bytes from high bit to low, as follows:
//
//   unvoiced 0 bit   -> X
//   unvoiced 1 bit   -> 5
//
//   voiced 0 bit     -> 6
//   voiced 1 bit     -> 24
//
// Where X is a value from the table:
//
//   { 0x18, 0x1A, 0x17, 0x17, 0x17 };
//
// The index into this table is determined by masking off the lower
// 3 bits from the SampledPhonemesTable:
//
//        index = (SampledPhonemesTable[i] & 7) - 1;
//
// For voices samples, samples are interleaved between voiced output.
// Code48227()
void RenderSample(uint8_t* mem66)
{
    int32_t tempA;
    // current phoneme's index
    mem49 = Y;
    // mask low three bits and subtract 1 get value to
    // convert 0 bits on unvoiced samples.
    A = mem39 & 7;
    X = A - 1;
    // store the result
    mem56 = X;
    // determine which offset to use from table { 0x18, 0x1A, 0x17, 0x17, 0x17 }
    // T, S, Z                0          0x18
    // CH, J, SH, ZH          1          0x1A
    // P, F*, V, TH, DH       2          0x17
    // /H                     3          0x17
    // /X                     4          0x17
    // get value from the table
    mem53 = tab48426[X];
    mem47 = X; //46016+mem[56]*256
    // voiced sample?
    A = mem39 & 248;
    if (A == 0) {
        // voiced phoneme: Z*, ZH, V*, DH
        Y = mem49;
        A = pitches[mem49] >> 4;
        // jump to voiced portion
        goto pos48315;
    }
    Y = A ^ 255;
pos48274:
    // step through the 8 bits in the sample
    mem56 = 8;
    // get the next sample from the table
    // mem47*256 = offset to start of samples
    A = sampleTable[mem47 * 256 + Y];
pos48280:
    // left shift to get the high bit
    tempA = A;
    A = A << 1;
    //48281: BCC 48290
    // bit not set?
    if ((tempA & 128) == 0) {
        // convert the bit to value from table
        X = mem53;
        //mem[54296] = X;
        // output the byte
        Output(1, X);
        // if X != 0, exit loop
        if (X != 0)
            goto pos48296;
    }
    // output a 5 for the on bit
    Output(2, 5);
//48295: NOP
pos48296:
    X = 0;
    // decrement counter
    mem56--;
    // if not done, jump to top of loop
    if (mem56 != 0)
        goto pos48280;
    // increment position
    Y++;
    if (Y != 0)
        goto pos48274;
    // restore values and return
    mem44 = 1;
    Y = mem49;
    return;
    uint8_t phase1;
pos48315:
    // handle voiced samples here
    // number of samples?
    phase1 = A ^ 255;
    Y = *mem66;
    do {
        //pos48321:
        // shift through all 8 bits
        mem56 = 8;
        //A = Read(mem47, Y);
        // fetch value from table
        A = sampleTable[mem47 * 256 + Y];
        // loop 8 times
        //pos48327:
        do {
            //48327: ASL A
            //48328: BCC 48337
            // left shift and check high bit
            tempA = A;
            A = A << 1;
            if ((tempA & 128) != 0) {
                // if bit set, output 26
                X = 26;
                Output(3, X);
            }
            else {
                //timetable 4
                // bit is not set, output a 6
                X = 6;
                Output(4, X);
            }
            mem56--;
        } while (mem56 != 0);
        // move ahead in the table
        Y++;
        // continue until counter done
        phase1++;
    } while (phase1 != 0);
    // restore values and return
    A = 1;
    mem44 = 1;
    *mem66 = Y;
    Y = mem49;
    return;
} // void RenderSample
// RENDER THE PHONEMES IN THE LIST
//
// The phoneme list is converted into sound through the steps:
//
// 1. Copy each phoneme <length> number of times into the frames list,
//    where each frame represents 10 milliseconds of sound.
//
// 2. Determine the transitions lengths between phonemes, and linearly
//    interpolate the values across the frames.
//
// 3. Offset the pitches by the fundamental frequency.
//
// 4. Render the each frame.
//void Code47574()
void Render()
{
    uint8_t phase1 = 0; //mem43
    uint8_t phase2;
    uint8_t phase3;
    uint8_t mem66;
    uint8_t mem38;
    uint8_t mem40;
    uint8_t speedcounter; //mem45
    uint8_t mem48;
    int32_t i;
    int32_t carry;
    if (phonemeIndexOutput[0] == 255)
        return; //exit if no data
    A = 0;
    X = 0;
    mem44 = 0;
    // CREATE FRAMES
    //
    // The length parameter in the list corresponds to the number of frames
    // to expand the phoneme to. Each frame represents 10 milliseconds of time.
    // So a phoneme with a length of 7 = 7 frames = 70 milliseconds duration.
    //
    // The parameters are copied from the phoneme to the frame verbatim.
    // pos47587:
    do {
        // get the index
        Y = mem44;
        // get the phoneme at the index
        A = phonemeIndexOutput[mem44];
        mem56 = A;
        // if terminal phoneme, exit the loop
        if (A == 255)
            break;
        // period phoneme *.
        if (A == 1) {
            // add rising inflection
            A = 1;
            mem48 = 1;
            //goto pos48376;
            AddInflection(mem48, phase1);
        }
        /*
        if (A == 2) goto pos48372;
        */
        // question mark phoneme?
        if (A == 2) {
            // create falling inflection
            mem48 = 255;
            AddInflection(mem48, phase1);
        }
        //    pos47615:
        // get the stress amount (more stress = higher pitch)
        phase1 = tab47492[stressOutput[Y] + 1];
        // get number of frames to write
        phase2 = phonemeLengthOutput[Y];
        Y = mem56;
        // copy from the source to the frames list
        do {
            frequency1[X] = freq1data[Y]; // F1 frequency
            frequency2[X] = freq2data[Y]; // F2 frequency
            frequency3[X] = freq3data[Y]; // F3 frequency
            amplitude1[X] = ampl1data[Y]; // F1 amplitude
            amplitude2[X] = ampl2data[Y]; // F2 amplitude
            amplitude3[X] = ampl3data[Y]; // F3 amplitude
            sampledConsonantFlag[X] = sampledConsonantFlags[Y]; // phoneme data for sampled consonants
            pitches[X] = pitch + phase1; // pitch
            X++;
            phase2--;
        } while (phase2 != 0);
        mem44++;
    } while (mem44 != 0);
    // -------------------
    //pos47694:
    // CREATE TRANSITIONS
    //
    // Linear transitions are now created to smoothly connect the
    // end of one sustained portion of a phoneme to the following
    // phoneme.
    //
    // To do this, three tables are used:
    //
    //  Table         Purpose
    //  =========     ==================================================
    //  blendRank     Determines which phoneme's blend values are used.
    //
    //  blendOut      The number of frames at the end of the phoneme that
    //                will be used to transition to the following phoneme.
    //
    //  blendIn       The number of frames of the following phoneme that
    //                will be used to transition into that phoneme.
    //
    // In creating a transition between two phonemes, the phoneme
    // with the HIGHEST rank is used. Phonemes are ranked on how much
    // their identity is based on their transitions. For example,
    // vowels are and diphthongs are identified by their sustained portion,
    // rather than the transitions, so they are given low values. In contrast,
    // stop consonants (P, B, T, K) and glides (Y, L) are almost entirely
    // defined by their transitions, and are given high rank values.
    //
    // Here are the rankings used by SAM:
    //
    //     Rank    Type                         Phonemes
    //     2       All vowels                   IY, IH, etc.
    //     5       Diphthong endings            YX, WX, ER
    //     8       Terminal liquid consonants   LX, WX, YX, N, NX
    //     9       Liquid consonants            L, RX, W
    //     10      Glide                        R, OH
    //     11      Glide                        WH
    //     18      Voiceless fricatives         S, SH, F, TH
    //     20      Voiced fricatives            Z, ZH, V, DH
    //     23      Plosives, stop consonants    P, T, K, KX, DX, CH
    //     26      Stop consonants              J, GX, B, D, G
    //     27-29   Stop consonants (internal)   **
    //     30      Unvoiced consonants          /H, /X and Q*
    //     160     Nasal                        M
    //
    // To determine how many frames to use, the two phonemes are
    // compared using the blendRank[] table. The phoneme with the
    // higher rank is selected. In case of a tie, a blend of each is used:
    //
    //      if blendRank[phoneme1] ==  blendRank[phomneme2]
    //          // use lengths from each phoneme
    //          outBlendFrames = outBlend[phoneme1]
    //          inBlendFrames = outBlend[phoneme2]
    //      else if blendRank[phoneme1] > blendRank[phoneme2]
    //          // use lengths from first phoneme
    //          outBlendFrames = outBlendLength[phoneme1]
    //          inBlendFrames = inBlendLength[phoneme1]
    //      else
    //          // use lengths from the second phoneme
    //          // note that in and out are SWAPPED!
    //          outBlendFrames = inBlendLength[phoneme2]
    //          inBlendFrames = outBlendLength[phoneme2]
    //
    // Blend lengths can't be less than zero.
    //
    // Transitions are assumed to be symetrical, so if the transition
    // values for the second phoneme are used, the inBlendLength and
    // outBlendLength values are SWAPPED.
    //
    // For most of the parameters, SAM interpolates over the range of the last
    // outBlendFrames-1 and the first inBlendFrames.
    //
    // The exception to this is the Pitch[] parameter, which is interpolates the
    // pitch from the CENTER of the current phoneme to the CENTER of the next
    // phoneme.
    //
    // Here are two examples. First, For example, consider the word "SUN" (S AH N)
    //
    //    Phoneme   Duration    BlendWeight    OutBlendFrames    InBlendFrames
    //    S         2           18             1                 3
    //    AH        8           2              4                 4
    //    N         7           8              1                 2
    //
    // The formant transitions for the output frames are calculated as follows:
    //
    //     flags ampl1 freq1 ampl2 freq2 ampl3 freq3 pitch
    //    ------------------------------------------------
    // S
    //    241     0     6     0    73     0    99    61   Use S (weight 18) for transition instead of AH (weight 2)
    //    241     0     6     0    73     0    99    61   <-- (OutBlendFrames-1) = (1-1) = 0 frames
    // AH
    //      0     2    10     2    66     0    96    59 * <-- InBlendFrames = 3 frames
    //      0     4    14     3    59     0    93    57 *
    //      0     8    18     5    52     0    90    55 *
    //      0    15    22     9    44     1    87    53
    //      0    15    22     9    44     1    87    53
    //      0    15    22     9    44     1    87    53   Use N (weight 8) for transition instead of AH (weight 2).
    //      0    15    22     9    44     1    87    53   Since N is second phoneme, reverse the IN and OUT values.
    //      0    11    17     8    47     1    98    56 * <-- (InBlendFrames-1) = (2-1) = 1 frames
    // N
    //      0     8    12     6    50     1   109    58 * <-- OutBlendFrames = 1
    //      0     5     6     5    54     0   121    61
    //      0     5     6     5    54     0   121    61
    //      0     5     6     5    54     0   121    61
    //      0     5     6     5    54     0   121    61
    //      0     5     6     5    54     0   121    61
    //      0     5     6     5    54     0   121    61
    //
    // Now, consider the reverse "NUS" (N AH S):
    //
    //     flags ampl1 freq1 ampl2 freq2 ampl3 freq3 pitch
    //    ------------------------------------------------
    // N
    //     0     5     6     5    54     0   121    61
    //     0     5     6     5    54     0   121    61
    //     0     5     6     5    54     0   121    61
    //     0     5     6     5    54     0   121    61
    //     0     5     6     5    54     0   121    61
    //     0     5     6     5    54     0   121    61   Use N (weight 8) for transition instead of AH (weight 2)
    //     0     5     6     5    54     0   121    61   <-- (OutBlendFrames-1) = (1-1) = 0 frames
    // AH
    //     0     8    11     6    51     0   110    59 * <-- InBlendFrames = 2
    //     0    11    16     8    48     0    99    56 *
    //     0    15    22     9    44     1    87    53   Use S (weight 18) for transition instead of AH (weight 2)
    //     0    15    22     9    44     1    87    53   Since S is second phoneme, reverse the IN and OUT values.
    //     0     9    18     5    51     1    90    55 * <-- (InBlendFrames-1) = (3-1) = 2
    //     0     4    14     3    58     1    93    57 *
    // S
    //   241     2    10     2    65     1    96    59 * <-- OutBlendFrames = 1
    //   241     0     6     0    73     0    99    61
    A = 0;
    mem44 = 0;
    mem49 = 0; // mem49 starts at as 0
    X = 0;
    while (1) //while No. 1
    {
        // get the current and following phoneme
        Y = phonemeIndexOutput[X];
        A = phonemeIndexOutput[X + 1];
        X++;
        // exit loop at end token
        if (A == 255)
            break; //goto pos47970;
        // get the ranking of each phoneme
        X = A;
        mem56 = blendRank[A];
        A = blendRank[Y];
        // compare the rank - lower rank value is stronger
        if (A == mem56) {
            // same rank, so use out blend lengths from each phoneme
            phase1 = outBlendLength[Y];
            phase2 = outBlendLength[X];
        }
        else if (A < mem56) {
            // first phoneme is stronger, so us it's blend lengths
            phase1 = inBlendLength[X];
            phase2 = outBlendLength[X];
        }
        else {
            // second phoneme is stronger, so use it's blend lengths
            // note the out/in are swapped
            phase1 = outBlendLength[Y];
            phase2 = inBlendLength[Y];
        }
        Y = mem44;
        A = mem49 + phonemeLengthOutput[mem44]; // A is mem49 + length
        mem49 = A; // mem49 now holds length + position
        A = A + phase2; //Maybe Problem because of carry flag
        //47776: ADC 42
        speedcounter = A;
        mem47 = 168;
        phase3 = mem49 - phase1; // what is mem49
        A = phase1 + phase2; // total transition?
        mem38 = A;
        X = A;
        X -= 2;
        if ((X & 128) == 0)
            do //while No. 2
            {
                //pos47810:
                // mem47 is used to index the tables:
                // 168  pitches[]
                // 169  frequency1
                // 170  frequency2
                // 171  frequency3
                // 172  amplitude1
                // 173  amplitude2
                // 174  amplitude3
                mem40 = mem38;
                if (mem47 == 168) // pitch
                {
                    // unlike the other values, the pitches[] interpolates from
                    // the middle of the current phoneme to the middle of the
                    // next phoneme
                    uint8_t mem36, mem37;
                    // half the width of the current phoneme
                    mem36 = phonemeLengthOutput[mem44] >> 1;
                    // half the width of the next phoneme
                    mem37 = phonemeLengthOutput[mem44 + 1] >> 1;
                    // sum the values
                    mem40 = mem36 + mem37; // length of both halves
                    mem37 += mem49; // center of next phoneme
                    mem36 = mem49 - mem36; // center index of current phoneme
                    A = Read(mem47, mem37); // value at center of next phoneme - end interpolation value
                    //A = mem[address];
                    Y = mem36; // start index of interpolation
                    mem53 = A - Read(mem47, mem36); // value to center of current phoneme
                }
                else {
                    // value to interpolate to
                    A = Read(mem47, speedcounter);
                    // position to start interpolation from
                    Y = phase3;
                    // value to interpolate from
                    mem53 = A - Read(mem47, phase3);
                }
                //Code47503(mem40);
                // ML : Code47503 is division with remainder, and mem50 gets the sign
                // calculate change per frame
                mem50 = (((int8_t)(mem53) < 0) ? 128 : 0);
                mem51 = abs((int8_t)mem53) % mem40;
                mem53 = (uint8_t)((int8_t)(mem53) / mem40);
                // interpolation range
                X = mem40; // number of frames to interpolate over
                Y = phase3; // starting frame
                // linearly interpolate values
                mem56 = 0;
                //47907: CLC
                //pos47908:
                while (1) //while No. 3
                {
                    A = Read(mem47, Y) + mem53; //carry alway cleared
                    mem48 = A;
                    Y++;
                    X--;
                    if (X == 0)
                        break;
                    mem56 += mem51;
                    if (mem56 >= mem40) //???
                    {
                        mem56 -= mem40; //carry? is set
                        //if ((mem56 & 128)==0)
                        if ((mem50 & 128) == 0) {
                            //47935: BIT 50
                            //47937: BMI 47943
                            if (mem48 != 0)
                                mem48++;
                        }
                        else
                            mem48--;
                    }
                    //pos47945:
                    Write(mem47, Y, mem48);
                } //while No. 3
                //pos47952:
                mem47++;
                //if (mem47 != 175) goto pos47810;
            } while (mem47 != 175); //while No. 2
        //pos47963:
        mem44++;
        X = mem44;
    } //while No. 1
    //goto pos47701;
    //pos47970:
    // add the length of this phoneme
    mem48 = mem49 + phonemeLengthOutput[mem44];
    // ASSIGN PITCH CONTOUR
    //
    // This subtracts the F1 frequency from the pitch to create a
    // pitch contour. Without this, the output would be at a single
    // pitch level (monotone).
    // don't adjust pitch if in sing mode
    if (!singmode) {
        // iterate through the buffer
        for (i = 0; i < 256; i++) {
            // subtract half the frequency of the formant 1.
            // this adds variety to the voice
            pitches[i] -= (frequency1[i] >> 1);
        }
    }
    phase1 = 0;
    phase2 = 0;
    phase3 = 0;
    mem49 = 0;
    speedcounter = 72; //sam standard speed
    // RESCALE AMPLITUDE
    //
    // Rescale volume from a linear scale to decibels.
    //
    //amplitude rescaling
    for (i = 255; i >= 0; i--) {
        amplitude1[i] = amplitudeRescale[amplitude1[i]];
        amplitude2[i] = amplitudeRescale[amplitude2[i]];
        amplitude3[i] = amplitudeRescale[amplitude3[i]];
    }
    Y = 0;
    A = pitches[0];
    mem44 = A;
    X = A;
    mem38 = A - (A >> 2); // 3/4*A ???
    if (debug) {
        PrintOutput(
            sampledConsonantFlag,
            frequency1,
            frequency2,
            frequency3,
            amplitude1,
            amplitude2,
            amplitude3,
            pitches);
    }
    // PROCESS THE FRAMES
    //
    // In traditional vocal synthesis, the glottal pulse drives filters, which
    // are attenuated to the frequencies of the formants.
    //
    // SAM generates these formants directly with sin and rectangular waves.
    // To simulate them being driven by the glottal pulse, the waveforms are
    // reset at the beginning of each glottal pulse.
    //finally the loop for sound output
    //pos48078:
    while (1) {
        // get the sampled information on the phoneme
        A = sampledConsonantFlag[Y];
        mem39 = A;
        // unvoiced sampled phoneme?
        A = A & 248;
        if (A != 0) {
            // render the sample for the phoneme
            RenderSample(&mem66);
            // skip ahead two in the phoneme buffer
            Y += 2;
            mem48 -= 2;
        }
        else {
            // simulate the glottal pulse and formants
            mem56 = multtable[sinus[phase1] | amplitude1[Y]];
            carry = 0;
            if ((mem56 + multtable[sinus[phase2] | amplitude2[Y]]) > 255)
                carry = 1;
            mem56 += multtable[sinus[phase2] | amplitude2[Y]];
            A = mem56 + multtable[rectangle[phase3] | amplitude3[Y]] + (carry ? 1 : 0);
            A = ((A + 136) & 255) >> 4; //there must be also a carry
            //mem[54296] = A;
            // output the accumulated value
            Output(0, A);
            speedcounter--;
            if (speedcounter != 0)
                goto pos48155;
            Y++; //go to next amplitude
            // decrement the frame count
            mem48--;
        }
        // if the frame count is zero, exit the loop
        if (mem48 == 0)
            return;
        speedcounter = speed;
    pos48155:
        // decrement the remaining length of the glottal pulse
        mem44--;
        // finished with a glottal pulse?
        if (mem44 == 0) {
        pos48159:
            // fetch the next glottal pulse length
            A = pitches[Y];
            mem44 = A;
            A = A - (A >> 2);
            mem38 = A;
            // reset the formant wave generators to keep them in
            // sync with the glottal pulse
            phase1 = 0;
            phase2 = 0;
            phase3 = 0;
            continue;
        }
        // decrement the count
        mem38--;
        // is the count non-zero and the sampled flag is zero?
        if ((mem38 != 0) || (mem39 == 0)) {
            // reset the phase of the formants to match the pulse
            phase1 += frequency1[Y];
            phase2 += frequency2[Y];
            phase3 += frequency3[Y];
            continue;
        }
        // voiced sampled phonemes interleave the sample with the
        // glottal pulse. The sample flag is non-zero, so render
        // the sample for the phoneme.
        RenderSample(&mem66);
        goto pos48159;
    } //while
#if 0
    // The following code is never reached. It's left over from when
    // the voiced sample code was part of this loop, instead of part
    // of RenderSample();
    //pos48315:
    int32_t tempA;
    phase1 = A ^ 255;
    Y = mem66;
    do {
        //pos48321:
        mem56 = 8;
        A = Read(mem47, Y);
        //pos48327:
        do {
            //48327: ASL A
            //48328: BCC 48337
            tempA = A;
            A = A << 1;
            if ((tempA & 128) != 0) {
                X = 26;
                // mem[54296] = X;
                bufferPos += 150;
                buffer[bufferPos / 50] = (X & 15) * 16;
            }
            else {
                //mem[54296] = 6;
                X = 6;
                bufferPos += 150;
                buffer[bufferPos / 50] = (X & 15) * 16;
            }
            for (X = wait2; X > 0; X--)
                ; //wait
            mem56--;
        } while (mem56 != 0);
        Y++;
        phase1++;
    } while (phase1 != 0);
    //    if (phase1 != 0) goto pos48321;
    A = 1;
    mem44 = 1;
    mem66 = Y;
    Y = mem49;
    return;
#endif
} // void Render
// Create a rising or falling inflection 30 frames prior to
// index X. A rising inflection is used for questions, and
// a falling inflection is used for statements.
void AddInflection(uint8_t mem48, uint8_t phase1)
{
    //pos48372:
    //    mem48 = 255;
    //pos48376:
    // store the location of the punctuation
    mem49 = X;
    A = X;
    int32_t Atemp = A;
    // backup 30 frames
    A = A - 30;
    // if index is before buffer, point to start of buffer
    if (Atemp <= 30)
        A = 0;
    X = A;
    // FIXME: Explain this fix better, it's not obvious
    // ML : A =, fixes a problem with invalid pitch with '.'
    while ((A = pitches[X]) == 127)
        X++;
pos48398:
    //48398: CLC
    //48399: ADC 48
    // add the inflection direction
    A += mem48;
    phase1 = A;
    // set the inflection
    pitches[X] = A;
pos48406:
    // increment the position
    X++;
    // exit if the punctuation has been reached
    if (X == mem49)
        return; //goto pos47615;
    if (pitches[X] == 255)
        goto pos48406;
    A = phase1;
    goto pos48398;
} // void AddInflection
/*
    SAM's voice can be altered by changing the frequencies of the
    mouth formant (F1) and the throat formant (F2). Only the voiced
    phonemes (5-29 and 48-53) are altered.
*/
void SetMouthThroat(uint8_t mouth, uint8_t throat)
{
    uint8_t initialFrequency;
    uint8_t newFrequency = 0;
    //uint8_t mouth; //mem38880
    //uint8_t throat; //mem38881
    // mouth formants (F1) 5..29
    const uint8_t mouthFormants5_29[30] = {
        0, 0, 0, 0, 0, 10,
        14, 19, 24, 27, 23, 21, 16, 20, 14, 18, 14, 18, 18,
        16, 13, 15, 11, 18, 14, 11, 9, 6, 6, 6
    };
    // throat formants (F2) 5..29
    const uint8_t throatFormants5_29[30] = {
        255, 255,
        255, 255, 255, 84, 73, 67, 63, 40, 44, 31, 37, 45, 73, 49,
        36, 30, 51, 37, 29, 69, 24, 50, 30, 24, 83, 46, 54, 86
    };
    // there must be no zeros in this 2 tables
    // formant 1 frequencies (mouth) 48..53
    const uint8_t mouthFormants48_53[6] = { 19, 27, 21, 27, 18, 13 };
    // formant 2 frequencies (throat) 48..53
    const uint8_t throatFormants48_53[6] = { 72, 39, 31, 43, 30, 34 };
    uint8_t pos = 5; //mem39216
    //pos38942:
    // recalculate formant frequencies 5..29 for the mouth (F1) and throat (F2)
    while (pos != 30) {
        // recalculate mouth frequency
        initialFrequency = mouthFormants5_29[pos];
        if (initialFrequency != 0)
            newFrequency = trans(mouth, initialFrequency);
        freq1data[pos] = newFrequency;
        // recalculate throat frequency
        initialFrequency = throatFormants5_29[pos];
        if (initialFrequency != 0)
            newFrequency = trans(throat, initialFrequency);
        freq2data[pos] = newFrequency;
        pos++;
    }
    //pos39059:
    // recalculate formant frequencies 48..53
    pos = 48;
    Y = 0;
    while (pos != 54) {
        // recalculate F1 (mouth formant)
        initialFrequency = mouthFormants48_53[Y];
        newFrequency = trans(mouth, initialFrequency);
        freq1data[pos] = newFrequency;
        // recalculate F2 (throat formant)
        initialFrequency = throatFormants48_53[Y];
        newFrequency = trans(throat, initialFrequency);
        freq2data[pos] = newFrequency;
        Y++;
        pos++;
    }
} // void SetMouthThroat
//return = (mem39212*mem39213) >> 1
uint8_t trans(uint8_t mem39212, uint8_t mem39213)
{
    //pos39008:
    uint8_t carry;
    int32_t temp;
    uint8_t mem39214, mem39215;
    A = 0;
    mem39215 = 0;
    mem39214 = 0;
    X = 8;
    do {
        carry = mem39212 & 1;
        mem39212 = mem39212 >> 1;
        if (carry != 0) {
            /*
            39018: LSR 39212
            39021: BCC 39033
            */
            carry = 0;
            A = mem39215;
            temp = (int32_t)A + (int32_t)mem39213;
            A = A + mem39213;
            if (temp > 255)
                carry = 1;
            mem39215 = A;
        }
        temp = mem39215 & 1;
        mem39215 = (mem39215 >> 1) | (carry ? 128 : 0);
        carry = temp;
        //39033: ROR 39215
        X--;
    } while (X != 0);
    temp = mem39214 & 128;
    mem39214 = (mem39214 << 1) | (carry ? 1 : 0);
    carry = temp;
    temp = mem39215 & 128;
    mem39215 = (mem39215 << 1) | (carry ? 1 : 0);
    carry = temp;
    return mem39215;
} // uint8_t trans
// END render.c
void WriteWav(int8_t* filename, int8_t* buffer, int32_t bufferlength)
{
#if (_MSC_VER)
    FILE * file = NULL;
    fopen_s(&file, filename, "wb");
#else
    FILE* file = fopen(filename, "wb");
#endif
    if (file == NULL)
        return;
    //RIFF header
    fwrite("RIFF", 4, 1, file);
    uint32_t filesize = bufferlength + 12 + 16 + 8 - 8;
    fwrite(&filesize, 4, 1, file);
    fwrite("WAVE", 4, 1, file);
    //format chunk
    fwrite("fmt ", 4, 1, file);
    uint32_t fmtlength = 16;
    fwrite(&fmtlength, 4, 1, file);
    uint16_t format = 1; //PCM
    fwrite(&format, 2, 1, file);
    uint16_t channels = 1;
    fwrite(&channels, 2, 1, file);
    uint32_t samplerate = 22050;
    fwrite(&samplerate, 4, 1, file);
    fwrite(&samplerate, 4, 1, file); // bytes/second
    uint16_t blockalign = 1;
    fwrite(&blockalign, 2, 1, file);
    uint16_t bitspersample = 8;
    fwrite(&bitspersample, 2, 1, file);
    //data chunk
    fwrite("data", 4, 1, file);
    fwrite(&bufferlength, 4, 1, file);
    fwrite(buffer, bufferlength, 1, file);
    fclose(file);
} // void WriteWav
void PrintUsage()
{
    printf("usage: sam [options] Word1 Word2 ....\n");
    printf("options\n");
    printf("    -phonetic         enters phonetic mode. (see below)\n");
    printf("    -pitch number        set pitch value (default=64)\n");
    printf("    -speed number        set speed value (default=72)\n");
    printf("    -throat number        set throat value (default=128)\n");
    printf("    -mouth number        set mouth value (default=128)\n");
    printf("    -wav filename        output to wav instead of libsdl\n");
    printf("    -sing            special treatment of pitch\n");
    printf("    -debug            print additional debug messages\n");
    printf("\n");
    printf("     VOWELS                            VOICED CONSONANTS    \n");
    printf("IY           f(ee)t                    R        red        \n");
    printf("IH           p(i)n                     L        allow        \n");
    printf("EH           beg                       W        away        \n");
    printf("AE           Sam                       W        whale        \n");
    printf("AA           pot                       Y        you        \n");
    printf("AH           b(u)dget                  M        Sam        \n");
    printf("AO           t(al)k                    N        man        \n");
    printf("OH           cone                      NX       so(ng)        \n");
    printf("UH           book                      B        bad        \n");
    printf("UX           l(oo)t                    D        dog        \n");
    printf("ER           bird                      G        again        \n");
    printf("AX           gall(o)n                  J        judge        \n");
    printf("IX           dig(i)t                   Z        zoo        \n");
    printf("                       ZH       plea(s)ure    \n");
    printf("   DIPHTHONGS                          V        seven        \n");
    printf("EY           m(a)de                    DH       (th)en        \n");
    printf("AY           h(igh)                        \n");
    printf("OY           boy                        \n");
    printf("AW           h(ow)                     UNVOICED CONSONANTS    \n");
    printf("OW           slow                      S         Sam        \n");
    printf("UW           crew                      Sh        fish        \n");
    printf("                                       F         fish        \n");
    printf("                                       TH        thin        \n");
    printf(" SPECIAL PHONEMES                      P         poke        \n");
    printf("UL           sett(le) (=AXL)           T         talk        \n");
    printf("UM           astron(omy) (=AXM)        K         cake        \n");
    printf("UN           functi(on) (=AXN)         CH        speech        \n");
    printf("Q            kitt-en (glottal stop)    /H        a(h)ead    \n");
} // void PrintUsage
#ifdef USESDL
int32_t pos = 0;
void MixAudio(void* unused, Uint8* stream, int32_t len)
{
    int32_t bufferpos = GetBufferLength();
    int8_t* buffer = GetBuffer();
    int32_t i;
    if (pos >= bufferpos)
        return;
    if ((bufferpos - pos) < len)
        len = (bufferpos - pos);
    for (i = 0; i < len; i++) {
        stream[i] = buffer[pos];
        pos++;
    }
} // void MixAudio
void OutputSound()
{
    int32_t bufferpos = GetBufferLength();
    bufferpos /= 50;
    SDL_AudioSpec fmt;
    fmt.freq = 22050;
    fmt.format = AUDIO_U8;
    fmt.channels = 1;
    fmt.samples = 2048;
    fmt.callback = MixAudio;
    fmt.userdata = NULL;
    /* Open the audio device and start playing sound! */
    if (SDL_OpenAudio(&fmt, NULL) < 0) {
        printf("Unable to open audio: %s\n", SDL_GetError());
        exit(1);
    }
    SDL_PauseAudio(0);
    //SDL_Delay((bufferPos)/7);
    while (pos < bufferpos) {
        SDL_Delay(100);
    }
    SDL_CloseAudio();
} // void OutputSound
#else
void OutputSound()
{
} // void OutputSound
#endif
int32_t main(int32_t argc, int8_t** argv)
{
    int32_t i;
    int32_t phonetic = 0;
    int8_t* wavfilename = NULL;
    int8_t input[256];
    for (i = 0; i < 256; i++)
        input[i] = 0;
    if (argc <= 1) {
        PrintUsage();
        return 1;
    }
    i = 1;
    while (i < argc) {
        if (argv[i][0] != '-') {
            strncat_s(input, sizeof(input), argv[i], 256);
            strncat_s(input, sizeof(input), " ", 256);
        }
        else {
            if (strcmp(&argv[i][1], "wav") == 0) {
                wavfilename = argv[i + 1];
                i++;
            }
            else if (strcmp(&argv[i][1], "sing") == 0) {
                EnableSingmode();
            }
            else if (strcmp(&argv[i][1], "phonetic") == 0) {
                phonetic = 1;
            }
            else if (strcmp(&argv[i][1], "debug") == 0) {
                debug = 1;
            }
            else if (strcmp(&argv[i][1], "pitch") == 0) {
                SetPitch(atoi(argv[i + 1]));
                i++;
            }
            else if (strcmp(&argv[i][1], "speed") == 0) {
                SetSpeed(atoi(argv[i + 1]));
                i++;
            }
            else if (strcmp(&argv[i][1], "mouth") == 0) {
                SetMouth(atoi(argv[i + 1]));
                i++;
            }
            else if (strcmp(&argv[i][1], "throat") == 0) {
                SetThroat(atoi(argv[i + 1]));
                i++;
            }
            else {
                PrintUsage();
                return 1;
            }
        }
        i++;
    } //while
    for (i = 0; input[i] != 0; i++)
        input[i] = toupper((int32_t)input[i]);
    if (debug) {
        if (phonetic)
            printf("phonetic input: %s\n", input);
        else
            printf("text input: %s\n", input);
    }
    if (!phonetic) {
        strncat_s(input, sizeof(input), "[", 256);
        if (!TextToPhonemes(input, 256))
            return 1;
        if (debug)
            printf("phonetic input: %s\n", input);
    }
    else
        strncat_s(input, sizeof(input), "\x9b", 256);
#ifdef USESDL
    if (SDL_Init(SDL_INIT_AUDIO) < 0) {
        printf("Unable to init SDL: %s\n", SDL_GetError());
        exit(1);
    }
    atexit(SDL_Quit);
#endif
    SetInput(input);
    if (!SAMMain()) {
        PrintUsage();
        return 1;
    }
    if (wavfilename != NULL)
        WriteWav(wavfilename, GetBuffer(), GetBufferLength() / 50);
    else
        OutputSound();
    return 0;
} // int32_t main
// BEGIN debug.c
void PrintPhonemes(uint8_t* phonemeindex, uint8_t* phonemeLength, uint8_t* stress)
{
    int32_t i = 0;
    printf("===========================================\n");
    printf("Internal Phoneme presentation:\n\n");
    printf(" idx    phoneme  length  stress\n");
    printf("------------------------------\n");
    while ((phonemeindex[i] != 255) && (i < 255)) {
        if (phonemeindex[i] < 81) {
            printf(" %3i      %c%c      %3i       %i\n",
                phonemeindex[i],
                signInputTable1[phonemeindex[i]],
                signInputTable2[phonemeindex[i]],
                phonemeLength[i],
                stress[i]);
        }
        else {
            printf(" %3i      ??      %3i       %i\n", phonemeindex[i], phonemeLength[i], stress[i]);
        }
        i++;
    }
    printf("===========================================\n");
    printf("\n");
} // void PrintPhonemes
void PrintOutput(
    uint8_t* flag,
    uint8_t* f1,
    uint8_t* f2,
    uint8_t* f3,
    uint8_t* a1,
    uint8_t* a2,
    uint8_t* a3,
    uint8_t* p)
{
    printf("===========================================\n");
    printf("Final data for speech output:\n\n");
    int32_t i = 0;
    printf(" flags ampl1 freq1 ampl2 freq2 ampl3 freq3 pitch\n");
    printf("------------------------------------------------\n");
    while (i < 255) {
        printf("%5i %5i %5i %5i %5i %5i %5i %5i\n", flag[i], a1[i], f1[i], a2[i], f2[i], a3[i], f3[i], p[i]);
        i++;
    }
    printf("===========================================\n");
} // void PrintOutput
void PrintRule(int32_t offset)
{
    int32_t i = 1;
    uint8_t A = 0;
    printf("Applying rule: ");
    do {
        A = GetRuleByte(offset, i);
        if ((A & 127) == '=')
            printf(" -> ");
        else
            printf("%c", A & 127);
        i++;
    } while ((A & 128) == 0);
    printf("\n");
} // void PrintRule
// END debug.c
Reply
#6
I did some more work, comparing the QB64PE code the ai spat out to the C code, and doing it this way can really see just how badly it mangled the code! I fixed a bunch of stuff, but still a long way to go. 

Here is the latest QB64PE code, and below that the original C code. 

QB64PE:
Code: (Select All)
' ################################################################################################################################################################
' SAM "SOFTWARE AUTOMATIC MOUTH"
' A native speech synthesizer for QB64PE
' version 0.2.21

' Translated by from C to QB64, from the bit-hack project at:
'
'     https://github.com/bit-hack/SAM
'
' which is a fork of Sebastian Macke's project at:
'
'     https://github.com/s-macke/SAM

' TO DO:
' * Initial translation was done by free ai, so lots of errors and bugs to fix!
' * Replace sound generation code with QB64PE sound commands
' * Get it working (TBD?)

' ################################################################################################################################################################




' ################################################################################################################################################################
' BEGIN INCLUDES
' ################################################################################################################################################################
'#include <assert.h>
'#include <ctype.h>
'#include <stdint.h>
'#include <stdio.h>
'#include <stdlib.h>
'#include <string.h>

'#ifdef USESDL
'#include <SDL/SDL.h>
'#endif
' ################################################################################################################################################################
' END INCLUDES
' ################################################################################################################################################################



' ################################################################################################################################################################
' BEGIN global constants
' ################################################################################################################################################################

Const cMaxPhonemes = 256 ' Example size, adjust as needed

' ################################################################################################################################################################
' END global constants
' ################################################################################################################################################################






' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' BEGIN test_phonemes.c
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

' Test State
Type TestState
    fails As Long
    passes As Long
End Type

'Data Structure
Type TestCase
    testInput As String
    expected As String
End Type

' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' END test_phonemes.c
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

' ################################################################################################################################################################
' BEGIN Global variables (equivalent to C globals)
' ################################################################################################################################################################

' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' BEGIN UNSORTED
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Dim Shared m_ProgramPath$: m_ProgramPath$ = Left$(Command$(0), _InStrRev(Command$(0), "\"))
Dim Shared m_ProgramName$: m_ProgramName$ = Mid$(Command$(0), _InStrRev(Command$(0), "\") + 1)

Dim Shared bDebug As Integer ' FROM debug.h, int32_t becomes INTEGER in QB64






Dim iIndex1 As Long
Dim iIndex2 As Long
Dim iSize As Integer

' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' END UNSORTED
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' BEGIN sam.c
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

' TODO: NEED TO RECONCILE inputtemp() vs TempInput$
'       BECAUSE NOT SURE IF Gemini CONVERTED CORRECTLY
'       IN SOME PLACES WE HAVE inputtemp LOOKING LIKE A STRING:
'           A = ASC(MID$(inputtemp, X + 1, 1))  ' Corrected index
'           inputtemp = SPACE$(256) ' Assuming inputtemp is a string, adjust size as needed
'           inputtemp = " " + inputtemp[0] = 0x20; // '
'       SO WE REPLACED inputtemp WITH TempInput$
'       IT IS REFERENCED IN
'           FUNCTION TextToPhonemes& (sInput AS STRING, max_size AS LONG)
'       WHICH CALLS ROUTINE
'           Function TestFlagDec~% (mem59 As Integer, mask As Long)
'       WHICH REFERENCES IT
'           A = ASC(MID$(TempInput$, X + 1, 1))  'QB64: Access char in string, ASC gets ASCII value
'       BUT IT'S NOT A PARAMETER OR DECLARED, SO DO WE ASSUME GLOBAL?
'       BUT THEN IN OTHER PLACES WE HAVE
'           A = inputtemp(X)
'       WHICH LOOKS LIKE inputtemp IS A NUMERIC ARRAY ?
'       SO TOTALLY CONFUSED ABOUT
'       - WHAT TYPE IT IS
'       - WHETHER IT'S ONE VARIABLE OR 2 OR MORE DIFFERENT VARIABLES
'       - WHETHER IT'S GLOBAL OR LOCAL IN SCOPE
'
' UPDATE:

Dim Shared TempInput$(256) ' int8_t input[256]; // tab39445
ReDim arrInput1(256) As String ' as _Byte ' int8_t input[256]; // tab39445

dim arrInputTemp$
'arrInputTemp$ = static uint8_t inputtemp[1024]; // secure copy of input tab36096


' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
' BEGIN standard sam sound
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
Dim speed As _Byte ' uint8_t speed = 72; <-- uint8_t becomes _BYTE
Dim pitch As _Byte ' uint8_t pitch = 64; <-- uint8_t becomes _BYTE
Dim mouth As _Byte ' uint8_t mouth = 128; <-- uint8_t becomes _BYTE
Dim throat As _Byte ' uint8_t throat = 128; <-- uint8_t becomes _BYTE
Dim singmode As Integer ' int32_t singmode = 0; <-- int32_t becomes Integer

speed = 72 'uint8_t speed = 72;
pitch = 64 'uint8_t pitch = 64;
mouth = 128 'uint8_t mouth = 128;
throat = 128 'uint8_t throat = 128;
singmode = 0 'int32_t singmode = 0;
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
' END standard sam sound
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------



Dim mem39 As _Byte ' uint8_t mem39;
Dim mem44 As _Byte ' uint8_t mem44;
Dim mem47 As _Byte ' uint8_t mem47;
Dim mem49 As _Byte ' uint8_t mem49; <-- uint8_t to _BYTE
Dim mem50 As _Byte ' uint8_t mem50;
Dim mem51 As _Byte ' uint8_t mem51;
Dim mem53 As _Byte ' uint8_t mem53;
Dim mem56 As _Byte ' uint8_t mem56; <-- uint8_t to _BYTE
Dim mem59 As _Byte ' uint8_t mem59 = 0; <-- uint8_t to _BYTE

' *** A AND Y ARE DECLARED AS uint32 IN reciter.c
Dim Shared A As _Unsigned _Byte ' uint8_t A; <-- or is it _BYTE ?
Dim Shared X As _Byte ' uint8_t X;
Dim Shared Y As _Byte ' uint8_t Y;

' contains the final sound buffer
Dim bufferPos As Integer ' int32_t bufferPos = 0;
Dim buffer As _Offset ' int8_t *buffer = NULL; <<- int8_t* to _OFFSET (pointer)

' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' BEGIN sam_tabs.h
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
'tab40672
ReDim arrPhoIndexOutput(59) As _Byte ' uint8_t phonemeIndexOutput[60];  // tab47296 <-- uint8_t to _BYTE

'DIM arrPhonemeIndex[256] AS _BYTE ' uint8_t to _BYTE
ReDim arrPhonemeIndex(cMaxPhonemes) As _Unsigned _Byte ' uint8_t phonemeIndex[256];

ReDim arrPhonemeLength(cMaxPhonemes) As _Byte ' uint8_t phonemeLength[256]; // tab40160 <-- uint8_t to _BYTE

ReDim arrPhoLengthOutput(59) As _Byte ' uint8_t phonemeLengthOutput[60]; // tab47416 <-- uint8_t to _BYTE

ReDim arrStress1(cMaxPhonemes) As _Unsigned _Byte ' uint8_t stress[256];        // numbers from 0 to 8 <-- uint8_t to _BYTE

ReDim arrStressOutput(59) As _Byte ' uint8_t stressOutput[60];        // tab47365 <-- uint8_t to _BYTE

' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
' BEGIN stressInputTable
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
'const uint8_t stressInputTable[] = {
'    '*', '1', '2', '3', '4', '5', '6', '7', '8'
'};

'DIM stressInputTable AS STRING * 9 ' Fixed-length string to hold the characters
'tab40672
'ReDim arrStressInputTable(9) As String
'arrStressInputTable(0) = "*"
'arrStressInputTable(1) = "1"
'arrStressInputTable(2) = "2"
'arrStressInputTable(3) = "3"
'arrStressInputTable(4) = "4"
'arrStressInputTable(5) = "5"
'arrStressInputTable(6) = "6"
'arrStressInputTable(7) = "7"
'arrStressInputTable(8) = "8"

ReDim arrStressInputTable(9) As String
stressInputTableData:
Data "*", "1", "2", "3", "4", "5", "6", "7", "8"
Restore stressInputTableData
For iIndex1 = 0 To 8
    Read arrStressInputTable(iIndex1)
Next iIndex1

' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
' END stressInputTable
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------

' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
' BEGIN tab40682
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
'Dim tab40682$
'ReDim arrSignInputTable1(89) As String ' <-- _Unsigned _Byte
''arrSignInputTable1 = " .?,--IIEAAAAUAIEOURLWYWR LWYMNNNDQSSFT//ZZVDC*J* *EAOAOUB* *D* *G* *GP* *T* *K* *K* *UUU" ' Initialize the string directly
'tab40682$ = " .?,--IIEAAAAUAIEOURLWYWR LWYMNNNDQSSFT//ZZVDC*J* *EAOAOUB* *D* *G* *GP* *T* *K* *K* *UUU" ' Initialize the string directly
'iSize = Len(tab40682$)
'ReDim arrSignInputTable1(0 To iSize - 1) As String ' _Unsigned _Byte
'For iIndex1 = 0 To iSize - 1
'    arrSignInputTable1(iIndex1) = Mid$(tab40682$, iIndex1 + 1, 1)
'Next iIndex1

ReDim signInputTable1(0 To 80) As String ' _Unsigned _Byte
signInputTable1Data:
data " ", ".", "?", ",", "-", "I", "I", "E'
data "A", "A", "A", "A", "U", "A", "I", "E'
data "U", "O", "R", "L", "W", "Y", "W", "R'
data "L", "W", "Y", "M", "N", "N", "D", "Q'
data "S", "S", "F", "T", "/", "/", "Z", "Z'
data "V", "D", "C", "*", "J", "*", "*", "*'
data "E", "A", "O", "A", "O", "U", "B", "*'
data "*", "D", "*", "*", "G", "*", "*", "G'
data "*", "*", "P", "*", "*", "T", "*", "*'
data "K", "*", "*", "K", "*", "*", "U", "U'
data "U"
Restore signInputTable1Data
For iIndex1 = 0 To 80
    Read signInputTable1(iIndex1)
Next iIndex1

' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
' END tab40682
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------

' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
' BEGIN tab40763
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
'Dim tab40763$
'arrSignInputTable2 = "**** *YHH EAHOHXXRXHXXXXH* *****XXX* H*HHHX* HHH* *YYYYWWW* ***** * * *X* * *LMN" ' Initialize the string directly
'tab40763$ = "**** *YHH EAHOHXXRXHXXXXH* *****XXX* H*HHHX* HHH* *YYYYWWW* ***** * * *X* * *LMN" ' Initialize the string directly
'iSize = Len(tab40763$)
'ReDim arrSignInputTable2(0 To iSize - 1) As String ' _Unsigned _Byte
'For iIndex1 = 0 To iSize - 1
'    arrSignInputTable2(iIndex1) = Mid$(tab40763$, iIndex1 + 1, 1)
'Next iIndex1

ReDim arrSignInputTable2(0 To 80) As String ' _Unsigned _Byte
signInputTable2Data:
Data "*","*","*","*","*","Y","H","H"
Data "E","A","H","O","H","X","X","R"
Data "X","H","X","X","X","X","H","*"
Data "*","*","*","*","*","X","X","*"
Data "*","H","*","H","H","X","*","H"
Data "*","H","H","*","*","*","*","*"
Data "Y","Y","Y","W","W","W","*","*"
Data "*","*","*","*","*","*","*","X"
Data "*","*","*","*","*","*","*","*"
Data "*","*","*","X","*","*","L","M"
Data "N"
Restore signInputTable2Data
For iIndex1 = 0 To 80
    Read signInputTable2Data(iIndex1)
Next iIndex1


' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
' END tab40763
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------


' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
' BEGIN loc_9F8C
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
ReDim arrFlags1(0 To 66) As _Unsigned _Byte
flags1Data:
Data &H00,&H00,&H00,&H00,&H00,&HA4,&HA4,&HA4
Data &HA4,&HA4,&HA4,&H84,&H84,&HA4,&HA4,&H84
Data &H84,&H84,&H84,&H84,&H84,&H84,&H44,&H44
Data &H44,&H44,&H44,&H4C,&H4C,&H4C,&H48,&H4C
Data &H40,&H40,&H40,&H40,&H40,&H40,&H44,&H44
Data &H44,&H44,&H48,&H40,&H4C,&H44,&H00,&H00
Data &HB4,&HB4,&HB4,&H94,&H94,&H94,&H4E,&H4E
Data &H4E,&H4E,&H4E,&H4E,&H4E,&H4E,&H4E,&H4E
Data &H4E,&H4E,&H4B,&H4B,&H4B,&H4B,&H4B,&H4B
Data &H4B,&H4B,&H4B,&H4B,&H4B,&H4B,&H80,&HC1
Data &HC1
Restore flags1Data
For iIndex1 = 0 To 66
    Read arrFlags1(iIndex1)
Next iIndex1
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
'END loc_9F8C
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------

' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
' BEGIN loc_9FDA
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
'??? arrFlags1 overlaps arrFlags2
ReDim arrFlags2(0 To 61) As _Unsigned _Byte
flags2Data:
Data &H80,&HC1,&HC1,&HC1,&HC1,&H00,&H00,&H00
Data &H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00
Data &H00,&H00,&H00,&H00,&H00,&H00,&H00,&H10
Data &H10,&H10,&H10,&H08,&H0C,&H08,&H04,&H40
Data &H24,&H20,&H20,&H24,&H00,&H00,&H24,&H20
Data &H20,&H24,&H20,&H20,&H00,&H20,&H00,&H00
Data &H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00
Data &H00,&H04,&H04,&H04,&H00,&H00,&H00,&H00
Data &H00,&H00,&H00,&H00,&H00,&H04,&H04,&H04
Data &H00,&H00,&H00,&H00,&H00,&H00
Restore flags2Data
For iIndex1 = 0 To 61
    Read arrFlags2(iIndex1)
Next iIndex1
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
' END loc_9FDA
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------



' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
' BEGIN tab45616???
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
ReDim arrPhoStressedLengthTable(0 To 61) As _Unsigned _Byte

phonemeStressedLengthTableData:
Data &H00,&H12,&H12,&H12,8,&HB,9,&HB
Data &HE,&HF,&HB,&H10,&HC,6,6,&HE
Data &HC,&HE,&HC,&HB,8,8,&HB,&HA
Data 9,8,8,8,8,8,3,5
Data 2,2,2,2,2,2,6,6
Data 8,6,6,2,9,4,2,1
Data &HE,&HF,&HF,&HF,&HE,&HE,8,2
Data 2,7,2,1,7,2,2,7
Data 2,2,8,2,2,6,2,2
Data 7,2,4,7,1,4,5,5

Restore phonemeStressedLengthTableData
For iIndex1 = 0 To 61
    Read arrPhoStressedLengthTable(iIndex1)
Next iIndex1
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
' END tab45616???
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------





' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
' BEGIN tab45536???
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
ReDim arrPhoLengthTable(0 To 61) As _Unsigned _Byte

phonemeLengthTableData:
Data 0,&h12,&h12,&h12,8,8,8,8
Data 8,&hB,6,&hC,&hA,5,5,&hB
Data &hA,&hA,&hA,9,8,7,9,7
Data 6,8,6,7,7,7,2,5
Data 2,2,2,2,2,2,6,6
Data 7,6,6,2,8,3,1,&h1E
Data &hD,&hC,&hC,&hC,&hE,9,6,1
Data 2,5,1,1,6,1,2,6
Data 1,2,8,2,2,4,2,2
Data 6,1,4,6,1,4,&hC7,&hFF


Restore phonemeLengthTableData
For iIndex1 = 0 To 61
    Read arrPhoLengthTable(iIndex1)
Next iIndex1
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
' END tab45536???
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------

' Ind  | phoneme |  flags   |
' -----|---------|----------|
' 0    |   *     | 00000000 |
' 1    |  .*     | 00000000 |
' 2    |  ?*     | 00000000 |
' 3    |  ,*     | 00000000 |
' 4    |  -*     | 00000000 |
'
' VOWELS
' 5    |  IY     | 10100100 |
' 6    |  IH     | 10100100 |
' 7    |  EH     | 10100100 |
' 8    |  AE     | 10100100 |
' 9    |  AA     | 10100100 |
' 10   |  AH     | 10100100 |
' 11   |  AO     | 10000100 |
' 17   |  OH     | 10000100 |
' 12   |  UH     | 10000100 |
' 16   |  UX     | 10000100 |
' 15   |  ER     | 10000100 |
' 13   |  AX     | 10100100 |
' 14   |  IX     | 10100100 |
'
' DIPHTONGS
' 48   |  EY     | 10110100 |
' 49   |  AY     | 10110100 |
' 50   |  OY     | 10110100 |
' 51   |  AW     | 10010100 |
' 52   |  OW     | 10010100 |
' 53   |  UW     | 10010100 |
'
'
' 21   |  YX     | 10000100 |
' 20   |  WX     | 10000100 |
' 18   |  RX     | 10000100 |
' 19   |  LX     | 10000100 |
' 37   |  /X     | 01000000 |
' 30   |  DX     | 01001000 |
'
'
' 22   |  WH     | 01000100 |
'
'
' VOICED CONSONANTS
' 23   |  R*     | 01000100 |
' 24   |  L*     | 01000100 |
' 25   |  W*     | 01000100 |
' 26   |  Y*     | 01000100 |
' 27   |  M*     | 01001100 |
' 28   |  N*     | 01001100 |
' 29   |  NX     | 01001100 |
' 54   |  B*     | 01001110 |
' 57   |  D*     | 01001110 |
' 60   |  G*     | 01001110 |
' 44   |  J*     | 01001100 |
' 38   |  Z*     | 01000100 |
' 39   |  ZH     | 01000100 |
' 40   |  V*     | 01000100 |
' 41   |  DH     | 01000100 |
'
' unvoiced CONSONANTS
' 32   |  S*     | 01000000 |
' 33   |  SH     | 01000000 |
' 34   |  F*     | 01000000 |
' 35   |  TH     | 01000000 |
' 66   |  P*     | 01001011 |
' 69   |  T*     | 01001011 |
' 72   |  K*     | 01001011 |
' 42   |  CH     | 01001000 |
' 36   |  /H     | 01000000 |
'
' 43   |  **     | 01000000 |
' 45   |  **     | 01000100 |
' 46   |  **     | 00000000 |
' 47   |  **     | 00000000 |
'
'
' 55   |  **     | 01001110 |
' 56   |  **     | 01001110 |
' 58   |  **     | 01001110 |
' 59   |  **     | 01001110 |
' 61   |  **     | 01001110 |
' 62   |  **     | 01001110 |
' 63   |  GX     | 01001110 |
' 64   |  **     | 01001110 |
' 65   |  **     | 01001110 |
' 67   |  **     | 01001011 |
' 68   |  **     | 01001011 |
' 70   |  **     | 01001011 |
' 71   |  **     | 01001011 |
' 73   |  **     | 01001011 |
' 74   |  **     | 01001011 |
' 75   |  KX     | 01001011 |
' 76   |  **     | 01001011 |
' 77   |  **     | 01001011 |
'
'
' SPECIAL
' 78   |  UL     | 10000000 |
' 79   |  UM     | 11000001 |
' 80   |  UN     | 11000001 |
' 31   |  Q*     | 01001100 |
'
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' END sam_tabs.h
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++



' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' BEGIN reciter_tabs.h
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
' BEGIN tab36376
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------

' Some flags
'
'  0x01        numeric
'  0x02        rule set 2
'  0x04        D J L N
'  0x08        B D G J L M N R V W Z
'  0x10        C G J S X Z R S T Z
'  0x20        B C D F G H J K L M N P Q R S T V X Y Z
'  0x40        is vowel + Y
'  0x80        alpha or '

ReDim arrTab36376(0 To 96) As Integer ' _Unsigned _Byte
' Not yes sure exactly how this is used
' array arrTab36376() appears to contain the flags for various ASCII characters
' which set by calculating with bitwise OR statements.
' Here are the values as they appear in the original C code
' (the ASCII characters appear in a comment for each line):
'
' Value                                | ASCII character
' ------------------------------------ | ---------------
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (none?)
' 0                                    | (space char)
' 0 | 0x02                             | !
' 0 | 0x02                             | "
' 0 | 0x02                             | #
' 0 | 0x02                             | $
' 0 | 0x02                             | %
' 0 | 0x02                             | &
' 0 | 0x80 | 0x02                      | '
' 0                                    | (
' 0                                    | )
' 0 | 0x02                             | *
' 0 | 0x02                             | +
' 0 | 0x02                             | ,
' 0 | 0x02                             | -
' 0 | 0x02                             | .
' 0 | 0x02                             | /
' 0 | 0x02 | 0x01                      | 0
' 0 | 0x02 | 0x01                      | 1
' 0 | 0x02 | 0x01                      | 2
' 0 | 0x02 | 0x01                      | 3
' 0 | 0x02 | 0x01                      | 4
' 0 | 0x02 | 0x01                      | 5
' 0 | 0x02 | 0x01                      | 6
' 0 | 0x02 | 0x01                      | 7
' 0 | 0x02 | 0x01                      | 8
' 0 | 0x02 | 0x01                      | 9
' 0 | 0x02                             | :
' 0 | 0x02                             | ;
' 0 | 0x02                             | <
' 0 | 0x02                             | =
' 0 | 0x02                             | >
' 0 | 0x02                             | ?
' 0 | 0x02                             | @
' 0 | 0x80 | 0x40                      | A
' 0 | 0x80 | 0x20 | 0x08               | B
' 0 | 0x80 | 0x20 | 0x10               | C
' 0 | 0x80 | 0x20 | 0x08 | 0x04        | D
' 0 | 0x80 | 0x40                      | E
' 0 | 0x80 | 0x20                      | F
' 0 | 0x80 | 0x20 | 0x10 | 0x08        | G
' 0 | 0x80 | 0x20                      | H
' 0 | 0x80 | 0x40                      | I
' 0 | 0x80 | 0x20 | 0x10 | 0x08 | 0x04 | J
' 0 | 0x80 | 0x20                      | K
' 0 | 0x80 | 0x20 | 0x08 | 0x04        | L
' 0 | 0x80 | 0x20 | 0x08               | M
' 0 | 0x80 | 0x20 | 0x08 | 0x04        | N
' 0 | 0x80 | 0x40                      | O
' 0 | 0x80 | 0x20                      | P
' 0 | 0x80 | 0x20                      | Q
' 0 | 0x80 | 0x20 | 0x08 | 0x04        | R
' 0 | 0x80 | 0x20 | 0x10 | 0x04        | S
' 0 | 0x80 | 0x20 | 0x04               | T
' 0 | 0x80 | 0x40                      | U
' 0 | 0x80 | 0x20 | 0x08               | V
' 0 | 0x80 | 0x20 | 0x08               | W
' 0 | 0x80 | 0x20 | 0x10               | X
' 0 | 0x80 | 0x40                      | Y
' 0 | 0x80 | 0x20 | 0x10 | 0x08 | 0x04 | Z
' 0                                    | [
' 0                                    | \
' 0                                    | ]
' 0 | 0x02                             | ^
' 0                                    | _
' 0 | 0x20 | 0x02                      | `

arrTab36376(0) = 0 ' (NO FLAGS SET)
arrTab36376(1) = 0 ' (NO FLAGS SET)
arrTab36376(2) = 0 ' (NO FLAGS SET)
arrTab36376(3) = 0 ' (NO FLAGS SET)
arrTab36376(4) = 0 ' (NO FLAGS SET)
arrTab36376(5) = 0 ' (NO FLAGS SET)
arrTab36376(6) = 0 ' (NO FLAGS SET)
arrTab36376(7) = 0 ' (NO FLAGS SET)
arrTab36376(8) = 0 ' (NO FLAGS SET)
arrTab36376(9) = 0 ' (NO FLAGS SET)
arrTab36376(10) = 0 ' (NO FLAGS SET)
arrTab36376(11) = 0 ' (NO FLAGS SET)
arrTab36376(12) = 0 ' (NO FLAGS SET)
arrTab36376(13) = 0 ' (NO FLAGS SET)
arrTab36376(14) = 0 ' (NO FLAGS SET)
arrTab36376(15) = 0 ' (NO FLAGS SET)
arrTab36376(16) = 0 ' (NO FLAGS SET)
arrTab36376(17) = 0 ' (NO FLAGS SET)
arrTab36376(18) = 0 ' (NO FLAGS SET)
arrTab36376(19) = 0 ' (NO FLAGS SET)
arrTab36376(20) = 0 ' (NO FLAGS SET)
arrTab36376(21) = 0 ' (NO FLAGS SET)
arrTab36376(22) = 0 ' (NO FLAGS SET)
arrTab36376(23) = 0 ' (NO FLAGS SET)
arrTab36376(24) = 0 ' (NO FLAGS SET)
arrTab36376(25) = 0 ' (NO FLAGS SET)
arrTab36376(26) = 0 ' (NO FLAGS SET)
arrTab36376(27) = 0 ' (NO FLAGS SET)
arrTab36376(28) = 0 ' (NO FLAGS SET)
arrTab36376(29) = 0 ' (NO FLAGS SET)
arrTab36376(30) = 0 ' (NO FLAGS SET)
arrTab36376(31) = 0 ' (NO FLAGS SET)
arrTab36376(32) = 0 ' FLAGS FOR " "
arrTab36376(33) = 0 OR &H02 ' FLAGS FOR "!"
arrTab36376(34) = 0 OR &H02 ' FLAGS FOR '"'
arrTab36376(35) = 0 OR &H02 ' FLAGS FOR "#"
arrTab36376(36) = 0 OR &H02 ' FLAGS FOR "$"
arrTab36376(37) = 0 OR &H02 ' FLAGS FOR "%"
arrTab36376(38) = 0 OR &H02 ' FLAGS FOR "&"
arrTab36376(39) = 0 OR &H80 OR &H02 ' FLAGS FOR "'"
arrTab36376(40) = 0 ' FLAGS FOR "("
arrTab36376(41) = 0 ' FLAGS FOR ")"
arrTab36376(42) = 0 OR &H02 ' FLAGS FOR "*"
arrTab36376(43) = 0 OR &H02 ' FLAGS FOR "+"
arrTab36376(44) = 0 OR &H02 ' FLAGS FOR ","
arrTab36376(45) = 0 OR &H02 ' FLAGS FOR "-"
arrTab36376(46) = 0 OR &H02 ' FLAGS FOR "."
arrTab36376(47) = 0 OR &H02 ' FLAGS FOR "/"
arrTab36376(48) = 0 OR &H02 OR &H01 ' FLAGS FOR "0"
arrTab36376(49) = 0 OR &H02 OR &H01 ' FLAGS FOR "1"
arrTab36376(50) = 0 OR &H02 OR &H01 ' FLAGS FOR "2"
arrTab36376(51) = 0 OR &H02 OR &H01 ' FLAGS FOR "3"
arrTab36376(52) = 0 OR &H02 OR &H01 ' FLAGS FOR "4"
arrTab36376(53) = 0 OR &H02 OR &H01 ' FLAGS FOR "5"
arrTab36376(54) = 0 OR &H02 OR &H01 ' FLAGS FOR "6"
arrTab36376(55) = 0 OR &H02 OR &H01 ' FLAGS FOR "7"
arrTab36376(56) = 0 OR &H02 OR &H01 ' FLAGS FOR "8"
arrTab36376(57) = 0 OR &H02 OR &H01 ' FLAGS FOR "9"
arrTab36376(58) = 0 OR &H02 ' FLAGS FOR ":"
arrTab36376(59) = 0 OR &H02 ' FLAGS FOR ";"
arrTab36376(60) = 0 OR &H02 ' FLAGS FOR "<"
arrTab36376(61) = 0 OR &H02 ' FLAGS FOR "="
arrTab36376(62) = 0 OR &H02 ' FLAGS FOR ">"
arrTab36376(63) = 0 OR &H02 ' FLAGS FOR "?"
arrTab36376(64) = 0 OR &H02 ' FLAGS FOR "@"
arrTab36376(65) = 0 OR &H80 OR &H40 ' FLAGS FOR "A"
arrTab36376(66) = 0 OR &H80 OR &H20 OR &H08 ' FLAGS FOR "B"
arrTab36376(67) = 0 OR &H80 OR &H20 OR &H10 ' FLAGS FOR "C"
arrTab36376(68) = 0 OR &H80 OR &H20 OR &H08 OR &H04 ' FLAGS FOR "D"
arrTab36376(69) = 0 OR &H80 OR &H40 ' FLAGS FOR "E"
arrTab36376(70) = 0 OR &H80 OR &H20 ' FLAGS FOR "F"
arrTab36376(71) = 0 OR &H80 OR &H20 OR &H10 OR &H08 ' FLAGS FOR "G"
arrTab36376(72) = 0 OR &H80 OR &H20 ' FLAGS FOR "H"
arrTab36376(73) = 0 OR &H80 OR &H40 ' FLAGS FOR "I"
arrTab36376(74) = 0 OR &H80 OR &H20 OR &H10 OR &H08 OR &H04 ' FLAGS FOR "J"
arrTab36376(75) = 0 OR &H80 OR &H20 ' FLAGS FOR "K"
arrTab36376(76) = 0 OR &H80 OR &H20 OR &H08 OR &H04 ' FLAGS FOR "L"
arrTab36376(77) = 0 OR &H80 OR &H20 OR &H08 ' FLAGS FOR "M"
arrTab36376(78) = 0 OR &H80 OR &H20 OR &H08 OR &H04 ' FLAGS FOR "N"
arrTab36376(79) = 0 OR &H80 OR &H40 ' FLAGS FOR "O"
arrTab36376(80) = 0 OR &H80 OR &H20 ' FLAGS FOR "P"
arrTab36376(81) = 0 OR &H80 OR &H20 ' FLAGS FOR "Q"
arrTab36376(82) = 0 OR &H80 OR &H20 OR &H08 OR &H04 ' FLAGS FOR "R"
arrTab36376(83) = 0 OR &H80 OR &H20 OR &H10 OR &H04 ' FLAGS FOR "S"
arrTab36376(84) = 0 OR &H80 OR &H20 OR &H04 ' FLAGS FOR "T"
arrTab36376(85) = 0 OR &H80 OR &H40 ' FLAGS FOR "U"
arrTab36376(86) = 0 OR &H80 OR &H20 OR &H08 ' FLAGS FOR "V"
arrTab36376(87) = 0 OR &H80 OR &H20 OR &H08 ' FLAGS FOR "W"
arrTab36376(88) = 0 OR &H80 OR &H20 OR &H10 ' FLAGS FOR "X"
arrTab36376(89) = 0 OR &H80 OR &H40 ' FLAGS FOR "Y"
arrTab36376(90) = 0 OR &H80 OR &H20 OR &H10 OR &H08 OR &H04 ' FLAGS FOR "Z"
arrTab36376(91) = 0 ' FLAGS FOR "["
arrTab36376(92) = 0 ' FLAGS FOR "\"
arrTab36376(93) = 0 ' FLAGS FOR "]"
arrTab36376(94) = 0 OR &H02 ' FLAGS FOR "^"
arrTab36376(95) = 0 ' FLAGS FOR "_"
arrTab36376(96) = 0 OR &H20 OR &H02 ' FLAGS FOR "`"
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
' END tab36376
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------

' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
' BEGIN rules
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
ReDim arrRules(0 To 150) As String
arrRules(0) = "]\xc1" ' "]A"
arrRules(1) = " (A.)=EH4Y.\xa0" ' " (A.)=EH4Y. "
arrRules(2) = "(A) =A\xc8" ' "(A) =AH"
arrRules(3) = " (ARE) =AA\xd2" ' " (ARE) =AAR"
arrRules(4) = " (AR)O=AX\xd2" ' " (AR)O=AXR"
arrRules(5) = "(AR)#=EH4\xd2" ' "(AR)#=EH4R"
arrRules(6) = " ^(AS)#=EY4\xd3" ' " ^(AS)#=EY4S"
arrRules(7) = "(A)WA=A\xd8" ' "(A)WA=AX"
arrRules(8) = "(AW)=AO\xb5" ' "(AW)=AO5"
arrRules(9) = " :(ANY)=EH4NI\xd9" ' " :(ANY)=EH4NIY"
arrRules(10) = "(A)^+#=EY\xb5" ' "(A)^+#=EY5"
arrRules(11) = "#:(ALLY)=ULI\xd9" ' "#:(ALLY)=ULIY"
arrRules(12) = " (AL)#=U\xcc" ' " (AL)#=UL"
arrRules(13) = "(AGAIN)=AXGEH4\xce" ' "(AGAIN)=AXGEH4N"
arrRules(14) = "#:(AG)E=IH\xca" ' "#:(AG)E=IHJ"
arrRules(15) = "(A)^%=E\xd9" ' "(A)^%=EY"
arrRules(16) = "(A)^+:#=A\xc5" ' "(A)^+:#=AE"
arrRules(17) = " :(A)^+ =EY\xb4" ' " :(A)^+ =EY4"
arrRules(18) = " (ARR)=AX\xd2" ' " (ARR)=AXR"
arrRules(19) = "(ARR)=AE4\xd2" ' "(ARR)=AE4R"
arrRules(20) = " ^(AR) =AA5\xd2" ' " ^(AR) =AA5R"
arrRules(21) = "(AR)=AA5\xd2" ' "(AR)=AA5R"
arrRules(22) = "(AIR)=EH4\xd2" ' "(AIR)=EH4R"
arrRules(23) = "(AI)=EY\xb4" ' "(AI)=EY4"
arrRules(24) = "(AY)=EY\xb5" ' "(AY)=EY5"
arrRules(25) = "(AU)=AO\xb4" ' "(AU)=AO4"
arrRules(26) = "#:(AL) =U\xcc" ' "#:(AL) =UL"
arrRules(27) = "#:(ALS) =UL\xda" ' "#:(ALS) =ULZ"
arrRules(28) = "(ALK)=AO4\xcb" ' "(ALK)=AO4K"
arrRules(29) = "(AL)^=AO\xcc" ' "(AL)^=AOL"
arrRules(30) = " :(ABLE)=EY4BU\xcc" ' " :(ABLE)=EY4BUL"
arrRules(31) = "(ABLE)=AXBU\xcc" ' "(ABLE)=AXBUL"
arrRules(32) = "(A)VO=EY\xb4" ' "(A)VO=EY4"
arrRules(33) = "(ANG)+=EY4N\xca" ' "(ANG)+=EY4NJ"
arrRules(34) = "(ATARI)=AHTAA4RI\xd9" ' "(ATARI)=AHTAA4RIY"
arrRules(35) = "(A)TOM=A\xc5" ' "(A)TOM=AE"
arrRules(36) = "(A)TTI=A\xc5" ' "(A)TTI=AE"
arrRules(37) = " (AT) =AE\xd4" ' " (AT) =AET"
arrRules(38) = " (A)T=A\xc8" ' " (A)T=AH"
arrRules(39) = "(A)=A\xc5" ' "(A)=AE"

arrRules(40) = "]\xc2" ' "]B"
arrRules(41) = " (B) =BIY\xb4" ' " (B) =BIY4"
arrRules(42) = " (BE)^#=BI\xc8" ' " (BE)^#=BIH"
arrRules(43) = "(BEING)=BIY4IHN\xd8" ' "(BEING)=BIY4IHNX"
arrRules(44) = " (BOTH) =BOW4T\xc8" ' " (BOTH) =BOW4TH"
arrRules(45) = " (BUS)#=BIH4\xda" ' " (BUS)#=BIH4Z"
arrRules(46) = "(BREAK)=BREY5\xcb" ' "(BREAK)=BREY5K"
arrRules(47) = "(BUIL)=BIH4\xcc" ' "(BUIL)=BIH4L"
arrRules(48) = "(B)=\xc2" ' "(B)=B"

arrRules(49) = "]\xc3" ' "]C"
arrRules(50) = " (C) =SIY\xb4" ' " (C) =SIY4"
arrRules(51) = " (CH)^=\xcb" ' " (CH)^=K"
arrRules(52) = "^E(CH)=\xcb" ' "^E(CH)=K"
arrRules(53) = "(CHA)R#=KEH\xb5" ' "(CHA)R#=KEH5"
arrRules(54) = "(CH)=C\xc8" ' "(CH)=CH"
arrRules(55) = " S(CI)#=SAY\xb4" ' " S(CI)#=SAY4"
arrRules(56) = "(CI)A=S\xc8" ' "(CI)A=SH"
arrRules(57) = "(CI)O=S\xc8" ' "(CI)O=SH"
arrRules(58) = "(CI)EN=S\xc8" ' "(CI)EN=SH"
arrRules(59) = "(CITY)=SIHTI\xd9" ' "(CITY)=SIHTIY"
arrRules(60) = "(C)+=\xd3" ' "(C)+=S"
arrRules(61) = "(CK)=\xcb" ' "(CK)=K"
arrRules(62) = "(COMMODORE)=KAA4MAHDOH\xd2" ' "(COMMODORE)=KAA4MAHDOHR"
arrRules(63) = "(COM)=KAH\xcd" ' "(COM)=KAHM"
arrRules(64) = "(CUIT)=KIH\xd4" ' "(CUIT)=KIHT"
arrRules(65) = "(CREA)=KRIYE\xd9" ' "(CREA)=KRIYEY"
arrRules(66) = "(C)=\xcb" ' "(C)=K"

arrRules(67) = "]\xc4" ' "]D"
arrRules(68) = " (D) =DIY\xb4" ' " (D) =DIY4"
arrRules(69) = " (DR.) =DAA4KTE\xd2" ' " (DR.) =DAA4KTER"
arrRules(70) = "#:(DED) =DIH\xc4" ' "#:(DED) =DIHD"
arrRules(71) = ".E(D) =\xc4" ' ".E(D) =D"
arrRules(72) = "#:^E(D) =\xd4" ' "#:^E(D) =T"
arrRules(73) = " (DE)^#=DI\xc8" ' " (DE)^#=DIH"
arrRules(74) = " (DO) =DU\xd7" ' " (DO) =DUW"
arrRules(75) = " (DOES)=DAH\xda" ' " (DOES)=DAHZ"
arrRules(76) = "(DONE) =DAH5\xce" ' "(DONE) =DAH5N"
arrRules(77) = "(DOING)=DUW4IHN\xd8" ' "(DOING)=DUW4IHNX"
arrRules(78) = " (DOW)=DA\xd7" ' " (DOW)=DAW"
arrRules(79) = "#(DU)A=JU\xd7" ' "#(DU)A=JUW"
arrRules(80) = "#(DU)^#=JA\xd8" ' "#(DU)^#=JAX"
arrRules(81) = "(D)=\xc4" ' "(D)=D"

arrRules(82) = "]\xc5" ' "]E"
arrRules(83) = " (E) =IYIY\xb4" ' " (E) =IYIY4"
arrRules(84) = "#:(E) \xbd" ' "#:(E) ="
arrRules(85) = "\\':^(E) \xbd" ' "\\':^(E) ="
arrRules(86) = " :(E) =I\xd9" ' " :(E) =IY"
arrRules(87) = "#(ED) =\xc4" ' "#(ED) =D"
arrRules(88) = "#:(E)D \xbd" ' "#:(E)D ="
arrRules(89) = "(EV)ER=EH4\xd6" ' "(EV)ER=EH4V"
arrRules(90) = "(E)^%=IY\xb4" ' "(E)^%=IY4"
arrRules(91) = "(ERI)#=IY4RI\xd9" ' "(ERI)#=IY4RIY"
arrRules(92) = "(ERI)=EH4RI\xc8" ' "(ERI)=EH4RIH"
arrRules(93) = "#:(ER)#=E\xd2" ' "#:(ER)#=ER"
arrRules(94) = "(ERROR)=EH4ROH\xd2" ' "(ERROR)=EH4ROHR"
arrRules(95) = "(ERASE)=IHREY5\xd3" ' "(ERASE)=IHREY5S"
arrRules(96) = "(ER)#=EH\xd2" ' "(ER)#=EHR"
arrRules(97) = "(ER)=E\xd2" ' "(ER)=ER"
arrRules(98) = " (EVEN)=IYVEH\xce" ' " (EVEN)=IYVEHN"
arrRules(99) = "#:(E)W\xbd" ' "#:(E)W="
arrRules(100) = "@(EW)=U\xd7" ' "@(EW)=UW"
arrRules(101) = "(EW)=YU\xd7" ' "(EW)=YUW"
arrRules(102) = "(E)O=I\xd9" ' "(E)O=IY"
arrRules(103) = "#:&(ES) =IH\xda" ' "#:&(ES) =IHZ"
arrRules(104) = "#:(E)S \xbd" ' "#:(E)S ="
arrRules(105) = "#:(ELY) =LI\xd9" ' "#:(ELY) =LIY"
arrRules(106) = "#:(EMENT)=MEHN\xd4" ' "#:(EMENT)=MEHNT"
arrRules(107) = "(EFUL)=FUH\xcc" ' "(EFUL)=FUHL"
arrRules(108) = "(EE)=IY\xb4" ' "(EE)=IY4"
arrRules(109) = "(EARN)=ER5\xce" ' "(EARN)=ER5N"
arrRules(110) = " (EAR)^=ER\xb5" ' " (EAR)^=ER5"
arrRules(111) = "(EAD)=EH\xc4" ' "(EAD)=EHD"
arrRules(112) = "#:(EA) =IYA\xd8" ' "#:(EA) =IYAX"
arrRules(113) = "(EA)SU=EH\xb5" ' "(EA)SU=EH5"
arrRules(114) = "(EA)=IY\xb5" ' "(EA)=IY5"
arrRules(115) = "(EIGH)=EY\xb4" ' "(EIGH)=EY4"
arrRules(116) = "(EI)=IY\xb4" ' "(EI)=IY4"
arrRules(117) = " (EYE)=AY\xb4" ' " (EYE)=AY4"
arrRules(118) = "(EY)=I\xd9" ' "(EY)=IY"
arrRules(119) = "(EU)=YUW\xb5" ' "(EU)=YUW5"
arrRules(120) = "(EQUAL)=IY4KWU\xcc" ' "(EQUAL)=IY4KWUL"
arrRules(121) = "(E)=E\xc8" ' "(E)=EH"

arrRules(122) = "]\xc6" ' "]F"
arrRules(123) = " (F) =EH4\xc6" ' " (F) =EH4F"
arrRules(124) = "(FUL)=FUH\xcc" ' "(FUL)=FUHL"
arrRules(125) = "(FRIEND)=FREH5N\xc4" ' "(FRIEND)=FREH5ND"
arrRules(126) = "(FATHER)=FAA4DHE\xd2" ' "(FATHER)=FAA4DHER"
arrRules(127) = "(F)F\xbd" ' "(F)F="
arrRules(128) = "(F)=\xc6" ' "(F)=F"

arrRules(129) = "]\xc7" ' "]G"
arrRules(130) = " (G) =JIY\xb4" ' " (G) =JIY4"
arrRules(131) = "(GIV)=GIH5\xd6" ' "(GIV)=GIH5V"
arrRules(132) = " (G)I^=\xc7" ' " (G)I^=G"
arrRules(133) = "(GE)T=GEH\xb5" ' "(GE)T=GEH5"
arrRules(134) = "SU(GGES)=GJEH4\xd3" ' "SU(GGES)=GJEH4S"
arrRules(135) = "(GG)=\xc7" ' "(GG)=G"
arrRules(136) = " B#(G)=\xc7" ' " B#(G)=G"
arrRules(137) = "(G)+=\xca" ' "(G)+=J"
arrRules(138) = "(GREAT)=GREY4\xd4" ' "(GREAT)=GREY4T"
arrRules(139) = "(GON)E=GAO5\xce" ' "(GON)E=GAO5N"
arrRules(140) = "#(GH)\xbd" ' "#(GH)="
arrRules(141) = " (GN)=\xce" ' " (GN)=N"
arrRules(142) = "(G)=\xc7" ' "(G)=G"

arrRules(143) = "]\xc8" ' "]H"
arrRules(144) = " (H) =EY4C\xc8" ' " (H) =EY4CH"
arrRules(145) = " (HAV)=/HAE6\xd6" ' " (HAV)=/HAE6V"
arrRules(146) = " (HERE)=/HIY\xd2" ' " (HERE)=/HIYR"
arrRules(147) = " (HOUR)=AW5E\xd2" ' " (HOUR)=AW5ER"
arrRules(148) = "(HOW)=/HA\xd7" ' "(HOW)=/HAW"
arrRules(149) = "(H)#=/\xc8" ' "(H)#=/H"
arrRules(150) = "(H)\xbd" ' "(H)="

arrRules(151) = "]\xc9" ' "]I"
arrRules(152) = " (IN)=IH\xce" ' " (IN)=IHN"
arrRules(153) = " (I) =AY\xb4" ' " (I) =AY4"
arrRules(154) = "(I) =A\xd9" ' "(I) =AY"
arrRules(155) = "(IN)D=AY5\xce" ' "(IN)D=AY5N"
arrRules(156) = "SEM(I)=I\xd9" ' "SEM(I)=IY"
arrRules(157) = " ANT(I)=A\xd9" ' " ANT(I)=AY"
arrRules(158) = "(IER)=IYE\xd2" ' "(IER)=IYER"
arrRules(159) = "#:R(IED) =IY\xc4" ' "#:R(IED) =IYD"
arrRules(160) = "(IED) =AY5\xc4" ' "(IED) =AY5D"
arrRules(161) = "(IEN)=IYEH\xce" ' "(IEN)=IYEHN"
arrRules(162) = "(IE)T=AY4E\xc8" ' "(IE)T=AY4EH"
arrRules(163) = "(I\\')=AY\xb5" ' "(I\\')=AY5"
arrRules(164) = " :(I)^%=AY\xb5" ' " :(I)^%=AY5"
arrRules(165) = " :(IE) =AY\xb4" ' " :(IE) =AY4"
arrRules(166) = "(I)%=I\xd9" ' "(I)%=IY"
arrRules(167) = "(IE)=IY\xb4" ' "(IE)=IY4"
arrRules(168) = " (IDEA)=AYDIY5A\xc8" ' " (IDEA)=AYDIY5AH"
arrRules(169) = "(I)^+:#=I\xc8" ' "(I)^+:#=IH"
arrRules(170) = "(IR)#=AY\xd2" ' "(IR)#=AYR"
arrRules(171) = "(IZ)%=AY\xda" ' "(IZ)%=AYZ"
arrRules(172) = "(IS)%=AY\xda" ' "(IS)%=AYZ"
arrRules(173) = "I^(I)^#=I\xc8" ' "I^(I)^#=IH"
arrRules(174) = "+^(I)^+=A\xd9" ' "+^(I)^+=AY"
arrRules(175) = "#:^(I)^+=I\xc8" ' "#:^(I)^+=IH"
arrRules(176) = "(I)^+=A\xd9" ' "(I)^+=AY"
arrRules(177) = "(IR)=E\xd2" ' "(IR)=ER"
arrRules(178) = "(IGH)=AY\xb4" ' "(IGH)=AY4"
arrRules(179) = "(ILD)=AY5L\xc4" ' "(ILD)=AY5LD"
arrRules(180) = " (IGN)=IHG\xce" ' " (IGN)=IHGN"
arrRules(181) = "(IGN) =AY4\xce" ' "(IGN) =AY4N"
arrRules(182) = "(IGN)^=AY4\xce" ' "(IGN)^=AY4N"
arrRules(183) = "(IGN)%=AY4\xce" ' "(IGN)%=AY4N"
arrRules(184) = "(ICRO)=AY4KRO\xc8" ' "(ICRO)=AY4KROH"
arrRules(185) = "(IQUE)=IY4\xcb" ' "(IQUE)=IY4K"
arrRules(186) = "(I)=I\xc8" ' "(I)=IH"

arrRules(187) = "]\xca" ' "]J"
arrRules(188) = " (J) =JEY\xb4" ' " (J) =JEY4"
arrRules(189) = "(J)=\xca" ' "(J)=J"

arrRules(190) = "]\xcb" ' "]K"
arrRules(191) = " (K) =KEY\xb4" ' " (K) =KEY4"
arrRules(192) = " (K)N\xbd" ' " (K)N="
arrRules(193) = "(K)=\xcb" ' "(K)=K"

arrRules(194) = "]\xcc" ' "]L"
arrRules(195) = " (L) =EH4\xcc" ' " (L) =EH4L"
arrRules(196) = "(LO)C#=LO\xd7" ' "(LO)C#=LOW"
arrRules(197) = "L(L)\xbd" ' "L(L)="
arrRules(198) = "#:^(L)%=U\xcc" ' "#:^(L)%=UL"
arrRules(199) = "(LEAD)=LIY\xc4" ' "(LEAD)=LIYD"
arrRules(200) = " (LAUGH)=LAE4\xc6" ' " (LAUGH)=LAE4F"
arrRules(201) = "(L)=\xcc" ' "(L)=L"

arrRules(202) = "]\xcd" ' "]M"
arrRules(203) = " (M) =EH4\xcd" ' " (M) =EH4M"
arrRules(204) = " (MR.) =MIH4STE\xd2" ' " (MR.) =MIH4STER"
arrRules(205) = " (MS.)=MIH5\xda" ' " (MS.)=MIH5Z"
arrRules(206) = " (MRS.) =MIH4SIX\xda" ' " (MRS.) =MIH4SIXZ"
arrRules(207) = "(MOV)=MUW4\xd6" ' "(MOV)=MUW4V"
arrRules(208) = "(MACHIN)=MAHSHIY5\xce" ' "(MACHIN)=MAHSHIY5N"
arrRules(209) = "M(M)\xbd" ' "M(M)="
arrRules(210) = "(M)=\xcd" ' "(M)=M"

arrRules(211) = "]\xce" ' "]N"
arrRules(212) = " (N) =EH4\xce" ' " (N) =EH4N"
arrRules(213) = "E(NG)+=N\xca" ' "E(NG)+=NJ"
arrRules(214) = "(NG)R=NX\xc7" ' "(NG)R=NXG"
arrRules(215) = "(NG)#=NX\xc7" ' "(NG)#=NXG"
arrRules(216) = "(NGL)%=NXGU\xcc" ' "(NGL)%=NXGUL"
arrRules(217) = "(NG)=N\xd8" ' "(NG)=NX"
arrRules(218) = "(NK)=NX\xcb" ' "(NK)=NXK"
arrRules(219) = " (NOW) =NAW\xb4" ' " (NOW) =NAW4"
arrRules(220) = "N(N)\xbd" ' "N(N)="
arrRules(221) = "(NON)E=NAH4\xce" ' "(NON)E=NAH4N"
arrRules(222) = "(N)=\xce" ' "(N)=N"

arrRules(223) = "]\xcf" ' "]O"
arrRules(224) = " (O) =OH4\xd7" ' " (O) =OH4W"
arrRules(225) = "(OF) =AH\xd6" ' "(OF) =AHV"
arrRules(226) = " (OH) =OW\xb5" ' " (OH) =OW5"
arrRules(227) = "(OROUGH)=ER4O\xd7" ' "(OROUGH)=ER4OW"
arrRules(228) = "#:(OR) =E\xd2" ' "#:(OR) =ER"
arrRules(229) = "#:(ORS) =ER\xda" ' "#:(ORS) =ERZ"
arrRules(230) = "(OR)=AO\xd2" ' "(OR)=AOR"
arrRules(231) = " (ONE)=WAH\xce" ' " (ONE)=WAHN"
arrRules(232) = "#(ONE) =WAH\xce" ' "#(ONE) =WAHN"
arrRules(233) = "(OW)=O\xd7" ' "(OW)=OW"
arrRules(234) = " (OVER)=OW5VE\xd2" ' " (OVER)=OW5VER"
arrRules(235) = "PR(O)V=UW\xb4" ' "PR(O)V=UW4"
arrRules(236) = "(OV)=AH4\xd6" ' "(OV)=AH4V"
arrRules(237) = "(O)^%=OW\xb5" ' "(O)^%=OW5"
arrRules(238) = "(O)^EN=O\xd7" ' "(O)^EN=OW"
arrRules(239) = "(O)^I#=OW\xb5" ' "(O)^I#=OW5"
arrRules(240) = "(OL)D=OW4\xcc" ' "(OL)D=OW4L"
arrRules(241) = "(OUGHT)=AO5\xd4" ' "(OUGHT)=AO5T"
arrRules(242) = "(OUGH)=AH5\xc6" ' "(OUGH)=AH5F"
arrRules(243) = " (OU)=A\xd7" ' " (OU)=AW"
arrRules(244) = "H(OU)S#=AW\xb4" ' "H(OU)S#=AW4"
arrRules(245) = "(OUS)=AX\xd3" ' "(OUS)=AXS"
arrRules(246) = "(OUR)=OH\xd2" ' "(OUR)=OHR"
arrRules(247) = "(OULD)=UH5\xc4" ' "(OULD)=UH5D"
arrRules(248) = "(OU)^L=AH\xb5" ' "(OU)^L=AH5"
arrRules(249) = "(OUP)=UW5\xd0" ' "(OUP)=UW5P"
arrRules(250) = "(OU)=A\xd7" ' "(OU)=AW"
arrRules(251) = "(OY)=O\xd9" ' "(OY)=OY"
arrRules(252) = "(OING)=OW4IHN\xd8" ' "(OING)=OW4IHNX"
arrRules(253) = "(OI)=OY\xb5" ' "(OI)=OY5"
arrRules(254) = "(OOR)=OH5\xd2" ' "(OOR)=OH5R"
arrRules(255) = "(OOK)=UH5\xcb" ' "(OOK)=UH5K"
arrRules(256) = "F(OOD)=UW5\xc4" ' "F(OOD)=UW5D"
arrRules(257) = "L(OOD)=AH5\xc4" ' "L(OOD)=AH5D"
arrRules(258) = "M(OOD)=UW5\xc4" ' "M(OOD)=UW5D"
arrRules(259) = "(OOD)=UH5\xc4" ' "(OOD)=UH5D"
arrRules(260) = "F(OOT)=UH5\xd4" ' "F(OOT)=UH5T"
arrRules(261) = "(OO)=UW\xb5" ' "(OO)=UW5"
arrRules(262) = "(O\\')=O\xc8" ' "(O\\')=OH"
arrRules(263) = "(O)E=O\xd7" ' "(O)E=OW"
arrRules(264) = "(O) =O\xd7" ' "(O) =OW"
arrRules(265) = "(OA)=OW\xb4" ' "(OA)=OW4"
arrRules(266) = " (ONLY)=OW4NLI\xd9" ' " (ONLY)=OW4NLIY"
arrRules(267) = " (ONCE)=WAH4N\xd3" ' " (ONCE)=WAH4NS"
arrRules(268) = "(ON\\'T)=OW4N\xd4" ' "(ON\\'T)=OW4NT"
arrRules(269) = "C(O)N=A\xc1" ' "C(O)N=AA"
arrRules(270) = "(O)NG=A\xcf" ' "(O)NG=AO"
arrRules(271) = " :^(O)N=A\xc8" ' " :^(O)N=AH"
arrRules(272) = "I(ON)=U\xce" ' "I(ON)=UN"
arrRules(273) = "#:(ON)=U\xce" ' "#:(ON)=UN"
arrRules(274) = "#^(ON)=U\xce" ' "#^(ON)=UN"
arrRules(275) = "(O)ST=O\xd7" ' "(O)ST=OW"
arrRules(276) = "(OF)^=AO4\xc6" ' "(OF)^=AO4F"
arrRules(277) = "(OTHER)=AH5DHE\xd2" ' "(OTHER)=AH5DHER"
arrRules(278) = "R(O)B=RA\xc1" ' "R(O)B=RAA"
arrRules(279) = "^R(O):#=OW\xb5" ' "^R(O):#=OW5"
arrRules(280) = "(OSS) =AO5\xd3" ' "(OSS) =AO5S"
arrRules(281) = "#:^(OM)=AH\xcd" ' "#:^(OM)=AHM"
arrRules(282) = "(O)=A\xc1" ' "(O)=AA"

arrRules(283) = "]\xd0" ' "]P"
arrRules(284) = " (P) =PIY\xb4" ' " (P) =PIY4"
arrRules(285) = "(PH)=\xc6" ' "(PH)=F"
arrRules(286) = "(PEOPL)=PIY5PU\xcc" ' "(PEOPL)=PIY5PUL"
arrRules(287) = "(POW)=PAW\xb4" ' "(POW)=PAW4"
arrRules(288) = "(PUT) =PUH\xd4" ' "(PUT) =PUHT"
arrRules(289) = "(P)P\xbd" ' "(P)P="
arrRules(290) = "(P)S\xbd" ' "(P)S="
arrRules(291) = "(P)N\xbd" ' "(P)N="
arrRules(292) = "(PROF.)=PROHFEH4SE\xd2" ' "(PROF.)=PROHFEH4SER"
arrRules(293) = "(P)=\xd0" ' "(P)=P"

arrRules(294) = "]\xd1" ' "]Q"
arrRules(295) = " (Q) =KYUW\xb4" ' " (Q) =KYUW4"
arrRules(296) = "(QUAR)=KWOH5\xd2" ' "(QUAR)=KWOH5R"
arrRules(297) = "(QU)=K\xd7" ' "(QU)=KW"
arrRules(298) = "(Q)=\xcb" ' "(Q)=K"
arrRules(299) = "]\xd2" ' "]R"
arrRules(300) = " (R) =AA5\xd2" ' " (R) =AA5R"
arrRules(301) = " (RE)^#=RI\xd9" ' " (RE)^#=RIY"
arrRules(302) = "(R)R\xbd" ' "(R)R="
arrRules(303) = "(R)=\xd2" ' "(R)=R"

arrRules(304) = "]\xd3" ' "]S"
arrRules(305) = " (S) =EH4\xd3" ' " (S) =EH4S"
arrRules(306) = "(SH)=S\xc8" ' "(SH)=SH"
arrRules(307) = "#(SION)=ZHU\xce" ' "#(SION)=ZHUN"
arrRules(308) = "(SOME)=SAH\xcd" ' "(SOME)=SAHM"
arrRules(309) = "#(SUR)#=ZHE\xd2" ' "#(SUR)#=ZHER"
arrRules(310) = "(SUR)#=SHE\xd2" ' "(SUR)#=SHER"
arrRules(311) = "#(SU)#=ZHU\xd7" ' "#(SU)#=ZHUW"
arrRules(312) = "#(SSU)#=SHU\xd7" ' "#(SSU)#=SHUW"
arrRules(313) = "#(SED)=Z\xc4" ' "#(SED)=ZD"
arrRules(314) = "#(S)#=\xda" ' "#(S)#=Z"
arrRules(315) = "(SAID)=SEH\xc4" ' "(SAID)=SEHD"
arrRules(316) = "^(SION)=SHU\xce" ' "^(SION)=SHUN"
arrRules(317) = "(S)S\xbd" ' "(S)S="
arrRules(318) = ".(S) =\xda" ' ".(S) =Z"
arrRules(319) = "#:.E(S) =\xda" ' "#:.E(S) =Z"
arrRules(320) = "#:^#(S) =\xd3" ' "#:^#(S) =S"
arrRules(321) = "U(S) =\xd3" ' "U(S) =S"
arrRules(322) = " :#(S) =\xda" ' " :#(S) =Z"
arrRules(323) = "##(S) =\xda" ' "##(S) =Z"
arrRules(324) = " (SCH)=S\xcb" ' " (SCH)=SK"
arrRules(325) = "(S)C+\xbd" ' "(S)C+="
arrRules(326) = "#(SM)=ZU\xcd" ' "#(SM)=ZUM"
arrRules(327) = "#(SN)\\'=ZU\xcd" ' "#(SN)\\'=ZUM"
arrRules(328) = "(STLE)=SU\xcc" ' "(STLE)=SUL"
arrRules(329) = "(S)=\xd3" ' "(S)=S"

arrRules(330) = "]\xd4" ' "]T"
arrRules(331) = " (T) =TIY\xb4" ' " (T) =TIY4"
arrRules(332) = " (THE) #=DHI\xd9" ' " (THE) #=DHIY"
arrRules(333) = " (THE) =DHA\xd8" ' " (THE) =DHAX"
arrRules(334) = "(TO) =TU\xd8" ' "(TO) =TUX"
arrRules(335) = " (THAT)=DHAE\xd4" ' " (THAT)=DHAET"
arrRules(336) = " (THIS) =DHIH\xd3" ' " (THIS) =DHIHS"
arrRules(337) = " (THEY)=DHE\xd9" ' " (THEY)=DHEY"
arrRules(338) = " (THERE)=DHEH\xd2" ' " (THERE)=DHEHR"
arrRules(339) = "(THER)=DHE\xd2" ' "(THER)=DHER"
arrRules(340) = "(THEIR)=DHEH\xd2" ' "(THEIR)=DHEHR"
arrRules(341) = " (THAN) =DHAE\xce" ' " (THAN) =DHAEN"
arrRules(342) = " (THEM) =DHAE\xce" ' " (THEM) =DHAEN"
arrRules(343) = "(THESE) =DHIY\xda" ' "(THESE) =DHIYZ"
arrRules(344) = " (THEN)=DHEH\xce" ' " (THEN)=DHEHN"
arrRules(345) = "(THROUGH)=THRUW\xb4" ' "(THROUGH)=THRUW4"
arrRules(346) = "(THOSE)=DHOH\xda" ' "(THOSE)=DHOHZ"
arrRules(347) = "(THOUGH) =DHO\xd7" ' "(THOUGH) =DHOW"
arrRules(348) = "(TODAY)=TUXDE\xd9" ' "(TODAY)=TUXDEY"
arrRules(349) = "(TOMO)RROW=TUMAA\xb5" ' "(TOMO)RROW=TUMAA5"
arrRules(350) = "(TO)TAL=TOW\xb5" ' "(TO)TAL=TOW5"
arrRules(351) = " (THUS)=DHAH4\xd3" ' " (THUS)=DHAH4S"
arrRules(352) = "(TH)=T\xc8" ' "(TH)=TH"
arrRules(353) = "#:(TED)=TIX\xc4" ' "#:(TED)=TIXD"
arrRules(354) = "S(TI)#N=C\xc8" ' "S(TI)#N=CH"
arrRules(355) = "(TI)O=S\xc8" ' "(TI)O=SH"
arrRules(356) = "(TI)A=S\xc8" ' "(TI)A=SH"
arrRules(357) = "(TIEN)=SHU\xce" ' "(TIEN)=SHUN"
arrRules(358) = "(TUR)#=CHE\xd2" ' "(TUR)#=CHER"
arrRules(359) = "(TU)A=CHU\xd7" ' "(TU)A=CHUW"
arrRules(360) = " (TWO)=TU\xd7" ' " (TWO)=TUW"
arrRules(361) = "&(T)EN \xbd" ' "&(T)EN ="
arrRules(362) = "(T)=\xd4" ' "(T)=T"

arrRules(363) = "]\xd5" ' "]U"
arrRules(364) = " (U) =YUW\xb4" ' " (U) =YUW4"
arrRules(365) = " (UN)I=YUW\xce" ' " (UN)I=YUWN"
arrRules(366) = " (UN)=AH\xce" ' " (UN)=AHN"
arrRules(367) = " (UPON)=AXPAO\xce" ' " (UPON)=AXPAON"
arrRules(368) = "@(UR)#=UH4\xd2" ' "@(UR)#=UH4R"
arrRules(369) = "(UR)#=YUH4\xd2" ' "(UR)#=YUH4R"
arrRules(370) = "(UR)=E\xd2" ' "(UR)=ER"
arrRules(371) = "(U)^ =A\xc8" ' "(U)^ =AH"
arrRules(372) = "(U)^^=AH\xb5" ' "(U)^^=AH5"
arrRules(373) = "(UY)=AY\xb5" ' "(UY)=AY5"
arrRules(374) = " G(U)#\xbd" ' " G(U)#="
arrRules(375) = "G(U)%\xbd" ' "G(U)%="
arrRules(376) = "G(U)#=\xd7" ' "G(U)#=W"
arrRules(377) = "#N(U)=YU\xd7" ' "#N(U)=YUW"
arrRules(378) = "@(U)=U\xd7" ' "@(U)=UW"
arrRules(379) = "(U)=YU\xd7" ' "(U)=YUW"

arrRules(380) = "]\xd6" ' "]V"
arrRules(381) = " (V) =VIY\xb4" ' " (V) =VIY4"
arrRules(382) = "(VIEW)=VYUW\xb5" ' "(VIEW)=VYUW5"
arrRules(383) = "(V)=\xd6" ' "(V)=V"

arrRules(384) = "]\xd7" ' "]W"
arrRules(385) = " (W) =DAH4BULYU\xd7" ' " (W) =DAH4BULYUW"
arrRules(386) = " (WERE)=WE\xd2" ' " (WERE)=WER"
arrRules(387) = "(WA)SH=WA\xc1" ' "(WA)SH=WAA"
arrRules(388) = "(WA)ST=WE\xd9" ' "(WA)ST=WEY"
arrRules(389) = "(WA)S=WA\xc8" ' "(WA)S=WAH"
arrRules(390) = "(WA)T=WA\xc1" ' "(WA)T=WAA"
arrRules(391) = "(WHERE)=WHEH\xd2" ' "(WHERE)=WHEHR"
arrRules(392) = "(WHAT)=WHAH\xd4" ' "(WHAT)=WHAHT"
arrRules(393) = "(WHOL)=/HOW\xcc" ' "(WHOL)=/HOWL"
arrRules(394) = "(WHO)=/HU\xd7" ' "(WHO)=/HUW"
arrRules(395) = "(WH)=W\xc8" ' "(WH)=WH"
arrRules(396) = "(WAR)#=WEH\xd2" ' "(WAR)#=WEHR"
arrRules(397) = "(WAR)=WAO\xd2" ' "(WAR)=WAOR"
arrRules(398) = "(WOR)^=WE\xd2" ' "(WOR)^=WER"
arrRules(399) = "(WR)=\xd2" ' "(WR)=R"
arrRules(400) = "(WOM)A=WUH\xcd" ' "(WOM)A=WUHM"
arrRules(401) = "(WOM)E=WIH\xcd" ' "(WOM)E=WIHM"
arrRules(402) = "(WEA)R=WE\xc8" ' "(WEA)R=WEH"
arrRules(403) = "(WANT)=WAA5N\xd4" ' "(WANT)=WAA5NT"
arrRules(404) = "ANS(WER)=E\xd2" ' "ANS(WER)=ER"
arrRules(405) = "(W)=\xd7" ' "(W)=W"

arrRules(406) = "]\xd8" ' "]X"
arrRules(407) = " (X) =EH4K\xd2" ' " (X) =EH4KR"
arrRules(408) = " (X)=\xda" ' " (X)=Z"
arrRules(409) = "(X)=K\xd3" ' "(X)=KS"

arrRules(410) = "]\xd9" ' "]Y"
arrRules(411) = " (Y) =WAY\xb4" ' " (Y) =WAY4"
arrRules(412) = "(YOUNG)=YAHN\xd8" ' "(YOUNG)=YAHNX"
arrRules(413) = " (YOUR)=YOH\xd2" ' " (YOUR)=YOHR"
arrRules(414) = " (YOU)=YU\xd7" ' " (YOU)=YUW"
arrRules(415) = " (YES)=YEH\xd3" ' " (YES)=YEHS"
arrRules(416) = " (Y)=\xd9" ' " (Y)=Y"
arrRules(417) = "F(Y)=A\xd9" ' "F(Y)=AY"
arrRules(418) = "PS(YCH)=AY\xcb" ' "PS(YCH)=AYK"
arrRules(419) = "#:^(Y)=I\xd9" ' "#:^(Y)=IY"
arrRules(420) = "#:^(Y)I=I\xd9" ' "#:^(Y)I=IY"
arrRules(421) = " :(Y) =A\xd9" ' " :(Y) =AY"
arrRules(422) = " :(Y)#=A\xd9" ' " :(Y)#=AY"
arrRules(423) = " :(Y)^+:#=I\xc8" ' " :(Y)^+:#=IH"
arrRules(424) = " :(Y)^#=A\xd9" ' " :(Y)^#=AY"
arrRules(425) = "(Y)=I\xc8" ' "(Y)=IH"

arrRules(426) = "]\xda" ' "]Z"
arrRules(427) = " (Z) =ZIY\xb4" ' " (Z) =ZIY4"
arrRules(428) = "(Z)=\xda" ' "(Z)=Z"

arrRules(429) = "]\xb0" ' "]0"
arrRules(430) = "(A)\xbd" ' "(A)="
arrRules(431) = "(!)=\xae" ' "(!)=."
arrRules(432) = "(\" + Chr$(34) + ") =-AH5NKWOWT\xad" ' "(\") =-AH5NKWOWT-"
arrRules(433) = "(\" + Chr$(34) + ")=KWOW4T\xad" ' "(\")=KWOW4T-"
arrRules(434) = "(#)= NAH4MBE\xd2" ' "(#)= NAH4MBER"
arrRules(435) = "($)= DAA4LE\xd2" ' "($)= DAA4LER"
arrRules(436) = "(%)= PERSEH4N\xd4" ' "(%)= PERSEH4NT"
arrRules(437) = "(&)= AEN\xc4" ' "(&)= AEND"
arrRules(438) = "(\\)\xbd" ' "(\\)="
arrRules(439) = "(*)= AE4STERIHS\xcb" ' "(*)= AE4STERIHSK"
arrRules(440) = "(+)= PLAH4\xd3" ' "(+)= PLAH4S"
arrRules(441) = "(,)=\xac" ' "(,)=,"
arrRules(442) = " (-) =\xad" ' " (-) =-"
arrRules(443) = "(-)\xbd" ' "(-)="
arrRules(444) = "(.)= POYN\xd4" ' "(.)= POYNT"
arrRules(445) = "(/)= SLAE4S\xc8" ' "(/)= SLAE4SH"
arrRules(446) = "(0)= ZIY4RO\xd7" ' "(0)= ZIY4ROW"
arrRules(447) = " (1ST)=FER4S\xd4" ' " (1ST)=FER4ST"
arrRules(448) = " (10TH)=TEH4NT\xc8" ' " (10TH)=TEH4NTH"
arrRules(449) = "(1)= WAH4\xce" ' "(1)= WAH4N"
arrRules(450) = " (2ND)=SEH4KUN\xc4" ' " (2ND)=SEH4KUND"
arrRules(451) = "(2)= TUW\xb4" ' "(2)= TUW4"
arrRules(452) = " (3RD)=THER4\xc4" ' " (3RD)=THER4D"
arrRules(453) = "(3)= THRIY\xb4" ' "(3)= THRIY4"
arrRules(454) = "(4)= FOH4\xd2" ' "(4)= FOH4R"
arrRules(455) = " (5TH)=FIH4FT\xc8" ' " (5TH)=FIH4FTH"
arrRules(456) = "(5)= FAY4\xd6" ' "(5)= FAY4V"
arrRules(457) = " (64) =SIH4KSTIY FOH\xd2" ' " (64) =SIH4KSTIY FOHR"
arrRules(458) = "(6)= SIH4K\xd3" ' "(6)= SIH4KS"
arrRules(459) = "(7)= SEH4VU\xce" ' "(7)= SEH4VUN"
arrRules(460) = " (8TH)=EY4T\xc8" ' " (8TH)=EY4TH"
arrRules(461) = "(8)= EY4\xd4" ' "(8)= EY4T"
arrRules(462) = "(9)= NAY4\xce" ' "(9)= NAY4N"
arrRules(463) = "(:)=\xae" ' "(:)=."
arrRules(464) = "(;)=\xae" ' "(;)=."
arrRules(465) = "(<)= LEH4S DHAE\xce" ' "(<)= LEH4S DHAEN"
arrRules(466) = "(=)= IY4KWUL\xda" ' "(=)= IY4KWULZ"
arrRules(467) = "(>)= GREY4TER DHAE\xce" ' "(>)= GREY4TER DHAEN"
arrRules(468) = "(?)=\xbf" ' "(?)=?"
arrRules(469) = "(@)= AE6\xd4" ' "(@)= AE6T"
arrRules(470) = "(^)= KAE4RIX\xd4" ' "(^)= KAE4RIXT"
arrRules(471) = "(')\xbd" ' "(')="
arrRules(472) = "(`)\xbd" ' "(`)="

arrRules(473) = "]\xb1" ' "]1'
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
' END rules
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------

' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
' BEGIN rule_tab
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
ReDim arrRuleTab(0 To 27) As Integer
rule_tabData:
data &H00, &H195, &H1f7, &H2a2, &H33f, &H4c6, &H507, &H57f
data &H5c8, &H728, &H739, &H750, &H793, &H7f3, &H857, &Haa5
data &Hb02, &Hb28, &Hb49, &Hc32, &Hdac, &He3b, &He58, &Hf33
data &Hf4c, &Hfdf, &Hff0, &H11b7
restore rule_tabData
For iIndex1 = 0 To 27
    Read arrRuleTab(iIndex1)
Next iIndex1

' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
' END rule_tab
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------


' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' END reciter_tabs.h
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' BEGIN reciter.c
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

'TODO: RECONCILE
' *** A AND Y ARE DECLARED AS uint32 IN sam.c
'uint32_t A;
'uint8_t X;
'uint32_t Y;

' secure copy of input because input will be overwritten by phonemes
'static uint8_t inputtemp[1024]; // secure copy of input tab36096
redim arrInputTemp$(1024) ' secure copy of input tab36096

' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' END reciter.c
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' BEGIN render_tabs.h
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
' BEGIN tab48426
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
'const uint8_t tab48426[5] = { 0x18, 0x1A, 0x17, 0x17, 0x17 };
ReDim arrTab48426(4) As _Byte ' Equivalent to uint8_t[5]
tab48426Data:
Data &H18, &H1A, &H17, &H17, &H17
restore tab48426Data
For iIndex1 = 0 To 4
    Read arrTab48426(iIndex1)
Next iIndex1
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
' END tab48426
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------

' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
' BEGIN tab47492
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
'const uint8_t tab47492[] = {
ReDim arrTab47492(10) As _Byte ' <-- Equivalent to uint8_t[], 11 elements
tab47492Data:
data 0, 0, &HE0, &HE6, &HEC, &HF3, &HF9, 0,
data 6, &HC, 6
restore tab47492Data
For iIndex1 = 0 To 10
    Read arrTab47492(iIndex1)
Next iIndex1
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
' END tab47492
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------

' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
' BEGIN amplitudeRescale
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
'const uint8_t amplitudeRescale[] = {
ReDim arrAmplitudeRescale(16) As _Byte ' <-- Equivalent to uint8_t[], 17 elements
amplitudeRescaleData:
Data 0, 1, 2, 2, 2, 3, 3, 4
Data 4, 5, 6, 8, 9, &HB, &HD, &HF, 0
' //17 elements?
restore amplitudeRescaleData
For iIndex1 = 0 To 16
    Read arrAmplitudeRescale(iIndex1)
Next iIndex1


' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
' END amplitudeRescale
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------

' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
' BEGIN blendRank
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
' Used to decide which phoneme's blend lengths. The candidate with the lower score is selected.
' tab45856
'const uint8_t blendRank[] = {
ReDim arrBlendRank(79) As _Byte ' <-- Equivalent to uint8_t[], 80 elements
blendRankData:
Data 0, &H1F, &H1F, &H1F, &H1F, 2, 2, 2
Data 2, 2, 2, 2, 2, 2, 5, 5
Data 2, &HA, 2, 8, 5, 5, &HB, &HA
Data 9, 8, 8, &HA0, 8, 8, &H17, &H1F
Data &H12, &H12, &H12, &H12, &H1E, &H1E, &H14, &H14
Data &H14, &H14, &H17, &H17, &H1A, &H1A, &H1D, &H1D
Data 2, 2, 2, 2, 2, 2, &H1A, &H1D
Data &H1B, &H1A, &H1D, &H1B, &H1A, &H1D, &H1B, &H1A
Data &H1D, &H1B, &H17, &H1D, &H17, &H17, &H1D, &H17
Data &H17, &H1D, &H17, &H17, &H1D, &H17, &H17, &H17

Restore blendRankData
For iIndex1 = 0 To 79
    Read arrBlendRank(iIndex1)
Next iIndex1

' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
' END blendRank
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------

' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
' BEGIN outBlendLength
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
' Number of frames at the end of a phoneme devoted to interpolating to next phoneme's final value
' tab45696
'const uint8_t outBlendLength[] = {
ReDim arrOutBlendLength(95) As _Unsigned _Byte
outBlendLengthData:
Data 0, 2, 2, 2, 2, 4, 4, 4
Data 4, 4, 4, 4, 4, 4, 4, 4
Data 4, 4, 3, 2, 4, 4, 2, 2
Data 2, 2, 2, 1, 1, 1, 1, 1
Data 1, 1, 1, 1, 1, 1, 2, 2
Data 2, 1, 0, 1, 0, 1, 0, 5
Data 5, 5, 5, 5, 4, 4, 2, 0
Data 1, 2, 0, 1, 2, 0, 1, 2
Data 0, 1, 2, 0, 2, 2, 0, 1
Data 3, 0, 2, 3, 0, 2, &HA0, &HA0
Restore outBlendLengthData
For iIndex1 = 0 To 95
    Read arrOutBlendLength(iIndex1)
Next iIndex1
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
' END outBlendLength
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------

' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
' BEGIN inBlendLength
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
' Number of frames at beginning of a phoneme devoted to interpolating to phoneme's final value
' tab45776
'const uint8_t inBlendLength[] = {
ReDim arrInBlendLength(95) As _Unsigned _Byte
inBlendLengthData:
data 0, 2, 2, 2, 2, 4, 4, 4
data 4, 4, 4, 4, 4, 4, 4, 4
data 4, 4, 3, 3, 4, 4, 3, 3
data 3, 3, 3, 1, 2, 3, 2, 1
data 3, 3, 3, 3, 1, 1, 3, 3
data 3, 2, 2, 3, 2, 3, 0, 0
data 5, 5, 5, 5, 4, 4, 2, 0
data 2, 2, 0, 3, 2, 0, 4, 2
data 0, 3, 2, 0, 2, 2, 0, 2
data 3, 0, 3, 3, 0, 3, &HB0, &HA0

Restore inBlendLengthData
For iIndex1 = 0 To 95
    Read arrInBlendLength(iIndex1)
Next iIndex1
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
' END inBlendLength
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------

' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
' BEGIN sampledConsonantFlags
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------

' Looks like it's used as bit flags
' High bits masked by 248 (11111000)
'
' 32: S*    241         11110001
' 33: SH    226         11100010
' 34: F*    211         11010011
' 35: TH    187         10111011
' 36: /H    124         01111100
' 37: /X    149         10010101
' 38: Z*    1           00000001
' 39: ZH    2           00000010
' 40: V*    3           00000011
' 41: DH    3           00000011
' 43: **    114         01110010
' 45: **    2           00000010
' 67: **    27          00011011
' 70: **    25          00011001

' tab45936
'const uint8_t sampledConsonantFlags[] = {
ReDim arrSampledConsonantFlags(79) As _Unsigned _Byte
sampledConsonantFlagsData:
Data 0, 0, 0, 0, 0, 0, 0, 0
Data 0, 0, 0, 0, 0, 0, 0, 0
Data 0, 0, 0, 0, 0, 0, 0, 0
Data 0, 0, 0, 0, 0, 0, 0, 0
Data &HF1, &HE2, &HD3, &HBB, &H7C, &H95, 1, 2
Data 3, 3, 0, &H72, 0, 2, 0, 0
Data 0, 0, 0, 0, 0, 0, 0, 0
Data 0, 0, 0, 0, 0, 0, 0, 0
Data 0, 0, 0, &H1B, 0, 0, &H19, 0
Data 0, 0, 0, 0, 0, 0, 0, 0

restore sampledConsonantFlagsData
For iIndex1 = 0 To 79
    Read arrSampledConsonantFlags(iIndex1)
Next iIndex1
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
' END sampledConsonantFlags
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------

' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
' BEGIN freq1data
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
'tab45056
'note: non const

'uint8_t freq1data[] = {
'ReDim arrFreq1Data(53) As _Byte
ReDim arrFreq1Data(71) As _Unsigned _Byte
freq1dataData:
Data &H00,&H13,&H13,&H13,&H13,&HA,&HE,&H12,&H18,&H1A,&H16,&H14,&H10,&H14,&HE,&H12,&HE,&H12,&H12,&H10,&HC,&HE,&HA,&H12,&HE,&HA,8,6,6,6,6,&H11,6,6,6,6,&HE,&H10,9,&HA,8,&HA,6,6,6,5,6,0,&H12,&H1A,&H14,&H1A,&H12,&HC,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,&HA,&HA,6,6,6,&H2C,&H13
restore freq1dataData
For iIndex1 = 0 To 71
    Read arrFreq1Data(iIndex1)
Next iIndex1
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
' END freq1data
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------

' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
' BEGIN arrFreq2Data
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
'tab451356
' note: non const
'uint8_t freq2data[] = {
'ReDim arrFreq2Data(53) As _Byte
ReDim arrFreq2Data(79) As _Unsigned _Byte
freq2dataData:
data &H00,&H43,&H43,&H43,&H43,&H54,&H48,&H42
data &H3E,&H28,&H2C,&H1E,&H24,&H2C,&H48,&H30
data &H24,&H1E,&H32,&H24,&H1C,&H44,&H18,&H32
data &H1E,&H18,&H52,&H2E,&H36,&H56,&H36,&H43
data &H49,&H4F,&H1A,&H42,&H49,&H25,&H33,&H42
data &H28,&H2F,&H4F,&H4F,&H42,&H4F,&H6E,&H00
data &H48,&H26,&H1E,&H2A,&H1E,&H22,&H1A,&H1A
data &H1A,&H42,&H42,&H42,&H6E,&H6E,&H6E,&H54
data &H54,&H54,&H1A,&H1A,&H1A,&H42,&H42,&H42
data &H6D,&H56,&H6D,&H54,&H54,&H54,&H7F,&H7F

restore freq2dataData
For iIndex1 = 60 To 79
    Read arrFreq2Data(iIndex1)
Next iIndex1
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
' END arrFreq2Data
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------

' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
' BEGIN freq3data
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
'tab45216
'const uint8_t freq3data[] = {
ReDim arrFreq3Data(79) As _Unsigned _Byte
freq3dataData:
data &H00, &H5B, &H5B, &H5B, &H5B, &H6E, &H5D, &H5B
data &H58, &H59, &H57, &H58, &H52, &H59, &H5D, &H3E
data &H52, &H58, &H3E, &H6E, &H50, &H5D, &H5A, &H3C
data &H6E, &H5A, &H6E, &H51, &H79, &H65, &H79, &H5B
data &H63, &H6A, &H51, &H79, &H5D, &H52, &H5D, &H67
data &H4C, &H5D, &H65, &H65, &H79, &H65, &H79, &H00
data &H5A, &H58, &H58, &H58, &H58, &H52, &H51, &H51
data &H51, &H79, &H79, &H79, &H70, &H6E, &H6E, &H5E
data &H5E, &H5E, &H51, &H51, &H51, &H79, &H79, &H79
data &H65, &H65, &H70, &H5E, &H5E, &H5E, &H08, &H01
restore freq3dataData
For iIndex1 = 0 To 79
    Read arrFreq3Data(iIndex1)
Next iIndex1
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
' END freq3data
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------

' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
' BEGIN ampl1data
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
ReDim arrAmp1Data(79) As _Byte
ampl1dataData:
data 0, 0, 0, 0, 0, &HD, &HD, &HE
data &HF, &HF, &HF, &HF, &HF, &HC, &HD, &HC
data &HF, &HF, &HD, &HD, &HD, &HE, &HD, &HC
data &HD, &HD, &HD, &HC, 9, 9, 0, 0
data 0, 0, 0, 0, 0, 0, &HB, &HB
data &HB, &HB, 0, 0, 1, &HB, 0, 2
data &HE, &HF, &HF, &HF, &HF, &HD, 2, 4
data 0, 2, 4, 0, 1, 4, 0, 1
data 4, 0, 0, 0, 0, 0, 0, 0
data 0, &HC, 0, 0, 0, 0, &HF, &HF
restore ampl1dataData
For iIndex1 = 0 To 79
    Read arrAmp1Data(iIndex1)
Next iIndex1
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
' END ampl1data
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------

' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
' BEGIN ampl2data
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
ReDim arrAmp2Data(79) As _Byte
ampl2dataData:
data 0, 0, 0, 0, 0, &HA, &HB, &HD
data &HE, &HD, &HC, &HC, &HB, 9, &HB, &HB
data &HC, &HC, &HC, 8, 8, &HC, 8, &HA
data 8, 8, &HA, 3, 9, 6, 0, 0
data 0, 0, 0, 0, 0, 0, 3, 5
data 3, 4, 0, 0, 0, 5, &HA, 2
data &HE, &HD, &HC, &HD, &HC, 8, 0, 1
data 0, 0, 1, 0, 0, 1, 0, 0
data 1, 0, 0, 0, 0, 0, 0, 0
data 0, &HA, 0, 0, &HA, 0, 0, 0
restore ampl2dataData
For iIndex1 = 0 To 79
    Read arrAmp2Data(iIndex1)
Next iIndex1
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
' END ampl2data
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------

' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
' BEGIN ampl3data
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
ReDim arrAmp3Data(79) As _Byte
ampl3dataData:
data 0, 0, 0, 0, 0, 8, 7, 8
data 8, 1, 1, 0, 1, 0, 7, 5
data 1, 0, 6, 1, 0, 7, 0, 5
data 1, 0, 8, 0, 0, 3, 0, 0
data 0, 0, 0, 0, 0, 0, 0, 1
data 0, 0, 0, 0, 0, 1, &HE, 1
data 9, 1, 0, 1, 0, 0, 0, 0
data 0, 0, 0, 0, 0, 0, 0, 0
data 0, 0, 0, 0, 0, 0, 0, 0
data 0, 7, 0, 0, 5, 0, &H13, &H10
restore ampl3dataData
For iIndex1 = 0 To 79
    Read arrAmp3Data(iIndex1)
Next iIndex1
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
' END ampl3data
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------

' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
' BEGIN sinus
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
ReDim arrSinus(255) As _Unsigned _Byte

sinusData:

data &H00, &H00, &H00, &H10, &H10, &H10, &H10, &H10
data &H10, &H20, &H20, &H20, &H20, &H20, &H20, &H30
data &H30, &H30, &H30, &H30, &H30, &H30, &H40, &H40
data &H40, &H40, &H40, &H40, &H40, &H50, &H50, &H50
data &H50, &H50, &H50, &H50, &H50, &H60, &H60, &H60
data &H60, &H60, &H60, &H60, &H60, &H60, &H60, &H60
data &H60, &H70, &H70, &H70, &H70, &H70, &H70, &H70
data &H70, &H70, &H70, &H70, &H70, &H70, &H70, &H70
data &H70, &H70, &H70, &H70, &H70, &H70, &H70, &H70
data &H70, &H70, &H70, &H70, &H70, &H70, &H70, &H70
data &H60, &H60, &H60, &H60, &H60, &H60, &H60, &H60
data &H60, &H60, &H60, &H60, &H50, &H50, &H50, &H50
data &H50, &H50, &H50, &H50, &H40, &H40, &H40, &H40
data &H40, &H40, &H40, &H30, &H30, &H30, &H30, &H30
data &H30, &H30, &H20, &H20, &H20, &H20, &H20, &H20
data &H10, &H10, &H10, &H10, &H10, &H10, &H00, &H00
data &H00, &H00, &H00, &HF0, &HF0, &HF0, &HF0, &HF0
data &HF0, &HE0, &HE0, &HE0, &HE0, &HE0, &HE0, &HD0
data &HD0, &HD0, &HD0, &HD0, &HD0, &HD0, &HC0, &HC0
data &HC0, &HC0, &HC0, &HC0, &HC0, &HB0, &HB0, &HB0
data &HB0, &HB0, &HB0, &HB0, &HB0, &HA0, &HA0, &HA0
data &HA0, &HA0, &HA0, &HA0, &HA0, &HA0, &HA0, &HA0
data &HA0, &H90, &H90, &H90, &H90, &H90, &H90, &H90
data &H90, &H90, &H90, &H90, &H90, &H90, &H90, &H90
data &H90, &H90, &H90, &H90, &H90, &H90, &H90, &H90
data &H90, &H90, &H90, &H90, &H90, &H90, &H90, &H90
data &HA0, &HA0, &HA0, &HA0, &HA0, &HA0, &HA0, &HA0
data &HA0, &HA0, &HA0, &HA0, &HB0, &HB0, &HB0, &HB0
data &HB0, &HB0, &HB0, &HB0, &HC0, &HC0, &HC0, &HC0
data &HC0, &HC0, &HC0, &HD0, &HD0, &HD0, &HD0, &HD0
data &HD0, &HD0, &HE0, &HE0, &HE0, &HE0, &HE0, &HE0
data &HF0, &HF0, &HF0, &HF0, &HF0, &HF0, &H00, &H00
restore sinusData
For iIndex1 = 0 To 255
    Read arrSinus(iIndex1)
Next iIndex1

' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
' END sinus
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------

' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
' BEGIN rectangle
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
'//tab42496
'const uint8_t rectangle[] = {
ReDim arrRectangle(255) As _Unsigned _Byte
rectangleData:
data &H90, &H90, &H90, &H90, &H90, &H90, &H90, &H90
data &H90, &H90, &H90, &H90, &H90, &H90, &H90, &H90
data &H90, &H90, &H90, &H90, &H90, &H90, &H90, &H90
data &H90, &H90, &H90, &H90, &H90, &H90, &H90, &H90
data &H90, &H90, &H90, &H90, &H90, &H90, &H90, &H90
data &H90, &H90, &H90, &H90, &H90, &H90, &H90, &H90
data &H90, &H90, &H90, &H90, &H90, &H90, &H90, &H90
data &H90, &H90, &H90, &H90, &H90, &H90, &H90, &H90
data &H90, &H90, &H90, &H90, &H90, &H90, &H90, &H90
data &H90, &H90, &H90, &H90, &H90, &H90, &H90, &H90
data &H90, &H90, &H90, &H90, &H90, &H90, &H90, &H90
data &H90, &H90, &H90, &H90, &H90, &H90, &H90, &H90
data &H90, &H90, &H90, &H90, &H90, &H90, &H90, &H90
data &H90, &H90, &H90, &H90, &H90, &H90, &H90, &H90
data &H90, &H90, &H90, &H90, &H90, &H90, &H90, &H90
data &H90, &H90, &H90, &H90, &H90, &H90, &H90, &H90
data &H70, &H70, &H70, &H70, &H70, &H70, &H70, &H70
data &H70, &H70, &H70, &H70, &H70, &H70, &H70, &H70
data &H70, &H70, &H70, &H70, &H70, &H70, &H70, &H70
data &H70, &H70, &H70, &H70, &H70, &H70, &H70, &H70
data &H70, &H70, &H70, &H70, &H70, &H70, &H70, &H70
data &H70, &H70, &H70, &H70, &H70, &H70, &H70, &H70
data &H70, &H70, &H70, &H70, &H70, &H70, &H70, &H70
data &H70, &H70, &H70, &H70, &H70, &H70, &H70, &H70
data &H70, &H70, &H70, &H70, &H70, &H70, &H70, &H70
data &H70, &H70, &H70, &H70, &H70, &H70, &H70, &H70
data &H70, &H70, &H70, &H70, &H70, &H70, &H70, &H70
data &H70, &H70, &H70, &H70, &H70, &H70, &H70, &H70
data &H70, &H70, &H70, &H70, &H70, &H70, &H70, &H70
data &H70, &H70, &H70, &H70, &H70, &H70, &H70, &H70
data &H70, &H70, &H70, &H70, &H70, &H70, &H70, &H70
data &H70, &H70, &H70, &H70, &H70, &H70, &H70, &H70
restore rectangleData
For iIndex1 = 0 To 255

    Read arrRectangle(iIndex1)
Next iIndex1
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
' END rectangle
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------

' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
' BEGIN multtable
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
'const uint8_t multtable[] = {
ReDim arrMultTable(255) As _Byte ' <-- QB64 uses byte for unsigned 8-bit
multtableData:
data &H00, &H00, &H00, &H00, &H00, &H00, &H00, &H00
data &H00, &H00, &H00, &H00, &H00, &H00, &H00, &H00
data &H00, &H00, 1, 1, 2, 2, 3, 3
data 4, 4, 5, 5, 6, 6, 7, 7
data 0, 1, 2, 3, 4, 5, 6, 7
data 8, 9, &HA, &HB, &HC, &HD, &HE, &HF
data &H00, 1, 3, 4, 6, 7, 9, &HA
data &HC, &HD, &HF, &H10, &H12, &H13, &H15, &H16
data &H00, 2, 4, 6, 8, &HA, &HC, &HE
data &H10, &H12, &H14, &H16, &H18, &H1A, &H1C, &H1E
data &H00, 2, 5, 7, &HA, &HC, &HF, &H11
data &H14, &H16, &H19, &H1B, &H1E, &H20, &H23, &H25
data &H00, 3, 6, 9, &HC, &HF, &H12, &H15
data &H18, &H1B, &H1E, &H21, &H24, &H27, &H2A, &H2D
data &H00, &H03, &H07, &H0A, &H0E, &H11, &H15, &H18
data &H1C, &H1F, &H23, &H26, &H2A, &H2D, &H31, &H34
data &H00, &HFC, &HF8, &HF4, &HF0, &HEC, &HE8, &HE4
data &HE0, &HDC, &HD8, &HD4, &HD0, &HCC, &HC8, &HC4
data &H00, &HFC, &HF9, &HF5, &HF2, &HEE, &HEB, &HE7
data &HE4, &HE0, &HDD, &HD9, &HD6, &HD2, &HCF, &HCB
data &H00, &HFD, &HFA, &HF7, &HF4, &HF1, &HEE, &HEB
data &HE8, &HE5, &HE2, &HDF, &HDC, &HD9, &HD6, &HD3
data &H00, &HFD, &HFB, &HF8, &HF6, &HF3, &HF1, &HEE
data &HEC, &HE9, &HE7, &HE4, &HE2, &HDF, &HDD, &HDA
data &H00, &HFE, &HFC, &HFA, &HF8, &HF6, &HF4, &HF2
data &HF0, &HEE, &HEC, &HEA, &HE8, &HE6, &HE4, &HE2
data &H00, &HFE, &HFD, &HFB, &HFA, &HF8, &HF7, &HF5
data &HF4, &HF2, &HF1, &HEF, &HEE, &HEC, &HEB, &HE9
data &H00, &HFF, &HFE, &HFD, &HFC, &HFB, &HFA, &HF9
data &HF8, &HF7, &HF6, &HF5, &HF4, &HF3, &HF2, &HF1
data &H00, &HFF, &HFF, &HFE, &HFE, &HFD, &HFD, &HFC
data &HFC, &HFB, &HFB, &HFA, &HFA, &HF9, &HF9, &HF8
restore multtableData
For iIndex1 = 0 To 255

    Read arrMultTable(iIndex1)
Next iIndex1
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
' END multtable
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------

' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
' BEGIN sampleTable
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
'const uint8_t sampleTable[0x500] = {
ReDim arrSampleTable(1279) As _Byte
SampleTableData:
' 00
Data &H38,&H84,&H6B,&H19,&HC6,&H63,&H18,&H86,&H73,&H98,&HC6,&HB1,&H1C,&HCA,&H31,&H8C,&HC7,&H31,&H88,&HC2,&H30,&H98,&H46,&H31,&H18,&HC6,&H35,&HC,&HCA,&H31,&HC,&HC6

' 20
Data &H21,&H10,&H24,&H69,&H12,&HC2,&H31,&H14,&HC4,&H71,&H08,&H4A,&H22,&H49,&HAB,&H6A,&HA8,&HAC,&H49,&H51,&H32,&HD5,&H52,&H88,&H93,&H6C,&H94,&H22,&H15,&H54,&HD2,&H25

' 40
Data &H96,&HD4,&H50,&HA5,&H46,&H21,&H08,&H85,&H6B,&H18,&HC4,&H63,&H10,&HCE,&H6B,&H18,&H8C,&H71,&H19,&H8C,&H63,&H35,&HC,&HC6,&H33,&H99,&HCC,&H6C,&HB5,&H4E,&HA2,&H99

' 60
Data &H46,&H21,&H28,&H82,&H95,&H2E,&HE3,&H30,&H9C,&HC5,&H30,&H9C,&HA2,&HB1,&H9C,&H67,&H31,&H88,&H66,&H59,&H2C,&H53,&H18,&H84,&H67,&H50,&HCA,&HE3,&HA,&HAC,&HAB,&H30

' 80
Data &HAC,&H62,&H30,&H8C,&H63,&H10,&H94,&H62,&HB1,&H8C,&H82,&H28,&H96,&H33,&H98,&HD6,&HB5,&H4C,&H62,&H29,&HA5,&H4A,&HB5,&H9C,&HC6,&H31,&H14,&HD6,&H38,&H9C,&H4B,&HB4

' A0
Data &H86,&H65,&H18,&HAE,&H67,&H1C,&HA6,&H63,&H19,&H96,&H23,&H19,&H84,&H13,&H08,&HA6,&H52,&HAC,&HCA,&H22,&H89,&H6E,&HAB,&H19,&H8C,&H62,&H34,&HC4,&H62,&H19,&H86,&H63

' C0
Data &H18,&HC4,&H23,&H58,&HD6,&HA3,&H50,&H42,&H54,&H4A,&HAD,&H4A,&H25,&H11,&H6B,&H64,&H89,&H4A,&H63,&H39,&H8A,&H23,&H31,&H2A,&HEA,&HA2,&HA9,&H44,&HC5,&H12,&HCD,&H42

' E0
Data &H34,&H8C,&H62,&H18,&H8C,&H63,&H11,&H48,&H66,&H31,&H9D,&H44,&H33,&H1D,&H46,&H31,&H9C,&HC6,&HB1,&HC,&HCD,&H32,&H88,&HC4,&H73,&H18,&H86,&H73,&H08,&HD6,&H63,&H58

' 100
Data &H07,&H81,&HE0,&HF0,&H3C,&H07,&H87,&H90,&H3C,&H7C,&HF,&HC7,&HC0,&HC0,&HF0,&H7C,&H1E,&H07,&H80,&H80,&H00,&H1C,&H78,&H70,&HF1,&HC7,&H1F,&HC0,&HC,&HFE,&H1C,&H1F

' 120
Data &H1F,&HE,&HA,&H7A,&HC0,&H71,&HF2,&H83,&H8F,&H03,&HF,&HF,&HC,&H00,&H79,&HF8,&H61,&HE0,&H43,&HF,&H83,&HE7,&H18,&HF9,&HC1,&H13,&HDA,&HE9,&H63,&H8F,&HF,&H83

' 140
Data &H83,&H87,&HC3,&H1F,&H3C,&H70,&HF0,&HE1,&HE1,&HE3,&H87,&HB8,&H71,&HE,&H20,&HE3,&H8D,&H48,&H78,&H1C,&H93,&H87,&H30,&HE1,&HC1,&HC1,&HE4,&H78,&H21,&H83,&H83,&HC3

' 160
Data &H87,&H06,&H39,&HE5,&HC3,&H87,&H07,&HE,&H1C,&H1C,&H70,&HF4,&H71,&H9C,&H60,&H36,&H32,&HC3,&H1E,&H3C,&HF3,&H8F,&HE,&H3C,&H70,&HE3,&HC7,&H8F,&HF,&HF,&HE,&H3C

' 180
Data &H78,&HF0,&HE3,&H87,&H06,&HF0,&HE3,&H07,&HC1,&H99,&H87,&HF,&H18,&H78,&H70,&H70,&HFC,&HF3,&H10,&HB1,&H8C,&H8C,&H31,&H7C,&H70,&HE1,&H86,&H3C,&H64,&H6C,&HB0,&HE1

' 1A0
Data &HE3,&HF,&H23,&H8F,&HF,&H1E,&H3E,&H38,&H3C,&H38,&H7B,&H8F,&H07,&HE,&H3C,&HF4,&H17,&H1E,&H3C,&H78,&HF2,&H9E,&H72,&H49,&HE3,&H25,&H36,&H38,&H58,&H39,&HE2,&HDE

' 1C0
Data &H3C,&H78,&H78,&HE1,&HC7,&H61,&HE1,&HE1,&HB0,&HF0,&HF0,&HC3,&HC7,&HE,&H38,&HC0,&HF0,&HCE,&H73,&H73,&H18,&H34,&HB0,&HE1,&HC7,&H8E,&H1C,&H3C,&HF8,&H38,&HF0,&HE1

' 1E0
Data &HC1,&H8B,&H86,&H8F,&H1C,&H78,&H70,&HF0,&H78,&HAC,&HB1,&H8F,&H39,&H31,&HDB,&H38,&H61,&HC3,&HE,&HE,&H38,&H78,&H73,&H17,&H1E,&H39,&H1E,&H38,&H64,&HE1,&HF1,&HC1

' 200
Data &H4E,&HF,&H40,&HA2,&H02,&HC5,&H8F,&H81,&HA1,&HFC,&H12,&H08,&H64,&HE0,&H3C,&H22,&HE0,&H45,&H07,&H8E,&HC,&H32,&H90,&HF0,&H1F,&H20,&H49,&HE0,&HF8,&HC,&H60,&HF0

' 220
Data &H17,&H1A,&H41,&HAA,&HA4,&HD0,&H8D,&H12,&H82,&H1E,&H1E,&H03,&HF8,&H3E,&H03,&HC,&H73,&H80,&H70,&H44,&H26,&H03,&H24,&HE1,&H3E,&H04,&H4E,&H04,&H1C,&HC1,&H09,&HCC

' 240
Data &H9E,&H90,&H21,&H07,&H90,&H43,&H64,&HC0,&HF,&HC6,&H90,&H9C,&HC1,&H5B,&H03,&HE2,&H1D,&H81,&HE0,&H5E,&H1D,&H03,&H84,&HB8,&H2C,&HF,&H80,&HB1,&H83,&HE0,&H30,&H41

' 260
Data &H1E,&H43,&H89,&H83,&H50,&HFC,&H24,&H2E,&H13,&H83,&HF1,&H7C,&H4C,&H2C,&HC9,&HD,&H83,&HB0,&HB5,&H82,&HE4,&HE8,&H06,&H9C,&H07,&HA0,&H99,&H1D,&H07,&H3E,&H82,&H8F

' 280
Data &H70,&H30,&H74,&H40,&HCA,&H10,&HE4,&HE8,&HF,&H92,&H14,&H3F,&H06,&HF8,&H84,&H88,&H43,&H81,&HA,&H34,&H39,&H41,&HC6,&HE3,&H1C,&H47,&H03,&HB0,&HB8,&H13,&HA,&HC2

' 2A0
Data &H64,&HF8,&H18,&HF9,&H60,&HB3,&HC0,&H65,&H20,&H60,&HA6,&H8C,&HC3,&H81,&H20,&H30,&H26,&H1E,&H1C,&H38,&HD3,&H01,&HB0,&H26,&H40,&HF4,&HB,&HC3,&H42,&H1F,&H85,&H32

' 2C0
Data &H26,&H60,&H40,&HC9,&HCB,&H01,&HEC,&H11,&H28,&H40,&HFA,&H04,&H34,&HE0,&H70,&H4C,&H8C,&H1D,&H07,&H69,&H03,&H16,&HC8,&H04,&H23,&HE8,&HC6,&H9A,&HB,&H1A,&H03,&HE0

' 2E0
Data &H76,&H06,&H05,&HCF,&H1E,&HBC,&H58,&H31,&H71,&H66,&H00,&HF8,&H3F,&H04,&HFC,&HC,&H74,&H27,&H8A,&H80,&H71,&HC2,&H3A,&H26,&H06,&HC0,&H1F,&H05,&HF,&H98,&H40,&HAE

' 300
Data &H01,&H7F,&HC0,&H07,&HFF,&H00,&HE,&HFE,&H00,&H03,&HDF,&H80,&H03,&HEF,&H80,&H1B,&HF1,&HC2,&H00,&HE7,&HE0,&H18,&HFC,&HE0,&H21,&HFC,&H80,&H3C,&HFC,&H40,&HE,&H7E

' 320
Data &H00,&H3F,&H3E,&H00,&HF,&HFE,&H00,&H1F,&HFF,&H00,&H3E,&HF0,&H07,&HFC,&H00,&H7E,&H10,&H3F,&HFF,&H00,&H3F,&H38,&HE,&H7C,&H01,&H87,&HC,&HFC,&HC7,&H00,&H3E,&H04

' 340
Data &HF,&H3E,&H1F,&HF,&HF,&H1F,&HF,&H02,&H83,&H87,&HCF,&H03,&H87,&HF,&H3F,&HC0,&H07,&H9E,&H60,&H3F,&HC0,&H03,&HFE,&H00,&H3F,&HE0,&H77,&HE1,&HC0,&HFE,&HE0,&HC3

' 360
Data &HE0,&H01,&HDF,&HF8,&H03,&H07,&H00,&H7E,&H70,&H00,&H7C,&H38,&H18,&HFE,&HC,&H1E,&H78,&H1C,&H7C,&H3E,&HE,&H1F,&H1E,&H1E,&H3E,&H00,&H7F,&H83,&H07,&HDB,&H87,&H83

' 380
Data &H07,&HC7,&H07,&H10,&H71,&HFF,&H00,&H3F,&HE2,&H01,&HE0,&HC1,&HC3,&HE1,&H00,&H7F,&HC0,&H05,&HF0,&H20,&HF8,&HF0,&H70,&HFE,&H78,&H79,&HF8,&H02,&H3F,&HC,&H8F,&H03

' 3a0
Data &HF,&H9F,&HE0,&HC1,&HC7,&H87,&H03,&HC3,&HC3,&HB0,&HE1,&HE1,&HC1,&HE3,&HE0,&H71,&HF0,&H00,&HFC,&H70,&H7C,&HC,&H3E,&H38,&HE,&H1C,&H70,&HC3,&HC7,&H03,&H81,&HC1

' 3c0
Data &HC7,&HE7,&H00,&HF,&HC7,&H87,&H19,&H09,&HEF,&HC4,&H33,&HE0,&HC1,&HFC,&HF8,&H70,&HF0,&H78,&HF8,&HF0,&H61,&HC7,&H00,&H1F,&HF8,&H01,&H7C,&HF8,&HF0,&H78,&H70,&H3C

' 3e0
Data &H7C,&HCE,&HE,&H21,&H83,&HCF,&H08,&H07,&H8F,&H08,&HC1,&H87,&H8F,&H80,&HC7,&HE3,&H00,&H07,&HF8,&HE0,&HEF,&H00,&H39,&HF7,&H80,&HE,&HF8,&HE1,&HE3,&HF8,&H21,&H9F

' 400
Data &HC0,&HFF,&H03,&HF8,&H07,&HC0,&H1F,&HF8,&HC4,&H04,&HFC,&HC4,&HC1,&HBC,&H87,&HF0,&HF,&HC0,&H7F,&H05,&HE0,&H25,&HEC,&HC0,&H3E,&H84,&H47,&HF0,&H8E,&H03,&HF8,&H03

' 420
Data &HFB,&HC0,&H19,&HF8,&H07,&H9C,&HC,&H17,&HF8,&H07,&HE0,&H1F,&HA1,&HFC,&HF,&HFC,&H01,&HF0,&H3F,&H00,&HFE,&H03,&HF0,&H1F,&H00,&HFD,&H00,&HFF,&H88,&HD,&HF9,&H01

' 440
Data &HFF,&H00,&H70,&H07,&HC0,&H3E,&H42,&HF3,&HD,&HC4,&H7F,&H80,&HFC,&H07,&HF0,&H5E,&HC0,&H3F,&H00,&H78,&H3F,&H81,&HFF,&H01,&HF8,&H01,&HC3,&HE8,&HC,&HE4,&H64,&H8F

' 460
Data &HE4,&HF,&HF0,&H07,&HF0,&HC2,&H1F,&H00,&H7F,&HC0,&H6F,&H80,&H7E,&H03,&HF8,&H07,&HF0,&H3F,&HC0,&H78,&HF,&H82,&H07,&HFE,&H22,&H77,&H70,&H02,&H76,&H03,&HFE,&H00

' 480
Data &HFE,&H67,&H00,&H7C,&HC7,&HF1,&H8E,&HC6,&H3B,&HE0,&H3F,&H84,&HF3,&H19,&HD8,&H03,&H99,&HFC,&H09,&HB8,&HF,&HF8,&H00,&H9D,&H24,&H61,&HF9,&HD,&H00,&HFD,&H03,&HF0

' 4a0
Data &H1F,&H90,&H3F,&H01,&HF8,&H1F,&HD0,&HF,&HF8,&H37,&H01,&HF8,&H07,&HF0,&HF,&HC0,&H3F,&H00,&HFE,&H03,&HF8,&HF,&HC0,&H3F,&H00,&HFA,&H03,&HF0,&HF,&H80,&HFF,&H01

' 4c0
Data &HB8,&H07,&HF0,&H01,&HFC,&H01,&HBC,&H80,&H13,&H1E,&H00,&H7F,&HE1,&H40,&H7F,&HA0,&H7F,&HB0,&H00,&H3F,&HC0,&H1F,&HC0,&H38,&HF,&HF0,&H1F,&H80,&HFF,&H01,&HFC,&H03

' 4e0
Data &HF1,&H7E,&H01,&HFE,&H01,&HF0,&HFF,&H00,&H7F,&HC0,&H1D,&H07,&HF0,&HF,&HC0,&H7E,&H06,&HE0,&H07,&HE0,&HF,&HF8,&H06,&HC1,&HFE,&H01,&HFC,&H03,&HE0,&HF,&H00,&HFC

Restore SampleTableData
For iIndex1 = 0 To 1279
    Read arrSampleTable(iIndex1)
Next iIndex1
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
' END sampleTable
' ----------------------------------------------------------------------------------------------------------------------------------------------------------------


' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' END render_tabs.h
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' BEGIN render.c
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
dim wait1 as integer ' uint8_t wait1 = 7;
wait1 = 7

dim wait2 as integer ' uint8_t wait2 = 6;
wait2 = 6

' A and Y are uint32 elsewhere:
' uint8_t A, X, Y;

ReDim arrPitches(255) As _Byte ' uint8_t pitches[256]; // tab43008

redim arrFrequency1(255) as integer ' uint8_t frequency1[256];
redim arrFrequency2(255) as integer ' uint8_t frequency2[256];
redim arrFrequency3(255) as integer ' uint8_t frequency3[256];

redim arrAmplitude1(255) as integer ' uint8_t amplitude1[256];
redim arrAmplitude2(255) as integer ' uint8_t amplitude2[256];
redim arrAmplitude3(255) as integer ' uint8_t amplitude3[256];

redim arrSampleConsonantFlag(255) as integer ' uint8_t sampledConsonantFlag[256]; // tab44800

//timetable for more accurate c64 simulation
redim arrTimeTable(4,4) as integer ' int32_t timetable[5][5] = {
timetableData:
data 162, 167, 167, 127, 128
data 226, 60, 60, 0, 0
data 225, 60, 59, 0, 0
data 200, 0, 0, 54, 55
data 199, 0, 0, 54, 54
restore timetableData
For iIndex1 = 0 To 4
    For iIndex2 = 0 To 4
        Read arrMultTable(iIndex1, iIndex2)
Next iIndex1

' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' END render.c
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++



























' *** HERE IS WHERE THE MAIN EXECUTION (MENU ETC.) WOULD GO #MAIN

' For now we'll hardcode the test routines to run...
TestHello

TestPhonemes

' *** END MAIN EXECUTION @MAIN












' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' Begin test_hello.c
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

' Main program
'int32_t test_hello_main(int32_t argc, int8_t** argv)
Sub TestHello
    Dim in$
    Input "Enter text to speak (all caps, include phonemes like '[')", in$

    ' Set the input (assuming SetInput$ function exists)
    ' in$ = "HELLO WORLD ["  ' Hardcoded input replaced by user input
    ' SetInput in$

    ' Simulate SetInput (replace with actual QB64 implementation if available)
    Print "Setting input to: "; in$

    ' Run SAMMain (assuming SAMMain function exists and returns 0 for false, non-zero for true)
    ' samResult = SAMMain()
    ' IF samResult = 0 THEN
    '    PRINT "SAMMain failed"
    '    SYSTEM
    ' END IF

    'Simulate SAMMain (replace with actual QB64 implementation)
    Print "Simulating SAMMain..."
    samResult = -1 ' Simulate success

    If samResult = 0 Then
        Print "SAMMain failed"
        End
    End If

    ' Get the buffer and its length (assuming these functions exist)
    ' buffer$ = GetBuffer$()
    ' bufferLength = GetBufferLength()

    'Simulate GetBuffer and GetBufferLength
    buffer$ = "Simulated speech data"
    bufferLength = 1000

    ' Call WriteWav
    wavResult = WriteWav(buffer$, bufferLength \ 50) ' Integer division in QB64 is '\'

    Print "WriteWav returned: "; wavResult

    Print "Done!"
    Sleep
    'END

End Sub ' TestHello

' Stub for WriteWav (since the C version just returns 0)
Function WriteWav% (buffer As String, bufferlength As Integer)
    WriteWav = 0
End Function


' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' End test_hello.c
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++






' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' Begin test_phonemes.c
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Sub TestPhonemes
    'Constants
   
    '#define END 0,0
    Const END_MARKER = "0,0" ' Using a string to represent the end marker
   
    '#define C_SIZE 1024
    Const C_SIZE = 1024
   
    ' *** IS THIS A STRING REPRESENTED BY A C ARRAY OR AN ACTUAL C ARRAY ??? ***
    'static char temp[C_SIZE];
    Dim sTemp As String ' * C_SIZE  ' Fixed-length string

   
    'Originally a 1-dimensional string array of {testInput1},{expected1},{testInput2},{expected2},...,{testInput{n}},{expected{n}}
    'Gemini refactored as 1-dimensional string array of type TestCase with each containing TestCase.testInput & testCase.expected
    'static const char * test_case[] = {
    Dim test_case(1 To 20) As TestCase ' Adjust size as needed based on your test data
    Dim test_state As TestState
   
   
    Dim state As TestState
    Dim iIndex1 As Integer
    Dim bResult As Integer

    ' *** NOTE
    ' PROBABLY NEED TO CALL Init BEFORE ANYTHING ?


    ' Initialize test cases (manually, since we can't directly translate C's array initialization)
    '------------------------------------------------------------------------------------------
    ' Manually populate the test cases.  This is tedious, but necessary in QB64.
    ' Note:  The index in QB64 starts at 1 by default, so adjust accordingly.
    ' Also, QB64 doesn't have direct equivalent for C's string literals with embedded newlines.
    '      We'll use multiline strings (might need QB64PE specific syntax) or concatenation.

    test_case(1).testInput = "HELLO"
    test_case(1).expected = " /HEHLOW"

    test_case(2).testInput = "WIZARD"
    test_case(2).expected = " WIHZAA5RD"

    test_case(3).testInput = "TWO THINGS"
    test_case(3).expected = " TUW THIHNXZ"

    test_case(4).testInput = "ANOTHER TRAVELER"
    test_case(4).expected = " AENAH5DHER TRAEVIY4LER"

    test_case(5).testInput = "HELLO, MY NAME IS SAM."
    test_case(5).expected = " /HEHLOW, MAY NEYM IHZ SAEM."

    test_case(6).testInput = "THE SKY ABOVE THE PORT WAS THE COLOR OF TELEVISION, TUNED TO A DEAD CHANNEL."
    test_case(6).expected = " DHAX SKAY AEBAH4V DHAX PAORT WAHZ DHAX KAALER AHV TEHLEHVIHZHUN, TUWND TUX AH DEHDCHAENEHL."

    test_case(7).testInput = "IT'S NOT LIKE I'M USING, CASE HEARD SOMEONE SAY, AS HE SHOULDERED HIS WAY THROUGH THE CROWD AROUND THE DOOR OF THE CHAT."
    test_case(7).expected = " IHTS NAAT LAY5K IHM YUWZIHNX, KEY4S /HIY5RD SAHMWAHN SEY5, AEZ /HIY SHUH5DIY4RD /HIHSWEY5 THRUW4 DHAX KROWD AXRAWND DHAX DOH5R AHV DHAX CHAET."

    test_case(8).testInput = "ITS LIKE MY BODYS DEVELOPED THIS MASSIVE DRUG DEFICIENCY."
    test_case(8).expected = " IHTS LAY5K MAY BAADIYS DIHVEHLOW5PT DHIHS MAESIHV DRAHG DIHFIHSHEHNSIY."

    test_case(9).testInput = "IT WAS A SPRAWL VOICE AND A SPRAWL JOKE."
    test_case(9).expected = " IHT WAHZ AH SPRAO5L VOY5S AEND AH SPRAO5L JOW5K."

    test_case(10).testInput = "THE CHATSUBO WAS A BAR FOR PROFESSIONAL EXPATRIATES YOU COULD DRINK THERE FOR A WEEK AND NEVER HEAR TWO WORDS IN JAPANESE."
    test_case(10).expected = " DHAX CHAETSUWBOW WAHZ AH BAA5R FAOR PROW5FEHSHUNUL EHKSPAETRIHEYTS YUW KUH5D DRIHNXK DHEHRFER AH WIY4K AEND NEH4VER /HIY5R TUW WERDZ IHN JAEPEYNIY4Z."

    test_case(11).testInput = "RATZ WAS TENDING BAR, HIS PROSTHETIC ARM JERKING MONOTONOUSLY AS HE FILLED A TRAY OF GLASSES WITH DRAFT KIRIN."
    test_case(11).expected = " RAETZ WAHZ TEHNDIHNX BAA5R, /HIHZ PROWSTHEHTIHK AA5RM JERKIHNX MAHNAATUNAXSLIY AEZ /HIY FIHLEHDAH TREY5 AHV GLAESIHZ WIHTH"

    test_case(12).testInput = "HE SAW CASE AND SMILED, HIS TEETH A WEB WORK OF EAST EUROPEAN STEEL AND BROWN DECAY."
    test_case(12).expected = " /HIY SAO5 KEY4S AEND SMAY5LD, /HIHZ TIY4TH AH WEHB WERK AHV IY5ST YUW5RAAPIY5N STIY4L AENDBROWN DIHKEY5."

    test_case(13).testInput = "CASE FOUND A PLACE AT THE BAR, BETWEEN THE UNLIKELY TAN ON ONE OF LONNY ZONE'S WHORES AND THE CRISP NAVAL UNIFORM OF A TALL AFRICAN WHOSE CHEEKBONES WERE RIDGED WITH PRECISE ROWS OF TRIBAL SCARS."
    test_case(13).expected = " KEY4S FAWND AH PLEYS AET DHAX BAA5R, BEHTWIY4N DHIY AHNLIHKLIY TAEN AAN WAHN AHV LAHNIYZUNEHS /HUWRZ AEND DHAX KRIHSP NAEVUL YUWNIHFAORM AHV AH TAOL AEFRIHKAEN /HUWZEHKIY4KBOW5NZ WER RIHDJD WIHTH PREHSAYZ ROWZ AHV TRIHBUL SKAA5RZ."

    test_case(14).testInput = "WAGE WAS IN HERE EARLY, WITH TWO JOE BOYS, RATZ SAID, SHOVING A DRAFT ACROSS THE BAR WITH HIS GOOD HAND."
    test_case(14).expected = " WEYJ WAHZ IHN /HIYR ER5LIY, WIHTH TUW JOW BOYZ, RAETZ SEHD, SHAH4VIHNX AH DRAEFTAEKRAO5S DHAX BAA5R WIHTH /HIHZ GUH5D /HAEND."

    test_case(15).testInput = "MAYBE SOME BUSINESS WITH YOU, CASE. CASE SHRUGGED."
    test_case(15).expected = " MEY5B SAHM BIH4ZIHNEHS WIHTH YUW, KEY4S. KEY4S SHRAH5GD."

    test_case(16).testInput = "THE GIRL TO HIS RIGHT GIGGLED AND NUDGED HIM."
    test_case(16).expected = " DHAX GERL TUX /HIHZ RAY4T GIHGULD AEND NAH5DJD /HIHM."

    ' Assuming END is a sentinel value, find the end of the data.
    last_test_case = 16 'Hardcoded for now, find a better way if possible

    'Main Program
    'No direct equivalent to C's main, so the following code is the main logic

    For iIndex1 = 1 To last_test_case
        ' call sam to process input, store in sTemp
        ' MOCKING sam and reciter calls for now
        sTemp = "MOCKED OUTPUT FOR: " + test_case(iIndex1).testInput ' Replace with actual SAM and reciter calls

        'trim ' Remove any trailing garbage from sTemp
        sTemp = _Trim$(sTemp)

        If compare%(sTemp, test_case(iIndex1).expected) Then
            test_state.passes = test_state.passes + 1
            Print "PASS: "; test_case(iIndex1).testInput
        Else
            test_state.fails = test_state.fails + 1
            Print "FAIL: "; test_case(iIndex1).testInput
            Print "  Expected: "; test_case(iIndex1).expected
            Print "  Actual:   "; sTemp
        End If

    Next iIndex1

    Print
    Print "--- SUMMARY ---"
    Print "Passes: "; test_state.passes
    Print "Fails:  "; test_state.fails

    'END 'End of main program

    ' Main program starts here
    ' Initialize state
    state.fails = 0
    state.passes = 0

    ' Verify reciter tables
    ReciterVerify

    ' Test cases (need to be adapted based on how test_case is structured)
    ' Example data - adjust as needed:
    Data "test1","expected1","test2","expected2",""
    Read test_case1$, test_case2$
    Do While Len(test_case1$) > 0
        If try_test$(test_case1$, test_case2$) = "0" Then
            Print "x";
            state.fails = state.fails + 1
        Else
            Print ".";
            state.passes = state.passes + 1
        End If
        Read test_case1$, test_case2$
    Loop

    ' Input test files (assuming SAM_TEST_DIR is a constant)
    ' *** NOT SURE WHAT file_test$ IS OR DOES ??? ***
    bResult = file_test%(m_ProgramPath$ + "words.txt", state) '  Need to adjust path as needed
    If bResult = _FALSE Then Print "File " + Chr$(34) + "words.txt" + Chr$(34) + " not found."

    bResult = file_test%(m_ProgramPath$ + "sentences.txt", state) ' Need to adjust path as needed
    If bResult = _FALSE Then Print "File " + Chr$(34) + "sentences.txt" + Chr$(34) + " not found."

    ' Print summary
    Print
    Print "total : "; state.fails + state.passes
    Print "failed: "; state.fails
    Print "passed: "; state.passes

    If state.fails > 0 Then
        Input "Press Enter to continue", a$
    End If

    'SYSTEM '  End program

End Sub ' TestPhonemes

'Function Definitions
Function compare% (sVal1 As String, sVal2 As String)
    Dim iPos1 As Integer
    Dim iPos2 As Integer
    Dim iLen1 As Integer
    Dim iLen2 As Integer

    compare% = _TRUE ' Default to true
    iLen1 = Len(sVal1)
    iLen2 = Len(sVal2)

    iPos1 = 1
    iPos2 = 1

    Do While iPos1 <= iLen1 And iPos2 <= iLen2

        If Mid$(sVal2, iPos2, 1) > Chr$(127) Then 'Simulate checking for 0x80 (not directly possible)
            Exit Do
        End If

        If Mid$(sVal1, iPos1, 1) <> Mid$(sVal2, iPos2, 1) Then
            compare% = _FALSE
            Exit Function
        End If
        iPos1 = iPos1 + 1
        iPos2 = iPos2 + 1
    Loop

    If iPos1 <= iLen1 Or (iPos2 <= iLen2 And Asc(Mid$(sVal2, iPos2, 1)) < 128) Then ' Check if either string has leftover
        compare% = _FALSE
    End If

End Function ' compare%



'SUB trim
'    FOR i = 1 TO LEN(temp)
'        IF ASC(MID$(temp, i, 1)) > 127 THEN  'Simulate checking for 0x80
'            temp = LEFT$(temp, i - 1)
'            EXIT SUB
'        END IF
'    NEXT i
'END SUB

' Function: try_test
' Tests a given input string against an expected phoneme output.
' Parameters:
'   in$ - The input string to convert to phonemes.
'   match$ - The expected phoneme output.
' Returns:
'   1 if the actual output matches the expected output, 0 otherwise.
Function try_test$ (in$, match$)
    ' Assuming C_SIZE is defined as a constant elsewhere (e.g., CONST C_SIZE = 256)
    Dim sTemp As String ' * 256 ' Adjust size as needed, using a fixed-length string

    sTemp = String$(256, 128) ' Initialize with ASCII 128 (0x80) -  QBasic/QB64 doesn't have memset like C
    sTemp = in$
    sTemp = sTemp + "["

    'max_size = 250
    If TextToPhonemes(sTemp, 250) < 1 Then
        try_test$ = "0"
        Exit Function
    End If
    sTemp = Left$(sTemp, 255) ' QB64 string length is limited; ensure null termination isn't an issue
    sTemp = _Trim$(sTemp) '  Need to implement a trim$ function in QB64

    'IF StrComp(match$, sTemp, 0) <> 0 THEN
    If compare%(match$, sTemp) <> 0 Then
        Print
        Print "sent"
        Print "'" + in$ + "'"
        Print "expected"
        Print "'" + match$ + "'"
        Print "got"
        Print "'" + sTemp + "'"
        try_test$ = "0"
        Exit Function
    End If

    try_test$ = "1"
End Function ' try_test$


' Function: read_line
' Reads a line from a file.
' Parameters:
'   fd - The file handle.
'   dst$ - The string to store the read line.
'   max_len - The maximum number of characters to read.  Not directly used in QB64 implementation
' Returns:
'   The length of the read line.
Function read_line% (fd As Long, dst$) ' QB64 doesn't have size_t, using INTEGER
    Dim ptr As Long
    Dim size As Integer
    Dim ch As String * 1

    size = 0
    Do
        If EOF(fd) Then
            read_line% = 0
            Exit Function
        End If
        Get #fd, , ch
        If Len(ch) = 0 Then
            read_line% = 0
            Exit Function
        End If
        If ch = Chr$(10) Then
            Exit Do
        End If
        If ch = Chr$(13) Then

        Else
            dst$ = dst$ + UCase$(ch) ' QB64 UCASE$ for toupper
            size = size + 1
        End If
    Loop
    read_line% = size
End Function

' Function: file_test
' Tests phoneme conversion on lines from a file.
' Parameters:
'   path$ - The path to the test file.
'   state - A structure to track test results.  Must be adapted for QB64
' Returns:
'   1 if the test completes successfully, 0 otherwise.
Function file_test% (path$, state As TestState)
    Dim fd As Long
    Dim sTemp1 As String
    Dim sTemp2 As String
    Dim iLen As Integer

    Open path$ For Binary As #fd
    If LOF(fd) = 0 Then ' Instead of fd = 0
        file_test% = _FALSE
        Exit Function
    End If
    Do
        iLen = read_line%(fd, sTemp1)
        If iLen = 0 Then
            Exit Do
        End If
        sTemp1 = sTemp1 + "["
        sTemp2 = sTemp1

        'max_size = 250
        If TextToPhonemes(sTemp1, 250) > 0 Then
            Print ".";
            state.passes = state.passes + 1
        Else
            Print "x";
            Print
            Print sTemp2
            state.fails = state.fails + 1
        End If
        sTemp1 = "" '  Reset sTemp1 for next loop
    Loop
    Close #fd
    file_test% = _TRUE
End Function ' file_test%

' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' End test_phonemes.c
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++






























' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' BEGIN sam.c
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Sub Init
    Dim i As Integer
    Call SetMouthThroat(mouth, throat)
    bufferPos = 0

    'Allocate memory - QB64 uses _NEW for this (similar to malloc)
    'Note:  _NEW returns a pointer, and we need to allocate enough space for bytes (_BYTE)
    'TODO: do we need to do _MEM stuff here?
    'buffer = _NEW _BYTE[22050 * 10]

    'The original C code had commented-out assignments to memory locations.
    'It's likely these are related to how the original C code interfaced with memory.
    'We'll leave them commented out in QB64, as we don't have the context to translate them directly.
    'If you have more information on what these memory locations represent, we can refine this.

    'freq2data = &mem[45136]
    'freq1data = &mem[45056]
    'freq3data = &mem[45216]
    'pitches = &mem[43008]
    'frequency1 = &mem[43264]
    'frequency2 = &mem[43520]
    'frequency3 = &mem[43776]
    'amplitude1 = &mem[44032]
    'amplitude2 = &mem[44288]
    'amplitude3 = &mem[44544]
    'phoneme = &mem[39904]
    'ampl1data = &mem[45296]
    'ampl2data = &mem[45376]
    'ampl3data = &mem[45456]

    For i = 0 To 255
        arrStress1(i) = 0
        arrPhonemeLength(i) = 0
    Next i

    For i = 0 To 59
        arrPhoIndexOutput(i) = 0
        arrStressOutput(i) = 0
        arrPhoLengthOutput(i) = 0
    Next i

    arrPhonemeIndex(255) = 255 'Prevent buffer overflow
End Sub

Function Main% ()
    Init
    arrPhonemeIndex(255) = 32 '//to prevent buffer overflow

    If Parser1% = _FALSE Then
        Main% = _FALSE
        Exit Function
    End If

    If (bDebug) Then
        PrintPhonemes arrPhonemeIndex(), arrPhonemeLength(), arrStress1()
    End If

    Parser2
    CopyStress
    SetPhonemeLength
    AdjustLengths
    Code41240

    Do
        A = arrPhonemeIndex(X)
        If (A > 80) Then
            arrPhonemeIndex(X) = 255
            Exit Do '// error: delete all behind it
        End If
        X = X + 1
    Loop Until X = 0

    '//pos39848:
    InsertBreath

    '//mem(40158) = 255
    If (bDebug) Then
        PrintPhonemes arrPhonemeIndex(), arrPhonemeLength(), arrStress1()
    End If

    PrepareOutput
    Main% = _TRUE
End Function ' Main

Sub SetInput (inputString As String)
    'Converts a QB64 String to a _BYTE array
    Dim i As Integer
    Dim l As Integer
    l = Len(inputString)
    If l > 254 Then l = 254

    For i = 1 To l
        arrInput1(i - 1) = Asc(Mid$(inputString, i, 1))
    Next i
    arrInput1(l) = 0 'Null terminate (C-style strings)
End Sub

Sub SetSpeed (inputSpeed As _Byte)
    speed = inputSpeed
End Sub

Sub SetPitch (inputPitch As _Byte)
    pitch = inputPitch
End Sub

Sub SetMouth (inputMouth As _Byte)
    mouth = inputMouth
End Sub

Sub SetThroat (inputThroat As _Byte)
    throat = inputThroat
End Sub

Sub EnableSingmode
    singmode = 1
End Sub

Function GetBuffer$ ()
    'Need to convert the _OFFSET to a QB64 String
    Dim result As String

    If buffer = 0 Then Exit Function 'Handle null pointer

    For i = 0 To bufferPos - 1
        result = result + Chr$(buffer(i))
    Next i

    GetBuffer$ = result
End Function

Function GetBufferLength% ()
    GetBufferLength = bufferPos
End Function


Sub PrepareOutput ()
    Dim iTemp As Integer
    A = 0
    X = 0
    Y = 0

    '//pos48551:
    Do While -1 '// Infinite loop, equivalent to while(1)
        A = arrPhonemeIndex(X)
        If (A = 255) Then
            A = 255
            arrPhoIndexOutput(Y) = 255
            Render
            Exit Sub
        End If
        If (A = 254) Then
            X = X + 1
            iTemp = X '// Local variable to mimic C's temp
            '//mem(48546) = X
            arrPhoIndexOutput(Y) = 255
            Render
            '//X = mem(48546)
            X = iTemp
            Y = 0
            _Continue
        End If

        If (A = 0) Then
            X = X + 1
            _Continue
        End If

        arrPhoIndexOutput(Y) = A
        arrPhoLengthOutput(Y) = arrPhonemeLength(X)
        arrStressOutput(Y) = arrStress1(X)
        X = X + 1
        Y = Y + 1
    Loop
End Sub ' PrepareOutput

Sub InsertBreath ()
    Dim mem54 As _Byte
    Dim mem55 As _Byte
    Dim index As _Byte 'variable Y
    Dim mem66 As _Byte

    mem54 = 255
    X = X + 1
    mem55 = 0
    mem66 = 0
    Do
        'pos48440:
        X = mem66
        index = arrPhonemeIndex(X)
        If index = 255 Then
            Exit Sub
        End If
        mem55 = mem55 + arrPhonemeLength(X)

        If mem55 < 232 Then
            If index <> 254 Then ' ML : Prevents an index out of bounds problem
                A = arrFlags2(index) And 1
                If A <> 0 Then
                    X = X + 1
                    mem55 = 0
                    Call Insert(X, 254, mem59, 0)
                    mem66 = mem66 + 1
                    mem66 = mem66 + 1
                    _Continue
                End If
            End If
            If index = 0 Then
                mem54 = X
            End If
            mem66 = mem66 + 1
        Else
            X = mem54
            arrPhonemeIndex(X) = 31 ' 'Q*' glottal stop
            arrPhonemeLength(X) = 4
            arrStress1(X) = 0
            X = X + 1
            mem55 = 0
            Call Insert(X, 254, mem59, 0)
            X = X + 1
            mem66 = X
        End If

    Loop
End Sub ' InsertBreath

Sub CopyStress ()
    ' loop thought all the phonemes to be output
    Dim iPos As Integer ' _BYTE
    iPos = 0 'mem66
    Do
        ' get the phomene
        Y = arrPhonemeIndex(iPos)
        ' exit at end of buffer
        If Y = 255 Then
            Exit Sub
        End If
        ' if CONSONANT_FLAG set, skip - only vowels get stress
        If (arrFlags1(Y) And 64) = 0 Then
            iPos = iPos + 1
            _Continue
        End If
        ' get the next phoneme
        Y = arrPhonemeIndex(iPos + 1)
        If Y = 255 Then 'prevent buffer overflow
            iPos = iPos + 1
            _Continue
        Else
            ' if the following phoneme is a vowel, skip
            If (arrFlags1(Y) And 128) = 0 Then
                iPos = iPos + 1
                _Continue
            End If
        End If

        ' get the stress value at the next position
        Y = arrStress1(iPos + 1)
        ' if next phoneme is not stressed, skip
        If Y = 0 Then
            iPos = iPos + 1
            _Continue
        End If

        ' if next phoneme is not a VOWEL OR ER, skip
        If (Y And 128) <> 0 Then
            iPos = iPos + 1
            _Continue
        End If

        ' copy stress from prior phoneme to this one
        arrStress1(iPos) = Y + 1
        ' advance pointer
        iPos = iPos + 1

    Loop
End Sub ' CopyStress

Sub Insert (position As _Byte, mem60 As _Byte, mem59 As _Byte, mem58 As _Byte)
    Dim i As Integer
    For i = 253 To position Step -1 ' ML : always keep last safe-guarding 255
        arrPhonemeIndex(i + 1) = arrPhonemeIndex(i)
        arrPhonemeLength(i + 1) = arrPhonemeLength(i)
        arrStress1(i + 1) = arrStress1(i)
    Next i

    arrPhonemeIndex(position) = mem60
    arrPhonemeLength(position) = mem59
    arrStress1(position) = mem58
End Sub ' Insert







' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' BEGIN Parser1 Function
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Function Parser1% ()
    Dim iIndex1 As Integer
    Dim sign1 As _Unsigned _Byte
    Dim sign2 As _Unsigned _Byte
    Dim position As _Unsigned _Byte
    position = 0
    X = 0
    A = 0
    Y = 0

    ' CLEAR THE STRESS TABLE
    For iIndex1 = 0 To 255
        arrStress1(iIndex1) = 0
    Next iIndex1

    ' THIS CODE MATCHES THE PHONEME LETTERS TO THE TABLE
    Do
        ' GET THE FIRST CHARACTER FROM THE PHONEME BUFFER
        sign1 = arrInput1(X) ' Assuming arrInput1 is 1-based array

        ' TEST FOR 155 () END OF LINE MARKER
        If sign1 = 155 Then
            ' MARK ENDPOINT AND RETURN
            arrPhonemeIndex(position) = 255
            'mark endpoint
            ' REACHED END OF PHONEMES, SO EXIT
            Parser1% = _TRUE ' all ok
            Exit Function
        End If

        ' GET THE NEXT CHARACTER FROM THE BUFFER
        X = X + 1
        sign2 = arrInput1(X)

        ' NOW sign1 = FIRST CHARACTER OF PHONEME, AND sign2 = SECOND CHARACTER OF PHONEME

        ' TRY TO MATCH PHONEMES ON TWO TWO-CHARACTER NAME
        ' IGNORE PHONEMES IN TABLE ENDING WITH WILDCARDS

        ' SET INDEX TO 0
        Y = 0

        Do
            ' GET FIRST CHARACTER AT POSITION Y IN signInputTable
            ' --> should change name to PhonemeNameTable1
            A = arrSignInputTable1(Y) ' Assuming arrSignInputTable1 is 0-based

            ' FIRST CHARACTER MATCHES?
            If A = sign1 Then
                ' GET THE CHARACTER FROM THE PhonemeSecondLetterTable
                A = arrSignInputTable2(Y)

                ' NOT A SPECIAL AND MATCHES SECOND CHARACTER?
                If (A <> Asc("*")) And (A = sign2) Then 'QB64 uses ASC() for character to ASCII
                    ' STORE THE INDEX OF THE PHONEME INTO THE phomeneIndexTable
                    arrPhonemeIndex(position) = Y

                    ' ADVANCE THE POINTER TO THE phonemeIndexTable
                    position = position + 1

                    ' ADVANCE THE POINTER TO the phonemeInputBuffer
                    X = X + 1

                    ' CONTINUE PARSING
                    _Continue
                End If
            End If

            ' NO MATCH, TRY TO MATCH ON FIRST CHARACTER TO WILDCARD NAMES (ENDING WITH '*')

            ' ADVANCE TO THE NEXT POSITION
            Y = Y + 1

            ' IF NOT END OF TABLE, CONTINUE
            If Y <> 81 Then
                'GOTO pos41095  ' QB64 doesn't encourage GOTO, using DO...LOOP
                _Continue
            End If

            ' REACHED END OF TABLE WITHOUT AN EXACT (2 CHARACTER) MATCH.
            ' THIS TIME, SEARCH FOR A 1 CHARACTER MATCH AGAINST THE WILDCARDS

            ' RESET THE INDEX TO POINT TO THE START OF THE PHONEME NAME TABLE
            Y = 0

            Do
                ' DOES THE PHONEME IN THE TABLE END WITH '*'?
                If arrSignInputTable2(Y) = Asc("*") Then
                    ' DOES THE FIRST CHARACTER MATCH THE FIRST LETTER OF THE PHONEME
                    If arrSignInputTable1(Y) = sign1 Then
                        ' SAVE THE POSITION AND MOVE AHEAD
                        arrPhonemeIndex(position) = Y

                        ' ADVANCE THE POINTER
                        position = position + 1

                        ' CONTINUE THROUGH THE LOOP
                        _Continue
                    End If
                End If
                Y = Y + 1
                If Y <> 81 Then
                    'GOTO pos41134
                    _Continue
                End If
            Loop

            '81 is size of PHONEME NAME table

            ' FAILED TO MATCH WITH A WILDCARD.
            ' ASSUME THIS IS A STRESS
            ' CHARACTER.
            ' SEARCH THROUGH THE STRESS TABLE

            ' SET INDEX TO POSITION 8 (END OF STRESS TABLE)
            Y = 8

            ' WALK BACK THROUGH TABLE LOOKING FOR A MATCH
            Do While (sign1 <> arrStressInputTable(Y)) And (Y > 0)
                ' DECREMENT INDEX
                Y = Y - 1
            Loop

            ' REACHED THE END OF THE SEARCH WITHOUT BREAKING OUT OF LOOP?
            If Y = 0 Then
                'mem[39444] = X
                '41181: JSR 42043 //Error
                ' FAILED TO MATCH ANYTHING, RETURN 0 ON FAILURE
                Parser1% = _FALSE
                Exit Function
            End If
            ' SET THE STRESS FOR THE PRIOR PHONEME
            arrStress1(position - 1) = Y
        Loop
    Loop
End Function ' Parser1%
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' END Parser1 Function
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' BEGIN SetPhonemeLength
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

' change phonemelength depedendent on stress
' void Code41203()
Sub SetPhonemeLength
    Dim A As _Unsigned _Byte
    Dim position As Integer
    position = 0

    Do While arrPhonemeIndex(position) <> 255
        A = arrStress1(position)

        '41218: BMI 41229  ' BMI is Branch if Minus (negative) -  QB64 doesn't have direct BMI, emulate with sign check
        If (A = 0) Or ((A And 128) <> 0) Then 'bitwise AND to check high bit (sign)
            arrPhonemeLength(position) = arrPhoLengthTable(arrPhonemeIndex(position))
        Else
            arrPhonemeLength(position) = arrPhoStressedLengthTable(arrPhonemeIndex(position))
        End If
        position = position + 1
    Loop
End Sub ' SetPhonemeLength
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' END SetPhonemeLength
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' BEGIN Code41240
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Sub Code41240
    Dim iPos As Integer ' _UNSIGNED _BYTE
    iPos = 0

    Do While arrPhonemeIndex(iPos) <> 255
        Dim index As _Unsigned _Byte 'register AC
        X = iPos
        index = arrPhonemeIndex(iPos)

        If (arrFlags1(index) And 2) = 0 Then ' Bitwise AND
            iPos = iPos + 1
            _Continue
        ElseIf (arrFlags1(index) And 1) = 0 Then ' Bitwise AND
            Insert iPos + 1, index + 1, arrPhoLengthTable(index + 1), arrStress1(iPos)
            Insert iPos + 2, index + 2, arrPhoLengthTable(index + 2), arrStress1(iPos)
            iPos = iPos + 3
            _Continue
        End If

        Do
            X = X + 1
            A = arrPhonemeIndex(X)
        Loop Until A <> 0

        If A <> 255 Then
            If (arrFlags1(A) And 8) <> 0 Then
                iPos = iPos + 1
                _Continue
            End If
            If (A = 36) Or (A = 37) Then
                iPos = iPos + 1
                _Continue
            End If ' '/H' '/X'
        End If

        Insert iPos + 1, index + 1, arrPhoLengthTable(index + 1), arrStress1(iPos)
        Insert iPos + 2, index + 2, arrPhoLengthTable(index + 2), arrStress1(iPos)
        iPos = iPos + 3
    Loop
End Sub ' Code41240
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' END Code41240
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////




' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' BEGIN Parser2
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

' Rewrites the phonemes using the following rules:
'
'       <DIPHTONG ENDING WITH WX> -> <DIPHTONG ENDING WITH WX> WX
'       <DIPHTONG NOT ENDING WITH WX> -> <DIPHTONG NOT ENDING WITH WX> YX
'       UL -> AX L
'       UM -> AX M
'       <STRESSED VOWEL> <SILENCE> <STRESSED VOWEL> -> <STRESSED VOWEL> <SILENCE> Q <VOWEL>
'       T R -> CH R
'       D R -> J R
'       <VOWEL> R -> <VOWEL> RX
'       <VOWEL> L -> <VOWEL> LX
'       G S -> G Z
'       K <VOWEL OR DIPHTONG NOT ENDING WITH IY> -> KX <VOWEL OR DIPHTONG NOT ENDING WITH IY>
'       G <VOWEL OR DIPHTONG NOT ENDING WITH IY> -> GX <VOWEL OR DIPHTONG NOT ENDING WITH IY>
'       S P -> S B
'       S T -> S D
'       S K -> S G
'       S KX -> S GX
'       <ALVEOLAR> UW -> <ALVEOLAR> UX
'       CH -> CH CH' (CH requires two phonemes to represent it)
'       J -> J J' (J requires two phonemes to represent it)
'       <UNSTRESSED VOWEL> T <PAUSE> -> <UNSTRESSED VOWEL> DX <PAUSE>
'       <UNSTRESSED VOWEL> D <PAUSE>  -> <UNSTRESSED VOWEL> DX <PAUSE>
'
'void Parser2()
Sub Parser2 ()
    Dim iPos As Integer

    '  if (debug)
    '   printf("Parser2\n");
    If bDebug Then
        Print "Parser2"
    End If
    ' uint8_t pos = 0; //mem66;
    iPos = 0
    ' uint8_t mem58 = 0;
    mem58 = 0
    ' Loop through phonemes
    Do
        ' SET X TO THE CURRENT POSITION
        X = iPos ' Assuming X is an integer
        ' GET THE PHONEME AT THE CURRENT POSITION
        A = arrPhonemeIndex(iPos) ' Assuming A and arrPhonemeIndex are integers
        ' DEBUG: Print phoneme and index
        If bDebug And A <> 255 Then
            Print X; ": "; arrSignInputTable1(A); arrSignInputTable2(A) ' Assuming arrSignInputTable1 and arrSignInputTable2 are string arrays
        End If
        ' Is phoneme pause?
        If A = 0 Then ' Assuming 0 represents a pause
            '  Move ahead to the
            iPos = iPos + 1
            _Continue ' QB64 equivalent of continue
        End If
        ' If end of phonemes flag reached, exit routine
        If A = 255 Then
            Exit Do ' QB64 equivalent of return
        End If
        ' Copy the current phoneme index to Y
        Y = A ' Assuming Y is an integer
        ' Check for DIPHTONG
        If (arrFlags1(A) And 16) = 0 Then ' Assuming flags is an integer array
            GoTo pos41457
        End If
        ' Not a diphthong. Get the stress
        mem58 = arrStress1(iPos) ' Assuming stress is an integer array
        ' End in IY sound?
        A = arrFlags1(Y) And 32
        ' If ends with IY, use YX, else use WX
        If A = 0 Then
            A = 20
        Else
            A = 21
        End If ' 'WX' = 20 'YX' = 21
        'pos41443:
        ' Insert at WX or YX following, copying the stress
        If bDebug Then
            If A = 20 Then
                Print "RULE: insert WX following diphtong NOT ending in IY sound"
            End If
        End If
        If bDebug Then
            If A = 21 Then
                Print "RULE: insert YX following diphtong ending in IY sound"
            End If
        End If
        Insert iPos + 1, A, mem59, mem58 ' Assuming Insert is a SUB and mem59 is an integer
        X = iPos
        ' Jump to ???
        GoTo pos41749
        pos41457:
        ' Get phoneme
        A = arrPhonemeIndex(X)
        ' Skip this rule if phoneme is not UL
        If A <> 78 Then ' Assuming 78 is the value for UL
            GoTo pos41487
        End If
        ' 'UL'
        A = 24 ' Assuming 24 is the value for 'L
        ' 'L'                 'change 'UL' to 'AX L'
        If bDebug Then
            Print "RULE: UL -> AX L"
        End If
        pos41466:
        ' Get current phoneme stress
        mem58 = arrStress1(X)
        ' Change UL to AX
        arrPhonemeIndex(X) = 13 ' Assuming 13 is the value for AX
        ' 'AX'
        ' Perform insert. Note code below may jump up here with different values
        Insert X + 1, A, mem59, mem58
        iPos = iPos + 1
        ' Move to next phoneme
        _Continue
        pos41487:
        ' Skip rule if phoneme != UM
        If A <> 79 Then ' Assuming 79 is the value for UM
            GoTo pos41495
        End If
        ' 'UM'
        ' Jump up to branch - replaces current phoneme with AX and continues
        A = 27 ' Assuming 27 is the value for M
        ' 'M'  'change 'UM' to  'AX M'
        If bDebug Then
            Print "RULE: UM -> AX M"
        End If
        GoTo pos41466
        pos41495:
        ' Skip rule if phoneme != UN
        If A <> 80 Then ' Assuming 80 is the value for UN
            GoTo pos41503
        End If
        ' 'UN'
        ' Jump up to branch - replaces current phoneme with AX and continues
        A = 28 ' Assuming 28 is the value for N
        ' 'N' 'change UN to 'AX N'
        If bDebug Then
            Print "RULE: UN -> AX N"
        End If
        GoTo pos41466
        pos41503:
        Y = A

        ' VOWEL set?
        A = arrFlags1(A) And 128 'Assumes flags is an array

        ' Skip if not a vowel
        If A <> 0 Then
            ' Get the stress
            A = arrStress1(X) ' Assumes stress is an array

            ' If stressed...
            If A <> 0 Then
                ' Get the following phoneme
                X = X + 1
                A = arrPhonemeIndex(X) ' Assumes arrPhonemeIndex is an array

                ' If following phoneme is a pause
                If A = 0 Then
                    ' Get the phoneme following pause
                    X = X + 1
                    Y = arrPhonemeIndex(X)

                    ' Check for end of buffer flag
                    If Y = 255 Then 'buffer overflow
                        ' ??? Not sure about these flags
                        A = 65 And 128
                    Else
                        ' And VOWEL flag to current phoneme's flags
                        A = arrFlags1(Y) And 128
                    End If

                    ' If following phonemes is not a pause
                    If A <> 0 Then
                        ' If the following phoneme is not stressed
                        A = arrStress1(X)
                        If A <> 0 Then
                            ' Insert a glottal stop and move forward
                            If bDebug Then 'Assumes debug is a variable
                                Print "RULE: Insert glottal stop between two stressed vowels with space between them"
                            End If
                            ' 31 = 'Q'
                            Call Insert(X, 31, mem59, 0) ' Assumes Insert is a SUB
                            iPos = iPos + 1
                            _Continue
                        End If
                    End If
                End If
            End If
        End If

        ' RULES FOR PHONEMES BEFORE R
        '       T R -> CH R
        ' Example: TRACK

        ' Get current position and phoneme
        X = iPos
        A = arrPhonemeIndex(iPos)
        If A <> 23 Then GoTo pos41611 ' 'R'

        ' Look at prior phoneme
        X = X - 1
        A = arrPhonemeIndex(iPos - 1)
        'pos41567:
        If A = 69 Then ' 'T'
            ' Change T to CH
            If bDebug Then
                Print "RULE: T R -> CH R"
            End If
            arrPhonemeIndex(iPos - 1) = 42
            GoTo pos41779
        End If

        ' RULES FOR PHONEMES BEFORE R
        '       D R -> J R
        ' Example: DRY

        ' Prior phonemes D?
        If A = 57 Then ' 'D'
            ' Change D to J
            arrPhonemeIndex(iPos - 1) = 44
            If bDebug Then
                Print "RULE: D R -> J R"
            End If
            GoTo pos41788
        End If

        ' RULES FOR PHONEMES BEFORE R
        '       <VOWEL> R -> <VOWEL> RX
        ' Example: ART

        ' If vowel flag is set change R to RX
        A = arrFlags1(A) And 128
        If bDebug Then
            Print "RULE: R -> RX"
        End If
        If A <> 0 Then
            arrPhonemeIndex(iPos) = 18 ' 'RX'
        End If

        ' continue to next phoneme
        iPos = iPos + 1



        pos41611:
        ' Is phoneme L?
        If A = 24 Then '// 'L'
            ' If prior phoneme does not have VOWEL flag set, move to next phoneme
            If (arrFlags1(arrPhonemeIndex(iPos - 1)) And 128) = 0 Then
                iPos = iPos + 1
                'goto pos41611
                _Continue
            End If
            ' Prior phoneme has VOWEL flag set, so change L to LX and move to next phoneme
            If bDebug Then
                Print "RULE: <VOWEL> L -> <VOWEL> LX"
            End If
            arrPhonemeIndex(X) = 19 '// 'LX'
            iPos = iPos + 1
            'goto pos41611
            _Continue
        End If

        ' Is current phoneme S?
        If A = 32 Then '// 'S'
            ' If prior phoneme is not G, move to next phoneme
            If arrPhonemeIndex(iPos - 1) <> 60 Then
                iPos = iPos + 1
                'goto pos41611
                _Continue
            End If
            ' Replace S with Z and move on
            If bDebug Then
                Print "RULE: G S -> G Z"
            End If
            arrPhonemeIndex(iPos) = 38 '// 'Z'
            iPos = iPos + 1
            'goto pos41611
            _Continue
        End If

        ' Is current phoneme K?
        If A = 72 Then '// 'K'
            ' Get next phoneme
            Y = arrPhonemeIndex(iPos + 1)
            ' If at end, replace current phoneme with KX
            If Y = 255 Then
                arrPhonemeIndex(iPos) = 75
                ' ML : prevents an index out of bounds problem
            Else
                ' VOWELS AND DIPHTONGS ENDING WITH IY SOUND flag set?
                A = arrFlags1(Y) And 32
                If bDebug Then
                    If A = 0 Then
                        Print "RULE: K <VOWEL OR DIPHTONG NOT ENDING WITH IY> -> KX <VOWEL OR DIPHTONG NOT ENDING WITH IY>"
                    End If
                End If
                ' Replace with KX
                If A = 0 Then
                    arrPhonemeIndex(iPos) = 75
                End If
                ' 'KX'
            End If
        Else

            ' Is int8_tacter a G?
            If A = 60 Then '// 'G'
                ' Get the following int8_tacter
                Dim index As _Byte
                index = arrPhonemeIndex(iPos + 1)
                ' At end of buffer?
                If index = 255 Then '//prevent buffer overflow
                    iPos = iPos + 1
                    'goto pos41611
                    _Continue
                Else
                    ' If diphtong ending with YX, move continue processing next phoneme
                    If (arrFlags1(index) And 32) <> 0 Then
                        iPos = iPos + 1
                        'goto pos41611
                        _Continue
                    End If
                    ' replace G with GX and continue processing next phoneme
                    If bDebug Then
                        Print "RULE: G <VOWEL OR DIPHTONG NOT ENDING WITH IY> -> GX <VOWEL OR DIPHTONG NOT ENDING WITH IY>"
                    End If
                    arrPhonemeIndex(iPos) = 63 '// 'GX'
                    iPos = iPos + 1
                    'goto pos41611
                    _Continue
                End If
            End If
        End If

        Y = arrPhonemeIndex(iPos)
        'pos41719:
        ' Replace with softer version?
        A = arrFlags1(Y) And 1
        If A = 0 Then
            GoTo pos41749
        End If
        A = arrPhonemeIndex(iPos - 1)
        If A <> 32 Then '// 'S'
            A = Y
            GoTo pos41812
        End If
        ' Replace with softer version
        If bDebug Then
            Print "RULE: S* "; Chr$(arrSignInputTable1(Y)); Chr$(arrSignInputTable2(Y)); " -> S* "; Chr$(arrSignInputTable1(Y - 12)); Chr$(arrSignInputTable2(Y - 12))
        End If
        arrPhonemeIndex(iPos) = Y - 12
        iPos = iPos + 1
        'goto pos41611
        _Continue

        pos41749:

        '       UW -> UX
        A = arrPhonemeIndex(X)
        If A = 53 Then '// 'UW'
            ' ALVEOLAR flag set?
            Y = arrPhonemeIndex(X - 1)
            A = arrFlags2(Y) And 4
            ' If not set, continue processing next phoneme
            If A = 0 Then
                iPos = iPos + 1
                'goto pos41611
                _Continue
            End If
            If bDebug Then
                Print "RULE: <ALVEOLAR> UW -> <ALVEOLAR> UX"
            End If
            arrPhonemeIndex(X) = 16
            iPos = iPos + 1
            'goto pos41611
            _Continue
        End If



        pos41779:

        If A = 42 Then '// 'CH'
            '       pos41783:
            If bDebug Then
                Print "CH -> CH CH+1"
            End If
            Call Insert(X + 1, A + 1, mem59, arrStress1(X))
            iPos = iPos + 1
            _Continue
        End If

        pos41788:

        If A = 44 Then '// 'J'
            If bDebug Then
                Print "J -> J J+1"
            End If
            Call Insert(X + 1, A + 1, mem59, arrStress1(X))
            iPos = iPos + 1
            _Continue
        End If

        ' Jump here to continue
        pos41812:

        ' Past this point, only process if phoneme is T or D
        If A <> 69 Then '// 'T'
            If A <> 57 Then
                iPos = iPos + 1
                _Continue
            End If '// 'D'
        End If
        'pos41825:

        ' If prior phoneme is not a vowel, continue processing phonemes
        If (arrFlags1(arrPhonemeIndex(X - 1)) And 128) = 0 Then
            iPos = iPos + 1
            _Continue
        End If

        ' Get next phoneme
        X = X + 1
        A = arrPhonemeIndex(X)
        'pos41841
        ' Is the next phoneme a pause?
        If A <> 0 Then
            ' If next phoneme is not a pause, continue processing phonemes
            If (arrFlags1(A) And 128) = 0 Then
                iPos = iPos + 1
                _Continue
            End If
            ' If next phoneme is stressed, continue processing phonemes
            ' FIXME: How does a pause get stressed?
            If arrStress1(X) <> 0 Then
                iPos = iPos + 1
                _Continue
            End If
            'pos41856:
            ' Set phonemes to DX
            If bDebug Then
                Print "RULE: Soften T or D following vowel or ER and preceding a pause -> DX"
            End If
            arrPhonemeIndex(iPos) = 30 '// 'DX'
        Else
            A = arrPhonemeIndex(X + 1)
            If A = 255 Then '//prevent buffer overflow
                A = 65 And 128
            Else
                ' Is next phoneme a vowel or ER?
                A = arrFlags1(A) And 128
            End If
            If bDebug Then
                If A <> 0 Then
                    Print "RULE: Soften T or D following vowel or ER and preceding a pause -> DX"
                End If
            End If
            If A <> 0 Then
                arrPhonemeIndex(iPos) = 30
            End If '// 'DX'
        End If

        iPos = iPos + 1
    Loop '// while
End Sub ' Parser2
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' END Parser2
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////



' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' BEGIN AdjustLengths
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

' Applies various rules that adjust the lengths of phonemes
'
'         Lengthen <FRICATIVE> or <VOICED> between <VOWEL> and <PUNCTUATION> by 1.5
'         <VOWEL> <RX | LX> <CONSONANT> - decrease <VOWEL> length by 1
'         <VOWEL> <UNVOICED PLOSIVE> - decrease vowel by 1/8th
'         <VOWEL> <UNVOICED CONSONANT> - increase vowel by 1/2 + 1
'         <NASAL> <STOP CONSONANT> - set nasal = 5, consonant = 6
'         <VOICED STOP CONSONANT> {optional silence} <STOP CONSONANT> - shorten both to 1/2 + 1
'         <LIQUID CONSONANT> <DIPHTONG> - decrease by 2

'// void Code48619()
'void AdjustLengths()
Sub AdjustLengths ()

    ' loop index
    Dim X As Integer
    Dim index As _Byte
    Dim A As Integer
    Dim loopIndex As _Byte
    Dim mem56 As Integer
    Dim debugX As Integer

    ' iterate through the phoneme list
    loopIndex = 0
    Do
        ' get a phoneme
        X = loopIndex
        index = arrPhonemeIndex(X)

        ' exit loop if end on buffer token
        If index = 255 Then
            Exit Do
        End If

        ' not punctuation?
        If (arrFlags2(index) And 1) = 0 Then
            ' skip
            X = X + 1
            _Continue
        End If

        ' hold index
        loopIndex = X

        ' Loop backwards from this point
        pos48644:

        ' back up one phoneme
        X = X - 1

        ' stop once the beginning is reached
        If X = 0 Then
            Exit Do
        End If

        ' get the preceding phoneme
        index = arrPhonemeIndex(X)

        If index <> 255 Then 'inserted to prevent access overrun
            If (arrFlags1(index) And 128) = 0 Then
                GoTo pos48644 ' if not a vowel, continue looping
            End If
        End If

        'pos48657:
        Do
            ' test for vowel
            index = arrPhonemeIndex(X)
            If index <> 255 Then 'inserted to prevent access overrun
                ' test for fricative/unvoiced or not voiced
                If ((arrFlags2(index) And 32) = 0) Or ((arrFlags1(index) And 4) <> 0) Then 'nochmal berprfen
                    'A = arrFlags1(Y) & 4;
                    'if(A == 0) goto pos48688;

                    ' get the phoneme length
                    A = arrPhonemeLength(X)
                    ' change phoneme length to (length * 1.5) + 1
                    A = (A \ 2) + A + 1
                    If bDebug Then
                        Print "RULE: Lengthen <FRICATIVE> or <VOICED> between <VOWEL> and <PUNCTUATION> by 1.5"
                    End If
                    If bDebug Then
                        Print "PRE"
                    End If
                    If bDebug Then
                        Print "phoneme"; X; "("; Chr$(arrSignInputTable1(arrPhonemeIndex(X))); Chr$(arrSignInputTable2(arrPhonemeIndex(X))); ") length"; arrPhonemeLength(X)
                    End If
                    arrPhonemeLength(X) = A

                    If bDebug Then
                        Print "POST"
                    End If
                    If bDebug Then
                        Print "phoneme"; X; "("; Chr$(arrSignInputTable1(arrPhonemeIndex(X))); Chr$(arrSignInputTable2(arrPhonemeIndex(X))); ") length"; arrPhonemeLength(X)
                    End If
                End If
            End If
            ' keep moving forward
            X = X + 1
        Loop Until X = loopIndex
        '    if (X != loopIndex) goto pos48657;
        X = X + 1
    Loop

    ' Similar to the above routine, but shorten vowels under some circumstances

    ' Loop throught all phonemes
    loopIndex = 0

    'pos48697

    Do
        ' get a phoneme
        X = loopIndex
        index = arrPhonemeIndex(X)

        ' exit routine at end token
        If index = 255 Then
            Exit Sub
        End If
        ' vowel?
        A = arrFlags1(index) And 128
        If A <> 0 Then
            ' get next phoneme
            X = X + 1
            index = arrPhonemeIndex(X)

            ' get flags
            If index = 255 Then
                mem56 = 65
            Else
                mem56 = arrFlags1(index)
            End If
            ' use if end marker
            ' not a consonant
            If (arrFlags1(index) And 64) = 0 Then
                ' RX or LX?
                If (index = 18) Or (index = 19) Then ' 'RX' & 'LX'
                    ' get the next phoneme
                    X = X + 1
                    index = arrPhonemeIndex(X)

                    ' next phoneme a consonant?
                    If (arrFlags1(index) And 64) <> 0 Then
                        If bDebug Then
                            Print "RULE: <VOWEL> <RX | LX> <CONSONANT> - decrease length by 1"
                        End If
                        If bDebug Then
                            Print "PRE"
                        End If
                        If bDebug Then
                            Print "phoneme"; loopIndex; "("; Chr$(arrSignInputTable1(arrPhonemeIndex(loopIndex))); Chr$(arrSignInputTable2(arrPhonemeIndex(loopIndex))); ") length"; arrPhonemeLength(loopIndex)
                        End If
                        ' decrease length of vowel by 1 frame
                        arrPhonemeLength(loopIndex) = arrPhonemeLength(loopIndex) - 1
                        If bDebug Then
                            Print "POST"
                        End If
                        If bDebug Then
                            Print "phoneme"; loopIndex; "("; Chr$(arrSignInputTable1(arrPhonemeIndex(loopIndex))); Chr$(arrSignInputTable2(arrPhonemeIndex(loopIndex))); ") length"; arrPhonemeLength(loopIndex)
                        End If
                    End If
                    ' move ahead
                    loopIndex = loopIndex + 1
                    _Continue
                End If
                ' move ahead
                loopIndex = loopIndex + 1
                _Continue
            End If

            ' Got here if not <VOWEL>

            ' not voiced
            If (mem56 And 4) = 0 Then
                ' Unvoiced
                ' *, .*, ?*, ,*, -*, DX, S*, SH, F*, TH, /H, /X, CH, P*, T*, K*,

                ' KX

                ' not an unvoiced plosive?
                If (mem56 And 1) = 0 Then
                    ' move ahead
                    loopIndex = loopIndex + 1
                    _Continue
                End If

                ' P*, T*, K*, KX

                ' move back
                X = X - 1
                If bDebug Then
                    Print "RULE: <VOWEL> <UNVOICED PLOSIVE> - decrease vowel by 1/8th"
                End If
                If bDebug Then
                    Print "PRE"
                End If
                If bDebug Then
                    Print "phoneme"; X; "("; Chr$(arrSignInputTable1(arrPhonemeIndex(X))); Chr$(arrSignInputTable2(arrPhonemeIndex(X))); ") length"; arrPhonemeLength(X)
                End If
                ' decrease length by 1/8th
                mem56 = arrPhonemeLength(X) \ 8
                arrPhonemeLength(X) = arrPhonemeLength(X) - mem56

                If bDebug Then
                    Print "POST"
                End If
                If bDebug Then
                    Print "phoneme"; X; "("; Chr$(arrSignInputTable1(arrPhonemeIndex(X))); Chr$(arrSignInputTable2(arrPhonemeIndex(X))); ") length"; arrPhonemeLength(X)
                End If
                ' move ahead
                loopIndex = loopIndex + 1
                _Continue
            End If

            If bDebug Then
                Print "RULE: <VOWEL> <VOICED CONSONANT> - increase vowel by 1/2 + 1"
            End If
            If bDebug Then
                Print "PRE"
            End If
            If bDebug Then
                Print "phoneme"; X - 1; "("; Chr$(arrSignInputTable1(arrPhonemeIndex(X - 1))); Chr$(arrSignInputTable2(arrPhonemeIndex(X - 1))); ") length"; arrPhonemeLength(X - 1)
            End If
            ' decrease length
            A = arrPhonemeLength(X - 1)
            arrPhonemeLength(X - 1) = (A \ 2) + A + 1
            ' 5/4*A + 1

            If bDebug Then
                Print "POST"
            End If
            If bDebug Then
                Print "phoneme"; X - 1; "("; Chr$(arrSignInputTable1(arrPhonemeIndex(X - 1))); Chr$(arrSignInputTable2(arrPhonemeIndex(X - 1))); ") length"; arrPhonemeLength(X - 1)
            End If
            ' move ahead
            loopIndex = loopIndex + 1
            _Continue
        End If

        ' WH, R*, L*, W*, Y*, Q*, Z*, ZH, V*, DH, J*, **,

        'pos48821:

        ' nasal?
        If (arrFlags2(index) And 8) <> 0 Then
            ' M*, N*, NX,
            ' get the next phoneme
            X = X + 1
            index = arrPhonemeIndex(X)

            ' end of buffer?
            If index = 255 Then
                A = 65 And 2
            Else
                A = arrFlags1(index) And 2
            End If
            'prevent buffer overflow
            ' check for stop consonant

            ' is next phoneme a stop consonant?
            If A <> 0 Then

                ' B*, D*, G*, GX, P*, T*, K*, KX

                If bDebug Then
                    Print "RULE: <NASAL> <STOP CONSONANT> - set nasal = 5, consonant = 6"
                End If
                If bDebug Then
                    Print "POST"
                End If
                If bDebug Then
                    Print "phoneme"; X; "("; Chr$(arrSignInputTable1(arrPhonemeIndex(X))); Chr$(arrSignInputTable2(arrPhonemeIndex(X))); ") length"; arrPhonemeLength(X)
                End If
                If bDebug Then
                    Print "phoneme"; X - 1; "("; Chr$(arrSignInputTable1(arrPhonemeIndex(X - 1))); Chr$(arrSignInputTable2(arrPhonemeIndex(X - 1))); ") length"; arrPhonemeLength(X - 1)
                End If
                ' set stop consonant length to 6
                arrPhonemeLength(X) = 6
                ' set nasal length to 5
                arrPhonemeLength(X - 1) = 5
                If bDebug Then
                    Print "POST"
                End If
                If bDebug Then
                    Print "phoneme"; X; "("; Chr$(arrSignInputTable1(arrPhonemeIndex(X))); Chr$(arrSignInputTable2(arrPhonemeIndex(X))); ") length"; arrPhonemeLength(X)
                End If
                If bDebug Then
                    Print "phoneme"; X - 1; "("; Chr$(arrSignInputTable1(arrPhonemeIndex(X - 1))); Chr$(arrSignInputTable2(arrPhonemeIndex(X - 1))); ") length"; arrPhonemeLength(X - 1)
                End If
            End If
            ' move to next phoneme
            loopIndex = loopIndex + 1
            _Continue
        End If

        If (arrFlags1(index) And 2) <> 0 Then
            ' B*, D*, G*, GX

            ' move past silence
            Do
                ' move ahead
                X = X + 1
                index = arrPhonemeIndex(X)
            Loop Until index = 0

            ' check for end of buffer
            If index = 255 Then 'buffer overflow
                ' ignore, overflow code
                If (65 And 2) = 0 Then
                    loopIndex = loopIndex + 1
                    _Continue
                End If
            ElseIf (arrFlags1(index) And 2) = 0 Then
                ' if another stop consonant, move ahead
                loopIndex = loopIndex + 1
                _Continue
            End If

            If bDebug Then
                Print "RULE: <UNVOICED STOP CONSONANT> {optional silence} <STOP CONSONANT> - shorten both to 1/2 + 1"
            End If
            If bDebug Then
                Print "PRE"
            End If
            If bDebug Then
                Print "phoneme"; X; "("; Chr$(arrSignInputTable1(arrPhonemeIndex(X))); Chr$(arrSignInputTable2(arrPhonemeIndex(X))); ") length"; arrPhonemeLength(X)
            End If
            If bDebug Then
                Print "phoneme"; X - 1; "("; Chr$(arrSignInputTable1(arrPhonemeIndex(X - 1))); Chr$(arrSignInputTable2(arrPhonemeIndex(X - 1))); ") length"; arrPhonemeLength(X - 1)
            End If
            ' X gets overwritten, so hold prior X value for debug statement
            debugX = X
            ' shorten the prior phoneme length to (length/2 + 1)
            arrPhonemeLength(X) = (arrPhonemeLength(X) \ 2) + 1
            X = loopIndex

            ' also shorten this phoneme length to (length/2 +1)
            arrPhonemeLength(loopIndex) = (arrPhonemeLength(loopIndex) \ 2) + 1
            If bDebug Then
                Print "POST"
            End If
            If bDebug Then
                Print "phoneme"; debugX; "("; Chr$(arrSignInputTable1(arrPhonemeIndex(debugX))); Chr$(arrSignInputTable2(arrPhonemeIndex(debugX))); ") length"; arrPhonemeLength(debugX)
            End If
            If bDebug Then
                Print "phoneme"; debugX - 1; "("; Chr$(arrSignInputTable1(arrPhonemeIndex(debugX - 1))); Chr$(arrSignInputTable2(arrPhonemeIndex(debugX - 1))); ") length"; arrPhonemeLength(debugX - 1)
            End If
            ' move ahead
            loopIndex = loopIndex + 1
            _Continue
        End If

        ' WH, R*, L*, W*, Y*, Q*, Z*, ZH, V*, DH, J*, **,

        ' liquic consonant?
        If (arrFlags2(index) And 16) <> 0 Then
            ' R*, L*, W*, Y*

            ' get the prior phoneme
            index = arrPhonemeIndex(X - 1)
            ' prior phoneme a stop consonant>
            If (arrFlags1(index) And 2) <> 0 Then
                If bDebug Then
                    Print "RULE: <LIQUID CONSONANT> <DIPHTONG> - decrease by 2"
                End If
                If bDebug Then
                    Print "PRE"
                End If
                If bDebug Then
                    Print "phoneme"; X; "("; Chr$(arrSignInputTable1(arrPhonemeIndex(X))); Chr$(arrSignInputTable2(arrPhonemeIndex(X))); ") length"; arrPhonemeLength(X)
                End If
                ' decrease the phoneme length by 2 frames (20 ms)
                arrPhonemeLength(X) = arrPhonemeLength(X) - 2
                If bDebug Then
                    Print "POST"
                End If
                If bDebug Then
                    Print "phoneme"; X; "("; Chr$(arrSignInputTable1(arrPhonemeIndex(X))); Chr$(arrSignInputTable2(arrPhonemeIndex(X))); ") length"; arrPhonemeLength(X)
                End If
            End If
        End If

        ' move to next phoneme
        loopIndex = loopIndex + 1
        _Continue
    Loop

End Sub ' AdjustLengths
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' END AdjustLengths
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////



' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' BEGIN Code47503
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

' ML : Code47503 is division with remainder, and mem50 gets the sign

'void Code47503(uint8_t mem52)
Sub Code47503 (mem52 As _Byte)
    Dim iTemp As Integer

    Y = 0
    If ((mem53 And 128) <> 0) Then
        mem53 = -mem53
        Y = 128
    End If
    mem50 = Y
    A = 0
    For X = 8 To 1 Step -1
        iTemp = mem53
        mem53 = mem53 * 2 ' QB64PE uses * for left bit shift
        A = A * 2 ' QB64PE uses * for left bit shift
        If (iTemp >= 128) Then
            A = A + 1
        End If
        If (A >= mem52) Then
            A = A - mem52
            mem53 = mem53 + 1
        End If
    Next X
    mem51 = A
    If ((mem50 And 128) <> 0) Then
        mem53 = -mem53
    End If
End Sub ' Code47503
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' END Code47503
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' END sam.c
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' BEGIN reciter.c
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' BEGIN Function TestFlag
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' test the flag bits for a specific char
' this is non ascii layout, but tests ascii chars
'uint32_t TestFlag(uint8_t in, uint8_t mask)
' {
'  assert(in<sizeof(tab36376));
'  const uint8_t val = tab36376[in];
'  return val & mask;
' }
Function TestFlag~% (in As _Unsigned _Byte, mask As _Unsigned _Byte)
    If in > UBound(tab36376) Then Stop 'QB64: Replace assert with STOP
    ' val = arrTab36376(in) 'Not needed, can use array element directly
    TestFlag = arrTab36376(in) And mask 'QB64: AND is bitwise AND
End Function ' TestFlag
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' END TestFlag
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////



' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' BEGIN TestFlagDec
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' test the flag bits for the pervious char in the stream
'uint32_t TestFlagDec(uint8_t mem59, uint8_t mask)
'{
'    X = mem59;
'    X--;
'    A = inputtemp[X];
'    Y = A;
'    assert(Y<sizeof(tab36376));
'    A = tab36376[Y];
'    return A & mask;
'}
Function TestFlagDec~% (mem59 As Integer, mask As Long)
    X = mem59
    X = X - 1
    A = Asc(Mid$(TempInput$, X + 1, 1)) 'QB64: Access char in string, ASC gets ASCII value
    Y = A
    If Y > UBound(tab36376) Then Stop
    A = arrTab36376(Y)
    TestFlagDec = A And mask
End Function ' TestFlagDec
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' END TestFlagDec
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////



' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' BEGIN TestFlagInc
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' test the flag bits for the next char in the stream
'uint32_t TestFlagInc(uint8_t mem58, uint8_t mask)
'{
'    X = mem58;
'    X++;
'    A = inputtemp[X];
'    Y = A;
'    assert(Y<sizeof(tab36376));
'    A = tab36376[Y];
'    return A & mask;
'}
Function TestFlagInc~% (mem58 As _Unsigned _Byte, mask As _Unsigned _Byte)
    X = mem58
    X = X + 1
    A = Asc(Mid$(TempInput$, X + 1, 1)) 'QB64: Access char in string, ASC gets ASCII value
    Y = A
    If Y > UBound(tab36376) Then Stop
    A = arrTab36376(Y)
    TestFlagInc = A And mask
End Function ' TestFlagInc
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' END TestFlagInc
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////





' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' BEGIN ReciterVerify
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' verify that the reciter tables are well formed
Sub ReciterVerify ()
    Dim iIndex1 As Integer
    Dim iPos As Integer

    For iIndex1 = 0 To 27 ' Assuming rule_tab is 0-based index and has 28 elements
        iPos = arrRuleTab(iIndex1)
        ' Assuming rules is an array and QB64PE arrays are 0-based
        If arrRules(iPos) <> 93 Then ' 93 is the ASCII code for ']'
            Print "Assertion failed: arrRules(" + _Trim$(Str$(iPos)) + ") <> ']'"
            Stop
        End If
    Next iIndex1
End Sub ' ReciterVerify
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' END ReciterVerify
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////






' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' BEGIN GetRuleByte
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' lookup a byte for a specific rule in the table
Function GetRuleByte% (rule_index As Integer, Y As Integer)
    ' Assuming rules is an array of integers (since C uses uint8_t)
    Dim iEnd As Integer
    Dim index As Integer

    iEnd = UBound(rules) 'UBOUND gives the highest index
    index = rule_index + Y
    If index >= iEnd Then
        Print "Assertion failed: index < iEnd"
        Stop
    End If
    GetRuleByte = arrRules(index)
End Function ' GetRuleByte
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' END GetRuleByte
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////





' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' BEGIN SecureCopyInput
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Sub SecureCopyInput (sInput As String, max_size As Integer)
    ' secure copy of sInput because sInput will be overwritten by phonemes
    X = 1
    Y = 0
    Do While Y < max_size
        A = Asc(Mid$(sInput, Y + 1, 1)) ' QB64PE strings are 1-based index
        Y = Y + 1
        If A < 32 Then '0x20 = 32
            _Continue
        End If
        If A = 96 Then '0x60 = 96
            _Continue
        End If
        If A = 39 Then '0x27 = 39
            _Continue
        End If
        If A >= 126 Then '0x7E = 126
            _Continue
        End If
        TempInput$(X) = Chr$(A)
        X = X + 1
    Loop

    '  Null-terminate the input string (important for C compatibility)
    sInput = String$(max_size, 0) ' Fills the string with null characters (ASCII 0)
End Sub ' SecureCopyInput
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' END SecureCopyInput
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////









' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' BEGIN TextToPhonemes
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Function TextToPhonemes& (sInput As String, max_size As Long)
    Const end_token = 155 ' ESC | 0x80

    'THIS IS REFERENCED IN OTHER FUNCTIONS, DO WE DIM AS GLOBAL?
    'dim TempInput$

    Dim out_pos As Long ' output position for phonemes
    Dim mem57 As Long
    Dim mem58 As Long ' current pos, used mostly in rhs match
    Dim mem59 As Long
    Dim mem60 As Long
    Dim mem61 As Long
    Dim rule_index As Long ' memory position of current rule

    Dim mem64 As Long ' position of '=' or current character
    Dim pos_rparen As Long ' position of ')
    Dim pos_lparen As Long ' position of '(
    Dim mem36653 As Long

    'max_size = 250

    ' NOT SURE WHAT THIS STUFF IS FOR,
    ' IF WE ONLY OVERWRITE IT WITH sInput ?
    TempInput$ = Space$(256) ' Assuming TempInput$ is a string, adjust size as needed
    TempInput$ = " " + TempInput$ 'inputtemp[0] = 0x20; // '
    'SECURECOPYINPUT in$, sInput, max_size  'Need to implement SecureCopyInput (see below)
    'For simplicity, assuming a direct copy for now.  Adjust as needed for QB64 string handling
    TempInput$ = sInput ' Assuming direct copy; implement SecureCopyInput for safety

    Y = 255
    X = 255
    TempInput$ = Left$(TempInput$, X) + Chr$(27) + Mid$(TempInput$, X + 2) 'inputtemp[X] = 27; // ESC
    mem61 = 255

    A = 255
    out_pos = 255

    ' ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    ' START PARSE
    ' ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    L_start_parse:

    Do
        mem61 = mem61 + 1
        X = mem61
        ' if end of input marker
        A = Asc(Mid$(TempInput$, X + 1, 1)) 'A = inputtemp[X];
        mem64 = A
        If A = Asc("[") Then
            out_pos = out_pos + 1
            X = out_pos

            A = end_token
            'arrInput1(X] = A  '  Cannot directly assign to input string like this
            ' Assuming input is passed by reference and we modify it.  Need to convert A back to character
            sInput = Left$(sInput, X) + Chr$(A) + Mid$(sInput, X + 2) ' Modify sInput string

            ' success
            TextToPhonemes = 1
            Exit Function
        End If
        If A = Asc(".") Then
            ' check a flag for next input char?
            X = X + 1

            Y = Asc(Mid$(TempInput$, X + 1, 1)) 'Y = inputtemp[X];
            'A = TestFlag(Y, 1) '  Need to implement TestFlag (see below)
            ' Assuming TestFlag checks bit 0;  using bitwise AND for now
            A = (Y And 1) '  Simple bit check, replace with actual TestFlag if needed
            If A = 0 Then
                ' output a '.'
                out_pos = out_pos + 1
                X = out_pos
                A = Asc(".")
                'arrInput1(X] = A
                sInput = Left$(sInput, X) + Chr$(A) + Mid$(sInput, X + 2) ' Modify sInput string
            Else
                Exit Do
            End If
        Else
            Exit Do
        End If
    Loop 'while

    ' if this character is non alpha
    A = mem64
    Y = A
    'A = TestFlag(A, 255) ' Need to implement TestFlag
    ' Assuming TestFlag checks for non-alpha;  QB64's ASCII range for A-Z is 65-90
    If (A >= 65 And A <= 90) Then
        mem57 = 0 '  If it's A-Z, flag is 0 (not non-alpha)
    Else
        mem57 = 2 '  Otherwise, set flag bit 1 (0x02)
    End If 'Simplified, replace with actual TestFlag

    If (mem57 And 2) Then 'if (A & 0x02)
        rule_index = arrRuleTab(27) ' Assuming rule_tab is an array, and we have 27 elements
        GoTo L_nextrule '  Use GOTO with caution, consider refactoring
    End If

    ' what be this ???
    A = mem57 ' flag for A
    If A = 0 Then
        A = Asc(" ")
        TempInput$ = Left$(TempInput$, X) + Chr$(A) + Mid$(TempInput$, X + 2) 'inputtemp[X] = A;
        out_pos = out_pos + 1
        X = out_pos
        ' hard exit on too long?
        If X > max_size Then
            'arrInput1(max_size - 1] = end_token
            sInput = Left$(sInput, max_size) + Chr$(end_token) + Mid$(sInput, max_size + 2)
            A = mem61
            mem36653 = A
            TextToPhonemes = 0
            Exit Function
        Else
            'arrInput1(X] = A
            sInput = Left$(sInput, X) + Chr$(A) + Mid$(sInput, X + 2)
            GoTo L_start_parse
        End If
    End If

    ' what is A at this point?
    A = mem57 And 128 '0x80 in decimal
    If A = 0 Then
        ' error
        TextToPhonemes = 0
        Exit Function
    End If

    ' go to the right rules for this character.
    X = mem64 - Asc("A")
    'assert(X<26);  ' QB64 doesn't have assert;  can add a check if needed
    If X < 0 Or X > 25 Then
        ' Handle out-of-bounds,  e.g.,  PRINT "Error: Invalid character";  RETURN
        Print "Error: Invalid character";
        TextToPhonemes = 0
        Exit Function
    End If
    rule_index = arrRuleTab(X + 1) ' QB64 arrays are 1-based

    '// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    '// TRY MATCHING NEXT RULE
    '// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    L_nextrule:
    '// find next rule
    '// skip to next rule byte with 0x80 mask
    Y = 0
    Do
        rule_index = rule_index + 1
        A = GetRuleByte(rule_index, Y) '//Need to define GetRuleByte function
    Loop While (A And &H80) = 0 '// (A&0x80)==0
    Y = Y + 1
    '// if there are no more rules in this set
    If GetRuleByte(rule_index, Y) = Asc("]") Then '// GetRuleByte(rule_index, Y)==']'
        TextToPhonemes& = 0
        Exit Function
    End If
    '// identify key points in this rule
    '// find '('
    Do
        '// fixme: fix infinite loop here with ' chars
        A = GetRuleByte(rule_index, Y)
        ' assert((A & 0x80)==0);   '// QB64 doesn't have assert, consider a conditional check
        If (A And &H80) <> 0 Then Stop '//  If assert fails, stop execution
        If A = Asc("(") Then Exit Do '// if (A == '(')
        Y = Y + 1
    Loop
    pos_lparen = Y
    '// find ')'
    Do
        Y = Y + 1
        A = GetRuleByte(rule_index, Y)
    Loop While A <> Asc(")") '// A != ')'
    pos_rparen = Y
    '// find '='
    Do
        Y = Y + 1
        A = GetRuleByte(rule_index, Y)
        A = A And &H7F '// A = A & 0x7F;
    Loop While A <> Asc("=") '// A != '='
    mem64 = Y
    X = mem61
    mem60 = X
    '// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    '// MATCH EXPRESSION IN PARENTHESIS
    '// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    Y = pos_lparen
    Y = Y + 1
    '// pos36759:
    Do
        mem57 = Asc(Mid$(TempInput$, X + 1, 1)) '// mem57 = inputtemp[X];
        A = GetRuleByte(rule_index, Y)
        If A <> mem57 Then '// if (A!=mem57)
            '// no match lets apply next rule
            GoTo L_nextrule
        End If
        Y = Y + 1
        If Y = pos_rparen Then Exit Do '// if (Y==pos_rparen)
        X = X + 1
        mem60 = X
    Loop
    '// the string in the bracket is correct
    '// pos36787:
    A = mem61
    mem59 = mem61

    '---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    'MATCH TO LEFT OF ( IN RULE
    '---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    L_match_left:
    ' scan back to find start?
    Do
        pos_lparen = pos_lparen - 1
        Y = pos_lparen
        A = GetRuleByte(rule_index, Y) 'Need equivalent QB64 function. See below
        mem57 = A
        ' if end of lhs pattern
        If (A And &H80) Then ' Check if the most significant bit is set
            A = mem60
            mem58 = A
            GoTo L_match_right ' QB64 uses GOTO
        End If
        '
        X = A And &H7F ' all but msb
        A = TestFlag(X, &H80) 'Need equivalent QB64 function.  See below
        If (A = 0) Then
            ' parse special escape rule
            Exit Do ' QB64 uses EXIT DO to exit a DO loop
        End If
        X = mem59 - 1
        A = inputtemp(X) ' TODO: NEED TO RECONCILE inputtemp() vs TempInput$ ?
        If (A <> mem57) Then
            GoTo L_nextrule ' QB64 uses GOTO
        End If
        mem59 = X
    Loop

    ' test for special escape chars
    A = mem57
    Select Case A
        Case 32 ' " "
            GoTo pos36895
        Case 35 ' "#"
            GoTo pos36910
        Case 46 ' "."
            GoTo pos36920
        Case 38 ' "&"
            GoTo pos36935
        Case 64 ' "@"
            GoTo pos36967
        Case 94 ' "^"
            GoTo pos37004
        Case 43 ' "+"
            GoTo pos37019
        Case 58 ' ":"
            GoTo pos37040
        Case Else
            ' error
            TextToPhonemes& = 0
            Exit Function
    End Select

    '---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    pos36895: ' handle " "
    A = TestFlagDec(mem59, &H80)
    If (A = 0) Then
        mem59 = X
        GoTo L_match_left
    End If
    GoTo L_nextrule

    '---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    pos36910: ' handle "#"
    A = TestFlagDec(mem59, &H40) 'Need equivalent QB64 function.  See below
    If (A <> 0) Then
        mem59 = X
        GoTo L_match_left
    End If
    GoTo L_nextrule

    '---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    pos36920: ' handle "."
    A = TestFlagDec(mem59, &H08) 'Need equivalent QB64 function.  See below
    If (A <> 0) Then
        mem59 = X
        GoTo L_match_left
    End If
    GoTo L_nextrule


    ' ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    pos36935: ' handle '&
    A = TestFlagDec(mem59, 16) '0x10
    If A <> 0 Then
        mem59 = X
        GoTo L_match_left
    End If
    A = Asc(Mid$(TempInput$, X + 1, 1))
    If A = Asc("H") Then
        X = X - 1
        A = Asc(Mid$(TempInput$, X + 1, 1))
        If (A = Asc("C")) Or (A = Asc("S")) Then
            mem59 = X
            GoTo L_match_left
        End If
    End If
    GoTo L_nextrule

    ' ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    pos36967: ' handle '@
    A = TestFlagDec(mem59, 4) '0x04
    If A <> 0 Then
        mem59 = X
        GoTo L_match_left
    End If
    A = Asc(Mid$(TempInput$, X + 1, 1))
    If (A <> Asc("H")) And (A <> Asc("T")) And (A <> Asc("C")) And (A <> Asc("S")) Then
        GoTo L_nextrule
    End If
    mem59 = X
    GoTo L_match_left

    ' ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    pos37004: ' handle '^
    A = TestFlagDec(mem59, 32) '0x20
    If A <> 0 Then
        mem59 = X
        GoTo L_match_left
    End If
    GoTo L_nextrule


    ' ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    pos37019: ' handle '+
    X = mem59
    X = X - 1
    A = Asc(Mid$(TempInput$, X, 1)) ' Assuming TempInput$ is a string version
    If (A = Asc("E")) Or (A = Asc("I")) Or (A = Asc("Y")) Then
        mem59 = X
        GoTo L_match_left
    End If
    GoTo L_nextrule

    ' ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    pos37040: ' handle ':
    A = TestFlagDec(mem59, &H20) ' Assuming TestFlagDec is a QB64 FUNCTION
    If A <> 0 Then
        mem59 = X
        GoTo pos37040
    End If
    GoTo L_match_left

    ' ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    pos37077: ' handle '%
    X = mem58 + 1
    A = Asc(Mid$(TempInput$, X, 1))
    If A <> Asc("E") Then
        GoTo L_match_ing
    End If
    X = X + 1
    Y = Asc(Mid$(TempInput$, X, 1))
    X = X - 1
    A = TestFlag(Y, &H80) ' Assuming TestFlag is a QB64 FUNCTION
    If A <> 0 Then
        X = X + 1
        A = Asc(Mid$(TempInput$, X, 1))
        If A <> Asc("R") Then
            GoTo pos37113
        End If
    End If
    mem58 = X
    GoTo L_match_right

    '
    '// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    'pos37113: // unknown ???
    pos37113:
    If (A = Asc("S")) Or (A = Asc("D")) Then
        mem58 = X
        GoTo L_match_right
    End If
    If A <> Asc("L") Then
        GoTo pos37135
    End If
    X = X + 1
    A = Asc(Mid$(TempInput$, X + 1, 1))
    If A <> Asc("Y") Then
        GoTo L_nextrule
    End If
    mem58 = X
    GoTo L_match_right

    'pos37135: // match FUV
    pos37135:
    If A <> Asc("F") Then
        GoTo L_nextrule
    End If
    X = X + 1
    A = Asc(Mid$(TempInput$, X + 1, 1))
    If A <> Asc("U") Then
        GoTo L_nextrule
    End If
    X = X + 1
    A = Asc(Mid$(TempInput$, X + 1, 1))
    If A <> Asc("V") Then
        GoTo L_nextrule
    End If
    mem58 = X
    GoTo L_match_right

    'L_match_ing: // match 'ING'
    L_match_ing:
    If A <> Asc("I") Then
        GoTo L_nextrule
    End If
    X = X + 1
    A = Asc(Mid$(TempInput$, X + 1, 1))
    If A <> Asc("N") Then
        GoTo L_nextrule
    End If
    X = X + 1
    A = Asc(Mid$(TempInput$, X + 1, 1))
    If A <> Asc("G") Then
        GoTo L_nextrule
    End If
    mem58 = X
    GoTo L_match_right

    '// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    '// MATCH RIGHT OF ) IN RULE
    '// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    L_match_right:
    Y = pos_rparen + 1
    If Y = mem64 Then
        GoTo L_emitrule
    End If
    pos_rparen = Y
    'A = GetRuleByte(rule_index, Y);
    'Need to define GetRuleByte function
    'A = GetRuleByte(rule_index, Y)
    'For now, placeholder:
    A = 0 ' Placeholder
    mem57 = A
    X = A
    'A = TestFlag(X, 0x80);
    'Need to define TestFlag function
    'A = TestFlag(X, &H80)
    'For now, placeholder:
    A = 0 'Placeholder
    If A = 0 Then
        A = mem57
        Select Case A
            Case Asc(" "): GoTo pos37295
            Case Asc("#"): GoTo pos37310
            Case Asc("."): GoTo pos37320
            Case Asc("&"): GoTo pos37335
            Case Asc("@"): GoTo pos37367
            Case Asc("^"): GoTo pos37404
            Case Asc("+"): GoTo pos37419
            Case Asc(":"): GoTo pos37440
            Case Asc("%"): GoTo pos37077
            Case Else
                '// error
                ' return 0;
                'PRINT "Error"
                'END 'Instead of return, you might want to handle this differently
                'GOTO ExitSub ' Add an exit label
                TextToPhonemes& = -1
        End Select
    Else
        '// what this does ??
        X = mem58 + 1
        A = Asc(Mid$(TempInput$, X + 1, 1))
        If A <> mem57 Then
            GoTo L_nextrule
        End If
        mem58 = X
        GoTo L_match_right
    End If


    ' ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    pos37295: ' handle '
    A = TestFlagInc(mem58, &H80)
    If A <> 0 Then
        GoTo L_nextrule
    End If
    mem58 = X
    GoTo L_match_right

    ' ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    pos37310: ' handle '#
    A = TestFlagInc(mem58, &H40)
    If A <> 0 Then
        mem58 = X
        GoTo L_match_right
    End If
    GoTo L_nextrule

    ' ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    pos37320: ' handle '.
    A = TestFlagInc(mem58, &H08)
    If A = 0 Then
        GoTo L_nextrule
    End If
    mem58 = X
    GoTo L_match_right

    ' ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    pos37335: ' handle '&
    A = TestFlagInc(mem58, &H10)
    If A <> 0 Then
        mem58 = X
        GoTo L_match_right
    End If
    A = Asc(Mid$(TempInput$, X + 1, 1)) ' Corrected index
    If A <> Asc("H") Then
        GoTo L_nextrule
    End If
    ' is this really x++ not x--?
    X = X + 1
    A = Asc(Mid$(TempInput$, X + 1, 1)) ' Corrected index

    If (A = Asc("C")) Or (A = Asc("S")) Then
        mem58 = X
        GoTo L_match_right
    End If
    GoTo L_nextrule

    ' ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    pos37367: ' handle '@'
    A = TestFlagInc(mem58, 4) ' 0x04
    If A <> 0 Then
        mem58 = X
        GoTo L_match_right
    End If
    A = inputtemp(X)
    If (A <> Asc("H")) And (A <> Asc("T")) And (A <> Asc("C")) And (A <> Asc("S")) Then
        GoTo L_nextrule
    End If
    mem58 = X
    GoTo L_match_right

    ' ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    pos37404: ' handle '^'
    A = TestFlagInc(mem58, 32) ' 0x20
    If A = 0 Then
        GoTo L_nextrule
    End If
    mem58 = X
    GoTo L_match_right

    ' ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    pos37419: ' handle '+'
    X = mem58
    X = X + 1
    A = inputtemp(X)
    If (A = Asc("E")) Or (A = Asc("I")) Or (A = Asc("Y")) Then
        mem58 = X
        GoTo L_match_right
    End If
    GoTo L_nextrule

    ' ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    pos37440: ' handle ':'
    Do
        A = TestFlagInc(mem58, 32) ' 0x20
        If A = 0 Then
            GoTo L_match_right
        End If
        mem58 = X
    Loop
    GoTo L_emitrule

    '// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    '// EMIT RULE
    '// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    L_emitrule:
    Y = mem64
    mem61 = mem60

    'if bDebug then  ' Assuming 'debug' is a global variable.
    '  PrintRule rule_index '  Assuming PrintRule is a function.
    'end if

    Do
        Y = Y + 1
        'A = GetRuleByte(rule_index, Y) ' Assuming GetRuleByte is a function.
        ' Placeholder for GetRuleByte
        ' A = GetRuleByte(rule_index, Y)  ' Needs QB64 Implementation
        ' Need to know how GetRuleByte works

        mem57 = A
        ' mask out parity
        A = A And 127 '// 0x7f

        If A <> Asc("=") Then
            out_pos = out_pos + 1
            X = out_pos
            'arrInput1(X] = A  ' Since 'input' is a string, we can't directly assign an integer to an index.
            Mid$(sInput, X + 1, 1) = Chr$(A) ' QB64 strings are 1-based index, C arrays are 0-based.
        End If

        ' if has parity set
        If (mem57 And 128) <> 0 Then ' //0x80
            GoTo L_start_parse
        End If
    Loop


    TextToPhonemes = out_pos
End Function ' TextToPhonemes&
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' END
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////





' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' BEGIN Render
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' RENDER THE PHONEMES IN THE LIST
'
' The phoneme list is converted into sound through the steps:
'
' 1. Copy each phoneme <length> number of times into the frames list,
'    where each frame represents 10 milliseconds of sound.
'
' 2. Determine the transitions lengths between phonemes, and linearly
'    interpolate the values across the frames.
'
' 3. Offset the pitches by the fundamental frequency.
'
' 4. Render the each frame.

Sub Render
    Dim phase1 As _Unsigned _Byte : phase1 = 0 ' mem43
    Dim phase2 As _Unsigned _Byte
    Dim phase3 As _Unsigned _Byte
    Dim mem66 As _Unsigned _Byte
    Dim mem38 As _Unsigned _Byte
    Dim mem40 As _Unsigned _Byte
    Dim speedcounter As _Unsigned _Byte ' mem45
    Dim mem48 As _Unsigned _Byte
    Dim i As Integer
    Dim carry As Integer

    If arrPhoIndexOutput(0) = 255 Then
        Exit Sub 'exit if no data
    End If

    A = 0
    X = 0
    mem44 = 0

    ' CREATE FRAMES
    '
    ' The length parameter in the list corresponds to the number of frames
    ' to expand the phoneme to.
    ' Each frame represents 10 milliseconds of time.
    ' So a phoneme with a length of 7 = 7 frames = 70 milliseconds duration.
    '
    ' The parameters are copied from the phoneme to the frame verbatim.

    Do
        ' get the index
        Y = mem44
        ' get the phoneme at the index
        A = arrPhoIndexOutput(mem44)
        mem56 = A
        ' if terminal phoneme, exit the loop
        If A = 255 Then Exit Do

        ' period phoneme *.
        If A = 1 Then
            ' add rising inflection
            A = 1
            mem48 = 1
            'goto pos48376;
            AddInflection mem48, phase1
        End If
        'question mark phoneme?
        If A = 2 Then
            ' create falling inflection
            mem48 = 255
            AddInflection mem48, phase1
        End If
        '    pos47615:

        ' get the stress amount (more stress = higher pitch)
        phase1 = arrTab47492(arrStressOutput(Y) + 1)

        ' get number of frames to write
        phase2 = arrPhoLengthOutput(Y)
        Y = mem56

        ' copy from the source to the frames list
        Do
            frequency1(X) = arrFreq1Data(Y) ' F1 frequency
            frequency2(X) = arrFreq2Data(Y) ' F2 frequency
            frequency3(X) = arrFreq3Data(Y) ' F3 frequency
            amplitude1(X) = arrAmp1Data(Y) ' F1 amplitude
            amplitude2(X) = arrAmp2Data(Y) ' F2 amplitude
            amplitude3(X) = arrAmp3Data(Y) ' F3 amplitude
            sampledConsonantFlag(X) = arrSampledConsonantFlags(Y) ' phoneme data for sampled consonants
            arrPitches(X) = pitch + phase1 ' pitch
            X = X + 1
            phase2 = phase2 - 1
        Loop Until phase2 = 0
        mem44 = mem44 + 1
    Loop Until mem44 = 0


    '// -------------------
    '//pos47694:

    '// CREATE TRANSITIONS
    '{here}

    A = 0
    mem44 = 0
    mem49 = 0 '// mem49 starts at as 0
    X = 0
    While -1 '//while No. 1
        '// get the current and following phoneme
        Y = arrPhoIndexOutput(X)
        A = arrPhoIndexOutput(X + 1)
        X = X + 1

        '// exit loop at end token
        If A = 255 Then
            Exit While
        End If
        '//goto pos47970;

        '// get the ranking of each phoneme
        X = A
        mem56 = arrBlendRank(A)
        A = arrBlendRank(Y)

        '// compare the rank - lower rank value is stronger
        If A = mem56 Then
            '// same rank, so use out blend lengths from each phoneme
            phase1 = arrOutBlendLength(Y)
            phase2 = arrOutBlendLength(X)
        ElseIf A < mem56 Then
            '// first phoneme is stronger, so us it's blend lengths
            phase1 = arrInBlendLength(X)
            phase2 = arrOutBlendLength(X)
        Else
            '// second phoneme is stronger, so use it's blend lengths
            '// note the out/in are swapped
            phase1 = arrOutBlendLength(Y)
            phase2 = arrInBlendLength(Y)
        End If

        Y = mem44
        A = mem49 + arrPhoLengthOutput(mem44)
        '// A is mem49 + length
        mem49 = A
        '// mem49 now holds length + position
        A = A + phase2
        '//Maybe Problem because of carry flag

        '//47776: ADC 42
        speedcounter = A
        mem47 = 168
        phase3 = mem49 - phase1 '// what is mem49
        A = phase1 + phase2
        '// total transition?
        mem38 = A

        X = A
        X = X - 2
        If (X And 128) = 0 Then
            Do '//while No. 2
                '//pos47810:

                '// mem47 is used to index the tables:
                '// 168  pitches[]

                '// 169  frequency1
                '// 170  frequency2
                '// 171  frequency3
                '// 172  amplitude1
                '// 173  amplitude2

                '// 174  amplitude3

                mem40 = mem38
                If mem47 = 168 Then '// pitch
                    '// unlike the other values, the pitches[] interpolates from
                    '// the middle of the current phoneme to the middle of the
                    '// next phoneme

                    Dim mem36 As _Unsigned Integer, mem37 As _Unsigned Integer
                    '// half the width of the current phoneme
                    mem36 = arrPhoLengthOutput(mem44) \ 2
                    '// half the width of the next phoneme
                    mem37 = arrPhoLengthOutput(mem44 + 1) \ 2
                    '// sum the values
                    mem40 = mem36 + mem37
                    '// length of both halves
                    mem37 = mem37 + mem49
                    '// center of next phoneme
                    mem36 = mem49 - mem36
                    '// center index of current phoneme

                    ' ****************************************************************************************************************************************************************
                    ' *** NOT SURE WHAT THIS IS:
                    'A = Read(mem47, mem37)
                    ' ****************************************************************************************************************************************************************

                    '// value at center of next phoneme - end interpolation value
                    '//A = mem[address];
                    Y = mem36 '// start index of interpolation

                    ' ****************************************************************************************************************************************************************
                    ' *** NOT SURE WHAT THIS IS:
                    'mem53 = A - Read(mem47, mem36)
                    ' ****************************************************************************************************************************************************************

                    '// value to center of current phoneme
                Else
                    '// value to interpolate to

                    ' ****************************************************************************************************************************************************************
                    ' *** NOT SURE WHAT THIS IS:
                    'A = Read(mem47, speedcounter)
                    ' ****************************************************************************************************************************************************************

                    '// position to start interpolation from
                    Y = phase3
                    '// value to interpolate from

                    ' ****************************************************************************************************************************************************************
                    ' *** NOT SURE WHAT THIS IS:
                    'mem53 = A - Read(mem47, phase3)
                    ' ****************************************************************************************************************************************************************


                End If

                '//Code47503(mem40);
                '// ML : Code47503 is division with remainder, and mem50 gets the sign

                '// calculate change per frame
                mem50 = IIf(Sgn(mem53) = -1, 128, 0)
                mem51 = Abs(mem53) Mod mem40
                mem53 = mem53 \ mem40
                '// interpolation range
                X = mem40
                '// number of frames to interpolate over
                Y = phase3
                '// starting frame

                '// linearly interpolate values

                mem56 = 0
                '//47907: CLC
                '//pos47908:
                While -1 '//while No. 3

                    ' ****************************************************************************************************************************************************************
                    ' *** NOT SURE WHAT THIS IS:
                    'A = Read(mem47, Y) + mem53
                    ' ****************************************************************************************************************************************************************


                    '//carry alway cleared

                    mem48 = A
                    Y = Y + 1
                    X = X - 1
                    If X = 0 Then
                        Exit While
                    End If
                    mem56 = mem56 + mem51
                    If mem56 >= mem40 Then '//???
                        mem56 = mem56 - mem40
                        '//carry? is set
                        '//if ((mem56 & 128)=0)
                        If (mem50 And 128) = 0 Then
                            '//47935: BIT 50
                            '//47937: BMI 47943
                            If mem48 <> 0 Then
                                mem48 = mem48 + 1
                            End If
                        Else
                            mem48 = mem48 - 1
                        End If
                    End If
                    '//pos47945:
                    Write mem47, Y, mem48
                Wend '//while No. 3

                '//pos47952:
                mem47 = mem47 + 1
                '//if (mem47 != 175) goto pos47810;
            Loop Until mem47 = 175 '//while No. 2
        End If
        '//pos47963:
        mem44 = mem44 + 1
        X = mem44
    Wend '//while No. 1

    '//goto pos47701;
    '//pos47970:

    ' add the length of this phoneme
    mem48 = mem49 + arrPhoLengthOutput(mem44)

    ' ASSIGN PITCH CONTOUR
    '
    ' This subtracts the F1 frequency from the pitch to create a
    ' pitch contour.
    ' Without this, the output would be at a single
    ' pitch level (monotone).
    ' don't adjust pitch if in sing mode
    If singmode = 0 Then
        ' iterate through the buffer
        For i = 0 To 255
            ' subtract half the frequency of the formant 1.
            ' this adds variety to the voice
            arrPitches(i) = arrPitches(i) - (frequency1(i) \ 2)
        Next i
    End If

    phase1 = 0
    phase2 = 0
    phase3 = 0
    mem49 = 0
    speedcounter = 72 'sam standard speed

    ' RESCALE AMPLITUDE
    '
    ' Rescale volume from a linear scale to decibels.
    '
    'amplitude rescaling
    For i = 255 To 0 Step -1
        amplitude1(i) = arrAmplitudeRescale(amplitude1(i))
        amplitude2(i) = arrAmplitudeRescale(amplitude2(i))
        amplitude3(i) = arrAmplitudeRescale(amplitude3(i))
    Next i

    Y = 0
    A = arrPitches(0)
    mem44 = A
    X = A
    mem38 = A - (A \ 4) ' 3/4*A ???
    If bDebug Then
        PrintOutput sampledConsonantFlag, frequency1, frequency2, frequency3, amplitude1, amplitude2, amplitude3, pitches
    End If

    ' PROCESS THE FRAMES
    '
    ' In traditional vocal synthesis, the glottal pulse drives filters, which
    ' are attenuated to the frequencies of the formants.
    '
    ' SAM generates these formants directly with sin and rectangular waves.
    ' To simulate them being driven by the glottal pulse, the waveforms are
    ' reset at the beginning of each glottal pulse.
    'finally the loop for sound output
    'pos48078:
    Do
        ' get the sampled information on the phoneme
        A = sampledConsonantFlag(Y)
        mem39 = A

        ' unvoiced sampled phoneme?
        A = A And 248
        If A <> 0 Then
            ' render the sample for the phoneme
            RenderSample mem66
            ' skip ahead two in the phoneme buffer
            Y = Y + 2
            mem48 = mem48 - 2
        Else
            ' simulate the glottal pulse and formants
            mem56 = arrMultTable(BINAND(arrSinus(phase1), amplitude1(Y)))

            carry = 0
            If (mem56 + arrMultTable(BINAND(arrSinus(phase2), amplitude2(Y)))) > 255 Then
                carry = 1
            End If
            mem56 = mem56 + arrMultTable(BINAND(arrSinus(phase2), amplitude2(Y)))
            A = mem56 + arrMultTable(BINAND(arrRectangle(phase3), amplitude3(Y))) + (IIf(carry = 1, 1, 0))
            A = ((A + 136) And 255) \ 16 'there must be also a carry
            'mem[54296] = A;
            ' output the accumulated value

            ' ****************************************************************************************************************************************************************
            ' *** NOT SURE WHAT THIS IS:
            'Output 0, A
            ' ****************************************************************************************************************************************************************

            speedcounter = speedcounter - 1
            If speedcounter <> 0 Then
                GoTo pos48155
            End If
            Y = Y + 1 'go to next amplitude

            ' decrement the frame count
            mem48 = mem48 - 1
        End If

        ' if the frame count is zero, exit the loop
        If mem48 = 0 Then
            Exit Do
        End If
        speedcounter = speed
        pos48155:

        ' decrement the remaining length of the glottal pulse
        mem44 = mem44 - 1
        ' finished with a glottal pulse?
        If mem44 = 0 Then
            pos48159:
            ' fetch the next glottal pulse length
            A = arrPitches(Y)
            mem44 = A
            A = A - (A \ 4)
            mem38 = A
            ' reset the formant wave generators to keep them in
            ' sync with the glottal pulse
            phase1 = 0
            phase2 = 0
            phase3 = 0

            _Continue
        End If

        ' decrement the count
        mem38 = mem38 - 1
        ' is the count non-zero and the sampled flag is zero?
        If (mem38 <> 0) Or (mem39 = 0) Then
            ' reset the phase of the formants to match the pulse
            phase1 = phase1 + frequency1(Y)
            phase2 = phase2 + frequency2(Y)
            phase3 = phase3 + frequency3(Y)

            _Continue


        End If

        ' voiced sampled phonemes interleave the sample with the
        ' glottal pulse. The sample flag is non-zero, so render
        ' the sample for the phoneme.
        RenderSample mem66
        GoTo pos48159
    Loop 'while

    '#IF 0
    ' The following code is never reached. It's left over from when
    ' the voiced sample code was part of this loop, instead of part
    ' of RenderSample();
    '#ENDIF
    'pos48315:
    '    DIM tempA AS Integer
    '    phase1 = A XOR 255
    '    Y = mem66
    '    DO
    'pos48321:
    '
    '        mem56 = 8
    '        A = Read(mem47, Y)
    '
    'pos48327:
    '        DO
    '            '48327: ASL A
    '            '48328: BCC 48337
    '            tempA = A
    '            A = A SHL 1
    '            IF (tempA AND 128) <> 0 THEN
    '                X = 26
    '                ' mem[54296] = X;
    '                bufferPos = bufferPos + 150
    '                buffer(bufferPos / 50) = (X AND 15) * 16
    '            ELSE
    '                'mem[54296] = 6;
    '                X = 6
    '                bufferPos = bufferPos + 150
    '                buffer(bufferPos / 50) = (X AND 15) * 16
    '            END IF
    '
    '            FOR X = wait2 TO 1 STEP -1
    '                'wait
    '            NEXT X
    '            mem56 = mem56 - 1
    '        LOOP WHILE mem56 <> 0
    '
    '        Y = Y + 1
    '        phase1 = phase1 + 1
    '    LOOP WHILE phase1 <> 0
    '    '    IF phase1 <> 0 GOTO pos48321
    '    A = 1
    '    mem44 = 1
    '    mem66 = Y
    '    Y = mem49
    '    RETURN
    '#IF 0
    'END IF
End Sub ' Render
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' END Render
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

















' SUBROUTINES and FUNCTIONS

' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' BEGIN AddInflection
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Sub AddInflection (mem48 As _Byte, phase1 As _Byte)
    ' store the location of the punctuation
    mem49 = X
    A = X
    Atemp = A

    ' backup 30 frames
    A = A - 30

    ' if index is before buffer, point to start of buffer
    If Atemp <= 30 Then
        A = 0
    End If
    X = A

    ' FIXME: Explain this fix better, it's not obvious
    ' ML : A =, fixes a problem with invalid pitch with '.'
    Do While arrPitches(X) = 127
        X = X + 1
    Loop

    ' add the inflection direction
    A = A + mem48
    phase1 = A

    ' set the inflection
    arrPitches(X) = A

    ' increment the position
    X = X + 1

    ' exit if the punctuation has been reached
    If X = mem49 Then
        Exit Sub
    End If

    'goto pos47615;
    If arrPitches(X) = 255 Then
        GoTo pos48406
    End If
    A = phase1
    GoTo pos48398

    pos48406:

    pos48398:
    '48398: CLC  (Carry flag is handled implicitly in QB64 addition)
    '48399: ADC 48
    ' QB64 doesn't have direct carry flag manipulation like assembly,
    ' so addition handles carries naturally.
End Sub ' AddInflection
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' END AddInflection
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////



' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' BEGIN SetMouthThroat
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Sub SetMouthThroat (mouth As _Byte, throat As _Byte)
    Dim initialFrequency As _Byte, newFrequency As _Byte
    Dim posV As _Byte ' *** original variable name "pos" is reserved in QB64
    dim iIndex1 as integer
   
   

    ' mouth formants (F1) 5..29
    'const uint8_t mouthFormants5_29[30] = {
    ReDim arrMouthFormants5_29(29) As _Byte
mouthFormants5_29Data:
    data 0, 0, 0, 0, 0, 10
    data 14, 19, 24, 27, 23, 21, 16, 20, 14, 18, 14, 18, 18
    data 16, 13, 15, 11, 18, 14, 11, 9, 6, 6, 6
    restore mouthFormants5_29Data
    For iIndex1 = 0 To 29
        Read arrMouthFormants5_29(iIndex1)
    Next iIndex1
   
   
    ' throat formants (F2) 5..29
    'const uint8_t throatFormants5_29[30] = {
    ReDim arrThroatFormants5_29(29) As _Byte
throatFormants5_29Data:
    data 255, 255
    data 255, 255, 255, 84, 73, 67, 63, 40, 44, 31, 37, 45, 73, 49
    data 36, 30, 51, 37, 29, 69, 24, 50, 30, 24, 83, 46, 54, 86
    restore throatFormants5_29Data
    For iIndex1 = 0 To 29
        Read arrThroatFormants5_29(iIndex1)
    Next iIndex1
   
   
    ' there must be no zeros in this 2 tables
    ' formant 1 frequencies (mouth) 48..53
   
    'const uint8_t mouthFormants48_53[6] = { 19, 27, 21, 27, 18, 13 };
     ReDim arrMouthFormants48_53(5) As _Byte
mouthFormants48_53Data:
    data 19, 27, 21, 27, 18, 13
    restore mouthFormants48_53Data
    For iIndex1 = 0 To 5
        Read arrMouthFormants48_53(iIndex1)
    Next iIndex1
   
    ' formant 2 frequencies (throat) 48..53
    'const uint8_t throatFormants48_53[5] = { 72, 39, 31, 43, 30, 34 };
     ReDim arrThroatFormants48_53(5) As _Byte
throatFormants48_53Data:
    data 72, 39, 31, 43, 30, 34
    restore throatFormants48_53Data
    For iIndex1 = 0 To 5
        Read arrThroatFormants48_53(iIndex1)
    Next iIndex1


    posV = 5 ' mem39216
    'pos38942:
    ' recalculate formant frequencies 5..29 for the mouth (F1) and throat (F2)
    Do While posV <> 30
        ' recalculate mouth frequency
        initialFrequency = arrMouthFormants5_29(posV)
        If initialFrequency <> 0 Then
            newFrequency = trans(mouth, initialFrequency)
        End If
        arrFreq1Data(posV) = newFrequency

        ' recalculate throat frequency
        initialFrequency = arrThroatFormants5_29(posV)
        If initialFrequency <> 0 Then
            newFrequency = trans(throat, initialFrequency)
        End If
        arrFreq2Data(posV) = newFrequency
        posV = posV + 1
    Loop

    'pos39059:
    ' recalculate formant frequencies 48..53
    posV = 48
    Y = 0
    Do While posV <> 54
        ' recalculate F1 (mouth formant)
        initialFrequency = arrMouthFormants48_53(Y)
        newFrequency = trans(mouth, initialFrequency)
        arrFreq1Data(posV) = newFrequency

        ' recalculate F2 (throat formant)
        initialFrequency = arrThroatFormants48_53(Y)
        newFrequency = trans(throat, initialFrequency)
        arrFreq2Data(posV) = newFrequency
        Y = Y + 1
        posV = posV + 1
    Loop
End Sub ' SetMouthThroat
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' END SetMouthThroat
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////





' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' BEGIN trans
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
'return = (mem39212*mem39213) >> 1
Function trans% (mem39212 As _Byte, mem39213 As _Byte)
    'pos39008:
    Dim carry As _Byte
    Dim temp As Integer ' Using INTEGER for intermediate calculations to avoid overflow
    Dim mem39214 As _Byte, mem39215 As _Byte
    A = 0
    mem39215 = 0
    mem39214 = 0
    X = 8
    Do
        carry = mem39212 And 1
        mem39212 = mem39212 \ 2 ' Integer division for right shift

        If carry <> 0 Then
            carry = 0
            A = mem39215
            temp = A + mem39213
            A = A + mem39213
            If temp > 255 Then
                carry = 1
            End If
            mem39215 = A
        End If
        temp = mem39215 And 1
        mem39215 = (mem39215 \ 2) Or (carry * 128)
        carry = temp
        X = X - 1
    Loop Until X = 0

    temp = mem39214 And 128
    mem39214 = (mem39214 * 2) Or carry
    carry = temp
    temp = mem39215 And 128
    mem39215 = (mem39215 * 2) Or carry
    carry = temp

    trans% = mem39215
End Function ' trans%
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' END trans
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////





' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' BEGIN RenderSample
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' Subroutine equivalent to the C function RenderSample
SUB RenderSample(mem66 as _OFFSET)
    dim tempA AS INTEGER
   
    ' current phoneme's index
    mem49 = Y  ' [cite: 1]

7
    ' mask low three bits and subtract 1 get value to
    ' convert 0 bits on unvoiced samples.
    A = mem39 AND 7  'Bitwise AND [cite: 3]
    X = A - 1

    ' store the result
    mem56 = X  ' [cite: 3]

    ' determine which offset to use from table { 0x18, 0x1A, 0x17, 0x17, 0x17 }
    ' T, S, Z                0          0x18
    ' CH, J, SH, ZH          1          0x1A
    ' P, F*, V, TH, DH       2         
    '  0x17
    ' /H                     3          0x17
    ' /X                     4          0x17

    ' get value from the table
    mem53 = tab48426(X)  ' [cite: 5]
    mem47 = X '46016+mem[56]*256  ' [cite: 6]

    ' voiced sample?
    A = mem39 AND 248  'Bitwise AND [cite: 6, 7]
    IF A = 0 THEN
        ' voiced phoneme: Z*, ZH, V*, DH
        Y = mem49  ' [cite: 7]
        A = pitches(mem49) \ 16  'Integer Division [cite: 8]

        ' jump to voiced portion
        GOTO pos48315  ' [cite: 8]
    END IF

    Y = A XOR 255  'Bitwise XOR [cite: 9]
pos48274:

    ' step through the 8 bits in the sample
    mem56 = 8  ' [cite: 9, 10]
    ' get the next sample from the table
    ' mem47*256 = offset to start of samples
    A = sampleTable(mem47 * 256 + Y)  ' [cite: 10]
pos48280:

    ' left shift to get the high bit
    tempA = A  ' [cite: 11, 12, 13]
    A = A * 2  'Left shift [cite: 12]
    '48281: BCC 48290

    ' bit not set?
    IF (tempA AND 128) = 0 THEN  ' [cite: 13]
        ' convert the bit to value from table
        X = mem53  ' [cite: 13, 14, 15]
        'mem[54296] = X;
        ' output the byte
        'Implementation of Output needs context.  Using PRINT for now
        PRINT CHR$(X);
        'Output 1, X  ' [cite: 14]
        ' if X != 0, exit loop
        IF X <> 0 THEN GOTO pos48296  ' [cite: 15]
    END IF

    ' output a 5 for the on bit
     'Implementation of Output needs context.  Using PRINT for now
    PRINT CHR$(5);
    'Output 2, 5  ' [cite: 16, 17]
'48295: NOP
pos48296:

    X = 0  ' [cite: 17]

    ' decrement counter
    mem56 = mem56 - 1  ' [cite: 17, 18]
    ' if not done, jump to top of loop
    IF mem56 <> 0 THEN GOTO pos48280  ' [cite: 18, 19, 20]

    ' increment position
    Y = Y + 1
    IF Y <> 0 THEN GOTO pos48274  ' [cite: 19]

    ' restore values and return
    mem44 = 1  ' [cite: 20]
    Y = mem49
    EXIT SUB

pos48315:
    ' handle voiced samples here

    ' number of samples?
    phase1 = A XOR 255  ' [cite: 21, 22]

    Y = mem66
    DO
        'pos48321:

        ' shift through all 8 bits
        mem56 = 8  ' [cite: 22, 23]
        'A = Read(mem47, Y);

        ' fetch value from table
        A = sampleTable(mem47 * 256 + Y)  ' [cite: 23, 24]

        ' loop 8 times
        'pos48327:
        DO
            '48327: ASL A
            '48328: BCC 48337

            ' left shift and check high bit
            tempA = A  ' [cite: 24, 25, 26, 27]
            A = A * 2  'Left shift [cite: 25]
            IF (tempA AND 128) <> 0 THEN
                ' if bit set, output 26
                X = 26  ' [cite: 25, 26]
                 'Implementation of Output needs context.  Using PRINT for now
                PRINT CHR$(X);
               ' Output 3, X  ' [cite: 26, 27]
            ELSE
                'timetable 4
                ' bit is not set, output a 6
                X = 6
                 'Implementation of Output needs context.  Using PRINT for now
                PRINT CHR$(X);
                'Output 4, X  ' [cite: 27, 28, 29, 30, 31]
            END IF

            mem56 = mem56 - 1
        LOOP UNTIL mem56 = 0
        ' move ahead in the table
        Y = Y + 1  ' [cite: 28, 29]
        ' continue until counter done
        phase1 = phase1 + 1

    LOOP UNTIL phase1 = 0  ' [cite: 29, 30, 31]
    ' restore values and return
    A = 1
    mem44 = 1
    mem66 = Y
    Y = mem49
    EXIT SUB

END SUB ' RenderSample
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' END RenderSample
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////







' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' END render.c
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' BEGIN debug.c
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' BEGIN PrintPhonemes
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Sub PrintPhonemes (phonemeindex As _Unsigned _Byte, arrPhonemeLength As _Unsigned _Byte, stress As _Unsigned _Byte)
    Dim i As Integer
    i = 0
    Print "==========================================="
    Print "Internal Phoneme presentation:"
    Print
    Print " idx    phoneme  length  stress"
    Print "------------------------------"

    Do While (phonemeindex(i) <> 255) And (i < 255) 'UBYTE arrays are indexed from 0 in QB64
        If phonemeindex(i) < 81 Then
            ' Assuming arrSignInputTable1 and arrSignInputTable2 are available
            ' and are also UBYTE arrays
            Print Using " ###      \  \      ###    #"; i; Chr$(arrSignInputTable1(phonemeindex(i))); Chr$(arrSignInputTable2(phonemeindex(i))); arrPhonemeLength(i); arrStress1(i) 'Format output
        Else
            Print Using " ###      ??      ###    #"; phonemeindex(i); arrPhonemeLength(i); arrStress1(i)
        End If
        i = i + 1
    Loop

    Print "==========================================="
    Print
End Sub ' PrintPhonemes
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' END PrintPhonemes
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////




' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' BEGIN PrintOutput
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Sub PrintOutput (flag As _Unsigned _Byte, f1 As _Unsigned _Byte, f2 As _Unsigned _Byte, f3 As _Unsigned _Byte, a1 As _Unsigned _Byte, a2 As _Unsigned _Byte, a3 As _Unsigned _Byte, p As _Unsigned _Byte)
    Print "==========================================="
    Print "Final data for speech output:"
    Print
    Print " flags ampl1 freq1 ampl2 freq2 ampl3 freq3 pitch"
    Print "------------------------------------------------"

    Dim i As Integer
    i = 0
    Do While i < 255
        Print Using " ##### ##### ##### ##### ##### ##### ##### #####"; flag(i); a1(i); f1(i); a2(i); f2(i); a3(i); f3(i); p(i)
        i = i + 1
    Loop

    Print "==========================================="
End Sub ' PrintOutput
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' END PrintOutput
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////




' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' BEGIN PrintRule
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
'extern uint8_t GetRuleByte(uint16_t mem62, uint8_t Y);  =>  Needs declaration if used
'  Assuming GetRuleByte is in another module.
'  TODO:  Add actual DECLARE FUNCTION if this function is needed in this module

Sub PrintRule (offset As Integer)
    Dim i As Integer
    Dim A As _Unsigned _Byte
    i = 1
    Print "Applying rule: ";

    Do
        ' Assuming GetRuleByte returns a UBYTE
        A = GetRuleByte(offset, i) 'Need to ensure GetRuleByte is available
        If (A And 127) = Asc("=") Then 'Bitwise AND and character comparison
            Print " -> ";
        Else
            Print Chr$(A And 127);
        End If
        i = i + 1
    Loop While (A And 128) = 0
    Print
End Sub ' PrintRule
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' END PrintRule
' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' END debug.c
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

C:
Code: (Select All)
// ################################################################################################################################################################
// SAM "SOFTWARE AUTOMATIC MOUTH"
// A native speech synthesizer

// C code from the bit-hack project at:
//
//     https://github.com/bit-hack/SAM
//
// which is a fork of Sebastian Macke's project at:
//
//     https://github.com/s-macke/SAM

// ################################################################################################################################################################




// ################################################################################################################################################################
// BEGIN INCLUDES
// ################################################################################################################################################################
#include <assert.h>
#include <ctype.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifdef USESDL
#include <SDL/SDL.h>
#endif
// ################################################################################################################################################################
// END INCLUDES
// ################################################################################################################################################################



// ################################################################################################################################################################
// BEGIN global constants
// ################################################################################################################################################################

Const cMaxPhonemes = 256 ' Example size, adjust as needed

' ################################################################################################################################################################
' END global constants
' ################################################################################################################################################################




// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// BEGIN test_phonemes.c
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

// Test State
typedef struct {
    size_t fails_;
    size_t passes_;
} test_state_t;

// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// END test_phonemes.c
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

// ################################################################################################################################################################
// BEGIN Global variables (equivalent to C globals)
// ################################################################################################################################################################

// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// BEGIN UNSORTED
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++









































// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// END UNSORTED
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// BEGIN sam.c
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++























int8_t input[256]; // tab39445



// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// BEGIN standard sam sound
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t speed = 72;
uint8_t pitch = 64;
uint8_t mouth = 128;
uint8_t throat = 128;
int32_t singmode = 0;
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
//END standard sam sound
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------



uint8_t mem39;
uint8_t mem44;
uint8_t mem47;
uint8_t mem49;
uint8_t mem50;
uint8_t mem51;
uint8_t mem53;
uint8_t mem56;
uint8_t mem59 = 0;

// *** A AND Y ARE DECLARED AS uint32 IN reciter.c
uint8_t A;
uint8_t X;
uint8_t Y;

// contains the final sound buffer
int32_t bufferPos = 0;
int8_t *buffer = NULL;

// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// BEGIN sam_tabs.h
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

//tab40672
uint8_t phonemeIndexOutput[60];  // tab47296


uint8_t phonemeIndex[256];

uint8_t phonemeLength[256]; // tab40160

uint8_t phonemeLengthOutput[60]; // tab47416

uint8_t stress[256];        // numbers from 0 to 8

uint8_t stressOutput[60];        // tab47365

// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// BEGIN stressInputTable
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
const uint8_t stressInputTable[] = {
    '*', '1', '2', '3', '4', '5', '6', '7', '8'
};
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// END stressInputTable
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------

// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// BEGIN tab40682
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
const uint8_t signInputTable1[] = {
    ' ', '.', '?', ',', '-', 'I', 'I', 'E',
    'A', 'A', 'A', 'A', 'U', 'A', 'I', 'E',
    'U', 'O', 'R', 'L', 'W', 'Y', 'W', 'R',
    'L', 'W', 'Y', 'M', 'N', 'N', 'D', 'Q',
    'S', 'S', 'F', 'T', '/', '/', 'Z', 'Z',
    'V', 'D', 'C', '*', 'J', '*', '*', '*',
    'E', 'A', 'O', 'A', 'O', 'U', 'B', '*',
    '*', 'D', '*', '*', 'G', '*', '*', 'G',
    '*', '*', 'P', '*', '*', 'T', '*', '*',
    'K', '*', '*', 'K', '*', '*', 'U', 'U',
    'U'
};
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// END tab40682
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------

// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// BEGIN tab40763
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
const uint8_t signInputTable2[] = {
    '*', '*', '*', '*', '*', 'Y', 'H', 'H',
    'E', 'A', 'H', 'O', 'H', 'X', 'X', 'R',
    'X', 'H', 'X', 'X', 'X', 'X', 'H', '*',
    '*', '*', '*', '*', '*', 'X', 'X', '*',
    '*', 'H', '*', 'H', 'H', 'X', '*', 'H',
    '*', 'H', 'H', '*', '*', '*', '*', '*',
    'Y', 'Y', 'Y', 'W', 'W', 'W', '*', '*',
    '*', '*', '*', '*', '*', '*', '*', 'X',
    '*', '*', '*', '*', '*', '*', '*', '*',
    '*', '*', '*', 'X', '*', '*', 'L', 'M',
    'N'
};
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// END tab40763
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------


// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// BEGIN loc_9F8C
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
const uint8_t flags[] = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0xA4, 0xA4, 0xA4,
    0xA4, 0xA4, 0xA4, 0x84, 0x84, 0xA4, 0xA4, 0x84,
    0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x44, 0x44,
    0x44, 0x44, 0x44, 0x4C, 0x4C, 0x4C, 0x48, 0x4C,
    0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x44, 0x44,
    0x44, 0x44, 0x48, 0x40, 0x4C, 0x44, 0x00, 0x00,
    0xB4, 0xB4, 0xB4, 0x94, 0x94, 0x94, 0x4E, 0x4E,
    0x4E, 0x4E, 0x4E, 0x4E, 0x4E, 0x4E, 0x4E, 0x4E,
    0x4E, 0x4E, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
    0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x80, 0xC1,
    0xC1

};
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// END loc_9F8C
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------

// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// BEGIN loc_9FDA
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
//??? flags overlap flags2
const uint8_t flags2[] = {
    0x80, 0xC1, 0xC1, 0xC1, 0xC1, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
    0x10, 0x10, 0x10, 0x08, 0x0C, 0x08, 0x04, 0x40,
    0x24, 0x20, 0x20, 0x24, 0x00, 0x00, 0x24, 0x20,
    0x20, 0x24, 0x20, 0x20, 0x00, 0x20, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// END loc_9FDA
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------



// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// BEGIN tab45616???
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
const uint8_t phonemeStressedLengthTable[] = {
    0x00, 0x12, 0x12, 0x12, 8, 0xB, 9, 0xB,
    0xE, 0xF, 0xB, 0x10, 0xC, 6, 6, 0xE,
    0xC, 0xE, 0xC, 0xB, 8, 8, 0xB, 0xA,
    9, 8, 8, 8, 8, 8, 3, 5,
    2, 2, 2, 2, 2, 2, 6, 6,
    8, 6, 6, 2, 9, 4, 2, 1,
    0xE, 0xF, 0xF, 0xF, 0xE, 0xE, 8, 2,
    2, 7, 2, 1, 7, 2, 2, 7,
    2, 2, 8, 2, 2, 6, 2, 2,
    7, 2, 4, 7, 1, 4, 5, 5
};
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// END tab45616???
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------






// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// BEGIN tab45536???
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
const uint8_t phonemeLengthTable[] = {
    0, 0x12, 0x12, 0x12, 8, 8, 8, 8,
    8, 0xB, 6, 0xC, 0xA, 5, 5, 0xB,
    0xA, 0xA, 0xA, 9, 8, 7, 9, 7,
    6, 8, 6, 7, 7, 7, 2, 5,
    2, 2, 2, 2, 2, 2, 6, 6,
    7, 6, 6, 2, 8, 3, 1, 0x1E,
    0xD, 0xC, 0xC, 0xC, 0xE, 9, 6, 1,
    2, 5, 1, 1, 6, 1, 2, 6,
    1, 2, 8, 2, 2, 4, 2, 2,
    6, 1, 4, 6, 1, 4, 0xC7, 0xFF
};
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// END tab45536???
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------

/*

Ind  | phoneme |  flags   |
-----|---------|----------|
0    |   *     | 00000000 |
1    |  .*     | 00000000 |
2    |  ?*     | 00000000 |
3    |  ,*     | 00000000 |
4    |  -*     | 00000000 |

VOWELS
5    |  IY     | 10100100 |
6    |  IH     | 10100100 |
7    |  EH     | 10100100 |
8    |  AE     | 10100100 |
9    |  AA     | 10100100 |
10   |  AH     | 10100100 |
11   |  AO     | 10000100 |
17   |  OH     | 10000100 |
12   |  UH     | 10000100 |
16   |  UX     | 10000100 |
15   |  ER     | 10000100 |
13   |  AX     | 10100100 |
14   |  IX     | 10100100 |

DIPHTONGS
48   |  EY     | 10110100 |
49   |  AY     | 10110100 |
50   |  OY     | 10110100 |
51   |  AW     | 10010100 |
52   |  OW     | 10010100 |
53   |  UW     | 10010100 |


21   |  YX     | 10000100 |
20   |  WX     | 10000100 |
18   |  RX     | 10000100 |
19   |  LX     | 10000100 |
37   |  /X     | 01000000 |
30   |  DX     | 01001000 |


22   |  WH     | 01000100 |


VOICED CONSONANTS
23   |  R*     | 01000100 |
24   |  L*     | 01000100 |
25   |  W*     | 01000100 |
26   |  Y*     | 01000100 |
27   |  M*     | 01001100 |
28   |  N*     | 01001100 |
29   |  NX     | 01001100 |
54   |  B*     | 01001110 |
57   |  D*     | 01001110 |
60   |  G*     | 01001110 |
44   |  J*     | 01001100 |
38   |  Z*     | 01000100 |
39   |  ZH     | 01000100 |
40   |  V*     | 01000100 |
41   |  DH     | 01000100 |

unvoiced CONSONANTS
32   |  S*     | 01000000 |
33   |  SH     | 01000000 |
34   |  F*     | 01000000 |
35   |  TH     | 01000000 |
66   |  P*     | 01001011 |
69   |  T*     | 01001011 |
72   |  K*     | 01001011 |
42   |  CH     | 01001000 |
36   |  /H     | 01000000 |

43   |  **     | 01000000 |
45   |  **     | 01000100 |
46   |  **     | 00000000 |
47   |  **     | 00000000 |


55   |  **     | 01001110 |
56   |  **     | 01001110 |
58   |  **     | 01001110 |
59   |  **     | 01001110 |
61   |  **     | 01001110 |
62   |  **     | 01001110 |
63   |  GX     | 01001110 |
64   |  **     | 01001110 |
65   |  **     | 01001110 |
67   |  **     | 01001011 |
68   |  **     | 01001011 |
70   |  **     | 01001011 |
71   |  **     | 01001011 |
73   |  **     | 01001011 |
74   |  **     | 01001011 |
75   |  KX     | 01001011 |
76   |  **     | 01001011 |
77   |  **     | 01001011 |


SPECIAL
78   |  UL     | 10000000 |
79   |  UM     | 11000001 |
80   |  UN     | 11000001 |
31   |  Q*     | 01001100 |

*/

#endif
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// END sam_tabs.h
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++



// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// BEGIN reciter_tabs.h
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// BEGIN tab36376
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------

// some flags
//
//  0x01        numeric
//  0x02        rule set 2
//  0x04        D J L N
//  0x08        B D G J L M N R V W Z
//  0x10        C G J S X Z R S T Z
//  0x20        B C D F G H J K L M N P Q R S T V X Y Z
//  0x40        is vowel + Y
//  0x80        alpha or '

const uint8_t tab36376[] = {
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,                                                           // ' '
    0                                           | 0x02,          // '!'
    0                                           | 0x02,          // '"'
    0                                           | 0x02,          // '#'
    0                                           | 0x02,          // '$'
    0                                           | 0x02,          // '%'
    0                                           | 0x02,          // '&'
    0 | 0x80                                    | 0x02,          // '''
    0,                                                           // '('
    0,                                                           // ')'
    0                                           | 0x02,          // '*'
    0                                           | 0x02,          // '+'
    0                                           | 0x02,          // ','
    0                                           | 0x02,          // '-'
    0                                           | 0x02,          // '.'
    0                                           | 0x02,          // '/'
    0                                           | 0x02 | 0x01,   // '0'
    0                                           | 0x02 | 0x01,   // '1'
    0                                           | 0x02 | 0x01,   // '2'
    0                                           | 0x02 | 0x01,   // '3'
    0                                           | 0x02 | 0x01,   // '4'
    0                                           | 0x02 | 0x01,   // '5'
    0                                           | 0x02 | 0x01,   // '6'
    0                                           | 0x02 | 0x01,   // '7'
    0                                           | 0x02 | 0x01,   // '8'
    0                                           | 0x02 | 0x01,   // '9'
    0                                           | 0x02,          // ':'
    0                                           | 0x02,          // ';'
    0                                           | 0x02,          // '<'
    0                                           | 0x02,          // '='
    0                                           | 0x02,          // '>'
    0                                           | 0x02,          // '?'
    0                                           | 0x02,          // '@'
    0 | 0x80 | 0x40,                                             // 'A'
    0 | 0x80        | 0x20        | 0x08,                        // 'B'
    0 | 0x80        | 0x20 | 0x10,                               // 'C'
    0 | 0x80        | 0x20        | 0x08 | 0x04,                 // 'D'
    0 | 0x80 | 0x40,                                             // 'E'
    0 | 0x80        | 0x20,                                      // 'F'
    0 | 0x80        | 0x20 | 0x10 | 0x08,                        // 'G'
    0 | 0x80        | 0x20,                                      // 'H'
    0 | 0x80 | 0x40,                                             // 'I'
    0 | 0x80        | 0x20 | 0x10 | 0x08 | 0x04,                 // 'J'
    0 | 0x80        | 0x20,                                      // 'K'
    0 | 0x80        | 0x20        | 0x08 | 0x04,                 // 'L'
    0 | 0x80        | 0x20        | 0x08,                        // 'M'
    0 | 0x80        | 0x20        | 0x08 | 0x04,                 // 'N'
    0 | 0x80 | 0x40,                                             // 'O'
    0 | 0x80        | 0x20,                                      // 'P'
    0 | 0x80        | 0x20,                                      // 'Q'
    0 | 0x80        | 0x20        | 0x08 | 0x04,                 // 'R'
    0 | 0x80        | 0x20 | 0x10        | 0x04,                 // 'S'
    0 | 0x80        | 0x20               | 0x04,                 // 'T'
    0 | 0x80 | 0x40,                                             // 'U'
    0 | 0x80        | 0x20        | 0x08,                        // 'V'
    0 | 0x80        | 0x20        | 0x08,                        // 'W'
    0 | 0x80        | 0x20 | 0x10,                               // 'X'
    0 | 0x80 | 0x40,                                             // 'Y'
    0 | 0x80        | 0x20 | 0x10 | 0x08 | 0x04,                 // 'Z'
    0,                                                           // '['
    0,                                                           // '\'
    0,                                                           // ']'
    0                                           | 0x02,          // '^'
    0,                                                           // '_'
    0               | 0x20                      | 0x02,          // '`'
  };
 
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// END tab36376
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------

// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// BEGIN rules
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
  const int8_t rules[] = {
    "]\xc1"                                        // ']A'
    " (A.)=EH4Y.\xa0"                              // ' (A.)=EH4Y. '
    "(A) =A\xc8"                                   // '(A) =AH'
    " (ARE) =AA\xd2"                               // ' (ARE) =AAR'
    " (AR)O=AX\xd2"                                // ' (AR)O=AXR'
    "(AR)#=EH4\xd2"                                // '(AR)#=EH4R'
    " ^(AS)#=EY4\xd3"                              // ' ^(AS)#=EY4S'
    "(A)WA=A\xd8"                                  // '(A)WA=AX'
    "(AW)=AO\xb5"                                  // '(AW)=AO5'
    " :(ANY)=EH4NI\xd9"                            // ' :(ANY)=EH4NIY'
    "(A)^+#=EY\xb5"                                // '(A)^+#=EY5'
    "#:(ALLY)=ULI\xd9"                             // '#:(ALLY)=ULIY'
    " (AL)#=U\xcc"                                 // ' (AL)#=UL'
    "(AGAIN)=AXGEH4\xce"                           // '(AGAIN)=AXGEH4N'
    "#:(AG)E=IH\xca"                               // '#:(AG)E=IHJ'
    "(A)^%=E\xd9"                                  // '(A)^%=EY'
    "(A)^+:#=A\xc5"                                // '(A)^+:#=AE'
    " :(A)^+ =EY\xb4"                              // ' :(A)^+ =EY4'
    " (ARR)=AX\xd2"                                // ' (ARR)=AXR'
    "(ARR)=AE4\xd2"                                // '(ARR)=AE4R'
    " ^(AR) =AA5\xd2"                              // ' ^(AR) =AA5R'
    "(AR)=AA5\xd2"                                 // '(AR)=AA5R'
    "(AIR)=EH4\xd2"                                // '(AIR)=EH4R'
    "(AI)=EY\xb4"                                  // '(AI)=EY4'
    "(AY)=EY\xb5"                                  // '(AY)=EY5'
    "(AU)=AO\xb4"                                  // '(AU)=AO4'
    "#:(AL) =U\xcc"                                // '#:(AL) =UL'
    "#:(ALS) =UL\xda"                              // '#:(ALS) =ULZ'
    "(ALK)=AO4\xcb"                                // '(ALK)=AO4K'
    "(AL)^=AO\xcc"                                 // '(AL)^=AOL'
    " :(ABLE)=EY4BU\xcc"                           // ' :(ABLE)=EY4BUL'
    "(ABLE)=AXBU\xcc"                              // '(ABLE)=AXBUL'
    "(A)VO=EY\xb4"                                 // '(A)VO=EY4'
    "(ANG)+=EY4N\xca"                              // '(ANG)+=EY4NJ'
    "(ATARI)=AHTAA4RI\xd9"                         // '(ATARI)=AHTAA4RIY'
    "(A)TOM=A\xc5"                                 // '(A)TOM=AE'
    "(A)TTI=A\xc5"                                 // '(A)TTI=AE'
    " (AT) =AE\xd4"                                // ' (AT) =AET'
    " (A)T=A\xc8"                                  // ' (A)T=AH'
    "(A)=A\xc5"                                    // '(A)=AE'
 
    "]\xc2"                                        // ']B'
    " (B) =BIY\xb4"                                // ' (B) =BIY4'
    " (BE)^#=BI\xc8"                               // ' (BE)^#=BIH'
    "(BEING)=BIY4IHN\xd8"                          // '(BEING)=BIY4IHNX'
    " (BOTH) =BOW4T\xc8"                           // ' (BOTH) =BOW4TH'
    " (BUS)#=BIH4\xda"                             // ' (BUS)#=BIH4Z'
    "(BREAK)=BREY5\xcb"                            // '(BREAK)=BREY5K'
    "(BUIL)=BIH4\xcc"                              // '(BUIL)=BIH4L'
    "(B)=\xc2"                                     // '(B)=B'
 
    "]\xc3"                                        // ']C'
    " (C) =SIY\xb4"                                // ' (C) =SIY4'
    " (CH)^=\xcb"                                  // ' (CH)^=K'
    "^E(CH)=\xcb"                                  // '^E(CH)=K'
    "(CHA)R#=KEH\xb5"                              // '(CHA)R#=KEH5'
    "(CH)=C\xc8"                                   // '(CH)=CH'
    " S(CI)#=SAY\xb4"                              // ' S(CI)#=SAY4'
    "(CI)A=S\xc8"                                  // '(CI)A=SH'
    "(CI)O=S\xc8"                                  // '(CI)O=SH'
    "(CI)EN=S\xc8"                                 // '(CI)EN=SH'
    "(CITY)=SIHTI\xd9"                             // '(CITY)=SIHTIY'
    "(C)+=\xd3"                                    // '(C)+=S'
    "(CK)=\xcb"                                    // '(CK)=K'
    "(COMMODORE)=KAA4MAHDOH\xd2"                   // '(COMMODORE)=KAA4MAHDOHR'
    "(COM)=KAH\xcd"                                // '(COM)=KAHM'
    "(CUIT)=KIH\xd4"                               // '(CUIT)=KIHT'
    "(CREA)=KRIYE\xd9"                             // '(CREA)=KRIYEY'
    "(C)=\xcb"                                     // '(C)=K'
 
    "]\xc4"                                        // ']D'
    " (D) =DIY\xb4"                                // ' (D) =DIY4'
    " (DR.) =DAA4KTE\xd2"                          // ' (DR.) =DAA4KTER'
    "#:(DED) =DIH\xc4"                             // '#:(DED) =DIHD'
    ".E(D) =\xc4"                                  // '.E(D) =D'
    "#:^E(D) =\xd4"                                // '#:^E(D) =T'
    " (DE)^#=DI\xc8"                               // ' (DE)^#=DIH'
    " (DO) =DU\xd7"                                // ' (DO) =DUW'
    " (DOES)=DAH\xda"                              // ' (DOES)=DAHZ'
    "(DONE) =DAH5\xce"                             // '(DONE) =DAH5N'
    "(DOING)=DUW4IHN\xd8"                          // '(DOING)=DUW4IHNX'
    " (DOW)=DA\xd7"                                // ' (DOW)=DAW'
    "#(DU)A=JU\xd7"                                // '#(DU)A=JUW'
    "#(DU)^#=JA\xd8"                               // '#(DU)^#=JAX'
    "(D)=\xc4"                                     // '(D)=D'
 
    "]\xc5"                                        // ']E'
    " (E) =IYIY\xb4"                               // ' (E) =IYIY4'
    "#:(E) \xbd"                                   // '#:(E) ='
    "\\':^(E) \xbd"                                // '\\':^(E) ='
    " :(E) =I\xd9"                                 // ' :(E) =IY'
    "#(ED) =\xc4"                                  // '#(ED) =D'
    "#:(E)D \xbd"                                  // '#:(E)D ='
    "(EV)ER=EH4\xd6"                               // '(EV)ER=EH4V'
    "(E)^%=IY\xb4"                                 // '(E)^%=IY4'
    "(ERI)#=IY4RI\xd9"                             // '(ERI)#=IY4RIY'
    "(ERI)=EH4RI\xc8"                              // '(ERI)=EH4RIH'
    "#:(ER)#=E\xd2"                                // '#:(ER)#=ER'
    "(ERROR)=EH4ROH\xd2"                           // '(ERROR)=EH4ROHR'
    "(ERASE)=IHREY5\xd3"                           // '(ERASE)=IHREY5S'
    "(ER)#=EH\xd2"                                 // '(ER)#=EHR'
    "(ER)=E\xd2"                                   // '(ER)=ER'
    " (EVEN)=IYVEH\xce"                            // ' (EVEN)=IYVEHN'
    "#:(E)W\xbd"                                   // '#:(E)W='
    "@(EW)=U\xd7"                                  // '@(EW)=UW'
    "(EW)=YU\xd7"                                  // '(EW)=YUW'
    "(E)O=I\xd9"                                   // '(E)O=IY'
    "#:&(ES) =IH\xda"                              // '#:&(ES) =IHZ'
    "#:(E)S \xbd"                                  // '#:(E)S ='
    "#:(ELY) =LI\xd9"                              // '#:(ELY) =LIY'
    "#:(EMENT)=MEHN\xd4"                           // '#:(EMENT)=MEHNT'
    "(EFUL)=FUH\xcc"                               // '(EFUL)=FUHL'
    "(EE)=IY\xb4"                                  // '(EE)=IY4'
    "(EARN)=ER5\xce"                               // '(EARN)=ER5N'
    " (EAR)^=ER\xb5"                               // ' (EAR)^=ER5'
    "(EAD)=EH\xc4"                                 // '(EAD)=EHD'
    "#:(EA) =IYA\xd8"                              // '#:(EA) =IYAX'
    "(EA)SU=EH\xb5"                                // '(EA)SU=EH5'
    "(EA)=IY\xb5"                                  // '(EA)=IY5'
    "(EIGH)=EY\xb4"                                // '(EIGH)=EY4'
    "(EI)=IY\xb4"                                  // '(EI)=IY4'
    " (EYE)=AY\xb4"                                // ' (EYE)=AY4'
    "(EY)=I\xd9"                                   // '(EY)=IY'
    "(EU)=YUW\xb5"                                 // '(EU)=YUW5'
    "(EQUAL)=IY4KWU\xcc"                           // '(EQUAL)=IY4KWUL'
    "(E)=E\xc8"                                    // '(E)=EH'
 
    "]\xc6"                                        // ']F'
    " (F) =EH4\xc6"                                // ' (F) =EH4F'
    "(FUL)=FUH\xcc"                                // '(FUL)=FUHL'
    "(FRIEND)=FREH5N\xc4"                          // '(FRIEND)=FREH5ND'
    "(FATHER)=FAA4DHE\xd2"                         // '(FATHER)=FAA4DHER'
    "(F)F\xbd"                                     // '(F)F='
    "(F)=\xc6"                                     // '(F)=F'
 
    "]\xc7"                                        // ']G'
    " (G) =JIY\xb4"                                // ' (G) =JIY4'
    "(GIV)=GIH5\xd6"                               // '(GIV)=GIH5V'
    " (G)I^=\xc7"                                  // ' (G)I^=G'
    "(GE)T=GEH\xb5"                                // '(GE)T=GEH5'
    "SU(GGES)=GJEH4\xd3"                           // 'SU(GGES)=GJEH4S'
    "(GG)=\xc7"                                    // '(GG)=G'
    " B#(G)=\xc7"                                  // ' B#(G)=G'
    "(G)+=\xca"                                    // '(G)+=J'
    "(GREAT)=GREY4\xd4"                            // '(GREAT)=GREY4T'
    "(GON)E=GAO5\xce"                              // '(GON)E=GAO5N'
    "#(GH)\xbd"                                    // '#(GH)='
    " (GN)=\xce"                                   // ' (GN)=N'
    "(G)=\xc7"                                     // '(G)=G'
 
    "]\xc8"                                        // ']H'
    " (H) =EY4C\xc8"                               // ' (H) =EY4CH'
    " (HAV)=/HAE6\xd6"                             // ' (HAV)=/HAE6V'
    " (HERE)=/HIY\xd2"                             // ' (HERE)=/HIYR'
    " (HOUR)=AW5E\xd2"                             // ' (HOUR)=AW5ER'
    "(HOW)=/HA\xd7"                                // '(HOW)=/HAW'
    "(H)#=/\xc8"                                   // '(H)#=/H'
    "(H)\xbd"                                      // '(H)='
 
    "]\xc9"                                        // ']I'
    " (IN)=IH\xce"                                 // ' (IN)=IHN'
    " (I) =AY\xb4"                                 // ' (I) =AY4'
    "(I) =A\xd9"                                   // '(I) =AY'
    "(IN)D=AY5\xce"                                // '(IN)D=AY5N'
    "SEM(I)=I\xd9"                                 // 'SEM(I)=IY'
    " ANT(I)=A\xd9"                                // ' ANT(I)=AY'
    "(IER)=IYE\xd2"                                // '(IER)=IYER'
    "#:R(IED) =IY\xc4"                             // '#:R(IED) =IYD'
    "(IED) =AY5\xc4"                               // '(IED) =AY5D'
    "(IEN)=IYEH\xce"                               // '(IEN)=IYEHN'
    "(IE)T=AY4E\xc8"                               // '(IE)T=AY4EH'
    "(I\\')=AY\xb5"                                // '(I\\')=AY5'
    " :(I)^%=AY\xb5"                               // ' :(I)^%=AY5'
    " :(IE) =AY\xb4"                               // ' :(IE) =AY4'
    "(I)%=I\xd9"                                   // '(I)%=IY'
    "(IE)=IY\xb4"                                  // '(IE)=IY4'
    " (IDEA)=AYDIY5A\xc8"                          // ' (IDEA)=AYDIY5AH'
    "(I)^+:#=I\xc8"                                // '(I)^+:#=IH'
    "(IR)#=AY\xd2"                                 // '(IR)#=AYR'
    "(IZ)%=AY\xda"                                 // '(IZ)%=AYZ'
    "(IS)%=AY\xda"                                 // '(IS)%=AYZ'
    "I^(I)^#=I\xc8"                                // 'I^(I)^#=IH'
    "+^(I)^+=A\xd9"                                // '+^(I)^+=AY'
    "#:^(I)^+=I\xc8"                               // '#:^(I)^+=IH'
    "(I)^+=A\xd9"                                  // '(I)^+=AY'
    "(IR)=E\xd2"                                   // '(IR)=ER'
    "(IGH)=AY\xb4"                                 // '(IGH)=AY4'
    "(ILD)=AY5L\xc4"                               // '(ILD)=AY5LD'
    " (IGN)=IHG\xce"                               // ' (IGN)=IHGN'
    "(IGN) =AY4\xce"                               // '(IGN) =AY4N'
    "(IGN)^=AY4\xce"                               // '(IGN)^=AY4N'
    "(IGN)%=AY4\xce"                               // '(IGN)%=AY4N'
    "(ICRO)=AY4KRO\xc8"                            // '(ICRO)=AY4KROH'
    "(IQUE)=IY4\xcb"                               // '(IQUE)=IY4K'
    "(I)=I\xc8"                                    // '(I)=IH'
 
    "]\xca"                                        // ']J'
    " (J) =JEY\xb4"                                // ' (J) =JEY4'
    "(J)=\xca"                                     // '(J)=J'
 
    "]\xcb"                                        // ']K'
    " (K) =KEY\xb4"                                // ' (K) =KEY4'
    " (K)N\xbd"                                    // ' (K)N='
    "(K)=\xcb"                                     // '(K)=K'
 
    "]\xcc"                                        // ']L'
    " (L) =EH4\xcc"                                // ' (L) =EH4L'
    "(LO)C#=LO\xd7"                                // '(LO)C#=LOW'
    "L(L)\xbd"                                     // 'L(L)='
    "#:^(L)%=U\xcc"                                // '#:^(L)%=UL'
    "(LEAD)=LIY\xc4"                               // '(LEAD)=LIYD'
    " (LAUGH)=LAE4\xc6"                            // ' (LAUGH)=LAE4F'
    "(L)=\xcc"                                     // '(L)=L'
 
    "]\xcd"                                        // ']M'
    " (M) =EH4\xcd"                                // ' (M) =EH4M'
    " (MR.) =MIH4STE\xd2"                          // ' (MR.) =MIH4STER'
    " (MS.)=MIH5\xda"                              // ' (MS.)=MIH5Z'
    " (MRS.) =MIH4SIX\xda"                         // ' (MRS.) =MIH4SIXZ'
    "(MOV)=MUW4\xd6"                               // '(MOV)=MUW4V'
    "(MACHIN)=MAHSHIY5\xce"                        // '(MACHIN)=MAHSHIY5N'
    "M(M)\xbd"                                     // 'M(M)='
    "(M)=\xcd"                                     // '(M)=M'
 
    "]\xce"                                        // ']N'
    " (N) =EH4\xce"                                // ' (N) =EH4N'
    "E(NG)+=N\xca"                                 // 'E(NG)+=NJ'
    "(NG)R=NX\xc7"                                 // '(NG)R=NXG'
    "(NG)#=NX\xc7"                                 // '(NG)#=NXG'
    "(NGL)%=NXGU\xcc"                              // '(NGL)%=NXGUL'
    "(NG)=N\xd8"                                   // '(NG)=NX'
    "(NK)=NX\xcb"                                  // '(NK)=NXK'
    " (NOW) =NAW\xb4"                              // ' (NOW) =NAW4'
    "N(N)\xbd"                                     // 'N(N)='
    "(NON)E=NAH4\xce"                              // '(NON)E=NAH4N'
    "(N)=\xce"                                     // '(N)=N'
 
    "]\xcf"                                        // ']O'
    " (O) =OH4\xd7"                                // ' (O) =OH4W'
    "(OF) =AH\xd6"                                 // '(OF) =AHV'
    " (OH) =OW\xb5"                                // ' (OH) =OW5'
    "(OROUGH)=ER4O\xd7"                            // '(OROUGH)=ER4OW'
    "#:(OR) =E\xd2"                                // '#:(OR) =ER'
    "#:(ORS) =ER\xda"                              // '#:(ORS) =ERZ'
    "(OR)=AO\xd2"                                  // '(OR)=AOR'
    " (ONE)=WAH\xce"                               // ' (ONE)=WAHN'
    "#(ONE) =WAH\xce"                              // '#(ONE) =WAHN'
    "(OW)=O\xd7"                                   // '(OW)=OW'
    " (OVER)=OW5VE\xd2"                            // ' (OVER)=OW5VER'
    "PR(O)V=UW\xb4"                                // 'PR(O)V=UW4'
    "(OV)=AH4\xd6"                                 // '(OV)=AH4V'
    "(O)^%=OW\xb5"                                 // '(O)^%=OW5'
    "(O)^EN=O\xd7"                                 // '(O)^EN=OW'
    "(O)^I#=OW\xb5"                                // '(O)^I#=OW5'
    "(OL)D=OW4\xcc"                                // '(OL)D=OW4L'
    "(OUGHT)=AO5\xd4"                              // '(OUGHT)=AO5T'
    "(OUGH)=AH5\xc6"                               // '(OUGH)=AH5F'
    " (OU)=A\xd7"                                  // ' (OU)=AW'
    "H(OU)S#=AW\xb4"                               // 'H(OU)S#=AW4'
    "(OUS)=AX\xd3"                                 // '(OUS)=AXS'
    "(OUR)=OH\xd2"                                 // '(OUR)=OHR'
    "(OULD)=UH5\xc4"                               // '(OULD)=UH5D'
    "(OU)^L=AH\xb5"                                // '(OU)^L=AH5'
    "(OUP)=UW5\xd0"                                // '(OUP)=UW5P'
    "(OU)=A\xd7"                                   // '(OU)=AW'
    "(OY)=O\xd9"                                   // '(OY)=OY'
    "(OING)=OW4IHN\xd8"                            // '(OING)=OW4IHNX'
    "(OI)=OY\xb5"                                  // '(OI)=OY5'
    "(OOR)=OH5\xd2"                                // '(OOR)=OH5R'
    "(OOK)=UH5\xcb"                                // '(OOK)=UH5K'
    "F(OOD)=UW5\xc4"                               // 'F(OOD)=UW5D'
    "L(OOD)=AH5\xc4"                               // 'L(OOD)=AH5D'
    "M(OOD)=UW5\xc4"                               // 'M(OOD)=UW5D'
    "(OOD)=UH5\xc4"                                // '(OOD)=UH5D'
    "F(OOT)=UH5\xd4"                               // 'F(OOT)=UH5T'
    "(OO)=UW\xb5"                                  // '(OO)=UW5'
    "(O\\')=O\xc8"                                 // '(O\\')=OH'
    "(O)E=O\xd7"                                   // '(O)E=OW'
    "(O) =O\xd7"                                   // '(O) =OW'
    "(OA)=OW\xb4"                                  // '(OA)=OW4'
    " (ONLY)=OW4NLI\xd9"                           // ' (ONLY)=OW4NLIY'
    " (ONCE)=WAH4N\xd3"                            // ' (ONCE)=WAH4NS'
    "(ON\\'T)=OW4N\xd4"                            // '(ON\\'T)=OW4NT'
    "C(O)N=A\xc1"                                  // 'C(O)N=AA'
    "(O)NG=A\xcf"                                  // '(O)NG=AO'
    " :^(O)N=A\xc8"                                // ' :^(O)N=AH'
    "I(ON)=U\xce"                                  // 'I(ON)=UN'
    "#:(ON)=U\xce"                                 // '#:(ON)=UN'
    "#^(ON)=U\xce"                                 // '#^(ON)=UN'
    "(O)ST=O\xd7"                                  // '(O)ST=OW'
    "(OF)^=AO4\xc6"                                // '(OF)^=AO4F'
    "(OTHER)=AH5DHE\xd2"                           // '(OTHER)=AH5DHER'
    "R(O)B=RA\xc1"                                 // 'R(O)B=RAA'
    "^R(O):#=OW\xb5"                               // '^R(O):#=OW5'
    "(OSS) =AO5\xd3"                               // '(OSS) =AO5S'
    "#:^(OM)=AH\xcd"                               // '#:^(OM)=AHM'
    "(O)=A\xc1"                                    // '(O)=AA'
 
    "]\xd0"                                        // ']P'
    " (P) =PIY\xb4"                                // ' (P) =PIY4'
    "(PH)=\xc6"                                    // '(PH)=F'
    "(PEOPL)=PIY5PU\xcc"                           // '(PEOPL)=PIY5PUL'
    "(POW)=PAW\xb4"                                // '(POW)=PAW4'
    "(PUT) =PUH\xd4"                               // '(PUT) =PUHT'
    "(P)P\xbd"                                     // '(P)P='
    "(P)S\xbd"                                     // '(P)S='
    "(P)N\xbd"                                     // '(P)N='
    "(PROF.)=PROHFEH4SE\xd2"                       // '(PROF.)=PROHFEH4SER'
    "(P)=\xd0"                                     // '(P)=P'
 
    "]\xd1"                                        // ']Q'
    " (Q) =KYUW\xb4"                               // ' (Q) =KYUW4'
    "(QUAR)=KWOH5\xd2"                             // '(QUAR)=KWOH5R'
    "(QU)=K\xd7"                                   // '(QU)=KW'
    "(Q)=\xcb"                                     // '(Q)=K'
    "]\xd2"                                        // ']R'
    " (R) =AA5\xd2"                                // ' (R) =AA5R'
    " (RE)^#=RI\xd9"                               // ' (RE)^#=RIY'
    "(R)R\xbd"                                     // '(R)R='
    "(R)=\xd2"                                     // '(R)=R'
 
    "]\xd3"                                        // ']S'
    " (S) =EH4\xd3"                                // ' (S) =EH4S'
    "(SH)=S\xc8"                                   // '(SH)=SH'
    "#(SION)=ZHU\xce"                              // '#(SION)=ZHUN'
    "(SOME)=SAH\xcd"                               // '(SOME)=SAHM'
    "#(SUR)#=ZHE\xd2"                              // '#(SUR)#=ZHER'
    "(SUR)#=SHE\xd2"                               // '(SUR)#=SHER'
    "#(SU)#=ZHU\xd7"                               // '#(SU)#=ZHUW'
    "#(SSU)#=SHU\xd7"                              // '#(SSU)#=SHUW'
    "#(SED)=Z\xc4"                                 // '#(SED)=ZD'
    "#(S)#=\xda"                                   // '#(S)#=Z'
    "(SAID)=SEH\xc4"                               // '(SAID)=SEHD'
    "^(SION)=SHU\xce"                              // '^(SION)=SHUN'
    "(S)S\xbd"                                     // '(S)S='
    ".(S) =\xda"                                   // '.(S) =Z'
    "#:.E(S) =\xda"                                // '#:.E(S) =Z'
    "#:^#(S) =\xd3"                                // '#:^#(S) =S'
    "U(S) =\xd3"                                   // 'U(S) =S'
    " :#(S) =\xda"                                 // ' :#(S) =Z'
    "##(S) =\xda"                                  // '##(S) =Z'
    " (SCH)=S\xcb"                                 // ' (SCH)=SK'
    "(S)C+\xbd"                                    // '(S)C+='
    "#(SM)=ZU\xcd"                                 // '#(SM)=ZUM'
    "#(SN)\\'=ZU\xcd"                              // '#(SN)\\'=ZUM'
    "(STLE)=SU\xcc"                                // '(STLE)=SUL'
    "(S)=\xd3"                                     // '(S)=S'
 
    "]\xd4"                                        // ']T'
    " (T) =TIY\xb4"                                // ' (T) =TIY4'
    " (THE) #=DHI\xd9"                             // ' (THE) #=DHIY'
    " (THE) =DHA\xd8"                              // ' (THE) =DHAX'
    "(TO) =TU\xd8"                                 // '(TO) =TUX'
    " (THAT)=DHAE\xd4"                             // ' (THAT)=DHAET'
    " (THIS) =DHIH\xd3"                            // ' (THIS) =DHIHS'
    " (THEY)=DHE\xd9"                              // ' (THEY)=DHEY'
    " (THERE)=DHEH\xd2"                            // ' (THERE)=DHEHR'
    "(THER)=DHE\xd2"                               // '(THER)=DHER'
    "(THEIR)=DHEH\xd2"                             // '(THEIR)=DHEHR'
    " (THAN) =DHAE\xce"                            // ' (THAN) =DHAEN'
    " (THEM) =DHAE\xce"                            // ' (THEM) =DHAEN'
    "(THESE) =DHIY\xda"                            // '(THESE) =DHIYZ'
    " (THEN)=DHEH\xce"                             // ' (THEN)=DHEHN'
    "(THROUGH)=THRUW\xb4"                          // '(THROUGH)=THRUW4'
    "(THOSE)=DHOH\xda"                             // '(THOSE)=DHOHZ'
    "(THOUGH) =DHO\xd7"                            // '(THOUGH) =DHOW'
    "(TODAY)=TUXDE\xd9"                            // '(TODAY)=TUXDEY'
    "(TOMO)RROW=TUMAA\xb5"                         // '(TOMO)RROW=TUMAA5'
    "(TO)TAL=TOW\xb5"                              // '(TO)TAL=TOW5'
    " (THUS)=DHAH4\xd3"                            // ' (THUS)=DHAH4S'
    "(TH)=T\xc8"                                   // '(TH)=TH'
    "#:(TED)=TIX\xc4"                              // '#:(TED)=TIXD'
    "S(TI)#N=C\xc8"                                // 'S(TI)#N=CH'
    "(TI)O=S\xc8"                                  // '(TI)O=SH'
    "(TI)A=S\xc8"                                  // '(TI)A=SH'
    "(TIEN)=SHU\xce"                               // '(TIEN)=SHUN'
    "(TUR)#=CHE\xd2"                               // '(TUR)#=CHER'
    "(TU)A=CHU\xd7"                                // '(TU)A=CHUW'
    " (TWO)=TU\xd7"                                // ' (TWO)=TUW'
    "&(T)EN \xbd"                                  // '&(T)EN ='
    "(T)=\xd4"                                     // '(T)=T'
 
    "]\xd5"                                        // ']U'
    " (U) =YUW\xb4"                                // ' (U) =YUW4'
    " (UN)I=YUW\xce"                               // ' (UN)I=YUWN'
    " (UN)=AH\xce"                                 // ' (UN)=AHN'
    " (UPON)=AXPAO\xce"                            // ' (UPON)=AXPAON'
    "@(UR)#=UH4\xd2"                               // '@(UR)#=UH4R'
    "(UR)#=YUH4\xd2"                               // '(UR)#=YUH4R'
    "(UR)=E\xd2"                                   // '(UR)=ER'
    "(U)^ =A\xc8"                                  // '(U)^ =AH'
    "(U)^^=AH\xb5"                                 // '(U)^^=AH5'
    "(UY)=AY\xb5"                                  // '(UY)=AY5'
    " G(U)#\xbd"                                   // ' G(U)#='
    "G(U)%\xbd"                                    // 'G(U)%='
    "G(U)#=\xd7"                                   // 'G(U)#=W'
    "#N(U)=YU\xd7"                                 // '#N(U)=YUW'
    "@(U)=U\xd7"                                   // '@(U)=UW'
    "(U)=YU\xd7"                                   // '(U)=YUW'
 
    "]\xd6"                                        // ']V'
    " (V) =VIY\xb4"                                // ' (V) =VIY4'
    "(VIEW)=VYUW\xb5"                              // '(VIEW)=VYUW5'
    "(V)=\xd6"                                     // '(V)=V'
 
    "]\xd7"                                        // ']W'
    " (W) =DAH4BULYU\xd7"                          // ' (W) =DAH4BULYUW'
    " (WERE)=WE\xd2"                               // ' (WERE)=WER'
    "(WA)SH=WA\xc1"                                // '(WA)SH=WAA'
    "(WA)ST=WE\xd9"                                // '(WA)ST=WEY'
    "(WA)S=WA\xc8"                                 // '(WA)S=WAH'
    "(WA)T=WA\xc1"                                 // '(WA)T=WAA'
    "(WHERE)=WHEH\xd2"                             // '(WHERE)=WHEHR'
    "(WHAT)=WHAH\xd4"                              // '(WHAT)=WHAHT'
    "(WHOL)=/HOW\xcc"                              // '(WHOL)=/HOWL'
    "(WHO)=/HU\xd7"                                // '(WHO)=/HUW'
    "(WH)=W\xc8"                                   // '(WH)=WH'
    "(WAR)#=WEH\xd2"                               // '(WAR)#=WEHR'
    "(WAR)=WAO\xd2"                                // '(WAR)=WAOR'
    "(WOR)^=WE\xd2"                                // '(WOR)^=WER'
    "(WR)=\xd2"                                    // '(WR)=R'
    "(WOM)A=WUH\xcd"                               // '(WOM)A=WUHM'
    "(WOM)E=WIH\xcd"                               // '(WOM)E=WIHM'
    "(WEA)R=WE\xc8"                                // '(WEA)R=WEH'
    "(WANT)=WAA5N\xd4"                             // '(WANT)=WAA5NT'
    "ANS(WER)=E\xd2"                               // 'ANS(WER)=ER'
    "(W)=\xd7"                                     // '(W)=W'
 
    "]\xd8"                                        // ']X'
    " (X) =EH4K\xd2"                               // ' (X) =EH4KR'
    " (X)=\xda"                                    // ' (X)=Z'
    "(X)=K\xd3"                                    // '(X)=KS'
 
    "]\xd9"                                        // ']Y'
    " (Y) =WAY\xb4"                                // ' (Y) =WAY4'
    "(YOUNG)=YAHN\xd8"                             // '(YOUNG)=YAHNX'
    " (YOUR)=YOH\xd2"                              // ' (YOUR)=YOHR'
    " (YOU)=YU\xd7"                                // ' (YOU)=YUW'
    " (YES)=YEH\xd3"                               // ' (YES)=YEHS'
    " (Y)=\xd9"                                    // ' (Y)=Y'
    "F(Y)=A\xd9"                                   // 'F(Y)=AY'
    "PS(YCH)=AY\xcb"                               // 'PS(YCH)=AYK'
    "#:^(Y)=I\xd9"                                 // '#:^(Y)=IY'
    "#:^(Y)I=I\xd9"                                // '#:^(Y)I=IY'
    " :(Y) =A\xd9"                                 // ' :(Y) =AY'
    " :(Y)#=A\xd9"                                 // ' :(Y)#=AY'
    " :(Y)^+:#=I\xc8"                              // ' :(Y)^+:#=IH'
    " :(Y)^#=A\xd9"                                // ' :(Y)^#=AY'
    "(Y)=I\xc8"                                    // '(Y)=IH'
 
    "]\xda"                                        // ']Z'
    " (Z) =ZIY\xb4"                                // ' (Z) =ZIY4'
    "(Z)=\xda"                                     // '(Z)=Z'
 
    "]\xb0"                                        // ']0'
    "(A)\xbd"                                      // '(A)='
    "(!)=\xae"                                     // '(!)=.'
    "(\") =-AH5NKWOWT\xad"                         // '(\") =-AH5NKWOWT-'
    "(\")=KWOW4T\xad"                              // '(\")=KWOW4T-'
    "(#)= NAH4MBE\xd2"                             // '(#)= NAH4MBER'
    "($)= DAA4LE\xd2"                              // '($)= DAA4LER'
    "(%)= PERSEH4N\xd4"                            // '(%)= PERSEH4NT'
    "(&)= AEN\xc4"                                 // '(&)= AEND'
    "(\\)\xbd"                                     // '(\\)='
    "(*)= AE4STERIHS\xcb"                          // '(*)= AE4STERIHSK'
    "(+)= PLAH4\xd3"                               // '(+)= PLAH4S'
    "(,)=\xac"                                     // '(,)=,'
    " (-) =\xad"                                   // ' (-) =-'
    "(-)\xbd"                                      // '(-)='
    "(.)= POYN\xd4"                                // '(.)= POYNT'
    "(/)= SLAE4S\xc8"                              // '(/)= SLAE4SH'
    "(0)= ZIY4RO\xd7"                              // '(0)= ZIY4ROW'
    " (1ST)=FER4S\xd4"                             // ' (1ST)=FER4ST'
    " (10TH)=TEH4NT\xc8"                           // ' (10TH)=TEH4NTH'
    "(1)= WAH4\xce"                                // '(1)= WAH4N'
    " (2ND)=SEH4KUN\xc4"                           // ' (2ND)=SEH4KUND'
    "(2)= TUW\xb4"                                 // '(2)= TUW4'
    " (3RD)=THER4\xc4"                             // ' (3RD)=THER4D'
    "(3)= THRIY\xb4"                               // '(3)= THRIY4'
    "(4)= FOH4\xd2"                                // '(4)= FOH4R'
    " (5TH)=FIH4FT\xc8"                            // ' (5TH)=FIH4FTH'
    "(5)= FAY4\xd6"                                // '(5)= FAY4V'
    " (64) =SIH4KSTIY FOH\xd2"                     // ' (64) =SIH4KSTIY FOHR'
    "(6)= SIH4K\xd3"                               // '(6)= SIH4KS'
    "(7)= SEH4VU\xce"                              // '(7)= SEH4VUN'
    " (8TH)=EY4T\xc8"                              // ' (8TH)=EY4TH'
    "(8)= EY4\xd4"                                 // '(8)= EY4T'
    "(9)= NAY4\xce"                                // '(9)= NAY4N'
    "(:)=\xae"                                     // '(:)=.'
    "(;)=\xae"                                     // '(;)=.'
    "(<)= LEH4S DHAE\xce"                          // '(<)= LEH4S DHAEN'
    "(=)= IY4KWUL\xda"                             // '(=)= IY4KWULZ'
    "(>)= GREY4TER DHAE\xce"                       // '(>)= GREY4TER DHAEN'
    "(?)=\xbf"                                     // '(?)=?'
    "(@)= AE6\xd4"                                 // '(@)= AE6T'
    "(^)= KAE4RIX\xd4"                             // '(^)= KAE4RIXT'
    "(')\xbd"                                      // '(')='
    "(`)\xbd"                                      // '(`)='
 
    "]\xb1"                                        // ']1'
  }; // rules[]
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// END rules
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------

// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// BEGIN rule_tab
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
  const uint16_t rule_tab[] = {
    0x00, 0x195, 0x1f7, 0x2a2, 0x33f, 0x4c6, 0x507, 0x57f,
    0x5c8, 0x728, 0x739, 0x750, 0x793, 0x7f3, 0x857, 0xaa5,
    0xb02, 0xb28, 0xb49, 0xc32, 0xdac, 0xe3b, 0xe58, 0xf33,
    0xf4c, 0xfdf, 0xff0, 0x11b7,
  }; // rule_tab
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// END rule_tab
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
#endif
 
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// END reciter_tabs.h
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// BEGIN reciter.c
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

// *** A AND Y ARE DECLARED AS uint32 IN sam.c
uint32_t A;
uint8_t X;
uint32_t Y;

// secure copy of input because input will be overwritten by phonemes
static uint8_t inputtemp[1024]; // secure copy of input tab36096

// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// END reciter.c
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// BEGIN render_tabs.h
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// BEGIN tab48426
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
const uint8_t tab48426[5] = { 0x18, 0x1A, 0x17, 0x17, 0x17 };
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// END tab48426
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------

// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// BEGIN tab47492
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
const uint8_t tab47492[] = {
    0, 0, 0xE0, 0xE6, 0xEC, 0xF3, 0xF9, 0,
    6, 0xC, 6
};
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// END tab47492
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------

// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// BEGIN amplitudeRescale
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------


const uint8_t amplitudeRescale[] = {
    0, 1, 2, 2, 2, 3, 3, 4,
    4, 5, 6, 8, 9, 0xB, 0xD, 0xF, 0 //17 elements?
};

// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// END amplitudeRescale
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------

// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// BEGIN blendRank
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// Used to decide which phoneme's blend lengths. The candidate with the lower score is selected.
// tab45856
const uint8_t blendRank[] = {
    0, 0x1F, 0x1F, 0x1F, 0x1F, 2, 2, 2,
    2, 2, 2, 2, 2, 2, 5, 5,
    2, 0xA, 2, 8, 5, 5, 0xB, 0xA,
    9, 8, 8, 0xA0, 8, 8, 0x17, 0x1F,
    0x12, 0x12, 0x12, 0x12, 0x1E, 0x1E, 0x14, 0x14,
    0x14, 0x14, 0x17, 0x17, 0x1A, 0x1A, 0x1D, 0x1D,
    2, 2, 2, 2, 2, 2, 0x1A, 0x1D,
    0x1B, 0x1A, 0x1D, 0x1B, 0x1A, 0x1D, 0x1B, 0x1A,
    0x1D, 0x1B, 0x17, 0x1D, 0x17, 0x17, 0x1D, 0x17,
    0x17, 0x1D, 0x17, 0x17, 0x1D, 0x17, 0x17, 0x17
};
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// END blendRank
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------

// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// BEGIN outBlendLength
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// Number of frames at the end of a phoneme devoted to interpolating to next phoneme's final value
//tab45696
const uint8_t outBlendLength[] = {
    0, 2, 2, 2, 2, 4, 4, 4,
    4, 4, 4, 4, 4, 4, 4, 4,
    4, 4, 3, 2, 4, 4, 2, 2,
    2, 2, 2, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 2, 2,
    2, 1, 0, 1, 0, 1, 0, 5,
    5, 5, 5, 5, 4, 4, 2, 0,
    1, 2, 0, 1, 2, 0, 1, 2,
    0, 1, 2, 0, 2, 2, 0, 1,
    3, 0, 2, 3, 0, 2, 0xA0, 0xA0
};
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// END outBlendLength
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------

// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// BEGIN inBlendLength
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// Number of frames at beginning of a phoneme devoted to interpolating to phoneme's final value
// tab45776
const uint8_t inBlendLength[] = {
    0, 2, 2, 2, 2, 4, 4, 4,
    4, 4, 4, 4, 4, 4, 4, 4,
    4, 4, 3, 3, 4, 4, 3, 3,
    3, 3, 3, 1, 2, 3, 2, 1,
    3, 3, 3, 3, 1, 1, 3, 3,
    3, 2, 2, 3, 2, 3, 0, 0,
    5, 5, 5, 5, 4, 4, 2, 0,
    2, 2, 0, 3, 2, 0, 4, 2,
    0, 3, 2, 0, 2, 2, 0, 2,
    3, 0, 3, 3, 0, 3, 0xB0, 0xA0
};
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// END inBlendLength
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------

// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// BEGIN sampledConsonantFlags
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------

// Looks like it's used as bit flags
// High bits masked by 248 (11111000)
//
// 32: S*    241         11110001
// 33: SH    226         11100010
// 34: F*    211         11010011
// 35: TH    187         10111011
// 36: /H    124         01111100
// 37: /X    149         10010101
// 38: Z*    1           00000001
// 39: ZH    2           00000010
// 40: V*    3           00000011
// 41: DH    3           00000011
// 43: **    114         01110010
// 45: **    2           00000010
// 67: **    27          00011011
// 70: **    25          00011001

// tab45936
const uint8_t sampledConsonantFlags[] = {
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0xF1, 0xE2, 0xD3, 0xBB, 0x7C, 0x95, 1, 2,
    3, 3, 0, 0x72, 0, 2, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0x1B, 0, 0, 0x19, 0,
    0, 0, 0, 0, 0, 0, 0, 0
};
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// END sampledConsonantFlags
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------

// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// BEGIN freq1data
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
//tab45056
//note: non cost
uint8_t freq1data[] = {
    0x00, 0x13, 0x13, 0x13, 0x13, 0xA, 0xE, 0x12, 0x18, 0x1A, 0x16, 0x14, 0x10, 0x14, 0xE, 0x12, 0xE, 0x12, 0x12, 0x10, 0xC, 0xE, 0xA, 0x12, 0xE, 0xA, 8, 6, 6, 6, 6, 0x11, 6, 6, 6, 6, 0xE, 0x10, 9, 0xA, 8, 0xA, 6, 6, 6, 5, 6, 0, 0x12, 0x1A, 0x14, 0x1A, 0x12, 0xC, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 0xA, 0xA, 6, 6, 6, 0x2C, 0x13
};
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// END freq1data
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------

// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// BEGIN freq2data
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
//tab451356
// note: non const
uint8_t freq2data[] = {
    0x00, 0x43, 0x43, 0x43, 0x43, 0x54, 0x48, 0x42,
    0x3E, 0x28, 0x2C, 0x1E, 0x24, 0x2C, 0x48, 0x30,
    0x24, 0x1E, 0x32, 0x24, 0x1C, 0x44, 0x18, 0x32,
    0x1E, 0x18, 0x52, 0x2E, 0x36, 0x56, 0x36, 0x43,
    0x49, 0x4F, 0x1A, 0x42, 0x49, 0x25, 0x33, 0x42,
    0x28, 0x2F, 0x4F, 0x4F, 0x42, 0x4F, 0x6E, 0x00,
    0x48, 0x26, 0x1E, 0x2A, 0x1E, 0x22, 0x1A, 0x1A,
    0x1A, 0x42, 0x42, 0x42, 0x6E, 0x6E, 0x6E, 0x54,
    0x54, 0x54, 0x1A, 0x1A, 0x1A, 0x42, 0x42, 0x42,
    0x6D, 0x56, 0x6D, 0x54, 0x54, 0x54, 0x7F, 0x7F
};
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// END arrFreq2Data
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------

// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// BEGIN freq3data
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
//tab45216
const uint8_t freq3data[] = {
    0x00, 0x5B, 0x5B, 0x5B, 0x5B, 0x6E, 0x5D, 0x5B,
    0x58, 0x59, 0x57, 0x58, 0x52, 0x59, 0x5D, 0x3E,
    0x52, 0x58, 0x3E, 0x6E, 0x50, 0x5D, 0x5A, 0x3C,
    0x6E, 0x5A, 0x6E, 0x51, 0x79, 0x65, 0x79, 0x5B,
    0x63, 0x6A, 0x51, 0x79, 0x5D, 0x52, 0x5D, 0x67,
    0x4C, 0x5D, 0x65, 0x65, 0x79, 0x65, 0x79, 0x00,
    0x5A, 0x58, 0x58, 0x58, 0x58, 0x52, 0x51, 0x51,
    0x51, 0x79, 0x79, 0x79, 0x70, 0x6E, 0x6E, 0x5E,
    0x5E, 0x5E, 0x51, 0x51, 0x51, 0x79, 0x79, 0x79,
    0x65, 0x65, 0x70, 0x5E, 0x5E, 0x5E, 0x08, 0x01
};
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// END freq3data
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------

// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// BEGIN ampl1data
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
const uint8_t ampl1data[] = {
    0, 0, 0, 0, 0, 0xD, 0xD, 0xE,
    0xF, 0xF, 0xF, 0xF, 0xF, 0xC, 0xD, 0xC,
    0xF, 0xF, 0xD, 0xD, 0xD, 0xE, 0xD, 0xC,
    0xD, 0xD, 0xD, 0xC, 9, 9, 0, 0,
    0, 0, 0, 0, 0, 0, 0xB, 0xB,
    0xB, 0xB, 0, 0, 1, 0xB, 0, 2,
    0xE, 0xF, 0xF, 0xF, 0xF, 0xD, 2, 4,
    0, 2, 4, 0, 1, 4, 0, 1,
    4, 0, 0, 0, 0, 0, 0, 0,
    0, 0xC, 0, 0, 0, 0, 0xF, 0xF
};
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// END ampl1data
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------

// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// BEGIN ampl2data
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------

const uint8_t ampl2data[] = {
    0, 0, 0, 0, 0, 0xA, 0xB, 0xD,
    0xE, 0xD, 0xC, 0xC, 0xB, 9, 0xB, 0xB,
    0xC, 0xC, 0xC, 8, 8, 0xC, 8, 0xA,
    8, 8, 0xA, 3, 9, 6, 0, 0,
    0, 0, 0, 0, 0, 0, 3, 5,
    3, 4, 0, 0, 0, 5, 0xA, 2,
    0xE, 0xD, 0xC, 0xD, 0xC, 8, 0, 1,
    0, 0, 1, 0, 0, 1, 0, 0,
    1, 0, 0, 0, 0, 0, 0, 0,
    0, 0xA, 0, 0, 0xA, 0, 0, 0
};
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// END ampl2data
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------

// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// BEGIN ampl3data
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
const uint8_t ampl3data[] = {
    0, 0, 0, 0, 0, 8, 7, 8,
    8, 1, 1, 0, 1, 0, 7, 5,
    1, 0, 6, 1, 0, 7, 0, 5,
    1, 0, 8, 0, 0, 3, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 1,
    0, 0, 0, 0, 0, 1, 0xE, 1,
    9, 1, 0, 1, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 7, 0, 0, 5, 0, 0x13, 0x10
};
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// END ampl3data
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------

// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// BEGIN sinus
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
//tab42240
const uint8_t sinus[] = {
    0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10,
    0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30,
    0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x40, 0x40,
    0x40, 0x40, 0x40, 0x40, 0x40, 0x50, 0x50, 0x50,
    0x50, 0x50, 0x50, 0x50, 0x50, 0x60, 0x60, 0x60,
    0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60,
    0x60, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
    0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
    0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
    0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
    0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60,
    0x60, 0x60, 0x60, 0x60, 0x50, 0x50, 0x50, 0x50,
    0x50, 0x50, 0x50, 0x50, 0x40, 0x40, 0x40, 0x40,
    0x40, 0x40, 0x40, 0x30, 0x30, 0x30, 0x30, 0x30,
    0x30, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
    0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00,
    0x00, 0x00, 0x00, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
    0xF0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xD0,
    0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xC0, 0xC0,
    0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xB0, 0xB0, 0xB0,
    0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xA0, 0xA0, 0xA0,
    0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0,
    0xA0, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
    0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0,
    0xA0, 0xA0, 0xA0, 0xA0, 0xB0, 0xB0, 0xB0, 0xB0,
    0xB0, 0xB0, 0xB0, 0xB0, 0xC0, 0xC0, 0xC0, 0xC0,
    0xC0, 0xC0, 0xC0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0,
    0xD0, 0xD0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0,
    0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0x00, 0x00
};
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// END sinus
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------

// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// BEGIN rectangle
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
//tab42496
const uint8_t rectangle[] = {
    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
    0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
    0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
    0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
    0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
    0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
    0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
    0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
    0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
    0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
    0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
    0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
    0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
    0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
    0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
    0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
    0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70
};
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// END rectangle
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------

// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// BEGIN multtable
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
//tab42752
const uint8_t multtable[] = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 1, 1, 2, 2, 3, 3,
    4, 4, 5, 5, 6, 6, 7, 7,
    0, 1, 2, 3, 4, 5, 6, 7,
    8, 9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF,
    0x00, 1, 3, 4, 6, 7, 9, 0xA,
    0xC, 0xD, 0xF, 0x10, 0x12, 0x13, 0x15, 0x16,
    0x00, 2, 4, 6, 8, 0xA, 0xC, 0xE,
    0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x1E,
    0x00, 2, 5, 7, 0xA, 0xC, 0xF, 0x11,
    0x14, 0x16, 0x19, 0x1B, 0x1E, 0x20, 0x23, 0x25,
    0x00, 3, 6, 9, 0xC, 0xF, 0x12, 0x15,
    0x18, 0x1B, 0x1E, 0x21, 0x24, 0x27, 0x2A, 0x2D,
    0x00, 0x03, 0x07, 0x0A, 0x0E, 0x11, 0x15, 0x18,
    0x1C, 0x1F, 0x23, 0x26, 0x2A, 0x2D, 0x31, 0x34,
    0x00, 0xFC, 0xF8, 0xF4, 0xF0, 0xEC, 0xE8, 0xE4,
    0xE0, 0xDC, 0xD8, 0xD4, 0xD0, 0xCC, 0xC8, 0xC4,
    0x00, 0xFC, 0xF9, 0xF5, 0xF2, 0xEE, 0xEB, 0xE7,
    0xE4, 0xE0, 0xDD, 0xD9, 0xD6, 0xD2, 0xCF, 0xCB,
    0x00, 0xFD, 0xFA, 0xF7, 0xF4, 0xF1, 0xEE, 0xEB,
    0xE8, 0xE5, 0xE2, 0xDF, 0xDC, 0xD9, 0xD6, 0xD3,
    0x00, 0xFD, 0xFB, 0xF8, 0xF6, 0xF3, 0xF1, 0xEE,
    0xEC, 0xE9, 0xE7, 0xE4, 0xE2, 0xDF, 0xDD, 0xDA,
    0x00, 0xFE, 0xFC, 0xFA, 0xF8, 0xF6, 0xF4, 0xF2,
    0xF0, 0xEE, 0xEC, 0xEA, 0xE8, 0xE6, 0xE4, 0xE2,
    0x00, 0xFE, 0xFD, 0xFB, 0xFA, 0xF8, 0xF7, 0xF5,
    0xF4, 0xF2, 0xF1, 0xEF, 0xEE, 0xEC, 0xEB, 0xE9,
    0x00, 0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9,
    0xF8, 0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2, 0xF1,
    0x00, 0xFF, 0xFF, 0xFE, 0xFE, 0xFD, 0xFD, 0xFC,
    0xFC, 0xFB, 0xFB, 0xFA, 0xFA, 0xF9, 0xF9, 0xF8
};
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// END multtable
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------

// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// BEGIN sampleTable
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------

//random data ?
const uint8_t sampleTable[0x500] = {
    //00

    0x38, 0x84, 0x6B, 0x19, 0xC6, 0x63, 0x18, 0x86, 0x73, 0x98, 0xC6, 0xB1, 0x1C, 0xCA, 0x31, 0x8C, 0xC7, 0x31, 0x88, 0xC2, 0x30, 0x98, 0x46, 0x31, 0x18, 0xC6, 0x35, 0xC, 0xCA, 0x31, 0xC, 0xC6
    //20
    ,
    0x21, 0x10, 0x24, 0x69, 0x12, 0xC2, 0x31, 0x14, 0xC4, 0x71, 8, 0x4A, 0x22, 0x49, 0xAB, 0x6A, 0xA8, 0xAC, 0x49, 0x51, 0x32, 0xD5, 0x52, 0x88, 0x93, 0x6C, 0x94, 0x22, 0x15, 0x54, 0xD2, 0x25
    //40
    ,
    0x96, 0xD4, 0x50, 0xA5, 0x46, 0x21, 8, 0x85, 0x6B, 0x18, 0xC4, 0x63, 0x10, 0xCE, 0x6B, 0x18, 0x8C, 0x71, 0x19, 0x8C, 0x63, 0x35, 0xC, 0xC6, 0x33, 0x99, 0xCC, 0x6C, 0xB5, 0x4E, 0xA2, 0x99
    //60
    ,
    0x46, 0x21, 0x28, 0x82, 0x95, 0x2E, 0xE3, 0x30, 0x9C, 0xC5, 0x30, 0x9C, 0xA2, 0xB1, 0x9C, 0x67, 0x31, 0x88, 0x66, 0x59, 0x2C, 0x53, 0x18, 0x84, 0x67, 0x50, 0xCA, 0xE3, 0xA, 0xAC, 0xAB, 0x30
    //80
    ,
    0xAC, 0x62, 0x30, 0x8C, 0x63, 0x10, 0x94, 0x62, 0xB1, 0x8C, 0x82, 0x28, 0x96, 0x33, 0x98, 0xD6, 0xB5, 0x4C, 0x62, 0x29, 0xA5, 0x4A, 0xB5, 0x9C, 0xC6, 0x31, 0x14, 0xD6, 0x38, 0x9C, 0x4B, 0xB4
    //A0
    ,
    0x86, 0x65, 0x18, 0xAE, 0x67, 0x1C, 0xA6, 0x63, 0x19, 0x96, 0x23, 0x19, 0x84, 0x13, 8, 0xA6, 0x52, 0xAC, 0xCA, 0x22, 0x89, 0x6E, 0xAB, 0x19, 0x8C, 0x62, 0x34, 0xC4, 0x62, 0x19, 0x86, 0x63
    //C0
    ,
    0x18, 0xC4, 0x23, 0x58, 0xD6, 0xA3, 0x50, 0x42, 0x54, 0x4A, 0xAD, 0x4A, 0x25, 0x11, 0x6B, 0x64, 0x89, 0x4A, 0x63, 0x39, 0x8A, 0x23, 0x31, 0x2A, 0xEA, 0xA2, 0xA9, 0x44, 0xC5, 0x12, 0xCD, 0x42
    //E0
    ,
    0x34, 0x8C, 0x62, 0x18, 0x8C, 0x63, 0x11, 0x48, 0x66, 0x31, 0x9D, 0x44, 0x33, 0x1D, 0x46, 0x31, 0x9C, 0xC6, 0xB1, 0xC, 0xCD, 0x32, 0x88, 0xC4, 0x73, 0x18, 0x86, 0x73, 8, 0xD6, 0x63, 0x58
    //100
    ,
    7, 0x81, 0xE0, 0xF0, 0x3C, 7, 0x87, 0x90, 0x3C, 0x7C, 0xF, 0xC7, 0xC0, 0xC0, 0xF0, 0x7C, 0x1E, 7, 0x80, 0x80, 0, 0x1C, 0x78, 0x70, 0xF1, 0xC7, 0x1F, 0xC0, 0xC, 0xFE, 0x1C, 0x1F
    //120
    ,
    0x1F, 0xE, 0xA, 0x7A, 0xC0, 0x71, 0xF2, 0x83, 0x8F, 3, 0xF, 0xF, 0xC, 0, 0x79, 0xF8, 0x61, 0xE0, 0x43, 0xF, 0x83, 0xE7, 0x18, 0xF9, 0xC1, 0x13, 0xDA, 0xE9, 0x63, 0x8F, 0xF, 0x83
    //140
    ,
    0x83, 0x87, 0xC3, 0x1F, 0x3C, 0x70, 0xF0, 0xE1, 0xE1, 0xE3, 0x87, 0xB8, 0x71, 0xE, 0x20, 0xE3, 0x8D, 0x48, 0x78, 0x1C, 0x93, 0x87, 0x30, 0xE1, 0xC1, 0xC1, 0xE4, 0x78, 0x21, 0x83, 0x83, 0xC3
    //160
    ,
    0x87, 6, 0x39, 0xE5, 0xC3, 0x87, 7, 0xE, 0x1C, 0x1C, 0x70, 0xF4, 0x71, 0x9C, 0x60, 0x36, 0x32, 0xC3, 0x1E, 0x3C, 0xF3, 0x8F, 0xE, 0x3C, 0x70, 0xE3, 0xC7, 0x8F, 0xF, 0xF, 0xE, 0x3C
    //180
    ,
    0x78, 0xF0, 0xE3, 0x87, 6, 0xF0, 0xE3, 7, 0xC1, 0x99, 0x87, 0xF, 0x18, 0x78, 0x70, 0x70, 0xFC, 0xF3, 0x10, 0xB1, 0x8C, 0x8C, 0x31, 0x7C, 0x70, 0xE1, 0x86, 0x3C, 0x64, 0x6C, 0xB0, 0xE1
    //1A0
    ,
    0xE3, 0xF, 0x23, 0x8F, 0xF, 0x1E, 0x3E, 0x38, 0x3C, 0x38, 0x7B, 0x8F, 7, 0xE, 0x3C, 0xF4, 0x17, 0x1E, 0x3C, 0x78, 0xF2, 0x9E, 0x72, 0x49, 0xE3, 0x25, 0x36, 0x38, 0x58, 0x39, 0xE2, 0xDE
    //1C0
    ,
    0x3C, 0x78, 0x78, 0xE1, 0xC7, 0x61, 0xE1, 0xE1, 0xB0, 0xF0, 0xF0, 0xC3, 0xC7, 0xE, 0x38, 0xC0, 0xF0, 0xCE, 0x73, 0x73, 0x18, 0x34, 0xB0, 0xE1, 0xC7, 0x8E, 0x1C, 0x3C, 0xF8, 0x38, 0xF0, 0xE1
    //1E0
    ,
    0xC1, 0x8B, 0x86, 0x8F, 0x1C, 0x78, 0x70, 0xF0, 0x78, 0xAC, 0xB1, 0x8F, 0x39, 0x31, 0xDB, 0x38, 0x61, 0xC3, 0xE, 0xE, 0x38, 0x78, 0x73, 0x17, 0x1E, 0x39, 0x1E, 0x38, 0x64, 0xE1, 0xF1, 0xC1
    //200
    ,
    0x4E, 0xF, 0x40, 0xA2, 2, 0xC5, 0x8F, 0x81, 0xA1, 0xFC, 0x12, 8, 0x64, 0xE0, 0x3C, 0x22, 0xE0, 0x45, 7, 0x8E, 0xC, 0x32, 0x90, 0xF0, 0x1F, 0x20, 0x49, 0xE0, 0xF8, 0xC, 0x60, 0xF0
    //220
    ,
    0x17, 0x1A, 0x41, 0xAA, 0xA4, 0xD0, 0x8D, 0x12, 0x82, 0x1E, 0x1E, 3, 0xF8, 0x3E, 3, 0xC, 0x73, 0x80, 0x70, 0x44, 0x26, 3, 0x24, 0xE1, 0x3E, 4, 0x4E, 4, 0x1C, 0xC1, 9, 0xCC
    //240
    ,
    0x9E, 0x90, 0x21, 7, 0x90, 0x43, 0x64, 0xC0, 0xF, 0xC6, 0x90, 0x9C, 0xC1, 0x5B, 3, 0xE2, 0x1D, 0x81, 0xE0, 0x5E, 0x1D, 3, 0x84, 0xB8, 0x2C, 0xF, 0x80, 0xB1, 0x83, 0xE0, 0x30, 0x41
    //260
    ,
    0x1E, 0x43, 0x89, 0x83, 0x50, 0xFC, 0x24, 0x2E, 0x13, 0x83, 0xF1, 0x7C, 0x4C, 0x2C, 0xC9, 0xD, 0x83, 0xB0, 0xB5, 0x82, 0xE4, 0xE8, 6, 0x9C, 7, 0xA0, 0x99, 0x1D, 7, 0x3E, 0x82, 0x8F
    //280
    ,
    0x70, 0x30, 0x74, 0x40, 0xCA, 0x10, 0xE4, 0xE8, 0xF, 0x92, 0x14, 0x3F, 6, 0xF8, 0x84, 0x88, 0x43, 0x81, 0xA, 0x34, 0x39, 0x41, 0xC6, 0xE3, 0x1C, 0x47, 3, 0xB0, 0xB8, 0x13, 0xA, 0xC2
    //2A0
    ,
    0x64, 0xF8, 0x18, 0xF9, 0x60, 0xB3, 0xC0, 0x65, 0x20, 0x60, 0xA6, 0x8C, 0xC3, 0x81, 0x20, 0x30, 0x26, 0x1E, 0x1C, 0x38, 0xD3, 1, 0xB0, 0x26, 0x40, 0xF4, 0xB, 0xC3, 0x42, 0x1F, 0x85, 0x32
    //2C0
    ,
    0x26, 0x60, 0x40, 0xC9, 0xCB, 1, 0xEC, 0x11, 0x28, 0x40, 0xFA, 4, 0x34, 0xE0, 0x70, 0x4C, 0x8C, 0x1D, 7, 0x69, 3, 0x16, 0xC8, 4, 0x23, 0xE8, 0xC6, 0x9A, 0xB, 0x1A, 3, 0xE0
    //2E0
    ,
    0x76, 6, 5, 0xCF, 0x1E, 0xBC, 0x58, 0x31, 0x71, 0x66, 0, 0xF8, 0x3F, 4, 0xFC, 0xC, 0x74, 0x27, 0x8A, 0x80, 0x71, 0xC2, 0x3A, 0x26, 6, 0xC0, 0x1F, 5, 0xF, 0x98, 0x40, 0xAE
    //300
    ,
    1, 0x7F, 0xC0, 7, 0xFF, 0, 0xE, 0xFE, 0, 3, 0xDF, 0x80, 3, 0xEF, 0x80, 0x1B, 0xF1, 0xC2, 0, 0xE7, 0xE0, 0x18, 0xFC, 0xE0, 0x21, 0xFC, 0x80, 0x3C, 0xFC, 0x40, 0xE, 0x7E
    //320
    ,
    0, 0x3F, 0x3E, 0, 0xF, 0xFE, 0, 0x1F, 0xFF, 0, 0x3E, 0xF0, 7, 0xFC, 0, 0x7E, 0x10, 0x3F, 0xFF, 0, 0x3F, 0x38, 0xE, 0x7C, 1, 0x87, 0xC, 0xFC, 0xC7, 0, 0x3E, 4
    //340
    ,
    0xF, 0x3E, 0x1F, 0xF, 0xF, 0x1F, 0xF, 2, 0x83, 0x87, 0xCF, 3, 0x87, 0xF, 0x3F, 0xC0, 7, 0x9E, 0x60, 0x3F, 0xC0, 3, 0xFE, 0, 0x3F, 0xE0, 0x77, 0xE1, 0xC0, 0xFE, 0xE0, 0xC3
    //360
    ,
    0xE0, 1, 0xDF, 0xF8, 3, 7, 0, 0x7E, 0x70, 0, 0x7C, 0x38, 0x18, 0xFE, 0xC, 0x1E, 0x78, 0x1C, 0x7C, 0x3E, 0xE, 0x1F, 0x1E, 0x1E, 0x3E, 0, 0x7F, 0x83, 7, 0xDB, 0x87, 0x83
    //380
    ,
    7, 0xC7, 7, 0x10, 0x71, 0xFF, 0, 0x3F, 0xE2, 1, 0xE0, 0xC1, 0xC3, 0xE1, 0, 0x7F, 0xC0, 5, 0xF0, 0x20, 0xF8, 0xF0, 0x70, 0xFE, 0x78, 0x79, 0xF8, 2, 0x3F, 0xC, 0x8F, 3
    //3a0
    ,
    0xF, 0x9F, 0xE0, 0xC1, 0xC7, 0x87, 3, 0xC3, 0xC3, 0xB0, 0xE1, 0xE1, 0xC1, 0xE3, 0xE0, 0x71, 0xF0, 0, 0xFC, 0x70, 0x7C, 0xC, 0x3E, 0x38, 0xE, 0x1C, 0x70, 0xC3, 0xC7, 3, 0x81, 0xC1
    //3c0
    ,
    0xC7, 0xE7, 0, 0xF, 0xC7, 0x87, 0x19, 9, 0xEF, 0xC4, 0x33, 0xE0, 0xC1, 0xFC, 0xF8, 0x70, 0xF0, 0x78, 0xF8, 0xF0, 0x61, 0xC7, 0, 0x1F, 0xF8, 1, 0x7C, 0xF8, 0xF0, 0x78, 0x70, 0x3C
    //3e0
    ,
    0x7C, 0xCE, 0xE, 0x21, 0x83, 0xCF, 8, 7, 0x8F, 8, 0xC1, 0x87, 0x8F, 0x80, 0xC7, 0xE3, 0, 7, 0xF8, 0xE0, 0xEF, 0, 0x39, 0xF7, 0x80, 0xE, 0xF8, 0xE1, 0xE3, 0xF8, 0x21, 0x9F
    //400
    ,
    0xC0, 0xFF, 3, 0xF8, 7, 0xC0, 0x1F, 0xF8, 0xC4, 4, 0xFC, 0xC4, 0xC1, 0xBC, 0x87, 0xF0, 0xF, 0xC0, 0x7F, 5, 0xE0, 0x25, 0xEC, 0xC0, 0x3E, 0x84, 0x47, 0xF0, 0x8E, 3, 0xF8, 3
    //420
    ,
    0xFB, 0xC0, 0x19, 0xF8, 7, 0x9C, 0xC, 0x17, 0xF8, 7, 0xE0, 0x1F, 0xA1, 0xFC, 0xF, 0xFC, 1, 0xF0, 0x3F, 0, 0xFE, 3, 0xF0, 0x1F, 0, 0xFD, 0, 0xFF, 0x88, 0xD, 0xF9, 1
    //440
    ,
    0xFF, 0, 0x70, 7, 0xC0, 0x3E, 0x42, 0xF3, 0xD, 0xC4, 0x7F, 0x80, 0xFC, 7, 0xF0, 0x5E, 0xC0, 0x3F, 0, 0x78, 0x3F, 0x81, 0xFF, 1, 0xF8, 1, 0xC3, 0xE8, 0xC, 0xE4, 0x64, 0x8F
    ////460
    ,
    0xE4, 0xF, 0xF0, 7, 0xF0, 0xC2, 0x1F, 0, 0x7F, 0xC0, 0x6F, 0x80, 0x7E, 3, 0xF8, 7, 0xF0, 0x3F, 0xC0, 0x78, 0xF, 0x82, 7, 0xFE, 0x22, 0x77, 0x70, 2, 0x76, 3, 0xFE, 0
    //480
    ,
    0xFE, 0x67, 0, 0x7C, 0xC7, 0xF1, 0x8E, 0xC6, 0x3B, 0xE0, 0x3F, 0x84, 0xF3, 0x19, 0xD8, 3, 0x99, 0xFC, 9, 0xB8, 0xF, 0xF8, 0, 0x9D, 0x24, 0x61, 0xF9, 0xD, 0, 0xFD, 3, 0xF0
    //4a0
    ,
    0x1F, 0x90, 0x3F, 1, 0xF8, 0x1F, 0xD0, 0xF, 0xF8, 0x37, 1, 0xF8, 7, 0xF0, 0xF, 0xC0, 0x3F, 0, 0xFE, 3, 0xF8, 0xF, 0xC0, 0x3F, 0, 0xFA, 3, 0xF0, 0xF, 0x80, 0xFF, 1
    //4c0
    ,
    0xB8, 7, 0xF0, 1, 0xFC, 1, 0xBC, 0x80, 0x13, 0x1E, 0, 0x7F, 0xE1, 0x40, 0x7F, 0xA0, 0x7F, 0xB0, 0, 0x3F, 0xC0, 0x1F, 0xC0, 0x38, 0xF, 0xF0, 0x1F, 0x80, 0xFF, 1, 0xFC, 3
    //4e0
    ,
    0xF1, 0x7E, 1, 0xFE, 1, 0xF0, 0xFF, 0, 0x7F, 0xC0, 0x1D, 7, 0xF0, 0xF, 0xC0, 0x7E, 6, 0xE0, 7, 0xE0, 0xF, 0xF8, 6, 0xC1, 0xFE, 1, 0xFC, 3, 0xE0, 0xF, 0, 0xFC
};
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------
// END sampleTable
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------

#endif

// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// END render_tabs.h
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// BEGIN render.c
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

uint8_t wait1 = 7;



uint8_t wait2 = 6;


// A and Y are uint32 elsewhere:
//uint8_t A, X, Y;
uint8_t pitches[256]; // tab43008

uint8_t frequency1[256];
uint8_t frequency2[256];
uint8_t frequency3[256];

uint8_t amplitude1[256];
uint8_t amplitude2[256];
uint8_t amplitude3[256];

uint8_t sampledConsonantFlag[256]; // tab44800

//timetable for more accurate c64 simulation
int32_t timetable[5][5] = {
    { 162, 167, 167, 127, 128 },
    { 226, 60, 60, 0, 0 },
    { 225, 60, 59, 0, 0 },
    { 200, 0, 0, 54, 55 },
    { 199, 0, 0, 54, 54 }
};

// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// END render.c
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// BEGIN test_hello.c
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

// was int32_t main
int32_t test_hello_main(int32_t argc, int8_t** argv)
{
    // note: must be caps
    const char * input = "HELLO WORLD [";

    SetInput(input);
    if (!SAMMain()) {
        return 1;
    }

    return WriteWav(GetBuffer(), GetBufferLength() / 50);
}

int32_t WriteWav(int8_t* buffer, int32_t bufferlength)
{
    return 0;
}

// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// END test_hello.c
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++






// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// BEGIN test_phonemes.c
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

#define END 0,0
#define C_SIZE 1024
static char temp[C_SIZE];

static const char * test_case[] = {
#if 1
    // ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
    "HELLO",
    " /HEHLOW",
    // ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
    "WIZARD",
    " WIHZAA5RD",
    // ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
    "TWO THINGS",
    " TUW THIHNXZ",
    // ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
    "ANOTHER TRAVELER",
    " AENAH5DHER TRAEVIY4LER",
    // ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
    "HELLO, MY NAME IS SAM.",
    " /HEHLOW, MAY NEYM IHZ SAEM.",
    // ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
    "THE SKY ABOVE THE PORT WAS THE COLOR OF TELEVISION, TUNED TO A DEAD"
        "CHANNEL.",
    " DHAX SKAY AEBAH4V DHAX PAORT WAHZ DHAX KAALER AHV TEHLEHVIHZHUN, TUWND "
        "TUX AH DEHDCHAENEHL.",
#endif
    // ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
    "IT'S NOT LIKE I'M USING, CASE HEARD SOMEONE SAY, AS HE SHOULDERED HIS"
        "WAY THROUGH THE CROWD AROUND THE DOOR OF THE CHAT.",
    " IHTS NAAT LAY5K IHM YUWZIHNX, KEY4S /HIY5RD SAHMWAHN SEY5, AEZ /HIY "
        "SHUH5DIY4RD /HIHSWEY5 THRUW4 DHAX KROWD AXRAWND DHAX DOH5R AHV DHAX "
        "CHAET.",
    // ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
    "ITS LIKE MY BODYS DEVELOPED THIS MASSIVE DRUG DEFICIENCY.",
    " IHTS LAY5K MAY BAADIYS DIHVEHLOW5PT DHIHS MAESIHV DRAHG DIHFIHSHEHNSIY.",
    // ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
    "IT WAS A SPRAWL VOICE AND A SPRAWL JOKE.",
    " IHT WAHZ AH SPRAO5L VOY5S AEND AH SPRAO5L JOW5K.",
    // ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
    "THE CHATSUBO WAS A BAR FOR PROFESSIONAL EXPATRIATES YOU COULD DRINK THERE"
        "FOR A WEEK AND NEVER HEAR TWO WORDS IN JAPANESE.",
    " DHAX CHAETSUWBOW WAHZ AH BAA5R FAOR PROW5FEHSHUNUL EHKSPAETRIHEYTS YUW "
        "KUH5D DRIHNXK DHEHRFER AH WIY4K AEND NEH4VER /HIY5R TUW WERDZ IHN "
        "JAEPEYNIY4Z.",
    // ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
    "RATZ WAS TENDING BAR, HIS PROSTHETIC ARM JERKING MONOTONOUSLY AS HE FILLED"
        "A TRAY OF GLASSES WITH DRAFT KIRIN.",
    " RAETZ WAHZ TEHNDIHNX BAA5R, /HIHZ PROWSTHEHTIHK AA5RM JERKIHNX "
        "MAHNAATUNAXSLIY AEZ /HIY FIHLEHDAH TREY5 AHV GLAESIHZ WIHTH",
    // ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
    "HE SAW CASE AND SMILED, HIS TEETH A WEB WORK OF EAST EUROPEAN STEEL AND"
        "BROWN DECAY.",
    " /HIY SAO5 KEY4S AEND SMAY5LD, /HIHZ TIY4TH AH WEHB WERK AHV IY5ST "
        "YUW5RAAPIY5N STIY4L AENDBROWN DIHKEY5.",
    // ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
    "CASE FOUND A PLACE AT THE BAR, BETWEEN THE UNLIKELY TAN ON ONE OF LONNY"
        "ZONE'S WHORES AND THE CRISP NAVAL UNIFORM OF A TALL AFRICAN WHOSE"
        "CHEEKBONES WERE RIDGED WITH PRECISE ROWS OF TRIBAL SCARS.",
    " KEY4S FAWND AH PLEYS AET DHAX BAA5R, BEHTWIY4N DHIY AHNLIHKLIY TAEN AAN "
        "WAHN AHV LAHNIYZUNEHS /HUWRZ AEND DHAX KRIHSP NAEVUL YUWNIHFAORM AHV "
        "AH TAOL AEFRIHKAEN /HUWZEHKIY4KBOW5NZ WER RIHDJD WIHTH PREHSAYZ ROWZ "
        "AHV TRIHBUL SKAA5RZ.",
    // ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
    "WAGE WAS IN HERE EARLY, WITH TWO JOE BOYS, RATZ SAID, SHOVING A DRAFT"
        "ACROSS THE BAR WITH HIS GOOD HAND.",
    " WEYJ WAHZ IHN /HIYR ER5LIY, WIHTH TUW JOW BOYZ, RAETZ SEHD, SHAH4VIHNX "
        "AH DRAEFTAEKRAO5S DHAX BAA5R WIHTH /HIHZ GUH5D /HAEND.",
    // ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
    "MAYBE SOME BUSINESS WITH YOU, CASE. CASE SHRUGGED.",
    " MEY5B SAHM BIH4ZIHNEHS WIHTH YUW, KEY4S. KEY4S SHRAH5GD.",
    // ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
    "THE GIRL TO HIS RIGHT GIGGLED AND NUDGED HIM.",
    " DHAX GERL TUX /HIHZ RAY4T GIHGULD AEND NAH5DJD /HIHM.",
    // ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --
    END
};

// END test_phonemes.c







// BEGIN debug.h

int32_t debug = 0;

// END debug.h









// BEGIN test_phonemes.c

// was int32_t main
int32_t test_phonemes_main(int32_t argc, int8_t** argv)
{
    test_state_t state;
    memset(&state, 0, sizeof(test_state_t));

    // verify the reciter tables are well formed
    ReciterVerify();

    // try expect loop
    for (size_t i = 0; test_case[i]; i += 2) {
        if (!try_test(test_case[i+0], test_case[i+1])) {
            printf("x");
            state.fails_++;
        }
        else {
            printf(".");
            state.passes_++;;
        }
    }
    // input test files
    file_test(SAM_TEST_DIR "\\assets\\words.txt", &state);
    file_test(SAM_TEST_DIR "\\assets\\sentences.txt", &state);
    // print raw summary
    printf("\ntotal : %d", state.fails_ + state.passes_);
    printf("\nfailed: %d", state.fails_);
    printf("\npassed: %d", state.passes_);
    if (state.fails_) {
        getchar();
    }

    return state.fails_;
} // int32_t main

static int compare(const char * a, const char * b) {
    while (*a && !(*b&0x80)) {
        if (*a!=*b) {
            return 0;
        }
        ++a, ++b;
    }
    return 1;
} // static int compare

static void trim() {
    for (size_t i = 0; i<C_SIZE; ++i) {
        if (temp[i] & 0x80) {
            temp[i] = '\0';
            break;
        }
    }
} // static void trim

static int try_test(const char * in, const char * match)
{
    memset(temp, 0x80, C_SIZE);
    strcpy_s(temp, C_SIZE, in);
    strcat_s(temp, C_SIZE, "[");
    if (!TextToPhonemes(temp, C_SIZE)) {
        return 0;
    }
    temp[C_SIZE-1] = '\0';
    trim();
    if (!compare(match, temp)) {
        printf("\nsent\n'%s';\nexpected\n'%s';\ngot\n'%s'\n", in, match, temp);
        return 0;
    }
    return 1;
} // static int try_test

size_t read_line(FILE * fd, char * dst, size_t max)
{
    assert(fd && dst);
    char * ptr = dst;
    const char * end = dst+max;
    size_t size = 0;
    for (; ptr!=end; ++ptr) {
        if (feof(fd)) {
            return 0;
        }
        if (fread(ptr, 1, 1, fd)!=1) {
            return 0;
        }
        if (*ptr=='\n') {
            *ptr = '\0';
            return size;
        }
        if (*ptr=='\r') {
            *ptr = '\0';
        }
        else {
            *ptr = toupper(*ptr);
            ++size;
        }
    }
    return 0;
} // size_t read_line

int file_test(const char * path, test_state_t * state)
{
    assert(state && path);
    FILE * fd = NULL;
    fopen_s(&fd, path, "rb");
    if (fd==NULL) {
        return 0;
    }
    char temp1[C_SIZE] = {'\0'};
    char temp2[C_SIZE] = {'\0'};
    size_t len = 0;
    while (len = read_line(fd, temp1, C_SIZE)) {
        temp1[len+0] = '[';
        temp1[len+1] = '\0';
        strcpy_s(temp2, C_SIZE, temp1);
        if (TextToPhonemes(temp1, C_SIZE)) {
            fputc('.', stdout);
            state->passes_++;
        }
        else {
            fputc('x', stdout);
            printf("\n%s\n", temp2);
            state->fails_++;
        }
    }
    return 1;
} // int file_test

// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// END test_phonemes.c
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
































// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// BEGIN sam.c
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void SetInput(const int8_t *_input)
{
    int32_t i, l;
    l = strlen(_input);
    if (l > 254)
        l = 254;
    for (i = 0; i < l; i++)
        input[i] = _input[i];
    input[l] = 0;
}

void SetSpeed(uint8_t _speed) { speed = _speed; };

void SetPitch(uint8_t _pitch) { pitch = _pitch; };

void SetMouth(uint8_t _mouth) { mouth = _mouth; };

void SetThroat(uint8_t _throat) { throat = _throat; };

void EnableSingmode() { singmode = 1; };

int8_t *GetBuffer() { return buffer; };

int32_t GetBufferLength() { return bufferPos; };

// 168=pitches
// 169=frequency1
// 170=frequency2
// 171=frequency3
// 172=amplitude1
// 173=amplitude2
// 174=amplitude3

void Init()
{
    int32_t i;
    SetMouthThroat(mouth, throat);

    bufferPos = 0;
    // todo: check for free the memory, 10 seconds of output should be more than enough
    // fixme: we only allocation 10 seconds of audio!!
    // todo: unhardcode sample rate
    buffer = malloc(22050 * 10);

    /*
    freq2data = &mem[45136];
    freq1data = &mem[45056];
    freq3data = &mem[45216];
    */
    // pitches = &mem[43008];
    /*
    frequency1 = &mem[43264];
    frequency2 = &mem[43520];
    frequency3 = &mem[43776];
    */
    /*
    amplitude1 = &mem[44032];
    amplitude2 = &mem[44288];
    amplitude3 = &mem[44544];
    */
    // phoneme = &mem[39904];
    /*
    ampl1data = &mem[45296];
    ampl2data = &mem[45376];
    ampl3data = &mem[45456];
    */

    for (i = 0; i < 256; i++)
    {
        stress[i] = 0;
        phonemeLength[i] = 0;
    }

    for (i = 0; i < 60; i++)
    {
        phonemeIndexOutput[i] = 0;
        stressOutput[i] = 0;
        phonemeLengthOutput[i] = 0;
    }

    // to prevent buffer overflow
    //  ML : changed from 32 to 255 to stop freezing with long inputs
    phonemeIndex[255] = 255;
} // void Init

// int32_t Code39771()
int32_t SAMMain()
{
    Init();
    phonemeIndex[255] = 32; // to prevent buffer overflow

    if (!Parser1())
        return 0;
    if (debug)
        PrintPhonemes(phonemeIndex, phonemeLength, stress);
    Parser2();
    CopyStress();
    SetPhonemeLength();
    AdjustLengths();
    Code41240();
    do
    {
        A = phonemeIndex[X];
        if (A > 80)
        {
            phonemeIndex[X] = 255;
            break; // error: delete all behind it
        }
        X++;
    } while (X != 0);

    // pos39848:
    InsertBreath();

    // mem[40158] = 255;
    if (debug)
    {
        PrintPhonemes(phonemeIndex, phonemeLength, stress);
    }

    PrepareOutput();
    return 1;
} // int32_t SAMMain

// void Code48547()
void PrepareOutput()
{
    A = 0;
    X = 0;
    Y = 0;

    // pos48551:
    while (1)
    {
        A = phonemeIndex[X];
        if (A == 255)
        {
            A = 255;
            phonemeIndexOutput[Y] = 255;
            Render();
            return;
        }
        if (A == 254)
        {
            X++;
            int32_t temp = X;
            // mem[48546] = X;
            phonemeIndexOutput[Y] = 255;
            Render();
            // X = mem[48546];
            X = temp;
            Y = 0;
            continue;
        }

        if (A == 0)
        {
            X++;
            continue;
        }

        phonemeIndexOutput[Y] = A;
        phonemeLengthOutput[Y] = phonemeLength[X];
        stressOutput[Y] = stress[X];
        X++;
        Y++;
    }
} // void PrepareOutput

// void Code48431()
void InsertBreath()
{
    uint8_t mem54;
    uint8_t mem55;
    uint8_t index; // variable Y
    mem54 = 255;
    X++;
    mem55 = 0;
    uint8_t mem66 = 0;
    while (1)
    {
        // pos48440:
        X = mem66;
        index = phonemeIndex[X];
        if (index == 255)
            return;
        mem55 += phonemeLength[X];

        if (mem55 < 232)
        {
            if (index != 254) // ML : Prevents an index out of bounds problem
            {
                A = flags2[index] & 1;
                if (A != 0)
                {
                    X++;
                    mem55 = 0;
                    Insert(X, 254, mem59, 0);
                    mem66++;
                    mem66++;
                    continue;
                }
            }
            if (index == 0)
                mem54 = X;
            mem66++;
            continue;
        }
        X = mem54;
        phonemeIndex[X] = 31; // 'Q*' glottal stop
        phonemeLength[X] = 4;
        stress[X] = 0;
        X++;
        mem55 = 0;
        Insert(X, 254, mem59, 0);
        X++;
        mem66 = X;
    }
} // void InsertBreath

// Iterates through the phoneme buffer, copying the stress value from
// the following phoneme under the following circumstance:

//     1. The current phoneme is voiced, excluding plosives and fricatives
//     2. The following phoneme is voiced, excluding plosives and fricatives, and
//     3. The following phoneme is stressed
//
//  In those cases, the stress value+1 from the following phoneme is copied.
//
// For example, the word LOITER is represented as LOY5TER, with as stress
// of 5 on the diphtong OY. This routine will copy the stress value of 6 (5+1)
// to the L that precedes it.

// void Code41883()
void CopyStress()
{
    // loop thought all the phonemes to be output
    uint8_t pos = 0; // mem66
    while (1)
    {
        // get the phomene
        Y = phonemeIndex[pos];

        // exit at end of buffer
        if (Y == 255)
            return;

        // if CONSONANT_FLAG set, skip - only vowels get stress
        if ((flags[Y] & 64) == 0)
        {
            pos++;
            continue;
        }
        // get the next phoneme
        Y = phonemeIndex[pos + 1];
        if (Y == 255) // prevent buffer overflow
        {
            pos++;
            continue;
        }
        else
            // if the following phoneme is a vowel, skip
            if ((flags[Y] & 128) == 0)
            {
                pos++;
                continue;
            }

        // get the stress value at the next position
        Y = stress[pos + 1];

        // if next phoneme is not stressed, skip
        if (Y == 0)
        {
            pos++;
            continue;
        }

        // if next phoneme is not a VOWEL OR ER, skip
        if ((Y & 128) != 0)
        {
            pos++;
            continue;
        }

        // copy stress from prior phoneme to this one
        stress[pos] = Y + 1;

        // advance pointer
        pos++;
    }
} // void CopyStress

// void Code41014()
void Insert(uint8_t position /*var57*/, uint8_t mem60, uint8_t mem59, uint8_t mem58)
{
    int32_t i;
    for (i = 253; i >= position; i--) // ML : always keep last safe-guarding 255
    {
        phonemeIndex[i + 1] = phonemeIndex[i];
        phonemeLength[i + 1] = phonemeLength[i];
        stress[i + 1] = stress[i];
    }

    phonemeIndex[position] = mem60;
    phonemeLength[position] = mem59;
    stress[position] = mem58;
    return;
} // void Insert(








// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// BEGIN Parser1 Function
// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// The input[] buffer contains a string of phonemes and stress markers along
// the lines of:
//
//     DHAX KAET IHZ AH5GLIY. <0x9B>
//
// The byte 0x9B marks the end of the buffer. Some phonemes are 2 bytes
// long, such as "DH" and "AX". Others are 1 byte long, such as "T" and "Z".
// There are also stress markers, such as "5" and ".".
//
// The first int8_tacter of the phonemes are stored in the table signInputTable1[].
// The second int8_tacter of the phonemes are stored in the table signInputTable2[].
// The stress int8_tacters are arranged in low to high stress order in stressInputTable[].
//
// The following process is used to parse the input[] buffer:
//
// Repeat until the <0x9B> int8_tacter is reached:
//
//        First, a search is made for a 2 int8_tacter match for phonemes that do not
//        end with the '*' (wildcard) int8_tacter. On a match, the index of the phoneme
//        is added to phonemeIndex[] and the buffer position is advanced 2 bytes.
//
//        If this fails, a search is made for a 1 int8_tacter match against all
//        phoneme names ending with a '*' (wildcard). If this succeeds, the
//        phoneme is added to phonemeIndex[] and the buffer position is advanced
//        1 byte.
//
//        If this fails, search for a 1 int8_tacter match in the stressInputTable[].
//        If this succeeds, the stress value is placed in the last stress[] table
//        at the same index of the last added phoneme, and the buffer position is
//        advanced by 1 byte.
//
//        If this fails, return a 0.
//
// On success:
//
//    1. phonemeIndex[] will contain the index of all the phonemes.
//    2. The last index in phonemeIndex[] will be 255.
//    3. stress[] will contain the stress value for each phoneme

// input[] holds the string of phonemes, each two bytes wide
// signInputTable1[] holds the first int8_tacter of each phoneme
// signInputTable2[] holds te second int8_tacter of each phoneme
// phonemeIndex[] holds the indexes of the phonemes after parsing input[]
//
// The parser scans through the input[], finding the names of the phonemes
// by searching signInputTable1[] and signInputTable2[]. On a match, it
// copies the index of the phoneme into the phonemeIndexTable[].
//
// The int8_tacter <0x9B> marks the end of text in input[]. When it is reached,
// the index 255 is placed at the end of the phonemeIndexTable[], and the
// function returns with a 1 indicating success.
int32_t Parser1()
{
    int32_t i;
    uint8_t sign1;
    uint8_t sign2;
    uint8_t position = 0;
    X = 0;
    A = 0;
    Y = 0;

    // CLEAR THE STRESS TABLE
    for (i = 0; i < 256; i++)
        stress[i] = 0;

    // THIS CODE MATCHES THE PHONEME LETTERS TO THE TABLE
    // pos41078:
    while (1)
    {
        // GET THE FIRST CHARACTER FROM THE PHONEME BUFFER
        sign1 = input[X];
        // TEST FOR 155 (�) END OF LINE MARKER
        if (sign1 == 155)
        {
            // MARK ENDPOINT AND RETURN
            phonemeIndex[position] = 255; // mark endpoint
            // REACHED END OF PHONEMES, SO EXIT
            return 1; // all ok
        }

        // GET THE NEXT CHARACTER FROM THE BUFFER
        X++;
        sign2 = input[X];

        // NOW sign1 = FIRST CHARACTER OF PHONEME, AND sign2 = SECOND CHARACTER OF PHONEME

        // TRY TO MATCH PHONEMES ON TWO TWO-CHARACTER NAME
        // IGNORE PHONEMES IN TABLE ENDING WITH WILDCARDS

        // SET INDEX TO 0
        Y = 0;
    pos41095:

        // GET FIRST CHARACTER AT POSITION Y IN signInputTable
        // --> should change name to PhonemeNameTable1
        A = signInputTable1[Y];

        // FIRST CHARACTER MATCHES?
        if (A == sign1)
        {
            // GET THE CHARACTER FROM THE PhonemeSecondLetterTable
            A = signInputTable2[Y];
            // NOT A SPECIAL AND MATCHES SECOND CHARACTER?
            if ((A != '*') && (A == sign2))
            {
                // STORE THE INDEX OF THE PHONEME INTO THE phomeneIndexTable
                phonemeIndex[position] = Y;

                // ADVANCE THE POINTER TO THE phonemeIndexTable
                position++;
                // ADVANCE THE POINTER TO THE phonemeInputBuffer
                X++;

                // CONTINUE PARSING
                continue;
            }
        }

        // NO MATCH, TRY TO MATCH ON FIRST CHARACTER TO WILDCARD NAMES (ENDING WITH '*')

        // ADVANCE TO THE NEXT POSITION
        Y++;
        // IF NOT END OF TABLE, CONTINUE
        if (Y != 81)
            goto pos41095;

        // REACHED END OF TABLE WITHOUT AN EXACT (2 CHARACTER) MATCH.
        // THIS TIME, SEARCH FOR A 1 CHARACTER MATCH AGAINST THE WILDCARDS

        // RESET THE INDEX TO POINT TO THE START OF THE PHONEME NAME TABLE
        Y = 0;
    pos41134:
        // DOES THE PHONEME IN THE TABLE END WITH '*'?
        if (signInputTable2[Y] == '*')
        {
            // DOES THE FIRST CHARACTER MATCH THE FIRST LETTER OF THE PHONEME
            if (signInputTable1[Y] == sign1)
            {
                // SAVE THE POSITION AND MOVE AHEAD
                phonemeIndex[position] = Y;

                // ADVANCE THE POINTER
                position++;

                // CONTINUE THROUGH THE LOOP
                continue;
            }
        }
        Y++;
        if (Y != 81)
            goto pos41134; // 81 is size of PHONEME NAME table

        // FAILED TO MATCH WITH A WILDCARD. ASSUME THIS IS A STRESS
        // CHARACTER. SEARCH THROUGH THE STRESS TABLE

        // SET INDEX TO POSITION 8 (END OF STRESS TABLE)
        Y = 8;

        // WALK BACK THROUGH TABLE LOOKING FOR A MATCH
        while ((sign1 != stressInputTable[Y]) && (Y > 0))
        {
            // DECREMENT INDEX
            Y--;
        }

        // REACHED THE END OF THE SEARCH WITHOUT BREAKING OUT OF LOOP?
        if (Y == 0)
        {
            // mem[39444] = X;
            // 41181: JSR 42043 //Error
            //  FAILED TO MATCH ANYTHING, RETURN 0 ON FAILURE
            return 0;
        }
        // SET THE STRESS FOR THE PRIOR PHONEME
        stress[position - 1] = Y;
    } // while
} // int32_t Parser1()
// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// END Parser1 Function
// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// BEGIN SetPhonemeLength
// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// change phonemelength depedendent on stress
// void Code41203()
void SetPhonemeLength()
{
    int32_t position = 0;
    while (phonemeIndex[position] != 255)
    {
        A = stress[position];
        // 41218: BMI 41229
        if ((A == 0) || ((A & 128) != 0))
        {
            phonemeLength[position] = phonemeLengthTable[phonemeIndex[position]];
        }
        else
        {
            phonemeLength[position] = phonemeStressedLengthTable[phonemeIndex[position]];
        }
        position++;
    }
} // void SetPhonemeLength()
// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// END SetPhonemeLength
// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// BEGIN
// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Code41240()
{
    uint8_t pos = 0;

    while (phonemeIndex[pos] != 255)
    {
        uint8_t index; // register AC
        X = pos;
        index = phonemeIndex[pos];
        if ((flags[index] & 2) == 0)
        {
            pos++;
            continue;
        }
        else if ((flags[index] & 1) == 0)
        {
            Insert(pos + 1, index + 1, phonemeLengthTable[index + 1], stress[pos]);
            Insert(pos + 2, index + 2, phonemeLengthTable[index + 2], stress[pos]);
            pos += 3;
            continue;
        }

        do
        {
            X++;
            A = phonemeIndex[X];
        } while (A == 0);

        if (A != 255)
        {
            if ((flags[A] & 8) != 0)
            {
                pos++;
                continue;
            }
            if ((A == 36) || (A == 37))
            {
                pos++;
                continue;
            } // '/H' '/X'
        }

        Insert(pos + 1, index + 1, phonemeLengthTable[index + 1], stress[pos]);
        Insert(pos + 2, index + 2, phonemeLengthTable[index + 2], stress[pos]);
        pos += 3;
    };
} // void Code41240()
// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// END Code41240
// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////




// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// BEGIN Parser2
// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// Rewrites the phonemes using the following rules:
//
//       <DIPHTONG ENDING WITH WX> -> <DIPHTONG ENDING WITH WX> WX
//       <DIPHTONG NOT ENDING WITH WX> -> <DIPHTONG NOT ENDING WITH WX> YX
//       UL -> AX L
//       UM -> AX M
//       <STRESSED VOWEL> <SILENCE> <STRESSED VOWEL> -> <STRESSED VOWEL> <SILENCE> Q <VOWEL>
//       T R -> CH R
//       D R -> J R
//       <VOWEL> R -> <VOWEL> RX
//       <VOWEL> L -> <VOWEL> LX
//       G S -> G Z
//       K <VOWEL OR DIPHTONG NOT ENDING WITH IY> -> KX <VOWEL OR DIPHTONG NOT ENDING WITH IY>
//       G <VOWEL OR DIPHTONG NOT ENDING WITH IY> -> GX <VOWEL OR DIPHTONG NOT ENDING WITH IY>
//       S P -> S B
//       S T -> S D
//       S K -> S G
//       S KX -> S GX
//       <ALVEOLAR> UW -> <ALVEOLAR> UX
//       CH -> CH CH' (CH requires two phonemes to represent it)
//       J -> J J' (J requires two phonemes to represent it)
//       <UNSTRESSED VOWEL> T <PAUSE> -> <UNSTRESSED VOWEL> DX <PAUSE>
//       <UNSTRESSED VOWEL> D <PAUSE>  -> <UNSTRESSED VOWEL> DX <PAUSE>

// void Code41397()
void Parser2()
{
    if (debug)
        printf("Parser2\n");
    uint8_t pos = 0; // mem66;
    uint8_t mem58 = 0;

    // Loop through phonemes
    while (1)
    {
        // SET X TO THE CURRENT POSITION
        X = pos;
        // GET THE PHONEME AT THE CURRENT POSITION
        A = phonemeIndex[pos];

        // DEBUG: Print phoneme and index
        if (debug && A != 255)
            printf("%d: %c%c\n", X, signInputTable1[A], signInputTable2[A]);

        // Is phoneme pause?
        if (A == 0)
        {
            // Move ahead to the
            pos++;
            continue;
        }

        // If end of phonemes flag reached, exit routine
        if (A == 255)
            return;

        // Copy the current phoneme index to Y
        Y = A;

        // RULE:
        //       <DIPHTONG ENDING WITH WX> -> <DIPHTONG ENDING WITH WX> WX
        //       <DIPHTONG NOT ENDING WITH WX> -> <DIPHTONG NOT ENDING WITH WX> YX
        // Example: OIL, COW

        // Check for DIPHTONG
        if ((flags[A] & 16) == 0)
            goto pos41457;

        // Not a diphthong. Get the stress
        mem58 = stress[pos];

        // End in IY sound?
        A = flags[Y] & 32;

        // If ends with IY, use YX, else use WX
        if (A == 0)
            A = 20;
        else
            A = 21; // 'WX' = 20 'YX' = 21
        // pos41443:
        //  Insert at WX or YX following, copying the stress

        if (debug)
            if (A == 20)
                printf("RULE: insert WX following diphtong NOT ending in IY sound\n");
        if (debug)
            if (A == 21)
                printf("RULE: insert YX following diphtong ending in IY sound\n");
        Insert(pos + 1, A, mem59, mem58);
        X = pos;
        // Jump to ???
        goto pos41749;

    pos41457:

        // RULE:
        //       UL -> AX L
        // Example: MEDDLE

        // Get phoneme
        A = phonemeIndex[X];
        // Skip this rule if phoneme is not UL
        if (A != 78)
            goto pos41487; // 'UL'
        A = 24;            // 'L'                 //change 'UL' to 'AX L'

        if (debug)
            printf("RULE: UL -> AX L\n");

    pos41466:
        // Get current phoneme stress
        mem58 = stress[X];

        // Change UL to AX
        phonemeIndex[X] = 13; // 'AX'
        // Perform insert. Note code below may jump up here with different values
        Insert(X + 1, A, mem59, mem58);
        pos++;
        // Move to next phoneme
        continue;

    pos41487:

        // RULE:
        //       UM -> AX M
        // Example: ASTRONOMY

        // Skip rule if phoneme != UM
        if (A != 79)
            goto pos41495; // 'UM'
        // Jump up to branch - replaces current phoneme with AX and continues
        A = 27; // 'M'  //change 'UM' to  'AX M'
        if (debug)
            printf("RULE: UM -> AX M\n");
        goto pos41466;
    pos41495:

        // RULE:
        //       UN -> AX N
        // Example: FUNCTION

        // Skip rule if phoneme != UN
        if (A != 80)
            goto pos41503; // 'UN'

        // Jump up to branch - replaces current phoneme with AX and continues
        A = 28; // 'N' //change UN to 'AX N'
        if (debug)
            printf("RULE: UN -> AX N\n");
        goto pos41466;
    pos41503:

        // RULE:
        //       <STRESSED VOWEL> <SILENCE> <STRESSED VOWEL> -> <STRESSED VOWEL> <SILENCE> Q <VOWEL>
        // EXAMPLE: AWAY EIGHT

        Y = A;
        // VOWEL set?
        A = flags[A] & 128;

        // Skip if not a vowel
        if (A != 0)
        {
            // Get the stress
            A = stress[X];

            // If stressed...
            if (A != 0)
            {
                // Get the following phoneme
                X++;
                A = phonemeIndex[X];
                // If following phoneme is a pause

                if (A == 0)
                {
                    // Get the phoneme following pause
                    X++;
                    Y = phonemeIndex[X];

                    // Check for end of buffer flag
                    if (Y == 255) // buffer overflow
                        // ??? Not sure about these flags
                        A = 65 & 128;
                    else
                        // And VOWEL flag to current phoneme's flags
                        A = flags[Y] & 128;

                    // If following phonemes is not a pause
                    if (A != 0)
                    {
                        // If the following phoneme is not stressed
                        A = stress[X];
                        if (A != 0)
                        {
                            // Insert a glottal stop and move forward
                            if (debug)
                                printf("RULE: Insert glottal stop between two stressed vowels with space between them\n");
                            // 31 = 'Q'
                            Insert(X, 31, mem59, 0);
                            pos++;
                            continue;
                        }
                    }
                }
            }
        }

        // RULES FOR PHONEMES BEFORE R
        //        T R -> CH R
        // Example: TRACK

        // Get current position and phoneme
        X = pos;
        A = phonemeIndex[pos];
        if (A != 23)
            goto pos41611; // 'R'

        // Look at prior phoneme
        X--;
        A = phonemeIndex[pos - 1];
        // pos41567:
        if (A == 69) // 'T'
        {
            // Change T to CH
            if (debug)
                printf("RULE: T R -> CH R\n");
            phonemeIndex[pos - 1] = 42;
            goto pos41779;
        }

        // RULES FOR PHONEMES BEFORE R
        //        D R -> J R
        // Example: DRY

        // Prior phonemes D?
        if (A == 57) // 'D'
        {
            // Change D to J
            phonemeIndex[pos - 1] = 44;
            if (debug)
                printf("RULE: D R -> J R\n");
            goto pos41788;
        }

        // RULES FOR PHONEMES BEFORE R
        //        <VOWEL> R -> <VOWEL> RX
        // Example: ART

        // If vowel flag is set change R to RX
        A = flags[A] & 128;
        if (debug)
            printf("RULE: R -> RX\n");
        if (A != 0)
            phonemeIndex[pos] = 18; // 'RX'

        // continue to next phoneme
        pos++;
        continue;

    pos41611:

        // RULE:
        //       <VOWEL> L -> <VOWEL> LX
        // Example: ALL

        // Is phoneme L?
        if (A == 24) // 'L'
        {
            // If prior phoneme does not have VOWEL flag set, move to next phoneme
            if ((flags[phonemeIndex[pos - 1]] & 128) == 0)
            {
                pos++;
                continue;
            }
            // Prior phoneme has VOWEL flag set, so change L to LX and move to next phoneme
            if (debug)
                printf("RULE: <VOWEL> L -> <VOWEL> LX\n");
            phonemeIndex[X] = 19; // 'LX'
            pos++;
            continue;
        }

        // RULE:
        //       G S -> G Z
        //
        // Can't get to fire -
        //       1. The G -> GX rule intervenes
        //       2. Reciter already replaces GS -> GZ

        // Is current phoneme S?
        if (A == 32) // 'S'
        {
            // If prior phoneme is not G, move to next phoneme
            if (phonemeIndex[pos - 1] != 60)
            {
                pos++;
                continue;
            }
            // Replace S with Z and move on
            if (debug)
                printf("RULE: G S -> G Z\n");
            phonemeIndex[pos] = 38; // 'Z'
            pos++;
            continue;
        }

        // RULE:
        //             K <VOWEL OR DIPHTONG NOT ENDING WITH IY> -> KX <VOWEL OR DIPHTONG NOT ENDING WITH IY>
        // Example: COW

        // Is current phoneme K?
        if (A == 72) // 'K'
        {
            // Get next phoneme
            Y = phonemeIndex[pos + 1];
            // If at end, replace current phoneme with KX
            if (Y == 255)
                phonemeIndex[pos] = 75; // ML : prevents an index out of bounds problem
            else
            {
                // VOWELS AND DIPHTONGS ENDING WITH IY SOUND flag set?
                A = flags[Y] & 32;
                if (debug)
                    if (A == 0)
                        printf("RULE: K <VOWEL OR DIPHTONG NOT ENDING WITH IY> -> KX <VOWEL OR DIPHTONG NOT ENDING WITH IY>\n");
                // Replace with KX
                if (A == 0)
                    phonemeIndex[pos] = 75; // 'KX'
            }
        }
        else

            // RULE:
            //             G <VOWEL OR DIPHTONG NOT ENDING WITH IY> -> GX <VOWEL OR DIPHTONG NOT ENDING WITH IY>
            // Example: GO

            // Is int8_tacter a G?
            if (A == 60) // 'G'
            {
                // Get the following int8_tacter
                uint8_t index = phonemeIndex[pos + 1];

                // At end of buffer?
                if (index == 255) // prevent buffer overflow
                {
                    pos++;
                    continue;
                }
                else
                    // If diphtong ending with YX, move continue processing next phoneme
                    if ((flags[index] & 32) != 0)
                    {
                        pos++;
                        continue;
                    }
                // replace G with GX and continue processing next phoneme
                if (debug)
                    printf("RULE: G <VOWEL OR DIPHTONG NOT ENDING WITH IY> -> GX <VOWEL OR DIPHTONG NOT ENDING WITH IY>\n");
                phonemeIndex[pos] = 63; // 'GX'
                pos++;
                continue;
            }

        // RULE:
        //      S P -> S B
        //      S T -> S D
        //      S K -> S G
        //      S KX -> S GX
        // Examples: SPY, STY, SKY, SCOWL

        Y = phonemeIndex[pos];
        // pos41719:
        //  Replace with softer version?
        A = flags[Y] & 1;
        if (A == 0)
            goto pos41749;
        A = phonemeIndex[pos - 1];
        if (A != 32) // 'S'
        {
            A = Y;
            goto pos41812;
        }
        // Replace with softer version
        if (debug)
            printf("RULE: S* %c%c -> S* %c%c\n", signInputTable1[Y], signInputTable2[Y], signInputTable1[Y - 12], signInputTable2[Y - 12]);
        phonemeIndex[pos] = Y - 12;
        pos++;
        continue;

    pos41749:

        // RULE:
        //      <ALVEOLAR> UW -> <ALVEOLAR> UX
        //
        // Example: NEW, DEW, SUE, ZOO, THOO, TOO

        //       UW -> UX

        A = phonemeIndex[X];
        if (A == 53) // 'UW'
        {
            // ALVEOLAR flag set?
            Y = phonemeIndex[X - 1];
            A = flags2[Y] & 4;
            // If not set, continue processing next phoneme
            if (A == 0)
            {
                pos++;
                continue;
            }
            if (debug)
                printf("RULE: <ALVEOLAR> UW -> <ALVEOLAR> UX\n");
            phonemeIndex[X] = 16;
            pos++;
            continue;
        }
    pos41779:

        // RULE:
        //       CH -> CH CH' (CH requires two phonemes to represent it)
        // Example: CHEW

        if (A == 42) // 'CH'
        {
            //        pos41783:
            if (debug)
                printf("CH -> CH CH+1\n");
            Insert(X + 1, A + 1, mem59, stress[X]);
            pos++;
            continue;
        }

    pos41788:

        // RULE:
        //       J -> J J' (J requires two phonemes to represent it)
        // Example: JAY

        if (A == 44) // 'J'
        {
            if (debug)
                printf("J -> J J+1\n");
            Insert(X + 1, A + 1, mem59, stress[X]);
            pos++;
            continue;
        }

    // Jump here to continue
    pos41812:

        // RULE: Soften T following vowel
        // NOTE: This rule fails for cases such as "ODD"
        //       <UNSTRESSED VOWEL> T <PAUSE> -> <UNSTRESSED VOWEL> DX <PAUSE>
        //       <UNSTRESSED VOWEL> D <PAUSE>  -> <UNSTRESSED VOWEL> DX <PAUSE>
        // Example: PARTY, TARDY

        // Past this point, only process if phoneme is T or D

        if (A != 69) // 'T'
            if (A != 57)
            {
                pos++;
                continue;
            } // 'D'
        // pos41825:

        // If prior phoneme is not a vowel, continue processing phonemes
        if ((flags[phonemeIndex[X - 1]] & 128) == 0)
        {
            pos++;
            continue;
        }

        // Get next phoneme
        X++;
        A = phonemeIndex[X];
        // pos41841
        //  Is the next phoneme a pause?
        if (A != 0)
        {
            // If next phoneme is not a pause, continue processing phonemes
            if ((flags[A] & 128) == 0)
            {
                pos++;
                continue;
            }
            // If next phoneme is stressed, continue processing phonemes
            // FIXME: How does a pause get stressed?
            if (stress[X] != 0)
            {
                pos++;
                continue;
            }
            // pos41856:
            //  Set phonemes to DX
            if (debug)
                printf("RULE: Soften T or D following vowel or ER and preceding a pause -> DX\n");
            phonemeIndex[pos] = 30; // 'DX'
        }
        else
        {
            A = phonemeIndex[X + 1];
            if (A == 255) // prevent buffer overflow
                A = 65 & 128;
            else
                // Is next phoneme a vowel or ER?
                A = flags[A] & 128;
            if (debug)
                if (A != 0)
                    printf("RULE: Soften T or D following vowel or ER and preceding a pause -> DX\n");
            if (A != 0)
                phonemeIndex[pos] = 30; // 'DX'
        }

        pos++;

    } // while
} // void Parser2()
// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// END Parser2
// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////



// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// BEGIN AdjustLengths
// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// Applies various rules that adjust the lengths of phonemes
//
//         Lengthen <FRICATIVE> or <VOICED> between <VOWEL> and <PUNCTUATION> by 1.5
//         <VOWEL> <RX | LX> <CONSONANT> - decrease <VOWEL> length by 1
//         <VOWEL> <UNVOICED PLOSIVE> - decrease vowel by 1/8th
//         <VOWEL> <UNVOICED CONSONANT> - increase vowel by 1/2 + 1
//         <NASAL> <STOP CONSONANT> - set nasal = 5, consonant = 6
//         <VOICED STOP CONSONANT> {optional silence} <STOP CONSONANT> - shorten both to 1/2 + 1
//         <LIQUID CONSONANT> <DIPHTONG> - decrease by 2

// void Code48619()
void AdjustLengths()
{
    // LENGTHEN VOWELS PRECEDING PUNCTUATION
    //
    // Search for punctuation. If found, back up to the first vowel, then
    // process all phonemes between there and up to (but not including) the punctuation.
    // If any phoneme is found that is a either a fricative or voiced, the duration is
    // increased by (length * 1.5) + 1

    // loop index
    X = 0;
    uint8_t index;

    // iterate through the phoneme list
    uint8_t loopIndex = 0;
    while (1)
    {
        // get a phoneme
        index = phonemeIndex[X];

        // exit loop if end on buffer token
        if (index == 255)
            break;

        // not punctuation?
        if ((flags2[index] & 1) == 0)
        {
            // skip
            X++;
            continue;
        }

        // hold index
        loopIndex = X;

    // Loop backwards from this point
    pos48644:

        // back up one phoneme
        X--;

        // stop once the beginning is reached
        if (X == 0)
            break;

        // get the preceding phoneme
        index = phonemeIndex[X];

        if (index != 255) // inserted to prevent access overrun
            if ((flags[index] & 128) == 0)
                goto pos48644; // if not a vowel, continue looping

        // pos48657:
        do
        {
            // test for vowel
            index = phonemeIndex[X];

            if (index != 255) // inserted to prevent access overrun
                // test for fricative/unvoiced or not voiced
                if (((flags2[index] & 32) == 0) || ((flags[index] & 4) != 0)) // nochmal �berpr�fen
                {
                    // A = flags[Y] & 4;
                    // if(A == 0) goto pos48688;

                    // get the phoneme length
                    A = phonemeLength[X];

                    // change phoneme length to (length * 1.5) + 1
                    A = (A >> 1) + A + 1;
                    if (debug)
                        printf("RULE: Lengthen <FRICATIVE> or <VOICED> between <VOWEL> and <PUNCTUATION> by 1.5\n");
                    if (debug)
                        printf("PRE\n");
                    if (debug)
                        printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeIndex[X]], signInputTable2[phonemeIndex[X]], phonemeLength[X]);

                    phonemeLength[X] = A;

                    if (debug)
                        printf("POST\n");
                    if (debug)
                        printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeIndex[X]], signInputTable2[phonemeIndex[X]], phonemeLength[X]);
                }
            // keep moving forward
            X++;
        } while (X != loopIndex);
        //    if (X != loopIndex) goto pos48657;
        X++;
    } // while

    // Similar to the above routine, but shorten vowels under some circumstances

    // Loop throught all phonemes
    loopIndex = 0;
    // pos48697

    while (1)
    {
        // get a phoneme
        X = loopIndex;
        index = phonemeIndex[X];

        // exit routine at end token
        if (index == 255)
            return;

        // vowel?
        A = flags[index] & 128;
        if (A != 0)
        {
            // get next phoneme
            X++;
            index = phonemeIndex[X];

            // get flags
            if (index == 255)
                mem56 = 65; // use if end marker
            else
                mem56 = flags[index];

            // not a consonant
            if ((flags[index] & 64) == 0)
            {
                // RX or LX?
                if ((index == 18) || (index == 19)) // 'RX' & 'LX'
                {
                    // get the next phoneme
                    X++;
                    index = phonemeIndex[X];

                    // next phoneme a consonant?
                    if ((flags[index] & 64) != 0)
                    {
                        // RULE: <VOWEL> RX | LX <CONSONANT>

                        if (debug)
                            printf("RULE: <VOWEL> <RX | LX> <CONSONANT> - decrease length by 1\n");
                        if (debug)
                            printf("PRE\n");
                        if (debug)
                            printf("phoneme %d (%c%c) length %d\n", loopIndex, signInputTable1[phonemeIndex[loopIndex]], signInputTable2[phonemeIndex[loopIndex]], phonemeLength[loopIndex]);

                        // decrease length of vowel by 1 frame
                        phonemeLength[loopIndex]--;

                        if (debug)
                            printf("POST\n");
                        if (debug)
                            printf("phoneme %d (%c%c) length %d\n", loopIndex, signInputTable1[phonemeIndex[loopIndex]], signInputTable2[phonemeIndex[loopIndex]], phonemeLength[loopIndex]);
                    }
                    // move ahead
                    loopIndex++;
                    continue;
                }
                // move ahead
                loopIndex++;
                continue;
            }

            // Got here if not <VOWEL>

            // not voiced
            if ((mem56 & 4) == 0)
            {
                // Unvoiced
                // *, .*, ?*, ,*, -*, DX, S*, SH, F*, TH, /H, /X, CH, P*, T*, K*, KX

                // not an unvoiced plosive?
                if ((mem56 & 1) == 0)
                {
                    // move ahead
                    loopIndex++;
                    continue;
                }

                // P*, T*, K*, KX

                // RULE: <VOWEL> <UNVOICED PLOSIVE>
                // <VOWEL> <P*, T*, K*, KX>

                // move back
                X--;

                if (debug)
                    printf("RULE: <VOWEL> <UNVOICED PLOSIVE> - decrease vowel by 1/8th\n");
                if (debug)
                    printf("PRE\n");
                if (debug)
                    printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeIndex[X]], signInputTable2[phonemeIndex[X]], phonemeLength[X]);

                // decrease length by 1/8th
                mem56 = phonemeLength[X] >> 3;
                phonemeLength[X] -= mem56;

                if (debug)
                    printf("POST\n");
                if (debug)
                    printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeIndex[X]], signInputTable2[phonemeIndex[X]], phonemeLength[X]);

                // move ahead
                loopIndex++;
                continue;
            }

            // RULE: <VOWEL> <VOICED CONSONANT>
            // <VOWEL> <WH, R*, L*, W*, Y*, M*, N*, NX, DX, Q*, Z*, ZH, V*, DH, J*, B*, D*, G*, GX>

            if (debug)
                printf("RULE: <VOWEL> <VOICED CONSONANT> - increase vowel by 1/2 + 1\n");
            if (debug)
                printf("PRE\n");
            if (debug)
                printf("phoneme %d (%c%c) length %d\n", X - 1, signInputTable1[phonemeIndex[X - 1]], signInputTable2[phonemeIndex[X - 1]], phonemeLength[X - 1]);

            // decrease length
            A = phonemeLength[X - 1];
            phonemeLength[X - 1] = (A >> 2) + A + 1; // 5/4*A + 1

            if (debug)
                printf("POST\n");
            if (debug)
                printf("phoneme %d (%c%c) length %d\n", X - 1, signInputTable1[phonemeIndex[X - 1]], signInputTable2[phonemeIndex[X - 1]], phonemeLength[X - 1]);

            // move ahead
            loopIndex++;
            continue;
        }

        // WH, R*, L*, W*, Y*, M*, N*, NX, Q*, Z*, ZH, V*, DH, J*, B*, D*, G*, GX

        // pos48821:

        // RULE: <NASAL> <STOP CONSONANT>
        //       Set punctuation length to 6
        //       Set stop consonant length to 5

        // nasal?
        if ((flags2[index] & 8) != 0)
        {
            // M*, N*, NX,
            // get the next phoneme
            X++;
            index = phonemeIndex[X];

            // end of buffer?
            if (index == 255)
                A = 65 & 2; // prevent buffer overflow
            else
                A = flags[index] & 2; // check for stop consonant

            // is next phoneme a stop consonant?
            if (A != 0)

            // B*, D*, G*, GX, P*, T*, K*, KX

            {
                if (debug)
                    printf("RULE: <NASAL> <STOP CONSONANT> - set nasal = 5, consonant = 6\n");
                if (debug)
                    printf("POST\n");
                if (debug)
                    printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeIndex[X]], signInputTable2[phonemeIndex[X]], phonemeLength[X]);
                if (debug)
                    printf("phoneme %d (%c%c) length %d\n", X - 1, signInputTable1[phonemeIndex[X - 1]], signInputTable2[phonemeIndex[X - 1]], phonemeLength[X - 1]);

                // set stop consonant length to 6
                phonemeLength[X] = 6;

                // set nasal length to 5
                phonemeLength[X - 1] = 5;

                if (debug)
                    printf("POST\n");
                if (debug)
                    printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeIndex[X]], signInputTable2[phonemeIndex[X]], phonemeLength[X]);
                if (debug)
                    printf("phoneme %d (%c%c) length %d\n", X - 1, signInputTable1[phonemeIndex[X - 1]], signInputTable2[phonemeIndex[X - 1]], phonemeLength[X - 1]);
            }
            // move to next phoneme
            loopIndex++;
            continue;
        }

        // WH, R*, L*, W*, Y*, Q*, Z*, ZH, V*, DH, J*, B*, D*, G*, GX

        // RULE: <VOICED STOP CONSONANT> {optional silence} <STOP CONSONANT>
        //       Shorten both to (length/2 + 1)

        // (voiced) stop consonant?
        if ((flags[index] & 2) != 0)
        {
            // B*, D*, G*, GX

            // move past silence
            do
            {
                // move ahead
                X++;
                index = phonemeIndex[X];
            } while (index == 0);

            // check for end of buffer
            if (index == 255) // buffer overflow
            {
                // ignore, overflow code
                if ((65 & 2) == 0)
                {
                    loopIndex++;
                    continue;
                }
            }
            else if ((flags[index] & 2) == 0)
            {
                // if another stop consonant, move ahead
                loopIndex++;
                continue;
            }

            // RULE: <UNVOICED STOP CONSONANT> {optional silence} <STOP CONSONANT>
            if (debug)
                printf("RULE: <UNVOICED STOP CONSONANT> {optional silence} <STOP CONSONANT> - shorten both to 1/2 + 1\n");
            if (debug)
                printf("PRE\n");
            if (debug)
                printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeIndex[X]], signInputTable2[phonemeIndex[X]], phonemeLength[X]);
            if (debug)
                printf("phoneme %d (%c%c) length %d\n", X - 1, signInputTable1[phonemeIndex[X - 1]], signInputTable2[phonemeIndex[X - 1]], phonemeLength[X - 1]);
            // X gets overwritten, so hold prior X value for debug statement
            int32_t debugX = X;
            // shorten the prior phoneme length to (length/2 + 1)
            phonemeLength[X] = (phonemeLength[X] >> 1) + 1;
            X = loopIndex;

            // also shorten this phoneme length to (length/2 +1)
            phonemeLength[loopIndex] = (phonemeLength[loopIndex] >> 1) + 1;

            if (debug)
                printf("POST\n");
            if (debug)
                printf("phoneme %d (%c%c) length %d\n", debugX, signInputTable1[phonemeIndex[debugX]], signInputTable2[phonemeIndex[debugX]], phonemeLength[debugX]);
            if (debug)
                printf("phoneme %d (%c%c) length %d\n", debugX - 1, signInputTable1[phonemeIndex[debugX - 1]], signInputTable2[phonemeIndex[debugX - 1]], phonemeLength[debugX - 1]);

            // move ahead
            loopIndex++;
            continue;
        }

        // WH, R*, L*, W*, Y*, Q*, Z*, ZH, V*, DH, J*, **,

        // RULE: <VOICED NON-VOWEL> <DIPHTONG>
        //       Decrease <DIPHTONG> by 2

        // liquic consonant?
        if ((flags2[index] & 16) != 0)
        {
            // R*, L*, W*, Y*

            // get the prior phoneme
            index = phonemeIndex[X - 1];

            // prior phoneme a stop consonant>
            if ((flags[index] & 2) != 0)
                // Rule: <LIQUID CONSONANT> <DIPHTONG>

                if (debug)
                    printf("RULE: <LIQUID CONSONANT> <DIPHTONG> - decrease by 2\n");
            if (debug)
                printf("PRE\n");
            if (debug)
                printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeIndex[X]], signInputTable2[phonemeIndex[X]], phonemeLength[X]);

            // decrease the phoneme length by 2 frames (20 ms)
            phonemeLength[X] -= 2;

            if (debug)
                printf("POST\n");
            if (debug)
                printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeIndex[X]], signInputTable2[phonemeIndex[X]], phonemeLength[X]);
        }

        // move to next phoneme
        loopIndex++;
        continue;
    }
    //            goto pos48701;
} // void AdjustLengths()
// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// END AdjustLengths
// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////



// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// BEGIN Code47503
// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// ML : Code47503 is division with remainder, and mem50 gets the sign

void Code47503(uint8_t mem52)
{
    Y = 0;
    if ((mem53 & 128) != 0)
    {
        mem53 = -mem53;
        Y = 128;
    }
    mem50 = Y;
    A = 0;
    for (X = 8; X > 0; X--)
    {
        int32_t temp = mem53;
        mem53 = mem53 << 1;
        A = A << 1;
        if (temp >= 128)
            A++;
        if (A >= mem52)
        {
            A = A - mem52;
            mem53++;
        }
    }
    mem51 = A;
    if ((mem50 & 128) != 0)
        mem53 = -mem53;
} // void Code47503(uint8_t mem52)
// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// END Code47503
// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// END sam.c
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++





// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// BEGIN reciter.c
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

// test the flag bits for a specific char
// this is non ascii layout, but tests ascii chars
uint32_t TestFlag(uint8_t in, uint8_t mask)
{
    assert(in<sizeof(tab36376));
    const uint8_t val = tab36376[in];
    return val & mask;
} // uint32_t TestFlag

// test the flag bits for the pervious char in the stream
uint32_t TestFlagDec(uint8_t mem59, uint8_t mask)
{
    X = mem59;
    X--;
    A = inputtemp[X];
    Y = A;
    assert(Y<sizeof(tab36376));
    A = tab36376[Y];
    return A & mask;
} // uint32_t TestFlagDec

// test the flag bits for the next char in the stream
uint32_t TestFlagInc(uint8_t mem58, uint8_t mask)
{
    X = mem58;
    X++;
    A = inputtemp[X];
    Y = A;
    assert(Y<sizeof(tab36376));
    A = tab36376[Y];
    return A & mask;
} // uint32_t TestFlagInc

// verify that the reciter tables are well formed
void ReciterVerify()
{
    size_t ix = 0;
    for (ix = 0; ix<28; ++ix) {
        const size_t pos = rule_tab[ix];
        assert(rules[pos]==']');
    }
} // void ReciterVerify

// lookup a byte for a specific rule in the table
uint8_t GetRuleByte(uint32_t rule_index, uint8_t Y)
{
    const size_t end = sizeof(rules);
    const size_t index = rule_index+Y;
    assert(index<end);
    return rules[index];
} // uint8_t GetRuleByte

void SecureCopyInput(int8_t * input, size_t max_size)
{
    // secure copy of input because input will be overwritten by phonemes
    X = 1;
    Y = 0;
    for (;Y<max_size;++Y) {
        A = input[Y];
        if (A<0x20) {
            continue;
        }
        if (A==0x60) {
            continue;
        }
        if (A==0x27) {
            continue;
        }
        if (A>=0x7E) {
            continue;
        }
        inputtemp[X++] = A;
    };
    memset(input, '\0', max_size);
} // void SecureCopyInput

int32_t TextToPhonemes(int8_t* input, size_t max_size)
{
    max_size = 250;

    static const uint8_t end_token = 155; // ESC | 0x80

    uint32_t out_pos; // output position for phonemes
    uint32_t mem57;
    uint32_t mem58; // current pos, used mostly in rhs match
    uint32_t mem59;
    uint32_t mem60;
    uint32_t mem61;
    uint32_t rule_index; // memory position of current rule

    uint32_t mem64; // position of '=' or current character
    uint32_t pos_rparen; // position of ')'
    uint32_t pos_lparen; // position of '('
    uint32_t mem36653;

    inputtemp[0] = 0x20; // ' '
    SecureCopyInput(input, max_size);

    Y = 255;
    X = 255;
    inputtemp[X] = 27; // ESC
    mem61 = 255;

    A = 255;
    out_pos = 255;

// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
// START PARSE
// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
L_start_parse:

    while (1) {
        mem61++;
        X = mem61;
        // if end of input marker
        A = inputtemp[X];
        mem64 = A;
        if (A=='[') {
            out_pos++;
            X = out_pos;
            A = end_token;
            input[X] = A;
            // success
            return 1;
        }
        if (A=='.') {
            // check a flag for next input char?
            X++;
            Y = inputtemp[X];
            A = TestFlag(Y, 0x01);
            if (A==0) {
                // output a '.'
                out_pos++;
                X = out_pos;
                A = '.';
                input[X] = A;
            }
            else {
                break;
            }
        }
        else {
            break;
        }
    } //while

    // if this character is non alpha
    A = mem64;
    Y = A;
    A = TestFlag(A, 0xff);
    mem57 = A;
    if (A & 0x02) {
        rule_index = rule_tab[26]; // rule2
        goto L_nextrule;
    }

    // what be this ???
    A = mem57; // flag for A
    if (A==0) {
        A = ' ';
        inputtemp[X] = A;
        out_pos++;
        X = out_pos;
        // hard exit on too long?
        if (X > max_size) {
            input[max_size-1] = end_token;
            A = mem61;
            mem36653 = A;
            return 0;
        }
        else {
            input[X] = A;
            goto L_start_parse;
        }
    }

    // what is A at this point?
    A = mem57 & 0x80;
    if (A==0) {
        // error
        return 0;
    }

    // go to the right rules for this character.
    X = mem64 - 'A';
    assert(X<26);
    rule_index = rule_tab[X];

// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
// TRY MATCHING NEXT RULE
// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
L_nextrule:

    // find next rule
    // skip to next rule byte with 0x80 mask
    Y = 0;
    do {
        rule_index += 1;
        A = GetRuleByte(rule_index, Y);
    } while ((A&0x80)==0);
    Y++;

    // if there are no more rules in this set
    if (GetRuleByte(rule_index, Y)==']') {
        return 0;
    }

    // identify key points in this rule

    // find '('
    while (1) {
        // fixme: fix infinite loop here with ' chars
        A = GetRuleByte(rule_index, Y);
        assert((A & 0x80)==0);
        if (A == '(')
            break;
        Y++;
    }
    pos_lparen = Y;

    // find ')'
    do {
        Y++;
        A = GetRuleByte(rule_index, Y);
    } while (A != ')');
    pos_rparen = Y;

    // find '='
    do {
        Y++;
        A = GetRuleByte(rule_index, Y);
        A = A & 0x7F;
    } while (A != '=');
    mem64 = Y;

    X = mem61;
    mem60 = X;

// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
// MATCH EXPRESSION IN PARENTHESIS
// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
    Y = pos_lparen;
    Y++;
    // pos36759:
    while (1) {
        mem57 = inputtemp[X];
        A = GetRuleByte(rule_index, Y);
        if (A!=mem57) {
            // no match lets apply next rule
            goto L_nextrule;
        }
        Y++;
        if (Y==pos_rparen) {
            break;
        }
        X++;
        mem60 = X;
    }

    // the string in the bracket is correct

    // pos36787:
    A = mem61;
    mem59 = mem61;

// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
// MATCH TO LEFT OF ( IN RULE
// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
L_match_left:
    // scan back to find start?
    for (;;) {
        pos_lparen--;
        Y = pos_lparen;
        A = GetRuleByte(rule_index, Y);
        mem57 = A;
        // if end of lhs pattern
        if (A & 0x80) {
            A = mem60;
            mem58 = A;
            goto L_match_right;
        }
        //
        X = A & 0x7f;            // all but msb
        A = TestFlag(X, 0x80);
        if (A==0) {
            // parse special escape rule
            break;
        }
        X = mem59 - 1;
        A = inputtemp[X];
        if (A!=mem57) {
            goto L_nextrule;
        }
        mem59 = X;
    }

    // test for special escape chars
    A = mem57;
    switch (A) {
    case (' '): goto pos36895;
    case ('#'): goto pos36910;
    case ('.'): goto pos36920;
    case ('&'): goto pos36935;
    case ('@'): goto pos36967;
    case ('^'): goto pos37004;
    case ('+'): goto pos37019;
    case (':'): goto pos37040;
    default:
        // error
        return 0;
    }

// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
pos36895: // handle ' '
    A = TestFlagDec(mem59, 0x80);
    if (A == 0) {
        mem59 = X;
        goto L_match_left;
    }
    goto L_nextrule;

// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
pos36910: // handle '#'
    A = TestFlagDec(mem59, 0x40);
    if (A!=0) {
        mem59 = X;
        goto L_match_left;
    }
    goto L_nextrule;

// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
pos36920: // handle '.'
    A = TestFlagDec(mem59, 0x08);
    if (A!=0) {
        mem59 = X;
        goto L_match_left;
    }
    goto L_nextrule;

// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
pos36935: // handle '&'
    A = TestFlagDec(mem59, 0x10);
    if (A!=0) {
        mem59 = X;
        goto L_match_left;
    }
    A = inputtemp[X];
    if (A=='H') {
        X--;
        A = inputtemp[X];
        if ((A=='C')||(A=='S')) {
            mem59 = X;
            goto L_match_left;
        }
    }
    goto L_nextrule;

// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
pos36967: // handle '@'
    A = TestFlagDec(mem59, 0x04);
    if (A!=0) {
        mem59 = X;
        goto L_match_left;
    }
    A = inputtemp[X];
    if ((A!='H')&&(A!='T')&&(A!='C')&&(A!='S')) {
        goto L_nextrule;
    }
    mem59 = X;
    goto L_match_left;

// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
pos37004: // handle '^'
    A = TestFlagDec(mem59, 0x20);
    if (A!=0) {
        mem59 = X;
        goto L_match_left;
    }
    goto L_nextrule;

// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
pos37019: // handle '+'
    X = mem59;
    X--;
    A = inputtemp[X];
    if ((A=='E')||(A=='I')||(A=='Y')) {
        mem59 = X;
        goto L_match_left;
    }
    goto L_nextrule;

// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
pos37040: // handle ':'
    A = TestFlagDec(mem59, 0x20);
    if (A!=0) {
        mem59 = X;
        goto pos37040;
    }
    goto L_match_left;

// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
pos37077: // handle '%'
    X = mem58 + 1;
    A = inputtemp[X];
    if (A!='E') {
        goto L_match_ing;
    }
    X++;
    Y = inputtemp[X];
    X--;
    A = TestFlag(Y, 0x80);
    if (A!=0) {
        X++;
        A = inputtemp[X];
        if (A!='R') {
            goto pos37113;
        }
    }
    mem58 = X;
    goto L_match_right;

// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
pos37113: // unknown ???
    if ((A=='S') || (A=='D')) {
        mem58 = X;
        goto L_match_right;
    }
    if (A!='L') {
        goto pos37135;
    }
    X++;
    A = inputtemp[X];
    if (A!='Y') {
        goto L_nextrule;
    }
    mem58 = X;
    goto L_match_right;

pos37135: // match FUV
    if (A!='F') {
        goto L_nextrule;
    }
    X++;
    A = inputtemp[X];
    if (A!='U') {
        goto L_nextrule;
    }
    X++;
    A = inputtemp[X];
    if (A!='V') {
        goto L_nextrule;
    }
    mem58 = X;
    goto L_match_right;

L_match_ing: // match 'ING'
    if (A!='I') {
        goto L_nextrule;
    }
    X++;
    A = inputtemp[X];
    if (A!='N') {
        goto L_nextrule;
    }
    X++;
    A = inputtemp[X];
    if (A!='G') {
        goto L_nextrule;
    }
    mem58 = X;
    goto L_match_right;

// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
// MATCH RIGHT OF ) IN RULE
// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
L_match_right:
    Y = pos_rparen + 1;
    if (Y==mem64) {
        goto L_emitrule;
    }
    pos_rparen = Y;
    A = GetRuleByte(rule_index, Y);
    mem57 = A;
    X = A;
    A = TestFlag(X, 0x80);
    if (A==0) {
        A = mem57;
        switch (A) {
        case (' '): goto pos37295;
        case ('#'): goto pos37310;
        case ('.'): goto pos37320;
        case ('&'): goto pos37335;
        case ('@'): goto pos37367;
        case ('^'): goto pos37404;
        case ('+'): goto pos37419;
        case (':'): goto pos37440;
        case ('%'): goto pos37077;
        default:
            // error
            return 0;
        }
    }
    else {
        // what this does ??
        X = mem58+1;
        A = inputtemp[X];
        if (A!=mem57) {
            goto L_nextrule;
        }
        mem58 = X;
        goto L_match_right;
    }

// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
pos37295: // handle ' '
    A = TestFlagInc(mem58, 0x80);
    if (A!=0) {
        goto L_nextrule;
    }
    mem58 = X;
    goto L_match_right;

// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
pos37310: // handle '#'
    A = TestFlagInc(mem58, 0x40);
    if (A!=0) {
        mem58 = X;
        goto L_match_right;
    }
    goto L_nextrule;

// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
pos37320: // handle '.'
    A = TestFlagInc(mem58, 0x08);
    if (A == 0)
        goto L_nextrule;
    mem58 = X;
    goto L_match_right;

// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
pos37335: // handle '&'
    A = TestFlagInc(mem58, 0x10);
    if (A!=0) {
        mem58 = X;
        goto L_match_right;
    }
    A = inputtemp[X];
    if (A!='H') {
        goto L_nextrule;
    }
    // is this really x++ not x--?
    X++;
    A = inputtemp[X];
    if ((A=='C')||(A=='S')) {
        mem58 = X;
        goto L_match_right;
    }
    goto L_nextrule;

// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
pos37367: // handle '@'
    A = TestFlagInc(mem58, 0x04);
    if (A!=0) {
        mem58 = X;
        goto L_match_right;
    }
    A = inputtemp[X];
    if ((A!='H')&&(A!='T')&&(A!='C')&&(A!='S')) {
        goto L_nextrule;
    }
    mem58 = X;
    goto L_match_right;

// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
pos37404: // handle '^'
    A = TestFlagInc(mem58, 0x20);
    if (A==0) {
        goto L_nextrule;
    }
    mem58 = X;
    goto L_match_right;

// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
pos37419: // handle '+'
    X = mem58;
    X++;
    A = inputtemp[X];
    if ((A=='E')||(A=='I')||(A=='Y')) {
        mem58 = X;
        goto L_match_right;
    }
    goto L_nextrule;

// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
pos37440: // handle ':'
    for (;;) {
        A = TestFlagInc(mem58, 0x20);
        if (A==0) {
            goto L_match_right;
        }
        mem58 = X;
    }
    goto L_emitrule;

// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
// EMIT RULE
// ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
L_emitrule:
    Y = mem64;
    mem61 = mem60;
    if (debug) {
        PrintRule(rule_index);
    }
    for (;; ++Y) {
        A = GetRuleByte(rule_index, Y);
        mem57 = A;
        // mask out parity
        A = A & 0x7f;
        if (A != '=') {
            out_pos++;
            X = out_pos;
            input[X] = A;
        }
        // if has parity set
        if (mem57 & 0x80) {
            goto L_start_parse;
        }
    }
} // int32_t TextToPhonemes

// END reciter.c







// BEGIN render.c

void Output(int32_t index, uint8_t A)
{
    static uint32_t oldtimetableindex = 0;
    int32_t k;
    bufferPos += timetable[oldtimetableindex][index];
    oldtimetableindex = index;
    // write a little bit in advance
    for (k = 0; k < 5; k++)
        buffer[bufferPos / 50 + k] = (A & 15) * 16;
} // void Output

//written by me because of different table positions.
// mem[47] = ...
// 168=pitches
// 169=frequency1
// 170=frequency2
// 171=frequency3
// 172=amplitude1
// 173=amplitude2
// 174=amplitude3
uint8_t Read(uint8_t p, uint8_t Y)
{
    switch (p) {
    case 168:
        return pitches[Y];
    case 169:
        return frequency1[Y];
    case 170:
        return frequency2[Y];
    case 171:
        return frequency3[Y];
    case 172:
        return amplitude1[Y];
    case 173:
        return amplitude2[Y];
    case 174:
        return amplitude3[Y];
    }
    printf("Error reading to tables");
    return 0;
} // uint8_t Read

void Write(uint8_t p, uint8_t Y, uint8_t value)
{
    switch (p) {
    case 168:
        pitches[Y] = value;
        return;
    case 169:
        frequency1[Y] = value;
        return;
    case 170:
        frequency2[Y] = value;
        return;
    case 171:
        frequency3[Y] = value;
        return;
    case 172:
        amplitude1[Y] = value;
        return;
    case 173:
        amplitude2[Y] = value;
        return;
    case 174:
        amplitude3[Y] = value;
        return;
    default:
        printf("Error writing to tables\n");
    }
} // void Write

// -------------------------------------------------------------------------
//Code48227
// Render a sampled sound from the sampleTable.
//
//   Phoneme   Sample Start   Sample End
//   32: S*    15             255
//   33: SH    257            511
//   34: F*    559            767
//   35: TH    583            767
//   36: /H    903            1023
//   37: /X    1135           1279
//   38: Z*    84             119
//   39: ZH    340            375
//   40: V*    596            639
//   41: DH    596            631
//
//   42: CH
//   43: **    399            511
//
//   44: J*
//   45: **    257            276
//   46: **
//
//   66: P*
//   67: **    743            767
//   68: **
//
//   69: T*
//   70: **    231            255
//   71: **
//
// The SampledPhonemesTable[] holds flags indicating if a phoneme is
// voiced or not. If the upper 5 bits are zero, the sample is voiced.
//
// Samples in the sampleTable are compressed, with bits being converted to
// bytes from high bit to low, as follows:
//
//   unvoiced 0 bit   -> X
//   unvoiced 1 bit   -> 5
//
//   voiced 0 bit     -> 6
//   voiced 1 bit     -> 24
//
// Where X is a value from the table:
//
//   { 0x18, 0x1A, 0x17, 0x17, 0x17 };
//
// The index into this table is determined by masking off the lower
// 3 bits from the SampledPhonemesTable:
//
//        index = (SampledPhonemesTable[i] & 7) - 1;
//
// For voices samples, samples are interleaved between voiced output.

// Code48227()
void RenderSample(uint8_t* mem66)
{
    int32_t tempA;
    // current phoneme's index
    mem49 = Y;

    // mask low three bits and subtract 1 get value to
    // convert 0 bits on unvoiced samples.
    A = mem39 & 7;
    X = A - 1;

    // store the result
    mem56 = X;

    // determine which offset to use from table { 0x18, 0x1A, 0x17, 0x17, 0x17 }
    // T, S, Z                0          0x18
    // CH, J, SH, ZH          1          0x1A
    // P, F*, V, TH, DH       2          0x17
    // /H                     3          0x17
    // /X                     4          0x17

    // get value from the table
    mem53 = tab48426[X];
    mem47 = X; //46016+mem[56]*256

    // voiced sample?
    A = mem39 & 248;
    if (A == 0) {
        // voiced phoneme: Z*, ZH, V*, DH
        Y = mem49;
        A = pitches[mem49] >> 4;

        // jump to voiced portion
        goto pos48315;
    }

    Y = A ^ 255;
pos48274:

    // step through the 8 bits in the sample
    mem56 = 8;

    // get the next sample from the table
    // mem47*256 = offset to start of samples
    A = sampleTable[mem47 * 256 + Y];
pos48280:

    // left shift to get the high bit
    tempA = A;
    A = A << 1;
    //48281: BCC 48290

    // bit not set?
    if ((tempA & 128) == 0) {
        // convert the bit to value from table
        X = mem53;
        //mem[54296] = X;
        // output the byte
        Output(1, X);
        // if X != 0, exit loop
        if (X != 0)
            goto pos48296;
    }

    // output a 5 for the on bit
    Output(2, 5);

//48295: NOP
pos48296:

    X = 0;

    // decrement counter
    mem56--;

    // if not done, jump to top of loop
    if (mem56 != 0)
        goto pos48280;

    // increment position
    Y++;
    if (Y != 0)
        goto pos48274;

    // restore values and return
    mem44 = 1;
    Y = mem49;
    return;

    uint8_t phase1;

pos48315:
    // handle voiced samples here

    // number of samples?
    phase1 = A ^ 255;

    Y = *mem66;
    do {
        //pos48321:

        // shift through all 8 bits
        mem56 = 8;
        //A = Read(mem47, Y);

        // fetch value from table
        A = sampleTable[mem47 * 256 + Y];

        // loop 8 times
        //pos48327:
        do {
            //48327: ASL A
            //48328: BCC 48337

            // left shift and check high bit
            tempA = A;
            A = A << 1;
            if ((tempA & 128) != 0) {
                // if bit set, output 26
                X = 26;
                Output(3, X);
            }
            else {
                //timetable 4
                // bit is not set, output a 6
                X = 6;
                Output(4, X);
            }

            mem56--;
        } while (mem56 != 0);

        // move ahead in the table
        Y++;

        // continue until counter done
        phase1++;

    } while (phase1 != 0);

    // restore values and return
    A = 1;
    mem44 = 1;
    *mem66 = Y;
    Y = mem49;
    return;
} // void RenderSample

// RENDER THE PHONEMES IN THE LIST
//
// The phoneme list is converted into sound through the steps:
//
// 1. Copy each phoneme <length> number of times into the frames list,
//    where each frame represents 10 milliseconds of sound.
//
// 2. Determine the transitions lengths between phonemes, and linearly
//    interpolate the values across the frames.
//
// 3. Offset the pitches by the fundamental frequency.
//
// 4. Render the each frame.

//void Code47574()
void Render()
{
    uint8_t phase1 = 0; //mem43
    uint8_t phase2;
    uint8_t phase3;
    uint8_t mem66;
    uint8_t mem38;
    uint8_t mem40;
    uint8_t speedcounter; //mem45
    uint8_t mem48;
    int32_t i;
    int32_t carry;
    if (phonemeIndexOutput[0] == 255)
        return; //exit if no data

    A = 0;
    X = 0;
    mem44 = 0;

    // CREATE FRAMES
    //
    // The length parameter in the list corresponds to the number of frames
    // to expand the phoneme to. Each frame represents 10 milliseconds of time.
    // So a phoneme with a length of 7 = 7 frames = 70 milliseconds duration.
    //
    // The parameters are copied from the phoneme to the frame verbatim.

    // pos47587:
    do {
        // get the index
        Y = mem44;
        // get the phoneme at the index
        A = phonemeIndexOutput[mem44];
        mem56 = A;

        // if terminal phoneme, exit the loop
        if (A == 255)
            break;

        // period phoneme *.
        if (A == 1) {
            // add rising inflection
            A = 1;
            mem48 = 1;
            //goto pos48376;
            AddInflection(mem48, phase1);
        }
        /*
        if (A == 2) goto pos48372;
        */

        // question mark phoneme?
        if (A == 2) {
            // create falling inflection
            mem48 = 255;
            AddInflection(mem48, phase1);
        }
        //    pos47615:

        // get the stress amount (more stress = higher pitch)
        phase1 = tab47492[stressOutput[Y] + 1];

        // get number of frames to write
        phase2 = phonemeLengthOutput[Y];
        Y = mem56;

        // copy from the source to the frames list
        do {
            frequency1[X] = freq1data[Y]; // F1 frequency
            frequency2[X] = freq2data[Y]; // F2 frequency
            frequency3[X] = freq3data[Y]; // F3 frequency
            amplitude1[X] = ampl1data[Y]; // F1 amplitude
            amplitude2[X] = ampl2data[Y]; // F2 amplitude
            amplitude3[X] = ampl3data[Y]; // F3 amplitude
            sampledConsonantFlag[X] = sampledConsonantFlags[Y]; // phoneme data for sampled consonants
            pitches[X] = pitch + phase1; // pitch
            X++;
            phase2--;
        } while (phase2 != 0);
        mem44++;
    } while (mem44 != 0);
    // -------------------
    //pos47694:

    // CREATE TRANSITIONS
    //
    // Linear transitions are now created to smoothly connect the
    // end of one sustained portion of a phoneme to the following
    // phoneme.
    //
    // To do this, three tables are used:
    //
    //  Table         Purpose
    //  =========     ==================================================
    //  blendRank     Determines which phoneme's blend values are used.
    //
    //  blendOut      The number of frames at the end of the phoneme that
    //                will be used to transition to the following phoneme.
    //
    //  blendIn       The number of frames of the following phoneme that
    //                will be used to transition into that phoneme.
    //
    // In creating a transition between two phonemes, the phoneme
    // with the HIGHEST rank is used. Phonemes are ranked on how much
    // their identity is based on their transitions. For example,
    // vowels are and diphthongs are identified by their sustained portion,
    // rather than the transitions, so they are given low values. In contrast,
    // stop consonants (P, B, T, K) and glides (Y, L) are almost entirely
    // defined by their transitions, and are given high rank values.
    //
    // Here are the rankings used by SAM:
    //
    //     Rank    Type                         Phonemes
    //     2       All vowels                   IY, IH, etc.
    //     5       Diphthong endings            YX, WX, ER
    //     8       Terminal liquid consonants   LX, WX, YX, N, NX
    //     9       Liquid consonants            L, RX, W
    //     10      Glide                        R, OH
    //     11      Glide                        WH
    //     18      Voiceless fricatives         S, SH, F, TH
    //     20      Voiced fricatives            Z, ZH, V, DH
    //     23      Plosives, stop consonants    P, T, K, KX, DX, CH
    //     26      Stop consonants              J, GX, B, D, G
    //     27-29   Stop consonants (internal)   **
    //     30      Unvoiced consonants          /H, /X and Q*
    //     160     Nasal                        M
    //
    // To determine how many frames to use, the two phonemes are
    // compared using the blendRank[] table. The phoneme with the
    // higher rank is selected. In case of a tie, a blend of each is used:
    //
    //      if blendRank[phoneme1] ==  blendRank[phomneme2]
    //          // use lengths from each phoneme
    //          outBlendFrames = outBlend[phoneme1]
    //          inBlendFrames = outBlend[phoneme2]
    //      else if blendRank[phoneme1] > blendRank[phoneme2]
    //          // use lengths from first phoneme
    //          outBlendFrames = outBlendLength[phoneme1]
    //          inBlendFrames = inBlendLength[phoneme1]
    //      else
    //          // use lengths from the second phoneme
    //          // note that in and out are SWAPPED!
    //          outBlendFrames = inBlendLength[phoneme2]
    //          inBlendFrames = outBlendLength[phoneme2]
    //
    // Blend lengths can't be less than zero.
    //
    // Transitions are assumed to be symetrical, so if the transition
    // values for the second phoneme are used, the inBlendLength and
    // outBlendLength values are SWAPPED.
    //
    // For most of the parameters, SAM interpolates over the range of the last
    // outBlendFrames-1 and the first inBlendFrames.
    //
    // The exception to this is the Pitch[] parameter, which is interpolates the
    // pitch from the CENTER of the current phoneme to the CENTER of the next
    // phoneme.
    //
    // Here are two examples. First, For example, consider the word "SUN" (S AH N)
    //
    //    Phoneme   Duration    BlendWeight    OutBlendFrames    InBlendFrames
    //    S         2           18             1                 3
    //    AH        8           2              4                 4
    //    N         7           8              1                 2
    //
    // The formant transitions for the output frames are calculated as follows:
    //
    //     flags ampl1 freq1 ampl2 freq2 ampl3 freq3 pitch
    //    ------------------------------------------------
    // S
    //    241     0     6     0    73     0    99    61   Use S (weight 18) for transition instead of AH (weight 2)
    //    241     0     6     0    73     0    99    61   <-- (OutBlendFrames-1) = (1-1) = 0 frames
    // AH
    //      0     2    10     2    66     0    96    59 * <-- InBlendFrames = 3 frames
    //      0     4    14     3    59     0    93    57 *
    //      0     8    18     5    52     0    90    55 *
    //      0    15    22     9    44     1    87    53
    //      0    15    22     9    44     1    87    53
    //      0    15    22     9    44     1    87    53   Use N (weight 8) for transition instead of AH (weight 2).
    //      0    15    22     9    44     1    87    53   Since N is second phoneme, reverse the IN and OUT values.
    //      0    11    17     8    47     1    98    56 * <-- (InBlendFrames-1) = (2-1) = 1 frames
    // N
    //      0     8    12     6    50     1   109    58 * <-- OutBlendFrames = 1
    //      0     5     6     5    54     0   121    61
    //      0     5     6     5    54     0   121    61
    //      0     5     6     5    54     0   121    61
    //      0     5     6     5    54     0   121    61
    //      0     5     6     5    54     0   121    61
    //      0     5     6     5    54     0   121    61
    //
    // Now, consider the reverse "NUS" (N AH S):
    //
    //     flags ampl1 freq1 ampl2 freq2 ampl3 freq3 pitch
    //    ------------------------------------------------
    // N
    //     0     5     6     5    54     0   121    61
    //     0     5     6     5    54     0   121    61
    //     0     5     6     5    54     0   121    61
    //     0     5     6     5    54     0   121    61
    //     0     5     6     5    54     0   121    61
    //     0     5     6     5    54     0   121    61   Use N (weight 8) for transition instead of AH (weight 2)
    //     0     5     6     5    54     0   121    61   <-- (OutBlendFrames-1) = (1-1) = 0 frames
    // AH
    //     0     8    11     6    51     0   110    59 * <-- InBlendFrames = 2
    //     0    11    16     8    48     0    99    56 *
    //     0    15    22     9    44     1    87    53   Use S (weight 18) for transition instead of AH (weight 2)
    //     0    15    22     9    44     1    87    53   Since S is second phoneme, reverse the IN and OUT values.
    //     0     9    18     5    51     1    90    55 * <-- (InBlendFrames-1) = (3-1) = 2
    //     0     4    14     3    58     1    93    57 *
    // S
    //   241     2    10     2    65     1    96    59 * <-- OutBlendFrames = 1
    //   241     0     6     0    73     0    99    61

    A = 0;
    mem44 = 0;
    mem49 = 0; // mem49 starts at as 0
    X = 0;
    while (1) //while No. 1
    {
        // get the current and following phoneme
        Y = phonemeIndexOutput[X];
        A = phonemeIndexOutput[X + 1];
        X++;

        // exit loop at end token
        if (A == 255)
            break; //goto pos47970;

        // get the ranking of each phoneme
        X = A;
        mem56 = blendRank[A];
        A = blendRank[Y];

        // compare the rank - lower rank value is stronger
        if (A == mem56) {
            // same rank, so use out blend lengths from each phoneme
            phase1 = outBlendLength[Y];
            phase2 = outBlendLength[X];
        }
        else if (A < mem56) {
            // first phoneme is stronger, so us it's blend lengths
            phase1 = inBlendLength[X];
            phase2 = outBlendLength[X];
        }
        else {
            // second phoneme is stronger, so use it's blend lengths
            // note the out/in are swapped
            phase1 = outBlendLength[Y];
            phase2 = inBlendLength[Y];
        }

        Y = mem44;
        A = mem49 + phonemeLengthOutput[mem44]; // A is mem49 + length
        mem49 = A; // mem49 now holds length + position
        A = A + phase2; //Maybe Problem because of carry flag

        //47776: ADC 42
        speedcounter = A;
        mem47 = 168;
        phase3 = mem49 - phase1; // what is mem49
        A = phase1 + phase2; // total transition?
        mem38 = A;

        X = A;
        X -= 2;
        if ((X & 128) == 0)
            do //while No. 2
            {
                //pos47810:

                // mem47 is used to index the tables:
                // 168  pitches[]
                // 169  frequency1
                // 170  frequency2
                // 171  frequency3
                // 172  amplitude1
                // 173  amplitude2
                // 174  amplitude3

                mem40 = mem38;

                if (mem47 == 168) // pitch
                {
                    // unlike the other values, the pitches[] interpolates from
                    // the middle of the current phoneme to the middle of the
                    // next phoneme

                    uint8_t mem36, mem37;
                    // half the width of the current phoneme
                    mem36 = phonemeLengthOutput[mem44] >> 1;
                    // half the width of the next phoneme
                    mem37 = phonemeLengthOutput[mem44 + 1] >> 1;
                    // sum the values
                    mem40 = mem36 + mem37; // length of both halves
                    mem37 += mem49; // center of next phoneme
                    mem36 = mem49 - mem36; // center index of current phoneme
                    A = Read(mem47, mem37); // value at center of next phoneme - end interpolation value
                    //A = mem[address];

                    Y = mem36; // start index of interpolation
                    mem53 = A - Read(mem47, mem36); // value to center of current phoneme
                }
                else {
                    // value to interpolate to
                    A = Read(mem47, speedcounter);
                    // position to start interpolation from
                    Y = phase3;
                    // value to interpolate from
                    mem53 = A - Read(mem47, phase3);
                }

                //Code47503(mem40);
                // ML : Code47503 is division with remainder, and mem50 gets the sign

                // calculate change per frame
                mem50 = (((int8_t)(mem53) < 0) ? 128 : 0);
                mem51 = abs((int8_t)mem53) % mem40;
                mem53 = (uint8_t)((int8_t)(mem53) / mem40);

                // interpolation range
                X = mem40; // number of frames to interpolate over
                Y = phase3; // starting frame

                // linearly interpolate values

                mem56 = 0;
                //47907: CLC
                //pos47908:
                while (1) //while No. 3
                {
                    A = Read(mem47, Y) + mem53; //carry alway cleared

                    mem48 = A;
                    Y++;
                    X--;
                    if (X == 0)
                        break;

                    mem56 += mem51;
                    if (mem56 >= mem40) //???
                    {
                        mem56 -= mem40; //carry? is set
                        //if ((mem56 & 128)==0)
                        if ((mem50 & 128) == 0) {
                            //47935: BIT 50
                            //47937: BMI 47943
                            if (mem48 != 0)
                                mem48++;
                        }
                        else
                            mem48--;
                    }
                    //pos47945:
                    Write(mem47, Y, mem48);
                } //while No. 3

                //pos47952:
                mem47++;
                //if (mem47 != 175) goto pos47810;
            } while (mem47 != 175); //while No. 2
        //pos47963:
        mem44++;
        X = mem44;
    } //while No. 1

    //goto pos47701;
    //pos47970:

    // add the length of this phoneme
    mem48 = mem49 + phonemeLengthOutput[mem44];

    // ASSIGN PITCH CONTOUR
    //
    // This subtracts the F1 frequency from the pitch to create a
    // pitch contour. Without this, the output would be at a single
    // pitch level (monotone).

    // don't adjust pitch if in sing mode
    if (!singmode) {
        // iterate through the buffer
        for (i = 0; i < 256; i++) {
            // subtract half the frequency of the formant 1.
            // this adds variety to the voice
            pitches[i] -= (frequency1[i] >> 1);
        }
    }

    phase1 = 0;
    phase2 = 0;
    phase3 = 0;
    mem49 = 0;
    speedcounter = 72; //sam standard speed

    // RESCALE AMPLITUDE
    //
    // Rescale volume from a linear scale to decibels.
    //

    //amplitude rescaling
    for (i = 255; i >= 0; i--) {
        amplitude1[i] = amplitudeRescale[amplitude1[i]];
        amplitude2[i] = amplitudeRescale[amplitude2[i]];
        amplitude3[i] = amplitudeRescale[amplitude3[i]];
    }

    Y = 0;
    A = pitches[0];
    mem44 = A;
    X = A;
    mem38 = A - (A >> 2); // 3/4*A ???

    if (debug) {
        PrintOutput(
            sampledConsonantFlag,
            frequency1,
            frequency2,
            frequency3,
            amplitude1,
            amplitude2,
            amplitude3,
            pitches);
    }

    // PROCESS THE FRAMES
    //
    // In traditional vocal synthesis, the glottal pulse drives filters, which
    // are attenuated to the frequencies of the formants.
    //
    // SAM generates these formants directly with sin and rectangular waves.
    // To simulate them being driven by the glottal pulse, the waveforms are
    // reset at the beginning of each glottal pulse.

    //finally the loop for sound output
    //pos48078:
    while (1) {
        // get the sampled information on the phoneme
        A = sampledConsonantFlag[Y];
        mem39 = A;

        // unvoiced sampled phoneme?
        A = A & 248;
        if (A != 0) {
            // render the sample for the phoneme
            RenderSample(&mem66);

            // skip ahead two in the phoneme buffer
            Y += 2;
            mem48 -= 2;
        }
        else {
            // simulate the glottal pulse and formants
            mem56 = multtable[sinus[phase1] | amplitude1[Y]];

            carry = 0;
            if ((mem56 + multtable[sinus[phase2] | amplitude2[Y]]) > 255)
                carry = 1;
            mem56 += multtable[sinus[phase2] | amplitude2[Y]];
            A = mem56 + multtable[rectangle[phase3] | amplitude3[Y]] + (carry ? 1 : 0);
            A = ((A + 136) & 255) >> 4; //there must be also a carry
            //mem[54296] = A;

            // output the accumulated value
            Output(0, A);
            speedcounter--;
            if (speedcounter != 0)
                goto pos48155;
            Y++; //go to next amplitude

            // decrement the frame count
            mem48--;
        }

        // if the frame count is zero, exit the loop
        if (mem48 == 0)
            return;
        speedcounter = speed;
    pos48155:

        // decrement the remaining length of the glottal pulse
        mem44--;

        // finished with a glottal pulse?
        if (mem44 == 0) {
        pos48159:
            // fetch the next glottal pulse length
            A = pitches[Y];
            mem44 = A;
            A = A - (A >> 2);
            mem38 = A;

            // reset the formant wave generators to keep them in
            // sync with the glottal pulse
            phase1 = 0;
            phase2 = 0;
            phase3 = 0;
            continue;
        }

        // decrement the count
        mem38--;

        // is the count non-zero and the sampled flag is zero?
        if ((mem38 != 0) || (mem39 == 0)) {
            // reset the phase of the formants to match the pulse
            phase1 += frequency1[Y];
            phase2 += frequency2[Y];
            phase3 += frequency3[Y];
            continue;
        }

        // voiced sampled phonemes interleave the sample with the
        // glottal pulse. The sample flag is non-zero, so render
        // the sample for the phoneme.
        RenderSample(&mem66);
        goto pos48159;
    } //while

#if 0
    // The following code is never reached. It's left over from when
    // the voiced sample code was part of this loop, instead of part
    // of RenderSample();

    //pos48315:
    int32_t tempA;
    phase1 = A ^ 255;
    Y = mem66;
    do {
        //pos48321:

        mem56 = 8;
        A = Read(mem47, Y);

        //pos48327:
        do {
            //48327: ASL A
            //48328: BCC 48337
            tempA = A;
            A = A << 1;
            if ((tempA & 128) != 0) {
                X = 26;
                // mem[54296] = X;
                bufferPos += 150;
                buffer[bufferPos / 50] = (X & 15) * 16;
            }
            else {
                //mem[54296] = 6;
                X = 6;
                bufferPos += 150;
                buffer[bufferPos / 50] = (X & 15) * 16;
            }

            for (X = wait2; X > 0; X--)
                ; //wait
            mem56--;
        } while (mem56 != 0);

        Y++;
        phase1++;

    } while (phase1 != 0);
    //    if (phase1 != 0) goto pos48321;
    A = 1;
    mem44 = 1;
    mem66 = Y;
    Y = mem49;
    return;
#endif
} // void Render

// Create a rising or falling inflection 30 frames prior to
// index X. A rising inflection is used for questions, and
// a falling inflection is used for statements.

void AddInflection(uint8_t mem48, uint8_t phase1)
{
    //pos48372:
    //    mem48 = 255;
    //pos48376:

    // store the location of the punctuation
    mem49 = X;
    A = X;
    int32_t Atemp = A;

    // backup 30 frames
    A = A - 30;
    // if index is before buffer, point to start of buffer
    if (Atemp <= 30)
        A = 0;
    X = A;

    // FIXME: Explain this fix better, it's not obvious
    // ML : A =, fixes a problem with invalid pitch with '.'
    while ((A = pitches[X]) == 127)
        X++;

pos48398:
    //48398: CLC
    //48399: ADC 48

    // add the inflection direction
    A += mem48;
    phase1 = A;

    // set the inflection
    pitches[X] = A;
pos48406:

    // increment the position
    X++;

    // exit if the punctuation has been reached
    if (X == mem49)
        return; //goto pos47615;
    if (pitches[X] == 255)
        goto pos48406;
    A = phase1;
    goto pos48398;
} // void AddInflection

/*
    SAM's voice can be altered by changing the frequencies of the
    mouth formant (F1) and the throat formant (F2). Only the voiced
    phonemes (5-29 and 48-53) are altered.
*/
void SetMouthThroat(uint8_t mouth, uint8_t throat)
{
    uint8_t initialFrequency;
    uint8_t newFrequency = 0;
    //uint8_t mouth; //mem38880
    //uint8_t throat; //mem38881

    // mouth formants (F1) 5..29
    const uint8_t mouthFormants5_29[30] = {
        0, 0, 0, 0, 0, 10,
        14, 19, 24, 27, 23, 21, 16, 20, 14, 18, 14, 18, 18,
        16, 13, 15, 11, 18, 14, 11, 9, 6, 6, 6
    };

    // throat formants (F2) 5..29
    const uint8_t throatFormants5_29[30] = {
        255, 255,
        255, 255, 255, 84, 73, 67, 63, 40, 44, 31, 37, 45, 73, 49,
        36, 30, 51, 37, 29, 69, 24, 50, 30, 24, 83, 46, 54, 86
    };

    // there must be no zeros in this 2 tables
    // formant 1 frequencies (mouth) 48..53
    const uint8_t mouthFormants48_53[6] = { 19, 27, 21, 27, 18, 13 };

    // formant 2 frequencies (throat) 48..53
    const uint8_t throatFormants48_53[6] = { 72, 39, 31, 43, 30, 34 };


    uint8_t pos = 5; //mem39216
    //pos38942:
    // recalculate formant frequencies 5..29 for the mouth (F1) and throat (F2)
    while (pos != 30) {
        // recalculate mouth frequency
        initialFrequency = mouthFormants5_29[pos];
        if (initialFrequency != 0)
            newFrequency = trans(mouth, initialFrequency);
        freq1data[pos] = newFrequency;

        // recalculate throat frequency
        initialFrequency = throatFormants5_29[pos];
        if (initialFrequency != 0)
            newFrequency = trans(throat, initialFrequency);
        freq2data[pos] = newFrequency;
        pos++;
    }

    //pos39059:
    // recalculate formant frequencies 48..53
    pos = 48;
    Y = 0;
    while (pos != 54) {
        // recalculate F1 (mouth formant)
        initialFrequency = mouthFormants48_53[Y];
        newFrequency = trans(mouth, initialFrequency);
        freq1data[pos] = newFrequency;

        // recalculate F2 (throat formant)
        initialFrequency = throatFormants48_53[Y];
        newFrequency = trans(throat, initialFrequency);
        freq2data[pos] = newFrequency;
        Y++;
        pos++;
    }
} // void SetMouthThroat

//return = (mem39212*mem39213) >> 1
uint8_t trans(uint8_t mem39212, uint8_t mem39213)
{
    //pos39008:
    uint8_t carry;
    int32_t temp;
    uint8_t mem39214, mem39215;
    A = 0;
    mem39215 = 0;
    mem39214 = 0;
    X = 8;
    do {
        carry = mem39212 & 1;
        mem39212 = mem39212 >> 1;
        if (carry != 0) {
            /*
            39018: LSR 39212
            39021: BCC 39033
            */
            carry = 0;
            A = mem39215;
            temp = (int32_t)A + (int32_t)mem39213;
            A = A + mem39213;
            if (temp > 255)
                carry = 1;
            mem39215 = A;
        }
        temp = mem39215 & 1;
        mem39215 = (mem39215 >> 1) | (carry ? 128 : 0);
        carry = temp;
        //39033: ROR 39215
        X--;
    } while (X != 0);
    temp = mem39214 & 128;
    mem39214 = (mem39214 << 1) | (carry ? 1 : 0);
    carry = temp;
    temp = mem39215 & 128;
    mem39215 = (mem39215 << 1) | (carry ? 1 : 0);
    carry = temp;

    return mem39215;
} // uint8_t trans

// END render.c






void WriteWav(int8_t* filename, int8_t* buffer, int32_t bufferlength)
{
#if (_MSC_VER)
    FILE * file = NULL;
    fopen_s(&file, filename, "wb");
#else
    FILE* file = fopen(filename, "wb");
#endif
    if (file == NULL)
        return;
    //RIFF header
    fwrite("RIFF", 4, 1, file);
    uint32_t filesize = bufferlength + 12 + 16 + 8 - 8;
    fwrite(&filesize, 4, 1, file);
    fwrite("WAVE", 4, 1, file);

    //format chunk
    fwrite("fmt ", 4, 1, file);
    uint32_t fmtlength = 16;
    fwrite(&fmtlength, 4, 1, file);
    uint16_t format = 1; //PCM
    fwrite(&format, 2, 1, file);
    uint16_t channels = 1;
    fwrite(&channels, 2, 1, file);
    uint32_t samplerate = 22050;
    fwrite(&samplerate, 4, 1, file);
    fwrite(&samplerate, 4, 1, file); // bytes/second
    uint16_t blockalign = 1;
    fwrite(&blockalign, 2, 1, file);
    uint16_t bitspersample = 8;
    fwrite(&bitspersample, 2, 1, file);

    //data chunk
    fwrite("data", 4, 1, file);
    fwrite(&bufferlength, 4, 1, file);
    fwrite(buffer, bufferlength, 1, file);

    fclose(file);
} // void WriteWav

void PrintUsage()
{
    printf("usage: sam [options] Word1 Word2 ....\n");
    printf("options\n");
    printf("    -phonetic         enters phonetic mode. (see below)\n");
    printf("    -pitch number        set pitch value (default=64)\n");
    printf("    -speed number        set speed value (default=72)\n");
    printf("    -throat number        set throat value (default=128)\n");
    printf("    -mouth number        set mouth value (default=128)\n");
    printf("    -wav filename        output to wav instead of libsdl\n");
    printf("    -sing            special treatment of pitch\n");
    printf("    -debug            print additional debug messages\n");
    printf("\n");

    printf("     VOWELS                            VOICED CONSONANTS    \n");
    printf("IY           f(ee)t                    R        red        \n");
    printf("IH           p(i)n                     L        allow        \n");
    printf("EH           beg                       W        away        \n");
    printf("AE           Sam                       W        whale        \n");
    printf("AA           pot                       Y        you        \n");
    printf("AH           b(u)dget                  M        Sam        \n");
    printf("AO           t(al)k                    N        man        \n");
    printf("OH           cone                      NX       so(ng)        \n");
    printf("UH           book                      B        bad        \n");
    printf("UX           l(oo)t                    D        dog        \n");
    printf("ER           bird                      G        again        \n");
    printf("AX           gall(o)n                  J        judge        \n");
    printf("IX           dig(i)t                   Z        zoo        \n");
    printf("                       ZH       plea(s)ure    \n");
    printf("   DIPHTHONGS                          V        seven        \n");
    printf("EY           m(a)de                    DH       (th)en        \n");
    printf("AY           h(igh)                        \n");
    printf("OY           boy                        \n");
    printf("AW           h(ow)                     UNVOICED CONSONANTS    \n");
    printf("OW           slow                      S         Sam        \n");
    printf("UW           crew                      Sh        fish        \n");
    printf("                                       F         fish        \n");
    printf("                                       TH        thin        \n");
    printf(" SPECIAL PHONEMES                      P         poke        \n");
    printf("UL           sett(le) (=AXL)           T         talk        \n");
    printf("UM           astron(omy) (=AXM)        K         cake        \n");
    printf("UN           functi(on) (=AXN)         CH        speech        \n");
    printf("Q            kitt-en (glottal stop)    /H        a(h)ead    \n");
} // void PrintUsage




#ifdef USESDL

int32_t pos = 0;
void MixAudio(void* unused, Uint8* stream, int32_t len)
{
    int32_t bufferpos = GetBufferLength();
    int8_t* buffer = GetBuffer();
    int32_t i;
    if (pos >= bufferpos)
        return;
    if ((bufferpos - pos) < len)
        len = (bufferpos - pos);
    for (i = 0; i < len; i++) {
        stream[i] = buffer[pos];
        pos++;
    }
} // void MixAudio

void OutputSound()
{
    int32_t bufferpos = GetBufferLength();
    bufferpos /= 50;
    SDL_AudioSpec fmt;

    fmt.freq = 22050;
    fmt.format = AUDIO_U8;
    fmt.channels = 1;
    fmt.samples = 2048;
    fmt.callback = MixAudio;
    fmt.userdata = NULL;

    /* Open the audio device and start playing sound! */
    if (SDL_OpenAudio(&fmt, NULL) < 0) {
        printf("Unable to open audio: %s\n", SDL_GetError());
        exit(1);
    }
    SDL_PauseAudio(0);
    //SDL_Delay((bufferPos)/7);

    while (pos < bufferpos) {
        SDL_Delay(100);
    }

    SDL_CloseAudio();
} // void OutputSound
#else
void OutputSound()
{
} // void OutputSound
#endif

int32_t main(int32_t argc, int8_t** argv)
{
    int32_t i;
    int32_t phonetic = 0;

    int8_t* wavfilename = NULL;
    int8_t input[256];

    for (i = 0; i < 256; i++)
        input[i] = 0;

    if (argc <= 1) {
        PrintUsage();
        return 1;
    }

    i = 1;
    while (i < argc) {
        if (argv[i][0] != '-') {
            strncat_s(input, sizeof(input), argv[i], 256);
            strncat_s(input, sizeof(input), " ", 256);
        }
        else {
            if (strcmp(&argv[i][1], "wav") == 0) {
                wavfilename = argv[i + 1];
                i++;
            }
            else if (strcmp(&argv[i][1], "sing") == 0) {
                EnableSingmode();
            }
            else if (strcmp(&argv[i][1], "phonetic") == 0) {
                phonetic = 1;
            }
            else if (strcmp(&argv[i][1], "debug") == 0) {
                debug = 1;
            }
            else if (strcmp(&argv[i][1], "pitch") == 0) {
                SetPitch(atoi(argv[i + 1]));
                i++;
            }
            else if (strcmp(&argv[i][1], "speed") == 0) {
                SetSpeed(atoi(argv[i + 1]));
                i++;
            }
            else if (strcmp(&argv[i][1], "mouth") == 0) {
                SetMouth(atoi(argv[i + 1]));
                i++;
            }
            else if (strcmp(&argv[i][1], "throat") == 0) {
                SetThroat(atoi(argv[i + 1]));
                i++;
            }
            else {
                PrintUsage();
                return 1;
            }
        }

        i++;
    } //while

    for (i = 0; input[i] != 0; i++)
        input[i] = toupper((int32_t)input[i]);

    if (debug) {
        if (phonetic)
            printf("phonetic input: %s\n", input);
        else
            printf("text input: %s\n", input);
    }

    if (!phonetic) {
        strncat_s(input, sizeof(input), "[", 256);
        if (!TextToPhonemes(input, 256))
            return 1;
        if (debug)
            printf("phonetic input: %s\n", input);
    }
    else
        strncat_s(input, sizeof(input), "\x9b", 256);

#ifdef USESDL
    if (SDL_Init(SDL_INIT_AUDIO) < 0) {
        printf("Unable to init SDL: %s\n", SDL_GetError());
        exit(1);
    }
    atexit(SDL_Quit);
#endif

    SetInput(input);
    if (!SAMMain()) {
        PrintUsage();
        return 1;
    }

    if (wavfilename != NULL)
        WriteWav(wavfilename, GetBuffer(), GetBufferLength() / 50);
    else
        OutputSound();

    return 0;
} // int32_t main






// BEGIN debug.c

void PrintPhonemes(uint8_t* phonemeindex, uint8_t* phonemeLength, uint8_t* stress)
{
    int32_t i = 0;
    printf("===========================================\n");

    printf("Internal Phoneme presentation:\n\n");
    printf(" idx    phoneme  length  stress\n");
    printf("------------------------------\n");

    while ((phonemeindex[i] != 255) && (i < 255)) {
        if (phonemeindex[i] < 81) {
            printf(" %3i      %c%c      %3i       %i\n",
                phonemeindex[i],
                signInputTable1[phonemeindex[i]],
                signInputTable2[phonemeindex[i]],
                phonemeLength[i],
                stress[i]);
        }
        else {
            printf(" %3i      ??      %3i       %i\n", phonemeindex[i], phonemeLength[i], stress[i]);
        }
        i++;
    }
    printf("===========================================\n");
    printf("\n");
} // void PrintPhonemes

void PrintOutput(
    uint8_t* flag,
    uint8_t* f1,
    uint8_t* f2,
    uint8_t* f3,
    uint8_t* a1,
    uint8_t* a2,
    uint8_t* a3,
    uint8_t* p)
{
    printf("===========================================\n");
    printf("Final data for speech output:\n\n");
    int32_t i = 0;
    printf(" flags ampl1 freq1 ampl2 freq2 ampl3 freq3 pitch\n");
    printf("------------------------------------------------\n");
    while (i < 255) {
        printf("%5i %5i %5i %5i %5i %5i %5i %5i\n", flag[i], a1[i], f1[i], a2[i], f2[i], a3[i], f3[i], p[i]);
        i++;
    }
    printf("===========================================\n");
} // void PrintOutput

void PrintRule(int32_t offset)
{
    int32_t i = 1;
    uint8_t A = 0;
    printf("Applying rule: ");
    do {
        A = GetRuleByte(offset, i);
        if ((A & 127) == '=')
            printf(" -> ");
        else
            printf("%c", A & 127);
        i++;
    } while ((A & 128) == 0);
    printf("\n");
} // void PrintRule

// END debug.c
Reply




Users browsing this thread: 1 Guest(s)