├── README.md ├── application.fam ├── icon.png ├── sam_app.cpp ├── stm32_sam.cpp └── stm32_sam.h /README.md: -------------------------------------------------------------------------------- 1 | - Type in a message and press the back button (or select save and press back at the text preview) 2 | - SAM will say the message and the app will exit. 3 | 4 | Made by combining code from the [caesarcipher (panki27)](https://github.com/panki27/caesar-cipher) and [SAM (ctoth)](https://github.com/ctoth/SAM) Flipper applications 5 | -------------------------------------------------------------------------------- /application.fam: -------------------------------------------------------------------------------- 1 | App( 2 | appid="text2sam", 3 | name="Text to SAM", 4 | apptype=FlipperAppType.EXTERNAL, 5 | entry_point="sam_app", 6 | cdefines=["APP_SAM"], 7 | # requires=["gui",], 8 | requires=[ 9 | "gui", 10 | "dialogs", 11 | ], 12 | stack_size=4 * 1024, 13 | # stack_size=2 * 1024, 14 | fap_icon="icon.png", 15 | fap_category="", 16 | order=20, 17 | ) 18 | -------------------------------------------------------------------------------- /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Round-Pi/flipperzero-text2sam/2917d02eaaa7d3d82173fec33a56af7d3d2692a9/icon.png -------------------------------------------------------------------------------- /sam_app.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "stm32_sam.h" 15 | 16 | #define TAG "SAM" 17 | #define SAM_SAVE_PATH EXT_PATH("sam.txt") 18 | #define TEXT_BUFFER_SIZE 256 19 | STM32SAM voice; 20 | 21 | typedef enum { 22 | EventTypeTick, 23 | EventTypeKey, 24 | } EventType; 25 | 26 | typedef struct { 27 | EventType type; 28 | InputEvent input; 29 | } PluginEvent; 30 | 31 | typedef struct { 32 | ViewDispatcher* view_dispatcher; 33 | TextInput* text_input; 34 | char input[TEXT_BUFFER_SIZE]; 35 | } AppState; 36 | 37 | AppState* app_state; 38 | 39 | static void say_something(char* something) { 40 | if(furi_hal_speaker_is_mine() || furi_hal_speaker_acquire(1000)) { 41 | voice.begin(); 42 | voice.say(something); 43 | furi_hal_speaker_release(); 44 | } 45 | } 46 | 47 | static void text_input_callback(void* ctx) { 48 | AppState* app_state = (AppState*)ctx; 49 | //FURI_LOG_D(TAG, "Input text: %s", app_state->input); 50 | 51 | // underscore_to_space(app_state->input); 52 | for(int i = 0; app_state->input[i] != '\0'; i++) { 53 | if(app_state->input[i] == '_') { 54 | app_state->input[i] = ' '; 55 | } 56 | } 57 | 58 | say_something(app_state->input); 59 | } 60 | 61 | static bool back_event_callback(void* ctx) { 62 | const AppState* app_state = (AppState*)ctx; 63 | view_dispatcher_stop(app_state->view_dispatcher); 64 | return true; 65 | } 66 | 67 | static void sam_state_init(AppState* const app_state) { 68 | app_state->view_dispatcher = view_dispatcher_alloc(); 69 | app_state->text_input = text_input_alloc(); 70 | } 71 | 72 | static void sam_state_free(AppState* const app_state) { 73 | text_input_free(app_state->text_input); 74 | view_dispatcher_remove_view(app_state->view_dispatcher, 0); 75 | view_dispatcher_free(app_state->view_dispatcher); 76 | free(app_state); 77 | } 78 | 79 | static void save_message(FuriString* save_string) { 80 | Storage* storage = (Storage*)furi_record_open(RECORD_STORAGE); 81 | File* file = storage_file_alloc(storage); 82 | if(storage_file_open(file, SAM_SAVE_PATH, FSAM_WRITE, FSOM_CREATE_ALWAYS)) { 83 | storage_file_write(file, save_string, TEXT_BUFFER_SIZE); 84 | } 85 | storage_file_close(file); 86 | storage_file_free(file); 87 | furi_record_close(RECORD_STORAGE); 88 | } 89 | 90 | static bool load_messages() { 91 | Storage* storage = (Storage*)furi_record_open(RECORD_STORAGE); 92 | File* file = storage_file_alloc(storage); 93 | uint16_t bytes_read = 0; 94 | if(storage_file_open(file, SAM_SAVE_PATH, FSAM_READ, FSOM_OPEN_EXISTING)) { 95 | bytes_read = storage_file_read(file, app_state->input, TEXT_BUFFER_SIZE); 96 | } 97 | storage_file_close(file); 98 | storage_file_free(file); 99 | furi_record_close(RECORD_STORAGE); 100 | return bytes_read == TEXT_BUFFER_SIZE; 101 | } 102 | 103 | extern "C" int32_t sam_app(void* p) { 104 | UNUSED(p); 105 | app_state = (AppState*)malloc(sizeof(AppState)); 106 | 107 | FURI_LOG_D(TAG, "Running sam_state_init"); 108 | sam_state_init(app_state); 109 | 110 | FURI_LOG_D(TAG, "Assigning text input callback"); 111 | 112 | load_messages(); 113 | text_input_set_result_callback( 114 | app_state->text_input, 115 | text_input_callback, 116 | app_state, 117 | app_state->input, 118 | TEXT_BUFFER_SIZE, 119 | false); //clear default text 120 | text_input_set_header_text(app_state->text_input, "Input"); 121 | 122 | Gui* gui = (Gui*)furi_record_open(RECORD_GUI); 123 | 124 | view_dispatcher_enable_queue(app_state->view_dispatcher); 125 | 126 | FURI_LOG_D(TAG, "Adding text input view to dispatcher"); 127 | view_dispatcher_add_view( 128 | app_state->view_dispatcher, 0, text_input_get_view(app_state->text_input)); 129 | 130 | FURI_LOG_D(TAG, "Attaching view dispatcher to GUI"); 131 | view_dispatcher_attach_to_gui(app_state->view_dispatcher, gui, ViewDispatcherTypeFullscreen); 132 | FURI_LOG_D(TAG, "starting view dispatcher"); 133 | view_dispatcher_set_navigation_event_callback(app_state->view_dispatcher, back_event_callback); 134 | view_dispatcher_set_event_callback_context(app_state->view_dispatcher, app_state); 135 | view_dispatcher_switch_to_view(app_state->view_dispatcher, 0); 136 | view_dispatcher_run(app_state->view_dispatcher); 137 | 138 | save_message((FuriString*)app_state->input); 139 | 140 | furi_record_close(RECORD_GUI); 141 | sam_state_free(app_state); 142 | 143 | return 0; 144 | } 145 | -------------------------------------------------------------------------------- /stm32_sam.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "stm32_sam.h" 3 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | 5 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 6 | 7 | //////////////////////////////////////////////////////////////////////////////////////////// 8 | // 9 | // All 10 | // 11 | //////////////////////////////////////////////////////////////////////////////////////////// 12 | 13 | char input[256 + 1] = {0}; //tab39445 14 | //standard sam sound 15 | 16 | unsigned char wait1 = 7; 17 | unsigned char wait2 = 6; 18 | 19 | unsigned char A, X, Y; 20 | unsigned char mem44; 21 | unsigned char mem47; 22 | unsigned char mem49; 23 | unsigned char mem39; 24 | unsigned char mem50; 25 | unsigned char mem51; 26 | unsigned char mem53; 27 | unsigned char mem56; 28 | unsigned char mem59 = 0; 29 | 30 | unsigned char phonemeIndexOutput[60]; //tab47296 31 | unsigned char stressOutput[60]; //tab47365 32 | unsigned char phonemeLengthOutput[60]; //tab47416 33 | 34 | // contains the soundbuffer position 35 | int bufferpos; 36 | 37 | //////////////////////////////////////////////////////////////////////////////////////////// 38 | // 39 | // Sam Tabs 40 | // 41 | //////////////////////////////////////////////////////////////////////////////////////////// 42 | 43 | //tab40672 44 | const unsigned char stressInputTable[] = {'*', '1', '2', '3', '4', '5', '6', '7', '8'}; 45 | 46 | //tab40682 47 | const unsigned char signInputTable1[] = { 48 | ' ', '.', '?', ',', '-', 'I', 'I', 'E', 'A', 'A', 'A', 'A', 'U', 'A', 'I', 'E', 'U', 49 | 'O', 'R', 'L', 'W', 'Y', 'W', 'R', 'L', 'W', 'Y', 'M', 'N', 'N', 'D', 'Q', 'S', 'S', 50 | 'F', 'T', '/', '/', 'Z', 'Z', 'V', 'D', 'C', '*', 'J', '*', '*', '*', 'E', 'A', 'O', 51 | 'A', 'O', 'U', 'B', '*', '*', 'D', '*', '*', 'G', '*', '*', 'G', '*', '*', 'P', '*', 52 | '*', 'T', '*', '*', 'K', '*', '*', 'K', '*', '*', 'U', 'U', 'U'}; 53 | 54 | //tab40763 55 | const unsigned char signInputTable2[] = { 56 | '*', '*', '*', '*', '*', 'Y', 'H', 'H', 'E', 'A', 'H', 'O', 'H', 'X', 'X', 'R', 'X', 57 | 'H', 'X', 'X', 'X', 'X', 'H', '*', '*', '*', '*', '*', '*', 'X', 'X', '*', '*', 'H', 58 | '*', 'H', 'H', 'X', '*', 'H', '*', 'H', 'H', '*', '*', '*', '*', '*', 'Y', 'Y', 'Y', 59 | 'W', 'W', 'W', '*', '*', '*', '*', '*', '*', '*', '*', '*', 'X', '*', '*', '*', '*', 60 | '*', '*', '*', '*', '*', '*', '*', 'X', '*', '*', 'L', 'M', 'N'}; 61 | 62 | //loc_9F8C 63 | const unsigned char flags[] = { 64 | 0x00, 0x00, 0x00, 0x00, 0x00, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0x84, 0x84, 0xA4, 65 | 0xA4, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x44, 0x44, 0x44, 0x44, 0x44, 0x4C, 66 | 0x4C, 0x4C, 0x48, 0x4C, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x44, 0x44, 0x44, 0x44, 67 | 0x48, 0x40, 0x4C, 0x44, 0x00, 0x00, 0xB4, 0xB4, 0xB4, 0x94, 0x94, 0x94, 0x4E, 0x4E, 68 | 0x4E, 0x4E, 0x4E, 0x4E, 0x4E, 0x4E, 0x4E, 0x4E, 0x4E, 0x4E, 0x4B, 0x4B, 0x4B, 0x4B, 69 | 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x80, 0xC1, 0xC1 70 | 71 | }; 72 | 73 | //??? flags overlap flags2 74 | //loc_9FDA 75 | const unsigned char flags2[] = { 76 | 0x80, 0xC1, 0xC1, 0xC1, 0xC1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 77 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x08, 0x0C, 0x08, 0x04, 0x40, 78 | 0x24, 0x20, 0x20, 0x24, 0x00, 0x00, 0x24, 0x20, 0x20, 0x24, 0x20, 0x20, 0x00, 0x20, 0x00, 0x00, 79 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 80 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 81 | 82 | //tab45616??? 83 | const unsigned char phonemeStressedLengthTable[] = { 84 | 0x00, 0x12, 0x12, 0x12, 8, 0xB, 9, 0xB, 0xE, 0xF, 0xB, 0x10, 0xC, 6, 6, 0xE, 85 | 0xC, 0xE, 0xC, 0xB, 8, 8, 0xB, 0xA, 9, 8, 8, 8, 8, 8, 3, 5, 86 | 2, 2, 2, 2, 2, 2, 6, 6, 8, 6, 6, 2, 9, 4, 2, 1, 87 | 0xE, 0xF, 0xF, 0xF, 0xE, 0xE, 8, 2, 2, 7, 2, 1, 7, 2, 2, 7, 88 | 2, 2, 8, 2, 2, 6, 2, 2, 7, 2, 4, 7, 1, 4, 5, 5}; 89 | 90 | //tab45536??? 91 | const unsigned char phonemeLengthTable[] = { 92 | 0, 0x12, 0x12, 0x12, 8, 8, 8, 8, 8, 0xB, 6, 0xC, 0xA, 5, 5, 0xB, 0xA, 0xA, 0xA, 9, 93 | 8, 7, 9, 7, 6, 8, 6, 7, 7, 7, 2, 5, 2, 2, 2, 2, 2, 2, 6, 6, 94 | 7, 6, 6, 2, 8, 3, 1, 0x1E, 0xD, 0xC, 0xC, 0xC, 0xE, 9, 6, 1, 2, 5, 1, 1, 95 | 6, 1, 2, 6, 1, 2, 8, 2, 2, 4, 2, 2, 6, 1, 4, 6, 1, 4, 0xC7, 0xFF}; 96 | 97 | /* 98 | 99 | Ind | phoneme | flags | 100 | -----|---------|----------| 101 | 0 | * | 00000000 | 102 | 1 | .* | 00000000 | 103 | 2 | ?* | 00000000 | 104 | 3 | ,* | 00000000 | 105 | 4 | -* | 00000000 | 106 | 107 | VOWELS 108 | 5 | IY | 10100100 | 109 | 6 | IH | 10100100 | 110 | 7 | EH | 10100100 | 111 | 8 | AE | 10100100 | 112 | 9 | AA | 10100100 | 113 | 10 | AH | 10100100 | 114 | 11 | AO | 10000100 | 115 | 17 | OH | 10000100 | 116 | 12 | UH | 10000100 | 117 | 16 | UX | 10000100 | 118 | 15 | ER | 10000100 | 119 | 13 | AX | 10100100 | 120 | 14 | IX | 10100100 | 121 | 122 | DIPHTONGS 123 | 48 | EY | 10110100 | 124 | 49 | AY | 10110100 | 125 | 50 | OY | 10110100 | 126 | 51 | AW | 10010100 | 127 | 52 | OW | 10010100 | 128 | 53 | UW | 10010100 | 129 | 130 | 131 | 21 | YX | 10000100 | 132 | 20 | WX | 10000100 | 133 | 18 | RX | 10000100 | 134 | 19 | LX | 10000100 | 135 | 37 | /X | 01000000 | 136 | 30 | DX | 01001000 | 137 | 138 | 139 | 22 | WH | 01000100 | 140 | 141 | 142 | VOICED CONSONANTS 143 | 23 | R* | 01000100 | 144 | 24 | L* | 01000100 | 145 | 25 | W* | 01000100 | 146 | 26 | Y* | 01000100 | 147 | 27 | M* | 01001100 | 148 | 28 | N* | 01001100 | 149 | 29 | NX | 01001100 | 150 | 54 | B* | 01001110 | 151 | 57 | D* | 01001110 | 152 | 60 | G* | 01001110 | 153 | 44 | J* | 01001100 | 154 | 38 | Z* | 01000100 | 155 | 39 | ZH | 01000100 | 156 | 40 | V* | 01000100 | 157 | 41 | DH | 01000100 | 158 | 159 | unvoiced CONSONANTS 160 | 32 | S* | 01000000 | 161 | 33 | SH | 01000000 | 162 | 34 | F* | 01000000 | 163 | 35 | TH | 01000000 | 164 | 66 | P* | 01001011 | 165 | 69 | T* | 01001011 | 166 | 72 | K* | 01001011 | 167 | 42 | CH | 01001000 | 168 | 36 | /H | 01000000 | 169 | 170 | 43 | ** | 01000000 | 171 | 45 | ** | 01000100 | 172 | 46 | ** | 00000000 | 173 | 47 | ** | 00000000 | 174 | 175 | 176 | 55 | ** | 01001110 | 177 | 56 | ** | 01001110 | 178 | 58 | ** | 01001110 | 179 | 59 | ** | 01001110 | 180 | 61 | ** | 01001110 | 181 | 62 | ** | 01001110 | 182 | 63 | GX | 01001110 | 183 | 64 | ** | 01001110 | 184 | 65 | ** | 01001110 | 185 | 67 | ** | 01001011 | 186 | 68 | ** | 01001011 | 187 | 70 | ** | 01001011 | 188 | 71 | ** | 01001011 | 189 | 73 | ** | 01001011 | 190 | 74 | ** | 01001011 | 191 | 75 | KX | 01001011 | 192 | 76 | ** | 01001011 | 193 | 77 | ** | 01001011 | 194 | 195 | 196 | SPECIAL 197 | 78 | UL | 10000000 | 198 | 79 | UM | 11000001 | 199 | 80 | UN | 11000001 | 200 | 31 | Q* | 01001100 | 201 | 202 | */ 203 | 204 | //////////////////////////////////////////////////////////////////////////////////////////// 205 | // 206 | // RenderTabs 207 | // 208 | //////////////////////////////////////////////////////////////////////////////////////////// 209 | 210 | const unsigned char tab48426[5] = {0x18, 0x1A, 0x17, 0x17, 0x17}; 211 | 212 | const unsigned char tab47492[] = {0, 0, 0xE0, 0xE6, 0xEC, 0xF3, 0xF9, 0, 6, 0xC, 6}; 213 | 214 | const unsigned char amplitudeRescale[] = { 215 | 0, 216 | 1, 217 | 2, 218 | 2, 219 | 2, 220 | 3, 221 | 3, 222 | 4, 223 | 4, 224 | 5, 225 | 6, 226 | 8, 227 | 9, 228 | 0xB, 229 | 0xD, 230 | 0xF, 231 | 0 //17 elements? 232 | }; 233 | 234 | // Used to decide which phoneme's blend lengths. The candidate with the lower score is selected. 235 | // tab45856 236 | const unsigned char blendRank[] = {0, 0x1F, 0x1F, 0x1F, 0x1F, 2, 2, 2, 2, 2, 237 | 2, 2, 2, 2, 5, 5, 2, 0xA, 2, 8, 238 | 5, 5, 0xB, 0xA, 9, 8, 8, 0xA0, 8, 8, 239 | 0x17, 0x1F, 0x12, 0x12, 0x12, 0x12, 0x1E, 0x1E, 0x14, 0x14, 240 | 0x14, 0x14, 0x17, 0x17, 0x1A, 0x1A, 0x1D, 0x1D, 2, 2, 241 | 2, 2, 2, 2, 0x1A, 0x1D, 0x1B, 0x1A, 0x1D, 0x1B, 242 | 0x1A, 0x1D, 0x1B, 0x1A, 0x1D, 0x1B, 0x17, 0x1D, 0x17, 0x17, 243 | 0x1D, 0x17, 0x17, 0x1D, 0x17, 0x17, 0x1D, 0x17, 0x17, 0x17}; 244 | 245 | // Number of frames at the end of a phoneme devoted to interpolating to next phoneme's final value 246 | //tab45696 247 | const unsigned char outBlendLength[] = {0, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 248 | 4, 4, 3, 2, 4, 4, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 249 | 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 0, 1, 0, 1, 0, 5, 250 | 5, 5, 5, 5, 4, 4, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 251 | 0, 1, 2, 0, 2, 2, 0, 1, 3, 0, 2, 3, 0, 2, 0xA0, 0xA0}; 252 | 253 | // Number of frames at beginning of a phoneme devoted to interpolating to phoneme's final value 254 | // tab45776 255 | const unsigned char inBlendLength[] = {0, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 256 | 4, 4, 3, 3, 4, 4, 3, 3, 3, 3, 3, 1, 2, 3, 2, 1, 257 | 3, 3, 3, 3, 1, 1, 3, 3, 3, 2, 2, 3, 2, 3, 0, 0, 258 | 5, 5, 5, 5, 4, 4, 2, 0, 2, 2, 0, 3, 2, 0, 4, 2, 259 | 0, 3, 2, 0, 2, 2, 0, 2, 3, 0, 3, 3, 0, 3, 0xB0, 0xA0}; 260 | 261 | // Looks like it's used as bit flags 262 | // High bits masked by 248 (11111000) 263 | // 264 | // 32: S* 241 11110001 265 | // 33: SH 226 11100010 266 | // 34: F* 211 11010011 267 | // 35: TH 187 10111011 268 | // 36: /H 124 01111100 269 | // 37: /X 149 10010101 270 | // 38: Z* 1 00000001 271 | // 39: ZH 2 00000010 272 | // 40: V* 3 00000011 273 | // 41: DH 3 00000011 274 | // 43: ** 114 01110010 275 | // 45: ** 2 00000010 276 | // 67: ** 27 00011011 277 | // 70: ** 25 00011001 278 | // tab45936 279 | const unsigned char sampledConsonantFlags[] = { 280 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 281 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xF1, 0xE2, 0xD3, 0xBB, 0x7C, 0x95, 1, 2, 282 | 3, 3, 0, 0x72, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 283 | 0, 0, 0, 0, 0, 0, 0, 0x1B, 0, 0, 0x19, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 284 | 285 | //tab45056 286 | unsigned char freq1data[] = { 287 | 0x00, 0x13, 0x13, 0x13, 0x13, 0xA, 0xE, 0x12, 0x18, 0x1A, 0x16, 0x14, 0x10, 0x14, 0xE, 0x12, 288 | 0xE, 0x12, 0x12, 0x10, 0xC, 0xE, 0xA, 0x12, 0xE, 0xA, 8, 6, 6, 6, 6, 0x11, 289 | 6, 6, 6, 6, 0xE, 0x10, 9, 0xA, 8, 0xA, 6, 6, 6, 5, 6, 0, 290 | 0x12, 0x1A, 0x14, 0x1A, 0x12, 0xC, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 291 | 6, 6, 6, 6, 6, 6, 6, 6, 6, 0xA, 0xA, 6, 6, 6, 0x2C, 0x13}; 292 | 293 | //tab451356 294 | unsigned char freq2data[] = {0x00, 0x43, 0x43, 0x43, 0x43, 0x54, 0x48, 0x42, 0x3E, 0x28, 295 | 0x2C, 0x1E, 0x24, 0x2C, 0x48, 0x30, 0x24, 0x1E, 0x32, 0x24, 296 | 0x1C, 0x44, 0x18, 0x32, 0x1E, 0x18, 0x52, 0x2E, 0x36, 0x56, 297 | 0x36, 0x43, 0x49, 0x4F, 0x1A, 0x42, 0x49, 0x25, 0x33, 0x42, 298 | 0x28, 0x2F, 0x4F, 0x4F, 0x42, 0x4F, 0x6E, 0x00, 0x48, 0x26, 299 | 0x1E, 0x2A, 0x1E, 0x22, 0x1A, 0x1A, 0x1A, 0x42, 0x42, 0x42, 300 | 0x6E, 0x6E, 0x6E, 0x54, 0x54, 0x54, 0x1A, 0x1A, 0x1A, 0x42, 301 | 0x42, 0x42, 0x6D, 0x56, 0x6D, 0x54, 0x54, 0x54, 0x7F, 0x7F}; 302 | //tab45216 303 | unsigned char freq3data[] = {0x00, 0x5B, 0x5B, 0x5B, 0x5B, 0x6E, 0x5D, 0x5B, 0x58, 0x59, 304 | 0x57, 0x58, 0x52, 0x59, 0x5D, 0x3E, 0x52, 0x58, 0x3E, 0x6E, 305 | 0x50, 0x5D, 0x5A, 0x3C, 0x6E, 0x5A, 0x6E, 0x51, 0x79, 0x65, 306 | 0x79, 0x5B, 0x63, 0x6A, 0x51, 0x79, 0x5D, 0x52, 0x5D, 0x67, 307 | 0x4C, 0x5D, 0x65, 0x65, 0x79, 0x65, 0x79, 0x00, 0x5A, 0x58, 308 | 0x58, 0x58, 0x58, 0x52, 0x51, 0x51, 0x51, 0x79, 0x79, 0x79, 309 | 0x70, 0x6E, 0x6E, 0x5E, 0x5E, 0x5E, 0x51, 0x51, 0x51, 0x79, 310 | 0x79, 0x79, 0x65, 0x65, 0x70, 0x5E, 0x5E, 0x5E, 0x08, 0x01}; 311 | 312 | //////////////////////////////////////////////////////////////////////////////////////////// 313 | // 314 | // Reciter 315 | // 316 | //////////////////////////////////////////////////////////////////////////////////////////// 317 | 318 | unsigned char inputtemp[256]; // secure copy of input tab36096 319 | 320 | //////////////////////////////////////////////////////////////////////////////////////////// 321 | // 322 | // Render 323 | // 324 | //////////////////////////////////////////////////////////////////////////////////////////// 325 | 326 | //timetable for more accurate c64 simulation 327 | int timetable[5][5] = { 328 | {162, 167, 167, 127, 128}, 329 | {226, 60, 60, 0, 0}, 330 | {225, 60, 59, 0, 0}, 331 | {200, 0, 0, 54, 55}, 332 | {199, 0, 0, 54, 54}}; 333 | 334 | unsigned oldtimetableindex; 335 | 336 | const unsigned char ampl1data[] = {0, 0, 0, 0, 0, 0xD, 0xD, 0xE, 0xF, 0xF, 0xF, 0xF, 337 | 0xF, 0xC, 0xD, 0xC, 0xF, 0xF, 0xD, 0xD, 0xD, 0xE, 0xD, 0xC, 338 | 0xD, 0xD, 0xD, 0xC, 9, 9, 0, 0, 0, 0, 0, 0, 339 | 0, 0, 0xB, 0xB, 0xB, 0xB, 0, 0, 1, 0xB, 0, 2, 340 | 0xE, 0xF, 0xF, 0xF, 0xF, 0xD, 2, 4, 0, 2, 4, 0, 341 | 1, 4, 0, 1, 4, 0, 0, 0, 0, 0, 0, 0, 342 | 0, 0xC, 0, 0, 0, 0, 0xF, 0xF}; 343 | 344 | const unsigned char ampl2data[] = { 345 | 0, 0, 0, 0, 0, 0xA, 0xB, 0xD, 0xE, 0xD, 0xC, 0xC, 0xB, 9, 0xB, 0xB, 0xC, 0xC, 0xC, 8, 346 | 8, 0xC, 8, 0xA, 8, 8, 0xA, 3, 9, 6, 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 347 | 3, 4, 0, 0, 0, 5, 0xA, 2, 0xE, 0xD, 0xC, 0xD, 0xC, 8, 0, 1, 0, 0, 1, 0, 348 | 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0xA, 0, 0, 0xA, 0, 0, 0}; 349 | 350 | const unsigned char ampl3data[] = {0, 0, 0, 0, 0, 8, 7, 8, 8, 1, 1, 0, 1, 0, 7, 5, 351 | 1, 0, 6, 1, 0, 7, 0, 5, 1, 0, 8, 0, 0, 3, 0, 0, 352 | 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0xE, 1, 353 | 9, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 354 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 5, 0, 0x13, 0x10}; 355 | 356 | //tab42240 357 | const signed char sinus[256] = { 358 | 0, 3, 6, 9, 12, 16, 19, 22, 25, 28, 31, 34, 37, 40, 43, 46, 359 | 49, 51, 54, 57, 60, 63, 65, 68, 71, 73, 76, 78, 81, 83, 85, 88, 360 | 90, 92, 94, 96, 98, 100, 102, 104, 106, 107, 109, 111, 112, 113, 115, 116, 361 | 117, 118, 120, 121, 122, 122, 123, 124, 125, 125, 126, 126, 126, 127, 127, 127, 362 | 127, 127, 127, 127, 126, 126, 126, 125, 125, 124, 123, 122, 122, 121, 120, 118, 363 | 117, 116, 115, 113, 112, 111, 109, 107, 106, 104, 102, 100, 98, 96, 94, 92, 364 | 90, 88, 85, 83, 81, 78, 76, 73, 71, 68, 65, 63, 60, 57, 54, 51, 365 | 49, 46, 43, 40, 37, 34, 31, 28, 25, 22, 19, 16, 12, 9, 6, 3, 366 | 0, -3, -6, -9, -12, -16, -19, -22, -25, -28, -31, -34, -37, -40, -43, -46, 367 | -49, -51, -54, -57, -60, -63, -65, -68, -71, -73, -76, -78, -81, -83, -85, -88, 368 | -90, -92, -94, -96, -98, -100, -102, -104, -106, -107, -109, -111, -112, -113, -115, -116, 369 | -117, -118, -120, -121, -122, -122, -123, -124, -125, -125, -126, -126, -126, -127, -127, -127, 370 | -127, -127, -127, -127, -126, -126, -126, -125, -125, -124, -123, -122, -122, -121, -120, -118, 371 | -117, -116, -115, -113, -112, -111, -109, -107, -106, -104, -102, -100, -98, -96, -94, -92, 372 | -90, -88, -85, -83, -81, -78, -76, -73, -71, -68, -65, -63, -60, -57, -54, -51, 373 | -49, -46, -43, -40, -37, -34, -31, -28, -25, -22, -19, -16, -12, -9, -6, -3}; 374 | 375 | //tab42496 376 | const unsigned char rectangle[] = { 377 | 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 378 | 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 379 | 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 380 | 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 381 | 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 382 | 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 383 | 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 384 | 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 385 | 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 386 | 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 387 | 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 388 | 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 389 | 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 390 | 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 391 | 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 392 | 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 393 | 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 394 | 0x70}; 395 | 396 | //random data ? 397 | const unsigned char sampleTable[0x500] = { 398 | //00 399 | 400 | 0x38, 401 | 0x84, 402 | 0x6B, 403 | 0x19, 404 | 0xC6, 405 | 0x63, 406 | 0x18, 407 | 0x86, 408 | 0x73, 409 | 0x98, 410 | 0xC6, 411 | 0xB1, 412 | 0x1C, 413 | 0xCA, 414 | 0x31, 415 | 0x8C, 416 | 0xC7, 417 | 0x31, 418 | 0x88, 419 | 0xC2, 420 | 0x30, 421 | 0x98, 422 | 0x46, 423 | 0x31, 424 | 0x18, 425 | 0xC6, 426 | 0x35, 427 | 0xC, 428 | 0xCA, 429 | 0x31, 430 | 0xC, 431 | 0xC6 432 | //20 433 | , 434 | 0x21, 435 | 0x10, 436 | 0x24, 437 | 0x69, 438 | 0x12, 439 | 0xC2, 440 | 0x31, 441 | 0x14, 442 | 0xC4, 443 | 0x71, 444 | 8, 445 | 0x4A, 446 | 0x22, 447 | 0x49, 448 | 0xAB, 449 | 0x6A, 450 | 0xA8, 451 | 0xAC, 452 | 0x49, 453 | 0x51, 454 | 0x32, 455 | 0xD5, 456 | 0x52, 457 | 0x88, 458 | 0x93, 459 | 0x6C, 460 | 0x94, 461 | 0x22, 462 | 0x15, 463 | 0x54, 464 | 0xD2, 465 | 0x25 466 | //40 467 | , 468 | 0x96, 469 | 0xD4, 470 | 0x50, 471 | 0xA5, 472 | 0x46, 473 | 0x21, 474 | 8, 475 | 0x85, 476 | 0x6B, 477 | 0x18, 478 | 0xC4, 479 | 0x63, 480 | 0x10, 481 | 0xCE, 482 | 0x6B, 483 | 0x18, 484 | 0x8C, 485 | 0x71, 486 | 0x19, 487 | 0x8C, 488 | 0x63, 489 | 0x35, 490 | 0xC, 491 | 0xC6, 492 | 0x33, 493 | 0x99, 494 | 0xCC, 495 | 0x6C, 496 | 0xB5, 497 | 0x4E, 498 | 0xA2, 499 | 0x99 500 | //60 501 | , 502 | 0x46, 503 | 0x21, 504 | 0x28, 505 | 0x82, 506 | 0x95, 507 | 0x2E, 508 | 0xE3, 509 | 0x30, 510 | 0x9C, 511 | 0xC5, 512 | 0x30, 513 | 0x9C, 514 | 0xA2, 515 | 0xB1, 516 | 0x9C, 517 | 0x67, 518 | 0x31, 519 | 0x88, 520 | 0x66, 521 | 0x59, 522 | 0x2C, 523 | 0x53, 524 | 0x18, 525 | 0x84, 526 | 0x67, 527 | 0x50, 528 | 0xCA, 529 | 0xE3, 530 | 0xA, 531 | 0xAC, 532 | 0xAB, 533 | 0x30 534 | //80 535 | , 536 | 0xAC, 537 | 0x62, 538 | 0x30, 539 | 0x8C, 540 | 0x63, 541 | 0x10, 542 | 0x94, 543 | 0x62, 544 | 0xB1, 545 | 0x8C, 546 | 0x82, 547 | 0x28, 548 | 0x96, 549 | 0x33, 550 | 0x98, 551 | 0xD6, 552 | 0xB5, 553 | 0x4C, 554 | 0x62, 555 | 0x29, 556 | 0xA5, 557 | 0x4A, 558 | 0xB5, 559 | 0x9C, 560 | 0xC6, 561 | 0x31, 562 | 0x14, 563 | 0xD6, 564 | 0x38, 565 | 0x9C, 566 | 0x4B, 567 | 0xB4 568 | //A0 569 | , 570 | 0x86, 571 | 0x65, 572 | 0x18, 573 | 0xAE, 574 | 0x67, 575 | 0x1C, 576 | 0xA6, 577 | 0x63, 578 | 0x19, 579 | 0x96, 580 | 0x23, 581 | 0x19, 582 | 0x84, 583 | 0x13, 584 | 8, 585 | 0xA6, 586 | 0x52, 587 | 0xAC, 588 | 0xCA, 589 | 0x22, 590 | 0x89, 591 | 0x6E, 592 | 0xAB, 593 | 0x19, 594 | 0x8C, 595 | 0x62, 596 | 0x34, 597 | 0xC4, 598 | 0x62, 599 | 0x19, 600 | 0x86, 601 | 0x63 602 | //C0 603 | , 604 | 0x18, 605 | 0xC4, 606 | 0x23, 607 | 0x58, 608 | 0xD6, 609 | 0xA3, 610 | 0x50, 611 | 0x42, 612 | 0x54, 613 | 0x4A, 614 | 0xAD, 615 | 0x4A, 616 | 0x25, 617 | 0x11, 618 | 0x6B, 619 | 0x64, 620 | 0x89, 621 | 0x4A, 622 | 0x63, 623 | 0x39, 624 | 0x8A, 625 | 0x23, 626 | 0x31, 627 | 0x2A, 628 | 0xEA, 629 | 0xA2, 630 | 0xA9, 631 | 0x44, 632 | 0xC5, 633 | 0x12, 634 | 0xCD, 635 | 0x42 636 | //E0 637 | , 638 | 0x34, 639 | 0x8C, 640 | 0x62, 641 | 0x18, 642 | 0x8C, 643 | 0x63, 644 | 0x11, 645 | 0x48, 646 | 0x66, 647 | 0x31, 648 | 0x9D, 649 | 0x44, 650 | 0x33, 651 | 0x1D, 652 | 0x46, 653 | 0x31, 654 | 0x9C, 655 | 0xC6, 656 | 0xB1, 657 | 0xC, 658 | 0xCD, 659 | 0x32, 660 | 0x88, 661 | 0xC4, 662 | 0x73, 663 | 0x18, 664 | 0x86, 665 | 0x73, 666 | 8, 667 | 0xD6, 668 | 0x63, 669 | 0x58 670 | //100 671 | , 672 | 7, 673 | 0x81, 674 | 0xE0, 675 | 0xF0, 676 | 0x3C, 677 | 7, 678 | 0x87, 679 | 0x90, 680 | 0x3C, 681 | 0x7C, 682 | 0xF, 683 | 0xC7, 684 | 0xC0, 685 | 0xC0, 686 | 0xF0, 687 | 0x7C, 688 | 0x1E, 689 | 7, 690 | 0x80, 691 | 0x80, 692 | 0, 693 | 0x1C, 694 | 0x78, 695 | 0x70, 696 | 0xF1, 697 | 0xC7, 698 | 0x1F, 699 | 0xC0, 700 | 0xC, 701 | 0xFE, 702 | 0x1C, 703 | 0x1F 704 | //120 705 | , 706 | 0x1F, 707 | 0xE, 708 | 0xA, 709 | 0x7A, 710 | 0xC0, 711 | 0x71, 712 | 0xF2, 713 | 0x83, 714 | 0x8F, 715 | 3, 716 | 0xF, 717 | 0xF, 718 | 0xC, 719 | 0, 720 | 0x79, 721 | 0xF8, 722 | 0x61, 723 | 0xE0, 724 | 0x43, 725 | 0xF, 726 | 0x83, 727 | 0xE7, 728 | 0x18, 729 | 0xF9, 730 | 0xC1, 731 | 0x13, 732 | 0xDA, 733 | 0xE9, 734 | 0x63, 735 | 0x8F, 736 | 0xF, 737 | 0x83 738 | //140 739 | , 740 | 0x83, 741 | 0x87, 742 | 0xC3, 743 | 0x1F, 744 | 0x3C, 745 | 0x70, 746 | 0xF0, 747 | 0xE1, 748 | 0xE1, 749 | 0xE3, 750 | 0x87, 751 | 0xB8, 752 | 0x71, 753 | 0xE, 754 | 0x20, 755 | 0xE3, 756 | 0x8D, 757 | 0x48, 758 | 0x78, 759 | 0x1C, 760 | 0x93, 761 | 0x87, 762 | 0x30, 763 | 0xE1, 764 | 0xC1, 765 | 0xC1, 766 | 0xE4, 767 | 0x78, 768 | 0x21, 769 | 0x83, 770 | 0x83, 771 | 0xC3 772 | //160 773 | , 774 | 0x87, 775 | 6, 776 | 0x39, 777 | 0xE5, 778 | 0xC3, 779 | 0x87, 780 | 7, 781 | 0xE, 782 | 0x1C, 783 | 0x1C, 784 | 0x70, 785 | 0xF4, 786 | 0x71, 787 | 0x9C, 788 | 0x60, 789 | 0x36, 790 | 0x32, 791 | 0xC3, 792 | 0x1E, 793 | 0x3C, 794 | 0xF3, 795 | 0x8F, 796 | 0xE, 797 | 0x3C, 798 | 0x70, 799 | 0xE3, 800 | 0xC7, 801 | 0x8F, 802 | 0xF, 803 | 0xF, 804 | 0xE, 805 | 0x3C 806 | //180 807 | , 808 | 0x78, 809 | 0xF0, 810 | 0xE3, 811 | 0x87, 812 | 6, 813 | 0xF0, 814 | 0xE3, 815 | 7, 816 | 0xC1, 817 | 0x99, 818 | 0x87, 819 | 0xF, 820 | 0x18, 821 | 0x78, 822 | 0x70, 823 | 0x70, 824 | 0xFC, 825 | 0xF3, 826 | 0x10, 827 | 0xB1, 828 | 0x8C, 829 | 0x8C, 830 | 0x31, 831 | 0x7C, 832 | 0x70, 833 | 0xE1, 834 | 0x86, 835 | 0x3C, 836 | 0x64, 837 | 0x6C, 838 | 0xB0, 839 | 0xE1 840 | //1A0 841 | , 842 | 0xE3, 843 | 0xF, 844 | 0x23, 845 | 0x8F, 846 | 0xF, 847 | 0x1E, 848 | 0x3E, 849 | 0x38, 850 | 0x3C, 851 | 0x38, 852 | 0x7B, 853 | 0x8F, 854 | 7, 855 | 0xE, 856 | 0x3C, 857 | 0xF4, 858 | 0x17, 859 | 0x1E, 860 | 0x3C, 861 | 0x78, 862 | 0xF2, 863 | 0x9E, 864 | 0x72, 865 | 0x49, 866 | 0xE3, 867 | 0x25, 868 | 0x36, 869 | 0x38, 870 | 0x58, 871 | 0x39, 872 | 0xE2, 873 | 0xDE 874 | //1C0 875 | , 876 | 0x3C, 877 | 0x78, 878 | 0x78, 879 | 0xE1, 880 | 0xC7, 881 | 0x61, 882 | 0xE1, 883 | 0xE1, 884 | 0xB0, 885 | 0xF0, 886 | 0xF0, 887 | 0xC3, 888 | 0xC7, 889 | 0xE, 890 | 0x38, 891 | 0xC0, 892 | 0xF0, 893 | 0xCE, 894 | 0x73, 895 | 0x73, 896 | 0x18, 897 | 0x34, 898 | 0xB0, 899 | 0xE1, 900 | 0xC7, 901 | 0x8E, 902 | 0x1C, 903 | 0x3C, 904 | 0xF8, 905 | 0x38, 906 | 0xF0, 907 | 0xE1 908 | //1E0 909 | , 910 | 0xC1, 911 | 0x8B, 912 | 0x86, 913 | 0x8F, 914 | 0x1C, 915 | 0x78, 916 | 0x70, 917 | 0xF0, 918 | 0x78, 919 | 0xAC, 920 | 0xB1, 921 | 0x8F, 922 | 0x39, 923 | 0x31, 924 | 0xDB, 925 | 0x38, 926 | 0x61, 927 | 0xC3, 928 | 0xE, 929 | 0xE, 930 | 0x38, 931 | 0x78, 932 | 0x73, 933 | 0x17, 934 | 0x1E, 935 | 0x39, 936 | 0x1E, 937 | 0x38, 938 | 0x64, 939 | 0xE1, 940 | 0xF1, 941 | 0xC1 942 | //200 943 | , 944 | 0x4E, 945 | 0xF, 946 | 0x40, 947 | 0xA2, 948 | 2, 949 | 0xC5, 950 | 0x8F, 951 | 0x81, 952 | 0xA1, 953 | 0xFC, 954 | 0x12, 955 | 8, 956 | 0x64, 957 | 0xE0, 958 | 0x3C, 959 | 0x22, 960 | 0xE0, 961 | 0x45, 962 | 7, 963 | 0x8E, 964 | 0xC, 965 | 0x32, 966 | 0x90, 967 | 0xF0, 968 | 0x1F, 969 | 0x20, 970 | 0x49, 971 | 0xE0, 972 | 0xF8, 973 | 0xC, 974 | 0x60, 975 | 0xF0 976 | //220 977 | , 978 | 0x17, 979 | 0x1A, 980 | 0x41, 981 | 0xAA, 982 | 0xA4, 983 | 0xD0, 984 | 0x8D, 985 | 0x12, 986 | 0x82, 987 | 0x1E, 988 | 0x1E, 989 | 3, 990 | 0xF8, 991 | 0x3E, 992 | 3, 993 | 0xC, 994 | 0x73, 995 | 0x80, 996 | 0x70, 997 | 0x44, 998 | 0x26, 999 | 3, 1000 | 0x24, 1001 | 0xE1, 1002 | 0x3E, 1003 | 4, 1004 | 0x4E, 1005 | 4, 1006 | 0x1C, 1007 | 0xC1, 1008 | 9, 1009 | 0xCC 1010 | //240 1011 | , 1012 | 0x9E, 1013 | 0x90, 1014 | 0x21, 1015 | 7, 1016 | 0x90, 1017 | 0x43, 1018 | 0x64, 1019 | 0xC0, 1020 | 0xF, 1021 | 0xC6, 1022 | 0x90, 1023 | 0x9C, 1024 | 0xC1, 1025 | 0x5B, 1026 | 3, 1027 | 0xE2, 1028 | 0x1D, 1029 | 0x81, 1030 | 0xE0, 1031 | 0x5E, 1032 | 0x1D, 1033 | 3, 1034 | 0x84, 1035 | 0xB8, 1036 | 0x2C, 1037 | 0xF, 1038 | 0x80, 1039 | 0xB1, 1040 | 0x83, 1041 | 0xE0, 1042 | 0x30, 1043 | 0x41 1044 | //260 1045 | , 1046 | 0x1E, 1047 | 0x43, 1048 | 0x89, 1049 | 0x83, 1050 | 0x50, 1051 | 0xFC, 1052 | 0x24, 1053 | 0x2E, 1054 | 0x13, 1055 | 0x83, 1056 | 0xF1, 1057 | 0x7C, 1058 | 0x4C, 1059 | 0x2C, 1060 | 0xC9, 1061 | 0xD, 1062 | 0x83, 1063 | 0xB0, 1064 | 0xB5, 1065 | 0x82, 1066 | 0xE4, 1067 | 0xE8, 1068 | 6, 1069 | 0x9C, 1070 | 7, 1071 | 0xA0, 1072 | 0x99, 1073 | 0x1D, 1074 | 7, 1075 | 0x3E, 1076 | 0x82, 1077 | 0x8F 1078 | //280 1079 | , 1080 | 0x70, 1081 | 0x30, 1082 | 0x74, 1083 | 0x40, 1084 | 0xCA, 1085 | 0x10, 1086 | 0xE4, 1087 | 0xE8, 1088 | 0xF, 1089 | 0x92, 1090 | 0x14, 1091 | 0x3F, 1092 | 6, 1093 | 0xF8, 1094 | 0x84, 1095 | 0x88, 1096 | 0x43, 1097 | 0x81, 1098 | 0xA, 1099 | 0x34, 1100 | 0x39, 1101 | 0x41, 1102 | 0xC6, 1103 | 0xE3, 1104 | 0x1C, 1105 | 0x47, 1106 | 3, 1107 | 0xB0, 1108 | 0xB8, 1109 | 0x13, 1110 | 0xA, 1111 | 0xC2 1112 | //2A0 1113 | , 1114 | 0x64, 1115 | 0xF8, 1116 | 0x18, 1117 | 0xF9, 1118 | 0x60, 1119 | 0xB3, 1120 | 0xC0, 1121 | 0x65, 1122 | 0x20, 1123 | 0x60, 1124 | 0xA6, 1125 | 0x8C, 1126 | 0xC3, 1127 | 0x81, 1128 | 0x20, 1129 | 0x30, 1130 | 0x26, 1131 | 0x1E, 1132 | 0x1C, 1133 | 0x38, 1134 | 0xD3, 1135 | 1, 1136 | 0xB0, 1137 | 0x26, 1138 | 0x40, 1139 | 0xF4, 1140 | 0xB, 1141 | 0xC3, 1142 | 0x42, 1143 | 0x1F, 1144 | 0x85, 1145 | 0x32 1146 | //2C0 1147 | , 1148 | 0x26, 1149 | 0x60, 1150 | 0x40, 1151 | 0xC9, 1152 | 0xCB, 1153 | 1, 1154 | 0xEC, 1155 | 0x11, 1156 | 0x28, 1157 | 0x40, 1158 | 0xFA, 1159 | 4, 1160 | 0x34, 1161 | 0xE0, 1162 | 0x70, 1163 | 0x4C, 1164 | 0x8C, 1165 | 0x1D, 1166 | 7, 1167 | 0x69, 1168 | 3, 1169 | 0x16, 1170 | 0xC8, 1171 | 4, 1172 | 0x23, 1173 | 0xE8, 1174 | 0xC6, 1175 | 0x9A, 1176 | 0xB, 1177 | 0x1A, 1178 | 3, 1179 | 0xE0 1180 | //2E0 1181 | , 1182 | 0x76, 1183 | 6, 1184 | 5, 1185 | 0xCF, 1186 | 0x1E, 1187 | 0xBC, 1188 | 0x58, 1189 | 0x31, 1190 | 0x71, 1191 | 0x66, 1192 | 0, 1193 | 0xF8, 1194 | 0x3F, 1195 | 4, 1196 | 0xFC, 1197 | 0xC, 1198 | 0x74, 1199 | 0x27, 1200 | 0x8A, 1201 | 0x80, 1202 | 0x71, 1203 | 0xC2, 1204 | 0x3A, 1205 | 0x26, 1206 | 6, 1207 | 0xC0, 1208 | 0x1F, 1209 | 5, 1210 | 0xF, 1211 | 0x98, 1212 | 0x40, 1213 | 0xAE 1214 | //300 1215 | , 1216 | 1, 1217 | 0x7F, 1218 | 0xC0, 1219 | 7, 1220 | 0xFF, 1221 | 0, 1222 | 0xE, 1223 | 0xFE, 1224 | 0, 1225 | 3, 1226 | 0xDF, 1227 | 0x80, 1228 | 3, 1229 | 0xEF, 1230 | 0x80, 1231 | 0x1B, 1232 | 0xF1, 1233 | 0xC2, 1234 | 0, 1235 | 0xE7, 1236 | 0xE0, 1237 | 0x18, 1238 | 0xFC, 1239 | 0xE0, 1240 | 0x21, 1241 | 0xFC, 1242 | 0x80, 1243 | 0x3C, 1244 | 0xFC, 1245 | 0x40, 1246 | 0xE, 1247 | 0x7E 1248 | //320 1249 | , 1250 | 0, 1251 | 0x3F, 1252 | 0x3E, 1253 | 0, 1254 | 0xF, 1255 | 0xFE, 1256 | 0, 1257 | 0x1F, 1258 | 0xFF, 1259 | 0, 1260 | 0x3E, 1261 | 0xF0, 1262 | 7, 1263 | 0xFC, 1264 | 0, 1265 | 0x7E, 1266 | 0x10, 1267 | 0x3F, 1268 | 0xFF, 1269 | 0, 1270 | 0x3F, 1271 | 0x38, 1272 | 0xE, 1273 | 0x7C, 1274 | 1, 1275 | 0x87, 1276 | 0xC, 1277 | 0xFC, 1278 | 0xC7, 1279 | 0, 1280 | 0x3E, 1281 | 4 1282 | //340 1283 | , 1284 | 0xF, 1285 | 0x3E, 1286 | 0x1F, 1287 | 0xF, 1288 | 0xF, 1289 | 0x1F, 1290 | 0xF, 1291 | 2, 1292 | 0x83, 1293 | 0x87, 1294 | 0xCF, 1295 | 3, 1296 | 0x87, 1297 | 0xF, 1298 | 0x3F, 1299 | 0xC0, 1300 | 7, 1301 | 0x9E, 1302 | 0x60, 1303 | 0x3F, 1304 | 0xC0, 1305 | 3, 1306 | 0xFE, 1307 | 0, 1308 | 0x3F, 1309 | 0xE0, 1310 | 0x77, 1311 | 0xE1, 1312 | 0xC0, 1313 | 0xFE, 1314 | 0xE0, 1315 | 0xC3 1316 | //360 1317 | , 1318 | 0xE0, 1319 | 1, 1320 | 0xDF, 1321 | 0xF8, 1322 | 3, 1323 | 7, 1324 | 0, 1325 | 0x7E, 1326 | 0x70, 1327 | 0, 1328 | 0x7C, 1329 | 0x38, 1330 | 0x18, 1331 | 0xFE, 1332 | 0xC, 1333 | 0x1E, 1334 | 0x78, 1335 | 0x1C, 1336 | 0x7C, 1337 | 0x3E, 1338 | 0xE, 1339 | 0x1F, 1340 | 0x1E, 1341 | 0x1E, 1342 | 0x3E, 1343 | 0, 1344 | 0x7F, 1345 | 0x83, 1346 | 7, 1347 | 0xDB, 1348 | 0x87, 1349 | 0x83 1350 | //380 1351 | , 1352 | 7, 1353 | 0xC7, 1354 | 7, 1355 | 0x10, 1356 | 0x71, 1357 | 0xFF, 1358 | 0, 1359 | 0x3F, 1360 | 0xE2, 1361 | 1, 1362 | 0xE0, 1363 | 0xC1, 1364 | 0xC3, 1365 | 0xE1, 1366 | 0, 1367 | 0x7F, 1368 | 0xC0, 1369 | 5, 1370 | 0xF0, 1371 | 0x20, 1372 | 0xF8, 1373 | 0xF0, 1374 | 0x70, 1375 | 0xFE, 1376 | 0x78, 1377 | 0x79, 1378 | 0xF8, 1379 | 2, 1380 | 0x3F, 1381 | 0xC, 1382 | 0x8F, 1383 | 3 1384 | //3a0 1385 | , 1386 | 0xF, 1387 | 0x9F, 1388 | 0xE0, 1389 | 0xC1, 1390 | 0xC7, 1391 | 0x87, 1392 | 3, 1393 | 0xC3, 1394 | 0xC3, 1395 | 0xB0, 1396 | 0xE1, 1397 | 0xE1, 1398 | 0xC1, 1399 | 0xE3, 1400 | 0xE0, 1401 | 0x71, 1402 | 0xF0, 1403 | 0, 1404 | 0xFC, 1405 | 0x70, 1406 | 0x7C, 1407 | 0xC, 1408 | 0x3E, 1409 | 0x38, 1410 | 0xE, 1411 | 0x1C, 1412 | 0x70, 1413 | 0xC3, 1414 | 0xC7, 1415 | 3, 1416 | 0x81, 1417 | 0xC1 1418 | //3c0 1419 | , 1420 | 0xC7, 1421 | 0xE7, 1422 | 0, 1423 | 0xF, 1424 | 0xC7, 1425 | 0x87, 1426 | 0x19, 1427 | 9, 1428 | 0xEF, 1429 | 0xC4, 1430 | 0x33, 1431 | 0xE0, 1432 | 0xC1, 1433 | 0xFC, 1434 | 0xF8, 1435 | 0x70, 1436 | 0xF0, 1437 | 0x78, 1438 | 0xF8, 1439 | 0xF0, 1440 | 0x61, 1441 | 0xC7, 1442 | 0, 1443 | 0x1F, 1444 | 0xF8, 1445 | 1, 1446 | 0x7C, 1447 | 0xF8, 1448 | 0xF0, 1449 | 0x78, 1450 | 0x70, 1451 | 0x3C 1452 | //3e0 1453 | , 1454 | 0x7C, 1455 | 0xCE, 1456 | 0xE, 1457 | 0x21, 1458 | 0x83, 1459 | 0xCF, 1460 | 8, 1461 | 7, 1462 | 0x8F, 1463 | 8, 1464 | 0xC1, 1465 | 0x87, 1466 | 0x8F, 1467 | 0x80, 1468 | 0xC7, 1469 | 0xE3, 1470 | 0, 1471 | 7, 1472 | 0xF8, 1473 | 0xE0, 1474 | 0xEF, 1475 | 0, 1476 | 0x39, 1477 | 0xF7, 1478 | 0x80, 1479 | 0xE, 1480 | 0xF8, 1481 | 0xE1, 1482 | 0xE3, 1483 | 0xF8, 1484 | 0x21, 1485 | 0x9F 1486 | //400 1487 | , 1488 | 0xC0, 1489 | 0xFF, 1490 | 3, 1491 | 0xF8, 1492 | 7, 1493 | 0xC0, 1494 | 0x1F, 1495 | 0xF8, 1496 | 0xC4, 1497 | 4, 1498 | 0xFC, 1499 | 0xC4, 1500 | 0xC1, 1501 | 0xBC, 1502 | 0x87, 1503 | 0xF0, 1504 | 0xF, 1505 | 0xC0, 1506 | 0x7F, 1507 | 5, 1508 | 0xE0, 1509 | 0x25, 1510 | 0xEC, 1511 | 0xC0, 1512 | 0x3E, 1513 | 0x84, 1514 | 0x47, 1515 | 0xF0, 1516 | 0x8E, 1517 | 3, 1518 | 0xF8, 1519 | 3 1520 | //420 1521 | , 1522 | 0xFB, 1523 | 0xC0, 1524 | 0x19, 1525 | 0xF8, 1526 | 7, 1527 | 0x9C, 1528 | 0xC, 1529 | 0x17, 1530 | 0xF8, 1531 | 7, 1532 | 0xE0, 1533 | 0x1F, 1534 | 0xA1, 1535 | 0xFC, 1536 | 0xF, 1537 | 0xFC, 1538 | 1, 1539 | 0xF0, 1540 | 0x3F, 1541 | 0, 1542 | 0xFE, 1543 | 3, 1544 | 0xF0, 1545 | 0x1F, 1546 | 0, 1547 | 0xFD, 1548 | 0, 1549 | 0xFF, 1550 | 0x88, 1551 | 0xD, 1552 | 0xF9, 1553 | 1 1554 | //440 1555 | , 1556 | 0xFF, 1557 | 0, 1558 | 0x70, 1559 | 7, 1560 | 0xC0, 1561 | 0x3E, 1562 | 0x42, 1563 | 0xF3, 1564 | 0xD, 1565 | 0xC4, 1566 | 0x7F, 1567 | 0x80, 1568 | 0xFC, 1569 | 7, 1570 | 0xF0, 1571 | 0x5E, 1572 | 0xC0, 1573 | 0x3F, 1574 | 0, 1575 | 0x78, 1576 | 0x3F, 1577 | 0x81, 1578 | 0xFF, 1579 | 1, 1580 | 0xF8, 1581 | 1, 1582 | 0xC3, 1583 | 0xE8, 1584 | 0xC, 1585 | 0xE4, 1586 | 0x64, 1587 | 0x8F 1588 | ////460 1589 | , 1590 | 0xE4, 1591 | 0xF, 1592 | 0xF0, 1593 | 7, 1594 | 0xF0, 1595 | 0xC2, 1596 | 0x1F, 1597 | 0, 1598 | 0x7F, 1599 | 0xC0, 1600 | 0x6F, 1601 | 0x80, 1602 | 0x7E, 1603 | 3, 1604 | 0xF8, 1605 | 7, 1606 | 0xF0, 1607 | 0x3F, 1608 | 0xC0, 1609 | 0x78, 1610 | 0xF, 1611 | 0x82, 1612 | 7, 1613 | 0xFE, 1614 | 0x22, 1615 | 0x77, 1616 | 0x70, 1617 | 2, 1618 | 0x76, 1619 | 3, 1620 | 0xFE, 1621 | 0 1622 | //480 1623 | , 1624 | 0xFE, 1625 | 0x67, 1626 | 0, 1627 | 0x7C, 1628 | 0xC7, 1629 | 0xF1, 1630 | 0x8E, 1631 | 0xC6, 1632 | 0x3B, 1633 | 0xE0, 1634 | 0x3F, 1635 | 0x84, 1636 | 0xF3, 1637 | 0x19, 1638 | 0xD8, 1639 | 3, 1640 | 0x99, 1641 | 0xFC, 1642 | 9, 1643 | 0xB8, 1644 | 0xF, 1645 | 0xF8, 1646 | 0, 1647 | 0x9D, 1648 | 0x24, 1649 | 0x61, 1650 | 0xF9, 1651 | 0xD, 1652 | 0, 1653 | 0xFD, 1654 | 3, 1655 | 0xF0 1656 | //4a0 1657 | , 1658 | 0x1F, 1659 | 0x90, 1660 | 0x3F, 1661 | 1, 1662 | 0xF8, 1663 | 0x1F, 1664 | 0xD0, 1665 | 0xF, 1666 | 0xF8, 1667 | 0x37, 1668 | 1, 1669 | 0xF8, 1670 | 7, 1671 | 0xF0, 1672 | 0xF, 1673 | 0xC0, 1674 | 0x3F, 1675 | 0, 1676 | 0xFE, 1677 | 3, 1678 | 0xF8, 1679 | 0xF, 1680 | 0xC0, 1681 | 0x3F, 1682 | 0, 1683 | 0xFA, 1684 | 3, 1685 | 0xF0, 1686 | 0xF, 1687 | 0x80, 1688 | 0xFF, 1689 | 1 1690 | //4c0 1691 | , 1692 | 0xB8, 1693 | 7, 1694 | 0xF0, 1695 | 1, 1696 | 0xFC, 1697 | 1, 1698 | 0xBC, 1699 | 0x80, 1700 | 0x13, 1701 | 0x1E, 1702 | 0, 1703 | 0x7F, 1704 | 0xE1, 1705 | 0x40, 1706 | 0x7F, 1707 | 0xA0, 1708 | 0x7F, 1709 | 0xB0, 1710 | 0, 1711 | 0x3F, 1712 | 0xC0, 1713 | 0x1F, 1714 | 0xC0, 1715 | 0x38, 1716 | 0xF, 1717 | 0xF0, 1718 | 0x1F, 1719 | 0x80, 1720 | 0xFF, 1721 | 1, 1722 | 0xFC, 1723 | 3 1724 | //4e0 1725 | , 1726 | 0xF1, 1727 | 0x7E, 1728 | 1, 1729 | 0xFE, 1730 | 1, 1731 | 0xF0, 1732 | 0xFF, 1733 | 0, 1734 | 0x7F, 1735 | 0xC0, 1736 | 0x1D, 1737 | 7, 1738 | 0xF0, 1739 | 0xF, 1740 | 0xC0, 1741 | 0x7E, 1742 | 6, 1743 | 0xE0, 1744 | 7, 1745 | 0xE0, 1746 | 0xF, 1747 | 0xF8, 1748 | 6, 1749 | 0xC1, 1750 | 0xFE, 1751 | 1, 1752 | 0xFC, 1753 | 3, 1754 | 0xE0, 1755 | 0xF, 1756 | 0, 1757 | 0xFC}; 1758 | 1759 | //////////////////////////////////////////////////////////////////////////////////////////// 1760 | // 1761 | // Render 1762 | // 1763 | //////////////////////////////////////////////////////////////////////////////////////////// 1764 | 1765 | unsigned char pitches[256]; // tab43008 1766 | 1767 | unsigned char frequency1[256]; 1768 | unsigned char frequency2[256]; 1769 | unsigned char frequency3[256]; 1770 | 1771 | unsigned char amplitude1[256]; 1772 | unsigned char amplitude2[256]; 1773 | unsigned char amplitude3[256]; 1774 | 1775 | unsigned char sampledConsonantFlag[256]; // tab44800 1776 | 1777 | //////////////////////////////////////////////////////////////////////////////////////////// 1778 | // 1779 | // Sam 1780 | // 1781 | //////////////////////////////////////////////////////////////////////////////////////////// 1782 | 1783 | unsigned char stress[256]; //numbers from 0 to 8 1784 | unsigned char phonemeLength[256]; //tab40160 1785 | unsigned char phonemeindex[256]; 1786 | 1787 | //////////////////////////////////////////////////////////////////////////////////////////// 1788 | // 1789 | // ReciterTabs 1790 | // 1791 | //////////////////////////////////////////////////////////////////////////////////////////// 1792 | 1793 | //some flags 1794 | const unsigned char tab36376[] = { 1795 | 0, 0, 0, 0, 0, 0, 0, 0, // 0-7 1796 | 0, 0, 0, 0, 0, 0, 0, 0, // 8-15 1797 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1798 | 0, 2, 2, 2, 2, 2, 2, 130, // ' ', '!' 1799 | 0, 0, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 1800 | 3, 3, 2, 2, 2, 2, 2, 2, 2, 192, 168, 176, 172, 192, 160, 184, // '@', 'A' 1801 | 160, 192, 188, 160, 172, 168, 172, 192, 160, 160, 172, 180, 164, 192, 168, 168, 1802 | 176, 192, 188, 0, 0, 0, 2, 0, // 'X', 'Y', 'Z', '[', 1803 | 32, 32, 155, 32, 192, 185, 32, 205, 163, 76, 138, 142}; 1804 | 1805 | const unsigned char rules[] = { 1806 | ']', 'A' | 0x80, ' ', '(', 'A', '.', ')', '=', 1807 | 'E', 'H', '4', 'Y', '.', ' ' | 0x80, '(', 'A', 1808 | ')', ' ', '=', 'A', 'H' | 0x80, ' ', '(', 'A', 1809 | 'R', 'E', ')', ' ', '=', 'A', 'A', 'R' | 0x80, 1810 | ' ', '(', 'A', 'R', ')', 'O', '=', 'A', 1811 | 'X', 'R' | 0x80, '(', 'A', 'R', ')', '#', '=', 1812 | 'E', 'H', '4', 'R' | 0x80, ' ', '^', '(', 'A', 1813 | 'S', ')', '#', '=', 'E', 'Y', '4', 'S' | 0x80, 1814 | '(', 'A', ')', 'W', 'A', '=', 'A', 'X' | 0x80, 1815 | '(', 'A', 'W', ')', '=', 'A', 'O', '5' | 0x80, 1816 | ' ', ':', '(', 'A', 'N', 'Y', ')', '=', 1817 | 'E', 'H', '4', 'N', 'I', 'Y' | 0x80, '(', 'A', 1818 | ')', '^', '+', '#', '=', 'E', 'Y', '5' | 0x80, 1819 | '#', ':', '(', 'A', 'L', 'L', 'Y', ')', 1820 | '=', 'U', 'L', 'I', 'Y' | 0x80, ' ', '(', 'A', 1821 | 'L', ')', '#', '=', 'U', 'L' | 0x80, '(', 'A', 1822 | 'G', 'A', 'I', 'N', ')', '=', 'A', 'X', 1823 | 'G', 'E', 'H', '4', 'N' | 0x80, '#', ':', '(', 1824 | 'A', 'G', ')', 'E', '=', 'I', 'H', 'J' | 0x80, 1825 | '(', 'A', ')', '^', '%', '=', 'E', 'Y' | 0x80, 1826 | '(', 'A', ')', '^', '+', ':', '#', '=', 1827 | 'A', 'E' | 0x80, ' ', ':', '(', 'A', ')', '^', 1828 | '+', ' ', '=', 'E', 'Y', '4' | 0x80, ' ', '(', 1829 | 'A', 'R', 'R', ')', '=', 'A', 'X', 'R' | 0x80, 1830 | '(', 'A', 'R', 'R', ')', '=', 'A', 'E', 1831 | '4', 'R' | 0x80, ' ', '^', '(', 'A', 'R', ')', 1832 | ' ', '=', 'A', 'A', '5', 'R' | 0x80, '(', 'A', 1833 | 'R', ')', '=', 'A', 'A', '5', 'R' | 0x80, '(', 1834 | 'A', 'I', 'R', ')', '=', 'E', 'H', '4', 1835 | 'R' | 0x80, '(', 'A', 'I', ')', '=', 'E', 'Y', 1836 | '4' | 0x80, '(', 'A', 'Y', ')', '=', 'E', 'Y', 1837 | '5' | 0x80, '(', 'A', 'U', ')', '=', 'A', 'O', 1838 | '4' | 0x80, '#', ':', '(', 'A', 'L', ')', ' ', 1839 | '=', 'U', 'L' | 0x80, '#', ':', '(', 'A', 'L', 1840 | 'S', ')', ' ', '=', 'U', 'L', 'Z' | 0x80, '(', 1841 | 'A', 'L', 'K', ')', '=', 'A', 'O', '4', 1842 | 'K' | 0x80, '(', 'A', 'L', ')', '^', '=', 'A', 1843 | 'O', 'L' | 0x80, ' ', ':', '(', 'A', 'B', 'L', 1844 | 'E', ')', '=', 'E', 'Y', '4', 'B', 'U', 1845 | 'L' | 0x80, '(', 'A', 'B', 'L', 'E', ')', '=', 1846 | 'A', 'X', 'B', 'U', 'L' | 0x80, '(', 'A', ')', 1847 | 'V', 'O', '=', 'E', 'Y', '4' | 0x80, '(', 'A', 1848 | 'N', 'G', ')', '+', '=', 'E', 'Y', '4', 1849 | 'N', 'J' | 0x80, '(', 'A', 'T', 'A', 'R', 'I', 1850 | ')', '=', 'A', 'H', 'T', 'A', 'A', '4', 1851 | 'R', 'I', 'Y' | 0x80, '(', 'A', ')', 'T', 'O', 1852 | 'M', '=', 'A', 'E' | 0x80, '(', 'A', ')', 'T', 1853 | 'T', 'I', '=', 'A', 'E' | 0x80, ' ', '(', 'A', 1854 | 'T', ')', ' ', '=', 'A', 'E', 'T' | 0x80, ' ', 1855 | '(', 'A', ')', 'T', '=', 'A', 'H' | 0x80, '(', 1856 | 'A', ')', '=', 'A', 'E' | 0x80, 1857 | 1858 | ']', 'B' | 0x80, ' ', '(', 'B', ')', ' ', '=', 1859 | 'B', 'I', 'Y', '4' | 0x80, ' ', '(', 'B', 'E', 1860 | ')', '^', '#', '=', 'B', 'I', 'H' | 0x80, '(', 1861 | 'B', 'E', 'I', 'N', 'G', ')', '=', 'B', 1862 | 'I', 'Y', '4', 'I', 'H', 'N', 'X' | 0x80, ' ', 1863 | '(', 'B', 'O', 'T', 'H', ')', ' ', '=', 1864 | 'B', 'O', 'W', '4', 'T', 'H' | 0x80, ' ', '(', 1865 | 'B', 'U', 'S', ')', '#', '=', 'B', 'I', 1866 | 'H', '4', 'Z' | 0x80, '(', 'B', 'R', 'E', 'A', 1867 | 'K', ')', '=', 'B', 'R', 'E', 'Y', '5', 1868 | 'K' | 0x80, '(', 'B', 'U', 'I', 'L', ')', '=', 1869 | 'B', 'I', 'H', '4', 'L' | 0x80, '(', 'B', ')', 1870 | '=', 'B' | 0x80, 1871 | 1872 | ']', 'C' | 0x80, ' ', '(', 'C', ')', ' ', '=', 1873 | 'S', 'I', 'Y', '4' | 0x80, ' ', '(', 'C', 'H', 1874 | ')', '^', '=', 'K' | 0x80, '^', 'E', '(', 'C', 1875 | 'H', ')', '=', 'K' | 0x80, '(', 'C', 'H', 'A', 1876 | ')', 'R', '#', '=', 'K', 'E', 'H', '5' | 0x80, 1877 | '(', 'C', 'H', ')', '=', 'C', 'H' | 0x80, ' ', 1878 | 'S', '(', 'C', 'I', ')', '#', '=', 'S', 1879 | 'A', 'Y', '4' | 0x80, '(', 'C', 'I', ')', 'A', 1880 | '=', 'S', 'H' | 0x80, '(', 'C', 'I', ')', 'O', 1881 | '=', 'S', 'H' | 0x80, '(', 'C', 'I', ')', 'E', 1882 | 'N', '=', 'S', 'H' | 0x80, '(', 'C', 'I', 'T', 1883 | 'Y', ')', '=', 'S', 'I', 'H', 'T', 'I', 1884 | 'Y' | 0x80, '(', 'C', ')', '+', '=', 'S' | 0x80, '(', 1885 | 'C', 'K', ')', '=', 'K' | 0x80, '(', 'C', 'O', 1886 | 'M', 'M', 'O', 'D', 'O', 'R', 'E', ')', 1887 | '=', 'K', 'A', 'A', '4', 'M', 'A', 'H', 1888 | 'D', 'O', 'H', 'R' | 0x80, '(', 'C', 'O', 'M', 1889 | ')', '=', 'K', 'A', 'H', 'M' | 0x80, '(', 'C', 1890 | 'U', 'I', 'T', ')', '=', 'K', 'I', 'H', 1891 | 'T' | 0x80, '(', 'C', 'R', 'E', 'A', ')', '=', 1892 | 'K', 'R', 'I', 'Y', 'E', 'Y' | 0x80, '(', 'C', 1893 | ')', '=', 'K' | 0x80, 1894 | 1895 | ']', 'D' | 0x80, ' ', '(', 'D', ')', ' ', '=', 1896 | 'D', 'I', 'Y', '4' | 0x80, ' ', '(', 'D', 'R', 1897 | '.', ')', ' ', '=', 'D', 'A', 'A', '4', 1898 | 'K', 'T', 'E', 'R' | 0x80, '#', ':', '(', 'D', 1899 | 'E', 'D', ')', ' ', '=', 'D', 'I', 'H', 1900 | 'D' | 0x80, '.', 'E', '(', 'D', ')', ' ', '=', 1901 | 'D' | 0x80, '#', ':', '^', 'E', '(', 'D', ')', 1902 | ' ', '=', 'T' | 0x80, ' ', '(', 'D', 'E', ')', 1903 | '^', '#', '=', 'D', 'I', 'H' | 0x80, ' ', '(', 1904 | 'D', 'O', ')', ' ', '=', 'D', 'U', 'W' | 0x80, 1905 | ' ', '(', 'D', 'O', 'E', 'S', ')', '=', 1906 | 'D', 'A', 'H', 'Z' | 0x80, '(', 'D', 'O', 'N', 1907 | 'E', ')', ' ', '=', 'D', 'A', 'H', '5', 1908 | 'N' | 0x80, '(', 'D', 'O', 'I', 'N', 'G', ')', 1909 | '=', 'D', 'U', 'W', '4', 'I', 'H', 'N', 1910 | 'X' | 0x80, ' ', '(', 'D', 'O', 'W', ')', '=', 1911 | 'D', 'A', 'W' | 0x80, '#', '(', 'D', 'U', ')', 1912 | 'A', '=', 'J', 'U', 'W' | 0x80, '#', '(', 'D', 1913 | 'U', ')', '^', '#', '=', 'J', 'A', 'X' | 0x80, 1914 | '(', 'D', ')', '=', 'D' | 0x80, 1915 | 1916 | ']', 'E' | 0x80, ' ', '(', 'E', ')', ' ', '=', 1917 | 'I', 'Y', 'I', 'Y', '4' | 0x80, '#', ':', '(', 1918 | 'E', ')', ' ', '=' | 0x80, '\'', ':', '^', '(', 1919 | 'E', ')', ' ', '=' | 0x80, ' ', ':', '(', 'E', 1920 | ')', ' ', '=', 'I', 'Y' | 0x80, '#', '(', 'E', 1921 | 'D', ')', ' ', '=', 'D' | 0x80, '#', ':', '(', 1922 | 'E', ')', 'D', ' ', '=' | 0x80, '(', 'E', 'V', 1923 | ')', 'E', 'R', '=', 'E', 'H', '4', 'V' | 0x80, 1924 | '(', 'E', ')', '^', '%', '=', 'I', 'Y', 1925 | '4' | 0x80, '(', 'E', 'R', 'I', ')', '#', '=', 1926 | 'I', 'Y', '4', 'R', 'I', 'Y' | 0x80, '(', 'E', 1927 | 'R', 'I', ')', '=', 'E', 'H', '4', 'R', 1928 | 'I', 'H' | 0x80, '#', ':', '(', 'E', 'R', ')', 1929 | '#', '=', 'E', 'R' | 0x80, '(', 'E', 'R', 'R', 1930 | 'O', 'R', ')', '=', 'E', 'H', '4', 'R', 1931 | 'O', 'H', 'R' | 0x80, '(', 'E', 'R', 'A', 'S', 1932 | 'E', ')', '=', 'I', 'H', 'R', 'E', 'Y', 1933 | '5', 'S' | 0x80, '(', 'E', 'R', ')', '#', '=', 1934 | 'E', 'H', 'R' | 0x80, '(', 'E', 'R', ')', '=', 1935 | 'E', 'R' | 0x80, ' ', '(', 'E', 'V', 'E', 'N', 1936 | ')', '=', 'I', 'Y', 'V', 'E', 'H', 'N' | 0x80, 1937 | '#', ':', '(', 'E', ')', 'W', '=' | 0x80, '@', 1938 | '(', 'E', 'W', ')', '=', 'U', 'W' | 0x80, '(', 1939 | 'E', 'W', ')', '=', 'Y', 'U', 'W' | 0x80, '(', 1940 | 'E', ')', 'O', '=', 'I', 'Y' | 0x80, '#', ':', 1941 | '&', '(', 'E', 'S', ')', ' ', '=', 'I', 1942 | 'H', 'Z' | 0x80, '#', ':', '(', 'E', ')', 'S', 1943 | ' ', '=' | 0x80, '#', ':', '(', 'E', 'L', 'Y', 1944 | ')', ' ', '=', 'L', 'I', 'Y' | 0x80, '#', ':', 1945 | '(', 'E', 'M', 'E', 'N', 'T', ')', '=', 1946 | 'M', 'E', 'H', 'N', 'T' | 0x80, '(', 'E', 'F', 1947 | 'U', 'L', ')', '=', 'F', 'U', 'H', 'L' | 0x80, 1948 | '(', 'E', 'E', ')', '=', 'I', 'Y', '4' | 0x80, 1949 | '(', 'E', 'A', 'R', 'N', ')', '=', 'E', 1950 | 'R', '5', 'N' | 0x80, ' ', '(', 'E', 'A', 'R', 1951 | ')', '^', '=', 'E', 'R', '5' | 0x80, '(', 'E', 1952 | 'A', 'D', ')', '=', 'E', 'H', 'D' | 0x80, '#', 1953 | ':', '(', 'E', 'A', ')', ' ', '=', 'I', 1954 | 'Y', 'A', 'X' | 0x80, '(', 'E', 'A', ')', 'S', 1955 | 'U', '=', 'E', 'H', '5' | 0x80, '(', 'E', 'A', 1956 | ')', '=', 'I', 'Y', '5' | 0x80, '(', 'E', 'I', 1957 | 'G', 'H', ')', '=', 'E', 'Y', '4' | 0x80, '(', 1958 | 'E', 'I', ')', '=', 'I', 'Y', '4' | 0x80, ' ', 1959 | '(', 'E', 'Y', 'E', ')', '=', 'A', 'Y', 1960 | '4' | 0x80, '(', 'E', 'Y', ')', '=', 'I', 'Y' | 0x80, 1961 | '(', 'E', 'U', ')', '=', 'Y', 'U', 'W', 1962 | '5' | 0x80, '(', 'E', 'Q', 'U', 'A', 'L', ')', 1963 | '=', 'I', 'Y', '4', 'K', 'W', 'U', 'L' | 0x80, 1964 | '(', 'E', ')', '=', 'E', 'H' | 0x80, 1965 | 1966 | ']', 'F' | 0x80, ' ', '(', 'F', ')', ' ', '=', 1967 | 'E', 'H', '4', 'F' | 0x80, '(', 'F', 'U', 'L', 1968 | ')', '=', 'F', 'U', 'H', 'L' | 0x80, '(', 'F', 1969 | 'R', 'I', 'E', 'N', 'D', ')', '=', 'F', 1970 | 'R', 'E', 'H', '5', 'N', 'D' | 0x80, '(', 'F', 1971 | 'A', 'T', 'H', 'E', 'R', ')', '=', 'F', 1972 | 'A', 'A', '4', 'D', 'H', 'E', 'R' | 0x80, '(', 1973 | 'F', ')', 'F', '=' | 0x80, '(', 'F', ')', '=', 1974 | 'F' | 0x80, 1975 | 1976 | ']', 'G' | 0x80, ' ', '(', 'G', ')', ' ', '=', 1977 | 'J', 'I', 'Y', '4' | 0x80, '(', 'G', 'I', 'V', 1978 | ')', '=', 'G', 'I', 'H', '5', 'V' | 0x80, ' ', 1979 | '(', 'G', ')', 'I', '^', '=', 'G' | 0x80, '(', 1980 | 'G', 'E', ')', 'T', '=', 'G', 'E', 'H', 1981 | '5' | 0x80, 'S', 'U', '(', 'G', 'G', 'E', 'S', 1982 | ')', '=', 'G', 'J', 'E', 'H', '4', 'S' | 0x80, 1983 | '(', 'G', 'G', ')', '=', 'G' | 0x80, ' ', 'B', 1984 | '#', '(', 'G', ')', '=', 'G' | 0x80, '(', 'G', 1985 | ')', '+', '=', 'J' | 0x80, '(', 'G', 'R', 'E', 1986 | 'A', 'T', ')', '=', 'G', 'R', 'E', 'Y', 1987 | '4', 'T' | 0x80, '(', 'G', 'O', 'N', ')', 'E', 1988 | '=', 'G', 'A', 'O', '5', 'N' | 0x80, '#', '(', 1989 | 'G', 'H', ')', '=' | 0x80, ' ', '(', 'G', 'N', 1990 | ')', '=', 'N' | 0x80, '(', 'G', ')', '=', 'G' | 0x80, 1991 | 1992 | ']', 'H' | 0x80, ' ', '(', 'H', ')', ' ', '=', 1993 | 'E', 'Y', '4', 'C', 'H' | 0x80, ' ', '(', 'H', 1994 | 'A', 'V', ')', '=', '/', 'H', 'A', 'E', 1995 | '6', 'V' | 0x80, ' ', '(', 'H', 'E', 'R', 'E', 1996 | ')', '=', '/', 'H', 'I', 'Y', 'R' | 0x80, ' ', 1997 | '(', 'H', 'O', 'U', 'R', ')', '=', 'A', 1998 | 'W', '5', 'E', 'R' | 0x80, '(', 'H', 'O', 'W', 1999 | ')', '=', '/', 'H', 'A', 'W' | 0x80, '(', 'H', 2000 | ')', '#', '=', '/', 'H' | 0x80, '(', 'H', ')', 2001 | '=' | 0x80, 2002 | 2003 | ']', 'I' | 0x80, ' ', '(', 'I', 'N', ')', '=', 2004 | 'I', 'H', 'N' | 0x80, ' ', '(', 'I', ')', ' ', 2005 | '=', 'A', 'Y', '4' | 0x80, '(', 'I', ')', ' ', 2006 | '=', 'A', 'Y' | 0x80, '(', 'I', 'N', ')', 'D', 2007 | '=', 'A', 'Y', '5', 'N' | 0x80, 'S', 'E', 'M', 2008 | '(', 'I', ')', '=', 'I', 'Y' | 0x80, ' ', 'A', 2009 | 'N', 'T', '(', 'I', ')', '=', 'A', 'Y' | 0x80, 2010 | '(', 'I', 'E', 'R', ')', '=', 'I', 'Y', 2011 | 'E', 'R' | 0x80, '#', ':', 'R', '(', 'I', 'E', 2012 | 'D', ')', ' ', '=', 'I', 'Y', 'D' | 0x80, '(', 2013 | 'I', 'E', 'D', ')', ' ', '=', 'A', 'Y', 2014 | '5', 'D' | 0x80, '(', 'I', 'E', 'N', ')', '=', 2015 | 'I', 'Y', 'E', 'H', 'N' | 0x80, '(', 'I', 'E', 2016 | ')', 'T', '=', 'A', 'Y', '4', 'E', 'H' | 0x80, 2017 | '(', 'I', '\'', ')', '=', 'A', 'Y', '5' | 0x80, 2018 | ' ', ':', '(', 'I', ')', '^', '%', '=', 2019 | 'A', 'Y', '5' | 0x80, ' ', ':', '(', 'I', 'E', 2020 | ')', ' ', '=', 'A', 'Y', '4' | 0x80, '(', 'I', 2021 | ')', '%', '=', 'I', 'Y' | 0x80, '(', 'I', 'E', 2022 | ')', '=', 'I', 'Y', '4' | 0x80, ' ', '(', 'I', 2023 | 'D', 'E', 'A', ')', '=', 'A', 'Y', 'D', 2024 | 'I', 'Y', '5', 'A', 'H' | 0x80, '(', 'I', ')', 2025 | '^', '+', ':', '#', '=', 'I', 'H' | 0x80, '(', 2026 | 'I', 'R', ')', '#', '=', 'A', 'Y', 'R' | 0x80, 2027 | '(', 'I', 'Z', ')', '%', '=', 'A', 'Y', 2028 | 'Z' | 0x80, '(', 'I', 'S', ')', '%', '=', 'A', 2029 | 'Y', 'Z' | 0x80, 'I', '^', '(', 'I', ')', '^', 2030 | '#', '=', 'I', 'H' | 0x80, '+', '^', '(', 'I', 2031 | ')', '^', '+', '=', 'A', 'Y' | 0x80, '#', ':', 2032 | '^', '(', 'I', ')', '^', '+', '=', 'I', 2033 | 'H' | 0x80, '(', 'I', ')', '^', '+', '=', 'A', 2034 | 'Y' | 0x80, '(', 'I', 'R', ')', '=', 'E', 'R' | 0x80, 2035 | '(', 'I', 'G', 'H', ')', '=', 'A', 'Y', 2036 | '4' | 0x80, '(', 'I', 'L', 'D', ')', '=', 'A', 2037 | 'Y', '5', 'L', 'D' | 0x80, ' ', '(', 'I', 'G', 2038 | 'N', ')', '=', 'I', 'H', 'G', 'N' | 0x80, '(', 2039 | 'I', 'G', 'N', ')', ' ', '=', 'A', 'Y', 2040 | '4', 'N' | 0x80, '(', 'I', 'G', 'N', ')', '^', 2041 | '=', 'A', 'Y', '4', 'N' | 0x80, '(', 'I', 'G', 2042 | 'N', ')', '%', '=', 'A', 'Y', '4', 'N' | 0x80, 2043 | '(', 'I', 'C', 'R', 'O', ')', '=', 'A', 2044 | 'Y', '4', 'K', 'R', 'O', 'H' | 0x80, '(', 'I', 2045 | 'Q', 'U', 'E', ')', '=', 'I', 'Y', '4', 2046 | 'K' | 0x80, '(', 'I', ')', '=', 'I', 'H' | 0x80, 2047 | 2048 | ']', 'J' | 0x80, ' ', '(', 'J', ')', ' ', '=', 2049 | 'J', 'E', 'Y', '4' | 0x80, '(', 'J', ')', '=', 2050 | 'J' | 0x80, 2051 | 2052 | ']', 'K' | 0x80, ' ', '(', 'K', ')', ' ', '=', 2053 | 'K', 'E', 'Y', '4' | 0x80, ' ', '(', 'K', ')', 2054 | 'N', '=' | 0x80, '(', 'K', ')', '=', 'K' | 0x80, 2055 | 2056 | ']', 'L' | 0x80, ' ', '(', 'L', ')', ' ', '=', 2057 | 'E', 'H', '4', 'L' | 0x80, '(', 'L', 'O', ')', 2058 | 'C', '#', '=', 'L', 'O', 'W' | 0x80, 'L', '(', 2059 | 'L', ')', '=' | 0x80, '#', ':', '^', '(', 'L', 2060 | ')', '%', '=', 'U', 'L' | 0x80, '(', 'L', 'E', 2061 | 'A', 'D', ')', '=', 'L', 'I', 'Y', 'D' | 0x80, 2062 | ' ', '(', 'L', 'A', 'U', 'G', 'H', ')', 2063 | '=', 'L', 'A', 'E', '4', 'F' | 0x80, '(', 'L', 2064 | ')', '=', 'L' | 0x80, 2065 | 2066 | ']', 'M' | 0x80, ' ', '(', 'M', ')', ' ', '=', 2067 | 'E', 'H', '4', 'M' | 0x80, ' ', '(', 'M', 'R', 2068 | '.', ')', ' ', '=', 'M', 'I', 'H', '4', 2069 | 'S', 'T', 'E', 'R' | 0x80, ' ', '(', 'M', 'S', 2070 | '.', ')', '=', 'M', 'I', 'H', '5', 'Z' | 0x80, 2071 | ' ', '(', 'M', 'R', 'S', '.', ')', ' ', 2072 | '=', 'M', 'I', 'H', '4', 'S', 'I', 'X', 2073 | 'Z' | 0x80, '(', 'M', 'O', 'V', ')', '=', 'M', 2074 | 'U', 'W', '4', 'V' | 0x80, '(', 'M', 'A', 'C', 2075 | 'H', 'I', 'N', ')', '=', 'M', 'A', 'H', 2076 | 'S', 'H', 'I', 'Y', '5', 'N' | 0x80, 'M', '(', 2077 | 'M', ')', '=' | 0x80, '(', 'M', ')', '=', 'M' | 0x80, 2078 | 2079 | ']', 'N' | 0x80, ' ', '(', 'N', ')', ' ', '=', 2080 | 'E', 'H', '4', 'N' | 0x80, 'E', '(', 'N', 'G', 2081 | ')', '+', '=', 'N', 'J' | 0x80, '(', 'N', 'G', 2082 | ')', 'R', '=', 'N', 'X', 'G' | 0x80, '(', 'N', 2083 | 'G', ')', '#', '=', 'N', 'X', 'G' | 0x80, '(', 2084 | 'N', 'G', 'L', ')', '%', '=', 'N', 'X', 2085 | 'G', 'U', 'L' | 0x80, '(', 'N', 'G', ')', '=', 2086 | 'N', 'X' | 0x80, '(', 'N', 'K', ')', '=', 'N', 2087 | 'X', 'K' | 0x80, ' ', '(', 'N', 'O', 'W', ')', 2088 | ' ', '=', 'N', 'A', 'W', '4' | 0x80, 'N', '(', 2089 | 'N', ')', '=' | 0x80, '(', 'N', 'O', 'N', ')', 2090 | 'E', '=', 'N', 'A', 'H', '4', 'N' | 0x80, '(', 2091 | 'N', ')', '=', 'N' | 0x80, 2092 | 2093 | ']', 'O' | 0x80, ' ', '(', 'O', ')', ' ', '=', 2094 | 'O', 'H', '4', 'W' | 0x80, '(', 'O', 'F', ')', 2095 | ' ', '=', 'A', 'H', 'V' | 0x80, ' ', '(', 'O', 2096 | 'H', ')', ' ', '=', 'O', 'W', '5' | 0x80, '(', 2097 | 'O', 'R', 'O', 'U', 'G', 'H', ')', '=', 2098 | 'E', 'R', '4', 'O', 'W' | 0x80, '#', ':', '(', 2099 | 'O', 'R', ')', ' ', '=', 'E', 'R' | 0x80, '#', 2100 | ':', '(', 'O', 'R', 'S', ')', ' ', '=', 2101 | 'E', 'R', 'Z' | 0x80, '(', 'O', 'R', ')', '=', 2102 | 'A', 'O', 'R' | 0x80, ' ', '(', 'O', 'N', 'E', 2103 | ')', '=', 'W', 'A', 'H', 'N' | 0x80, '#', '(', 2104 | 'O', 'N', 'E', ')', ' ', '=', 'W', 'A', 2105 | 'H', 'N' | 0x80, '(', 'O', 'W', ')', '=', 'O', 2106 | 'W' | 0x80, ' ', '(', 'O', 'V', 'E', 'R', ')', 2107 | '=', 'O', 'W', '5', 'V', 'E', 'R' | 0x80, 'P', 2108 | 'R', '(', 'O', ')', 'V', '=', 'U', 'W', 2109 | '4' | 0x80, '(', 'O', 'V', ')', '=', 'A', 'H', 2110 | '4', 'V' | 0x80, '(', 'O', ')', '^', '%', '=', 2111 | 'O', 'W', '5' | 0x80, '(', 'O', ')', '^', 'E', 2112 | 'N', '=', 'O', 'W' | 0x80, '(', 'O', ')', '^', 2113 | 'I', '#', '=', 'O', 'W', '5' | 0x80, '(', 'O', 2114 | 'L', ')', 'D', '=', 'O', 'W', '4', 'L' | 0x80, 2115 | '(', 'O', 'U', 'G', 'H', 'T', ')', '=', 2116 | 'A', 'O', '5', 'T' | 0x80, '(', 'O', 'U', 'G', 2117 | 'H', ')', '=', 'A', 'H', '5', 'F' | 0x80, ' ', 2118 | '(', 'O', 'U', ')', '=', 'A', 'W' | 0x80, 'H', 2119 | '(', 'O', 'U', ')', 'S', '#', '=', 'A', 2120 | 'W', '4' | 0x80, '(', 'O', 'U', 'S', ')', '=', 2121 | 'A', 'X', 'S' | 0x80, '(', 'O', 'U', 'R', ')', 2122 | '=', 'O', 'H', 'R' | 0x80, '(', 'O', 'U', 'L', 2123 | 'D', ')', '=', 'U', 'H', '5', 'D' | 0x80, '(', 2124 | 'O', 'U', ')', '^', 'L', '=', 'A', 'H', 2125 | '5' | 0x80, '(', 'O', 'U', 'P', ')', '=', 'U', 2126 | 'W', '5', 'P' | 0x80, '(', 'O', 'U', ')', '=', 2127 | 'A', 'W' | 0x80, '(', 'O', 'Y', ')', '=', 'O', 2128 | 'Y' | 0x80, '(', 'O', 'I', 'N', 'G', ')', '=', 2129 | 'O', 'W', '4', 'I', 'H', 'N', 'X' | 0x80, '(', 2130 | 'O', 'I', ')', '=', 'O', 'Y', '5' | 0x80, '(', 2131 | 'O', 'O', 'R', ')', '=', 'O', 'H', '5', 2132 | 'R' | 0x80, '(', 'O', 'O', 'K', ')', '=', 'U', 2133 | 'H', '5', 'K' | 0x80, 'F', '(', 'O', 'O', 'D', 2134 | ')', '=', 'U', 'W', '5', 'D' | 0x80, 'L', '(', 2135 | 'O', 'O', 'D', ')', '=', 'A', 'H', '5', 2136 | 'D' | 0x80, 'M', '(', 'O', 'O', 'D', ')', '=', 2137 | 'U', 'W', '5', 'D' | 0x80, '(', 'O', 'O', 'D', 2138 | ')', '=', 'U', 'H', '5', 'D' | 0x80, 'F', '(', 2139 | 'O', 'O', 'T', ')', '=', 'U', 'H', '5', 2140 | 'T' | 0x80, '(', 'O', 'O', ')', '=', 'U', 'W', 2141 | '5' | 0x80, '(', 'O', '\'', ')', '=', 'O', 'H' | 0x80, 2142 | '(', 'O', ')', 'E', '=', 'O', 'W' | 0x80, '(', 2143 | 'O', ')', ' ', '=', 'O', 'W' | 0x80, '(', 'O', 2144 | 'A', ')', '=', 'O', 'W', '4' | 0x80, ' ', '(', 2145 | 'O', 'N', 'L', 'Y', ')', '=', 'O', 'W', 2146 | '4', 'N', 'L', 'I', 'Y' | 0x80, ' ', '(', 'O', 2147 | 'N', 'C', 'E', ')', '=', 'W', 'A', 'H', 2148 | '4', 'N', 'S' | 0x80, '(', 'O', 'N', '\'', 'T', 2149 | ')', '=', 'O', 'W', '4', 'N', 'T' | 0x80, 'C', 2150 | '(', 'O', ')', 'N', '=', 'A', 'A' | 0x80, '(', 2151 | 'O', ')', 'N', 'G', '=', 'A', 'O' | 0x80, ' ', 2152 | ':', '^', '(', 'O', ')', 'N', '=', 'A', 2153 | 'H' | 0x80, 'I', '(', 'O', 'N', ')', '=', 'U', 2154 | 'N' | 0x80, '#', ':', '(', 'O', 'N', ')', '=', 2155 | 'U', 'N' | 0x80, '#', '^', '(', 'O', 'N', ')', 2156 | '=', 'U', 'N' | 0x80, '(', 'O', ')', 'S', 'T', 2157 | '=', 'O', 'W' | 0x80, '(', 'O', 'F', ')', '^', 2158 | '=', 'A', 'O', '4', 'F' | 0x80, '(', 'O', 'T', 2159 | 'H', 'E', 'R', ')', '=', 'A', 'H', '5', 2160 | 'D', 'H', 'E', 'R' | 0x80, 'R', '(', 'O', ')', 2161 | 'B', '=', 'R', 'A', 'A' | 0x80, '^', 'R', '(', 2162 | 'O', ')', ':', '#', '=', 'O', 'W', '5' | 0x80, 2163 | '(', 'O', 'S', 'S', ')', ' ', '=', 'A', 2164 | 'O', '5', 'S' | 0x80, '#', ':', '^', '(', 'O', 2165 | 'M', ')', '=', 'A', 'H', 'M' | 0x80, '(', 'O', 2166 | ')', '=', 'A', 'A' | 0x80, 2167 | 2168 | ']', 'P' | 0x80, ' ', '(', 'P', ')', ' ', '=', 2169 | 'P', 'I', 'Y', '4' | 0x80, '(', 'P', 'H', ')', 2170 | '=', 'F' | 0x80, '(', 'P', 'E', 'O', 'P', 'L', 2171 | ')', '=', 'P', 'I', 'Y', '5', 'P', 'U', 2172 | 'L' | 0x80, '(', 'P', 'O', 'W', ')', '=', 'P', 2173 | 'A', 'W', '4' | 0x80, '(', 'P', 'U', 'T', ')', 2174 | ' ', '=', 'P', 'U', 'H', 'T' | 0x80, '(', 'P', 2175 | ')', 'P', '=' | 0x80, '(', 'P', ')', 'S', '=' | 0x80, 2176 | '(', 'P', ')', 'N', '=' | 0x80, '(', 'P', 'R', 2177 | 'O', 'F', '.', ')', '=', 'P', 'R', 'O', 2178 | 'H', 'F', 'E', 'H', '4', 'S', 'E', 'R' | 0x80, 2179 | '(', 'P', ')', '=', 'P' | 0x80, 2180 | 2181 | ']', 'Q' | 0x80, ' ', '(', 'Q', ')', ' ', '=', 2182 | 'K', 'Y', 'U', 'W', '4' | 0x80, '(', 'Q', 'U', 2183 | 'A', 'R', ')', '=', 'K', 'W', 'O', 'H', 2184 | '5', 'R' | 0x80, '(', 'Q', 'U', ')', '=', 'K', 2185 | 'W' | 0x80, '(', 'Q', ')', '=', 'K' | 0x80, ']', 'R' | 0x80, 2186 | ' ', '(', 'R', ')', ' ', '=', 'A', 'A', 2187 | '5', 'R' | 0x80, ' ', '(', 'R', 'E', ')', '^', 2188 | '#', '=', 'R', 'I', 'Y' | 0x80, '(', 'R', ')', 2189 | 'R', '=' | 0x80, '(', 'R', ')', '=', 'R' | 0x80, 2190 | 2191 | ']', 'S' | 0x80, ' ', '(', 'S', ')', ' ', '=', 2192 | 'E', 'H', '4', 'S' | 0x80, '(', 'S', 'H', ')', 2193 | '=', 'S', 'H' | 0x80, '#', '(', 'S', 'I', 'O', 2194 | 'N', ')', '=', 'Z', 'H', 'U', 'N' | 0x80, '(', 2195 | 'S', 'O', 'M', 'E', ')', '=', 'S', 'A', 2196 | 'H', 'M' | 0x80, '#', '(', 'S', 'U', 'R', ')', 2197 | '#', '=', 'Z', 'H', 'E', 'R' | 0x80, '(', 'S', 2198 | 'U', 'R', ')', '#', '=', 'S', 'H', 'E', 2199 | 'R' | 0x80, '#', '(', 'S', 'U', ')', '#', '=', 2200 | 'Z', 'H', 'U', 'W' | 0x80, '#', '(', 'S', 'S', 2201 | 'U', ')', '#', '=', 'S', 'H', 'U', 'W' | 0x80, 2202 | '#', '(', 'S', 'E', 'D', ')', '=', 'Z', 2203 | 'D' | 0x80, '#', '(', 'S', ')', '#', '=', 'Z' | 0x80, 2204 | '(', 'S', 'A', 'I', 'D', ')', '=', 'S', 2205 | 'E', 'H', 'D' | 0x80, '^', '(', 'S', 'I', 'O', 2206 | 'N', ')', '=', 'S', 'H', 'U', 'N' | 0x80, '(', 2207 | 'S', ')', 'S', '=' | 0x80, '.', '(', 'S', ')', 2208 | ' ', '=', 'Z' | 0x80, '#', ':', '.', 'E', '(', 2209 | 'S', ')', ' ', '=', 'Z' | 0x80, '#', ':', '^', 2210 | '#', '(', 'S', ')', ' ', '=', 'S' | 0x80, 'U', 2211 | '(', 'S', ')', ' ', '=', 'S' | 0x80, ' ', ':', 2212 | '#', '(', 'S', ')', ' ', '=', 'Z' | 0x80, '#', 2213 | '#', '(', 'S', ')', ' ', '=', 'Z' | 0x80, ' ', 2214 | '(', 'S', 'C', 'H', ')', '=', 'S', 'K' | 0x80, 2215 | '(', 'S', ')', 'C', '+', '=' | 0x80, '#', '(', 2216 | 'S', 'M', ')', '=', 'Z', 'U', 'M' | 0x80, '#', 2217 | '(', 'S', 'N', ')', '\'', '=', 'Z', 'U', 2218 | 'M' | 0x80, '(', 'S', 'T', 'L', 'E', ')', '=', 2219 | 'S', 'U', 'L' | 0x80, '(', 'S', ')', '=', 'S' | 0x80, 2220 | 2221 | ']', 'T' | 0x80, ' ', '(', 'T', ')', ' ', '=', 2222 | 'T', 'I', 'Y', '4' | 0x80, ' ', '(', 'T', 'H', 2223 | 'E', ')', ' ', '#', '=', 'D', 'H', 'I', 2224 | 'Y' | 0x80, ' ', '(', 'T', 'H', 'E', ')', ' ', 2225 | '=', 'D', 'H', 'A', 'X' | 0x80, '(', 'T', 'O', 2226 | ')', ' ', '=', 'T', 'U', 'X' | 0x80, ' ', '(', 2227 | 'T', 'H', 'A', 'T', ')', '=', 'D', 'H', 2228 | 'A', 'E', 'T' | 0x80, ' ', '(', 'T', 'H', 'I', 2229 | 'S', ')', ' ', '=', 'D', 'H', 'I', 'H', 2230 | 'S' | 0x80, ' ', '(', 'T', 'H', 'E', 'Y', ')', 2231 | '=', 'D', 'H', 'E', 'Y' | 0x80, ' ', '(', 'T', 2232 | 'H', 'E', 'R', 'E', ')', '=', 'D', 'H', 2233 | 'E', 'H', 'R' | 0x80, '(', 'T', 'H', 'E', 'R', 2234 | ')', '=', 'D', 'H', 'E', 'R' | 0x80, '(', 'T', 2235 | 'H', 'E', 'I', 'R', ')', '=', 'D', 'H', 2236 | 'E', 'H', 'R' | 0x80, ' ', '(', 'T', 'H', 'A', 2237 | 'N', ')', ' ', '=', 'D', 'H', 'A', 'E', 2238 | 'N' | 0x80, ' ', '(', 'T', 'H', 'E', 'M', ')', 2239 | ' ', '=', 'D', 'H', 'A', 'E', 'N' | 0x80, '(', 2240 | 'T', 'H', 'E', 'S', 'E', ')', ' ', '=', 2241 | 'D', 'H', 'I', 'Y', 'Z' | 0x80, ' ', '(', 'T', 2242 | 'H', 'E', 'N', ')', '=', 'D', 'H', 'E', 2243 | 'H', 'N' | 0x80, '(', 'T', 'H', 'R', 'O', 'U', 2244 | 'G', 'H', ')', '=', 'T', 'H', 'R', 'U', 2245 | 'W', '4' | 0x80, '(', 'T', 'H', 'O', 'S', 'E', 2246 | ')', '=', 'D', 'H', 'O', 'H', 'Z' | 0x80, '(', 2247 | 'T', 'H', 'O', 'U', 'G', 'H', ')', ' ', 2248 | '=', 'D', 'H', 'O', 'W' | 0x80, '(', 'T', 'O', 2249 | 'D', 'A', 'Y', ')', '=', 'T', 'U', 'X', 2250 | 'D', 'E', 'Y' | 0x80, '(', 'T', 'O', 'M', 'O', 2251 | ')', 'R', 'R', 'O', 'W', '=', 'T', 'U', 2252 | 'M', 'A', 'A', '5' | 0x80, '(', 'T', 'O', ')', 2253 | 'T', 'A', 'L', '=', 'T', 'O', 'W', '5' | 0x80, 2254 | ' ', '(', 'T', 'H', 'U', 'S', ')', '=', 2255 | 'D', 'H', 'A', 'H', '4', 'S' | 0x80, '(', 'T', 2256 | 'H', ')', '=', 'T', 'H' | 0x80, '#', ':', '(', 2257 | 'T', 'E', 'D', ')', '=', 'T', 'I', 'X', 2258 | 'D' | 0x80, 'S', '(', 'T', 'I', ')', '#', 'N', 2259 | '=', 'C', 'H' | 0x80, '(', 'T', 'I', ')', 'O', 2260 | '=', 'S', 'H' | 0x80, '(', 'T', 'I', ')', 'A', 2261 | '=', 'S', 'H' | 0x80, '(', 'T', 'I', 'E', 'N', 2262 | ')', '=', 'S', 'H', 'U', 'N' | 0x80, '(', 'T', 2263 | 'U', 'R', ')', '#', '=', 'C', 'H', 'E', 2264 | 'R' | 0x80, '(', 'T', 'U', ')', 'A', '=', 'C', 2265 | 'H', 'U', 'W' | 0x80, ' ', '(', 'T', 'W', 'O', 2266 | ')', '=', 'T', 'U', 'W' | 0x80, '&', '(', 'T', 2267 | ')', 'E', 'N', ' ', '=' | 0x80, '(', 'T', ')', 2268 | '=', 'T' | 0x80, 2269 | 2270 | ']', 'U' | 0x80, ' ', '(', 'U', ')', ' ', '=', 2271 | 'Y', 'U', 'W', '4' | 0x80, ' ', '(', 'U', 'N', 2272 | ')', 'I', '=', 'Y', 'U', 'W', 'N' | 0x80, ' ', 2273 | '(', 'U', 'N', ')', '=', 'A', 'H', 'N' | 0x80, 2274 | ' ', '(', 'U', 'P', 'O', 'N', ')', '=', 2275 | 'A', 'X', 'P', 'A', 'O', 'N' | 0x80, '@', '(', 2276 | 'U', 'R', ')', '#', '=', 'U', 'H', '4', 2277 | 'R' | 0x80, '(', 'U', 'R', ')', '#', '=', 'Y', 2278 | 'U', 'H', '4', 'R' | 0x80, '(', 'U', 'R', ')', 2279 | '=', 'E', 'R' | 0x80, '(', 'U', ')', '^', ' ', 2280 | '=', 'A', 'H' | 0x80, '(', 'U', ')', '^', '^', 2281 | '=', 'A', 'H', '5' | 0x80, '(', 'U', 'Y', ')', 2282 | '=', 'A', 'Y', '5' | 0x80, ' ', 'G', '(', 'U', 2283 | ')', '#', '=' | 0x80, 'G', '(', 'U', ')', '%', 2284 | '=' | 0x80, 'G', '(', 'U', ')', '#', '=', 'W' | 0x80, 2285 | '#', 'N', '(', 'U', ')', '=', 'Y', 'U', 2286 | 'W' | 0x80, '@', '(', 'U', ')', '=', 'U', 'W' | 0x80, 2287 | '(', 'U', ')', '=', 'Y', 'U', 'W' | 0x80, 2288 | 2289 | ']', 'V' | 0x80, ' ', '(', 'V', ')', ' ', '=', 2290 | 'V', 'I', 'Y', '4' | 0x80, '(', 'V', 'I', 'E', 2291 | 'W', ')', '=', 'V', 'Y', 'U', 'W', '5' | 0x80, 2292 | '(', 'V', ')', '=', 'V' | 0x80, 2293 | 2294 | ']', 'W' | 0x80, ' ', '(', 'W', ')', ' ', '=', 2295 | 'D', 'A', 'H', '4', 'B', 'U', 'L', 'Y', 2296 | 'U', 'W' | 0x80, ' ', '(', 'W', 'E', 'R', 'E', 2297 | ')', '=', 'W', 'E', 'R' | 0x80, '(', 'W', 'A', 2298 | ')', 'S', 'H', '=', 'W', 'A', 'A' | 0x80, '(', 2299 | 'W', 'A', ')', 'S', 'T', '=', 'W', 'E', 2300 | 'Y' | 0x80, '(', 'W', 'A', ')', 'S', '=', 'W', 2301 | 'A', 'H' | 0x80, '(', 'W', 'A', ')', 'T', '=', 2302 | 'W', 'A', 'A' | 0x80, '(', 'W', 'H', 'E', 'R', 2303 | 'E', ')', '=', 'W', 'H', 'E', 'H', 'R' | 0x80, 2304 | '(', 'W', 'H', 'A', 'T', ')', '=', 'W', 2305 | 'H', 'A', 'H', 'T' | 0x80, '(', 'W', 'H', 'O', 2306 | 'L', ')', '=', '/', 'H', 'O', 'W', 'L' | 0x80, 2307 | '(', 'W', 'H', 'O', ')', '=', '/', 'H', 2308 | 'U', 'W' | 0x80, '(', 'W', 'H', ')', '=', 'W', 2309 | 'H' | 0x80, '(', 'W', 'A', 'R', ')', '#', '=', 2310 | 'W', 'E', 'H', 'R' | 0x80, '(', 'W', 'A', 'R', 2311 | ')', '=', 'W', 'A', 'O', 'R' | 0x80, '(', 'W', 2312 | 'O', 'R', ')', '^', '=', 'W', 'E', 'R' | 0x80, 2313 | '(', 'W', 'R', ')', '=', 'R' | 0x80, '(', 'W', 2314 | 'O', 'M', ')', 'A', '=', 'W', 'U', 'H', 2315 | 'M' | 0x80, '(', 'W', 'O', 'M', ')', 'E', '=', 2316 | 'W', 'I', 'H', 'M' | 0x80, '(', 'W', 'E', 'A', 2317 | ')', 'R', '=', 'W', 'E', 'H' | 0x80, '(', 'W', 2318 | 'A', 'N', 'T', ')', '=', 'W', 'A', 'A', 2319 | '5', 'N', 'T' | 0x80, 'A', 'N', 'S', '(', 'W', 2320 | 'E', 'R', ')', '=', 'E', 'R' | 0x80, '(', 'W', 2321 | ')', '=', 'W' | 0x80, 2322 | 2323 | ']', 'X' | 0x80, ' ', '(', 'X', ')', ' ', '=', 2324 | 'E', 'H', '4', 'K', 'R' | 0x80, ' ', '(', 'X', 2325 | ')', '=', 'Z' | 0x80, '(', 'X', ')', '=', 'K', 2326 | 'S' | 0x80, 2327 | 2328 | ']', 'Y' | 0x80, ' ', '(', 'Y', ')', ' ', '=', 2329 | 'W', 'A', 'Y', '4' | 0x80, '(', 'Y', 'O', 'U', 2330 | 'N', 'G', ')', '=', 'Y', 'A', 'H', 'N', 2331 | 'X' | 0x80, ' ', '(', 'Y', 'O', 'U', 'R', ')', 2332 | '=', 'Y', 'O', 'H', 'R' | 0x80, ' ', '(', 'Y', 2333 | 'O', 'U', ')', '=', 'Y', 'U', 'W' | 0x80, ' ', 2334 | '(', 'Y', 'E', 'S', ')', '=', 'Y', 'E', 2335 | 'H', 'S' | 0x80, ' ', '(', 'Y', ')', '=', 'Y' | 0x80, 2336 | 'F', '(', 'Y', ')', '=', 'A', 'Y' | 0x80, 'P', 2337 | 'S', '(', 'Y', 'C', 'H', ')', '=', 'A', 2338 | 'Y', 'K' | 0x80, '#', ':', '^', '(', 'Y', ')', 2339 | '=', 'I', 'Y' | 0x80, '#', ':', '^', '(', 'Y', 2340 | ')', 'I', '=', 'I', 'Y' | 0x80, ' ', ':', '(', 2341 | 'Y', ')', ' ', '=', 'A', 'Y' | 0x80, ' ', ':', 2342 | '(', 'Y', ')', '#', '=', 'A', 'Y' | 0x80, ' ', 2343 | ':', '(', 'Y', ')', '^', '+', ':', '#', 2344 | '=', 'I', 'H' | 0x80, ' ', ':', '(', 'Y', ')', 2345 | '^', '#', '=', 'A', 'Y' | 0x80, '(', 'Y', ')', 2346 | '=', 'I', 'H' | 0x80, 2347 | 2348 | ']', 'Z' | 0x80, ' ', '(', 'Z', ')', ' ', '=', 2349 | 'Z', 'I', 'Y', '4' | 0x80, '(', 'Z', ')', '=', 2350 | 'Z' | 0x80, 'j' | 0x80}; 2351 | 2352 | const unsigned char rules2[] = { 2353 | '(', 'A', ')', '=' | 0x80, '(', '!', ')', '=', 2354 | '.' | 0x80, '(', '"', ')', ' ', '=', '-', 'A', 2355 | 'H', '5', 'N', 'K', 'W', 'O', 'W', 'T', 2356 | '-' | 0x80, '(', '"', ')', '=', 'K', 'W', 'O', 2357 | 'W', '4', 'T', '-' | 0x80, '(', '#', ')', '=', 2358 | ' ', 'N', 'A', 'H', '4', 'M', 'B', 'E', 2359 | 'R' | 0x80, '(', '$', ')', '=', ' ', 'D', 'A', 2360 | 'A', '4', 'L', 'E', 'R' | 0x80, '(', '%', ')', 2361 | '=', ' ', 'P', 'E', 'R', 'S', 'E', 'H', 2362 | '4', 'N', 'T' | 0x80, '(', '&', ')', '=', ' ', 2363 | 'A', 'E', 'N', 'D' | 0x80, '(', '\'', ')', '=' | 0x80, 2364 | '(', '*', ')', '=', ' ', 'A', 'E', '4', 2365 | 'S', 'T', 'E', 'R', 'I', 'H', 'S', 'K' | 0x80, 2366 | '(', '+', ')', '=', ' ', 'P', 'L', 'A', 2367 | 'H', '4', 'S' | 0x80, '(', ',', ')', '=', ',' | 0x80, 2368 | ' ', '(', '-', ')', ' ', '=', '-' | 0x80, '(', 2369 | '-', ')', '=' | 0x80, '(', '.', ')', '=', ' ', 2370 | 'P', 'O', 'Y', 'N', 'T' | 0x80, '(', '/', ')', 2371 | '=', ' ', 'S', 'L', 'A', 'E', '4', 'S', 2372 | 'H' | 0x80, '(', '0', ')', '=', ' ', 'Z', 'I', 2373 | 'Y', '4', 'R', 'O', 'W' | 0x80, ' ', '(', '1', 2374 | 'S', 'T', ')', '=', 'F', 'E', 'R', '4', 2375 | 'S', 'T' | 0x80, ' ', '(', '1', '0', 'T', 'H', 2376 | ')', '=', 'T', 'E', 'H', '4', 'N', 'T', 2377 | 'H' | 0x80, '(', '1', ')', '=', ' ', 'W', 'A', 2378 | 'H', '4', 'N' | 0x80, ' ', '(', '2', 'N', 'D', 2379 | ')', '=', 'S', 'E', 'H', '4', 'K', 'U', 2380 | 'N', 'D' | 0x80, '(', '2', ')', '=', ' ', 'T', 2381 | 'U', 'W', '4' | 0x80, ' ', '(', '3', 'R', 'D', 2382 | ')', '=', 'T', 'H', 'E', 'R', '4', 'D' | 0x80, 2383 | '(', '3', ')', '=', ' ', 'T', 'H', 'R', 2384 | 'I', 'Y', '4' | 0x80, '(', '4', ')', '=', ' ', 2385 | 'F', 'O', 'H', '4', 'R' | 0x80, ' ', '(', '5', 2386 | 'T', 'H', ')', '=', 'F', 'I', 'H', '4', 2387 | 'F', 'T', 'H' | 0x80, '(', '5', ')', '=', ' ', 2388 | 'F', 'A', 'Y', '4', 'V' | 0x80, ' ', '(', '6', 2389 | '4', ')', ' ', '=', 'S', 'I', 'H', '4', 2390 | 'K', 'S', 'T', 'I', 'Y', ' ', 'F', 'O', 2391 | 'H', 'R' | 0x80, '(', '6', ')', '=', ' ', 'S', 2392 | 'I', 'H', '4', 'K', 'S' | 0x80, '(', '7', ')', 2393 | '=', ' ', 'S', 'E', 'H', '4', 'V', 'U', 2394 | 'N' | 0x80, ' ', '(', '8', 'T', 'H', ')', '=', 2395 | 'E', 'Y', '4', 'T', 'H' | 0x80, '(', '8', ')', 2396 | '=', ' ', 'E', 'Y', '4', 'T' | 0x80, '(', '9', 2397 | ')', '=', ' ', 'N', 'A', 'Y', '4', 'N' | 0x80, 2398 | '(', ':', ')', '=', '.' | 0x80, '(', ';', ')', 2399 | '=', '.' | 0x80, '(', '<', ')', '=', ' ', 'L', 2400 | 'E', 'H', '4', 'S', ' ', 'D', 'H', 'A', 2401 | 'E', 'N' | 0x80, '(', '=', ')', '=', ' ', 'I', 2402 | 'Y', '4', 'K', 'W', 'U', 'L', 'Z' | 0x80, '(', 2403 | '>', ')', '=', ' ', 'G', 'R', 'E', 'Y', 2404 | '4', 'T', 'E', 'R', ' ', 'D', 'H', 'A', 2405 | 'E', 'N' | 0x80, '(', '?', ')', '=', '?' | 0x80, '(', 2406 | '@', ')', '=', ' ', 'A', 'E', '6', 'T' | 0x80, 2407 | '(', '^', ')', '=', ' ', 'K', 'A', 'E', 2408 | '4', 'R', 'I', 'X', 'T' | 0x80, ']', 'A' | 0x80}; 2409 | 2410 | //26 items. From 'A' to 'Z' 2411 | // positions for mem62 and mem63 for each character 2412 | const unsigned char tab37489[] = {0, 149, 247, 162, 57, 197, 6, 126, 199, 38, 55, 78, 145, 2413 | 241, 85, 161, 254, 36, 69, 45, 167, 54, 83, 46, 71, 218}; 2414 | 2415 | const unsigned char tab37515[] = {125, 126, 126, 127, 128, 129, 130, 130, 130, 132, 132, 132, 132, 2416 | 132, 133, 135, 135, 136, 136, 137, 138, 139, 139, 140, 140, 140}; 2417 | 2418 | void STM32SAM::Output8BitAry(int index, unsigned char ary[5]) { 2419 | int k; 2420 | 2421 | uint32_t bufferposOld = bufferpos; 2422 | 2423 | bufferpos += timetable[oldtimetableindex][index]; 2424 | oldtimetableindex = index; 2425 | 2426 | int sample_uS = bufferpos - bufferposOld; 2427 | 2428 | uint32_t f = 0; 2429 | 2430 | // write a little bit in advance 2431 | for(k = 0; k < 5; k++) { 2432 | // buffer[bufferpos / 50 + k] = ary[k]; 2433 | 2434 | // f = micros() + sample_uS / (_STM32SAM_SPEED + 1); 2435 | // while(micros() < f) { 2436 | // }; 2437 | f = sample_uS / (_STM32SAM_SPEED + 1); 2438 | furi_delay_us(f); 2439 | SetAUDIO(ary[k]); 2440 | // delayMicroseconds(sample_uS / 5 ); 2441 | } 2442 | 2443 | // SetAUDIO(ary[0]); 2444 | } 2445 | 2446 | void STM32SAM::Output8Bit(int index, unsigned char A) { 2447 | unsigned char ary[5] = {A, A, A, A, A}; 2448 | Output8BitAry(index, ary); 2449 | } 2450 | 2451 | //written by me because of different table positions. 2452 | // mem[47] = ... 2453 | // 168=pitches 2454 | // 169=frequency1 2455 | // 170=frequency2 2456 | // 171=frequency3 2457 | // 172=amplitude1 2458 | // 173=amplitude2 2459 | // 174=amplitude3 2460 | unsigned char STM32SAM::Read(unsigned char p, unsigned char Y) { 2461 | switch(p) { 2462 | case 168: 2463 | return pitches[Y]; 2464 | case 169: 2465 | return frequency1[Y]; 2466 | case 170: 2467 | return frequency2[Y]; 2468 | case 171: 2469 | return frequency3[Y]; 2470 | case 172: 2471 | return amplitude1[Y]; 2472 | case 173: 2473 | return amplitude2[Y]; 2474 | case 174: 2475 | return amplitude3[Y]; 2476 | } 2477 | // Serial1.println("Error reading to tables"); 2478 | return 0; 2479 | } 2480 | 2481 | void STM32SAM::Write(unsigned char p, unsigned char Y, unsigned char value) { 2482 | switch(p) { 2483 | case 168: 2484 | pitches[Y] = value; 2485 | return; 2486 | case 169: 2487 | frequency1[Y] = value; 2488 | return; 2489 | case 170: 2490 | frequency2[Y] = value; 2491 | return; 2492 | case 171: 2493 | frequency3[Y] = value; 2494 | return; 2495 | case 172: 2496 | amplitude1[Y] = value; 2497 | return; 2498 | case 173: 2499 | amplitude2[Y] = value; 2500 | return; 2501 | case 174: 2502 | amplitude3[Y] = value; 2503 | return; 2504 | } 2505 | //Serial1.println("Error writing to tables\n"); 2506 | } 2507 | 2508 | // ------------------------------------------------------------------------- 2509 | //Code48227 2510 | // Render a sampled sound from the sampleTable. 2511 | // 2512 | // Phoneme Sample Start Sample End 2513 | // 32: S* 15 255 2514 | // 33: SH 257 511 2515 | // 34: F* 559 767 2516 | // 35: TH 583 767 2517 | // 36: /H 903 1023 2518 | // 37: /X 1135 1279 2519 | // 38: Z* 84 119 2520 | // 39: ZH 340 375 2521 | // 40: V* 596 639 2522 | // 41: DH 596 631 2523 | // 2524 | // 42: CH 2525 | // 43: ** 399 511 2526 | // 2527 | // 44: J* 2528 | // 45: ** 257 276 2529 | // 46: ** 2530 | // 2531 | // 66: P* 2532 | // 67: ** 743 767 2533 | // 68: ** 2534 | // 2535 | // 69: T* 2536 | // 70: ** 231 255 2537 | // 71: ** 2538 | // 2539 | // The SampledPhonemesTable[] holds flags indicating if a phoneme is 2540 | // voiced or not. If the upper 5 bits are zero, the sample is voiced. 2541 | // 2542 | // Samples in the sampleTable are compressed, with bits being converted to 2543 | // bytes from high bit to low, as follows: 2544 | // 2545 | // unvoiced 0 bit -> X 2546 | // unvoiced 1 bit -> 5 2547 | // 2548 | // voiced 0 bit -> 6 2549 | // voiced 1 bit -> 24 2550 | // 2551 | // Where X is a value from the table: 2552 | // 2553 | // { 0x18, 0x1A, 0x17, 0x17, 0x17 }; 2554 | // 2555 | // The index into this table is determined by masking off the lower 2556 | // 3 bits from the SampledPhonemesTable: 2557 | // 2558 | // index = (SampledPhonemesTable[i] & 7) - 1; 2559 | // 2560 | // For voices samples, samples are interleaved between voiced output. 2561 | 2562 | // Code48227() 2563 | void STM32SAM::RenderSample(unsigned char* mem66) { 2564 | int tempA; 2565 | // current phoneme's index 2566 | mem49 = Y; 2567 | 2568 | // mask low three bits and subtract 1 get value to 2569 | // convert 0 bits on unvoiced samples. 2570 | A = mem39 & 7; 2571 | X = A - 1; 2572 | 2573 | // store the result 2574 | mem56 = X; 2575 | 2576 | // determine which offset to use from table { 0x18, 0x1A, 0x17, 0x17, 0x17 } 2577 | // T, S, Z 0 0x18 2578 | // CH, J, SH, ZH 1 0x1A 2579 | // P, F*, V, TH, DH 2 0x17 2580 | // /H 3 0x17 2581 | // /X 4 0x17 2582 | 2583 | // get value from the table 2584 | mem53 = tab48426[X]; 2585 | mem47 = X; //46016+mem[56]*256 2586 | 2587 | // voiced sample? 2588 | A = mem39 & 248; 2589 | if(A == 0) { 2590 | // voiced phoneme: Z*, ZH, V*, DH 2591 | Y = mem49; 2592 | A = pitches[mem49] >> 4; 2593 | 2594 | // jump to voiced portion 2595 | goto pos48315; 2596 | } 2597 | 2598 | Y = A ^ 255; 2599 | pos48274: 2600 | 2601 | // step through the 8 bits in the sample 2602 | mem56 = 8; 2603 | 2604 | // get the next sample from the table 2605 | // mem47*256 = offset to start of samples 2606 | A = sampleTable[mem47 * 256 + Y]; 2607 | pos48280: 2608 | 2609 | // left shift to get the high bit 2610 | tempA = A; 2611 | A = A << 1; 2612 | //48281: BCC 48290 2613 | 2614 | // bit not set? 2615 | if((tempA & 128) == 0) { 2616 | // convert the bit to value from table 2617 | X = mem53; 2618 | //mem[54296] = X; 2619 | // output the byte 2620 | Output8Bit(1, (X & 0x0f) * 16); 2621 | // if X != 0, exit loop 2622 | if(X != 0) goto pos48296; 2623 | } 2624 | 2625 | // output a 5 for the on bit 2626 | Output8Bit(2, 5 * 16); 2627 | 2628 | //48295: NOP 2629 | pos48296: 2630 | 2631 | X = 0; 2632 | 2633 | // decrement counter 2634 | mem56--; 2635 | 2636 | // if not done, jump to top of loop 2637 | if(mem56 != 0) goto pos48280; 2638 | 2639 | // increment position 2640 | Y++; 2641 | if(Y != 0) goto pos48274; 2642 | 2643 | // restore values and return 2644 | mem44 = 1; 2645 | Y = mem49; 2646 | return; 2647 | 2648 | unsigned char phase1; 2649 | 2650 | pos48315: 2651 | // handle voiced samples here 2652 | 2653 | // number of samples? 2654 | phase1 = A ^ 255; 2655 | 2656 | Y = *mem66; 2657 | do { 2658 | //pos48321: 2659 | 2660 | // shift through all 8 bits 2661 | mem56 = 8; 2662 | //A = Read(mem47, Y); 2663 | 2664 | // fetch value from table 2665 | A = sampleTable[mem47 * 256 + Y]; 2666 | 2667 | // loop 8 times 2668 | //pos48327: 2669 | do { 2670 | //48327: ASL A 2671 | //48328: BCC 48337 2672 | 2673 | // left shift and check high bit 2674 | tempA = A; 2675 | A = A << 1; 2676 | if((tempA & 128) != 0) { 2677 | // if bit set, output 26 2678 | X = 26; 2679 | Output8Bit(3, (X & 0xf) * 16); 2680 | } else { 2681 | //timetable 4 2682 | // bit is not set, output a 6 2683 | X = 6; 2684 | Output8Bit(4, (X & 0xf) * 16); 2685 | } 2686 | 2687 | mem56--; 2688 | } while(mem56 != 0); 2689 | 2690 | // move ahead in the table 2691 | Y++; 2692 | 2693 | // continue until counter done 2694 | phase1++; 2695 | 2696 | } while(phase1 != 0); 2697 | // if (phase1 != 0) goto pos48321; 2698 | 2699 | // restore values and return 2700 | A = 1; 2701 | mem44 = 1; 2702 | *mem66 = Y; 2703 | Y = mem49; 2704 | return; 2705 | } 2706 | 2707 | // RENDER THE PHONEMES IN THE LIST 2708 | // 2709 | // The phoneme list is converted into sound through the steps: 2710 | // 2711 | // 1. Copy each phoneme number of times into the frames list, 2712 | // where each frame represents 10 milliseconds of sound. 2713 | // 2714 | // 2. Determine the transitions lengths between phonemes, and linearly 2715 | // interpolate the values across the frames. 2716 | // 2717 | // 3. Offset the pitches by the fundamental frequency. 2718 | // 2719 | // 4. Render the each frame. 2720 | 2721 | //void Code47574() 2722 | void STM32SAM::Render() { 2723 | unsigned char phase1 = 0; //mem43 2724 | unsigned char phase2 = 0; 2725 | unsigned char phase3 = 0; 2726 | unsigned char mem66 = 0; 2727 | unsigned char mem38 = 0; 2728 | unsigned char mem40 = 0; 2729 | unsigned char speedcounter = 0; //mem45 2730 | unsigned char mem48 = 0; 2731 | int i; 2732 | if(phonemeIndexOutput[0] == 255) return; //exit if no data 2733 | 2734 | A = 0; 2735 | X = 0; 2736 | mem44 = 0; 2737 | 2738 | // CREATE FRAMES 2739 | // 2740 | // The length parameter in the list corresponds to the number of frames 2741 | // to expand the phoneme to. Each frame represents 10 milliseconds of time. 2742 | // So a phoneme with a length of 7 = 7 frames = 70 milliseconds duration. 2743 | // 2744 | // The parameters are copied from the phoneme to the frame verbatim. 2745 | 2746 | // pos47587: 2747 | do { 2748 | // get the index 2749 | Y = mem44; 2750 | // get the phoneme at the index 2751 | A = phonemeIndexOutput[mem44]; 2752 | mem56 = A; 2753 | 2754 | // if terminal phoneme, exit the loop 2755 | if(A == 255) break; 2756 | 2757 | // period phoneme *. 2758 | if(A == 1) { 2759 | // add rising inflection 2760 | A = 1; 2761 | mem48 = 1; 2762 | //goto pos48376; 2763 | AddInflection(mem48, phase1); 2764 | } 2765 | /* 2766 | if (A == 2) goto pos48372; 2767 | */ 2768 | 2769 | // question mark phoneme? 2770 | if(A == 2) { 2771 | // create falling inflection 2772 | mem48 = 255; 2773 | AddInflection(mem48, phase1); 2774 | } 2775 | // pos47615: 2776 | 2777 | // get the stress amount (more stress = higher pitch) 2778 | phase1 = tab47492[stressOutput[Y] + 1]; 2779 | 2780 | // get number of frames to write 2781 | phase2 = phonemeLengthOutput[Y]; 2782 | Y = mem56; 2783 | 2784 | // copy from the source to the frames list 2785 | do { 2786 | frequency1[X] = freq1data[Y]; // F1 frequency 2787 | frequency2[X] = freq2data[Y]; // F2 frequency 2788 | frequency3[X] = freq3data[Y]; // F3 frequency 2789 | amplitude1[X] = ampl1data[Y]; // F1 amplitude 2790 | amplitude2[X] = ampl2data[Y]; // F2 amplitude 2791 | amplitude3[X] = ampl3data[Y]; // F3 amplitude 2792 | sampledConsonantFlag[X] = 2793 | sampledConsonantFlags[Y]; // phoneme data for sampled consonants 2794 | pitches[X] = pitch + phase1; // pitch 2795 | X++; 2796 | phase2--; 2797 | } while(phase2 != 0); 2798 | mem44++; 2799 | } while(mem44 != 0); 2800 | // ------------------- 2801 | //pos47694: 2802 | 2803 | // CREATE TRANSITIONS 2804 | // 2805 | // Linear transitions are now created to smoothly connect the 2806 | // end of one sustained portion of a phoneme to the following 2807 | // phoneme. 2808 | // 2809 | // To do this, three tables are used: 2810 | // 2811 | // Table Purpose 2812 | // ========= ================================================== 2813 | // blendRank Determines which phoneme's blend values are used. 2814 | // 2815 | // blendOut The number of frames at the end of the phoneme that 2816 | // will be used to transition to the following phoneme. 2817 | // 2818 | // blendIn The number of frames of the following phoneme that 2819 | // will be used to transition into that phoneme. 2820 | // 2821 | // In creating a transition between two phonemes, the phoneme 2822 | // with the HIGHEST rank is used. Phonemes are ranked on how much 2823 | // their identity is based on their transitions. For example, 2824 | // vowels are and diphthongs are identified by their sustained portion, 2825 | // rather than the transitions, so they are given low values. In contrast, 2826 | // stop consonants (P, B, T, K) and glides (Y, L) are almost entirely 2827 | // defined by their transitions, and are given high rank values. 2828 | // 2829 | // Here are the rankings used by SAM: 2830 | // 2831 | // Rank Type Phonemes 2832 | // 2 All vowels IY, IH, etc. 2833 | // 5 Diphthong endings YX, WX, ER 2834 | // 8 Terminal liquid consonants LX, WX, YX, N, NX 2835 | // 9 Liquid consonants L, RX, W 2836 | // 10 Glide R, OH 2837 | // 11 Glide WH 2838 | // 18 Voiceless fricatives S, SH, F, TH 2839 | // 20 Voiced fricatives Z, ZH, V, DH 2840 | // 23 Plosives, stop consonants P, T, K, KX, DX, CH 2841 | // 26 Stop consonants J, GX, B, D, G 2842 | // 27-29 Stop consonants (internal) ** 2843 | // 30 Unvoiced consonants /H, /X and Q* 2844 | // 160 Nasal M 2845 | // 2846 | // To determine how many frames to use, the two phonemes are 2847 | // compared using the blendRank[] table. The phoneme with the 2848 | // higher rank is selected. In case of a tie, a blend of each is used: 2849 | // 2850 | // if blendRank[phoneme1] == blendRank[phomneme2] 2851 | // // use lengths from each phoneme 2852 | // outBlendFrames = outBlend[phoneme1] 2853 | // inBlendFrames = outBlend[phoneme2] 2854 | // else if blendRank[phoneme1] > blendRank[phoneme2] 2855 | // // use lengths from first phoneme 2856 | // outBlendFrames = outBlendLength[phoneme1] 2857 | // inBlendFrames = inBlendLength[phoneme1] 2858 | // else 2859 | // // use lengths from the second phoneme 2860 | // // note that in and out are SWAPPED! 2861 | // outBlendFrames = inBlendLength[phoneme2] 2862 | // inBlendFrames = outBlendLength[phoneme2] 2863 | // 2864 | // Blend lengths can't be less than zero. 2865 | // 2866 | // Transitions are assumed to be symetrical, so if the transition 2867 | // values for the second phoneme are used, the inBlendLength and 2868 | // outBlendLength values are SWAPPED. 2869 | // 2870 | // For most of the parameters, SAM interpolates over the range of the last 2871 | // outBlendFrames-1 and the first inBlendFrames. 2872 | // 2873 | // The exception to this is the Pitch[] parameter, which is interpolates the 2874 | // pitch from the CENTER of the current phoneme to the CENTER of the next 2875 | // phoneme. 2876 | // 2877 | // Here are two examples. First, For example, consider the word "SUN" (S AH N) 2878 | // 2879 | // Phoneme Duration BlendWeight OutBlendFrames InBlendFrames 2880 | // S 2 18 1 3 2881 | // AH 8 2 4 4 2882 | // N 7 8 1 2 2883 | // 2884 | // The formant transitions for the output frames are calculated as follows: 2885 | // 2886 | // flags ampl1 freq1 ampl2 freq2 ampl3 freq3 pitch 2887 | // ------------------------------------------------ 2888 | // S 2889 | // 241 0 6 0 73 0 99 61 Use S (weight 18) for transition instead of AH (weight 2) 2890 | // 241 0 6 0 73 0 99 61 <-- (OutBlendFrames-1) = (1-1) = 0 frames 2891 | // AH 2892 | // 0 2 10 2 66 0 96 59 * <-- InBlendFrames = 3 frames 2893 | // 0 4 14 3 59 0 93 57 * 2894 | // 0 8 18 5 52 0 90 55 * 2895 | // 0 15 22 9 44 1 87 53 2896 | // 0 15 22 9 44 1 87 53 2897 | // 0 15 22 9 44 1 87 53 Use N (weight 8) for transition instead of AH (weight 2). 2898 | // 0 15 22 9 44 1 87 53 Since N is second phoneme, reverse the IN and OUT values. 2899 | // 0 11 17 8 47 1 98 56 * <-- (InBlendFrames-1) = (2-1) = 1 frames 2900 | // N 2901 | // 0 8 12 6 50 1 109 58 * <-- OutBlendFrames = 1 2902 | // 0 5 6 5 54 0 121 61 2903 | // 0 5 6 5 54 0 121 61 2904 | // 0 5 6 5 54 0 121 61 2905 | // 0 5 6 5 54 0 121 61 2906 | // 0 5 6 5 54 0 121 61 2907 | // 0 5 6 5 54 0 121 61 2908 | // 2909 | // Now, consider the reverse "NUS" (N AH S): 2910 | // 2911 | // flags ampl1 freq1 ampl2 freq2 ampl3 freq3 pitch 2912 | // ------------------------------------------------ 2913 | // N 2914 | // 0 5 6 5 54 0 121 61 2915 | // 0 5 6 5 54 0 121 61 2916 | // 0 5 6 5 54 0 121 61 2917 | // 0 5 6 5 54 0 121 61 2918 | // 0 5 6 5 54 0 121 61 2919 | // 0 5 6 5 54 0 121 61 Use N (weight 8) for transition instead of AH (weight 2) 2920 | // 0 5 6 5 54 0 121 61 <-- (OutBlendFrames-1) = (1-1) = 0 frames 2921 | // AH 2922 | // 0 8 11 6 51 0 110 59 * <-- InBlendFrames = 2 2923 | // 0 11 16 8 48 0 99 56 * 2924 | // 0 15 22 9 44 1 87 53 Use S (weight 18) for transition instead of AH (weight 2) 2925 | // 0 15 22 9 44 1 87 53 Since S is second phoneme, reverse the IN and OUT values. 2926 | // 0 9 18 5 51 1 90 55 * <-- (InBlendFrames-1) = (3-1) = 2 2927 | // 0 4 14 3 58 1 93 57 * 2928 | // S 2929 | // 241 2 10 2 65 1 96 59 * <-- OutBlendFrames = 1 2930 | // 241 0 6 0 73 0 99 61 2931 | 2932 | A = 0; 2933 | mem44 = 0; 2934 | mem49 = 0; // mem49 starts at as 0 2935 | X = 0; 2936 | while(1) //while No. 1 2937 | { 2938 | // get the current and following phoneme 2939 | Y = phonemeIndexOutput[X]; 2940 | A = phonemeIndexOutput[X + 1]; 2941 | X++; 2942 | 2943 | // exit loop at end token 2944 | if(A == 255) break; //goto pos47970; 2945 | 2946 | // get the ranking of each phoneme 2947 | X = A; 2948 | mem56 = blendRank[A]; 2949 | A = blendRank[Y]; 2950 | 2951 | // compare the rank - lower rank value is stronger 2952 | if(A == mem56) { 2953 | // same rank, so use out blend lengths from each phoneme 2954 | phase1 = outBlendLength[Y]; 2955 | phase2 = outBlendLength[X]; 2956 | } else if(A < mem56) { 2957 | // first phoneme is stronger, so us it's blend lengths 2958 | phase1 = inBlendLength[X]; 2959 | phase2 = outBlendLength[X]; 2960 | } else { 2961 | // second phoneme is stronger, so use it's blend lengths 2962 | // note the out/in are swapped 2963 | phase1 = outBlendLength[Y]; 2964 | phase2 = inBlendLength[Y]; 2965 | } 2966 | 2967 | Y = mem44; 2968 | A = mem49 + phonemeLengthOutput[mem44]; // A is mem49 + length 2969 | mem49 = A; // mem49 now holds length + position 2970 | A = A + phase2; //Maybe Problem because of carry flag 2971 | 2972 | //47776: ADC 42 2973 | speedcounter = A; 2974 | mem47 = 168; 2975 | phase3 = mem49 - phase1; // what is mem49 2976 | A = phase1 + phase2; // total transition? 2977 | mem38 = A; 2978 | 2979 | X = A; 2980 | X -= 2; 2981 | if((X & 128) == 0) 2982 | do //while No. 2 2983 | { 2984 | //pos47810: 2985 | 2986 | // mem47 is used to index the tables: 2987 | // 168 pitches[] 2988 | // 169 frequency1 2989 | // 170 frequency2 2990 | // 171 frequency3 2991 | // 172 amplitude1 2992 | // 173 amplitude2 2993 | // 174 amplitude3 2994 | 2995 | mem40 = mem38; 2996 | 2997 | if(mem47 == 168) // pitch 2998 | { 2999 | // unlike the other values, the pitches[] interpolates from 3000 | // the middle of the current phoneme to the middle of the 3001 | // next phoneme 3002 | 3003 | unsigned char mem36, mem37; 3004 | // half the width of the current phoneme 3005 | mem36 = phonemeLengthOutput[mem44] >> 1; 3006 | // half the width of the next phoneme 3007 | mem37 = phonemeLengthOutput[mem44 + 1] >> 1; 3008 | // sum the values 3009 | mem40 = mem36 + mem37; // length of both halves 3010 | mem37 += mem49; // center of next phoneme 3011 | mem36 = mem49 - mem36; // center index of current phoneme 3012 | A = Read( 3013 | mem47, mem37); // value at center of next phoneme - end interpolation value 3014 | //A = mem[address]; 3015 | 3016 | Y = mem36; // start index of interpolation 3017 | mem53 = A - Read(mem47, mem36); // value to center of current phoneme 3018 | } else { 3019 | // value to interpolate to 3020 | A = Read(mem47, speedcounter); 3021 | // position to start interpolation from 3022 | Y = phase3; 3023 | // value to interpolate from 3024 | mem53 = A - Read(mem47, phase3); 3025 | } 3026 | 3027 | //Code47503(mem40); 3028 | // ML : Code47503 is division with remainder, and mem50 gets the sign 3029 | 3030 | // calculate change per frame 3031 | signed char m53 = (signed char)mem53; 3032 | mem50 = mem53 & 128; 3033 | unsigned char m53abs = abs(m53); 3034 | mem51 = m53abs % mem40; //abs((char)m53) % mem40; 3035 | mem53 = (unsigned char)((signed char)(m53) / mem40); 3036 | 3037 | // interpolation range 3038 | X = mem40; // number of frames to interpolate over 3039 | Y = phase3; // starting frame 3040 | 3041 | // linearly interpolate values 3042 | 3043 | mem56 = 0; 3044 | //47907: CLC 3045 | //pos47908: 3046 | while(1) //while No. 3 3047 | { 3048 | A = Read(mem47, Y) + mem53; //carry alway cleared 3049 | 3050 | mem48 = A; 3051 | Y++; 3052 | X--; 3053 | if(X == 0) break; 3054 | 3055 | mem56 += mem51; 3056 | if(mem56 >= mem40) //??? 3057 | { 3058 | mem56 -= mem40; //carry? is set 3059 | //if ((mem56 & 128)==0) 3060 | if((mem50 & 128) == 0) { 3061 | //47935: BIT 50 3062 | //47937: BMI 47943 3063 | if(mem48 != 0) mem48++; 3064 | } else 3065 | mem48--; 3066 | } 3067 | //pos47945: 3068 | Write(mem47, Y, mem48); 3069 | } //while No. 3 3070 | 3071 | //pos47952: 3072 | mem47++; 3073 | //if (mem47 != 175) goto pos47810; 3074 | } while(mem47 != 175); //while No. 2 3075 | //pos47963: 3076 | mem44++; 3077 | X = mem44; 3078 | } //while No. 1 3079 | 3080 | //goto pos47701; 3081 | //pos47970: 3082 | 3083 | // add the length of this phoneme 3084 | mem48 = mem49 + phonemeLengthOutput[mem44]; 3085 | 3086 | // ASSIGN PITCH CONTOUR 3087 | // 3088 | // This subtracts the F1 frequency from the pitch to create a 3089 | // pitch contour. Without this, the output would be at a single 3090 | // pitch level (monotone). 3091 | 3092 | // don't adjust pitch if in sing mode 3093 | if(!singmode) { 3094 | // iterate through the buffer 3095 | for(i = 0; i < 256; i++) { 3096 | // subtract half the frequency of the formant 1. 3097 | // this adds variety to the voice 3098 | pitches[i] -= (frequency1[i] >> 1); 3099 | } 3100 | } 3101 | 3102 | phase1 = 0; 3103 | phase2 = 0; 3104 | phase3 = 0; 3105 | mem49 = 0; 3106 | speedcounter = 72; //sam standard speed 3107 | 3108 | // RESCALE AMPLITUDE 3109 | // 3110 | // Rescale volume from a linear scale to decibels. 3111 | // 3112 | 3113 | //amplitude rescaling 3114 | for(i = 255; i >= 0; i--) { 3115 | amplitude1[i] = amplitudeRescale[amplitude1[i]]; 3116 | amplitude2[i] = amplitudeRescale[amplitude2[i]]; 3117 | amplitude3[i] = amplitudeRescale[amplitude3[i]]; 3118 | } 3119 | 3120 | Y = 0; 3121 | A = pitches[0]; 3122 | mem44 = A; 3123 | X = A; 3124 | mem38 = A - (A >> 2); // 3/4*A ??? 3125 | 3126 | // PROCESS THE FRAMES 3127 | // 3128 | // In traditional vocal synthesis, the glottal pulse drives filters, which 3129 | // are attenuated to the frequencies of the formants. 3130 | // 3131 | // SAM generates these formants directly with sin and rectangular waves. 3132 | // To simulate them being driven by the glottal pulse, the waveforms are 3133 | // reset at the beginning of each glottal pulse. 3134 | 3135 | //finally the loop for sound output 3136 | //pos48078: 3137 | while(1) { 3138 | // get the sampled information on the phoneme 3139 | A = sampledConsonantFlag[Y]; 3140 | mem39 = A; 3141 | 3142 | // unvoiced sampled phoneme? 3143 | A = A & 248; 3144 | if(A != 0) { 3145 | // render the sample for the phoneme 3146 | RenderSample(&mem66); 3147 | 3148 | // skip ahead two in the phoneme buffer 3149 | Y += 2; 3150 | mem48 -= 2; 3151 | } else { 3152 | // simulate the glottal pulse and formants 3153 | unsigned char ary[5]; 3154 | unsigned int p1 = 3155 | phase1 * 256; // Fixed point integers because we need to divide later on 3156 | unsigned int p2 = phase2 * 256; 3157 | unsigned int p3 = phase3 * 256; 3158 | int k; 3159 | for(k = 0; k < 5; k++) { 3160 | signed char sp1 = (signed char)sinus[0xff & (p1 >> 8)]; 3161 | signed char sp2 = (signed char)sinus[0xff & (p2 >> 8)]; 3162 | signed char rp3 = (signed char)rectangle[0xff & (p3 >> 8)]; 3163 | signed int sin1 = sp1 * ((unsigned char)amplitude1[Y] & 0x0f); 3164 | signed int sin2 = sp2 * ((unsigned char)amplitude2[Y] & 0x0f); 3165 | signed int rect = rp3 * ((unsigned char)amplitude3[Y] & 0x0f); 3166 | signed int mux = sin1 + sin2 + rect; 3167 | mux /= 32; 3168 | mux += 128; // Go from signed to unsigned amplitude 3169 | ary[k] = mux; 3170 | p1 += frequency1[Y] * 256 / 4; // Compromise, this becomes a shift and works well 3171 | p2 += frequency2[Y] * 256 / 4; 3172 | p3 += frequency3[Y] * 256 / 4; 3173 | } 3174 | // output the accumulated value 3175 | Output8BitAry(0, ary); 3176 | speedcounter--; 3177 | if(speedcounter != 0) goto pos48155; 3178 | Y++; //go to next amplitude 3179 | 3180 | // decrement the frame count 3181 | mem48--; 3182 | } 3183 | 3184 | // if the frame count is zero, exit the loop 3185 | if(mem48 == 0) return; 3186 | speedcounter = speed; 3187 | pos48155: 3188 | 3189 | // decrement the remaining length of the glottal pulse 3190 | mem44--; 3191 | 3192 | // finished with a glottal pulse? 3193 | if(mem44 == 0) { 3194 | pos48159: 3195 | // fetch the next glottal pulse length 3196 | A = pitches[Y]; 3197 | mem44 = A; 3198 | A = A - (A >> 2); 3199 | mem38 = A; 3200 | 3201 | // reset the formant wave generators to keep them in 3202 | // sync with the glottal pulse 3203 | phase1 = 0; 3204 | phase2 = 0; 3205 | phase3 = 0; 3206 | continue; 3207 | } 3208 | 3209 | // decrement the count 3210 | mem38--; 3211 | 3212 | // is the count non-zero and the sampled flag is zero? 3213 | if((mem38 != 0) || (mem39 == 0)) { 3214 | // reset the phase of the formants to match the pulse 3215 | phase1 += frequency1[Y]; 3216 | phase2 += frequency2[Y]; 3217 | phase3 += frequency3[Y]; 3218 | continue; 3219 | } 3220 | 3221 | // voiced sampled phonemes interleave the sample with the 3222 | // glottal pulse. The sample flag is non-zero, so render 3223 | // the sample for the phoneme. 3224 | RenderSample(&mem66); 3225 | goto pos48159; 3226 | } //while 3227 | 3228 | // The following code is never reached. It's left over from when 3229 | // the voiced sample code was part of this loop, instead of part 3230 | // of RenderSample(); 3231 | 3232 | //pos48315: 3233 | int tempA; 3234 | phase1 = A ^ 255; 3235 | Y = mem66; 3236 | do { 3237 | //pos48321: 3238 | 3239 | mem56 = 8; 3240 | A = Read(mem47, Y); 3241 | 3242 | //pos48327: 3243 | do { 3244 | //48327: ASL A 3245 | //48328: BCC 48337 3246 | tempA = A; 3247 | A = A << 1; 3248 | if((tempA & 128) != 0) { 3249 | X = 26; 3250 | // mem[54296] = X; 3251 | bufferpos += 150; 3252 | // 3253 | // 3254 | // buffer[bufferpos / 50] = (X & 15) * 16; 3255 | // 3256 | // 3257 | 3258 | } else { 3259 | //mem[54296] = 6; 3260 | X = 6; 3261 | bufferpos += 150; 3262 | // 3263 | // buffer[bufferpos / 50] = (X & 15) * 16; 3264 | // 3265 | // 3266 | } 3267 | 3268 | for(X = wait2; X > 0; X--) 3269 | ; //wait 3270 | mem56--; 3271 | } while(mem56 != 0); 3272 | 3273 | Y++; 3274 | phase1++; 3275 | 3276 | } while(phase1 != 0); 3277 | // if (phase1 != 0) goto pos48321; 3278 | A = 1; 3279 | mem44 = 1; 3280 | mem66 = Y; 3281 | Y = mem49; 3282 | return; 3283 | } 3284 | 3285 | // Create a rising or falling inflection 30 frames prior to 3286 | // index X. A rising inflection is used for questions, and 3287 | // a falling inflection is used for statements. 3288 | 3289 | void STM32SAM::AddInflection(unsigned char mem48, unsigned char phase1) { 3290 | //pos48372: 3291 | // mem48 = 255; 3292 | //pos48376: 3293 | 3294 | // store the location of the punctuation 3295 | mem49 = X; 3296 | A = X; 3297 | int Atemp = A; 3298 | 3299 | // backup 30 frames 3300 | A = A - 30; 3301 | // if index is before buffer, point to start of buffer 3302 | if(Atemp <= 30) A = 0; 3303 | X = A; 3304 | 3305 | // FIXME: Explain this fix better, it's not obvious 3306 | // ML : A =, fixes a problem with invalid pitch with '.' 3307 | while((A = pitches[X]) == 127) X++; 3308 | 3309 | pos48398: 3310 | //48398: CLC 3311 | //48399: ADC 48 3312 | 3313 | // add the inflection direction 3314 | A += mem48; 3315 | phase1 = A; 3316 | 3317 | // set the inflection 3318 | pitches[X] = A; 3319 | pos48406: 3320 | 3321 | // increment the position 3322 | X++; 3323 | 3324 | // exit if the punctuation has been reached 3325 | if(X == mem49) return; //goto pos47615; 3326 | if(pitches[X] == 255) goto pos48406; 3327 | A = phase1; 3328 | goto pos48398; 3329 | } 3330 | 3331 | /* 3332 | SAM's voice can be altered by changing the frequencies of the 3333 | mouth formant (F1) and the throat formant (F2). Only the voiced 3334 | phonemes (5-29 and 48-53) are altered. 3335 | */ 3336 | void STM32SAM::SetMouthThroat() { 3337 | unsigned char initialFrequency; 3338 | unsigned char newFrequency = 0; 3339 | //unsigned char mouth; //mem38880 3340 | //unsigned char throat; //mem38881 3341 | 3342 | // mouth formants (F1) 5..29 3343 | unsigned char mouthFormants5_29[30] = {0, 0, 0, 0, 0, 10, 14, 19, 24, 27, 3344 | 23, 21, 16, 20, 14, 18, 14, 18, 18, 16, 3345 | 13, 15, 11, 18, 14, 11, 9, 6, 6, 6}; 3346 | 3347 | // throat formants (F2) 5..29 3348 | unsigned char throatFormants5_29[30] = {255, 255, 255, 255, 255, 84, 73, 67, 63, 40, 3349 | 44, 31, 37, 45, 73, 49, 36, 30, 51, 37, 3350 | 29, 69, 24, 50, 30, 24, 83, 46, 54, 86}; 3351 | 3352 | // there must be no zeros in this 2 tables 3353 | // formant 1 frequencies (mouth) 48..53 3354 | unsigned char mouthFormants48_53[6] = {19, 27, 21, 27, 18, 13}; 3355 | 3356 | // formant 2 frequencies (throat) 48..53 3357 | unsigned char throatFormants48_53[6] = {72, 39, 31, 43, 30, 34}; 3358 | 3359 | unsigned char pos = 5; //mem39216 3360 | //pos38942: 3361 | // recalculate formant frequencies 5..29 for the mouth (F1) and throat (F2) 3362 | while(pos != 30) { 3363 | // recalculate mouth frequency 3364 | initialFrequency = mouthFormants5_29[pos]; 3365 | if(initialFrequency != 0) newFrequency = trans(mouth, initialFrequency); 3366 | freq1data[pos] = newFrequency; 3367 | 3368 | // recalculate throat frequency 3369 | initialFrequency = throatFormants5_29[pos]; 3370 | if(initialFrequency != 0) newFrequency = trans(throat, initialFrequency); 3371 | freq2data[pos] = newFrequency; 3372 | pos++; 3373 | } 3374 | 3375 | //pos39059: 3376 | // recalculate formant frequencies 48..53 3377 | pos = 48; 3378 | Y = 0; 3379 | while(pos != 54) { 3380 | // recalculate F1 (mouth formant) 3381 | initialFrequency = mouthFormants48_53[Y]; 3382 | newFrequency = trans(mouth, initialFrequency); 3383 | freq1data[pos] = newFrequency; 3384 | 3385 | // recalculate F2 (throat formant) 3386 | initialFrequency = throatFormants48_53[Y]; 3387 | newFrequency = trans(throat, initialFrequency); 3388 | freq2data[pos] = newFrequency; 3389 | Y++; 3390 | pos++; 3391 | } 3392 | } 3393 | 3394 | //return = (mem39212*mem39213) >> 1 3395 | unsigned char STM32SAM::trans(unsigned char mem39212, unsigned char mem39213) { 3396 | //pos39008: 3397 | unsigned char carry; 3398 | int temp; 3399 | unsigned char mem39214, mem39215; 3400 | A = 0; 3401 | mem39215 = 0; 3402 | mem39214 = 0; 3403 | X = 8; 3404 | do { 3405 | carry = mem39212 & 1; 3406 | mem39212 = mem39212 >> 1; 3407 | if(carry != 0) { 3408 | /* 3409 | 39018: LSR 39212 3410 | 39021: BCC 39033 3411 | */ 3412 | carry = 0; 3413 | A = mem39215; 3414 | temp = (int)A + (int)mem39213; 3415 | A = A + mem39213; 3416 | if(temp > 255) carry = 1; 3417 | mem39215 = A; 3418 | } 3419 | temp = mem39215 & 1; 3420 | mem39215 = (mem39215 >> 1) | (carry ? 128 : 0); 3421 | carry = temp; 3422 | //39033: ROR 39215 3423 | X--; 3424 | } while(X != 0); 3425 | temp = mem39214 & 128; 3426 | mem39214 = (mem39214 << 1) | (carry ? 1 : 0); 3427 | carry = temp; 3428 | temp = mem39215 & 128; 3429 | mem39215 = (mem39215 << 1) | (carry ? 1 : 0); 3430 | carry = temp; 3431 | 3432 | return mem39215; 3433 | } 3434 | 3435 | //////////////////////////////////////////////////////////////////////////////////////////// 3436 | // 3437 | // Sam 3438 | // 3439 | //////////////////////////////////////////////////////////////////////////////////////////// 3440 | 3441 | //char input[]={"/HAALAOAO MAYN NAAMAEAE IHSTT SAEBAASTTIHAAN \x9b\x9b\0"}; 3442 | //unsigned char input[]={"/HAALAOAO \x9b\0"}; 3443 | //unsigned char input[]={"AA \x9b\0"}; 3444 | //unsigned char input[] = {"GUH5DEHN TAEG\x9b\0"}; 3445 | 3446 | //unsigned char input[]={"AY5 AEM EY TAO4LXKIHNX KAX4MPYUX4TAH. GOW4 AH/HEH3D PAHNK.MEYK MAY8 DEY.\x9b\0"}; 3447 | //unsigned char input[]={"/HEH3LOW2, /HAW AH YUX2 TUXDEY. AY /HOH3P YUX AH FIYLIHNX OW4 KEY.\x9b\0"}; 3448 | //unsigned char input[]={"/HEY2, DHIHS IH3Z GREY2T. /HAH /HAH /HAH.AYL BIY5 BAEK.\x9b\0"}; 3449 | //unsigned char input[]={"/HAH /HAH /HAH \x9b\0"}; 3450 | //unsigned char input[]={"/HAH /HAH /HAH.\x9b\0"}; 3451 | //unsigned char input[]={".TUW BIY5Y3,, OHR NAA3T - TUW BIY5IYIY., DHAE4T IHZ DHAH KWEH4SCHAHN.\x9b\0"}; 3452 | //unsigned char input[]={"/HEY2, DHIHS \x9b\0"}; 3453 | 3454 | //unsigned char input[]={" IYIHEHAEAAAHAOOHUHUXERAXIX \x9b\0"}; 3455 | //unsigned char input[]={" RLWWYMNNXBDGJZZHVDH \x9b\0"}; 3456 | //unsigned char input[]={" SSHFTHPTKCH/H \x9b\0"}; 3457 | 3458 | //unsigned char input[]={" EYAYOYAWOWUW ULUMUNQ YXWXRXLX/XDX\x9b\0"}; 3459 | 3460 | void STM32SAM::SetInput(char* _input) { 3461 | int i, l; 3462 | l = strlen(_input); 3463 | if(l > 254) l = 254; 3464 | for(i = 0; i < l; i++) { 3465 | input[i] = _input[i]; 3466 | } 3467 | input[l] = 0; 3468 | } 3469 | 3470 | // 168=pitches 3471 | // 169=frequency1 3472 | // 170=frequency2 3473 | // 171=frequency3 3474 | // 172=amplitude1 3475 | // 173=amplitude2 3476 | // 174=amplitude3 3477 | 3478 | void STM32SAM::Init() { 3479 | bufferpos = 0; 3480 | int i; 3481 | SetMouthThroat(); 3482 | 3483 | bufferpos = 0; 3484 | // TODO, check for free the memory, 10 seconds of output should be more than enough 3485 | //buffer = malloc(22050*10); 3486 | 3487 | // buffer = (char*) calloc(1, sizeof(char)); 3488 | 3489 | /* 3490 | freq2data = &mem[45136]; 3491 | freq1data = &mem[45056]; 3492 | freq3data = &mem[45216]; 3493 | */ 3494 | //pitches = &mem[43008]; 3495 | /* 3496 | frequency1 = &mem[43264]; 3497 | frequency2 = &mem[43520]; 3498 | frequency3 = &mem[43776]; 3499 | */ 3500 | /* 3501 | amplitude1 = &mem[44032]; 3502 | amplitude2 = &mem[44288]; 3503 | amplitude3 = &mem[44544]; 3504 | */ 3505 | //phoneme = &mem[39904]; 3506 | /* 3507 | ampl1data = &mem[45296]; 3508 | ampl2data = &mem[45376]; 3509 | ampl3data = &mem[45456]; 3510 | */ 3511 | 3512 | for(i = 0; i < 256; i++) { 3513 | stress[i] = 0; 3514 | phonemeLength[i] = 0; 3515 | } 3516 | 3517 | for(i = 0; i < 60; i++) { 3518 | phonemeIndexOutput[i] = 0; 3519 | stressOutput[i] = 0; 3520 | phonemeLengthOutput[i] = 0; 3521 | } 3522 | phonemeindex[255] = 3523 | 255; //to prevent buffer overflow // ML : changed from 32 to 255 to stop freezing with long inputs 3524 | } 3525 | 3526 | //int Code39771() 3527 | int STM32SAM::SAMMain() { 3528 | Init(); 3529 | phonemeindex[255] = 32; //to prevent buffer overflow 3530 | 3531 | if(!Parser1()) { 3532 | return 0; 3533 | } 3534 | 3535 | Parser2(); 3536 | CopyStress(); 3537 | SetPhonemeLength(); 3538 | AdjustLengths(); 3539 | Code41240(); 3540 | do { 3541 | A = phonemeindex[X]; 3542 | if(A > 80) { 3543 | phonemeindex[X] = 255; 3544 | break; // error: delete all behind it 3545 | } 3546 | X++; 3547 | } while(X != 0); 3548 | 3549 | //pos39848: 3550 | InsertBreath(); 3551 | 3552 | //mem[40158] = 255; 3553 | 3554 | PrepareOutput(); 3555 | 3556 | return 1; 3557 | } 3558 | 3559 | //void Code48547() 3560 | void STM32SAM::PrepareOutput() { 3561 | A = 0; 3562 | X = 0; 3563 | Y = 0; 3564 | 3565 | //pos48551: 3566 | while(1) { 3567 | A = phonemeindex[X]; 3568 | if(A == 255) { 3569 | A = 255; 3570 | phonemeIndexOutput[Y] = 255; 3571 | Render(); 3572 | return; 3573 | } 3574 | if(A == 254) { 3575 | X++; 3576 | int temp = X; 3577 | //mem[48546] = X; 3578 | phonemeIndexOutput[Y] = 255; 3579 | Render(); 3580 | //X = mem[48546]; 3581 | X = temp; 3582 | Y = 0; 3583 | continue; 3584 | } 3585 | 3586 | if(A == 0) { 3587 | X++; 3588 | continue; 3589 | } 3590 | 3591 | phonemeIndexOutput[Y] = A; 3592 | phonemeLengthOutput[Y] = phonemeLength[X]; 3593 | stressOutput[Y] = stress[X]; 3594 | X++; 3595 | Y++; 3596 | } 3597 | } 3598 | 3599 | //void Code41014() 3600 | void STM32SAM::Insert( 3601 | unsigned char position /*var57*/, 3602 | unsigned char mem60, 3603 | unsigned char mem59, 3604 | unsigned char mem58) { 3605 | int i; 3606 | for(i = 253; i >= position; i--) // ML : always keep last safe-guarding 255 3607 | { 3608 | phonemeindex[i + 1] = phonemeindex[i]; 3609 | phonemeLength[i + 1] = phonemeLength[i]; 3610 | stress[i + 1] = stress[i]; 3611 | } 3612 | 3613 | phonemeindex[position] = mem60; 3614 | phonemeLength[position] = mem59; 3615 | stress[position] = mem58; 3616 | return; 3617 | } 3618 | 3619 | //void Code48431() 3620 | void STM32SAM::InsertBreath() { 3621 | unsigned char mem54; 3622 | unsigned char mem55; 3623 | unsigned char index; //variable Y 3624 | mem54 = 255; 3625 | X++; 3626 | mem55 = 0; 3627 | unsigned char mem66 = 0; 3628 | while(1) { 3629 | //pos48440: 3630 | X = mem66; 3631 | index = phonemeindex[X]; 3632 | if(index == 255) return; 3633 | mem55 += phonemeLength[X]; 3634 | 3635 | if(mem55 < 232) { 3636 | if(index != 254) // ML : Prevents an index out of bounds problem 3637 | { 3638 | A = flags2[index] & 1; 3639 | if(A != 0) { 3640 | X++; 3641 | mem55 = 0; 3642 | Insert(X, 254, mem59, 0); 3643 | mem66++; 3644 | mem66++; 3645 | continue; 3646 | } 3647 | } 3648 | if(index == 0) mem54 = X; 3649 | mem66++; 3650 | continue; 3651 | } 3652 | X = mem54; 3653 | phonemeindex[X] = 31; // 'Q*' glottal stop 3654 | phonemeLength[X] = 4; 3655 | stress[X] = 0; 3656 | X++; 3657 | mem55 = 0; 3658 | Insert(X, 254, mem59, 0); 3659 | X++; 3660 | mem66 = X; 3661 | } 3662 | } 3663 | 3664 | // Iterates through the phoneme buffer, copying the stress value from 3665 | // the following phoneme under the following circumstance: 3666 | 3667 | // 1. The current phoneme is voiced, excluding plosives and fricatives 3668 | // 2. The following phoneme is voiced, excluding plosives and fricatives, and 3669 | // 3. The following phoneme is stressed 3670 | // 3671 | // In those cases, the stress value+1 from the following phoneme is copied. 3672 | // 3673 | // For example, the word LOITER is represented as LOY5TER, with as stress 3674 | // of 5 on the diphtong OY. This routine will copy the stress value of 6 (5+1) 3675 | // to the L that precedes it. 3676 | 3677 | //void Code41883() 3678 | void STM32SAM::CopyStress() { 3679 | // loop thought all the phonemes to be output 3680 | unsigned char pos = 0; //mem66 3681 | while(1) { 3682 | // get the phomene 3683 | Y = phonemeindex[pos]; 3684 | 3685 | // exit at end of buffer 3686 | if(Y == 255) return; 3687 | 3688 | // if CONSONANT_FLAG set, skip - only vowels get stress 3689 | if((flags[Y] & 64) == 0) { 3690 | pos++; 3691 | continue; 3692 | } 3693 | // get the next phoneme 3694 | Y = phonemeindex[pos + 1]; 3695 | if(Y == 255) //prevent buffer overflow 3696 | { 3697 | pos++; 3698 | continue; 3699 | } else 3700 | // if the following phoneme is a vowel, skip 3701 | if((flags[Y] & 128) == 0) { 3702 | pos++; 3703 | continue; 3704 | } 3705 | 3706 | // get the stress value at the next position 3707 | Y = stress[pos + 1]; 3708 | 3709 | // if next phoneme is not stressed, skip 3710 | if(Y == 0) { 3711 | pos++; 3712 | continue; 3713 | } 3714 | 3715 | // if next phoneme is not a VOWEL OR ER, skip 3716 | if((Y & 128) != 0) { 3717 | pos++; 3718 | continue; 3719 | } 3720 | 3721 | // copy stress from prior phoneme to this one 3722 | stress[pos] = Y + 1; 3723 | 3724 | // advance pointer 3725 | pos++; 3726 | } 3727 | } 3728 | 3729 | // The input[] buffer contains a string of phonemes and stress markers along 3730 | // the lines of: 3731 | // 3732 | // DHAX KAET IHZ AH5GLIY. <0x9B> 3733 | // 3734 | // The byte 0x9B marks the end of the buffer. Some phonemes are 2 bytes 3735 | // long, such as "DH" and "AX". Others are 1 byte long, such as "T" and "Z". 3736 | // There are also stress markers, such as "5" and ".". 3737 | // 3738 | // The first character of the phonemes are stored in the table signInputTable1[]. 3739 | // The second character of the phonemes are stored in the table signInputTable2[]. 3740 | // The stress characters are arranged in low to high stress order in stressInputTable[]. 3741 | // 3742 | // The following process is used to parse the input[] buffer: 3743 | // 3744 | // Repeat until the <0x9B> character is reached: 3745 | // 3746 | // First, a search is made for a 2 character match for phonemes that do not 3747 | // end with the '*' (wildcard) character. On a match, the index of the phoneme 3748 | // is added to phonemeIndex[] and the buffer position is advanced 2 bytes. 3749 | // 3750 | // If this fails, a search is made for a 1 character match against all 3751 | // phoneme names ending with a '*' (wildcard). If this succeeds, the 3752 | // phoneme is added to phonemeIndex[] and the buffer position is advanced 3753 | // 1 byte. 3754 | // 3755 | // If this fails, search for a 1 character match in the stressInputTable[]. 3756 | // If this succeeds, the stress value is placed in the last stress[] table 3757 | // at the same index of the last added phoneme, and the buffer position is 3758 | // advanced by 1 byte. 3759 | // 3760 | // If this fails, return a 0. 3761 | // 3762 | // On success: 3763 | // 3764 | // 1. phonemeIndex[] will contain the index of all the phonemes. 3765 | // 2. The last index in phonemeIndex[] will be 255. 3766 | // 3. stress[] will contain the stress value for each phoneme 3767 | 3768 | // input[] holds the string of phonemes, each two bytes wide 3769 | // signInputTable1[] holds the first character of each phoneme 3770 | // signInputTable2[] holds te second character of each phoneme 3771 | // phonemeIndex[] holds the indexes of the phonemes after parsing input[] 3772 | // 3773 | // The parser scans through the input[], finding the names of the phonemes 3774 | // by searching signInputTable1[] and signInputTable2[]. On a match, it 3775 | // copies the index of the phoneme into the phonemeIndexTable[]. 3776 | // 3777 | // The character <0x9B> marks the end of text in input[]. When it is reached, 3778 | // the index 255 is placed at the end of the phonemeIndexTable[], and the 3779 | // function returns with a 1 indicating success. 3780 | int STM32SAM::Parser1() { 3781 | int i; 3782 | unsigned char sign1; 3783 | unsigned char sign2; 3784 | unsigned char position = 0; 3785 | X = 0; 3786 | A = 0; 3787 | Y = 0; 3788 | 3789 | // CLEAR THE STRESS TABLE 3790 | for(i = 0; i < 256; i++) stress[i] = 0; 3791 | 3792 | // THIS CODE MATCHES THE PHONEME LETTERS TO THE TABLE 3793 | // pos41078: 3794 | while(1) { 3795 | // GET THE FIRST CHARACTER FROM THE PHONEME BUFFER 3796 | sign1 = input[X]; 3797 | // TEST FOR 155 (�) END OF LINE MARKER 3798 | if(sign1 == 155) { 3799 | // MARK ENDPOINT AND RETURN 3800 | phonemeindex[position] = 255; //mark endpoint 3801 | // REACHED END OF PHONEMES, SO EXIT 3802 | return 1; //all ok 3803 | } 3804 | 3805 | // GET THE NEXT CHARACTER FROM THE BUFFER 3806 | X++; 3807 | sign2 = input[X]; 3808 | 3809 | // NOW sign1 = FIRST CHARACTER OF PHONEME, AND sign2 = SECOND CHARACTER OF PHONEME 3810 | 3811 | // TRY TO MATCH PHONEMES ON TWO TWO-CHARACTER NAME 3812 | // IGNORE PHONEMES IN TABLE ENDING WITH WILDCARDS 3813 | 3814 | // SET INDEX TO 0 3815 | Y = 0; 3816 | pos41095: 3817 | 3818 | // GET FIRST CHARACTER AT POSITION Y IN signInputTable 3819 | // --> should change name to PhonemeNameTable1 3820 | A = signInputTable1[Y]; 3821 | 3822 | // FIRST CHARACTER MATCHES? 3823 | if(A == sign1) { 3824 | // GET THE CHARACTER FROM THE PhonemeSecondLetterTable 3825 | A = signInputTable2[Y]; 3826 | // NOT A SPECIAL AND MATCHES SECOND CHARACTER? 3827 | if((A != '*') && (A == sign2)) { 3828 | // STORE THE INDEX OF THE PHONEME INTO THE phomeneIndexTable 3829 | phonemeindex[position] = Y; 3830 | 3831 | // ADVANCE THE POINTER TO THE phonemeIndexTable 3832 | position++; 3833 | // ADVANCE THE POINTER TO THE phonemeInputBuffer 3834 | X++; 3835 | 3836 | // CONTINUE PARSING 3837 | continue; 3838 | } 3839 | } 3840 | 3841 | // NO MATCH, TRY TO MATCH ON FIRST CHARACTER TO WILDCARD NAMES (ENDING WITH '*') 3842 | 3843 | // ADVANCE TO THE NEXT POSITION 3844 | Y++; 3845 | // IF NOT END OF TABLE, CONTINUE 3846 | if(Y != 81) goto pos41095; 3847 | 3848 | // REACHED END OF TABLE WITHOUT AN EXACT (2 CHARACTER) MATCH. 3849 | // THIS TIME, SEARCH FOR A 1 CHARACTER MATCH AGAINST THE WILDCARDS 3850 | 3851 | // RESET THE INDEX TO POINT TO THE START OF THE PHONEME NAME TABLE 3852 | Y = 0; 3853 | pos41134: 3854 | // DOES THE PHONEME IN THE TABLE END WITH '*'? 3855 | if(signInputTable2[Y] == '*') { 3856 | // DOES THE FIRST CHARACTER MATCH THE FIRST LETTER OF THE PHONEME 3857 | if(signInputTable1[Y] == sign1) { 3858 | // SAVE THE POSITION AND MOVE AHEAD 3859 | phonemeindex[position] = Y; 3860 | 3861 | // ADVANCE THE POINTER 3862 | position++; 3863 | 3864 | // CONTINUE THROUGH THE LOOP 3865 | continue; 3866 | } 3867 | } 3868 | Y++; 3869 | if(Y != 81) goto pos41134; //81 is size of PHONEME NAME table 3870 | 3871 | // FAILED TO MATCH WITH A WILDCARD. ASSUME THIS IS A STRESS 3872 | // CHARACTER. SEARCH THROUGH THE STRESS TABLE 3873 | 3874 | // SET INDEX TO POSITION 8 (END OF STRESS TABLE) 3875 | Y = 8; 3876 | 3877 | // WALK BACK THROUGH TABLE LOOKING FOR A MATCH 3878 | while((sign1 != stressInputTable[Y]) && (Y > 0)) { 3879 | // DECREMENT INDEX 3880 | Y--; 3881 | } 3882 | 3883 | // REACHED THE END OF THE SEARCH WITHOUT BREAKING OUT OF LOOP? 3884 | if(Y == 0) { 3885 | //mem[39444] = X; 3886 | //41181: JSR 42043 //Error 3887 | // FAILED TO MATCH ANYTHING, RETURN 0 ON FAILURE 3888 | return 0; 3889 | } 3890 | // SET THE STRESS FOR THE PRIOR PHONEME 3891 | stress[position - 1] = Y; 3892 | } //while 3893 | } 3894 | 3895 | //change phonemelength depedendent on stress 3896 | //void Code41203() 3897 | void STM32SAM::SetPhonemeLength() { 3898 | unsigned char A; 3899 | int position = 0; 3900 | while(phonemeindex[position] != 255) { 3901 | A = stress[position]; 3902 | //41218: BMI 41229 3903 | if((A == 0) || ((A & 128) != 0)) { 3904 | phonemeLength[position] = phonemeLengthTable[phonemeindex[position]]; 3905 | } else { 3906 | phonemeLength[position] = phonemeStressedLengthTable[phonemeindex[position]]; 3907 | } 3908 | position++; 3909 | } 3910 | } 3911 | 3912 | void STM32SAM::Code41240() { 3913 | unsigned char pos = 0; 3914 | 3915 | while(phonemeindex[pos] != 255) { 3916 | unsigned char index; //register AC 3917 | X = pos; 3918 | index = phonemeindex[pos]; 3919 | if((flags[index] & 2) == 0) { 3920 | pos++; 3921 | continue; 3922 | } else if((flags[index] & 1) == 0) { 3923 | Insert(pos + 1, index + 1, phonemeLengthTable[index + 1], stress[pos]); 3924 | Insert(pos + 2, index + 2, phonemeLengthTable[index + 2], stress[pos]); 3925 | pos += 3; 3926 | continue; 3927 | } 3928 | 3929 | do { 3930 | X++; 3931 | A = phonemeindex[X]; 3932 | } while(A == 0); 3933 | 3934 | if(A != 255) { 3935 | if((flags[A] & 8) != 0) { 3936 | pos++; 3937 | continue; 3938 | } 3939 | if((A == 36) || (A == 37)) { 3940 | pos++; // '/H' '/X' 3941 | continue; 3942 | } 3943 | } 3944 | 3945 | Insert(pos + 1, index + 1, phonemeLengthTable[index + 1], stress[pos]); 3946 | Insert(pos + 2, index + 2, phonemeLengthTable[index + 2], stress[pos]); 3947 | pos += 3; 3948 | }; 3949 | } 3950 | 3951 | // Rewrites the phonemes using the following rules: 3952 | // 3953 | // -> WX 3954 | // -> YX 3955 | // UL -> AX L 3956 | // UM -> AX M 3957 | // -> Q 3958 | // T R -> CH R 3959 | // D R -> J R 3960 | // R -> RX 3961 | // L -> LX 3962 | // G S -> G Z 3963 | // K -> KX 3964 | // G -> GX 3965 | // S P -> S B 3966 | // S T -> S D 3967 | // S K -> S G 3968 | // S KX -> S GX 3969 | // UW -> UX 3970 | // CH -> CH CH' (CH requires two phonemes to represent it) 3971 | // J -> J J' (J requires two phonemes to represent it) 3972 | // T -> DX 3973 | // D -> DX 3974 | 3975 | //void Code41397() 3976 | void STM32SAM::Parser2() { 3977 | unsigned char pos = 0; //mem66; 3978 | unsigned char mem58 = 0; 3979 | 3980 | // Loop through phonemes 3981 | while(1) { 3982 | // SET X TO THE CURRENT POSITION 3983 | X = pos; 3984 | // GET THE PHONEME AT THE CURRENT POSITION 3985 | A = phonemeindex[pos]; 3986 | 3987 | // Is phoneme pause? 3988 | if(A == 0) { 3989 | // Move ahead to the 3990 | pos++; 3991 | continue; 3992 | } 3993 | 3994 | // If end of phonemes flag reached, exit routine 3995 | if(A == 255) return; 3996 | 3997 | // Copy the current phoneme index to Y 3998 | Y = A; 3999 | 4000 | // RULE: 4001 | // -> WX 4002 | // -> YX 4003 | // Example: OIL, COW 4004 | 4005 | // Check for DIPHTONG 4006 | if((flags[A] & 16) == 0) goto pos41457; 4007 | 4008 | // Not a diphthong. Get the stress 4009 | mem58 = stress[pos]; 4010 | 4011 | // End in IY sound? 4012 | A = flags[Y] & 32; 4013 | 4014 | // If ends with IY, use YX, else use WX 4015 | if(A == 0) 4016 | A = 20; 4017 | else 4018 | A = 21; // 'WX' = 20 'YX' = 21 4019 | //pos41443: 4020 | // Insert at WX or YX following, copying the stress 4021 | 4022 | Insert(pos + 1, A, mem59, mem58); 4023 | X = pos; 4024 | // Jump to ??? 4025 | goto pos41749; 4026 | 4027 | pos41457: 4028 | 4029 | // RULE: 4030 | // UL -> AX L 4031 | // Example: MEDDLE 4032 | 4033 | // Get phoneme 4034 | A = phonemeindex[X]; 4035 | // Skip this rule if phoneme is not UL 4036 | if(A != 78) goto pos41487; // 'UL' 4037 | A = 24; // 'L' //change 'UL' to 'AX L' 4038 | 4039 | pos41466: 4040 | // Get current phoneme stress 4041 | mem58 = stress[X]; 4042 | 4043 | // Change UL to AX 4044 | phonemeindex[X] = 13; // 'AX' 4045 | // Perform insert. Note code below may jump up here with different values 4046 | Insert(X + 1, A, mem59, mem58); 4047 | pos++; 4048 | // Move to next phoneme 4049 | continue; 4050 | 4051 | pos41487: 4052 | 4053 | // RULE: 4054 | // UM -> AX M 4055 | // Example: ASTRONOMY 4056 | 4057 | // Skip rule if phoneme != UM 4058 | if(A != 79) goto pos41495; // 'UM' 4059 | // Jump up to branch - replaces current phoneme with AX and continues 4060 | A = 27; // 'M' //change 'UM' to 'AX M' 4061 | 4062 | goto pos41466; 4063 | pos41495: 4064 | 4065 | // RULE: 4066 | // UN -> AX N 4067 | // Example: FUNCTION 4068 | 4069 | // Skip rule if phoneme != UN 4070 | if(A != 80) goto pos41503; // 'UN' 4071 | 4072 | // Jump up to branch - replaces current phoneme with AX and continues 4073 | A = 28; // 'N' //change UN to 'AX N' 4074 | 4075 | goto pos41466; 4076 | pos41503: 4077 | 4078 | // RULE: 4079 | // -> Q 4080 | // EXAMPLE: AWAY EIGHT 4081 | 4082 | Y = A; 4083 | // VOWEL set? 4084 | A = flags[A] & 128; 4085 | 4086 | // Skip if not a vowel 4087 | if(A != 0) { 4088 | // Get the stress 4089 | A = stress[X]; 4090 | 4091 | // If stressed... 4092 | if(A != 0) { 4093 | // Get the following phoneme 4094 | X++; 4095 | A = phonemeindex[X]; 4096 | // If following phoneme is a pause 4097 | 4098 | if(A == 0) { 4099 | // Get the phoneme following pause 4100 | X++; 4101 | Y = phonemeindex[X]; 4102 | 4103 | // Check for end of buffer flag 4104 | if(Y == 255) //buffer overflow 4105 | // ??? Not sure about these flags 4106 | A = 65 & 128; 4107 | else 4108 | // And VOWEL flag to current phoneme's flags 4109 | A = flags[Y] & 128; 4110 | 4111 | // If following phonemes is not a pause 4112 | if(A != 0) { 4113 | // If the following phoneme is not stressed 4114 | A = stress[X]; 4115 | if(A != 0) { 4116 | // 31 = 'Q' 4117 | Insert(X, 31, mem59, 0); 4118 | pos++; 4119 | continue; 4120 | } 4121 | } 4122 | } 4123 | } 4124 | } 4125 | 4126 | // RULES FOR PHONEMES BEFORE R 4127 | // T R -> CH R 4128 | // Example: TRACK 4129 | 4130 | // Get current position and phoneme 4131 | X = pos; 4132 | A = phonemeindex[pos]; 4133 | if(A != 23) goto pos41611; // 'R' 4134 | 4135 | // Look at prior phoneme 4136 | X--; 4137 | A = phonemeindex[pos - 1]; 4138 | //pos41567: 4139 | if(A == 69) // 'T' 4140 | { 4141 | phonemeindex[pos - 1] = 42; 4142 | goto pos41779; 4143 | } 4144 | 4145 | // RULES FOR PHONEMES BEFORE R 4146 | // D R -> J R 4147 | // Example: DRY 4148 | 4149 | // Prior phonemes D? 4150 | if(A == 57) // 'D' 4151 | { 4152 | // Change D to J 4153 | phonemeindex[pos - 1] = 44; 4154 | 4155 | goto pos41788; 4156 | } 4157 | 4158 | // RULES FOR PHONEMES BEFORE R 4159 | // R -> RX 4160 | // Example: ART 4161 | 4162 | // If vowel flag is set change R to RX 4163 | A = flags[A] & 128; 4164 | 4165 | if(A != 0) phonemeindex[pos] = 18; // 'RX' 4166 | 4167 | // continue to next phoneme 4168 | pos++; 4169 | continue; 4170 | 4171 | pos41611: 4172 | 4173 | // RULE: 4174 | // L -> LX 4175 | // Example: ALL 4176 | 4177 | // Is phoneme L? 4178 | if(A == 24) // 'L' 4179 | { 4180 | // If prior phoneme does not have VOWEL flag set, move to next phoneme 4181 | if((flags[phonemeindex[pos - 1]] & 128) == 0) { 4182 | pos++; 4183 | continue; 4184 | } 4185 | // Prior phoneme has VOWEL flag set, so change L to LX and move to next phoneme 4186 | 4187 | phonemeindex[X] = 19; // 'LX' 4188 | pos++; 4189 | continue; 4190 | } 4191 | 4192 | // RULE: 4193 | // G S -> G Z 4194 | // 4195 | // Can't get to fire - 4196 | // 1. The G -> GX rule intervenes 4197 | // 2. Reciter already replaces GS -> GZ 4198 | 4199 | // Is current phoneme S? 4200 | if(A == 32) // 'S' 4201 | { 4202 | // If prior phoneme is not G, move to next phoneme 4203 | if(phonemeindex[pos - 1] != 60) { 4204 | pos++; 4205 | continue; 4206 | } 4207 | // Replace S with Z and move on 4208 | 4209 | phonemeindex[pos] = 38; // 'Z' 4210 | pos++; 4211 | continue; 4212 | } 4213 | 4214 | // RULE: 4215 | // K -> KX 4216 | // Example: COW 4217 | 4218 | // Is current phoneme K? 4219 | if(A == 72) // 'K' 4220 | { 4221 | // Get next phoneme 4222 | Y = phonemeindex[pos + 1]; 4223 | // If at end, replace current phoneme with KX 4224 | if(Y == 255) 4225 | phonemeindex[pos] = 75; // ML : prevents an index out of bounds problem 4226 | else { 4227 | // VOWELS AND DIPHTONGS ENDING WITH IY SOUND flag set? 4228 | A = flags[Y] & 32; 4229 | 4230 | // Replace with KX 4231 | if(A == 0) phonemeindex[pos] = 75; // 'KX' 4232 | } 4233 | } else 4234 | 4235 | // RULE: 4236 | // G -> GX 4237 | // Example: GO 4238 | 4239 | // Is character a G? 4240 | if(A == 60) // 'G' 4241 | { 4242 | // Get the following character 4243 | unsigned char index = phonemeindex[pos + 1]; 4244 | 4245 | // At end of buffer? 4246 | if(index == 255) //prevent buffer overflow 4247 | { 4248 | pos++; 4249 | continue; 4250 | } else 4251 | // If diphtong ending with YX, move continue processing next phoneme 4252 | if((flags[index] & 32) != 0) { 4253 | pos++; 4254 | continue; 4255 | } 4256 | // replace G with GX and continue processing next phoneme 4257 | 4258 | phonemeindex[pos] = 63; // 'GX' 4259 | pos++; 4260 | continue; 4261 | } 4262 | 4263 | // RULE: 4264 | // S P -> S B 4265 | // S T -> S D 4266 | // S K -> S G 4267 | // S KX -> S GX 4268 | // Examples: SPY, STY, SKY, SCOWL 4269 | 4270 | Y = phonemeindex[pos]; 4271 | //pos41719: 4272 | // Replace with softer version? 4273 | A = flags[Y] & 1; 4274 | if(A == 0) goto pos41749; 4275 | A = phonemeindex[pos - 1]; 4276 | if(A != 32) // 'S' 4277 | { 4278 | A = Y; 4279 | goto pos41812; 4280 | } 4281 | // Replace with softer version 4282 | 4283 | phonemeindex[pos] = Y - 12; 4284 | pos++; 4285 | continue; 4286 | 4287 | pos41749: 4288 | 4289 | // RULE: 4290 | // UW -> UX 4291 | // 4292 | // Example: NEW, DEW, SUE, ZOO, THOO, TOO 4293 | 4294 | // UW -> UX 4295 | 4296 | A = phonemeindex[X]; 4297 | if(A == 53) // 'UW' 4298 | { 4299 | // ALVEOLAR flag set? 4300 | Y = phonemeindex[X - 1]; 4301 | A = flags2[Y] & 4; 4302 | // If not set, continue processing next phoneme 4303 | if(A == 0) { 4304 | pos++; 4305 | continue; 4306 | } 4307 | 4308 | phonemeindex[X] = 16; 4309 | pos++; 4310 | continue; 4311 | } 4312 | pos41779: 4313 | 4314 | // RULE: 4315 | // CH -> CH CH' (CH requires two phonemes to represent it) 4316 | // Example: CHEW 4317 | 4318 | if(A == 42) // 'CH' 4319 | { 4320 | // pos41783: 4321 | 4322 | Insert(X + 1, A + 1, mem59, stress[X]); 4323 | pos++; 4324 | continue; 4325 | } 4326 | 4327 | pos41788: 4328 | 4329 | // RULE: 4330 | // J -> J J' (J requires two phonemes to represent it) 4331 | // Example: JAY 4332 | 4333 | if(A == 44) // 'J' 4334 | { 4335 | Insert(X + 1, A + 1, mem59, stress[X]); 4336 | pos++; 4337 | continue; 4338 | } 4339 | 4340 | // Jump here to continue 4341 | pos41812: 4342 | 4343 | // RULE: Soften T following vowel 4344 | // NOTE: This rule fails for cases such as "ODD" 4345 | // T -> DX 4346 | // D -> DX 4347 | // Example: PARTY, TARDY 4348 | 4349 | // Past this point, only process if phoneme is T or D 4350 | 4351 | if(A != 69) // 'T' 4352 | if(A != 57) { 4353 | pos++; // 'D' 4354 | continue; 4355 | } 4356 | //pos41825: 4357 | 4358 | // If prior phoneme is not a vowel, continue processing phonemes 4359 | if((flags[phonemeindex[X - 1]] & 128) == 0) { 4360 | pos++; 4361 | continue; 4362 | } 4363 | 4364 | // Get next phoneme 4365 | X++; 4366 | A = phonemeindex[X]; 4367 | //pos41841 4368 | // Is the next phoneme a pause? 4369 | if(A != 0) { 4370 | // If next phoneme is not a pause, continue processing phonemes 4371 | if((flags[A] & 128) == 0) { 4372 | pos++; 4373 | continue; 4374 | } 4375 | // If next phoneme is stressed, continue processing phonemes 4376 | // FIXME: How does a pause get stressed? 4377 | if(stress[X] != 0) { 4378 | pos++; 4379 | continue; 4380 | } 4381 | //pos41856: 4382 | // Set phonemes to DX 4383 | 4384 | phonemeindex[pos] = 30; // 'DX' 4385 | } else { 4386 | A = phonemeindex[X + 1]; 4387 | if(A == 255) //prevent buffer overflow 4388 | A = 65 & 128; 4389 | else 4390 | // Is next phoneme a vowel or ER? 4391 | A = flags[A] & 128; 4392 | 4393 | if(A != 0) phonemeindex[pos] = 30; // 'DX' 4394 | } 4395 | 4396 | pos++; 4397 | 4398 | } // while 4399 | } // parser 2 4400 | 4401 | // Applies various rules that adjust the lengths of phonemes 4402 | // 4403 | // Lengthen or between and by 1.5 4404 | // - decrease length by 1 4405 | // - decrease vowel by 1/8th 4406 | // - increase vowel by 1/2 + 1 4407 | // - set nasal = 5, consonant = 6 4408 | // {optional silence} - shorten both to 1/2 + 1 4409 | // - decrease by 2 4410 | 4411 | //void Code48619() 4412 | void STM32SAM::AdjustLengths() { 4413 | // LENGTHEN VOWELS PRECEDING PUNCTUATION 4414 | // 4415 | // Search for punctuation. If found, back up to the first vowel, then 4416 | // process all phonemes between there and up to (but not including) the punctuation. 4417 | // If any phoneme is found that is a either a fricative or voiced, the duration is 4418 | // increased by (length * 1.5) + 1 4419 | 4420 | // loop index 4421 | X = 0; 4422 | unsigned char index; 4423 | 4424 | // iterate through the phoneme list 4425 | unsigned char loopIndex = 0; 4426 | while(1) { 4427 | // get a phoneme 4428 | index = phonemeindex[X]; 4429 | 4430 | // exit loop if end on buffer token 4431 | if(index == 255) break; 4432 | 4433 | // not punctuation? 4434 | if((flags2[index] & 1) == 0) { 4435 | // skip 4436 | X++; 4437 | continue; 4438 | } 4439 | 4440 | // hold index 4441 | loopIndex = X; 4442 | 4443 | // Loop backwards from this point 4444 | pos48644: 4445 | 4446 | // back up one phoneme 4447 | X--; 4448 | 4449 | // stop once the beginning is reached 4450 | if(X == 0) break; 4451 | 4452 | // get the preceding phoneme 4453 | index = phonemeindex[X]; 4454 | 4455 | if(index != 255) //inserted to prevent access overrun 4456 | if((flags[index] & 128) == 0) goto pos48644; // if not a vowel, continue looping 4457 | 4458 | //pos48657: 4459 | do { 4460 | // test for vowel 4461 | index = phonemeindex[X]; 4462 | 4463 | if(index != 255) //inserted to prevent access overrun 4464 | // test for fricative/unvoiced or not voiced 4465 | if(((flags2[index] & 32) == 0) || ((flags[index] & 4) != 0)) //nochmal �berpr�fen 4466 | { 4467 | //A = flags[Y] & 4; 4468 | //if(A == 0) goto pos48688; 4469 | 4470 | // get the phoneme length 4471 | A = phonemeLength[X]; 4472 | 4473 | // change phoneme length to (length * 1.5) + 1 4474 | A = (A >> 1) + A + 1; 4475 | 4476 | phonemeLength[X] = A; 4477 | } 4478 | // keep moving forward 4479 | X++; 4480 | } while(X != loopIndex); 4481 | // if (X != loopIndex) goto pos48657; 4482 | X++; 4483 | } // while 4484 | 4485 | // Similar to the above routine, but shorten vowels under some circumstances 4486 | 4487 | // Loop throught all phonemes 4488 | loopIndex = 0; 4489 | //pos48697 4490 | 4491 | while(1) { 4492 | // get a phoneme 4493 | X = loopIndex; 4494 | index = phonemeindex[X]; 4495 | 4496 | // exit routine at end token 4497 | if(index == 255) return; 4498 | 4499 | // vowel? 4500 | A = flags[index] & 128; 4501 | if(A != 0) { 4502 | // get next phoneme 4503 | X++; 4504 | index = phonemeindex[X]; 4505 | 4506 | // get flags 4507 | if(index == 255) 4508 | mem56 = 65; // use if end marker 4509 | else 4510 | mem56 = flags[index]; 4511 | 4512 | // not a consonant 4513 | if((flags[index] & 64) == 0) { 4514 | // RX or LX? 4515 | if((index == 18) || (index == 19)) // 'RX' & 'LX' 4516 | { 4517 | // get the next phoneme 4518 | X++; 4519 | index = phonemeindex[X]; 4520 | 4521 | // next phoneme a consonant? 4522 | if((flags[index] & 64) != 0) { 4523 | // RULE: RX | LX 4524 | 4525 | // decrease length of vowel by 1 frame 4526 | phonemeLength[loopIndex]--; 4527 | } 4528 | // move ahead 4529 | loopIndex++; 4530 | continue; 4531 | } 4532 | // move ahead 4533 | loopIndex++; 4534 | continue; 4535 | } 4536 | 4537 | // Got here if not 4538 | 4539 | // not voiced 4540 | if((mem56 & 4) == 0) { 4541 | // Unvoiced 4542 | // *, .*, ?*, ,*, -*, DX, S*, SH, F*, TH, /H, /X, CH, P*, T*, K*, KX 4543 | 4544 | // not an unvoiced plosive? 4545 | if((mem56 & 1) == 0) { 4546 | // move ahead 4547 | loopIndex++; 4548 | continue; 4549 | } 4550 | 4551 | // P*, T*, K*, KX 4552 | 4553 | // RULE: 4554 | // 4555 | 4556 | // move back 4557 | X--; 4558 | 4559 | // decrease length by 1/8th 4560 | mem56 = phonemeLength[X] >> 3; 4561 | phonemeLength[X] -= mem56; 4562 | 4563 | // move ahead 4564 | loopIndex++; 4565 | continue; 4566 | } 4567 | 4568 | // RULE: 4569 | // 4570 | 4571 | // decrease length 4572 | A = phonemeLength[X - 1]; 4573 | phonemeLength[X - 1] = (A >> 2) + A + 1; // 5/4*A + 1 4574 | 4575 | // move ahead 4576 | loopIndex++; 4577 | continue; 4578 | } 4579 | 4580 | // WH, R*, L*, W*, Y*, M*, N*, NX, Q*, Z*, ZH, V*, DH, J*, B*, D*, G*, GX 4581 | 4582 | //pos48821: 4583 | 4584 | // RULE: 4585 | // Set punctuation length to 6 4586 | // Set stop consonant length to 5 4587 | 4588 | // nasal? 4589 | if((flags2[index] & 8) != 0) { 4590 | // M*, N*, NX, 4591 | 4592 | // get the next phoneme 4593 | X++; 4594 | index = phonemeindex[X]; 4595 | 4596 | // end of buffer? 4597 | if(index == 255) 4598 | A = 65 & 2; //prevent buffer overflow 4599 | else 4600 | A = flags[index] & 2; // check for stop consonant 4601 | 4602 | // is next phoneme a stop consonant? 4603 | if(A != 0) 4604 | 4605 | // B*, D*, G*, GX, P*, T*, K*, KX 4606 | 4607 | { 4608 | // set stop consonant length to 6 4609 | phonemeLength[X] = 6; 4610 | 4611 | // set nasal length to 5 4612 | phonemeLength[X - 1] = 5; 4613 | } 4614 | // move to next phoneme 4615 | loopIndex++; 4616 | continue; 4617 | } 4618 | 4619 | // WH, R*, L*, W*, Y*, Q*, Z*, ZH, V*, DH, J*, B*, D*, G*, GX 4620 | 4621 | // RULE: {optional silence} 4622 | // Shorten both to (length/2 + 1) 4623 | 4624 | // (voiced) stop consonant? 4625 | if((flags[index] & 2) != 0) { 4626 | // B*, D*, G*, GX 4627 | 4628 | // move past silence 4629 | do { 4630 | // move ahead 4631 | X++; 4632 | index = phonemeindex[X]; 4633 | } while(index == 0); 4634 | 4635 | // check for end of buffer 4636 | if(index == 255) //buffer overflow 4637 | { 4638 | // ignore, overflow code 4639 | if((65 & 2) == 0) { 4640 | loopIndex++; 4641 | continue; 4642 | } 4643 | } else if((flags[index] & 2) == 0) { 4644 | // if another stop consonant, move ahead 4645 | loopIndex++; 4646 | continue; 4647 | } 4648 | 4649 | // RULE: {optional silence} 4650 | 4651 | // X gets overwritten, so hold prior X value for debug statement 4652 | // int debugX = X; 4653 | // shorten the prior phoneme length to (length/2 + 1) 4654 | phonemeLength[X] = (phonemeLength[X] >> 1) + 1; 4655 | X = loopIndex; 4656 | 4657 | // also shorten this phoneme length to (length/2 +1) 4658 | phonemeLength[loopIndex] = (phonemeLength[loopIndex] >> 1) + 1; 4659 | 4660 | // move ahead 4661 | loopIndex++; 4662 | continue; 4663 | } 4664 | 4665 | // WH, R*, L*, W*, Y*, Q*, Z*, ZH, V*, DH, J*, **, 4666 | 4667 | // RULE: 4668 | // Decrease by 2 4669 | 4670 | // liquic consonant? 4671 | if((flags2[index] & 16) != 0) { 4672 | // R*, L*, W*, Y* 4673 | 4674 | // get the prior phoneme 4675 | index = phonemeindex[X - 1]; 4676 | 4677 | // prior phoneme a stop consonant> 4678 | if((flags[index] & 2) != 0) { 4679 | // Rule: 4680 | 4681 | // decrease the phoneme length by 2 frames (20 ms) 4682 | phonemeLength[X] -= 2; 4683 | } 4684 | } 4685 | 4686 | // move to next phoneme 4687 | loopIndex++; 4688 | continue; 4689 | } 4690 | // goto pos48701; 4691 | } 4692 | 4693 | // ------------------------------------------------------------------------- 4694 | // ML : Code47503 is division with remainder, and mem50 gets the sign 4695 | void STM32SAM::Code47503(unsigned char mem52) { 4696 | Y = 0; 4697 | if((mem53 & 128) != 0) { 4698 | mem53 = -mem53; 4699 | Y = 128; 4700 | } 4701 | mem50 = Y; 4702 | A = 0; 4703 | for(X = 8; X > 0; X--) { 4704 | int temp = mem53; 4705 | mem53 = mem53 << 1; 4706 | A = A << 1; 4707 | if(temp >= 128) A++; 4708 | if(A >= mem52) { 4709 | A = A - mem52; 4710 | mem53++; 4711 | } 4712 | } 4713 | 4714 | mem51 = A; 4715 | if((mem50 & 128) != 0) mem53 = -mem53; 4716 | } 4717 | 4718 | //////////////////////////////////////////////////////////////////////////////////////////// 4719 | // 4720 | // Reciter 4721 | // 4722 | //////////////////////////////////////////////////////////////////////////////////////////// 4723 | 4724 | void STM32SAM::Code37055(unsigned char mem59) { 4725 | X = mem59; 4726 | X--; 4727 | A = inputtemp[X]; 4728 | Y = A; 4729 | A = tab36376[Y]; 4730 | return; 4731 | } 4732 | 4733 | void STM32SAM::Code37066(unsigned char mem58) { 4734 | X = mem58; 4735 | X++; 4736 | A = inputtemp[X]; 4737 | Y = A; 4738 | A = tab36376[Y]; 4739 | } 4740 | 4741 | unsigned char STM32SAM::GetRuleByte(unsigned short mem62, unsigned char Y) { 4742 | unsigned int address = mem62; 4743 | 4744 | if(mem62 >= 37541) { 4745 | address -= 37541; 4746 | return rules2[address + Y]; 4747 | } 4748 | address -= 32000; 4749 | return rules[address + Y]; 4750 | } 4751 | 4752 | int STM32SAM::TextToPhonemes(unsigned char* input) // Code36484 4753 | { 4754 | //unsigned char *tab39445 = &mem[39445]; //input and output 4755 | //unsigned char mem29; 4756 | unsigned char mem56; //output position for phonemes 4757 | unsigned char mem57; 4758 | unsigned char mem58; 4759 | unsigned char mem59; 4760 | unsigned char mem60; 4761 | unsigned char mem61; 4762 | unsigned short mem62; // memory position of current rule 4763 | 4764 | unsigned char mem64; // position of '=' or current character 4765 | unsigned char mem65; // position of ')' 4766 | unsigned char mem66; // position of '(' 4767 | unsigned char mem36653; 4768 | 4769 | inputtemp[0] = 32; 4770 | 4771 | // secure copy of input 4772 | // because input will be overwritten by phonemes 4773 | X = 1; 4774 | Y = 0; 4775 | do { 4776 | //pos36499: 4777 | A = input[Y] & 127; 4778 | if(A >= 112) 4779 | A = A & 95; 4780 | else if(A >= 96) 4781 | A = A & 79; 4782 | 4783 | inputtemp[X] = A; 4784 | X++; 4785 | Y++; 4786 | } while(Y != 255); 4787 | 4788 | X = 255; 4789 | inputtemp[X] = 27; 4790 | mem61 = 255; 4791 | 4792 | pos36550: 4793 | A = 255; 4794 | mem56 = 255; 4795 | 4796 | pos36554: 4797 | while(1) { 4798 | mem61++; 4799 | X = mem61; 4800 | A = inputtemp[X]; 4801 | mem64 = A; 4802 | if(A == '[') { 4803 | mem56++; 4804 | X = mem56; 4805 | A = 155; 4806 | input[X] = 155; 4807 | //goto pos36542; 4808 | // Code39771(); //Code39777(); 4809 | return 1; 4810 | } 4811 | 4812 | //pos36579: 4813 | if(A != '.') break; 4814 | X++; 4815 | Y = inputtemp[X]; 4816 | A = tab36376[Y] & 1; 4817 | if(A != 0) break; 4818 | mem56++; 4819 | X = mem56; 4820 | A = '.'; 4821 | input[X] = '.'; 4822 | } //while 4823 | 4824 | //pos36607: 4825 | A = mem64; 4826 | Y = A; 4827 | A = tab36376[A]; 4828 | mem57 = A; 4829 | if((A & 2) != 0) { 4830 | mem62 = 37541; 4831 | goto pos36700; 4832 | } 4833 | 4834 | //pos36630: 4835 | A = mem57; 4836 | if(A != 0) goto pos36677; 4837 | A = 32; 4838 | inputtemp[X] = ' '; 4839 | mem56++; 4840 | X = mem56; 4841 | if(X > 120) goto pos36654; 4842 | input[X] = A; 4843 | goto pos36554; 4844 | 4845 | // ----- 4846 | 4847 | //36653 is unknown. Contains position 4848 | 4849 | pos36654: 4850 | input[X] = 155; 4851 | A = mem61; 4852 | mem36653 = A; 4853 | // mem29 = A; // not used 4854 | // Code36538(); das ist eigentlich 4855 | return 1; 4856 | //Code39771(); 4857 | //go on if there is more input ??? 4858 | mem61 = mem36653; 4859 | goto pos36550; 4860 | 4861 | pos36677: 4862 | A = mem57 & 128; 4863 | if(A == 0) { 4864 | //36683: BRK 4865 | return 0; 4866 | } 4867 | 4868 | // go to the right rules for this character. 4869 | X = mem64 - 'A'; 4870 | mem62 = tab37489[X] | (tab37515[X] << 8); 4871 | 4872 | // ------------------------------------- 4873 | // go to next rule 4874 | // ------------------------------------- 4875 | 4876 | pos36700: 4877 | 4878 | // find next rule 4879 | Y = 0; 4880 | do { 4881 | mem62 += 1; 4882 | A = GetRuleByte(mem62, Y); 4883 | } while((A & 128) == 0); 4884 | Y++; 4885 | 4886 | //pos36720: 4887 | // find '(' 4888 | while(1) { 4889 | A = GetRuleByte(mem62, Y); 4890 | if(A == '(') break; 4891 | Y++; 4892 | } 4893 | mem66 = Y; 4894 | 4895 | //pos36732: 4896 | // find ')' 4897 | do { 4898 | Y++; 4899 | A = GetRuleByte(mem62, Y); 4900 | } while(A != ')'); 4901 | mem65 = Y; 4902 | 4903 | //pos36741: 4904 | // find '=' 4905 | do { 4906 | Y++; 4907 | A = GetRuleByte(mem62, Y); 4908 | A = A & 127; 4909 | } while(A != '='); 4910 | mem64 = Y; 4911 | 4912 | X = mem61; 4913 | mem60 = X; 4914 | 4915 | // compare the string within the bracket 4916 | Y = mem66; 4917 | Y++; 4918 | //pos36759: 4919 | while(1) { 4920 | mem57 = inputtemp[X]; 4921 | A = GetRuleByte(mem62, Y); 4922 | if(A != mem57) goto pos36700; 4923 | Y++; 4924 | if(Y == mem65) break; 4925 | X++; 4926 | mem60 = X; 4927 | } 4928 | 4929 | // the string in the bracket is correct 4930 | 4931 | //pos36787: 4932 | A = mem61; 4933 | mem59 = mem61; 4934 | 4935 | pos36791: 4936 | while(1) { 4937 | mem66--; 4938 | Y = mem66; 4939 | A = GetRuleByte(mem62, Y); 4940 | mem57 = A; 4941 | //36800: BPL 36805 4942 | if((A & 128) != 0) goto pos37180; 4943 | X = A & 127; 4944 | A = tab36376[X] & 128; 4945 | if(A == 0) break; 4946 | X = mem59 - 1; 4947 | A = inputtemp[X]; 4948 | if(A != mem57) goto pos36700; 4949 | mem59 = X; 4950 | } 4951 | 4952 | //pos36833: 4953 | A = mem57; 4954 | if(A == ' ') goto pos36895; 4955 | if(A == '#') goto pos36910; 4956 | if(A == '.') goto pos36920; 4957 | if(A == '&') goto pos36935; 4958 | if(A == '@') goto pos36967; 4959 | if(A == '^') goto pos37004; 4960 | if(A == '+') goto pos37019; 4961 | if(A == ':') goto pos37040; 4962 | // Code42041(); //Error 4963 | //36894: BRK 4964 | return 0; 4965 | 4966 | // -------------- 4967 | 4968 | pos36895: 4969 | Code37055(mem59); 4970 | A = A & 128; 4971 | if(A != 0) goto pos36700; 4972 | pos36905: 4973 | mem59 = X; 4974 | goto pos36791; 4975 | 4976 | // -------------- 4977 | 4978 | pos36910: 4979 | Code37055(mem59); 4980 | A = A & 64; 4981 | if(A != 0) goto pos36905; 4982 | goto pos36700; 4983 | 4984 | // -------------- 4985 | 4986 | pos36920: 4987 | Code37055(mem59); 4988 | A = A & 8; 4989 | if(A == 0) goto pos36700; 4990 | pos36930: 4991 | mem59 = X; 4992 | goto pos36791; 4993 | 4994 | // -------------- 4995 | 4996 | pos36935: 4997 | Code37055(mem59); 4998 | A = A & 16; 4999 | if(A != 0) goto pos36930; 5000 | A = inputtemp[X]; 5001 | if(A != 72) goto pos36700; 5002 | X--; 5003 | A = inputtemp[X]; 5004 | if((A == 67) || (A == 83)) goto pos36930; 5005 | goto pos36700; 5006 | 5007 | // -------------- 5008 | 5009 | pos36967: 5010 | Code37055(mem59); 5011 | A = A & 4; 5012 | if(A != 0) goto pos36930; 5013 | A = inputtemp[X]; 5014 | if(A != 72) goto pos36700; 5015 | if((A != 84) && (A != 67) && (A != 83)) goto pos36700; 5016 | mem59 = X; 5017 | goto pos36791; 5018 | 5019 | // -------------- 5020 | 5021 | pos37004: 5022 | Code37055(mem59); 5023 | A = A & 32; 5024 | if(A == 0) goto pos36700; 5025 | 5026 | pos37014: 5027 | mem59 = X; 5028 | goto pos36791; 5029 | 5030 | // -------------- 5031 | 5032 | pos37019: 5033 | X = mem59; 5034 | X--; 5035 | A = inputtemp[X]; 5036 | if((A == 'E') || (A == 'I') || (A == 'Y')) goto pos37014; 5037 | goto pos36700; 5038 | // -------------- 5039 | 5040 | pos37040: 5041 | Code37055(mem59); 5042 | A = A & 32; 5043 | if(A == 0) goto pos36791; 5044 | mem59 = X; 5045 | goto pos37040; 5046 | 5047 | //--------------------------------------- 5048 | 5049 | pos37077: 5050 | X = mem58 + 1; 5051 | A = inputtemp[X]; 5052 | if(A != 'E') goto pos37157; 5053 | X++; 5054 | Y = inputtemp[X]; 5055 | X--; 5056 | A = tab36376[Y] & 128; 5057 | if(A == 0) goto pos37108; 5058 | X++; 5059 | A = inputtemp[X]; 5060 | if(A != 'R') goto pos37113; 5061 | pos37108: 5062 | mem58 = X; 5063 | goto pos37184; 5064 | pos37113: 5065 | if((A == 83) || (A == 68)) goto pos37108; // 'S' 'D' 5066 | if(A != 76) goto pos37135; // 'L' 5067 | X++; 5068 | A = inputtemp[X]; 5069 | if(A != 89) goto pos36700; 5070 | goto pos37108; 5071 | 5072 | pos37135: 5073 | if(A != 70) goto pos36700; 5074 | X++; 5075 | A = inputtemp[X]; 5076 | if(A != 85) goto pos36700; 5077 | X++; 5078 | A = inputtemp[X]; 5079 | if(A == 76) goto pos37108; 5080 | goto pos36700; 5081 | 5082 | pos37157: 5083 | if(A != 73) goto pos36700; 5084 | X++; 5085 | A = inputtemp[X]; 5086 | if(A != 78) goto pos36700; 5087 | X++; 5088 | A = inputtemp[X]; 5089 | if(A == 71) goto pos37108; 5090 | //pos37177: 5091 | goto pos36700; 5092 | 5093 | // ----------------------------------------- 5094 | 5095 | pos37180: 5096 | 5097 | A = mem60; 5098 | mem58 = A; 5099 | 5100 | pos37184: 5101 | Y = mem65 + 1; 5102 | 5103 | //37187: CPY 64 5104 | // if(? != 0) goto pos37194; 5105 | if(Y == mem64) goto pos37455; 5106 | mem65 = Y; 5107 | //37196: LDA (62),y 5108 | A = GetRuleByte(mem62, Y); 5109 | mem57 = A; 5110 | X = A; 5111 | A = tab36376[X] & 128; 5112 | if(A == 0) goto pos37226; 5113 | X = mem58 + 1; 5114 | A = inputtemp[X]; 5115 | if(A != mem57) goto pos36700; 5116 | mem58 = X; 5117 | goto pos37184; 5118 | pos37226: 5119 | A = mem57; 5120 | if(A == 32) goto pos37295; // ' ' 5121 | if(A == 35) goto pos37310; // '#' 5122 | if(A == 46) goto pos37320; // '.' 5123 | if(A == 38) goto pos37335; // '&' 5124 | if(A == 64) goto pos37367; // '' 5125 | if(A == 94) goto pos37404; // '' 5126 | if(A == 43) goto pos37419; // '+' 5127 | if(A == 58) goto pos37440; // ':' 5128 | if(A == 37) goto pos37077; // '%' 5129 | //pos37291: 5130 | // Code42041(); //Error 5131 | //37294: BRK 5132 | return 0; 5133 | 5134 | // -------------- 5135 | pos37295: 5136 | Code37066(mem58); 5137 | A = A & 128; 5138 | if(A != 0) goto pos36700; 5139 | pos37305: 5140 | mem58 = X; 5141 | goto pos37184; 5142 | 5143 | // -------------- 5144 | 5145 | pos37310: 5146 | Code37066(mem58); 5147 | A = A & 64; 5148 | if(A != 0) goto pos37305; 5149 | goto pos36700; 5150 | 5151 | // -------------- 5152 | 5153 | pos37320: 5154 | Code37066(mem58); 5155 | A = A & 8; 5156 | if(A == 0) goto pos36700; 5157 | 5158 | pos37330: 5159 | mem58 = X; 5160 | goto pos37184; 5161 | 5162 | // -------------- 5163 | 5164 | pos37335: 5165 | Code37066(mem58); 5166 | A = A & 16; 5167 | if(A != 0) goto pos37330; 5168 | A = inputtemp[X]; 5169 | if(A != 72) goto pos36700; 5170 | X++; 5171 | A = inputtemp[X]; 5172 | if((A == 67) || (A == 83)) goto pos37330; 5173 | goto pos36700; 5174 | 5175 | // -------------- 5176 | 5177 | pos37367: 5178 | Code37066(mem58); 5179 | A = A & 4; 5180 | if(A != 0) goto pos37330; 5181 | A = inputtemp[X]; 5182 | if(A != 72) goto pos36700; 5183 | if((A != 84) && (A != 67) && (A != 83)) goto pos36700; 5184 | mem58 = X; 5185 | goto pos37184; 5186 | 5187 | // -------------- 5188 | 5189 | pos37404: 5190 | Code37066(mem58); 5191 | A = A & 32; 5192 | if(A == 0) goto pos36700; 5193 | pos37414: 5194 | mem58 = X; 5195 | goto pos37184; 5196 | 5197 | // -------------- 5198 | 5199 | pos37419: 5200 | X = mem58; 5201 | X++; 5202 | A = inputtemp[X]; 5203 | if((A == 69) || (A == 73) || (A == 89)) goto pos37414; 5204 | goto pos36700; 5205 | 5206 | // ---------------------- 5207 | 5208 | pos37440: 5209 | 5210 | Code37066(mem58); 5211 | A = A & 32; 5212 | if(A == 0) goto pos37184; 5213 | mem58 = X; 5214 | goto pos37440; 5215 | pos37455: 5216 | Y = mem64; 5217 | mem61 = mem60; 5218 | 5219 | pos37461: 5220 | //37461: LDA (62),y 5221 | A = GetRuleByte(mem62, Y); 5222 | mem57 = A; 5223 | A = A & 127; 5224 | if(A != '=') { 5225 | mem56++; 5226 | X = mem56; 5227 | input[X] = A; 5228 | } 5229 | 5230 | //37478: BIT 57 5231 | //37480: BPL 37485 //not negative flag 5232 | if((mem57 & 128) == 0) goto pos37485; //??? 5233 | goto pos36554; 5234 | pos37485: 5235 | Y++; 5236 | goto pos37461; 5237 | } 5238 | 5239 | // Constructor 5240 | 5241 | STM32SAM::STM32SAM(uint32_t STM32SAM_SPEED /* = 5 */) { 5242 | STM32SAM_SPEED = STM32SAM_SPEED & 0x1f; // limit it from 0 to 31 5243 | 5244 | _STM32SAM_SPEED = STM32SAM_SPEED; 5245 | 5246 | // set default voice 5247 | 5248 | speed = 72; 5249 | pitch = 64; 5250 | mouth = 128; 5251 | throat = 128; 5252 | 5253 | phonetic = 0; 5254 | singmode = 0; 5255 | 5256 | wait1 = 7; 5257 | wait2 = 6; 5258 | 5259 | mem59 = 0; 5260 | 5261 | oldtimetableindex = 0; 5262 | } 5263 | 5264 | STM32SAM::STM32SAM() { 5265 | _STM32SAM_SPEED = 7; 5266 | 5267 | // set default voice 5268 | 5269 | speed = 72; 5270 | pitch = 64; 5271 | mouth = 128; 5272 | throat = 128; 5273 | 5274 | phonetic = 0; 5275 | singmode = 0; 5276 | 5277 | wait1 = 7; 5278 | wait2 = 6; 5279 | 5280 | mem59 = 0; 5281 | 5282 | oldtimetableindex = 0; 5283 | } 5284 | 5285 | /* 5286 | STM32SAM::~STM32SAM() { 5287 | { 5288 | // TODO: end(); 5289 | } 5290 | */ 5291 | 5292 | //////////////////////////////////////////////////////////////////////////////////////////// 5293 | // 5294 | // STM32SAM sam (variable string, phonetic, sing, pitch, speed, mouth, throat) 5295 | // STM32SAM say (sing off, phonetic off) (const string) 5296 | // STM32SAM say (sing off, phonetic off) (variable string) 5297 | // STM32SAM sing (sing on, phonetic off) (const string) 5298 | // STM32SAM sing (sing on, phonetic off) (variable string) 5299 | // STM32SAM sayPhonetic (sing off, phonetic on) (const string) 5300 | // STM32SAM sayPhonetic (sing off, phonetic on) (variable string) 5301 | // STM32SAM singPhonetic (sing on, phonetic on) (const string) 5302 | // STM32SAM singPhonetic (sing on, phonetic on) (variable string) 5303 | // STM32SAM voice (pitch, speed, mouth, throat) 5304 | // STM32SAM setPitch (pitch) 5305 | // STM32SAM setSpeed (speed) 5306 | // STM32SAM setMouth (mouth) 5307 | // STM32SAM setThroat (throat) 5308 | // 5309 | // 5310 | //////////////////////////////////////////////////////////////////////////////////////////// 5311 | 5312 | //////////////////////////////////////////////////////////////////////////////////////////// 5313 | // 5314 | // STM32SAM sam (const string, phonetic, sing, pitch, speed, mouth, throat) 5315 | // 5316 | //////////////////////////////////////////////////////////////////////////////////////////// 5317 | 5318 | char to_upper_case(char c) { 5319 | if(c >= 'a' && c <= 'z') { 5320 | return c - 'a' + 'A'; 5321 | } 5322 | return c; 5323 | } 5324 | 5325 | void STM32SAM::sam( 5326 | const char* argv, 5327 | unsigned char _phonetic, 5328 | unsigned char _singmode, 5329 | unsigned char _pitch, 5330 | unsigned char _speed, 5331 | unsigned char _mouth, 5332 | unsigned char _throat) { 5333 | phonetic = _phonetic; 5334 | singmode = _singmode; 5335 | pitch = _pitch; 5336 | speed = _speed; 5337 | mouth = _mouth; 5338 | throat = _throat; 5339 | 5340 | int i; 5341 | 5342 | for(i = 0; i < 256; i++) { 5343 | input[i] = argv[i]; 5344 | } 5345 | 5346 | for(i = 0; input[i] != 0; i++) { 5347 | if(i != 0) { 5348 | input[i] = to_upper_case((int)argv[i]); 5349 | } 5350 | } 5351 | 5352 | if(!phonetic) { 5353 | strncat(input, "[", 256); 5354 | if(!TextToPhonemes((unsigned char*)input)) { 5355 | // PrintUsage(); 5356 | return; 5357 | } 5358 | 5359 | } else { 5360 | strncat(input, "\x9b", 256); 5361 | } 5362 | 5363 | SetInput(input); 5364 | 5365 | if(!SAMMain()) { 5366 | return; 5367 | } 5368 | } 5369 | 5370 | //////////////////////////////////////////////////////////////////////////////////////////// 5371 | // 5372 | // STM32SAM sam (variable string, phonetic, sing, pitch, speed, mouth, throat) 5373 | // 5374 | //////////////////////////////////////////////////////////////////////////////////////////// 5375 | 5376 | void STM32SAM::sam( 5377 | char* argv, 5378 | unsigned char _phonetic, 5379 | unsigned char _singmode, 5380 | unsigned char _pitch, 5381 | unsigned char _speed, 5382 | unsigned char _mouth, 5383 | unsigned char _throat) { 5384 | phonetic = _phonetic; 5385 | singmode = _singmode; 5386 | pitch = _pitch; 5387 | speed = _speed; 5388 | mouth = _mouth; 5389 | throat = _throat; 5390 | 5391 | int i; 5392 | 5393 | for(i = 0; i < 256; i++) { 5394 | input[i] = argv[i]; 5395 | } 5396 | 5397 | for(i = 0; input[i] != 0; i++) { 5398 | if(i != 0) { 5399 | input[i] = to_upper_case((int)argv[i]); 5400 | } 5401 | } 5402 | 5403 | if(!phonetic) { 5404 | strncat(input, "[", 256); 5405 | if(!TextToPhonemes((unsigned char*)input)) { 5406 | // PrintUsage(); 5407 | return; 5408 | } 5409 | 5410 | } else { 5411 | strncat(input, "\x9b", 256); 5412 | } 5413 | 5414 | SetInput(input); 5415 | 5416 | if(!SAMMain()) { 5417 | return; 5418 | } 5419 | } 5420 | 5421 | //////////////////////////////////////////////////////////////////////////////////////////// 5422 | // 5423 | // STM32SAM say(sing off, phonetic off) (const string) 5424 | // 5425 | //////////////////////////////////////////////////////////////////////////////////////////// 5426 | 5427 | void STM32SAM::say(const char* argv) { 5428 | int i; 5429 | 5430 | phonetic = 0; 5431 | singmode = 0; 5432 | 5433 | char const_input[256]; 5434 | 5435 | for(i = 0; i < 256; i++) { 5436 | const_input[i] = argv[i]; 5437 | } 5438 | 5439 | sam(const_input, phonetic, singmode, pitch, speed, mouth, throat); 5440 | } 5441 | 5442 | void STM32SAM::say(char* argv) { 5443 | int i; 5444 | 5445 | phonetic = 0; 5446 | singmode = 0; 5447 | 5448 | char const_input[256]; 5449 | 5450 | for(i = 0; i < 256; i++) { 5451 | const_input[i] = argv[i]; 5452 | } 5453 | 5454 | sam(const_input, phonetic, singmode, pitch, speed, mouth, throat); 5455 | } 5456 | 5457 | //////////////////////////////////////////////////////////////////////////////////////////// 5458 | // 5459 | // STM32SAM sing (sing on, phonetic off) 5460 | // 5461 | //////////////////////////////////////////////////////////////////////////////////////////// 5462 | 5463 | void STM32SAM::sing(const char* argv) { 5464 | int i; 5465 | 5466 | phonetic = 0; 5467 | singmode = 1; 5468 | 5469 | char const_input[256]; 5470 | 5471 | for(i = 0; i < 256; i++) { 5472 | const_input[i] = argv[i]; 5473 | } 5474 | 5475 | sam(const_input, phonetic, singmode, pitch, speed, mouth, throat); 5476 | } 5477 | 5478 | void STM32SAM::sing(char* argv) { 5479 | int i; 5480 | 5481 | phonetic = 0; 5482 | singmode = 1; 5483 | 5484 | char const_input[256]; 5485 | 5486 | for(i = 0; i < 256; i++) { 5487 | const_input[i] = argv[i]; 5488 | } 5489 | 5490 | sam(const_input, phonetic, singmode, pitch, speed, mouth, throat); 5491 | } 5492 | 5493 | //////////////////////////////////////////////////////////////////////////////////////////// 5494 | // 5495 | // STM32SAM sayPhonetic (sing off, phonetic on) 5496 | // 5497 | //////////////////////////////////////////////////////////////////////////////////////////// 5498 | 5499 | void STM32SAM::sayPhonetic(const char* argv) { 5500 | int i; 5501 | 5502 | phonetic = 1; 5503 | singmode = 0; 5504 | 5505 | char const_input[256]; 5506 | 5507 | for(i = 0; i < 256; i++) { 5508 | const_input[i] = argv[i]; 5509 | } 5510 | 5511 | sam(const_input, phonetic, singmode, pitch, speed, mouth, throat); 5512 | } 5513 | 5514 | void STM32SAM::sayPhonetic(char* argv) { 5515 | int i; 5516 | 5517 | phonetic = 1; 5518 | singmode = 0; 5519 | 5520 | char const_input[256]; 5521 | 5522 | for(i = 0; i < 256; i++) { 5523 | const_input[i] = argv[i]; 5524 | } 5525 | 5526 | sam(const_input, phonetic, singmode, pitch, speed, mouth, throat); 5527 | } 5528 | 5529 | //////////////////////////////////////////////////////////////////////////////////////////// 5530 | // 5531 | // STM32SAM singPhonetic (sing on, phonetic on) 5532 | // 5533 | //////////////////////////////////////////////////////////////////////////////////////////// 5534 | 5535 | void STM32SAM::singPhonetic(const char* argv) { 5536 | int i; 5537 | 5538 | phonetic = 1; 5539 | singmode = 1; 5540 | 5541 | char const_input[256]; 5542 | 5543 | for(i = 0; i < 256; i++) { 5544 | const_input[i] = argv[i]; 5545 | } 5546 | 5547 | sam(const_input, phonetic, singmode, pitch, speed, mouth, throat); 5548 | } 5549 | 5550 | void STM32SAM::singPhonetic(char* argv) { 5551 | int i; 5552 | 5553 | phonetic = 1; 5554 | singmode = 0; 5555 | 5556 | char const_input[256]; 5557 | 5558 | for(i = 0; i < 256; i++) { 5559 | const_input[i] = argv[i]; 5560 | } 5561 | 5562 | sam(const_input, phonetic, singmode, pitch, speed, mouth, throat); 5563 | } 5564 | 5565 | //////////////////////////////////////////////////////////////////////////////////////////// 5566 | // 5567 | // STM32SAM voice (pitch, speed, mouth, throat) 5568 | // 5569 | //////////////////////////////////////////////////////////////////////////////////////////// 5570 | 5571 | void STM32SAM::setVoice( 5572 | unsigned char _pitch /* = 64 */, 5573 | unsigned char _speed /* = 72 */, 5574 | unsigned char _mouth /* = 128 */, 5575 | unsigned char _throat /* = 128 */) { 5576 | pitch = _pitch; 5577 | speed = _speed; 5578 | mouth = _mouth; 5579 | throat = _throat; 5580 | } 5581 | 5582 | //////////////////////////////////////////////////////////////////////////////////////////// 5583 | // 5584 | // STM32SAM setPitch (pitch) 5585 | // 5586 | //////////////////////////////////////////////////////////////////////////////////////////// 5587 | 5588 | void STM32SAM::setPitch(unsigned char _pitch /* = 64 */) { 5589 | pitch = _pitch; 5590 | } 5591 | //////////////////////////////////////////////////////////////////////////////////////////// 5592 | // 5593 | // STM32SAM setSpeed (speed) 5594 | // 5595 | //////////////////////////////////////////////////////////////////////////////////////////// 5596 | 5597 | void STM32SAM::setSpeed(unsigned char _speed /* = 72 */) { 5598 | speed = _speed; 5599 | } 5600 | //////////////////////////////////////////////////////////////////////////////////////////// 5601 | // 5602 | // STM32SAM setMouth (mouth) 5603 | // 5604 | //////////////////////////////////////////////////////////////////////////////////////////// 5605 | 5606 | void STM32SAM::setMouth(unsigned char _mouth /* = 128 */) { 5607 | mouth = _mouth; 5608 | } 5609 | 5610 | //////////////////////////////////////////////////////////////////////////////////////////// 5611 | // 5612 | // STM32SAM setThroat (throat) 5613 | // 5614 | //////////////////////////////////////////////////////////////////////////////////////////// 5615 | 5616 | void STM32SAM::setThroat(unsigned char _throat /* = 128 */) { 5617 | throat = _throat; 5618 | } 5619 | //////////////////////////////////////////////////////////////////////////////////////////// 5620 | // 5621 | // Hardware 5622 | // 5623 | //////////////////////////////////////////////////////////////////////////////////////////// 5624 | // Hardware specifics, for easier porting to other microcontrollers 5625 | 5626 | // 5627 | // Set PA8 pin as PWM, at 256 timer ticks overflow (8bit resolution) 5628 | 5629 | #include 5630 | #include 5631 | 5632 | #define FURI_HAL_SPEAKER_TIMER TIM16 5633 | #define FURI_HAL_SPEAKER_CHANNEL LL_TIM_CHANNEL_CH1 5634 | 5635 | void STM32SAM::begin(void) { 5636 | #ifdef USE_ROGER_CORE 5637 | 5638 | pinMode(PA8, PWM); // audio output pin 5639 | 5640 | Timer1.setPeriod( 5641 | 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) 5642 | 5643 | #endif 5644 | 5645 | #ifdef USE_STM32duino_CORE 5646 | pinMode(PA8, OUTPUT); 5647 | 5648 | PWM->pause(); 5649 | PWM->setMode(1, TIMER_OUTPUT_COMPARE_PWM1, PA8); // TIM1 CH1 (PA8) 5650 | PWM->setPrescaleFactor(1); 5651 | PWM->setOverflow(256, TICK_FORMAT); // 256 ticks overflow, no matter the CPU (timer) speed 5652 | PWM->resume(); 5653 | 5654 | #endif 5655 | 5656 | LL_TIM_InitTypeDef TIM_InitStruct; 5657 | memset(&TIM_InitStruct, 0, sizeof(LL_TIM_InitTypeDef)); 5658 | TIM_InitStruct.Prescaler = 4; 5659 | TIM_InitStruct.Autoreload = 255; 5660 | LL_TIM_Init(FURI_HAL_SPEAKER_TIMER, &TIM_InitStruct); 5661 | 5662 | LL_TIM_OC_InitTypeDef TIM_OC_InitStruct; 5663 | memset(&TIM_OC_InitStruct, 0, sizeof(LL_TIM_OC_InitTypeDef)); 5664 | TIM_OC_InitStruct.OCMode = LL_TIM_OCMODE_PWM1; 5665 | TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_ENABLE; 5666 | TIM_OC_InitStruct.CompareValue = 127; 5667 | LL_TIM_OC_Init(FURI_HAL_SPEAKER_TIMER, FURI_HAL_SPEAKER_CHANNEL, &TIM_OC_InitStruct); 5668 | 5669 | LL_TIM_EnableAllOutputs(FURI_HAL_SPEAKER_TIMER); 5670 | LL_TIM_EnableCounter(FURI_HAL_SPEAKER_TIMER); 5671 | } // begin 5672 | 5673 | inline void STM32SAM::SetAUDIO(unsigned char main_volume) { 5674 | #ifdef USE_ROGER_CORE 5675 | Timer1.setCompare(TIMER_CH1, main_volume); 5676 | #endif 5677 | 5678 | #ifdef USE_STM32duino_CORE 5679 | PWM->setCaptureCompare(1, main_volume, TICK_COMPARE_FORMAT); 5680 | #endif 5681 | 5682 | // if(main_volume > 64) { 5683 | // LL_TIM_OC_SetCompareCH1(FURI_HAL_SPEAKER_TIMER, 127); 5684 | // } else { 5685 | // LL_TIM_OC_SetCompareCH1(FURI_HAL_SPEAKER_TIMER, main_volume); 5686 | // } 5687 | 5688 | float data = main_volume; 5689 | data /= 255.0f; 5690 | data -= 0.5f; 5691 | data *= 4.0f; 5692 | data = tanhf(data); 5693 | 5694 | data += 0.5f; 5695 | data *= 255.0f; 5696 | 5697 | if(data < 0) { 5698 | data = 0; 5699 | } else if(data > 255) { 5700 | data = 255; 5701 | } 5702 | 5703 | LL_TIM_OC_SetCompareCH1(FURI_HAL_SPEAKER_TIMER, data); 5704 | } -------------------------------------------------------------------------------- /stm32_sam.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifndef __STM32SAM__ 4 | #define __STM32SAM__ 5 | 6 | // SAM Text-To-Speech (TTS), ported from https://github.com/s-macke/SAM 7 | 8 | class STM32SAM { 9 | public: 10 | STM32SAM(uint32_t STM32SAM_SPEED); 11 | STM32SAM(); 12 | 13 | void begin(void); 14 | 15 | void 16 | sam(const char* argv, 17 | unsigned char phonetic, 18 | unsigned char singmode, 19 | unsigned char pitch, 20 | unsigned char speed, 21 | unsigned char mouth, 22 | unsigned char throat); 23 | void 24 | sam(char* argv, 25 | unsigned char phonetic, 26 | unsigned char singmode, 27 | unsigned char pitch, 28 | unsigned char speed, 29 | unsigned char mouth, 30 | unsigned char throat); 31 | 32 | void say(const char* argv); 33 | void say(char* argv); 34 | void sing(const char* argv); 35 | void sing(char* argv); 36 | void sayPhonetic(const char* argv); 37 | void sayPhonetic(char* argv); 38 | void singPhonetic(const char* argv); 39 | void singPhonetic(char* argv); 40 | void setVoice( 41 | unsigned char _pitch = 64, 42 | unsigned char _speed = 72, 43 | unsigned char _mouth = 128, 44 | unsigned char _throat = 128); 45 | void setPitch(unsigned char _pitch = 64); 46 | void setSpeed(unsigned char _speed = 72); 47 | void setMouth(unsigned char _mouth = 128); 48 | void setThroat(unsigned char _throat = 128); 49 | 50 | private: 51 | void SetAUDIO(unsigned char main_volume); 52 | 53 | void Output8BitAry(int index, unsigned char ary[5]); 54 | void Output8Bit(int index, unsigned char A); 55 | unsigned char Read(unsigned char p, unsigned char Y); 56 | void Write(unsigned char p, unsigned char Y, unsigned char value); 57 | void RenderSample(unsigned char* mem66); 58 | void Render(); 59 | void AddInflection(unsigned char mem48, unsigned char phase1); 60 | void SetMouthThroat(); 61 | unsigned char trans(unsigned char mem39212, unsigned char mem39213); 62 | void SetInput(char* _input); 63 | void Init(); 64 | int SAMMain(); 65 | void PrepareOutput(); 66 | void Insert( 67 | unsigned char position /*var57*/, 68 | unsigned char mem60, 69 | unsigned char mem59, 70 | unsigned char mem58); 71 | void InsertBreath(); 72 | void CopyStress(); 73 | int Parser1(); 74 | void SetPhonemeLength(); 75 | void Code41240(); 76 | void Parser2(); 77 | void AdjustLengths(); 78 | void Code47503(unsigned char mem52); 79 | void Code37055(unsigned char mem59); 80 | void Code37066(unsigned char mem58); 81 | unsigned char GetRuleByte(unsigned short mem62, unsigned char Y); 82 | int TextToPhonemes(unsigned char* input); // Code36484 83 | 84 | uint32_t _STM32SAM_SPEED; 85 | 86 | unsigned char speed; 87 | unsigned char pitch; 88 | unsigned char mouth; 89 | unsigned char throat; 90 | 91 | unsigned char phonetic; 92 | unsigned char singmode; 93 | 94 | }; // STM32SAM class 95 | 96 | #endif --------------------------------------------------------------------------------