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


Messages In This Thread
RE: SAM native QB64PE speech synthesizer, port from C (v0.2.1), fixed design-time errors - by madscijr - 04-07-2025, 06:16 PM



Users browsing this thread: 1 Guest(s)