#include "stm32_sam.h" /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////// // // All // //////////////////////////////////////////////////////////////////////////////////////////// char input[256 + 1] = {0}; //tab39445 //standard sam sound unsigned char wait1 = 7; unsigned char wait2 = 6; unsigned char A, X, Y; unsigned char mem44; unsigned char mem47; unsigned char mem49; unsigned char mem39; unsigned char mem50; unsigned char mem51; unsigned char mem53; unsigned char mem56; unsigned char mem59 = 0; unsigned char phonemeIndexOutput[60]; //tab47296 unsigned char stressOutput[60]; //tab47365 unsigned char phonemeLengthOutput[60]; //tab47416 // contains the soundbuffer position int bufferpos; //////////////////////////////////////////////////////////////////////////////////////////// // // Sam Tabs // //////////////////////////////////////////////////////////////////////////////////////////// //tab40672 const unsigned char stressInputTable[] = {'*', '1', '2', '3', '4', '5', '6', '7', '8'}; //tab40682 const unsigned char 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 unsigned char 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 unsigned char 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 unsigned char 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 unsigned char 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 unsigned char 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 | */ //////////////////////////////////////////////////////////////////////////////////////////// // // RenderTabs // //////////////////////////////////////////////////////////////////////////////////////////// const unsigned char tab48426[5] = {0x18, 0x1A, 0x17, 0x17, 0x17}; const unsigned char tab47492[] = {0, 0, 0xE0, 0xE6, 0xEC, 0xF3, 0xF9, 0, 6, 0xC, 6}; const unsigned char 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 unsigned char 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 unsigned char 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 unsigned char 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 unsigned char 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 unsigned char 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 unsigned char 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 unsigned char 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}; //////////////////////////////////////////////////////////////////////////////////////////// // // Reciter // //////////////////////////////////////////////////////////////////////////////////////////// unsigned char inputtemp[256]; // secure copy of input tab36096 //////////////////////////////////////////////////////////////////////////////////////////// // // Render // //////////////////////////////////////////////////////////////////////////////////////////// //timetable for more accurate c64 simulation int 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}}; unsigned oldtimetableindex; const unsigned char 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 unsigned char 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 unsigned char 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 signed char sinus[256] = { 0, 3, 6, 9, 12, 16, 19, 22, 25, 28, 31, 34, 37, 40, 43, 46, 49, 51, 54, 57, 60, 63, 65, 68, 71, 73, 76, 78, 81, 83, 85, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 107, 109, 111, 112, 113, 115, 116, 117, 118, 120, 121, 122, 122, 123, 124, 125, 125, 126, 126, 126, 127, 127, 127, 127, 127, 127, 127, 126, 126, 126, 125, 125, 124, 123, 122, 122, 121, 120, 118, 117, 116, 115, 113, 112, 111, 109, 107, 106, 104, 102, 100, 98, 96, 94, 92, 90, 88, 85, 83, 81, 78, 76, 73, 71, 68, 65, 63, 60, 57, 54, 51, 49, 46, 43, 40, 37, 34, 31, 28, 25, 22, 19, 16, 12, 9, 6, 3, 0, -3, -6, -9, -12, -16, -19, -22, -25, -28, -31, -34, -37, -40, -43, -46, -49, -51, -54, -57, -60, -63, -65, -68, -71, -73, -76, -78, -81, -83, -85, -88, -90, -92, -94, -96, -98, -100, -102, -104, -106, -107, -109, -111, -112, -113, -115, -116, -117, -118, -120, -121, -122, -122, -123, -124, -125, -125, -126, -126, -126, -127, -127, -127, -127, -127, -127, -127, -126, -126, -126, -125, -125, -124, -123, -122, -122, -121, -120, -118, -117, -116, -115, -113, -112, -111, -109, -107, -106, -104, -102, -100, -98, -96, -94, -92, -90, -88, -85, -83, -81, -78, -76, -73, -71, -68, -65, -63, -60, -57, -54, -51, -49, -46, -43, -40, -37, -34, -31, -28, -25, -22, -19, -16, -12, -9, -6, -3}; //tab42496 const unsigned char 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}; //random data ? const unsigned char 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}; //////////////////////////////////////////////////////////////////////////////////////////// // // Render // //////////////////////////////////////////////////////////////////////////////////////////// unsigned char pitches[256]; // tab43008 unsigned char frequency1[256]; unsigned char frequency2[256]; unsigned char frequency3[256]; unsigned char amplitude1[256]; unsigned char amplitude2[256]; unsigned char amplitude3[256]; unsigned char sampledConsonantFlag[256]; // tab44800 //////////////////////////////////////////////////////////////////////////////////////////// // // Sam // //////////////////////////////////////////////////////////////////////////////////////////// unsigned char stress[256]; //numbers from 0 to 8 unsigned char phonemeLength[256]; //tab40160 unsigned char phonemeindex[256]; //////////////////////////////////////////////////////////////////////////////////////////// // // ReciterTabs // //////////////////////////////////////////////////////////////////////////////////////////// //some flags const unsigned char tab36376[] = { 0, 0, 0, 0, 0, 0, 0, 0, // 0-7 0, 0, 0, 0, 0, 0, 0, 0, // 8-15 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 130, // ' ', '!' 0, 0, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 192, 168, 176, 172, 192, 160, 184, // '@', 'A' 160, 192, 188, 160, 172, 168, 172, 192, 160, 160, 172, 180, 164, 192, 168, 168, 176, 192, 188, 0, 0, 0, 2, 0, // 'X', 'Y', 'Z', '[', 32, 32, 155, 32, 192, 185, 32, 205, 163, 76, 138, 142}; const unsigned char rules[] = { ']', 'A' | 0x80, ' ', '(', 'A', '.', ')', '=', 'E', 'H', '4', 'Y', '.', ' ' | 0x80, '(', 'A', ')', ' ', '=', 'A', 'H' | 0x80, ' ', '(', 'A', 'R', 'E', ')', ' ', '=', 'A', 'A', 'R' | 0x80, ' ', '(', 'A', 'R', ')', 'O', '=', 'A', 'X', 'R' | 0x80, '(', 'A', 'R', ')', '#', '=', 'E', 'H', '4', 'R' | 0x80, ' ', '^', '(', 'A', 'S', ')', '#', '=', 'E', 'Y', '4', 'S' | 0x80, '(', 'A', ')', 'W', 'A', '=', 'A', 'X' | 0x80, '(', 'A', 'W', ')', '=', 'A', 'O', '5' | 0x80, ' ', ':', '(', 'A', 'N', 'Y', ')', '=', 'E', 'H', '4', 'N', 'I', 'Y' | 0x80, '(', 'A', ')', '^', '+', '#', '=', 'E', 'Y', '5' | 0x80, '#', ':', '(', 'A', 'L', 'L', 'Y', ')', '=', 'U', 'L', 'I', 'Y' | 0x80, ' ', '(', 'A', 'L', ')', '#', '=', 'U', 'L' | 0x80, '(', 'A', 'G', 'A', 'I', 'N', ')', '=', 'A', 'X', 'G', 'E', 'H', '4', 'N' | 0x80, '#', ':', '(', 'A', 'G', ')', 'E', '=', 'I', 'H', 'J' | 0x80, '(', 'A', ')', '^', '%', '=', 'E', 'Y' | 0x80, '(', 'A', ')', '^', '+', ':', '#', '=', 'A', 'E' | 0x80, ' ', ':', '(', 'A', ')', '^', '+', ' ', '=', 'E', 'Y', '4' | 0x80, ' ', '(', 'A', 'R', 'R', ')', '=', 'A', 'X', 'R' | 0x80, '(', 'A', 'R', 'R', ')', '=', 'A', 'E', '4', 'R' | 0x80, ' ', '^', '(', 'A', 'R', ')', ' ', '=', 'A', 'A', '5', 'R' | 0x80, '(', 'A', 'R', ')', '=', 'A', 'A', '5', 'R' | 0x80, '(', 'A', 'I', 'R', ')', '=', 'E', 'H', '4', 'R' | 0x80, '(', 'A', 'I', ')', '=', 'E', 'Y', '4' | 0x80, '(', 'A', 'Y', ')', '=', 'E', 'Y', '5' | 0x80, '(', 'A', 'U', ')', '=', 'A', 'O', '4' | 0x80, '#', ':', '(', 'A', 'L', ')', ' ', '=', 'U', 'L' | 0x80, '#', ':', '(', 'A', 'L', 'S', ')', ' ', '=', 'U', 'L', 'Z' | 0x80, '(', 'A', 'L', 'K', ')', '=', 'A', 'O', '4', 'K' | 0x80, '(', 'A', 'L', ')', '^', '=', 'A', 'O', 'L' | 0x80, ' ', ':', '(', 'A', 'B', 'L', 'E', ')', '=', 'E', 'Y', '4', 'B', 'U', 'L' | 0x80, '(', 'A', 'B', 'L', 'E', ')', '=', 'A', 'X', 'B', 'U', 'L' | 0x80, '(', 'A', ')', 'V', 'O', '=', 'E', 'Y', '4' | 0x80, '(', 'A', 'N', 'G', ')', '+', '=', 'E', 'Y', '4', 'N', 'J' | 0x80, '(', 'A', 'T', 'A', 'R', 'I', ')', '=', 'A', 'H', 'T', 'A', 'A', '4', 'R', 'I', 'Y' | 0x80, '(', 'A', ')', 'T', 'O', 'M', '=', 'A', 'E' | 0x80, '(', 'A', ')', 'T', 'T', 'I', '=', 'A', 'E' | 0x80, ' ', '(', 'A', 'T', ')', ' ', '=', 'A', 'E', 'T' | 0x80, ' ', '(', 'A', ')', 'T', '=', 'A', 'H' | 0x80, '(', 'A', ')', '=', 'A', 'E' | 0x80, ']', 'B' | 0x80, ' ', '(', 'B', ')', ' ', '=', 'B', 'I', 'Y', '4' | 0x80, ' ', '(', 'B', 'E', ')', '^', '#', '=', 'B', 'I', 'H' | 0x80, '(', 'B', 'E', 'I', 'N', 'G', ')', '=', 'B', 'I', 'Y', '4', 'I', 'H', 'N', 'X' | 0x80, ' ', '(', 'B', 'O', 'T', 'H', ')', ' ', '=', 'B', 'O', 'W', '4', 'T', 'H' | 0x80, ' ', '(', 'B', 'U', 'S', ')', '#', '=', 'B', 'I', 'H', '4', 'Z' | 0x80, '(', 'B', 'R', 'E', 'A', 'K', ')', '=', 'B', 'R', 'E', 'Y', '5', 'K' | 0x80, '(', 'B', 'U', 'I', 'L', ')', '=', 'B', 'I', 'H', '4', 'L' | 0x80, '(', 'B', ')', '=', 'B' | 0x80, ']', 'C' | 0x80, ' ', '(', 'C', ')', ' ', '=', 'S', 'I', 'Y', '4' | 0x80, ' ', '(', 'C', 'H', ')', '^', '=', 'K' | 0x80, '^', 'E', '(', 'C', 'H', ')', '=', 'K' | 0x80, '(', 'C', 'H', 'A', ')', 'R', '#', '=', 'K', 'E', 'H', '5' | 0x80, '(', 'C', 'H', ')', '=', 'C', 'H' | 0x80, ' ', 'S', '(', 'C', 'I', ')', '#', '=', 'S', 'A', 'Y', '4' | 0x80, '(', 'C', 'I', ')', 'A', '=', 'S', 'H' | 0x80, '(', 'C', 'I', ')', 'O', '=', 'S', 'H' | 0x80, '(', 'C', 'I', ')', 'E', 'N', '=', 'S', 'H' | 0x80, '(', 'C', 'I', 'T', 'Y', ')', '=', 'S', 'I', 'H', 'T', 'I', 'Y' | 0x80, '(', 'C', ')', '+', '=', 'S' | 0x80, '(', 'C', 'K', ')', '=', 'K' | 0x80, '(', 'C', 'O', 'M', 'M', 'O', 'D', 'O', 'R', 'E', ')', '=', 'K', 'A', 'A', '4', 'M', 'A', 'H', 'D', 'O', 'H', 'R' | 0x80, '(', 'C', 'O', 'M', ')', '=', 'K', 'A', 'H', 'M' | 0x80, '(', 'C', 'U', 'I', 'T', ')', '=', 'K', 'I', 'H', 'T' | 0x80, '(', 'C', 'R', 'E', 'A', ')', '=', 'K', 'R', 'I', 'Y', 'E', 'Y' | 0x80, '(', 'C', ')', '=', 'K' | 0x80, ']', 'D' | 0x80, ' ', '(', 'D', ')', ' ', '=', 'D', 'I', 'Y', '4' | 0x80, ' ', '(', 'D', 'R', '.', ')', ' ', '=', 'D', 'A', 'A', '4', 'K', 'T', 'E', 'R' | 0x80, '#', ':', '(', 'D', 'E', 'D', ')', ' ', '=', 'D', 'I', 'H', 'D' | 0x80, '.', 'E', '(', 'D', ')', ' ', '=', 'D' | 0x80, '#', ':', '^', 'E', '(', 'D', ')', ' ', '=', 'T' | 0x80, ' ', '(', 'D', 'E', ')', '^', '#', '=', 'D', 'I', 'H' | 0x80, ' ', '(', 'D', 'O', ')', ' ', '=', 'D', 'U', 'W' | 0x80, ' ', '(', 'D', 'O', 'E', 'S', ')', '=', 'D', 'A', 'H', 'Z' | 0x80, '(', 'D', 'O', 'N', 'E', ')', ' ', '=', 'D', 'A', 'H', '5', 'N' | 0x80, '(', 'D', 'O', 'I', 'N', 'G', ')', '=', 'D', 'U', 'W', '4', 'I', 'H', 'N', 'X' | 0x80, ' ', '(', 'D', 'O', 'W', ')', '=', 'D', 'A', 'W' | 0x80, '#', '(', 'D', 'U', ')', 'A', '=', 'J', 'U', 'W' | 0x80, '#', '(', 'D', 'U', ')', '^', '#', '=', 'J', 'A', 'X' | 0x80, '(', 'D', ')', '=', 'D' | 0x80, ']', 'E' | 0x80, ' ', '(', 'E', ')', ' ', '=', 'I', 'Y', 'I', 'Y', '4' | 0x80, '#', ':', '(', 'E', ')', ' ', '=' | 0x80, '\'', ':', '^', '(', 'E', ')', ' ', '=' | 0x80, ' ', ':', '(', 'E', ')', ' ', '=', 'I', 'Y' | 0x80, '#', '(', 'E', 'D', ')', ' ', '=', 'D' | 0x80, '#', ':', '(', 'E', ')', 'D', ' ', '=' | 0x80, '(', 'E', 'V', ')', 'E', 'R', '=', 'E', 'H', '4', 'V' | 0x80, '(', 'E', ')', '^', '%', '=', 'I', 'Y', '4' | 0x80, '(', 'E', 'R', 'I', ')', '#', '=', 'I', 'Y', '4', 'R', 'I', 'Y' | 0x80, '(', 'E', 'R', 'I', ')', '=', 'E', 'H', '4', 'R', 'I', 'H' | 0x80, '#', ':', '(', 'E', 'R', ')', '#', '=', 'E', 'R' | 0x80, '(', 'E', 'R', 'R', 'O', 'R', ')', '=', 'E', 'H', '4', 'R', 'O', 'H', 'R' | 0x80, '(', 'E', 'R', 'A', 'S', 'E', ')', '=', 'I', 'H', 'R', 'E', 'Y', '5', 'S' | 0x80, '(', 'E', 'R', ')', '#', '=', 'E', 'H', 'R' | 0x80, '(', 'E', 'R', ')', '=', 'E', 'R' | 0x80, ' ', '(', 'E', 'V', 'E', 'N', ')', '=', 'I', 'Y', 'V', 'E', 'H', 'N' | 0x80, '#', ':', '(', 'E', ')', 'W', '=' | 0x80, '@', '(', 'E', 'W', ')', '=', 'U', 'W' | 0x80, '(', 'E', 'W', ')', '=', 'Y', 'U', 'W' | 0x80, '(', 'E', ')', 'O', '=', 'I', 'Y' | 0x80, '#', ':', '&', '(', 'E', 'S', ')', ' ', '=', 'I', 'H', 'Z' | 0x80, '#', ':', '(', 'E', ')', 'S', ' ', '=' | 0x80, '#', ':', '(', 'E', 'L', 'Y', ')', ' ', '=', 'L', 'I', 'Y' | 0x80, '#', ':', '(', 'E', 'M', 'E', 'N', 'T', ')', '=', 'M', 'E', 'H', 'N', 'T' | 0x80, '(', 'E', 'F', 'U', 'L', ')', '=', 'F', 'U', 'H', 'L' | 0x80, '(', 'E', 'E', ')', '=', 'I', 'Y', '4' | 0x80, '(', 'E', 'A', 'R', 'N', ')', '=', 'E', 'R', '5', 'N' | 0x80, ' ', '(', 'E', 'A', 'R', ')', '^', '=', 'E', 'R', '5' | 0x80, '(', 'E', 'A', 'D', ')', '=', 'E', 'H', 'D' | 0x80, '#', ':', '(', 'E', 'A', ')', ' ', '=', 'I', 'Y', 'A', 'X' | 0x80, '(', 'E', 'A', ')', 'S', 'U', '=', 'E', 'H', '5' | 0x80, '(', 'E', 'A', ')', '=', 'I', 'Y', '5' | 0x80, '(', 'E', 'I', 'G', 'H', ')', '=', 'E', 'Y', '4' | 0x80, '(', 'E', 'I', ')', '=', 'I', 'Y', '4' | 0x80, ' ', '(', 'E', 'Y', 'E', ')', '=', 'A', 'Y', '4' | 0x80, '(', 'E', 'Y', ')', '=', 'I', 'Y' | 0x80, '(', 'E', 'U', ')', '=', 'Y', 'U', 'W', '5' | 0x80, '(', 'E', 'Q', 'U', 'A', 'L', ')', '=', 'I', 'Y', '4', 'K', 'W', 'U', 'L' | 0x80, '(', 'E', ')', '=', 'E', 'H' | 0x80, ']', 'F' | 0x80, ' ', '(', 'F', ')', ' ', '=', 'E', 'H', '4', 'F' | 0x80, '(', 'F', 'U', 'L', ')', '=', 'F', 'U', 'H', 'L' | 0x80, '(', 'F', 'R', 'I', 'E', 'N', 'D', ')', '=', 'F', 'R', 'E', 'H', '5', 'N', 'D' | 0x80, '(', 'F', 'A', 'T', 'H', 'E', 'R', ')', '=', 'F', 'A', 'A', '4', 'D', 'H', 'E', 'R' | 0x80, '(', 'F', ')', 'F', '=' | 0x80, '(', 'F', ')', '=', 'F' | 0x80, ']', 'G' | 0x80, ' ', '(', 'G', ')', ' ', '=', 'J', 'I', 'Y', '4' | 0x80, '(', 'G', 'I', 'V', ')', '=', 'G', 'I', 'H', '5', 'V' | 0x80, ' ', '(', 'G', ')', 'I', '^', '=', 'G' | 0x80, '(', 'G', 'E', ')', 'T', '=', 'G', 'E', 'H', '5' | 0x80, 'S', 'U', '(', 'G', 'G', 'E', 'S', ')', '=', 'G', 'J', 'E', 'H', '4', 'S' | 0x80, '(', 'G', 'G', ')', '=', 'G' | 0x80, ' ', 'B', '#', '(', 'G', ')', '=', 'G' | 0x80, '(', 'G', ')', '+', '=', 'J' | 0x80, '(', 'G', 'R', 'E', 'A', 'T', ')', '=', 'G', 'R', 'E', 'Y', '4', 'T' | 0x80, '(', 'G', 'O', 'N', ')', 'E', '=', 'G', 'A', 'O', '5', 'N' | 0x80, '#', '(', 'G', 'H', ')', '=' | 0x80, ' ', '(', 'G', 'N', ')', '=', 'N' | 0x80, '(', 'G', ')', '=', 'G' | 0x80, ']', 'H' | 0x80, ' ', '(', 'H', ')', ' ', '=', 'E', 'Y', '4', 'C', 'H' | 0x80, ' ', '(', 'H', 'A', 'V', ')', '=', '/', 'H', 'A', 'E', '6', 'V' | 0x80, ' ', '(', 'H', 'E', 'R', 'E', ')', '=', '/', 'H', 'I', 'Y', 'R' | 0x80, ' ', '(', 'H', 'O', 'U', 'R', ')', '=', 'A', 'W', '5', 'E', 'R' | 0x80, '(', 'H', 'O', 'W', ')', '=', '/', 'H', 'A', 'W' | 0x80, '(', 'H', ')', '#', '=', '/', 'H' | 0x80, '(', 'H', ')', '=' | 0x80, ']', 'I' | 0x80, ' ', '(', 'I', 'N', ')', '=', 'I', 'H', 'N' | 0x80, ' ', '(', 'I', ')', ' ', '=', 'A', 'Y', '4' | 0x80, '(', 'I', ')', ' ', '=', 'A', 'Y' | 0x80, '(', 'I', 'N', ')', 'D', '=', 'A', 'Y', '5', 'N' | 0x80, 'S', 'E', 'M', '(', 'I', ')', '=', 'I', 'Y' | 0x80, ' ', 'A', 'N', 'T', '(', 'I', ')', '=', 'A', 'Y' | 0x80, '(', 'I', 'E', 'R', ')', '=', 'I', 'Y', 'E', 'R' | 0x80, '#', ':', 'R', '(', 'I', 'E', 'D', ')', ' ', '=', 'I', 'Y', 'D' | 0x80, '(', 'I', 'E', 'D', ')', ' ', '=', 'A', 'Y', '5', 'D' | 0x80, '(', 'I', 'E', 'N', ')', '=', 'I', 'Y', 'E', 'H', 'N' | 0x80, '(', 'I', 'E', ')', 'T', '=', 'A', 'Y', '4', 'E', 'H' | 0x80, '(', 'I', '\'', ')', '=', 'A', 'Y', '5' | 0x80, ' ', ':', '(', 'I', ')', '^', '%', '=', 'A', 'Y', '5' | 0x80, ' ', ':', '(', 'I', 'E', ')', ' ', '=', 'A', 'Y', '4' | 0x80, '(', 'I', ')', '%', '=', 'I', 'Y' | 0x80, '(', 'I', 'E', ')', '=', 'I', 'Y', '4' | 0x80, ' ', '(', 'I', 'D', 'E', 'A', ')', '=', 'A', 'Y', 'D', 'I', 'Y', '5', 'A', 'H' | 0x80, '(', 'I', ')', '^', '+', ':', '#', '=', 'I', 'H' | 0x80, '(', 'I', 'R', ')', '#', '=', 'A', 'Y', 'R' | 0x80, '(', 'I', 'Z', ')', '%', '=', 'A', 'Y', 'Z' | 0x80, '(', 'I', 'S', ')', '%', '=', 'A', 'Y', 'Z' | 0x80, 'I', '^', '(', 'I', ')', '^', '#', '=', 'I', 'H' | 0x80, '+', '^', '(', 'I', ')', '^', '+', '=', 'A', 'Y' | 0x80, '#', ':', '^', '(', 'I', ')', '^', '+', '=', 'I', 'H' | 0x80, '(', 'I', ')', '^', '+', '=', 'A', 'Y' | 0x80, '(', 'I', 'R', ')', '=', 'E', 'R' | 0x80, '(', 'I', 'G', 'H', ')', '=', 'A', 'Y', '4' | 0x80, '(', 'I', 'L', 'D', ')', '=', 'A', 'Y', '5', 'L', 'D' | 0x80, ' ', '(', 'I', 'G', 'N', ')', '=', 'I', 'H', 'G', 'N' | 0x80, '(', 'I', 'G', 'N', ')', ' ', '=', 'A', 'Y', '4', 'N' | 0x80, '(', 'I', 'G', 'N', ')', '^', '=', 'A', 'Y', '4', 'N' | 0x80, '(', 'I', 'G', 'N', ')', '%', '=', 'A', 'Y', '4', 'N' | 0x80, '(', 'I', 'C', 'R', 'O', ')', '=', 'A', 'Y', '4', 'K', 'R', 'O', 'H' | 0x80, '(', 'I', 'Q', 'U', 'E', ')', '=', 'I', 'Y', '4', 'K' | 0x80, '(', 'I', ')', '=', 'I', 'H' | 0x80, ']', 'J' | 0x80, ' ', '(', 'J', ')', ' ', '=', 'J', 'E', 'Y', '4' | 0x80, '(', 'J', ')', '=', 'J' | 0x80, ']', 'K' | 0x80, ' ', '(', 'K', ')', ' ', '=', 'K', 'E', 'Y', '4' | 0x80, ' ', '(', 'K', ')', 'N', '=' | 0x80, '(', 'K', ')', '=', 'K' | 0x80, ']', 'L' | 0x80, ' ', '(', 'L', ')', ' ', '=', 'E', 'H', '4', 'L' | 0x80, '(', 'L', 'O', ')', 'C', '#', '=', 'L', 'O', 'W' | 0x80, 'L', '(', 'L', ')', '=' | 0x80, '#', ':', '^', '(', 'L', ')', '%', '=', 'U', 'L' | 0x80, '(', 'L', 'E', 'A', 'D', ')', '=', 'L', 'I', 'Y', 'D' | 0x80, ' ', '(', 'L', 'A', 'U', 'G', 'H', ')', '=', 'L', 'A', 'E', '4', 'F' | 0x80, '(', 'L', ')', '=', 'L' | 0x80, ']', 'M' | 0x80, ' ', '(', 'M', ')', ' ', '=', 'E', 'H', '4', 'M' | 0x80, ' ', '(', 'M', 'R', '.', ')', ' ', '=', 'M', 'I', 'H', '4', 'S', 'T', 'E', 'R' | 0x80, ' ', '(', 'M', 'S', '.', ')', '=', 'M', 'I', 'H', '5', 'Z' | 0x80, ' ', '(', 'M', 'R', 'S', '.', ')', ' ', '=', 'M', 'I', 'H', '4', 'S', 'I', 'X', 'Z' | 0x80, '(', 'M', 'O', 'V', ')', '=', 'M', 'U', 'W', '4', 'V' | 0x80, '(', 'M', 'A', 'C', 'H', 'I', 'N', ')', '=', 'M', 'A', 'H', 'S', 'H', 'I', 'Y', '5', 'N' | 0x80, 'M', '(', 'M', ')', '=' | 0x80, '(', 'M', ')', '=', 'M' | 0x80, ']', 'N' | 0x80, ' ', '(', 'N', ')', ' ', '=', 'E', 'H', '4', 'N' | 0x80, 'E', '(', 'N', 'G', ')', '+', '=', 'N', 'J' | 0x80, '(', 'N', 'G', ')', 'R', '=', 'N', 'X', 'G' | 0x80, '(', 'N', 'G', ')', '#', '=', 'N', 'X', 'G' | 0x80, '(', 'N', 'G', 'L', ')', '%', '=', 'N', 'X', 'G', 'U', 'L' | 0x80, '(', 'N', 'G', ')', '=', 'N', 'X' | 0x80, '(', 'N', 'K', ')', '=', 'N', 'X', 'K' | 0x80, ' ', '(', 'N', 'O', 'W', ')', ' ', '=', 'N', 'A', 'W', '4' | 0x80, 'N', '(', 'N', ')', '=' | 0x80, '(', 'N', 'O', 'N', ')', 'E', '=', 'N', 'A', 'H', '4', 'N' | 0x80, '(', 'N', ')', '=', 'N' | 0x80, ']', 'O' | 0x80, ' ', '(', 'O', ')', ' ', '=', 'O', 'H', '4', 'W' | 0x80, '(', 'O', 'F', ')', ' ', '=', 'A', 'H', 'V' | 0x80, ' ', '(', 'O', 'H', ')', ' ', '=', 'O', 'W', '5' | 0x80, '(', 'O', 'R', 'O', 'U', 'G', 'H', ')', '=', 'E', 'R', '4', 'O', 'W' | 0x80, '#', ':', '(', 'O', 'R', ')', ' ', '=', 'E', 'R' | 0x80, '#', ':', '(', 'O', 'R', 'S', ')', ' ', '=', 'E', 'R', 'Z' | 0x80, '(', 'O', 'R', ')', '=', 'A', 'O', 'R' | 0x80, ' ', '(', 'O', 'N', 'E', ')', '=', 'W', 'A', 'H', 'N' | 0x80, '#', '(', 'O', 'N', 'E', ')', ' ', '=', 'W', 'A', 'H', 'N' | 0x80, '(', 'O', 'W', ')', '=', 'O', 'W' | 0x80, ' ', '(', 'O', 'V', 'E', 'R', ')', '=', 'O', 'W', '5', 'V', 'E', 'R' | 0x80, 'P', 'R', '(', 'O', ')', 'V', '=', 'U', 'W', '4' | 0x80, '(', 'O', 'V', ')', '=', 'A', 'H', '4', 'V' | 0x80, '(', 'O', ')', '^', '%', '=', 'O', 'W', '5' | 0x80, '(', 'O', ')', '^', 'E', 'N', '=', 'O', 'W' | 0x80, '(', 'O', ')', '^', 'I', '#', '=', 'O', 'W', '5' | 0x80, '(', 'O', 'L', ')', 'D', '=', 'O', 'W', '4', 'L' | 0x80, '(', 'O', 'U', 'G', 'H', 'T', ')', '=', 'A', 'O', '5', 'T' | 0x80, '(', 'O', 'U', 'G', 'H', ')', '=', 'A', 'H', '5', 'F' | 0x80, ' ', '(', 'O', 'U', ')', '=', 'A', 'W' | 0x80, 'H', '(', 'O', 'U', ')', 'S', '#', '=', 'A', 'W', '4' | 0x80, '(', 'O', 'U', 'S', ')', '=', 'A', 'X', 'S' | 0x80, '(', 'O', 'U', 'R', ')', '=', 'O', 'H', 'R' | 0x80, '(', 'O', 'U', 'L', 'D', ')', '=', 'U', 'H', '5', 'D' | 0x80, '(', 'O', 'U', ')', '^', 'L', '=', 'A', 'H', '5' | 0x80, '(', 'O', 'U', 'P', ')', '=', 'U', 'W', '5', 'P' | 0x80, '(', 'O', 'U', ')', '=', 'A', 'W' | 0x80, '(', 'O', 'Y', ')', '=', 'O', 'Y' | 0x80, '(', 'O', 'I', 'N', 'G', ')', '=', 'O', 'W', '4', 'I', 'H', 'N', 'X' | 0x80, '(', 'O', 'I', ')', '=', 'O', 'Y', '5' | 0x80, '(', 'O', 'O', 'R', ')', '=', 'O', 'H', '5', 'R' | 0x80, '(', 'O', 'O', 'K', ')', '=', 'U', 'H', '5', 'K' | 0x80, 'F', '(', 'O', 'O', 'D', ')', '=', 'U', 'W', '5', 'D' | 0x80, 'L', '(', 'O', 'O', 'D', ')', '=', 'A', 'H', '5', 'D' | 0x80, 'M', '(', 'O', 'O', 'D', ')', '=', 'U', 'W', '5', 'D' | 0x80, '(', 'O', 'O', 'D', ')', '=', 'U', 'H', '5', 'D' | 0x80, 'F', '(', 'O', 'O', 'T', ')', '=', 'U', 'H', '5', 'T' | 0x80, '(', 'O', 'O', ')', '=', 'U', 'W', '5' | 0x80, '(', 'O', '\'', ')', '=', 'O', 'H' | 0x80, '(', 'O', ')', 'E', '=', 'O', 'W' | 0x80, '(', 'O', ')', ' ', '=', 'O', 'W' | 0x80, '(', 'O', 'A', ')', '=', 'O', 'W', '4' | 0x80, ' ', '(', 'O', 'N', 'L', 'Y', ')', '=', 'O', 'W', '4', 'N', 'L', 'I', 'Y' | 0x80, ' ', '(', 'O', 'N', 'C', 'E', ')', '=', 'W', 'A', 'H', '4', 'N', 'S' | 0x80, '(', 'O', 'N', '\'', 'T', ')', '=', 'O', 'W', '4', 'N', 'T' | 0x80, 'C', '(', 'O', ')', 'N', '=', 'A', 'A' | 0x80, '(', 'O', ')', 'N', 'G', '=', 'A', 'O' | 0x80, ' ', ':', '^', '(', 'O', ')', 'N', '=', 'A', 'H' | 0x80, 'I', '(', 'O', 'N', ')', '=', 'U', 'N' | 0x80, '#', ':', '(', 'O', 'N', ')', '=', 'U', 'N' | 0x80, '#', '^', '(', 'O', 'N', ')', '=', 'U', 'N' | 0x80, '(', 'O', ')', 'S', 'T', '=', 'O', 'W' | 0x80, '(', 'O', 'F', ')', '^', '=', 'A', 'O', '4', 'F' | 0x80, '(', 'O', 'T', 'H', 'E', 'R', ')', '=', 'A', 'H', '5', 'D', 'H', 'E', 'R' | 0x80, 'R', '(', 'O', ')', 'B', '=', 'R', 'A', 'A' | 0x80, '^', 'R', '(', 'O', ')', ':', '#', '=', 'O', 'W', '5' | 0x80, '(', 'O', 'S', 'S', ')', ' ', '=', 'A', 'O', '5', 'S' | 0x80, '#', ':', '^', '(', 'O', 'M', ')', '=', 'A', 'H', 'M' | 0x80, '(', 'O', ')', '=', 'A', 'A' | 0x80, ']', 'P' | 0x80, ' ', '(', 'P', ')', ' ', '=', 'P', 'I', 'Y', '4' | 0x80, '(', 'P', 'H', ')', '=', 'F' | 0x80, '(', 'P', 'E', 'O', 'P', 'L', ')', '=', 'P', 'I', 'Y', '5', 'P', 'U', 'L' | 0x80, '(', 'P', 'O', 'W', ')', '=', 'P', 'A', 'W', '4' | 0x80, '(', 'P', 'U', 'T', ')', ' ', '=', 'P', 'U', 'H', 'T' | 0x80, '(', 'P', ')', 'P', '=' | 0x80, '(', 'P', ')', 'S', '=' | 0x80, '(', 'P', ')', 'N', '=' | 0x80, '(', 'P', 'R', 'O', 'F', '.', ')', '=', 'P', 'R', 'O', 'H', 'F', 'E', 'H', '4', 'S', 'E', 'R' | 0x80, '(', 'P', ')', '=', 'P' | 0x80, ']', 'Q' | 0x80, ' ', '(', 'Q', ')', ' ', '=', 'K', 'Y', 'U', 'W', '4' | 0x80, '(', 'Q', 'U', 'A', 'R', ')', '=', 'K', 'W', 'O', 'H', '5', 'R' | 0x80, '(', 'Q', 'U', ')', '=', 'K', 'W' | 0x80, '(', 'Q', ')', '=', 'K' | 0x80, ']', 'R' | 0x80, ' ', '(', 'R', ')', ' ', '=', 'A', 'A', '5', 'R' | 0x80, ' ', '(', 'R', 'E', ')', '^', '#', '=', 'R', 'I', 'Y' | 0x80, '(', 'R', ')', 'R', '=' | 0x80, '(', 'R', ')', '=', 'R' | 0x80, ']', 'S' | 0x80, ' ', '(', 'S', ')', ' ', '=', 'E', 'H', '4', 'S' | 0x80, '(', 'S', 'H', ')', '=', 'S', 'H' | 0x80, '#', '(', 'S', 'I', 'O', 'N', ')', '=', 'Z', 'H', 'U', 'N' | 0x80, '(', 'S', 'O', 'M', 'E', ')', '=', 'S', 'A', 'H', 'M' | 0x80, '#', '(', 'S', 'U', 'R', ')', '#', '=', 'Z', 'H', 'E', 'R' | 0x80, '(', 'S', 'U', 'R', ')', '#', '=', 'S', 'H', 'E', 'R' | 0x80, '#', '(', 'S', 'U', ')', '#', '=', 'Z', 'H', 'U', 'W' | 0x80, '#', '(', 'S', 'S', 'U', ')', '#', '=', 'S', 'H', 'U', 'W' | 0x80, '#', '(', 'S', 'E', 'D', ')', '=', 'Z', 'D' | 0x80, '#', '(', 'S', ')', '#', '=', 'Z' | 0x80, '(', 'S', 'A', 'I', 'D', ')', '=', 'S', 'E', 'H', 'D' | 0x80, '^', '(', 'S', 'I', 'O', 'N', ')', '=', 'S', 'H', 'U', 'N' | 0x80, '(', 'S', ')', 'S', '=' | 0x80, '.', '(', 'S', ')', ' ', '=', 'Z' | 0x80, '#', ':', '.', 'E', '(', 'S', ')', ' ', '=', 'Z' | 0x80, '#', ':', '^', '#', '(', 'S', ')', ' ', '=', 'S' | 0x80, 'U', '(', 'S', ')', ' ', '=', 'S' | 0x80, ' ', ':', '#', '(', 'S', ')', ' ', '=', 'Z' | 0x80, '#', '#', '(', 'S', ')', ' ', '=', 'Z' | 0x80, ' ', '(', 'S', 'C', 'H', ')', '=', 'S', 'K' | 0x80, '(', 'S', ')', 'C', '+', '=' | 0x80, '#', '(', 'S', 'M', ')', '=', 'Z', 'U', 'M' | 0x80, '#', '(', 'S', 'N', ')', '\'', '=', 'Z', 'U', 'M' | 0x80, '(', 'S', 'T', 'L', 'E', ')', '=', 'S', 'U', 'L' | 0x80, '(', 'S', ')', '=', 'S' | 0x80, ']', 'T' | 0x80, ' ', '(', 'T', ')', ' ', '=', 'T', 'I', 'Y', '4' | 0x80, ' ', '(', 'T', 'H', 'E', ')', ' ', '#', '=', 'D', 'H', 'I', 'Y' | 0x80, ' ', '(', 'T', 'H', 'E', ')', ' ', '=', 'D', 'H', 'A', 'X' | 0x80, '(', 'T', 'O', ')', ' ', '=', 'T', 'U', 'X' | 0x80, ' ', '(', 'T', 'H', 'A', 'T', ')', '=', 'D', 'H', 'A', 'E', 'T' | 0x80, ' ', '(', 'T', 'H', 'I', 'S', ')', ' ', '=', 'D', 'H', 'I', 'H', 'S' | 0x80, ' ', '(', 'T', 'H', 'E', 'Y', ')', '=', 'D', 'H', 'E', 'Y' | 0x80, ' ', '(', 'T', 'H', 'E', 'R', 'E', ')', '=', 'D', 'H', 'E', 'H', 'R' | 0x80, '(', 'T', 'H', 'E', 'R', ')', '=', 'D', 'H', 'E', 'R' | 0x80, '(', 'T', 'H', 'E', 'I', 'R', ')', '=', 'D', 'H', 'E', 'H', 'R' | 0x80, ' ', '(', 'T', 'H', 'A', 'N', ')', ' ', '=', 'D', 'H', 'A', 'E', 'N' | 0x80, ' ', '(', 'T', 'H', 'E', 'M', ')', ' ', '=', 'D', 'H', 'A', 'E', 'N' | 0x80, '(', 'T', 'H', 'E', 'S', 'E', ')', ' ', '=', 'D', 'H', 'I', 'Y', 'Z' | 0x80, ' ', '(', 'T', 'H', 'E', 'N', ')', '=', 'D', 'H', 'E', 'H', 'N' | 0x80, '(', 'T', 'H', 'R', 'O', 'U', 'G', 'H', ')', '=', 'T', 'H', 'R', 'U', 'W', '4' | 0x80, '(', 'T', 'H', 'O', 'S', 'E', ')', '=', 'D', 'H', 'O', 'H', 'Z' | 0x80, '(', 'T', 'H', 'O', 'U', 'G', 'H', ')', ' ', '=', 'D', 'H', 'O', 'W' | 0x80, '(', 'T', 'O', 'D', 'A', 'Y', ')', '=', 'T', 'U', 'X', 'D', 'E', 'Y' | 0x80, '(', 'T', 'O', 'M', 'O', ')', 'R', 'R', 'O', 'W', '=', 'T', 'U', 'M', 'A', 'A', '5' | 0x80, '(', 'T', 'O', ')', 'T', 'A', 'L', '=', 'T', 'O', 'W', '5' | 0x80, ' ', '(', 'T', 'H', 'U', 'S', ')', '=', 'D', 'H', 'A', 'H', '4', 'S' | 0x80, '(', 'T', 'H', ')', '=', 'T', 'H' | 0x80, '#', ':', '(', 'T', 'E', 'D', ')', '=', 'T', 'I', 'X', 'D' | 0x80, 'S', '(', 'T', 'I', ')', '#', 'N', '=', 'C', 'H' | 0x80, '(', 'T', 'I', ')', 'O', '=', 'S', 'H' | 0x80, '(', 'T', 'I', ')', 'A', '=', 'S', 'H' | 0x80, '(', 'T', 'I', 'E', 'N', ')', '=', 'S', 'H', 'U', 'N' | 0x80, '(', 'T', 'U', 'R', ')', '#', '=', 'C', 'H', 'E', 'R' | 0x80, '(', 'T', 'U', ')', 'A', '=', 'C', 'H', 'U', 'W' | 0x80, ' ', '(', 'T', 'W', 'O', ')', '=', 'T', 'U', 'W' | 0x80, '&', '(', 'T', ')', 'E', 'N', ' ', '=' | 0x80, '(', 'T', ')', '=', 'T' | 0x80, ']', 'U' | 0x80, ' ', '(', 'U', ')', ' ', '=', 'Y', 'U', 'W', '4' | 0x80, ' ', '(', 'U', 'N', ')', 'I', '=', 'Y', 'U', 'W', 'N' | 0x80, ' ', '(', 'U', 'N', ')', '=', 'A', 'H', 'N' | 0x80, ' ', '(', 'U', 'P', 'O', 'N', ')', '=', 'A', 'X', 'P', 'A', 'O', 'N' | 0x80, '@', '(', 'U', 'R', ')', '#', '=', 'U', 'H', '4', 'R' | 0x80, '(', 'U', 'R', ')', '#', '=', 'Y', 'U', 'H', '4', 'R' | 0x80, '(', 'U', 'R', ')', '=', 'E', 'R' | 0x80, '(', 'U', ')', '^', ' ', '=', 'A', 'H' | 0x80, '(', 'U', ')', '^', '^', '=', 'A', 'H', '5' | 0x80, '(', 'U', 'Y', ')', '=', 'A', 'Y', '5' | 0x80, ' ', 'G', '(', 'U', ')', '#', '=' | 0x80, 'G', '(', 'U', ')', '%', '=' | 0x80, 'G', '(', 'U', ')', '#', '=', 'W' | 0x80, '#', 'N', '(', 'U', ')', '=', 'Y', 'U', 'W' | 0x80, '@', '(', 'U', ')', '=', 'U', 'W' | 0x80, '(', 'U', ')', '=', 'Y', 'U', 'W' | 0x80, ']', 'V' | 0x80, ' ', '(', 'V', ')', ' ', '=', 'V', 'I', 'Y', '4' | 0x80, '(', 'V', 'I', 'E', 'W', ')', '=', 'V', 'Y', 'U', 'W', '5' | 0x80, '(', 'V', ')', '=', 'V' | 0x80, ']', 'W' | 0x80, ' ', '(', 'W', ')', ' ', '=', 'D', 'A', 'H', '4', 'B', 'U', 'L', 'Y', 'U', 'W' | 0x80, ' ', '(', 'W', 'E', 'R', 'E', ')', '=', 'W', 'E', 'R' | 0x80, '(', 'W', 'A', ')', 'S', 'H', '=', 'W', 'A', 'A' | 0x80, '(', 'W', 'A', ')', 'S', 'T', '=', 'W', 'E', 'Y' | 0x80, '(', 'W', 'A', ')', 'S', '=', 'W', 'A', 'H' | 0x80, '(', 'W', 'A', ')', 'T', '=', 'W', 'A', 'A' | 0x80, '(', 'W', 'H', 'E', 'R', 'E', ')', '=', 'W', 'H', 'E', 'H', 'R' | 0x80, '(', 'W', 'H', 'A', 'T', ')', '=', 'W', 'H', 'A', 'H', 'T' | 0x80, '(', 'W', 'H', 'O', 'L', ')', '=', '/', 'H', 'O', 'W', 'L' | 0x80, '(', 'W', 'H', 'O', ')', '=', '/', 'H', 'U', 'W' | 0x80, '(', 'W', 'H', ')', '=', 'W', 'H' | 0x80, '(', 'W', 'A', 'R', ')', '#', '=', 'W', 'E', 'H', 'R' | 0x80, '(', 'W', 'A', 'R', ')', '=', 'W', 'A', 'O', 'R' | 0x80, '(', 'W', 'O', 'R', ')', '^', '=', 'W', 'E', 'R' | 0x80, '(', 'W', 'R', ')', '=', 'R' | 0x80, '(', 'W', 'O', 'M', ')', 'A', '=', 'W', 'U', 'H', 'M' | 0x80, '(', 'W', 'O', 'M', ')', 'E', '=', 'W', 'I', 'H', 'M' | 0x80, '(', 'W', 'E', 'A', ')', 'R', '=', 'W', 'E', 'H' | 0x80, '(', 'W', 'A', 'N', 'T', ')', '=', 'W', 'A', 'A', '5', 'N', 'T' | 0x80, 'A', 'N', 'S', '(', 'W', 'E', 'R', ')', '=', 'E', 'R' | 0x80, '(', 'W', ')', '=', 'W' | 0x80, ']', 'X' | 0x80, ' ', '(', 'X', ')', ' ', '=', 'E', 'H', '4', 'K', 'R' | 0x80, ' ', '(', 'X', ')', '=', 'Z' | 0x80, '(', 'X', ')', '=', 'K', 'S' | 0x80, ']', 'Y' | 0x80, ' ', '(', 'Y', ')', ' ', '=', 'W', 'A', 'Y', '4' | 0x80, '(', 'Y', 'O', 'U', 'N', 'G', ')', '=', 'Y', 'A', 'H', 'N', 'X' | 0x80, ' ', '(', 'Y', 'O', 'U', 'R', ')', '=', 'Y', 'O', 'H', 'R' | 0x80, ' ', '(', 'Y', 'O', 'U', ')', '=', 'Y', 'U', 'W' | 0x80, ' ', '(', 'Y', 'E', 'S', ')', '=', 'Y', 'E', 'H', 'S' | 0x80, ' ', '(', 'Y', ')', '=', 'Y' | 0x80, 'F', '(', 'Y', ')', '=', 'A', 'Y' | 0x80, 'P', 'S', '(', 'Y', 'C', 'H', ')', '=', 'A', 'Y', 'K' | 0x80, '#', ':', '^', '(', 'Y', ')', '=', 'I', 'Y' | 0x80, '#', ':', '^', '(', 'Y', ')', 'I', '=', 'I', 'Y' | 0x80, ' ', ':', '(', 'Y', ')', ' ', '=', 'A', 'Y' | 0x80, ' ', ':', '(', 'Y', ')', '#', '=', 'A', 'Y' | 0x80, ' ', ':', '(', 'Y', ')', '^', '+', ':', '#', '=', 'I', 'H' | 0x80, ' ', ':', '(', 'Y', ')', '^', '#', '=', 'A', 'Y' | 0x80, '(', 'Y', ')', '=', 'I', 'H' | 0x80, ']', 'Z' | 0x80, ' ', '(', 'Z', ')', ' ', '=', 'Z', 'I', 'Y', '4' | 0x80, '(', 'Z', ')', '=', 'Z' | 0x80, 'j' | 0x80}; const unsigned char rules2[] = { '(', 'A', ')', '=' | 0x80, '(', '!', ')', '=', '.' | 0x80, '(', '"', ')', ' ', '=', '-', 'A', 'H', '5', 'N', 'K', 'W', 'O', 'W', 'T', '-' | 0x80, '(', '"', ')', '=', 'K', 'W', 'O', 'W', '4', 'T', '-' | 0x80, '(', '#', ')', '=', ' ', 'N', 'A', 'H', '4', 'M', 'B', 'E', 'R' | 0x80, '(', '$', ')', '=', ' ', 'D', 'A', 'A', '4', 'L', 'E', 'R' | 0x80, '(', '%', ')', '=', ' ', 'P', 'E', 'R', 'S', 'E', 'H', '4', 'N', 'T' | 0x80, '(', '&', ')', '=', ' ', 'A', 'E', 'N', 'D' | 0x80, '(', '\'', ')', '=' | 0x80, '(', '*', ')', '=', ' ', 'A', 'E', '4', 'S', 'T', 'E', 'R', 'I', 'H', 'S', 'K' | 0x80, '(', '+', ')', '=', ' ', 'P', 'L', 'A', 'H', '4', 'S' | 0x80, '(', ',', ')', '=', ',' | 0x80, ' ', '(', '-', ')', ' ', '=', '-' | 0x80, '(', '-', ')', '=' | 0x80, '(', '.', ')', '=', ' ', 'P', 'O', 'Y', 'N', 'T' | 0x80, '(', '/', ')', '=', ' ', 'S', 'L', 'A', 'E', '4', 'S', 'H' | 0x80, '(', '0', ')', '=', ' ', 'Z', 'I', 'Y', '4', 'R', 'O', 'W' | 0x80, ' ', '(', '1', 'S', 'T', ')', '=', 'F', 'E', 'R', '4', 'S', 'T' | 0x80, ' ', '(', '1', '0', 'T', 'H', ')', '=', 'T', 'E', 'H', '4', 'N', 'T', 'H' | 0x80, '(', '1', ')', '=', ' ', 'W', 'A', 'H', '4', 'N' | 0x80, ' ', '(', '2', 'N', 'D', ')', '=', 'S', 'E', 'H', '4', 'K', 'U', 'N', 'D' | 0x80, '(', '2', ')', '=', ' ', 'T', 'U', 'W', '4' | 0x80, ' ', '(', '3', 'R', 'D', ')', '=', 'T', 'H', 'E', 'R', '4', 'D' | 0x80, '(', '3', ')', '=', ' ', 'T', 'H', 'R', 'I', 'Y', '4' | 0x80, '(', '4', ')', '=', ' ', 'F', 'O', 'H', '4', 'R' | 0x80, ' ', '(', '5', 'T', 'H', ')', '=', 'F', 'I', 'H', '4', 'F', 'T', 'H' | 0x80, '(', '5', ')', '=', ' ', 'F', 'A', 'Y', '4', 'V' | 0x80, ' ', '(', '6', '4', ')', ' ', '=', 'S', 'I', 'H', '4', 'K', 'S', 'T', 'I', 'Y', ' ', 'F', 'O', 'H', 'R' | 0x80, '(', '6', ')', '=', ' ', 'S', 'I', 'H', '4', 'K', 'S' | 0x80, '(', '7', ')', '=', ' ', 'S', 'E', 'H', '4', 'V', 'U', 'N' | 0x80, ' ', '(', '8', 'T', 'H', ')', '=', 'E', 'Y', '4', 'T', 'H' | 0x80, '(', '8', ')', '=', ' ', 'E', 'Y', '4', 'T' | 0x80, '(', '9', ')', '=', ' ', 'N', 'A', 'Y', '4', 'N' | 0x80, '(', ':', ')', '=', '.' | 0x80, '(', ';', ')', '=', '.' | 0x80, '(', '<', ')', '=', ' ', 'L', 'E', 'H', '4', 'S', ' ', 'D', 'H', 'A', 'E', 'N' | 0x80, '(', '=', ')', '=', ' ', 'I', 'Y', '4', 'K', 'W', 'U', 'L', 'Z' | 0x80, '(', '>', ')', '=', ' ', 'G', 'R', 'E', 'Y', '4', 'T', 'E', 'R', ' ', 'D', 'H', 'A', 'E', 'N' | 0x80, '(', '?', ')', '=', '?' | 0x80, '(', '@', ')', '=', ' ', 'A', 'E', '6', 'T' | 0x80, '(', '^', ')', '=', ' ', 'K', 'A', 'E', '4', 'R', 'I', 'X', 'T' | 0x80, ']', 'A' | 0x80}; //26 items. From 'A' to 'Z' // positions for mem62 and mem63 for each character const unsigned char tab37489[] = {0, 149, 247, 162, 57, 197, 6, 126, 199, 38, 55, 78, 145, 241, 85, 161, 254, 36, 69, 45, 167, 54, 83, 46, 71, 218}; const unsigned char tab37515[] = {125, 126, 126, 127, 128, 129, 130, 130, 130, 132, 132, 132, 132, 132, 133, 135, 135, 136, 136, 137, 138, 139, 139, 140, 140, 140}; void STM32SAM::Output8BitAry(int index, unsigned char ary[5]) { int k; uint32_t bufferposOld = bufferpos; bufferpos += timetable[oldtimetableindex][index]; oldtimetableindex = index; int sample_uS = bufferpos - bufferposOld; uint32_t f = 0; // write a little bit in advance for(k = 0; k < 5; k++) { // buffer[bufferpos / 50 + k] = ary[k]; // f = micros() + sample_uS / (_STM32SAM_SPEED + 1); // while(micros() < f) { // }; f = sample_uS / (_STM32SAM_SPEED + 1); furi_delay_us(f); SetAUDIO(ary[k]); // delayMicroseconds(sample_uS / 5 ); } // SetAUDIO(ary[0]); } void STM32SAM::Output8Bit(int index, unsigned char A) { unsigned char ary[5] = {A, A, A, A, A}; Output8BitAry(index, ary); } //written by me because of different table positions. // mem[47] = ... // 168=pitches // 169=frequency1 // 170=frequency2 // 171=frequency3 // 172=amplitude1 // 173=amplitude2 // 174=amplitude3 unsigned char STM32SAM::Read(unsigned char p, unsigned char 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]; } // Serial1.println("Error reading to tables"); return 0; } void STM32SAM::Write(unsigned char p, unsigned char Y, unsigned char 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; } //Serial1.println("Error writing to tables\n"); } // ------------------------------------------------------------------------- //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 STM32SAM::RenderSample(unsigned char* mem66) { int 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 Output8Bit(1, (X & 0x0f) * 16); // if X != 0, exit loop if(X != 0) goto pos48296; } // output a 5 for the on bit Output8Bit(2, 5 * 16); //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; unsigned char 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; Output8Bit(3, (X & 0xf) * 16); } else { //timetable 4 // bit is not set, output a 6 X = 6; Output8Bit(4, (X & 0xf) * 16); } mem56--; } while(mem56 != 0); // move ahead in the table Y++; // continue until counter done phase1++; } while(phase1 != 0); // if (phase1 != 0) goto pos48321; // restore values and return A = 1; mem44 = 1; *mem66 = Y; Y = mem49; return; } // RENDER THE PHONEMES IN THE LIST // // The phoneme list is converted into sound through the steps: // // 1. Copy each phoneme 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 STM32SAM::Render() { unsigned char phase1 = 0; //mem43 unsigned char phase2 = 0; unsigned char phase3 = 0; unsigned char mem66 = 0; unsigned char mem38 = 0; unsigned char mem40 = 0; unsigned char speedcounter = 0; //mem45 unsigned char mem48 = 0; int i; 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 unsigned char 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 signed char m53 = (signed char)mem53; mem50 = mem53 & 128; unsigned char m53abs = abs(m53); mem51 = m53abs % mem40; //abs((char)m53) % mem40; mem53 = (unsigned char)((signed char)(m53) / 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 ??? // 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 unsigned char ary[5]; unsigned int p1 = phase1 * 256; // Fixed point integers because we need to divide later on unsigned int p2 = phase2 * 256; unsigned int p3 = phase3 * 256; int k; for(k = 0; k < 5; k++) { signed char sp1 = (signed char)sinus[0xff & (p1 >> 8)]; signed char sp2 = (signed char)sinus[0xff & (p2 >> 8)]; signed char rp3 = (signed char)rectangle[0xff & (p3 >> 8)]; signed int sin1 = sp1 * ((unsigned char)amplitude1[Y] & 0x0f); signed int sin2 = sp2 * ((unsigned char)amplitude2[Y] & 0x0f); signed int rect = rp3 * ((unsigned char)amplitude3[Y] & 0x0f); signed int mux = sin1 + sin2 + rect; mux /= 32; mux += 128; // Go from signed to unsigned amplitude ary[k] = mux; p1 += frequency1[Y] * 256 / 4; // Compromise, this becomes a shift and works well p2 += frequency2[Y] * 256 / 4; p3 += frequency3[Y] * 256 / 4; } // output the accumulated value Output8BitAry(0, ary); 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 // 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: int 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; } // 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 STM32SAM::AddInflection(unsigned char mem48, unsigned char phase1) { //pos48372: // mem48 = 255; //pos48376: // store the location of the punctuation mem49 = X; A = X; int 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; } /* 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 STM32SAM::SetMouthThroat() { unsigned char initialFrequency; unsigned char newFrequency = 0; //unsigned char mouth; //mem38880 //unsigned char throat; //mem38881 // mouth formants (F1) 5..29 unsigned char 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 unsigned char 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 unsigned char mouthFormants48_53[6] = {19, 27, 21, 27, 18, 13}; // formant 2 frequencies (throat) 48..53 unsigned char throatFormants48_53[6] = {72, 39, 31, 43, 30, 34}; unsigned char 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++; } } //return = (mem39212*mem39213) >> 1 unsigned char STM32SAM::trans(unsigned char mem39212, unsigned char mem39213) { //pos39008: unsigned char carry; int temp; unsigned char 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 = (int)A + (int)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; } //////////////////////////////////////////////////////////////////////////////////////////// // // Sam // //////////////////////////////////////////////////////////////////////////////////////////// //char input[]={"/HAALAOAO MAYN NAAMAEAE IHSTT SAEBAASTTIHAAN \x9b\x9b\0"}; //unsigned char input[]={"/HAALAOAO \x9b\0"}; //unsigned char input[]={"AA \x9b\0"}; //unsigned char input[] = {"GUH5DEHN TAEG\x9b\0"}; //unsigned char input[]={"AY5 AEM EY TAO4LXKIHNX KAX4MPYUX4TAH. GOW4 AH/HEH3D PAHNK.MEYK MAY8 DEY.\x9b\0"}; //unsigned char input[]={"/HEH3LOW2, /HAW AH YUX2 TUXDEY. AY /HOH3P YUX AH FIYLIHNX OW4 KEY.\x9b\0"}; //unsigned char input[]={"/HEY2, DHIHS IH3Z GREY2T. /HAH /HAH /HAH.AYL BIY5 BAEK.\x9b\0"}; //unsigned char input[]={"/HAH /HAH /HAH \x9b\0"}; //unsigned char input[]={"/HAH /HAH /HAH.\x9b\0"}; //unsigned char input[]={".TUW BIY5Y3,, OHR NAA3T - TUW BIY5IYIY., DHAE4T IHZ DHAH KWEH4SCHAHN.\x9b\0"}; //unsigned char input[]={"/HEY2, DHIHS \x9b\0"}; //unsigned char input[]={" IYIHEHAEAAAHAOOHUHUXERAXIX \x9b\0"}; //unsigned char input[]={" RLWWYMNNXBDGJZZHVDH \x9b\0"}; //unsigned char input[]={" SSHFTHPTKCH/H \x9b\0"}; //unsigned char input[]={" EYAYOYAWOWUW ULUMUNQ YXWXRXLX/XDX\x9b\0"}; void STM32SAM::SetInput(char* _input) { int i, l; l = strlen(_input); if(l > 254) l = 254; for(i = 0; i < l; i++) { input[i] = _input[i]; } input[l] = 0; } // 168=pitches // 169=frequency1 // 170=frequency2 // 171=frequency3 // 172=amplitude1 // 173=amplitude2 // 174=amplitude3 void STM32SAM::Init() { bufferpos = 0; int i; SetMouthThroat(); bufferpos = 0; // TODO, check for free the memory, 10 seconds of output should be more than enough //buffer = malloc(22050*10); // buffer = (char*) calloc(1, sizeof(char)); /* 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; } phonemeindex[255] = 255; //to prevent buffer overflow // ML : changed from 32 to 255 to stop freezing with long inputs } //int Code39771() int STM32SAM::SAMMain() { Init(); phonemeindex[255] = 32; //to prevent buffer overflow if(!Parser1()) { return 0; } 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; PrepareOutput(); return 1; } //void Code48547() void STM32SAM::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++; int 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 Code41014() void STM32SAM::Insert( unsigned char position /*var57*/, unsigned char mem60, unsigned char mem59, unsigned char mem58) { int 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 Code48431() void STM32SAM::InsertBreath() { unsigned char mem54; unsigned char mem55; unsigned char index; //variable Y mem54 = 255; X++; mem55 = 0; unsigned char 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; } } // 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 STM32SAM::CopyStress() { // loop thought all the phonemes to be output unsigned char 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++; } } // 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 character of the phonemes are stored in the table signInputTable1[]. // The second character of the phonemes are stored in the table signInputTable2[]. // The stress characters are arranged in low to high stress order in stressInputTable[]. // // The following process is used to parse the input[] buffer: // // Repeat until the <0x9B> character is reached: // // First, a search is made for a 2 character match for phonemes that do not // end with the '*' (wildcard) character. 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 character 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 character 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 character of each phoneme // signInputTable2[] holds te second character 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 character <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. int STM32SAM::Parser1() { int i; unsigned char sign1; unsigned char sign2; unsigned char 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 } //change phonemelength depedendent on stress //void Code41203() void STM32SAM::SetPhonemeLength() { unsigned char A; int 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 STM32SAM::Code41240() { unsigned char pos = 0; while(phonemeindex[pos] != 255) { unsigned char 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++; // '/H' '/X' continue; } } Insert(pos + 1, index + 1, phonemeLengthTable[index + 1], stress[pos]); Insert(pos + 2, index + 2, phonemeLengthTable[index + 2], stress[pos]); pos += 3; }; } // Rewrites the phonemes using the following rules: // // -> WX // -> YX // UL -> AX L // UM -> AX M // -> Q // T R -> CH R // D R -> J R // R -> RX // L -> LX // G S -> G Z // K -> KX // G -> GX // S P -> S B // S T -> S D // S K -> S G // S KX -> S GX // UW -> UX // CH -> CH CH' (CH requires two phonemes to represent it) // J -> J J' (J requires two phonemes to represent it) // T -> DX // D -> DX //void Code41397() void STM32SAM::Parser2() { unsigned char pos = 0; //mem66; unsigned char 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]; // 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: // -> 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 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' 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' 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' goto pos41466; pos41503: // RULE: // -> Q // 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) { // 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' { 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; goto pos41788; } // RULES FOR PHONEMES BEFORE R // R -> RX // Example: ART // If vowel flag is set change R to RX A = flags[A] & 128; if(A != 0) phonemeindex[pos] = 18; // 'RX' // continue to next phoneme pos++; continue; pos41611: // RULE: // L -> 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 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 phonemeindex[pos] = 38; // 'Z' pos++; continue; } // RULE: // K -> KX // 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; // Replace with KX if(A == 0) phonemeindex[pos] = 75; // 'KX' } } else // RULE: // G -> GX // Example: GO // Is character a G? if(A == 60) // 'G' { // Get the following character unsigned char 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 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 phonemeindex[pos] = Y - 12; pos++; continue; pos41749: // RULE: // UW -> 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; } phonemeindex[X] = 16; pos++; continue; } pos41779: // RULE: // CH -> CH CH' (CH requires two phonemes to represent it) // Example: CHEW if(A == 42) // 'CH' { // pos41783: 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' { 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" // T -> DX // D -> DX // Example: PARTY, TARDY // Past this point, only process if phoneme is T or D if(A != 69) // 'T' if(A != 57) { pos++; // 'D' continue; } //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 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(A != 0) phonemeindex[pos] = 30; // 'DX' } pos++; } // while } // parser 2 // Applies various rules that adjust the lengths of phonemes // // Lengthen or between and by 1.5 // - decrease length by 1 // - decrease vowel by 1/8th // - increase vowel by 1/2 + 1 // - set nasal = 5, consonant = 6 // {optional silence} - shorten both to 1/2 + 1 // - decrease by 2 //void Code48619() void STM32SAM::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; unsigned char index; // iterate through the phoneme list unsigned char 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; phonemeLength[X] = A; } // 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: RX | LX // decrease length of vowel by 1 frame phonemeLength[loopIndex]--; } // move ahead loopIndex++; continue; } // move ahead loopIndex++; continue; } // Got here if not // 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: // // move back X--; // decrease length by 1/8th mem56 = phonemeLength[X] >> 3; phonemeLength[X] -= mem56; // move ahead loopIndex++; continue; } // RULE: // // decrease length A = phonemeLength[X - 1]; phonemeLength[X - 1] = (A >> 2) + A + 1; // 5/4*A + 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: // 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 { // set stop consonant length to 6 phonemeLength[X] = 6; // set nasal length to 5 phonemeLength[X - 1] = 5; } // move to next phoneme loopIndex++; continue; } // WH, R*, L*, W*, Y*, Q*, Z*, ZH, V*, DH, J*, B*, D*, G*, GX // RULE: {optional silence} // 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: {optional silence} // X gets overwritten, so hold prior X value for debug statement // int 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; // move ahead loopIndex++; continue; } // WH, R*, L*, W*, Y*, Q*, Z*, ZH, V*, DH, J*, **, // RULE: // Decrease 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: // decrease the phoneme length by 2 frames (20 ms) phonemeLength[X] -= 2; } } // move to next phoneme loopIndex++; continue; } // goto pos48701; } // ------------------------------------------------------------------------- // ML : Code47503 is division with remainder, and mem50 gets the sign void STM32SAM::Code47503(unsigned char mem52) { Y = 0; if((mem53 & 128) != 0) { mem53 = -mem53; Y = 128; } mem50 = Y; A = 0; for(X = 8; X > 0; X--) { int 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; } //////////////////////////////////////////////////////////////////////////////////////////// // // Reciter // //////////////////////////////////////////////////////////////////////////////////////////// void STM32SAM::Code37055(unsigned char mem59) { X = mem59; X--; A = inputtemp[X]; Y = A; A = tab36376[Y]; return; } void STM32SAM::Code37066(unsigned char mem58) { X = mem58; X++; A = inputtemp[X]; Y = A; A = tab36376[Y]; } unsigned char STM32SAM::GetRuleByte(unsigned short mem62, unsigned char Y) { unsigned int address = mem62; if(mem62 >= 37541) { address -= 37541; return rules2[address + Y]; } address -= 32000; return rules[address + Y]; } int STM32SAM::TextToPhonemes(unsigned char* input) // Code36484 { //unsigned char *tab39445 = &mem[39445]; //input and output //unsigned char mem29; unsigned char mem56; //output position for phonemes unsigned char mem57; unsigned char mem58; unsigned char mem59; unsigned char mem60; unsigned char mem61; unsigned short mem62; // memory position of current rule unsigned char mem64; // position of '=' or current character unsigned char mem65; // position of ')' unsigned char mem66; // position of '(' unsigned char mem36653; inputtemp[0] = 32; // secure copy of input // because input will be overwritten by phonemes X = 1; Y = 0; do { //pos36499: A = input[Y] & 127; if(A >= 112) A = A & 95; else if(A >= 96) A = A & 79; inputtemp[X] = A; X++; Y++; } while(Y != 255); X = 255; inputtemp[X] = 27; mem61 = 255; pos36550: A = 255; mem56 = 255; pos36554: while(1) { mem61++; X = mem61; A = inputtemp[X]; mem64 = A; if(A == '[') { mem56++; X = mem56; A = 155; input[X] = 155; //goto pos36542; // Code39771(); //Code39777(); return 1; } //pos36579: if(A != '.') break; X++; Y = inputtemp[X]; A = tab36376[Y] & 1; if(A != 0) break; mem56++; X = mem56; A = '.'; input[X] = '.'; } //while //pos36607: A = mem64; Y = A; A = tab36376[A]; mem57 = A; if((A & 2) != 0) { mem62 = 37541; goto pos36700; } //pos36630: A = mem57; if(A != 0) goto pos36677; A = 32; inputtemp[X] = ' '; mem56++; X = mem56; if(X > 120) goto pos36654; input[X] = A; goto pos36554; // ----- //36653 is unknown. Contains position pos36654: input[X] = 155; A = mem61; mem36653 = A; // mem29 = A; // not used // Code36538(); das ist eigentlich return 1; //Code39771(); //go on if there is more input ??? mem61 = mem36653; goto pos36550; pos36677: A = mem57 & 128; if(A == 0) { //36683: BRK return 0; } // go to the right rules for this character. X = mem64 - 'A'; mem62 = tab37489[X] | (tab37515[X] << 8); // ------------------------------------- // go to next rule // ------------------------------------- pos36700: // find next rule Y = 0; do { mem62 += 1; A = GetRuleByte(mem62, Y); } while((A & 128) == 0); Y++; //pos36720: // find '(' while(1) { A = GetRuleByte(mem62, Y); if(A == '(') break; Y++; } mem66 = Y; //pos36732: // find ')' do { Y++; A = GetRuleByte(mem62, Y); } while(A != ')'); mem65 = Y; //pos36741: // find '=' do { Y++; A = GetRuleByte(mem62, Y); A = A & 127; } while(A != '='); mem64 = Y; X = mem61; mem60 = X; // compare the string within the bracket Y = mem66; Y++; //pos36759: while(1) { mem57 = inputtemp[X]; A = GetRuleByte(mem62, Y); if(A != mem57) goto pos36700; Y++; if(Y == mem65) break; X++; mem60 = X; } // the string in the bracket is correct //pos36787: A = mem61; mem59 = mem61; pos36791: while(1) { mem66--; Y = mem66; A = GetRuleByte(mem62, Y); mem57 = A; //36800: BPL 36805 if((A & 128) != 0) goto pos37180; X = A & 127; A = tab36376[X] & 128; if(A == 0) break; X = mem59 - 1; A = inputtemp[X]; if(A != mem57) goto pos36700; mem59 = X; } //pos36833: A = mem57; if(A == ' ') goto pos36895; if(A == '#') goto pos36910; if(A == '.') goto pos36920; if(A == '&') goto pos36935; if(A == '@') goto pos36967; if(A == '^') goto pos37004; if(A == '+') goto pos37019; if(A == ':') goto pos37040; // Code42041(); //Error //36894: BRK return 0; // -------------- pos36895: Code37055(mem59); A = A & 128; if(A != 0) goto pos36700; pos36905: mem59 = X; goto pos36791; // -------------- pos36910: Code37055(mem59); A = A & 64; if(A != 0) goto pos36905; goto pos36700; // -------------- pos36920: Code37055(mem59); A = A & 8; if(A == 0) goto pos36700; pos36930: mem59 = X; goto pos36791; // -------------- pos36935: Code37055(mem59); A = A & 16; if(A != 0) goto pos36930; A = inputtemp[X]; if(A != 72) goto pos36700; X--; A = inputtemp[X]; if((A == 67) || (A == 83)) goto pos36930; goto pos36700; // -------------- pos36967: Code37055(mem59); A = A & 4; if(A != 0) goto pos36930; A = inputtemp[X]; if(A != 72) goto pos36700; if((A != 84) && (A != 67) && (A != 83)) goto pos36700; mem59 = X; goto pos36791; // -------------- pos37004: Code37055(mem59); A = A & 32; if(A == 0) goto pos36700; pos37014: mem59 = X; goto pos36791; // -------------- pos37019: X = mem59; X--; A = inputtemp[X]; if((A == 'E') || (A == 'I') || (A == 'Y')) goto pos37014; goto pos36700; // -------------- pos37040: Code37055(mem59); A = A & 32; if(A == 0) goto pos36791; mem59 = X; goto pos37040; //--------------------------------------- pos37077: X = mem58 + 1; A = inputtemp[X]; if(A != 'E') goto pos37157; X++; Y = inputtemp[X]; X--; A = tab36376[Y] & 128; if(A == 0) goto pos37108; X++; A = inputtemp[X]; if(A != 'R') goto pos37113; pos37108: mem58 = X; goto pos37184; pos37113: if((A == 83) || (A == 68)) goto pos37108; // 'S' 'D' if(A != 76) goto pos37135; // 'L' X++; A = inputtemp[X]; if(A != 89) goto pos36700; goto pos37108; pos37135: if(A != 70) goto pos36700; X++; A = inputtemp[X]; if(A != 85) goto pos36700; X++; A = inputtemp[X]; if(A == 76) goto pos37108; goto pos36700; pos37157: if(A != 73) goto pos36700; X++; A = inputtemp[X]; if(A != 78) goto pos36700; X++; A = inputtemp[X]; if(A == 71) goto pos37108; //pos37177: goto pos36700; // ----------------------------------------- pos37180: A = mem60; mem58 = A; pos37184: Y = mem65 + 1; //37187: CPY 64 // if(? != 0) goto pos37194; if(Y == mem64) goto pos37455; mem65 = Y; //37196: LDA (62),y A = GetRuleByte(mem62, Y); mem57 = A; X = A; A = tab36376[X] & 128; if(A == 0) goto pos37226; X = mem58 + 1; A = inputtemp[X]; if(A != mem57) goto pos36700; mem58 = X; goto pos37184; pos37226: A = mem57; if(A == 32) goto pos37295; // ' ' if(A == 35) goto pos37310; // '#' if(A == 46) goto pos37320; // '.' if(A == 38) goto pos37335; // '&' if(A == 64) goto pos37367; // '' if(A == 94) goto pos37404; // '' if(A == 43) goto pos37419; // '+' if(A == 58) goto pos37440; // ':' if(A == 37) goto pos37077; // '%' //pos37291: // Code42041(); //Error //37294: BRK return 0; // -------------- pos37295: Code37066(mem58); A = A & 128; if(A != 0) goto pos36700; pos37305: mem58 = X; goto pos37184; // -------------- pos37310: Code37066(mem58); A = A & 64; if(A != 0) goto pos37305; goto pos36700; // -------------- pos37320: Code37066(mem58); A = A & 8; if(A == 0) goto pos36700; pos37330: mem58 = X; goto pos37184; // -------------- pos37335: Code37066(mem58); A = A & 16; if(A != 0) goto pos37330; A = inputtemp[X]; if(A != 72) goto pos36700; X++; A = inputtemp[X]; if((A == 67) || (A == 83)) goto pos37330; goto pos36700; // -------------- pos37367: Code37066(mem58); A = A & 4; if(A != 0) goto pos37330; A = inputtemp[X]; if(A != 72) goto pos36700; if((A != 84) && (A != 67) && (A != 83)) goto pos36700; mem58 = X; goto pos37184; // -------------- pos37404: Code37066(mem58); A = A & 32; if(A == 0) goto pos36700; pos37414: mem58 = X; goto pos37184; // -------------- pos37419: X = mem58; X++; A = inputtemp[X]; if((A == 69) || (A == 73) || (A == 89)) goto pos37414; goto pos36700; // ---------------------- pos37440: Code37066(mem58); A = A & 32; if(A == 0) goto pos37184; mem58 = X; goto pos37440; pos37455: Y = mem64; mem61 = mem60; pos37461: //37461: LDA (62),y A = GetRuleByte(mem62, Y); mem57 = A; A = A & 127; if(A != '=') { mem56++; X = mem56; input[X] = A; } //37478: BIT 57 //37480: BPL 37485 //not negative flag if((mem57 & 128) == 0) goto pos37485; //??? goto pos36554; pos37485: Y++; goto pos37461; } // Constructor STM32SAM::STM32SAM(uint32_t STM32SAM_SPEED /* = 5 */) { STM32SAM_SPEED = STM32SAM_SPEED & 0x1f; // limit it from 0 to 31 _STM32SAM_SPEED = STM32SAM_SPEED; // set default voice speed = 72; pitch = 64; mouth = 128; throat = 128; phonetic = 0; singmode = 0; wait1 = 7; wait2 = 6; mem59 = 0; oldtimetableindex = 0; } STM32SAM::STM32SAM() { _STM32SAM_SPEED = 7; // set default voice speed = 72; pitch = 64; mouth = 128; throat = 128; phonetic = 0; singmode = 0; wait1 = 7; wait2 = 6; mem59 = 0; oldtimetableindex = 0; } /* STM32SAM::~STM32SAM() { { // TODO: end(); } */ //////////////////////////////////////////////////////////////////////////////////////////// // // STM32SAM sam (variable string, phonetic, sing, pitch, speed, mouth, throat) // STM32SAM say (sing off, phonetic off) (const string) // STM32SAM say (sing off, phonetic off) (variable string) // STM32SAM sing (sing on, phonetic off) (const string) // STM32SAM sing (sing on, phonetic off) (variable string) // STM32SAM sayPhonetic (sing off, phonetic on) (const string) // STM32SAM sayPhonetic (sing off, phonetic on) (variable string) // STM32SAM singPhonetic (sing on, phonetic on) (const string) // STM32SAM singPhonetic (sing on, phonetic on) (variable string) // STM32SAM voice (pitch, speed, mouth, throat) // STM32SAM setPitch (pitch) // STM32SAM setSpeed (speed) // STM32SAM setMouth (mouth) // STM32SAM setThroat (throat) // // //////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////// // // STM32SAM sam (const string, phonetic, sing, pitch, speed, mouth, throat) // //////////////////////////////////////////////////////////////////////////////////////////// char to_upper_case(char c) { if(c >= 'a' && c <= 'z') { return c - 'a' + 'A'; } return c; } void STM32SAM::sam( const char* argv, unsigned char _phonetic, unsigned char _singmode, unsigned char _pitch, unsigned char _speed, unsigned char _mouth, unsigned char _throat) { phonetic = _phonetic; singmode = _singmode; pitch = _pitch; speed = _speed; mouth = _mouth; throat = _throat; int i; for(i = 0; i < 256; i++) { input[i] = argv[i]; } for(i = 0; input[i] != 0; i++) { if(i != 0) { input[i] = to_upper_case((int)argv[i]); } } if(!phonetic) { strncat(input, "[", 256); if(!TextToPhonemes((unsigned char*)input)) { // PrintUsage(); return; } } else { strncat(input, "\x9b", 256); } SetInput(input); if(!SAMMain()) { return; } } //////////////////////////////////////////////////////////////////////////////////////////// // // STM32SAM sam (variable string, phonetic, sing, pitch, speed, mouth, throat) // //////////////////////////////////////////////////////////////////////////////////////////// void STM32SAM::sam( char* argv, unsigned char _phonetic, unsigned char _singmode, unsigned char _pitch, unsigned char _speed, unsigned char _mouth, unsigned char _throat) { phonetic = _phonetic; singmode = _singmode; pitch = _pitch; speed = _speed; mouth = _mouth; throat = _throat; int i; for(i = 0; i < 256; i++) { input[i] = argv[i]; } for(i = 0; input[i] != 0; i++) { if(i != 0) { input[i] = to_upper_case((int)argv[i]); } } if(!phonetic) { strncat(input, "[", 256); if(!TextToPhonemes((unsigned char*)input)) { // PrintUsage(); return; } } else { strncat(input, "\x9b", 256); } SetInput(input); if(!SAMMain()) { return; } } //////////////////////////////////////////////////////////////////////////////////////////// // // STM32SAM say(sing off, phonetic off) (const string) // //////////////////////////////////////////////////////////////////////////////////////////// void STM32SAM::say(const char* argv) { int i; phonetic = 0; singmode = 0; char const_input[256]; for(i = 0; i < 256; i++) { const_input[i] = argv[i]; } sam(const_input, phonetic, singmode, pitch, speed, mouth, throat); } void STM32SAM::say(char* argv) { int i; phonetic = 0; singmode = 0; char const_input[256]; for(i = 0; i < 256; i++) { const_input[i] = argv[i]; } sam(const_input, phonetic, singmode, pitch, speed, mouth, throat); } //////////////////////////////////////////////////////////////////////////////////////////// // // STM32SAM sing (sing on, phonetic off) // //////////////////////////////////////////////////////////////////////////////////////////// void STM32SAM::sing(const char* argv) { int i; phonetic = 0; singmode = 1; char const_input[256]; for(i = 0; i < 256; i++) { const_input[i] = argv[i]; } sam(const_input, phonetic, singmode, pitch, speed, mouth, throat); } void STM32SAM::sing(char* argv) { int i; phonetic = 0; singmode = 1; char const_input[256]; for(i = 0; i < 256; i++) { const_input[i] = argv[i]; } sam(const_input, phonetic, singmode, pitch, speed, mouth, throat); } //////////////////////////////////////////////////////////////////////////////////////////// // // STM32SAM sayPhonetic (sing off, phonetic on) // //////////////////////////////////////////////////////////////////////////////////////////// void STM32SAM::sayPhonetic(const char* argv) { int i; phonetic = 1; singmode = 0; char const_input[256]; for(i = 0; i < 256; i++) { const_input[i] = argv[i]; } sam(const_input, phonetic, singmode, pitch, speed, mouth, throat); } void STM32SAM::sayPhonetic(char* argv) { int i; phonetic = 1; singmode = 0; char const_input[256]; for(i = 0; i < 256; i++) { const_input[i] = argv[i]; } sam(const_input, phonetic, singmode, pitch, speed, mouth, throat); } //////////////////////////////////////////////////////////////////////////////////////////// // // STM32SAM singPhonetic (sing on, phonetic on) // //////////////////////////////////////////////////////////////////////////////////////////// void STM32SAM::singPhonetic(const char* argv) { int i; phonetic = 1; singmode = 1; char const_input[256]; for(i = 0; i < 256; i++) { const_input[i] = argv[i]; } sam(const_input, phonetic, singmode, pitch, speed, mouth, throat); } void STM32SAM::singPhonetic(char* argv) { int i; phonetic = 1; singmode = 0; char const_input[256]; for(i = 0; i < 256; i++) { const_input[i] = argv[i]; } sam(const_input, phonetic, singmode, pitch, speed, mouth, throat); } //////////////////////////////////////////////////////////////////////////////////////////// // // STM32SAM voice (pitch, speed, mouth, throat) // //////////////////////////////////////////////////////////////////////////////////////////// void STM32SAM::setVoice( unsigned char _pitch /* = 64 */, unsigned char _speed /* = 72 */, unsigned char _mouth /* = 128 */, unsigned char _throat /* = 128 */) { pitch = _pitch; speed = _speed; mouth = _mouth; throat = _throat; } //////////////////////////////////////////////////////////////////////////////////////////// // // STM32SAM setPitch (pitch) // //////////////////////////////////////////////////////////////////////////////////////////// void STM32SAM::setPitch(unsigned char _pitch /* = 64 */) { pitch = _pitch; } //////////////////////////////////////////////////////////////////////////////////////////// // // STM32SAM setSpeed (speed) // //////////////////////////////////////////////////////////////////////////////////////////// void STM32SAM::setSpeed(unsigned char _speed /* = 72 */) { speed = _speed; } //////////////////////////////////////////////////////////////////////////////////////////// // // STM32SAM setMouth (mouth) // //////////////////////////////////////////////////////////////////////////////////////////// void STM32SAM::setMouth(unsigned char _mouth /* = 128 */) { mouth = _mouth; } //////////////////////////////////////////////////////////////////////////////////////////// // // STM32SAM setThroat (throat) // //////////////////////////////////////////////////////////////////////////////////////////// void STM32SAM::setThroat(unsigned char _throat /* = 128 */) { throat = _throat; } //////////////////////////////////////////////////////////////////////////////////////////// // // Hardware // //////////////////////////////////////////////////////////////////////////////////////////// // Hardware specifics, for easier porting to other microcontrollers // // Set PA8 pin as PWM, at 256 timer ticks overflow (8bit resolution) #include #include #define FURI_HAL_SPEAKER_TIMER TIM16 #define FURI_HAL_SPEAKER_CHANNEL LL_TIM_CHANNEL_CH1 void STM32SAM::begin(void) { #ifdef USE_ROGER_CORE pinMode(PA8, PWM); // audio output pin Timer1.setPeriod( 4); // Can't set at 256 ticks, only in uS. First nearest uS is 4 (Roger core is only for bluepill, that means 72*4=288 ticks, or 128*4=512 ticks when overclocked. It's ok, just overall volume will be lower, because maximum volume will be 256/288 or 256/512) #endif #ifdef USE_STM32duino_CORE pinMode(PA8, OUTPUT); PWM->pause(); PWM->setMode(1, TIMER_OUTPUT_COMPARE_PWM1, PA8); // TIM1 CH1 (PA8) PWM->setPrescaleFactor(1); PWM->setOverflow(256, TICK_FORMAT); // 256 ticks overflow, no matter the CPU (timer) speed PWM->resume(); #endif LL_TIM_InitTypeDef TIM_InitStruct; memset(&TIM_InitStruct, 0, sizeof(LL_TIM_InitTypeDef)); TIM_InitStruct.Prescaler = 4; TIM_InitStruct.Autoreload = 255; LL_TIM_Init(FURI_HAL_SPEAKER_TIMER, &TIM_InitStruct); LL_TIM_OC_InitTypeDef TIM_OC_InitStruct; memset(&TIM_OC_InitStruct, 0, sizeof(LL_TIM_OC_InitTypeDef)); TIM_OC_InitStruct.OCMode = LL_TIM_OCMODE_PWM1; TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_ENABLE; TIM_OC_InitStruct.CompareValue = 127; LL_TIM_OC_Init(FURI_HAL_SPEAKER_TIMER, FURI_HAL_SPEAKER_CHANNEL, &TIM_OC_InitStruct); LL_TIM_EnableAllOutputs(FURI_HAL_SPEAKER_TIMER); LL_TIM_EnableCounter(FURI_HAL_SPEAKER_TIMER); } // begin inline void STM32SAM::SetAUDIO(unsigned char main_volume) { #ifdef USE_ROGER_CORE Timer1.setCompare(TIMER_CH1, main_volume); #endif #ifdef USE_STM32duino_CORE PWM->setCaptureCompare(1, main_volume, TICK_COMPARE_FORMAT); #endif // if(main_volume > 64) { // LL_TIM_OC_SetCompareCH1(FURI_HAL_SPEAKER_TIMER, 127); // } else { // LL_TIM_OC_SetCompareCH1(FURI_HAL_SPEAKER_TIMER, main_volume); // } float data = main_volume; data /= 255.0f; data -= 0.5f; data *= 4.0f; data = tanhf(data); data += 0.5f; data *= 255.0f; if(data < 0) { data = 0; } else if(data > 255) { data = 255; } LL_TIM_OC_SetCompareCH1(FURI_HAL_SPEAKER_TIMER, data); }