Просмотр исходного кода

Remove SAM, Mandelbrot, Music Beeper, Zero Tracker

Willy-JL 1 год назад
Родитель
Сommit
6fbc11f594
37 измененных файлов с 0 добавлено и 8677 удалено
  1. 0 1
      mandelbrot/.gitsubtree
  2. BIN
      mandelbrot/Mandelbrot.png
  3. 0 16
      mandelbrot/application.fam
  4. BIN
      mandelbrot/img/1.png
  5. BIN
      mandelbrot/img/2.png
  6. 0 172
      mandelbrot/mandelbrot.c
  7. 0 1
      music_beeper/.gitsubtree
  8. 0 18
      music_beeper/application.fam
  9. 0 6
      music_beeper/files/Marble_Machine.fmf
  10. BIN
      music_beeper/music_10px.png
  11. 0 384
      music_beeper/music_beeper.c
  12. 0 48
      music_beeper/music_beeper_cli.c
  13. 0 510
      music_beeper/music_beeper_worker.c
  14. 0 46
      music_beeper/music_beeper_worker.h
  15. 0 27
      music_tracker/.github/workflows/build_dev.yml
  16. 0 2
      music_tracker/.gitsubtree
  17. 0 4
      music_tracker/README.md
  18. 0 17
      music_tracker/application.fam
  19. 0 0
      music_tracker/icons/.gitignore
  20. BIN
      music_tracker/img/1.png
  21. BIN
      music_tracker/img/2.png
  22. 0 109
      music_tracker/tracker_engine/speaker_hal.c
  23. 0 19
      music_tracker/tracker_engine/speaker_hal.h
  24. 0 441
      music_tracker/tracker_engine/tracker.c
  25. 0 38
      music_tracker/tracker_engine/tracker.h
  26. 0 64
      music_tracker/tracker_engine/tracker_notes.h
  27. 0 109
      music_tracker/tracker_engine/tracker_song.h
  28. 0 182
      music_tracker/view/tracker_view.c
  29. 0 29
      music_tracker/view/tracker_view.h
  30. 0 536
      music_tracker/zero_tracker.c
  31. 0 0
      music_tracker/zero_tracker.h
  32. BIN
      music_tracker/zero_tracker.png
  33. 0 52
      sam/application.fam
  34. BIN
      sam/music_10px.png
  35. 0 46
      sam/sam_app.cpp
  36. 0 5704
      sam/stm32_sam.cpp
  37. 0 96
      sam/stm32_sam.h

+ 0 - 1
mandelbrot/.gitsubtree

@@ -1 +0,0 @@
-https://github.com/xMasterX/all-the-plugins dev apps_source_code/mandelbrot

BIN
mandelbrot/Mandelbrot.png


+ 0 - 16
mandelbrot/application.fam

@@ -1,16 +0,0 @@
-App(
-    appid="mandelbrotset",
-    name="Mandelbrot Set",
-    apptype=FlipperAppType.EXTERNAL,
-    entry_point="mandelbrot_app",
-    cdefines=["APP_MANDELBROT_GAME"],
-    requires=["gui"],
-    stack_size=1 * 1024,
-    order=130,
-    fap_icon="Mandelbrot.png",
-    fap_category="Media",
-    fap_author="@Possibly-Matt",
-    fap_weburl="https://github.com/Possibly-Matt",
-    fap_version="1.1",
-    fap_description="The Mandelbrot set is the set of all so-called (complex) numbers that meet Mandelbrots simple arithmetic criterion.",
-)

BIN
mandelbrot/img/1.png


BIN
mandelbrot/img/2.png


+ 0 - 172
mandelbrot/mandelbrot.c

@@ -1,172 +0,0 @@
-#include <furi.h>
-#include <math.h>
-#include <gui/gui.h>
-#include <input/input.h>
-#include <stdlib.h>
-
-typedef enum {
-    EventTypeTick,
-    EventTypeKey,
-} EventType;
-
-typedef struct {
-    EventType type;
-    InputEvent input;
-} PluginEvent;
-
-typedef struct {
-    FuriMutex* mutex;
-    float xZoom;
-    float yZoom;
-    float xOffset;
-    float yOffset;
-    float zoom;
-} PluginState;
-
-bool mandelbrot_pixel(int x, int y, float xZoom, float yZoom, float xOffset, float yOffset) {
-    float ratio = 128.0 / 64.0;
-    //x0 := scaled x coordinate of pixel (scaled to lie in the Mandelbrot X scale (-2.00, 0.47))
-    float x0 = (((x / 128.0) * ratio * xZoom)) - xOffset;
-    //y0 := scaled y coordinate of pixel (scaled to lie in the Mandelbrot Y scale (-1.12, 1.12))
-    float y0 = ((y / 64.0) * yZoom) - yOffset;
-    float x1 = 0.0;
-    float y1 = 0.0;
-    float x2 = 0.0;
-    float y2 = 0.0;
-
-    int iteration = 0;
-    int max_iteration = 50;
-
-    while(x2 + y2 <= 4.0 && iteration < max_iteration) {
-        y1 = 2.0 * x1 * y1 + y0;
-        x1 = x2 - y2 + x0;
-        x2 = x1 * x1;
-        y2 = y1 * y1;
-        iteration++;
-    }
-
-    if(iteration > 49) {
-        return true;
-    }
-
-    return false;
-}
-
-static void render_callback(Canvas* const canvas, void* ctx) {
-    furi_assert(ctx);
-    const PluginState* plugin_state = ctx;
-    furi_mutex_acquire(plugin_state->mutex, FuriWaitForever);
-    // border around the edge of the screen
-    canvas_draw_frame(canvas, 0, 0, 128, 64);
-
-    for(int y = 0; y < 64; y++) {
-        for(int x = 0; x < 128; x++) {
-            // did you know if you just pass the indivdiual bits of plugin_state instead of plugin_state
-            // you dont get any compiler warnings :)
-            if(mandelbrot_pixel(
-                   x,
-                   y,
-                   plugin_state->xZoom,
-                   plugin_state->yZoom,
-                   plugin_state->xOffset,
-                   plugin_state->yOffset)) {
-                canvas_draw_dot(canvas, x, y);
-            }
-        }
-    }
-
-    furi_mutex_release(plugin_state->mutex);
-}
-
-static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) {
-    furi_assert(event_queue);
-
-    PluginEvent event = {.type = EventTypeKey, .input = *input_event};
-    furi_message_queue_put(event_queue, &event, FuriWaitForever);
-}
-
-static void mandelbrot_state_init(PluginState* const plugin_state) {
-    plugin_state->xOffset = 3.0;
-    plugin_state->yOffset = 1.12;
-    plugin_state->xZoom = 2.47;
-    plugin_state->yZoom = 2.24;
-    plugin_state->zoom = 1; // this controls the camera when
-}
-
-int32_t mandelbrot_app(void* p) {
-    UNUSED(p);
-
-    FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(PluginEvent));
-
-    PluginState* plugin_state = malloc(sizeof(PluginState));
-    mandelbrot_state_init(plugin_state);
-    plugin_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
-    if(!plugin_state->mutex) {
-        FURI_LOG_E("mandelbrot", "cannot create mutex\r\n");
-        furi_message_queue_free(event_queue);
-        free(plugin_state);
-        return 255;
-    }
-
-    // Set system callbacks
-    ViewPort* view_port = view_port_alloc();
-    view_port_draw_callback_set(view_port, render_callback, plugin_state);
-    view_port_input_callback_set(view_port, input_callback, event_queue);
-
-    // Open GUI and register view_port
-    Gui* gui = furi_record_open(RECORD_GUI);
-    gui_add_view_port(gui, view_port, GuiLayerFullscreen);
-
-    PluginEvent event;
-    for(bool processing = true; processing;) {
-        FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100);
-        furi_mutex_acquire(plugin_state->mutex, FuriWaitForever);
-
-        if(event_status == FuriStatusOk) {
-            // press events
-            if(event.type == EventTypeKey) {
-                if(event.input.type == InputTypePress) {
-                    switch(event.input.key) {
-                    case InputKeyUp:
-                        plugin_state->yOffset += 0.1 / plugin_state->zoom;
-                        break;
-                    case InputKeyDown:
-                        plugin_state->yOffset += -0.1 / plugin_state->zoom;
-                        break;
-                    case InputKeyRight:
-                        plugin_state->xOffset += -0.1 / plugin_state->zoom;
-                        break;
-                    case InputKeyLeft:
-                        plugin_state->xOffset += 0.1 / plugin_state->zoom;
-                        break;
-                    case InputKeyOk:
-                        plugin_state->xZoom -= (2.47 / 10) / plugin_state->zoom;
-                        plugin_state->yZoom -= (2.24 / 10) / plugin_state->zoom;
-                        // used to make camera control finer the more zoomed you are
-                        // this needs to be some sort of curve
-                        plugin_state->zoom += 0.15;
-                        break;
-                    case InputKeyBack:
-                        processing = false;
-                        break;
-                    default:
-                        break;
-                    }
-                }
-            }
-        }
-
-        furi_mutex_release(plugin_state->mutex);
-        view_port_update(view_port);
-    }
-
-    view_port_enabled_set(view_port, false);
-    gui_remove_view_port(gui, view_port);
-    furi_record_close(RECORD_GUI);
-    view_port_free(view_port);
-    furi_message_queue_free(event_queue);
-    furi_mutex_free(plugin_state->mutex);
-    free(plugin_state);
-
-    return 0;
-}

+ 0 - 1
music_beeper/.gitsubtree

@@ -1 +0,0 @@
-https://github.com/xMasterX/all-the-plugins dev non_catalog_apps/music_beeper

+ 0 - 18
music_beeper/application.fam

@@ -1,18 +0,0 @@
-App(
-    appid="music_beeper",
-    name="Music Beeper",
-    apptype=FlipperAppType.EXTERNAL,
-    entry_point="music_beeper_app",
-    requires=[
-        "gui",
-        "dialogs",
-    ],
-    stack_size=2 * 1024,
-    targets=["f7"],
-    fap_version="1.1",
-    fap_icon="music_10px.png",
-    fap_category="Media",
-    fap_description="An app to play RTTL music files",
-    fap_icon_assets="icons",
-    fap_file_assets="files",
-)

+ 0 - 6
music_beeper/files/Marble_Machine.fmf

@@ -1,6 +0,0 @@
-Filetype: Flipper Music Format
-Version: 0
-BPM: 130
-Duration: 8
-Octave: 5
-Notes: E6, P, E, B, 4P, E, A, G, A, E, B, P, G, A, D6, 4P, D, B, 4P, D, A, G, A, D, F#, P, G, A, D6, 4P, F#, B, 4P, F#, D6, C6, B, F#, A, P, G, F#, E, P, C, E, B, B4, C, D, D6, C6, B, F#, A, P, G, A, E6, 4P, E, B, 4P, E, A, G, A, E, B, P, G, A, D6, 4P, D, B, 4P, D, A, G, A, D, F#, P, G, A, D6, 4P, F#, B, 4P, F#, D6, C6, B, F#, A, P, G, F#, E, P, C, E, B, B4, C, D, D6, C6, B, F#, A, P, G, A, E6

BIN
music_beeper/music_10px.png


+ 0 - 384
music_beeper/music_beeper.c

@@ -1,384 +0,0 @@
-#include "music_beeper_worker.h"
-
-#include <furi.h>
-#include <furi_hal.h>
-
-#include <music_beeper_icons.h>
-#include <gui/gui.h>
-#include <dialogs/dialogs.h>
-#include <storage/storage.h>
-
-#include <assets_icons.h>
-
-#define TAG "MusicBeeper"
-
-#define MUSIC_BEEPER_APP_PATH EXT_PATH("apps_data/music_player")
-#define MUSIC_BEEPER_APP_EXTENSION "*"
-#define MUSIC_BEEPER_EXAMPLE_FILE "Marble_Machine.fmf"
-
-#define MUSIC_BEEPER_SEMITONE_HISTORY_SIZE 4
-
-typedef struct {
-    uint8_t semitone_history[MUSIC_BEEPER_SEMITONE_HISTORY_SIZE];
-    uint8_t duration_history[MUSIC_BEEPER_SEMITONE_HISTORY_SIZE];
-
-    uint8_t volume;
-    uint8_t semitone;
-    uint8_t dots;
-    uint8_t duration;
-    float position;
-} MusicBeeperModel;
-
-typedef struct {
-    MusicBeeperModel* model;
-    FuriMutex** model_mutex;
-
-    FuriMessageQueue* input_queue;
-
-    ViewPort* view_port;
-    Gui* gui;
-
-    MusicBeeperWorker* worker;
-} MusicBeeper;
-
-static const float MUSIC_BEEPER_VOLUMES[] = {0, .25, .5, .75, 1};
-
-static const char* semitone_to_note(int8_t semitone) {
-    switch(semitone) {
-    case 0:
-        return "C";
-    case 1:
-        return "C#";
-    case 2:
-        return "D";
-    case 3:
-        return "D#";
-    case 4:
-        return "E";
-    case 5:
-        return "F";
-    case 6:
-        return "F#";
-    case 7:
-        return "G";
-    case 8:
-        return "G#";
-    case 9:
-        return "A";
-    case 10:
-        return "A#";
-    case 11:
-        return "B";
-    default:
-        return "--";
-    }
-}
-
-static bool is_white_note(uint8_t semitone, uint8_t id) {
-    switch(semitone) {
-    case 0:
-        if(id == 0) return true;
-        break;
-    case 2:
-        if(id == 1) return true;
-        break;
-    case 4:
-        if(id == 2) return true;
-        break;
-    case 5:
-        if(id == 3) return true;
-        break;
-    case 7:
-        if(id == 4) return true;
-        break;
-    case 9:
-        if(id == 5) return true;
-        break;
-    case 11:
-        if(id == 6) return true;
-        break;
-    default:
-        break;
-    }
-
-    return false;
-}
-
-static bool is_black_note(uint8_t semitone, uint8_t id) {
-    switch(semitone) {
-    case 1:
-        if(id == 0) return true;
-        break;
-    case 3:
-        if(id == 1) return true;
-        break;
-    case 6:
-        if(id == 3) return true;
-        break;
-    case 8:
-        if(id == 4) return true;
-        break;
-    case 10:
-        if(id == 5) return true;
-        break;
-    default:
-        break;
-    }
-
-    return false;
-}
-
-static void render_callback(Canvas* canvas, void* ctx) {
-    MusicBeeper* music_beeper = ctx;
-    furi_check(furi_mutex_acquire(music_beeper->model_mutex, FuriWaitForever) == FuriStatusOk);
-
-    canvas_clear(canvas);
-    canvas_set_color(canvas, ColorBlack);
-    canvas_set_font(canvas, FontPrimary);
-    canvas_draw_str(canvas, 0, 12, "MusicBeeper");
-
-    uint8_t x_pos = 0;
-    uint8_t y_pos = 24;
-    const uint8_t white_w = 10;
-    const uint8_t white_h = 40;
-
-    const int8_t black_x = 6;
-    const int8_t black_y = -5;
-    const uint8_t black_w = 8;
-    const uint8_t black_h = 32;
-
-    // white keys
-    for(size_t i = 0; i < 7; i++) {
-        if(is_white_note(music_beeper->model->semitone, i)) {
-            canvas_draw_box(canvas, x_pos + white_w * i, y_pos, white_w + 1, white_h);
-        } else {
-            canvas_draw_frame(canvas, x_pos + white_w * i, y_pos, white_w + 1, white_h);
-        }
-    }
-
-    // black keys
-    for(size_t i = 0; i < 7; i++) {
-        if(i != 2 && i != 6) {
-            canvas_set_color(canvas, ColorWhite);
-            canvas_draw_box(
-                canvas, x_pos + white_w * i + black_x, y_pos + black_y, black_w + 1, black_h);
-            canvas_set_color(canvas, ColorBlack);
-            if(is_black_note(music_beeper->model->semitone, i)) {
-                canvas_draw_box(
-                    canvas, x_pos + white_w * i + black_x, y_pos + black_y, black_w + 1, black_h);
-            } else {
-                canvas_draw_frame(
-                    canvas, x_pos + white_w * i + black_x, y_pos + black_y, black_w + 1, black_h);
-            }
-        }
-    }
-
-    // volume view_port
-    x_pos = 124;
-    y_pos = 0;
-    const uint8_t volume_h =
-        (64 / (COUNT_OF(MUSIC_BEEPER_VOLUMES) - 1)) * music_beeper->model->volume;
-    canvas_draw_frame(canvas, x_pos, y_pos, 4, 64);
-    canvas_draw_box(canvas, x_pos, y_pos + (64 - volume_h), 4, volume_h);
-
-    // note stack view_port
-    x_pos = 73;
-    y_pos = 0; //-V1048
-    canvas_set_color(canvas, ColorBlack);
-    canvas_set_font(canvas, FontPrimary);
-    canvas_draw_frame(canvas, x_pos, y_pos, 49, 64);
-    canvas_draw_line(canvas, x_pos + 28, 0, x_pos + 28, 64);
-
-    char duration_text[16];
-    for(uint8_t i = 0; i < MUSIC_BEEPER_SEMITONE_HISTORY_SIZE; i++) {
-        if(music_beeper->model->duration_history[i] == 0xFF) {
-            snprintf(duration_text, 15, "--");
-        } else {
-            snprintf(duration_text, 15, "%d", music_beeper->model->duration_history[i]);
-        }
-
-        if(i == 0) {
-            canvas_draw_box(canvas, x_pos, y_pos + 48, 49, 16);
-            canvas_set_color(canvas, ColorWhite);
-        } else {
-            canvas_set_color(canvas, ColorBlack);
-        }
-        canvas_draw_str(
-            canvas,
-            x_pos + 4,
-            64 - 16 * i - 3,
-            semitone_to_note(music_beeper->model->semitone_history[i]));
-        canvas_draw_str(canvas, x_pos + 31, 64 - 16 * i - 3, duration_text);
-        canvas_draw_line(canvas, x_pos, 64 - 16 * i, x_pos + 48, 64 - 16 * i);
-    }
-
-    furi_mutex_release(music_beeper->model_mutex);
-}
-
-static void input_callback(InputEvent* input_event, void* ctx) {
-    MusicBeeper* music_beeper = ctx;
-    if(input_event->type == InputTypeShort) {
-        furi_message_queue_put(music_beeper->input_queue, input_event, 0);
-    }
-}
-
-static void music_beeper_worker_callback(
-    uint8_t semitone,
-    uint8_t dots,
-    uint8_t duration,
-    float position,
-    void* context) {
-    MusicBeeper* music_beeper = context;
-    furi_check(furi_mutex_acquire(music_beeper->model_mutex, FuriWaitForever) == FuriStatusOk);
-
-    for(size_t i = 0; i < MUSIC_BEEPER_SEMITONE_HISTORY_SIZE - 1; i++) {
-        size_t r = MUSIC_BEEPER_SEMITONE_HISTORY_SIZE - 1 - i;
-        music_beeper->model->duration_history[r] = music_beeper->model->duration_history[r - 1];
-        music_beeper->model->semitone_history[r] = music_beeper->model->semitone_history[r - 1];
-    }
-
-    semitone = (semitone == 0xFF) ? 0xFF : semitone % 12;
-
-    music_beeper->model->semitone = semitone;
-    music_beeper->model->dots = dots;
-    music_beeper->model->duration = duration;
-    music_beeper->model->position = position;
-
-    music_beeper->model->semitone_history[0] = semitone;
-    music_beeper->model->duration_history[0] = duration;
-
-    furi_mutex_release(music_beeper->model_mutex);
-    view_port_update(music_beeper->view_port);
-}
-
-void music_beeper_clear(MusicBeeper* instance) {
-    memset(instance->model->duration_history, 0xff, MUSIC_BEEPER_SEMITONE_HISTORY_SIZE);
-    memset(instance->model->semitone_history, 0xff, MUSIC_BEEPER_SEMITONE_HISTORY_SIZE);
-    music_beeper_worker_clear(instance->worker);
-}
-
-MusicBeeper* music_beeper_alloc() {
-    MusicBeeper* instance = malloc(sizeof(MusicBeeper));
-
-    instance->model = malloc(sizeof(MusicBeeperModel));
-    instance->model->volume = 3;
-
-    instance->model_mutex = furi_mutex_alloc(FuriMutexTypeNormal);
-
-    instance->input_queue = furi_message_queue_alloc(8, sizeof(InputEvent));
-
-    instance->worker = music_beeper_worker_alloc();
-    music_beeper_worker_set_volume(
-        instance->worker, MUSIC_BEEPER_VOLUMES[instance->model->volume]);
-    music_beeper_worker_set_callback(instance->worker, music_beeper_worker_callback, instance);
-
-    music_beeper_clear(instance);
-
-    instance->view_port = view_port_alloc();
-    view_port_draw_callback_set(instance->view_port, render_callback, instance);
-    view_port_input_callback_set(instance->view_port, input_callback, instance);
-
-    // Open GUI and register view_port
-    instance->gui = furi_record_open(RECORD_GUI);
-    gui_add_view_port(instance->gui, instance->view_port, GuiLayerFullscreen);
-
-    return instance;
-}
-
-void music_beeper_free(MusicBeeper* instance) {
-    gui_remove_view_port(instance->gui, instance->view_port);
-    furi_record_close(RECORD_GUI);
-    view_port_free(instance->view_port);
-
-    music_beeper_worker_free(instance->worker);
-
-    furi_message_queue_free(instance->input_queue);
-
-    furi_mutex_free(instance->model_mutex);
-
-    free(instance->model);
-    free(instance);
-}
-
-int32_t music_beeper_app(void* p) {
-    MusicBeeper* music_beeper = music_beeper_alloc();
-
-    FuriString* file_path;
-    file_path = furi_string_alloc();
-
-    do {
-        if(p && strlen(p)) {
-            furi_string_set(file_path, (const char*)p);
-        } else {
-            Storage* storage = furi_record_open(RECORD_STORAGE);
-            storage_common_migrate(storage, EXT_PATH("music_player"), MUSIC_BEEPER_APP_PATH);
-
-            if(!storage_common_exists(
-                   storage, MUSIC_BEEPER_APP_PATH "/" MUSIC_BEEPER_EXAMPLE_FILE)) {
-                storage_common_copy(
-                    storage,
-                    APP_ASSETS_PATH(MUSIC_BEEPER_EXAMPLE_FILE),
-                    MUSIC_BEEPER_APP_PATH "/" MUSIC_BEEPER_EXAMPLE_FILE);
-            }
-            furi_record_close(RECORD_STORAGE);
-
-            furi_string_set(file_path, MUSIC_BEEPER_APP_PATH);
-
-            DialogsFileBrowserOptions browser_options;
-            dialog_file_browser_set_basic_options(
-                &browser_options, MUSIC_BEEPER_APP_EXTENSION, &I_music_10px);
-            browser_options.hide_ext = false;
-            browser_options.base_path = MUSIC_BEEPER_APP_PATH;
-
-            DialogsApp* dialogs = furi_record_open(RECORD_DIALOGS);
-            bool res = dialog_file_browser_show(dialogs, file_path, file_path, &browser_options);
-
-            furi_record_close(RECORD_DIALOGS);
-
-            if(!res) {
-                FURI_LOG_E(TAG, "No file selected");
-                break;
-            }
-        }
-
-        if(!music_beeper_worker_load(music_beeper->worker, furi_string_get_cstr(file_path))) {
-            FURI_LOG_E(TAG, "Unable to load file");
-            break;
-        }
-
-        music_beeper_worker_start(music_beeper->worker);
-
-        InputEvent input;
-        while(furi_message_queue_get(music_beeper->input_queue, &input, FuriWaitForever) ==
-              FuriStatusOk) {
-            furi_check(
-                furi_mutex_acquire(music_beeper->model_mutex, FuriWaitForever) == FuriStatusOk);
-
-            if(input.key == InputKeyBack) {
-                furi_mutex_release(music_beeper->model_mutex);
-                break;
-            } else if(input.key == InputKeyUp) {
-                if(music_beeper->model->volume < COUNT_OF(MUSIC_BEEPER_VOLUMES) - 1)
-                    music_beeper->model->volume++;
-                music_beeper_worker_set_volume(
-                    music_beeper->worker, MUSIC_BEEPER_VOLUMES[music_beeper->model->volume]);
-            } else if(input.key == InputKeyDown) {
-                if(music_beeper->model->volume > 0) music_beeper->model->volume--;
-                music_beeper_worker_set_volume(
-                    music_beeper->worker, MUSIC_BEEPER_VOLUMES[music_beeper->model->volume]);
-            }
-
-            furi_mutex_release(music_beeper->model_mutex);
-            view_port_update(music_beeper->view_port);
-        }
-
-        music_beeper_worker_stop(music_beeper->worker);
-        if(p && strlen(p)) break; // Exit instead of going to browser if launched with arg
-        music_beeper_clear(music_beeper);
-    } while(1);
-
-    furi_string_free(file_path);
-    music_beeper_free(music_beeper);
-
-    return 0;
-}

+ 0 - 48
music_beeper/music_beeper_cli.c

@@ -1,48 +0,0 @@
-#include <furi.h>
-#include <cli/cli.h>
-#include <storage/storage.h>
-#include "music_beeper_worker.h"
-
-static void music_beeper_cli(Cli* cli, FuriString* args, void* context) {
-    UNUSED(context);
-    MusicBeeperWorker* music_beeper_worker = music_beeper_worker_alloc();
-    Storage* storage = furi_record_open(RECORD_STORAGE);
-
-    do {
-        if(storage_common_stat(storage, furi_string_get_cstr(args), NULL) == FSE_OK) {
-            if(!music_beeper_worker_load(music_beeper_worker, furi_string_get_cstr(args))) {
-                printf("Failed to open file %s\r\n", furi_string_get_cstr(args));
-                break;
-            }
-        } else {
-            if(!music_beeper_worker_load_rtttl_from_string(
-                   music_beeper_worker, furi_string_get_cstr(args))) {
-                printf("Argument is not a file or RTTTL\r\n");
-                break;
-            }
-        }
-
-        printf("Press CTRL+C to stop\r\n");
-        music_beeper_worker_set_volume(music_beeper_worker, 1.0f);
-        music_beeper_worker_start(music_beeper_worker);
-        while(!cli_cmd_interrupt_received(cli)) {
-            furi_delay_ms(50);
-        }
-        music_beeper_worker_stop(music_beeper_worker);
-    } while(0);
-
-    furi_record_close(RECORD_STORAGE);
-    music_beeper_worker_free(music_beeper_worker);
-}
-
-void music_beeper_on_system_start() {
-#ifdef SRV_CLI
-    Cli* cli = furi_record_open(RECORD_CLI);
-
-    cli_add_command(cli, "music_beeper", CliCommandFlagDefault, music_beeper_cli, NULL);
-
-    furi_record_close(RECORD_CLI);
-#else
-    UNUSED(music_beeper_cli);
-#endif
-}

+ 0 - 510
music_beeper/music_beeper_worker.c

@@ -1,510 +0,0 @@
-#include "music_beeper_worker.h"
-
-#include <furi_hal.h>
-#include <furi.h>
-
-#include <storage/storage.h>
-#include <lib/flipper_format/flipper_format.h>
-
-#include <m-array.h>
-
-#define TAG "MusicBeeperWorker"
-
-#define MUSIC_BEEPER_FILETYPE "Flipper Music Format"
-#define MUSIC_BEEPER_VERSION 0
-
-#define SEMITONE_PAUSE 0xFF
-
-#define NOTE_C4 261.63f
-#define NOTE_C4_SEMITONE (4.0f * 12.0f)
-#define TWO_POW_TWELTH_ROOT 1.059463094359f
-
-typedef struct {
-    uint8_t semitone;
-    uint8_t duration;
-    uint8_t dots;
-} NoteBlock;
-
-ARRAY_DEF(NoteBlockArray, NoteBlock, M_POD_OPLIST);
-
-struct MusicBeeperWorker {
-    FuriThread* thread;
-    bool should_work;
-
-    MusicBeeperWorkerCallback callback;
-    void* callback_context;
-
-    float volume;
-    uint32_t bpm;
-    uint32_t duration;
-    uint32_t octave;
-    NoteBlockArray_t notes;
-};
-
-static int32_t music_beeper_worker_thread_callback(void* context) {
-    furi_assert(context);
-    MusicBeeperWorker* instance = context;
-
-    NoteBlockArray_it_t it;
-    NoteBlockArray_it(it, instance->notes);
-    if(furi_hal_speaker_acquire(1000)) {
-        while(instance->should_work) {
-            if(NoteBlockArray_end_p(it)) {
-                NoteBlockArray_it(it, instance->notes);
-                furi_delay_ms(10);
-            } else {
-                NoteBlock* note_block = NoteBlockArray_ref(it);
-
-                float note_from_a4 = (float)note_block->semitone - NOTE_C4_SEMITONE;
-                float frequency = NOTE_C4 * powf(TWO_POW_TWELTH_ROOT, note_from_a4);
-                float duration = 60.0 * furi_kernel_get_tick_frequency() * 4 / instance->bpm /
-                                 note_block->duration;
-                uint32_t dots = note_block->dots;
-                while(dots > 0) {
-                    duration += duration / 2;
-                    dots--;
-                }
-                uint32_t next_tick = furi_get_tick() + duration;
-                float volume = instance->volume;
-
-                if(instance->callback) {
-                    instance->callback(
-                        note_block->semitone,
-                        note_block->dots,
-                        note_block->duration,
-                        0.0,
-                        instance->callback_context);
-                }
-
-                furi_hal_speaker_stop();
-                furi_hal_speaker_start(frequency, volume);
-                while(instance->should_work && furi_get_tick() < next_tick) {
-                    volume *= 1;
-                    furi_hal_speaker_set_volume(volume);
-                    furi_delay_ms(2);
-                }
-                NoteBlockArray_next(it);
-            }
-        }
-
-        furi_hal_speaker_stop();
-        furi_hal_speaker_release();
-    } else {
-        FURI_LOG_E(TAG, "Speaker system is busy with another process.");
-    }
-
-    return 0;
-}
-
-MusicBeeperWorker* music_beeper_worker_alloc() {
-    MusicBeeperWorker* instance = malloc(sizeof(MusicBeeperWorker));
-
-    NoteBlockArray_init(instance->notes);
-
-    instance->thread = furi_thread_alloc();
-    furi_thread_set_name(instance->thread, "MusicBeeperWorker");
-    furi_thread_set_stack_size(instance->thread, 1024);
-    furi_thread_set_context(instance->thread, instance);
-    furi_thread_set_callback(instance->thread, music_beeper_worker_thread_callback);
-
-    instance->volume = 1.0f;
-
-    return instance;
-}
-
-void music_beeper_worker_clear(MusicBeeperWorker* instance) {
-    NoteBlockArray_reset(instance->notes);
-}
-
-void music_beeper_worker_free(MusicBeeperWorker* instance) {
-    furi_assert(instance);
-    furi_thread_free(instance->thread);
-    NoteBlockArray_clear(instance->notes);
-    free(instance);
-}
-
-static bool is_digit(const char c) {
-    return isdigit(c) != 0;
-}
-
-static bool is_letter(const char c) {
-    return islower(c) != 0 || isupper(c) != 0;
-}
-
-static bool is_space(const char c) {
-    return c == ' ' || c == '\t';
-}
-
-static size_t extract_number(const char* string, uint32_t* number) {
-    size_t ret = 0;
-    *number = 0;
-    while(is_digit(*string)) {
-        *number *= 10;
-        *number += (*string - '0');
-        string++;
-        ret++;
-    }
-    return ret;
-}
-
-static size_t extract_dots(const char* string, uint32_t* number) {
-    size_t ret = 0;
-    *number = 0;
-    while(*string == '.') {
-        *number += 1;
-        string++;
-        ret++;
-    }
-    return ret;
-}
-
-static size_t extract_char(const char* string, char* symbol) {
-    if(is_letter(*string)) {
-        *symbol = *string;
-        return 1;
-    } else {
-        return 0;
-    }
-}
-
-static size_t extract_sharp(const char* string, char* symbol) {
-    if(*string == '#' || *string == '_') {
-        *symbol = '#';
-        return 1;
-    } else {
-        return 0;
-    }
-}
-
-static size_t skip_till(const char* string, const char symbol) {
-    size_t ret = 0;
-    while(*string != '\0' && *string != symbol) {
-        string++;
-        ret++;
-    }
-    if(*string != symbol) {
-        ret = 0;
-    }
-    return ret;
-}
-
-static bool music_beeper_worker_add_note(
-    MusicBeeperWorker* instance,
-    uint8_t semitone,
-    uint8_t duration,
-    uint8_t dots) {
-    NoteBlock note_block;
-
-    note_block.semitone = semitone;
-    note_block.duration = duration;
-    note_block.dots = dots;
-
-    NoteBlockArray_push_back(instance->notes, note_block);
-
-    return true;
-}
-
-static int8_t note_to_semitone(const char note) {
-    switch(note) {
-    case 'C':
-        return 0;
-    // C#
-    case 'D':
-        return 2;
-    // D#
-    case 'E':
-        return 4;
-    case 'F':
-        return 5;
-    // F#
-    case 'G':
-        return 7;
-    // G#
-    case 'A':
-        return 9;
-    // A#
-    case 'B':
-        return 11;
-    default:
-        return 0;
-    }
-}
-
-static bool music_beeper_worker_parse_notes(MusicBeeperWorker* instance, const char* string) {
-    const char* cursor = string;
-    bool result = true;
-
-    while(*cursor != '\0') {
-        if(!is_space(*cursor)) {
-            uint32_t duration = 0;
-            char note_char = '\0';
-            char sharp_char = '\0';
-            uint32_t octave = 0;
-            uint32_t dots = 0;
-
-            // Parsing
-            cursor += extract_number(cursor, &duration);
-            cursor += extract_char(cursor, &note_char);
-            cursor += extract_sharp(cursor, &sharp_char);
-            cursor += extract_number(cursor, &octave);
-            cursor += extract_dots(cursor, &dots);
-
-            // Post processing
-            note_char = toupper(note_char);
-            if(!duration) {
-                duration = instance->duration;
-            }
-            if(!octave) {
-                octave = instance->octave;
-            }
-
-            // Validation
-            bool is_valid = true;
-            is_valid &= (duration >= 1 && duration <= 128);
-            is_valid &= ((note_char >= 'A' && note_char <= 'G') || note_char == 'P');
-            is_valid &= (sharp_char == '#' || sharp_char == '\0');
-            is_valid &= (octave <= 16);
-            is_valid &= (dots <= 16);
-            if(!is_valid) {
-                FURI_LOG_E(
-                    TAG,
-                    "Invalid note: %lu%c%c%lu.%lu",
-                    duration,
-                    note_char == '\0' ? '_' : note_char,
-                    sharp_char == '\0' ? '_' : sharp_char,
-                    octave,
-                    dots);
-                result = false;
-                break;
-            }
-
-            // Note to semitones
-            uint8_t semitone = 0;
-            if(note_char == 'P') {
-                semitone = SEMITONE_PAUSE;
-            } else {
-                semitone += octave * 12;
-                semitone += note_to_semitone(note_char);
-                semitone += sharp_char == '#' ? 1 : 0;
-            }
-
-            if(music_beeper_worker_add_note(instance, semitone, duration, dots)) {
-                FURI_LOG_D(
-                    TAG,
-                    "Added note: %c%c%lu.%lu = %u %lu",
-                    note_char == '\0' ? '_' : note_char,
-                    sharp_char == '\0' ? '_' : sharp_char,
-                    octave,
-                    dots,
-                    semitone,
-                    duration);
-            } else {
-                FURI_LOG_E(
-                    TAG,
-                    "Invalid note: %c%c%lu.%lu = %u %lu",
-                    note_char == '\0' ? '_' : note_char,
-                    sharp_char == '\0' ? '_' : sharp_char,
-                    octave,
-                    dots,
-                    semitone,
-                    duration);
-            }
-            cursor += skip_till(cursor, ',');
-        }
-
-        if(*cursor != '\0') cursor++;
-    }
-
-    return result;
-}
-
-bool music_beeper_worker_load(MusicBeeperWorker* instance, const char* file_path) {
-    furi_assert(instance);
-    furi_assert(file_path);
-
-    bool ret = false;
-    if(strcasestr(file_path, ".fmf")) {
-        ret = music_beeper_worker_load_fmf_from_file(instance, file_path);
-    } else {
-        ret = music_beeper_worker_load_rtttl_from_file(instance, file_path);
-    }
-    return ret;
-}
-
-bool music_beeper_worker_load_fmf_from_file(MusicBeeperWorker* instance, const char* file_path) {
-    furi_assert(instance);
-    furi_assert(file_path);
-
-    bool result = false;
-    FuriString* temp_str;
-    temp_str = furi_string_alloc();
-
-    Storage* storage = furi_record_open(RECORD_STORAGE);
-    FlipperFormat* file = flipper_format_file_alloc(storage);
-
-    do {
-        if(!flipper_format_file_open_existing(file, file_path)) break;
-
-        uint32_t version = 0;
-        if(!flipper_format_read_header(file, temp_str, &version)) break;
-        if(furi_string_cmp_str(temp_str, MUSIC_BEEPER_FILETYPE) ||
-           (version != MUSIC_BEEPER_VERSION)) {
-            FURI_LOG_E(TAG, "Incorrect file format or version");
-            break;
-        }
-
-        if(!flipper_format_read_uint32(file, "BPM", &instance->bpm, 1)) {
-            FURI_LOG_E(TAG, "BPM is missing");
-            break;
-        }
-        if(!flipper_format_read_uint32(file, "Duration", &instance->duration, 1)) {
-            FURI_LOG_E(TAG, "Duration is missing");
-            break;
-        }
-        if(!flipper_format_read_uint32(file, "Octave", &instance->octave, 1)) {
-            FURI_LOG_E(TAG, "Octave is missing");
-            break;
-        }
-
-        if(!flipper_format_read_string(file, "Notes", temp_str)) {
-            FURI_LOG_E(TAG, "Notes is missing");
-            break;
-        }
-
-        if(!music_beeper_worker_parse_notes(instance, furi_string_get_cstr(temp_str))) {
-            break;
-        }
-
-        result = true;
-    } while(false);
-
-    furi_record_close(RECORD_STORAGE);
-    flipper_format_free(file);
-    furi_string_free(temp_str);
-
-    return result;
-}
-
-bool music_beeper_worker_load_rtttl_from_file(MusicBeeperWorker* instance, const char* file_path) {
-    furi_assert(instance);
-    furi_assert(file_path);
-
-    bool result = false;
-    FuriString* content;
-    content = furi_string_alloc();
-    Storage* storage = furi_record_open(RECORD_STORAGE);
-    File* file = storage_file_alloc(storage);
-
-    do {
-        if(!storage_file_open(file, file_path, FSAM_READ, FSOM_OPEN_EXISTING)) {
-            FURI_LOG_E(TAG, "Unable to open file");
-            break;
-        };
-
-        uint16_t ret = 0;
-        do {
-            uint8_t buffer[65] = {0};
-            ret = storage_file_read(file, buffer, sizeof(buffer) - 1);
-            for(size_t i = 0; i < ret; i++) {
-                furi_string_push_back(content, buffer[i]);
-            }
-        } while(ret > 0);
-
-        furi_string_trim(content);
-        if(!furi_string_size(content)) {
-            FURI_LOG_E(TAG, "Empty file");
-            break;
-        }
-
-        if(!music_beeper_worker_load_rtttl_from_string(instance, furi_string_get_cstr(content))) {
-            FURI_LOG_E(TAG, "Invalid file content");
-            break;
-        }
-
-        result = true;
-    } while(0);
-
-    storage_file_free(file);
-    furi_record_close(RECORD_STORAGE);
-    furi_string_free(content);
-
-    return result;
-}
-
-bool music_beeper_worker_load_rtttl_from_string(MusicBeeperWorker* instance, const char* string) {
-    furi_assert(instance);
-
-    const char* cursor = string;
-
-    // Skip name
-    cursor += skip_till(cursor, ':');
-    if(*cursor != ':') {
-        return false;
-    }
-
-    // Duration
-    cursor += skip_till(cursor, '=');
-    if(*cursor != '=') {
-        return false;
-    }
-    cursor++;
-    cursor += extract_number(cursor, &instance->duration);
-
-    // Octave
-    cursor += skip_till(cursor, '=');
-    if(*cursor != '=') {
-        return false;
-    }
-    cursor++;
-    cursor += extract_number(cursor, &instance->octave);
-
-    // BPM
-    cursor += skip_till(cursor, '=');
-    if(*cursor != '=') {
-        return false;
-    }
-    cursor++;
-    cursor += extract_number(cursor, &instance->bpm);
-
-    // Notes
-    cursor += skip_till(cursor, ':');
-    if(*cursor != ':') {
-        return false;
-    }
-    cursor++;
-    if(!music_beeper_worker_parse_notes(instance, cursor)) {
-        return false;
-    }
-
-    return true;
-}
-
-void music_beeper_worker_set_callback(
-    MusicBeeperWorker* instance,
-    MusicBeeperWorkerCallback callback,
-    void* context) {
-    furi_assert(instance);
-    instance->callback = callback;
-    instance->callback_context = context;
-}
-
-void music_beeper_worker_set_volume(MusicBeeperWorker* instance, float volume) {
-    furi_assert(instance);
-    instance->volume = volume;
-}
-
-void music_beeper_worker_start(MusicBeeperWorker* instance) {
-    furi_assert(instance);
-    furi_assert(instance->should_work == false);
-
-    instance->should_work = true;
-    furi_thread_start(instance->thread);
-}
-
-void music_beeper_worker_stop(MusicBeeperWorker* instance) {
-    furi_assert(instance);
-    furi_assert(instance->should_work == true);
-
-    instance->should_work = false;
-    furi_thread_join(instance->thread);
-}

+ 0 - 46
music_beeper/music_beeper_worker.h

@@ -1,46 +0,0 @@
-#pragma once
-
-#include <stdbool.h>
-#include <stdint.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef void (*MusicBeeperWorkerCallback)(
-    uint8_t semitone,
-    uint8_t dots,
-    uint8_t duration,
-    float position,
-    void* context);
-
-typedef struct MusicBeeperWorker MusicBeeperWorker;
-
-MusicBeeperWorker* music_beeper_worker_alloc();
-
-void music_beeper_worker_clear(MusicBeeperWorker* instance);
-
-void music_beeper_worker_free(MusicBeeperWorker* instance);
-
-bool music_beeper_worker_load(MusicBeeperWorker* instance, const char* file_path);
-
-bool music_beeper_worker_load_fmf_from_file(MusicBeeperWorker* instance, const char* file_path);
-
-bool music_beeper_worker_load_rtttl_from_file(MusicBeeperWorker* instance, const char* file_path);
-
-bool music_beeper_worker_load_rtttl_from_string(MusicBeeperWorker* instance, const char* string);
-
-void music_beeper_worker_set_callback(
-    MusicBeeperWorker* instance,
-    MusicBeeperWorkerCallback callback,
-    void* context);
-
-void music_beeper_worker_set_volume(MusicBeeperWorker* instance, float volume);
-
-void music_beeper_worker_start(MusicBeeperWorker* instance);
-
-void music_beeper_worker_stop(MusicBeeperWorker* instance);
-
-#ifdef __cplusplus
-}
-#endif

+ 0 - 27
music_tracker/.github/workflows/build_dev.yml

@@ -1,27 +0,0 @@
-name: "FAP: Build and lint"
-on: [push, pull_request]
-jobs:
-  ufbt-build-action:
-    runs-on: ubuntu-latest
-    name: 'ufbt: Build for Dev branch'
-    steps:
-      - name: Checkout
-        uses: actions/checkout@v3
-      - name: Build with ufbt
-        uses: flipperdevices/flipperzero-ufbt-action@v0.1.0
-        id: build-app
-        with:
-          # Set to 'release' to build for latest published release version
-          sdk-channel: dev
-      - name: Upload app artifacts
-        uses: actions/upload-artifact@v3
-        with:
-          name: zero_tracker.fap.zip
-          path: ${{ steps.build-app.outputs.fap-artifacts }}
-      # You can remove this step if you don't want to check source code formatting
-      - name: Lint sources
-        uses: flipperdevices/flipperzero-ufbt-action@v0.1.0
-        with:
-          # skip SDK setup, we already did it in previous step
-          skip-setup: true
-          task: lint

+ 0 - 2
music_tracker/.gitsubtree

@@ -1,2 +0,0 @@
-https://github.com/DrZlo13/flipper-zero-music-tracker master /
-https://github.com/xMasterX/all-the-plugins dev apps_source_code/musictracker

+ 0 - 4
music_tracker/README.md

@@ -1,4 +0,0 @@
-# Flipper Zero music tracker
--=-=- MVP Stage: minimum viable player -=-=-
-
-[>Get latest build<](https://nightly.link/DrZlo13/flipper-zero-music-tracker/workflows/build_dev/master/zero_tracker.fap.zip)

+ 0 - 17
music_tracker/application.fam

@@ -1,17 +0,0 @@
-App(
-    appid="zero_tracker",
-    name="Zero Tracker",
-    apptype=FlipperAppType.EXTERNAL,
-    entry_point="zero_tracker_app",
-    requires=[
-        "gui",
-    ],
-    stack_size=4 * 1024,
-    order=20,
-    fap_icon="zero_tracker.png",
-    fap_category="Media",
-    fap_author="@DrZlo13",
-    fap_weburl="https://github.com/DrZlo13/flipper-zero-music-tracker",
-    fap_version="1.2",
-    fap_description="App plays hardcoded tracker song",
-)

+ 0 - 0
music_tracker/icons/.gitignore


BIN
music_tracker/img/1.png


BIN
music_tracker/img/2.png


+ 0 - 109
music_tracker/tracker_engine/speaker_hal.c

@@ -1,109 +0,0 @@
-#include "speaker_hal.h"
-
-#define FURI_HAL_SPEAKER_TIMER TIM16
-#define FURI_HAL_SPEAKER_CHANNEL LL_TIM_CHANNEL_CH1
-#define FURI_HAL_SPEAKER_PRESCALER 500
-
-void tracker_speaker_play(float frequency, float pwm) {
-    uint32_t autoreload = (SystemCoreClock / FURI_HAL_SPEAKER_PRESCALER / frequency) - 1;
-    if(autoreload < 2) {
-        autoreload = 2;
-    } else if(autoreload > UINT16_MAX) {
-        autoreload = UINT16_MAX;
-    }
-
-    if(pwm < 0) pwm = 0;
-    if(pwm > 1) pwm = 1;
-
-    uint32_t compare_value = pwm * autoreload;
-
-    if(compare_value == 0) {
-        compare_value = 1;
-    }
-
-    if(LL_TIM_OC_GetCompareCH1(FURI_HAL_SPEAKER_TIMER) != compare_value) {
-        LL_TIM_OC_SetCompareCH1(FURI_HAL_SPEAKER_TIMER, compare_value);
-    }
-
-    if(LL_TIM_GetAutoReload(FURI_HAL_SPEAKER_TIMER) != autoreload) {
-        LL_TIM_SetAutoReload(FURI_HAL_SPEAKER_TIMER, autoreload);
-        if(LL_TIM_GetCounter(FURI_HAL_SPEAKER_TIMER) > autoreload) {
-            LL_TIM_SetCounter(FURI_HAL_SPEAKER_TIMER, 0);
-        }
-    }
-
-    LL_TIM_EnableAllOutputs(FURI_HAL_SPEAKER_TIMER);
-}
-
-void tracker_speaker_stop() {
-    LL_TIM_DisableAllOutputs(FURI_HAL_SPEAKER_TIMER);
-}
-
-void tracker_speaker_init() {
-    if(furi_hal_speaker_is_mine() || furi_hal_speaker_acquire(1000)) {
-        furi_hal_speaker_start(200.0f, 0.01f);
-        tracker_speaker_stop();
-    }
-}
-
-void tracker_speaker_deinit() {
-    if(furi_hal_speaker_is_mine()) {
-        furi_hal_speaker_stop();
-        furi_hal_speaker_release();
-    }
-}
-
-static FuriHalInterruptISR tracker_isr;
-static void* tracker_isr_context;
-static void tracker_interrupt_cb(void* context) {
-    UNUSED(context);
-
-    if(LL_TIM_IsActiveFlag_UPDATE(TIM2)) {
-        LL_TIM_ClearFlag_UPDATE(TIM2);
-
-        if(tracker_isr) {
-            tracker_isr(tracker_isr_context);
-        }
-    }
-}
-
-void tracker_interrupt_init(float freq, FuriHalInterruptISR isr, void* context) {
-    tracker_isr = isr;
-    tracker_isr_context = context;
-
-    furi_hal_bus_enable(FuriHalBusTIM2);
-
-    furi_hal_interrupt_set_isr(FuriHalInterruptIdTIM2, tracker_interrupt_cb, NULL);
-
-    LL_TIM_InitTypeDef TIM_InitStruct = {0};
-    // Prescaler to get 1kHz clock
-    TIM_InitStruct.Prescaler = SystemCoreClock / 1000000 - 1;
-    TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
-    // Auto reload to get freq Hz interrupt
-    TIM_InitStruct.Autoreload = (1000000 / freq) - 1;
-    TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
-    LL_TIM_Init(TIM2, &TIM_InitStruct);
-    LL_TIM_EnableIT_UPDATE(TIM2);
-    LL_TIM_EnableAllOutputs(TIM2);
-    LL_TIM_EnableCounter(TIM2);
-}
-
-void tracker_interrupt_deinit() {
-    FURI_CRITICAL_ENTER();
-    furi_hal_bus_disable(FuriHalBusTIM2);
-    FURI_CRITICAL_EXIT();
-
-    furi_hal_interrupt_set_isr(FuriHalInterruptIdTIM2, NULL, NULL);
-}
-
-void tracker_debug_init() {
-    furi_hal_gpio_init(&gpio_ext_pc3, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
-}
-
-void tracker_debug_set(bool value) {
-    furi_hal_gpio_write(&gpio_ext_pc3, value);
-}
-
-void tracker_debug_deinit() {
-    furi_hal_gpio_init(&gpio_ext_pc3, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
-}

+ 0 - 19
music_tracker/tracker_engine/speaker_hal.h

@@ -1,19 +0,0 @@
-#include <furi_hal.h>
-
-void tracker_speaker_init();
-
-void tracker_speaker_deinit();
-
-void tracker_speaker_play(float frequency, float pwm);
-
-void tracker_speaker_stop();
-
-void tracker_interrupt_init(float freq, FuriHalInterruptISR isr, void* context);
-
-void tracker_interrupt_deinit();
-
-void tracker_debug_init();
-
-void tracker_debug_set(bool value);
-
-void tracker_debug_deinit();

+ 0 - 441
music_tracker/tracker_engine/tracker.c

@@ -1,441 +0,0 @@
-#include "tracker.h"
-#include <stdbool.h>
-#include "speaker_hal.h"
-
-// SongState song_state = {
-//     .tick = 0,
-//     .tick_limit = 2,
-//     .row = 0,
-// };
-
-typedef struct {
-    uint8_t speed;
-    uint8_t depth;
-    int8_t direction;
-    int8_t value;
-} IntegerOscillator;
-
-typedef struct {
-    float frequency;
-    float frequency_target;
-    float pwm;
-    bool play;
-    IntegerOscillator vibrato;
-} ChannelState;
-
-typedef struct {
-    ChannelState* channels;
-    uint8_t tick;
-    uint8_t tick_limit;
-
-    uint8_t pattern_index;
-    uint8_t row_index;
-    uint8_t order_list_index;
-} SongState;
-
-typedef struct {
-    uint8_t note;
-    uint8_t effect;
-    uint8_t data;
-} UnpackedRow;
-
-struct Tracker {
-    const Song* song;
-    bool playing;
-    TrackerMessageCallback callback;
-    void* context;
-    SongState song_state;
-};
-
-static void channels_state_init(ChannelState* channel) {
-    channel->frequency = 0;
-    channel->frequency_target = FREQUENCY_UNSET;
-    channel->pwm = PWM_DEFAULT;
-    channel->play = false;
-    channel->vibrato.speed = 0;
-    channel->vibrato.depth = 0;
-    channel->vibrato.direction = 0;
-    channel->vibrato.value = 0;
-}
-
-static void tracker_song_state_init(Tracker* tracker) {
-    tracker->song_state.tick = 0;
-    tracker->song_state.tick_limit = 2;
-    tracker->song_state.row_index = 0;
-    tracker->song_state.order_list_index = 0;
-    tracker->song_state.pattern_index = tracker->song->order_list[0];
-
-    if(tracker->song_state.channels != NULL) {
-        free(tracker->song_state.channels);
-    }
-
-    tracker->song_state.channels = malloc(sizeof(ChannelState) * tracker->song->channels_count);
-    for(uint8_t i = 0; i < tracker->song->channels_count; i++) {
-        channels_state_init(&tracker->song_state.channels[i]);
-    }
-}
-
-static void tracker_song_state_clear(Tracker* tracker) {
-    if(tracker->song_state.channels != NULL) {
-        free(tracker->song_state.channels);
-        tracker->song_state.channels = NULL;
-    }
-}
-
-static uint8_t record_get_note(Row note) {
-    return note & ROW_NOTE_MASK;
-}
-
-static uint8_t record_get_effect(Row note) {
-    return (note >> 6) & ROW_EFFECT_MASK;
-}
-
-static uint8_t record_get_effect_data(Row note) {
-    return (note >> 10) & ROW_EFFECT_DATA_MASK;
-}
-
-#define NOTES_PER_OCT 12
-const float notes_oct[NOTES_PER_OCT] = {
-    130.813f,
-    138.591f,
-    146.832f,
-    155.563f,
-    164.814f,
-    174.614f,
-    184.997f,
-    195.998f,
-    207.652f,
-    220.00f,
-    233.082f,
-    246.942f,
-};
-
-static float note_to_freq(uint8_t note) {
-    if(note == NOTE_NONE) return 0.0f;
-    note = note - NOTE_C2;
-    uint8_t octave = note / NOTES_PER_OCT;
-    uint8_t note_in_oct = note % NOTES_PER_OCT;
-    return notes_oct[note_in_oct] * (1 << octave);
-}
-
-static float frequency_offset_semitones(float frequency, uint8_t semitones) {
-    return frequency * (1.0f + ((1.0f / 12.0f) * semitones));
-}
-
-static float frequency_get_seventh_of_a_semitone(float frequency) {
-    return frequency * ((1.0f / 12.0f) / 7.0f);
-}
-
-static UnpackedRow get_current_row(const Song* song, SongState* song_state, uint8_t channel) {
-    const Pattern* pattern = &song->patterns[song_state->pattern_index];
-    const Row row = pattern->channels[channel].rows[song_state->row_index];
-    return (UnpackedRow){
-        .note = record_get_note(row),
-        .effect = record_get_effect(row),
-        .data = record_get_effect_data(row),
-    };
-}
-
-static int16_t advance_order_and_get_next_pattern_index(const Song* song, SongState* song_state) {
-    song_state->order_list_index++;
-    if(song_state->order_list_index >= song->order_list_size) {
-        return -1;
-    } else {
-        return song->order_list[song_state->order_list_index];
-    }
-}
-
-typedef struct {
-    int16_t pattern;
-    int16_t row;
-    bool change_pattern;
-    bool change_row;
-} Location;
-
-static void tracker_send_position_message(Tracker* tracker) {
-    if(tracker->callback != NULL) {
-        tracker->callback(
-            (TrackerMessage){
-                .type = TrackerPositionChanged,
-                .data =
-                    {
-                        .position =
-                            {
-                                .order_list_index = tracker->song_state.order_list_index,
-                                .row = tracker->song_state.row_index,
-                            },
-                    },
-            },
-            tracker->context);
-    }
-}
-
-static void tracker_send_end_message(Tracker* tracker) {
-    if(tracker->callback != NULL) {
-        tracker->callback((TrackerMessage){.type = TrackerEndOfSong}, tracker->context);
-    }
-}
-
-static void advance_to_pattern(Tracker* tracker, Location advance) {
-    if(advance.change_pattern) {
-        if(advance.pattern < 0 || advance.pattern >= tracker->song->patterns_count) {
-            tracker->playing = false;
-            tracker_send_end_message(tracker);
-        } else {
-            tracker->song_state.pattern_index = advance.pattern;
-            tracker->song_state.row_index = 0;
-        }
-    }
-
-    if(advance.change_row) {
-        if(advance.row < 0) advance.row = 0;
-        if(advance.row >= PATTERN_SIZE) advance.row = PATTERN_SIZE - 1;
-        tracker->song_state.row_index = advance.row;
-    }
-
-    tracker_send_position_message(tracker);
-}
-
-static void tracker_interrupt_body(Tracker* tracker) {
-    if(!tracker->playing) {
-        tracker_speaker_stop();
-        return;
-    }
-
-    const uint8_t channel_index = 0;
-    SongState* song_state = &tracker->song_state;
-    ChannelState* channel_state = &song_state->channels[channel_index];
-    const Song* song = tracker->song;
-    UnpackedRow row = get_current_row(song, song_state, channel_index);
-
-    // load frequency from note at tick 0
-    if(song_state->tick == 0) {
-        bool invalidate_row = false;
-        // handle "on first tick" effects
-        if(row.effect == EffectBreakPattern) {
-            int16_t next_row_index = row.data;
-            int16_t next_pattern_index =
-                advance_order_and_get_next_pattern_index(song, song_state);
-            advance_to_pattern(
-                tracker,
-                (Location){
-                    .pattern = next_pattern_index,
-                    .row = next_row_index,
-                    .change_pattern = true,
-                    .change_row = true,
-                });
-
-            invalidate_row = true;
-        }
-
-        if(row.effect == EffectJumpToOrder) {
-            song_state->order_list_index = row.data;
-            int16_t next_pattern_index = song->order_list[song_state->order_list_index];
-
-            advance_to_pattern(
-                tracker,
-                (Location){
-                    .pattern = next_pattern_index,
-                    .change_pattern = true,
-                });
-
-            invalidate_row = true;
-        }
-
-        // tracker state can be affected by effects
-        if(!tracker->playing) {
-            tracker_speaker_stop();
-            return;
-        }
-
-        if(invalidate_row) {
-            row = get_current_row(song, song_state, channel_index);
-
-            if(row.effect == EffectSetSpeed) {
-                song_state->tick_limit = row.data;
-            }
-        }
-
-        // handle note effects
-        if(row.note == NOTE_OFF) {
-            channel_state->play = false;
-        } else if((row.note > NOTE_NONE) && (row.note < NOTE_OFF)) {
-            channel_state->play = true;
-
-            // reset vibrato
-            channel_state->vibrato.speed = 0;
-            channel_state->vibrato.depth = 0;
-            channel_state->vibrato.value = 0;
-            channel_state->vibrato.direction = 0;
-
-            // reset pwm
-            channel_state->pwm = PWM_DEFAULT;
-
-            if(row.effect == EffectSlideToNote) {
-                channel_state->frequency_target = note_to_freq(row.note);
-            } else {
-                channel_state->frequency = note_to_freq(row.note);
-                channel_state->frequency_target = FREQUENCY_UNSET;
-            }
-        }
-    }
-
-    if(channel_state->play) {
-        float frequency, pwm;
-
-        if((row.effect == EffectSlideUp || row.effect == EffectSlideDown) &&
-           row.data != EFFECT_DATA_NONE) {
-            // apply slide effect
-            channel_state->frequency += (row.effect == EffectSlideUp ? 1 : -1) * row.data;
-        } else if(row.effect == EffectSlideToNote) {
-            // apply slide to note effect, if target frequency is set
-            if(channel_state->frequency_target > 0) {
-                if(channel_state->frequency_target > channel_state->frequency) {
-                    channel_state->frequency += row.data;
-                    if(channel_state->frequency > channel_state->frequency_target) {
-                        channel_state->frequency = channel_state->frequency_target;
-                        channel_state->frequency_target = FREQUENCY_UNSET;
-                    }
-                } else if(channel_state->frequency_target < channel_state->frequency) {
-                    channel_state->frequency -= row.data;
-                    if(channel_state->frequency < channel_state->frequency_target) {
-                        channel_state->frequency = channel_state->frequency_target;
-                        channel_state->frequency_target = FREQUENCY_UNSET;
-                    }
-                }
-            }
-        }
-
-        frequency = channel_state->frequency;
-        pwm = channel_state->pwm;
-
-        // apply arpeggio effect
-        if(row.effect == EffectArpeggio) {
-            if(row.data != EFFECT_DATA_NONE) {
-                if((song_state->tick % 3) == 1) {
-                    uint8_t note_offset = EFFECT_DATA_GET_X(row.data);
-                    frequency = frequency_offset_semitones(frequency, note_offset);
-                } else if((song_state->tick % 3) == 2) {
-                    uint8_t note_offset = EFFECT_DATA_GET_Y(row.data);
-                    frequency = frequency_offset_semitones(frequency, note_offset);
-                }
-            }
-        } else if(row.effect == EffectVibrato) {
-            // apply vibrato effect, data = speed, depth
-            uint8_t vibrato_speed = EFFECT_DATA_GET_X(row.data);
-            uint8_t vibrato_depth = EFFECT_DATA_GET_Y(row.data);
-
-            // update vibrato parameters if speed or depth is non-zero
-            if(vibrato_speed != 0) channel_state->vibrato.speed = vibrato_speed;
-            if(vibrato_depth != 0) channel_state->vibrato.depth = vibrato_depth;
-
-            // update vibrato value
-            channel_state->vibrato.value +=
-                channel_state->vibrato.direction * channel_state->vibrato.speed;
-
-            // change direction if value is at the limit
-            if(channel_state->vibrato.value > channel_state->vibrato.depth) {
-                channel_state->vibrato.direction = -1;
-            } else if(channel_state->vibrato.value < -channel_state->vibrato.depth) {
-                channel_state->vibrato.direction = 1;
-            } else if(channel_state->vibrato.direction == 0) {
-                // set initial direction, if it is not set
-                channel_state->vibrato.direction = 1;
-            }
-
-            frequency +=
-                (frequency_get_seventh_of_a_semitone(frequency) * channel_state->vibrato.value);
-        } else if(row.effect == EffectPWM) {
-            pwm = (pwm - PWM_MIN) / EFFECT_DATA_1_MAX * row.data + PWM_MIN;
-        }
-
-        tracker_speaker_play(frequency, pwm);
-    } else {
-        tracker_speaker_stop();
-    }
-
-    song_state->tick++;
-    if(song_state->tick >= song_state->tick_limit) {
-        song_state->tick = 0;
-
-        // next note
-        song_state->row_index = (song_state->row_index + 1);
-
-        if(song_state->row_index >= PATTERN_SIZE) {
-            int16_t next_pattern_index =
-                advance_order_and_get_next_pattern_index(song, song_state);
-            advance_to_pattern(
-                tracker,
-                (Location){
-                    .pattern = next_pattern_index,
-                    .change_pattern = true,
-                });
-        } else {
-            tracker_send_position_message(tracker);
-        }
-    }
-}
-
-static void tracker_interrupt_cb(void* context) {
-    Tracker* tracker = (Tracker*)context;
-    tracker_debug_set(true);
-    tracker_interrupt_body(tracker);
-    tracker_debug_set(false);
-}
-
-/*********************************************************************
- * Tracker Interface
- *********************************************************************/
-
-Tracker* tracker_alloc() {
-    Tracker* tracker = malloc(sizeof(Tracker));
-    return tracker;
-}
-
-void tracker_free(Tracker* tracker) {
-    tracker_song_state_clear(tracker);
-    free(tracker);
-}
-
-void tracker_set_message_callback(Tracker* tracker, TrackerMessageCallback callback, void* context) {
-    furi_check(tracker->playing == false);
-    tracker->callback = callback;
-    tracker->context = context;
-}
-
-void tracker_set_song(Tracker* tracker, const Song* song) {
-    furi_check(tracker->playing == false);
-    tracker->song = song;
-    tracker_song_state_init(tracker);
-}
-
-void tracker_set_order_index(Tracker* tracker, uint8_t order_index) {
-    furi_check(tracker->playing == false);
-    furi_check(order_index < tracker->song->order_list_size);
-    tracker->song_state.order_list_index = order_index;
-    tracker->song_state.pattern_index = tracker->song->order_list[order_index];
-}
-
-void tracker_set_row(Tracker* tracker, uint8_t row) {
-    furi_check(tracker->playing == false);
-    furi_check(row < PATTERN_SIZE);
-    tracker->song_state.row_index = row;
-}
-
-void tracker_start(Tracker* tracker) {
-    furi_check(tracker->song != NULL);
-
-    tracker->playing = true;
-    tracker_send_position_message(tracker);
-    tracker_debug_init();
-    tracker_speaker_init();
-    tracker_interrupt_init(tracker->song->ticks_per_second, tracker_interrupt_cb, tracker);
-}
-
-void tracker_stop(Tracker* tracker) {
-    tracker_interrupt_deinit();
-    tracker_speaker_deinit();
-    tracker_debug_deinit();
-
-    tracker->playing = false;
-}

+ 0 - 38
music_tracker/tracker_engine/tracker.h

@@ -1,38 +0,0 @@
-#pragma once
-#include "tracker_notes.h"
-#include "tracker_song.h"
-
-typedef enum {
-    TrackerPositionChanged,
-    TrackerEndOfSong,
-} TrackerMessageType;
-
-typedef struct {
-    TrackerMessageType type;
-    union tracker_message_data {
-        struct {
-            uint8_t order_list_index;
-            uint8_t row;
-        } position;
-    } data;
-} TrackerMessage;
-
-typedef void (*TrackerMessageCallback)(TrackerMessage message, void* context);
-
-typedef struct Tracker Tracker;
-
-Tracker* tracker_alloc();
-
-void tracker_free(Tracker* tracker);
-
-void tracker_set_message_callback(Tracker* tracker, TrackerMessageCallback callback, void* context);
-
-void tracker_set_song(Tracker* tracker, const Song* song);
-
-void tracker_set_order_index(Tracker* tracker, uint8_t order_index);
-
-void tracker_set_row(Tracker* tracker, uint8_t row);
-
-void tracker_start(Tracker* tracker);
-
-void tracker_stop(Tracker* tracker);

+ 0 - 64
music_tracker/tracker_engine/tracker_notes.h

@@ -1,64 +0,0 @@
-#pragma once
-
-#define NOTE_NONE 0
-#define NOTE_C2 1
-#define NOTE_Cs2 2
-#define NOTE_D2 3
-#define NOTE_Ds2 4
-#define NOTE_E2 5
-#define NOTE_F2 6
-#define NOTE_Fs2 7
-#define NOTE_G2 8
-#define NOTE_Gs2 9
-#define NOTE_A2 10
-#define NOTE_As2 11
-#define NOTE_B2 12
-#define NOTE_C3 13
-#define NOTE_Cs3 14
-#define NOTE_D3 15
-#define NOTE_Ds3 16
-#define NOTE_E3 17
-#define NOTE_F3 18
-#define NOTE_Fs3 19
-#define NOTE_G3 20
-#define NOTE_Gs3 21
-#define NOTE_A3 22
-#define NOTE_As3 23
-#define NOTE_B3 24
-#define NOTE_C4 25
-#define NOTE_Cs4 26
-#define NOTE_D4 27
-#define NOTE_Ds4 28
-#define NOTE_E4 29
-#define NOTE_F4 30
-#define NOTE_Fs4 31
-#define NOTE_G4 32
-#define NOTE_Gs4 33
-#define NOTE_A4 34
-#define NOTE_As4 35
-#define NOTE_B4 36
-#define NOTE_C5 37
-#define NOTE_Cs5 38
-#define NOTE_D5 39
-#define NOTE_Ds5 40
-#define NOTE_E5 41
-#define NOTE_F5 42
-#define NOTE_Fs5 43
-#define NOTE_G5 44
-#define NOTE_Gs5 45
-#define NOTE_A5 46
-#define NOTE_As5 47
-#define NOTE_B5 48
-#define NOTE_C6 49
-#define NOTE_Cs6 50
-#define NOTE_D6 51
-#define NOTE_Ds6 52
-#define NOTE_E6 53
-#define NOTE_F6 54
-#define NOTE_Fs6 55
-#define NOTE_G6 56
-#define NOTE_Gs6 57
-#define NOTE_A6 58
-#define NOTE_As6 59
-#define NOTE_B6 60
-#define NOTE_OFF 63

+ 0 - 109
music_tracker/tracker_engine/tracker_song.h

@@ -1,109 +0,0 @@
-#pragma once
-#include <stdint.h>
-
-/**
- * @brief Row
- * 
- * AH       AL
- * FEDCBA98 76543210
- * nnnnnnee eedddddd
- * -------- --------
- * nnnnnn            = [0] do nothing, [1..60] note number, [61] note off, [62..63] not used
- *       ee ee       = [0..F] effect 
- *            111222 = [0..63] or [0..7, 0..7] effect data 
- */
-typedef uint16_t Row;
-
-#define ROW_NOTE_MASK 0x3F
-#define ROW_EFFECT_MASK 0x0F
-#define ROW_EFFECT_DATA_MASK 0x3F
-
-typedef enum {
-    // 0xy, x - first semitones offset, y - second semitones offset. 0 - no offset .. 7 - +7 semitones...
-    // Play the arpeggio chord with three notes. The first note is the base note, the second and third are offset by x and y.
-    // Each note plays one tick.
-    EffectArpeggio = 0x00,
-
-    // 1xx, xx - effect speed, 0 - no effect, 1 - slowest, 0x3F - fastest.
-    // Slide the note pitch up by xx Hz every tick.
-    EffectSlideUp = 0x01,
-
-    // 2xx, xx - effect speed, 0 - no effect, 1 - slowest, 0x3F - fastest.
-    // Slide the note pitch down by xx Hz every tick.
-    EffectSlideDown = 0x02,
-
-    // 3xx, xx - effect speed, 0 - no effect, 1 - slowest, 0x3F - fastest.
-    // Slide the already playing note pitch towards another one by xx Hz every tick.
-    // The note value is saved until the note is playing, so you don't have to repeat the note value to continue sliding.
-    EffectSlideToNote = 0x03,
-
-    // 4xy, x - vibrato speed (0..7), y - vibrato depth (0..7).
-    // Vibrato effect. The pitch of the note increases by x Hz each tick to a positive vibrato depth, then decreases to a negative depth.
-    // Value 1 of depth means 1/7 of a semitone (about 14.28 ct), so value 7 means full semitone.
-    // Note will play without vibrato on the first tick at the beginning of the effect.
-    // Vibrato speed and depth are saved until the note is playing, and will be updated only if they are not zero, so you doesn't have to repeat them every tick.
-    EffectVibrato = 0x04,
-
-    // Effect05 = 0x05,
-    // Effect06 = 0x06,
-    // Effect07 = 0x07,
-    // Effect08 = 0x08,
-    // Effect09 = 0x09,
-    // Effect0A = 0x0A,
-
-    // Bxx, xx - pattern number
-    // Jump to the order xx in the pattern order table at first tick of current row.
-    // So if you want to jump to the pattern after note 4, you should put this effect on the 5th note.
-    EffectJumpToOrder = 0x0B,
-
-    // Cxx, xx - pwm value
-    // Set the PWM value to xx for current row.
-    EffectPWM = 0x0C,
-
-    // Bxx, xx - row number
-    // Jump to the row xx in next pattern at first tick of current row.
-    // So if you want to jump to the pattern after note 4, you should put this effect on the 5th note.
-    EffectBreakPattern = 0x0D,
-
-    // Effect0E = 0x0E,
-
-    // Fxx, xx - song speed, 0 - 1 tick per note, 1 - 2 ticks per note, 0x3F - 64 ticks per note.
-    // Set the speed of the song in terms of ticks per note.
-    // Will be applied at the first tick of current row.
-    EffectSetSpeed = 0x0F,
-} Effect;
-
-#define EFFECT_DATA_2(x, y) ((x) | ((y) << 3))
-#define EFFECT_DATA_GET_X(data) ((data)&0x07)
-#define EFFECT_DATA_GET_Y(data) (((data) >> 3) & 0x07)
-#define EFFECT_DATA_NONE 0
-#define EFFECT_DATA_1_MAX 0x3F
-#define EFFECT_DATA_2_MAX 0x07
-
-#define FREQUENCY_UNSET -1.0f
-
-#define PWM_MIN 0.01f
-#define PWM_MAX 0.5f
-#define PWM_DEFAULT PWM_MAX
-
-#define PATTERN_SIZE 64
-
-#define ROW_MAKE(note, effect, data) \
-    ((Row)(((note)&0x3F) | (((effect)&0xF) << 6) | (((data)&0x3F) << 10)))
-
-typedef struct {
-    Row rows[PATTERN_SIZE];
-} Channel;
-
-typedef struct {
-    Channel* channels;
-} Pattern;
-
-typedef struct {
-    uint8_t channels_count;
-    uint8_t patterns_count;
-    Pattern* patterns;
-    uint8_t order_list_size;
-    uint8_t* order_list;
-    uint16_t ticks_per_second;
-} Song;

+ 0 - 182
music_tracker/view/tracker_view.c

@@ -1,182 +0,0 @@
-#include "tracker_view.h"
-#include <gui/elements.h>
-#include <furi.h>
-
-typedef struct {
-    const Song* song;
-    uint8_t order_list_index;
-    uint8_t row;
-} TrackerViewModel;
-
-struct TrackerView {
-    View* view;
-    void* back_context;
-    TrackerViewCallback back_callback;
-};
-
-static Channel* get_current_channel(TrackerViewModel* model) {
-    uint8_t channel_id = 0;
-    uint8_t pattern_id = model->song->order_list[model->order_list_index];
-    Pattern* pattern = &model->song->patterns[pattern_id];
-    return &pattern->channels[channel_id];
-}
-
-static const char* get_note_from_id(uint8_t note) {
-#define NOTE_COUNT 12
-    const char* notes[NOTE_COUNT] = {
-        "C ",
-        "C#",
-        "D ",
-        "D#",
-        "E ",
-        "F ",
-        "F#",
-        "G ",
-        "G#",
-        "A ",
-        "A#",
-        "B ",
-    };
-    return notes[(note) % NOTE_COUNT];
-#undef NOTE_COUNT
-}
-
-static uint8_t get_octave_from_id(uint8_t note) {
-    return ((note) / 12) + 2;
-}
-
-static uint8_t get_first_row_id(uint8_t row) {
-    return (row / 10) * 10;
-}
-
-static void
-    draw_row(Canvas* canvas, uint8_t i, Channel* channel, uint8_t row, FuriString* buffer) {
-    uint8_t x = 12 * (i + 1);
-    uint8_t first_row_id = get_first_row_id(row);
-    uint8_t current_row_id = first_row_id + i;
-
-    if((current_row_id) >= 64) {
-        return;
-    }
-
-    Row current_row = channel->rows[current_row_id];
-    uint8_t note = current_row & ROW_NOTE_MASK;
-    uint8_t effect = (current_row >> 6) & ROW_EFFECT_MASK;
-    uint8_t data = (current_row >> 10) & ROW_EFFECT_DATA_MASK;
-
-    if(current_row_id == row) {
-        canvas_set_color(canvas, ColorBlack);
-        canvas_draw_line(canvas, x - 9, 1, x - 9, 62);
-        canvas_draw_box(canvas, x - 8, 0, 9, 64);
-        canvas_draw_line(canvas, x + 1, 1, x + 1, 62);
-        canvas_set_color(canvas, ColorWhite);
-    }
-
-    furi_string_printf(buffer, "%02X", current_row_id);
-    canvas_draw_str(canvas, x, 61, furi_string_get_cstr(buffer));
-
-    if(note > 0 && note < NOTE_OFF) {
-        furi_string_printf(
-            buffer, "%s%d", get_note_from_id(note - 1), get_octave_from_id(note - 1));
-        canvas_draw_str(canvas, x, 44, furi_string_get_cstr(buffer));
-    } else if(note == NOTE_OFF) {
-        canvas_draw_str(canvas, x, 44, "OFF");
-    } else {
-        canvas_draw_str(canvas, x, 44, "---");
-    }
-
-    if(effect == 0 && data == 0) {
-        canvas_draw_str(canvas, x, 21, "-");
-        canvas_draw_str(canvas, x, 12, "--");
-    } else {
-        furi_string_printf(buffer, "%X", effect);
-        canvas_draw_str(canvas, x, 21, furi_string_get_cstr(buffer));
-
-        if(effect == EffectArpeggio || effect == EffectVibrato) {
-            uint8_t data_x = EFFECT_DATA_GET_X(data);
-            uint8_t data_y = EFFECT_DATA_GET_Y(data);
-            furi_string_printf(buffer, "%d%d", data_x, data_y);
-            canvas_draw_str(canvas, x, 12, furi_string_get_cstr(buffer));
-        } else {
-            furi_string_printf(buffer, "%02X", data);
-            canvas_draw_str(canvas, x, 12, furi_string_get_cstr(buffer));
-        }
-    }
-
-    if(current_row_id == row) {
-        canvas_set_color(canvas, ColorBlack);
-    }
-}
-
-static void tracker_view_draw_callback(Canvas* canvas, void* _model) {
-    TrackerViewModel* model = _model;
-    if(model->song == NULL) {
-        return;
-    }
-
-    canvas_set_font_direction(canvas, CanvasDirectionBottomToTop);
-    canvas_set_font(canvas, FontKeyboard);
-
-    Channel* channel = get_current_channel(model);
-    FuriString* buffer = furi_string_alloc();
-
-    for(uint8_t i = 0; i < 10; i++) {
-        draw_row(canvas, i, channel, model->row, buffer);
-    }
-    furi_string_free(buffer);
-}
-
-static bool tracker_view_input_callback(InputEvent* event, void* context) {
-    TrackerView* tracker_view = context;
-
-    if(tracker_view->back_callback) {
-        if(event->type == InputTypeShort && event->key == InputKeyBack) {
-            tracker_view->back_callback(tracker_view->back_context);
-            return true;
-        }
-    }
-    return false;
-}
-
-TrackerView* tracker_view_alloc() {
-    TrackerView* tracker_view = malloc(sizeof(TrackerView));
-    tracker_view->view = view_alloc();
-    view_allocate_model(tracker_view->view, ViewModelTypeLocking, sizeof(TrackerViewModel));
-    view_set_context(tracker_view->view, tracker_view);
-    view_set_draw_callback(tracker_view->view, (ViewDrawCallback)tracker_view_draw_callback);
-    view_set_input_callback(tracker_view->view, (ViewInputCallback)tracker_view_input_callback);
-    return tracker_view;
-}
-
-void tracker_view_free(TrackerView* tracker_view) {
-    view_free(tracker_view->view);
-    free(tracker_view);
-}
-
-View* tracker_view_get_view(TrackerView* tracker_view) {
-    return tracker_view->view;
-}
-
-void tracker_view_set_back_callback(
-    TrackerView* tracker_view,
-    TrackerViewCallback callback,
-    void* context) {
-    tracker_view->back_callback = callback;
-    tracker_view->back_context = context;
-}
-
-void tracker_view_set_song(TrackerView* tracker_view, const Song* song) {
-    with_view_model(
-        tracker_view->view, TrackerViewModel * model, { model->song = song; }, true);
-}
-
-void tracker_view_set_position(TrackerView* tracker_view, uint8_t order_list_index, uint8_t row) {
-    with_view_model(
-        tracker_view->view,
-        TrackerViewModel * model,
-        {
-            model->order_list_index = order_list_index;
-            model->row = row;
-        },
-        true);
-}

+ 0 - 29
music_tracker/view/tracker_view.h

@@ -1,29 +0,0 @@
-#include <gui/view.h>
-#include "../tracker_engine/tracker.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct TrackerView TrackerView;
-
-TrackerView* tracker_view_alloc();
-
-void tracker_view_free(TrackerView* tracker_view);
-
-View* tracker_view_get_view(TrackerView* tracker_view);
-
-typedef void (*TrackerViewCallback)(void* context);
-
-void tracker_view_set_back_callback(
-    TrackerView* tracker_view,
-    TrackerViewCallback callback,
-    void* context);
-
-void tracker_view_set_song(TrackerView* tracker_view, const Song* song);
-
-void tracker_view_set_position(TrackerView* tracker_view, uint8_t order_list_index, uint8_t row);
-
-#ifdef __cplusplus
-}
-#endif

+ 0 - 536
music_tracker/zero_tracker.c

@@ -1,536 +0,0 @@
-#include <furi.h>
-#include <gui/gui.h>
-#include <gui/view_dispatcher.h>
-#include <notification/notification_messages.h>
-#include "zero_tracker.h"
-#include "tracker_engine/tracker.h"
-#include "view/tracker_view.h"
-
-// Channel p_0_channels[] = {
-//     {
-//         .rows =
-//             {
-//                 // 1/4
-//                 ROW_MAKE(NOTE_C3, EffectArpeggio, EFFECT_DATA_2(4, 7)),
-//                 ROW_MAKE(0, EffectArpeggio, EFFECT_DATA_2(4, 7)),
-//                 ROW_MAKE(NOTE_C4, EffectSlideToNote, 0x20),
-//                 ROW_MAKE(0, EffectSlideToNote, 0x20),
-//                 //
-//                 ROW_MAKE(0, EffectSlideToNote, 0x20),
-//                 ROW_MAKE(0, EffectSlideToNote, 0x20),
-//                 ROW_MAKE(0, EffectSlideToNote, 0x20),
-//                 ROW_MAKE(0, EffectSlideToNote, 0x20),
-//                 //
-//                 ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(1, 1)),
-//                 ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(1, 1)),
-//                 ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(1, 1)),
-//                 ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(1, 1)),
-//                 //
-//                 ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(2, 2)),
-//                 ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(2, 2)),
-//                 ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(2, 2)),
-//                 ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(2, 2)),
-//                 // 2/4
-//                 ROW_MAKE(NOTE_C3, EffectSlideDown, 0x20),
-//                 ROW_MAKE(0, EffectSlideDown, 0x20),
-//                 ROW_MAKE(NOTE_C4, EffectVibrato, EFFECT_DATA_2(3, 3)),
-//                 ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(3, 3)),
-//                 //
-//                 ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(3, 3)),
-//                 ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(3, 3)),
-//                 ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(3, 3)),
-//                 ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(3, 3)),
-//                 //
-//                 ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(3, 3)),
-//                 ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(3, 3)),
-//                 ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(3, 3)),
-//                 ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(3, 3)),
-//                 //
-//                 ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(3, 3)),
-//                 ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(3, 3)),
-//                 ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(3, 3)),
-//                 ROW_MAKE(NOTE_OFF, EffectVibrato, EFFECT_DATA_2(3, 3)),
-//                 // 3/4
-//                 ROW_MAKE(NOTE_C3, EffectArpeggio, EFFECT_DATA_2(4, 7)),
-//                 ROW_MAKE(0, EffectArpeggio, EFFECT_DATA_2(4, 7)),
-//                 ROW_MAKE(NOTE_OFF, 0, 0),
-//                 ROW_MAKE(0, 0, 0),
-//                 //
-//                 ROW_MAKE(0, 0, 0),
-//                 ROW_MAKE(0, 0, 0),
-//                 ROW_MAKE(0, 0, 0),
-//                 ROW_MAKE(0, 0, 0),
-//                 //
-//                 ROW_MAKE(NOTE_C2, EffectPWM, 60),
-//                 ROW_MAKE(0, EffectPWM, 32),
-//                 ROW_MAKE(0, EffectPWM, 12),
-//                 ROW_MAKE(NOTE_OFF, 0, 0),
-//                 //
-//                 ROW_MAKE(0, 0, 0),
-//                 ROW_MAKE(0, 0, 0),
-//                 ROW_MAKE(0, 0, 0),
-//                 ROW_MAKE(0, 0, 0),
-//                 // 4/4
-//                 ROW_MAKE(NOTE_C3, EffectSlideDown, 0x20),
-//                 ROW_MAKE(0, EffectSlideDown, 0x20),
-//                 ROW_MAKE(0, EffectSlideDown, 0x20),
-//                 ROW_MAKE(NOTE_OFF, 0, 0),
-//                 //
-//                 ROW_MAKE(0, 0, 0),
-//                 ROW_MAKE(0, 0, 0),
-//                 ROW_MAKE(0, 0, 0),
-//                 ROW_MAKE(0, 0, 0),
-//                 //
-//                 ROW_MAKE(NOTE_C2, EffectPWM, 60),
-//                 ROW_MAKE(0, EffectPWM, 32),
-//                 ROW_MAKE(0, EffectPWM, 12),
-//                 ROW_MAKE(NOTE_OFF, 0, 0),
-//                 //
-//                 ROW_MAKE(0, 0, 0),
-//                 ROW_MAKE(0, 0, 0),
-//                 ROW_MAKE(0, 0, 0),
-//                 ROW_MAKE(0, 0, 0),
-//             },
-//     },
-// };
-
-Channel p_0_channels[] = {
-    {
-        .rows =
-            {
-                //
-                ROW_MAKE(NOTE_A4, EffectArpeggio, EFFECT_DATA_2(4, 7)),
-                ROW_MAKE(NOTE_C3, 0, 0),
-                ROW_MAKE(NOTE_F2, 0, 0),
-                ROW_MAKE(NOTE_C3, 0, 0),
-                //
-                ROW_MAKE(NOTE_E4, 0, 0),
-                ROW_MAKE(NOTE_C3, 0, 0),
-                ROW_MAKE(NOTE_E4, EffectPWM, 50),
-                ROW_MAKE(NOTE_OFF, 0, 0),
-                //
-                ROW_MAKE(NOTE_A4, 0, 0),
-                ROW_MAKE(0, EffectPWM, 55),
-                ROW_MAKE(0, EffectPWM, 45),
-                ROW_MAKE(NOTE_OFF, 0, 0),
-                //
-                ROW_MAKE(NOTE_E5, 0, 0),
-                ROW_MAKE(0, EffectPWM, 55),
-                ROW_MAKE(0, EffectPWM, 45),
-                ROW_MAKE(NOTE_OFF, 0, 0),
-                //
-                ROW_MAKE(NOTE_D5, 0, 0),
-                ROW_MAKE(NOTE_C3, EffectSlideDown, 0x30),
-                ROW_MAKE(NOTE_F2, 0, 0),
-                ROW_MAKE(NOTE_C3, 0, 0),
-                //
-                ROW_MAKE(NOTE_C5, 0, 0),
-                ROW_MAKE(NOTE_C3, 0, 0),
-                ROW_MAKE(NOTE_C5, 0, 0),
-                ROW_MAKE(NOTE_OFF, 0, 0),
-                //
-                ROW_MAKE(NOTE_A4, 0, 0),
-                ROW_MAKE(0, 0, 0),
-                ROW_MAKE(0, 0, 0),
-                ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(1, 1)),
-                //
-                ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(1, 1)),
-                ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(2, 2)),
-                ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(2, 2)),
-                ROW_MAKE(NOTE_OFF, 0, 0),
-                //
-                ROW_MAKE(NOTE_B4, EffectArpeggio, EFFECT_DATA_2(4, 7)),
-                ROW_MAKE(NOTE_D3, 0, 0),
-                ROW_MAKE(NOTE_G2, 0, 0),
-                ROW_MAKE(NOTE_D3, 0, 0),
-                //
-                ROW_MAKE(NOTE_E4, 0, 0),
-                ROW_MAKE(NOTE_D3, 0, 0),
-                ROW_MAKE(NOTE_E4, EffectPWM, 50),
-                ROW_MAKE(NOTE_OFF, 0, 0),
-                //
-                ROW_MAKE(NOTE_A4, 0, 0),
-                ROW_MAKE(0, EffectPWM, 55),
-                ROW_MAKE(0, EffectPWM, 45),
-                ROW_MAKE(NOTE_OFF, 0, 0),
-                //
-                ROW_MAKE(NOTE_E5, 0, 0),
-                ROW_MAKE(0, EffectPWM, 55),
-                ROW_MAKE(0, EffectPWM, 45),
-                ROW_MAKE(NOTE_OFF, 0, 0),
-                //
-                ROW_MAKE(NOTE_D5, 0, 0),
-                ROW_MAKE(NOTE_D3, EffectSlideDown, 0x3F),
-                ROW_MAKE(NOTE_G2, 0, 0),
-                ROW_MAKE(NOTE_D3, 0, 0),
-                //
-                ROW_MAKE(NOTE_C5, 0, 0),
-                ROW_MAKE(NOTE_D3, 0, 0),
-                ROW_MAKE(NOTE_C5, 0, 0),
-                ROW_MAKE(NOTE_OFF, 0, 0),
-                //
-                ROW_MAKE(NOTE_A4, 0, 0),
-                ROW_MAKE(0, 0, 0),
-                ROW_MAKE(0, 0, 0),
-                ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(1, 1)),
-                //
-                ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(1, 1)),
-                ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(2, 2)),
-                ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(2, 2)),
-                ROW_MAKE(NOTE_OFF, 0, 0),
-            },
-    },
-};
-
-Channel p_1_channels[] = {
-    {
-        .rows =
-            {
-                //
-                ROW_MAKE(NOTE_C5, EffectArpeggio, EFFECT_DATA_2(4, 7)),
-                ROW_MAKE(NOTE_E3, 0, 0),
-                ROW_MAKE(NOTE_A2, 0, 0),
-                ROW_MAKE(NOTE_E3, 0, 0),
-                //
-                ROW_MAKE(NOTE_B4, 0, 0),
-                ROW_MAKE(NOTE_E3, 0, 0),
-                ROW_MAKE(NOTE_B4, EffectPWM, 50),
-                ROW_MAKE(NOTE_OFF, 0, 0),
-                //
-                ROW_MAKE(NOTE_G4, 0, 0),
-                ROW_MAKE(0, EffectPWM, 55),
-                ROW_MAKE(0, EffectPWM, 45),
-                ROW_MAKE(NOTE_OFF, 0, 0),
-                //
-                ROW_MAKE(NOTE_C5, 0, 0),
-                ROW_MAKE(0, EffectPWM, 55),
-                ROW_MAKE(0, EffectPWM, 45),
-                ROW_MAKE(NOTE_OFF, 0, 0),
-                //
-                ROW_MAKE(NOTE_C6, 0, 0),
-                ROW_MAKE(NOTE_E3, EffectSlideDown, 0x30),
-                ROW_MAKE(NOTE_A2, 0, 0),
-                ROW_MAKE(NOTE_E3, 0, 0),
-                //
-                ROW_MAKE(NOTE_B4, 0, 0),
-                ROW_MAKE(NOTE_E3, 0, 0),
-                ROW_MAKE(NOTE_B4, EffectPWM, 50),
-                ROW_MAKE(NOTE_OFF, 0, 0),
-                //
-                ROW_MAKE(NOTE_G4, 0, 0),
-                ROW_MAKE(0, 0, 0),
-                ROW_MAKE(0, 0, 0),
-                ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(1, 1)),
-                //
-                ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(1, 1)),
-                ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(2, 2)),
-                ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(2, 2)),
-                ROW_MAKE(NOTE_OFF, 0, 0),
-                //
-                ROW_MAKE(NOTE_C5, EffectArpeggio, EFFECT_DATA_2(4, 7)),
-                ROW_MAKE(NOTE_E3, 0, 0),
-                ROW_MAKE(NOTE_A2, 0, 0),
-                ROW_MAKE(NOTE_E3, 0, 0),
-                //
-                ROW_MAKE(NOTE_B4, 0, 0),
-                ROW_MAKE(NOTE_E3, 0, 0),
-                ROW_MAKE(NOTE_B4, EffectPWM, 50),
-                ROW_MAKE(NOTE_OFF, 0, 0),
-                //
-                ROW_MAKE(NOTE_G4, 0, 0),
-                ROW_MAKE(0, EffectPWM, 55),
-                ROW_MAKE(0, EffectPWM, 45),
-                ROW_MAKE(NOTE_OFF, 0, 0),
-                //
-                ROW_MAKE(NOTE_D5, 0, 0),
-                ROW_MAKE(0, EffectPWM, 55),
-                ROW_MAKE(0, EffectPWM, 45),
-                ROW_MAKE(NOTE_OFF, 0, 0),
-                //
-                ROW_MAKE(NOTE_C6, 0, 0),
-                ROW_MAKE(NOTE_E3, EffectSlideDown, 0x30),
-                ROW_MAKE(NOTE_A2, 0, 0),
-                ROW_MAKE(NOTE_E3, 0, 0),
-                //
-                ROW_MAKE(NOTE_B4, 0, 0),
-                ROW_MAKE(NOTE_E3, 0, 0),
-                ROW_MAKE(NOTE_B4, EffectPWM, 50),
-                ROW_MAKE(NOTE_OFF, 0, 0),
-                //
-                ROW_MAKE(NOTE_G4, 0, 0),
-                ROW_MAKE(0, 0, 0),
-                ROW_MAKE(0, 0, 0),
-                ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(1, 1)),
-                //
-                ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(1, 1)),
-                ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(2, 2)),
-                ROW_MAKE(0, EffectVibrato, EFFECT_DATA_2(2, 2)),
-                ROW_MAKE(NOTE_OFF, 0, 0),
-            },
-    },
-};
-
-Channel p_2_channels[] = {
-    {
-        .rows =
-            {
-                //
-                ROW_MAKE(NOTE_C5, EffectArpeggio, EFFECT_DATA_2(4, 7)),
-                ROW_MAKE(NOTE_E3, 0, 0),
-                ROW_MAKE(NOTE_A2, 0, 0),
-                ROW_MAKE(NOTE_E3, 0, 0),
-                //
-                ROW_MAKE(NOTE_C5, 0, 0),
-                ROW_MAKE(NOTE_A4, 0, 0),
-                ROW_MAKE(NOTE_C5, 0, 0),
-                ROW_MAKE(NOTE_A4, 0, 0),
-                //
-                ROW_MAKE(NOTE_C5, EffectPWM, 55),
-                ROW_MAKE(NOTE_A4, EffectPWM, 45),
-                ROW_MAKE(NOTE_C5, EffectPWM, 35),
-                ROW_MAKE(NOTE_OFF, 0, 0),
-                //
-                ROW_MAKE(NOTE_C5, 0, 0),
-                ROW_MAKE(NOTE_A4, 0, 0),
-                ROW_MAKE(NOTE_C5, EffectPWM, 55),
-                ROW_MAKE(NOTE_OFF, 0, 0),
-                //
-                ROW_MAKE(NOTE_D5, 0, 0),
-                ROW_MAKE(NOTE_E3, EffectSlideDown, 0x30),
-                ROW_MAKE(NOTE_A2, 0, 0),
-                ROW_MAKE(NOTE_E3, 0, 0),
-                //
-                ROW_MAKE(NOTE_OFF, 0, 0),
-                ROW_MAKE(NOTE_E3, 0, 0),
-                ROW_MAKE(NOTE_B4, EffectPWM, 55),
-                ROW_MAKE(NOTE_OFF, 0, 0),
-                //
-                ROW_MAKE(NOTE_D5, 0, 0),
-                ROW_MAKE(NOTE_B4, 0, 0),
-                ROW_MAKE(NOTE_D5, EffectPWM, 55),
-                ROW_MAKE(NOTE_B4, EffectPWM, 55),
-                //
-                ROW_MAKE(NOTE_D5, EffectPWM, 45),
-                ROW_MAKE(NOTE_B4, EffectPWM, 45),
-                ROW_MAKE(NOTE_D5, EffectPWM, 35),
-                ROW_MAKE(NOTE_OFF, 0, 0),
-                //
-                ROW_MAKE(NOTE_D5, EffectArpeggio, EFFECT_DATA_2(4, 7)),
-                ROW_MAKE(NOTE_E3, 0, 0),
-                ROW_MAKE(NOTE_A2, 0, 0),
-                ROW_MAKE(NOTE_E3, 0, 0),
-                //
-                ROW_MAKE(NOTE_E5, 0, 0),
-                ROW_MAKE(NOTE_C5, 0, 0),
-                ROW_MAKE(NOTE_E5, 0, 0),
-                ROW_MAKE(NOTE_C5, 0, 0),
-                //
-                ROW_MAKE(NOTE_E5, EffectPWM, 55),
-                ROW_MAKE(NOTE_C5, EffectPWM, 45),
-                ROW_MAKE(NOTE_E5, EffectPWM, 35),
-                ROW_MAKE(NOTE_OFF, 0, 0),
-                //
-                ROW_MAKE(NOTE_E5, 0, 0),
-                ROW_MAKE(NOTE_C5, 0, 0),
-                ROW_MAKE(NOTE_E5, EffectPWM, 55),
-                ROW_MAKE(NOTE_OFF, 0, 0),
-                //
-                ROW_MAKE(NOTE_D5, 0, 0),
-                ROW_MAKE(NOTE_E3, EffectSlideDown, 0x30),
-                ROW_MAKE(NOTE_A2, 0, 0),
-                ROW_MAKE(NOTE_E3, 0, 0),
-                //
-                ROW_MAKE(NOTE_OFF, 0, 0),
-                ROW_MAKE(NOTE_E3, 0, 0),
-                ROW_MAKE(NOTE_B4, EffectPWM, 55),
-                ROW_MAKE(NOTE_OFF, 0, 0),
-                //
-                ROW_MAKE(NOTE_D5, 0, 0),
-                ROW_MAKE(NOTE_B4, 0, 0),
-                ROW_MAKE(NOTE_D5, EffectPWM, 55),
-                ROW_MAKE(NOTE_B4, EffectPWM, 55),
-                //
-                ROW_MAKE(NOTE_D5, EffectPWM, 45),
-                ROW_MAKE(NOTE_B4, EffectPWM, 45),
-                ROW_MAKE(NOTE_D5, EffectPWM, 35),
-                ROW_MAKE(NOTE_OFF, 0, 0),
-            },
-    },
-};
-
-Channel p_3_channels[] = {
-    {
-        .rows =
-            {
-                //
-                ROW_MAKE(NOTE_Ds5, EffectArpeggio, EFFECT_DATA_2(4, 6)),
-                ROW_MAKE(NOTE_C5, 0, 0),
-                ROW_MAKE(NOTE_Ds5, 0, 0),
-                ROW_MAKE(NOTE_C5, EffectPWM, 55),
-                //
-                ROW_MAKE(NOTE_Ds5, EffectPWM, 45),
-                ROW_MAKE(NOTE_C5, EffectPWM, 35),
-                ROW_MAKE(NOTE_Ds5, EffectPWM, 30),
-                ROW_MAKE(NOTE_OFF, 0, 0),
-                //
-                ROW_MAKE(NOTE_D5, 0, 0),
-                ROW_MAKE(NOTE_B4, 0, 0),
-                ROW_MAKE(NOTE_D5, 0, 0),
-                ROW_MAKE(NOTE_B4, EffectPWM, 55),
-                //
-                ROW_MAKE(NOTE_D5, EffectPWM, 45),
-                ROW_MAKE(NOTE_B4, EffectPWM, 35),
-                ROW_MAKE(NOTE_D5, EffectPWM, 30),
-                ROW_MAKE(NOTE_OFF, 0, 0),
-                //
-                ROW_MAKE(NOTE_Cs5, EffectArpeggio, EFFECT_DATA_2(4, 6)),
-                ROW_MAKE(NOTE_As4, 0, 0),
-                ROW_MAKE(NOTE_Cs5, 0, 0),
-                ROW_MAKE(NOTE_As4, EffectPWM, 55),
-                //
-                ROW_MAKE(NOTE_Cs5, EffectPWM, 45),
-                ROW_MAKE(NOTE_As4, EffectPWM, 35),
-                ROW_MAKE(NOTE_Cs5, EffectPWM, 30),
-                ROW_MAKE(NOTE_OFF, 0, 0),
-                //
-                ROW_MAKE(NOTE_C5, 0, 0),
-                ROW_MAKE(NOTE_A4, 0, 0),
-                ROW_MAKE(NOTE_C5, 0, 0),
-                ROW_MAKE(NOTE_A4, EffectPWM, 55),
-                //
-                ROW_MAKE(NOTE_C5, EffectPWM, 45),
-                ROW_MAKE(NOTE_A4, EffectPWM, 35),
-                ROW_MAKE(NOTE_C5, EffectPWM, 30),
-                ROW_MAKE(NOTE_OFF, 0, 0),
-                //
-                ROW_MAKE(NOTE_B4, EffectArpeggio, EFFECT_DATA_2(4, 6)),
-                ROW_MAKE(NOTE_Gs4, 0, 0),
-                ROW_MAKE(NOTE_B4, 0, 0),
-                ROW_MAKE(NOTE_Gs4, EffectPWM, 55),
-                //
-                ROW_MAKE(NOTE_B4, EffectPWM, 45),
-                ROW_MAKE(NOTE_Gs4, EffectPWM, 35),
-                ROW_MAKE(NOTE_B4, EffectPWM, 30),
-                ROW_MAKE(NOTE_OFF, 0, 0),
-                //
-                ROW_MAKE(NOTE_C5, 0, 0),
-                ROW_MAKE(NOTE_A4, 0, 0),
-                ROW_MAKE(NOTE_C5, 0, 0),
-                ROW_MAKE(NOTE_A4, EffectPWM, 55),
-                //
-                ROW_MAKE(NOTE_C5, EffectPWM, 45),
-                ROW_MAKE(NOTE_A4, EffectPWM, 35),
-                ROW_MAKE(NOTE_C5, EffectPWM, 30),
-                ROW_MAKE(NOTE_OFF, 0, 0),
-                //
-                ROW_MAKE(NOTE_Cs5, EffectArpeggio, EFFECT_DATA_2(4, 6)),
-                ROW_MAKE(NOTE_As4, 0, 0),
-                ROW_MAKE(NOTE_Cs5, 0, 0),
-                ROW_MAKE(NOTE_As4, EffectPWM, 55),
-                //
-                ROW_MAKE(NOTE_Cs5, EffectPWM, 45),
-                ROW_MAKE(NOTE_As4, EffectPWM, 35),
-                ROW_MAKE(NOTE_Cs5, EffectPWM, 30),
-                ROW_MAKE(NOTE_OFF, 0, 0),
-                //
-                ROW_MAKE(NOTE_D5, 0, 0),
-                ROW_MAKE(NOTE_B4, 0, 0),
-                ROW_MAKE(NOTE_D5, 0, 0),
-                ROW_MAKE(NOTE_B4, EffectPWM, 55),
-                //
-                ROW_MAKE(NOTE_D5, EffectPWM, 45),
-                ROW_MAKE(NOTE_B4, EffectPWM, 35),
-                ROW_MAKE(NOTE_D5, EffectPWM, 30),
-                ROW_MAKE(NOTE_OFF, 0, 0),
-            },
-    },
-};
-Pattern patterns[] = {
-    {.channels = p_0_channels},
-    {.channels = p_1_channels},
-    {.channels = p_2_channels},
-    {.channels = p_3_channels},
-};
-
-uint8_t order_list[] = {
-    0,
-    1,
-    0,
-    2,
-    0,
-    1,
-    0,
-    3,
-};
-
-Song song = {
-    .channels_count = 1,
-    .patterns_count = sizeof(patterns) / sizeof(patterns[0]),
-    .patterns = patterns,
-
-    .order_list_size = sizeof(order_list) / sizeof(order_list[0]),
-    .order_list = order_list,
-
-    .ticks_per_second = 60,
-};
-
-void tracker_message(TrackerMessage message, void* context) {
-    FuriMessageQueue* queue = context;
-    furi_assert(queue);
-    furi_message_queue_put(queue, &message, 0);
-}
-
-int32_t zero_tracker_app(void* p) {
-    UNUSED(p);
-
-    NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION);
-    notification_message(notification, &sequence_display_backlight_enforce_on);
-
-    Gui* gui = furi_record_open(RECORD_GUI);
-    ViewDispatcher* view_dispatcher = view_dispatcher_alloc();
-    TrackerView* tracker_view = tracker_view_alloc();
-    tracker_view_set_song(tracker_view, &song);
-    view_dispatcher_add_view(view_dispatcher, 0, tracker_view_get_view(tracker_view));
-    view_dispatcher_attach_to_gui(view_dispatcher, gui, ViewDispatcherTypeFullscreen);
-    view_dispatcher_switch_to_view(view_dispatcher, 0);
-
-    FuriMessageQueue* queue = furi_message_queue_alloc(8, sizeof(TrackerMessage));
-    Tracker* tracker = tracker_alloc();
-    tracker_set_message_callback(tracker, tracker_message, queue);
-    tracker_set_song(tracker, &song);
-    tracker_start(tracker);
-
-    while(1) {
-        TrackerMessage message;
-        FuriStatus status = furi_message_queue_get(queue, &message, FuriWaitForever);
-        if(status == FuriStatusOk) {
-            if(message.type == TrackerPositionChanged) {
-                uint8_t order_list_index = message.data.position.order_list_index;
-                uint8_t row = message.data.position.row;
-                uint8_t pattern = song.order_list[order_list_index];
-                tracker_view_set_position(tracker_view, order_list_index, row);
-                FURI_LOG_I("Tracker", "O:%d P:%d R:%d", order_list_index, pattern, row);
-            } else if(message.type == TrackerEndOfSong) {
-                FURI_LOG_I("Tracker", "End of song");
-                break;
-            }
-        }
-    }
-
-    tracker_stop(tracker);
-    tracker_free(tracker);
-    furi_message_queue_free(queue);
-
-    furi_delay_ms(500);
-
-    view_dispatcher_remove_view(view_dispatcher, 0);
-    tracker_view_free(tracker_view);
-    view_dispatcher_free(view_dispatcher);
-
-    notification_message(notification, &sequence_display_backlight_enforce_auto);
-
-    furi_record_close(RECORD_NOTIFICATION);
-    furi_record_close(RECORD_GUI);
-
-    return 0;
-}

+ 0 - 0
music_tracker/zero_tracker.h


BIN
music_tracker/zero_tracker.png


+ 0 - 52
sam/application.fam

@@ -1,52 +0,0 @@
-App(
-    appid="sam",
-    name="SAM AYBABTU",
-    apptype=FlipperAppType.EXTERNAL,
-    entry_point="sam_app",
-    requires=[
-        "gui",
-        "dialogs",
-    ],
-    stack_size=4 * 1024,
-    fap_icon="music_10px.png",
-    fap_category="Media",
-)
-App(
-    appid="sam_yes",
-    name="SAM YES",
-    apptype=FlipperAppType.EXTERNAL,
-    entry_point="sam_app_yes",
-    requires=[
-        "gui",
-        "dialogs",
-    ],
-    stack_size=4 * 1024,
-    fap_icon="music_10px.png",
-    fap_category="Media",
-)
-App(
-    appid="sam_no",
-    name="SAM NO",
-    apptype=FlipperAppType.EXTERNAL,
-    entry_point="sam_app_no",
-    requires=[
-        "gui",
-        "dialogs",
-    ],
-    stack_size=4 * 1024,
-    fap_icon="music_10px.png",
-    fap_category="Media",
-)
-App(
-    appid="sam_wtf",
-    name="SAM WTF",
-    apptype=FlipperAppType.EXTERNAL,
-    entry_point="sam_app_wtf",
-    requires=[
-        "gui",
-        "dialogs",
-    ],
-    stack_size=4 * 1024,
-    fap_icon="music_10px.png",
-    fap_category="Media",
-)

BIN
sam/music_10px.png


+ 0 - 46
sam/sam_app.cpp

@@ -1,46 +0,0 @@
-#include <furi.h>
-#include <furi_hal.h>
-#include "stm32_sam.h"
-// WOULD BE COOL IF SOMEONE MADE A TEXT ENTRY SCREEN TO HAVE IT READ WHAT IS ENTERED TO TEXT
-STM32SAM voice;
-
-extern "C" int32_t sam_app(void* p) {
-    UNUSED(p);
-    if(furi_hal_speaker_is_mine() || furi_hal_speaker_acquire(1000)) {
-        voice.begin();
-        voice.say(
-            "All your base are belong to us. You have no chance to survive make your time. ha. ha. ha. GOOD BYE. ");
-        furi_hal_speaker_release();
-    }
-    return 0;
-}
-
-extern "C" int32_t sam_app_yes(void* p) {
-    UNUSED(p);
-    if(furi_hal_speaker_is_mine() || furi_hal_speaker_acquire(1000)) {
-        voice.begin();
-        voice.say("Yes");
-        furi_hal_speaker_release();
-    }
-    return 0;
-}
-
-extern "C" int32_t sam_app_no(void* p) {
-    UNUSED(p);
-    if(furi_hal_speaker_is_mine() || furi_hal_speaker_acquire(1000)) {
-        voice.begin();
-        voice.say("No");
-        furi_hal_speaker_release();
-    }
-    return 0;
-}
-
-extern "C" int32_t sam_app_wtf(void* p) {
-    UNUSED(p);
-    if(furi_hal_speaker_is_mine() || furi_hal_speaker_acquire(1000)) {
-        voice.begin();
-        voice.say("What The Fuck");
-        furi_hal_speaker_release();
-    }
-    return 0;
-}

+ 0 - 5704
sam/stm32_sam.cpp

@@ -1,5704 +0,0 @@
-
-#include "stm32_sam.h"
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-////////////////////////////////////////////////////////////////////////////////////////////
-//
-//           All
-//
-////////////////////////////////////////////////////////////////////////////////////////////
-
-char input[256 + 1] = {0}; //tab39445
-//standard sam sound
-
-unsigned char wait1 = 7;
-unsigned char wait2 = 6;
-
-unsigned char A, X, Y;
-unsigned char mem44;
-unsigned char mem47;
-unsigned char mem49;
-unsigned char mem39;
-unsigned char mem50;
-unsigned char mem51;
-unsigned char mem53;
-unsigned char mem56;
-unsigned char mem59 = 0;
-
-unsigned char phonemeIndexOutput[60]; //tab47296
-unsigned char stressOutput[60]; //tab47365
-unsigned char phonemeLengthOutput[60]; //tab47416
-
-// contains the soundbuffer position
-int bufferpos;
-
-////////////////////////////////////////////////////////////////////////////////////////////
-//
-//           Sam Tabs
-//
-////////////////////////////////////////////////////////////////////////////////////////////
-
-//tab40672
-const unsigned char stressInputTable[] = {'*', '1', '2', '3', '4', '5', '6', '7', '8'};
-
-//tab40682
-const unsigned char signInputTable1[] = {
-    ' ', '.', '?', ',', '-', 'I', 'I', 'E', 'A', 'A', 'A', 'A', 'U', 'A', 'I', 'E', 'U',
-    'O', 'R', 'L', 'W', 'Y', 'W', 'R', 'L', 'W', 'Y', 'M', 'N', 'N', 'D', 'Q', 'S', 'S',
-    'F', 'T', '/', '/', 'Z', 'Z', 'V', 'D', 'C', '*', 'J', '*', '*', '*', 'E', 'A', 'O',
-    'A', 'O', 'U', 'B', '*', '*', 'D', '*', '*', 'G', '*', '*', 'G', '*', '*', 'P', '*',
-    '*', 'T', '*', '*', 'K', '*', '*', 'K', '*', '*', 'U', 'U', 'U'};
-
-//tab40763
-const unsigned char signInputTable2[] = {
-    '*', '*', '*', '*', '*', 'Y', 'H', 'H', 'E', 'A', 'H', 'O', 'H', 'X', 'X', 'R', 'X',
-    'H', 'X', 'X', 'X', 'X', 'H', '*', '*', '*', '*', '*', '*', 'X', 'X', '*', '*', 'H',
-    '*', 'H', 'H', 'X', '*', 'H', '*', 'H', 'H', '*', '*', '*', '*', '*', 'Y', 'Y', 'Y',
-    'W', 'W', 'W', '*', '*', '*', '*', '*', '*', '*', '*', '*', 'X', '*', '*', '*', '*',
-    '*', '*', '*', '*', '*', '*', '*', 'X', '*', '*', 'L', 'M', 'N'};
-
-//loc_9F8C
-const unsigned char flags[] = {
-    0x00, 0x00, 0x00, 0x00, 0x00, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0x84, 0x84, 0xA4,
-    0xA4, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x44, 0x44, 0x44, 0x44, 0x44, 0x4C,
-    0x4C, 0x4C, 0x48, 0x4C, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x44, 0x44, 0x44, 0x44,
-    0x48, 0x40, 0x4C, 0x44, 0x00, 0x00, 0xB4, 0xB4, 0xB4, 0x94, 0x94, 0x94, 0x4E, 0x4E,
-    0x4E, 0x4E, 0x4E, 0x4E, 0x4E, 0x4E, 0x4E, 0x4E, 0x4E, 0x4E, 0x4B, 0x4B, 0x4B, 0x4B,
-    0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x80, 0xC1, 0xC1
-
-};
-
-//??? flags overlap flags2
-//loc_9FDA
-const unsigned char flags2[] = {
-    0x80, 0xC1, 0xC1, 0xC1, 0xC1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x08, 0x0C, 0x08, 0x04, 0x40,
-    0x24, 0x20, 0x20, 0x24, 0x00, 0x00, 0x24, 0x20, 0x20, 0x24, 0x20, 0x20, 0x00, 0x20, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-
-//tab45616???
-const unsigned char phonemeStressedLengthTable[] = {
-    0x00, 0x12, 0x12, 0x12, 8,   0xB, 9,   0xB, 0xE, 0xF, 0xB, 0x10, 0xC, 6, 6, 0xE,
-    0xC,  0xE,  0xC,  0xB,  8,   8,   0xB, 0xA, 9,   8,   8,   8,    8,   8, 3, 5,
-    2,    2,    2,    2,    2,   2,   6,   6,   8,   6,   6,   2,    9,   4, 2, 1,
-    0xE,  0xF,  0xF,  0xF,  0xE, 0xE, 8,   2,   2,   7,   2,   1,    7,   2, 2, 7,
-    2,    2,    8,    2,    2,   6,   2,   2,   7,   2,   4,   7,    1,   4, 5, 5};
-
-//tab45536???
-const unsigned char phonemeLengthTable[] = {
-    0, 0x12, 0x12, 0x12, 8, 8, 8, 8,    8,   0xB, 6,   0xC, 0xA, 5, 5, 0xB, 0xA, 0xA, 0xA,  9,
-    8, 7,    9,    7,    6, 8, 6, 7,    7,   7,   2,   5,   2,   2, 2, 2,   2,   2,   6,    6,
-    7, 6,    6,    2,    8, 3, 1, 0x1E, 0xD, 0xC, 0xC, 0xC, 0xE, 9, 6, 1,   2,   5,   1,    1,
-    6, 1,    2,    6,    1, 2, 8, 2,    2,   4,   2,   2,   6,   1, 4, 6,   1,   4,   0xC7, 0xFF};
-
-/*
-
-  Ind  | phoneme |  flags   |
-  -----|---------|----------|
-  0    |   *     | 00000000 |
-  1    |  .*     | 00000000 |
-  2    |  ?*     | 00000000 |
-  3    |  ,*     | 00000000 |
-  4    |  -*     | 00000000 |
-
-  VOWELS
-  5    |  IY     | 10100100 |
-  6    |  IH     | 10100100 |
-  7    |  EH     | 10100100 |
-  8    |  AE     | 10100100 |
-  9    |  AA     | 10100100 |
-  10   |  AH     | 10100100 |
-  11   |  AO     | 10000100 |
-  17   |  OH     | 10000100 |
-  12   |  UH     | 10000100 |
-  16   |  UX     | 10000100 |
-  15   |  ER     | 10000100 |
-  13   |  AX     | 10100100 |
-  14   |  IX     | 10100100 |
-
-  DIPHTONGS
-  48   |  EY     | 10110100 |
-  49   |  AY     | 10110100 |
-  50   |  OY     | 10110100 |
-  51   |  AW     | 10010100 |
-  52   |  OW     | 10010100 |
-  53   |  UW     | 10010100 |
-
-
-  21   |  YX     | 10000100 |
-  20   |  WX     | 10000100 |
-  18   |  RX     | 10000100 |
-  19   |  LX     | 10000100 |
-  37   |  /X     | 01000000 |
-  30   |  DX     | 01001000 |
-
-
-  22   |  WH     | 01000100 |
-
-
-  VOICED CONSONANTS
-  23   |  R*     | 01000100 |
-  24   |  L*     | 01000100 |
-  25   |  W*     | 01000100 |
-  26   |  Y*     | 01000100 |
-  27   |  M*     | 01001100 |
-  28   |  N*     | 01001100 |
-  29   |  NX     | 01001100 |
-  54   |  B*     | 01001110 |
-  57   |  D*     | 01001110 |
-  60   |  G*     | 01001110 |
-  44   |  J*     | 01001100 |
-  38   |  Z*     | 01000100 |
-  39   |  ZH     | 01000100 |
-  40   |  V*     | 01000100 |
-  41   |  DH     | 01000100 |
-
-  unvoiced CONSONANTS
-  32   |  S*     | 01000000 |
-  33   |  SH     | 01000000 |
-  34   |  F*     | 01000000 |
-  35   |  TH     | 01000000 |
-  66   |  P*     | 01001011 |
-  69   |  T*     | 01001011 |
-  72   |  K*     | 01001011 |
-  42   |  CH     | 01001000 |
-  36   |  /H     | 01000000 |
-
-  43   |  **     | 01000000 |
-  45   |  **     | 01000100 |
-  46   |  **     | 00000000 |
-  47   |  **     | 00000000 |
-
-
-  55   |  **     | 01001110 |
-  56   |  **     | 01001110 |
-  58   |  **     | 01001110 |
-  59   |  **     | 01001110 |
-  61   |  **     | 01001110 |
-  62   |  **     | 01001110 |
-  63   |  GX     | 01001110 |
-  64   |  **     | 01001110 |
-  65   |  **     | 01001110 |
-  67   |  **     | 01001011 |
-  68   |  **     | 01001011 |
-  70   |  **     | 01001011 |
-  71   |  **     | 01001011 |
-  73   |  **     | 01001011 |
-  74   |  **     | 01001011 |
-  75   |  KX     | 01001011 |
-  76   |  **     | 01001011 |
-  77   |  **     | 01001011 |
-
-
-  SPECIAL
-  78   |  UL     | 10000000 |
-  79   |  UM     | 11000001 |
-  80   |  UN     | 11000001 |
-  31   |  Q*     | 01001100 |
-
-*/
-
-////////////////////////////////////////////////////////////////////////////////////////////
-//
-//           RenderTabs
-//
-////////////////////////////////////////////////////////////////////////////////////////////
-
-const unsigned char tab48426[5] = {0x18, 0x1A, 0x17, 0x17, 0x17};
-
-const unsigned char tab47492[] = {0, 0, 0xE0, 0xE6, 0xEC, 0xF3, 0xF9, 0, 6, 0xC, 6};
-
-const unsigned char amplitudeRescale[] = {
-    0,
-    1,
-    2,
-    2,
-    2,
-    3,
-    3,
-    4,
-    4,
-    5,
-    6,
-    8,
-    9,
-    0xB,
-    0xD,
-    0xF,
-    0 //17 elements?
-};
-
-// Used to decide which phoneme's blend lengths. The candidate with the lower score is selected.
-// tab45856
-const unsigned char blendRank[] = {0,    0x1F, 0x1F, 0x1F, 0x1F, 2,    2,    2,    2,    2,
-                                   2,    2,    2,    2,    5,    5,    2,    0xA,  2,    8,
-                                   5,    5,    0xB,  0xA,  9,    8,    8,    0xA0, 8,    8,
-                                   0x17, 0x1F, 0x12, 0x12, 0x12, 0x12, 0x1E, 0x1E, 0x14, 0x14,
-                                   0x14, 0x14, 0x17, 0x17, 0x1A, 0x1A, 0x1D, 0x1D, 2,    2,
-                                   2,    2,    2,    2,    0x1A, 0x1D, 0x1B, 0x1A, 0x1D, 0x1B,
-                                   0x1A, 0x1D, 0x1B, 0x1A, 0x1D, 0x1B, 0x17, 0x1D, 0x17, 0x17,
-                                   0x1D, 0x17, 0x17, 0x1D, 0x17, 0x17, 0x1D, 0x17, 0x17, 0x17};
-
-// Number of frames at the end of a phoneme devoted to interpolating to next phoneme's final value
-//tab45696
-const unsigned char outBlendLength[] = {0, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,    4,
-                                        4, 4, 3, 2, 4, 4, 2, 2, 2, 2, 2, 1, 1, 1, 1,    1,
-                                        1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 0, 1, 0, 1, 0,    5,
-                                        5, 5, 5, 5, 4, 4, 2, 0, 1, 2, 0, 1, 2, 0, 1,    2,
-                                        0, 1, 2, 0, 2, 2, 0, 1, 3, 0, 2, 3, 0, 2, 0xA0, 0xA0};
-
-// Number of frames at beginning of a phoneme devoted to interpolating to phoneme's final value
-// tab45776
-const unsigned char inBlendLength[] = {0, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,    4,
-                                       4, 4, 3, 3, 4, 4, 3, 3, 3, 3, 3, 1, 2, 3, 2,    1,
-                                       3, 3, 3, 3, 1, 1, 3, 3, 3, 2, 2, 3, 2, 3, 0,    0,
-                                       5, 5, 5, 5, 4, 4, 2, 0, 2, 2, 0, 3, 2, 0, 4,    2,
-                                       0, 3, 2, 0, 2, 2, 0, 2, 3, 0, 3, 3, 0, 3, 0xB0, 0xA0};
-
-// Looks like it's used as bit flags
-// High bits masked by 248 (11111000)
-//
-// 32: S*    241         11110001
-// 33: SH    226         11100010
-// 34: F*    211         11010011
-// 35: TH    187         10111011
-// 36: /H    124         01111100
-// 37: /X    149         10010101
-// 38: Z*    1           00000001
-// 39: ZH    2           00000010
-// 40: V*    3           00000011
-// 41: DH    3           00000011
-// 43: **    114         01110010
-// 45: **    2           00000010
-// 67: **    27          00011011
-// 70: **    25          00011001
-// tab45936
-const unsigned char sampledConsonantFlags[] = {
-    0, 0, 0, 0,    0, 0, 0, 0,    0, 0, 0,    0, 0,    0,    0,    0,    0,    0,    0, 0,
-    0, 0, 0, 0,    0, 0, 0, 0,    0, 0, 0,    0, 0xF1, 0xE2, 0xD3, 0xBB, 0x7C, 0x95, 1, 2,
-    3, 3, 0, 0x72, 0, 2, 0, 0,    0, 0, 0,    0, 0,    0,    0,    0,    0,    0,    0, 0,
-    0, 0, 0, 0,    0, 0, 0, 0x1B, 0, 0, 0x19, 0, 0,    0,    0,    0,    0,    0,    0, 0};
-
-//tab45056
-unsigned char freq1data[] = {
-    0x00, 0x13, 0x13, 0x13, 0x13, 0xA,  0xE, 0x12, 0x18, 0x1A, 0x16, 0x14, 0x10, 0x14, 0xE,  0x12,
-    0xE,  0x12, 0x12, 0x10, 0xC,  0xE,  0xA, 0x12, 0xE,  0xA,  8,    6,    6,    6,    6,    0x11,
-    6,    6,    6,    6,    0xE,  0x10, 9,   0xA,  8,    0xA,  6,    6,    6,    5,    6,    0,
-    0x12, 0x1A, 0x14, 0x1A, 0x12, 0xC,  6,   6,    6,    6,    6,    6,    6,    6,    6,    6,
-    6,    6,    6,    6,    6,    6,    6,   6,    6,    0xA,  0xA,  6,    6,    6,    0x2C, 0x13};
-
-//tab451356
-unsigned char freq2data[] = {0x00, 0x43, 0x43, 0x43, 0x43, 0x54, 0x48, 0x42, 0x3E, 0x28,
-                             0x2C, 0x1E, 0x24, 0x2C, 0x48, 0x30, 0x24, 0x1E, 0x32, 0x24,
-                             0x1C, 0x44, 0x18, 0x32, 0x1E, 0x18, 0x52, 0x2E, 0x36, 0x56,
-                             0x36, 0x43, 0x49, 0x4F, 0x1A, 0x42, 0x49, 0x25, 0x33, 0x42,
-                             0x28, 0x2F, 0x4F, 0x4F, 0x42, 0x4F, 0x6E, 0x00, 0x48, 0x26,
-                             0x1E, 0x2A, 0x1E, 0x22, 0x1A, 0x1A, 0x1A, 0x42, 0x42, 0x42,
-                             0x6E, 0x6E, 0x6E, 0x54, 0x54, 0x54, 0x1A, 0x1A, 0x1A, 0x42,
-                             0x42, 0x42, 0x6D, 0x56, 0x6D, 0x54, 0x54, 0x54, 0x7F, 0x7F};
-//tab45216
-unsigned char freq3data[] = {0x00, 0x5B, 0x5B, 0x5B, 0x5B, 0x6E, 0x5D, 0x5B, 0x58, 0x59,
-                             0x57, 0x58, 0x52, 0x59, 0x5D, 0x3E, 0x52, 0x58, 0x3E, 0x6E,
-                             0x50, 0x5D, 0x5A, 0x3C, 0x6E, 0x5A, 0x6E, 0x51, 0x79, 0x65,
-                             0x79, 0x5B, 0x63, 0x6A, 0x51, 0x79, 0x5D, 0x52, 0x5D, 0x67,
-                             0x4C, 0x5D, 0x65, 0x65, 0x79, 0x65, 0x79, 0x00, 0x5A, 0x58,
-                             0x58, 0x58, 0x58, 0x52, 0x51, 0x51, 0x51, 0x79, 0x79, 0x79,
-                             0x70, 0x6E, 0x6E, 0x5E, 0x5E, 0x5E, 0x51, 0x51, 0x51, 0x79,
-                             0x79, 0x79, 0x65, 0x65, 0x70, 0x5E, 0x5E, 0x5E, 0x08, 0x01};
-
-////////////////////////////////////////////////////////////////////////////////////////////
-//
-//           Reciter
-//
-////////////////////////////////////////////////////////////////////////////////////////////
-
-unsigned char inputtemp[256]; // secure copy of input tab36096
-
-////////////////////////////////////////////////////////////////////////////////////////////
-//
-//           Render
-//
-////////////////////////////////////////////////////////////////////////////////////////////
-
-//timetable for more accurate c64 simulation
-int timetable[5][5] = {
-    {162, 167, 167, 127, 128},
-    {226, 60, 60, 0, 0},
-    {225, 60, 59, 0, 0},
-    {200, 0, 0, 54, 55},
-    {199, 0, 0, 54, 54}};
-
-unsigned oldtimetableindex;
-
-const unsigned char ampl1data[] = {0,   0,   0,   0,   0,   0xD, 0xD, 0xE, 0xF, 0xF, 0xF, 0xF,
-                                   0xF, 0xC, 0xD, 0xC, 0xF, 0xF, 0xD, 0xD, 0xD, 0xE, 0xD, 0xC,
-                                   0xD, 0xD, 0xD, 0xC, 9,   9,   0,   0,   0,   0,   0,   0,
-                                   0,   0,   0xB, 0xB, 0xB, 0xB, 0,   0,   1,   0xB, 0,   2,
-                                   0xE, 0xF, 0xF, 0xF, 0xF, 0xD, 2,   4,   0,   2,   4,   0,
-                                   1,   4,   0,   1,   4,   0,   0,   0,   0,   0,   0,   0,
-                                   0,   0xC, 0,   0,   0,   0,   0xF, 0xF};
-
-const unsigned char ampl2data[] = {
-    0, 0,   0, 0,   0, 0xA, 0xB, 0xD, 0xE, 0xD, 0xC, 0xC, 0xB, 9,   0xB, 0xB, 0xC, 0xC, 0xC, 8,
-    8, 0xC, 8, 0xA, 8, 8,   0xA, 3,   9,   6,   0,   0,   0,   0,   0,   0,   0,   0,   3,   5,
-    3, 4,   0, 0,   0, 5,   0xA, 2,   0xE, 0xD, 0xC, 0xD, 0xC, 8,   0,   1,   0,   0,   1,   0,
-    0, 1,   0, 0,   1, 0,   0,   0,   0,   0,   0,   0,   0,   0xA, 0,   0,   0xA, 0,   0,   0};
-
-const unsigned char ampl3data[] = {0, 0, 0, 0, 0, 8, 7, 8, 8, 1, 1, 0, 1, 0, 7,    5,
-                                   1, 0, 6, 1, 0, 7, 0, 5, 1, 0, 8, 0, 0, 3, 0,    0,
-                                   0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0xE,  1,
-                                   9, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,    0,
-                                   0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 5, 0, 0x13, 0x10};
-
-//tab42240
-const signed char sinus[256] = {
-    0,    3,    6,    9,    12,   16,   19,   22,   25,   28,   31,   34,   37,   40,   43,   46,
-    49,   51,   54,   57,   60,   63,   65,   68,   71,   73,   76,   78,   81,   83,   85,   88,
-    90,   92,   94,   96,   98,   100,  102,  104,  106,  107,  109,  111,  112,  113,  115,  116,
-    117,  118,  120,  121,  122,  122,  123,  124,  125,  125,  126,  126,  126,  127,  127,  127,
-    127,  127,  127,  127,  126,  126,  126,  125,  125,  124,  123,  122,  122,  121,  120,  118,
-    117,  116,  115,  113,  112,  111,  109,  107,  106,  104,  102,  100,  98,   96,   94,   92,
-    90,   88,   85,   83,   81,   78,   76,   73,   71,   68,   65,   63,   60,   57,   54,   51,
-    49,   46,   43,   40,   37,   34,   31,   28,   25,   22,   19,   16,   12,   9,    6,    3,
-    0,    -3,   -6,   -9,   -12,  -16,  -19,  -22,  -25,  -28,  -31,  -34,  -37,  -40,  -43,  -46,
-    -49,  -51,  -54,  -57,  -60,  -63,  -65,  -68,  -71,  -73,  -76,  -78,  -81,  -83,  -85,  -88,
-    -90,  -92,  -94,  -96,  -98,  -100, -102, -104, -106, -107, -109, -111, -112, -113, -115, -116,
-    -117, -118, -120, -121, -122, -122, -123, -124, -125, -125, -126, -126, -126, -127, -127, -127,
-    -127, -127, -127, -127, -126, -126, -126, -125, -125, -124, -123, -122, -122, -121, -120, -118,
-    -117, -116, -115, -113, -112, -111, -109, -107, -106, -104, -102, -100, -98,  -96,  -94,  -92,
-    -90,  -88,  -85,  -83,  -81,  -78,  -76,  -73,  -71,  -68,  -65,  -63,  -60,  -57,  -54,  -51,
-    -49,  -46,  -43,  -40,  -37,  -34,  -31,  -28,  -25,  -22,  -19,  -16,  -12,  -9,   -6,   -3};
-
-//tab42496
-const unsigned char rectangle[] = {
-    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
-    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
-    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
-    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
-    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
-    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
-    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
-    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
-    0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
-    0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
-    0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
-    0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
-    0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
-    0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
-    0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
-    0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
-    0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
-    0x70};
-
-//random data ?
-const unsigned char sampleTable[0x500] = {
-    //00
-
-    0x38,
-    0x84,
-    0x6B,
-    0x19,
-    0xC6,
-    0x63,
-    0x18,
-    0x86,
-    0x73,
-    0x98,
-    0xC6,
-    0xB1,
-    0x1C,
-    0xCA,
-    0x31,
-    0x8C,
-    0xC7,
-    0x31,
-    0x88,
-    0xC2,
-    0x30,
-    0x98,
-    0x46,
-    0x31,
-    0x18,
-    0xC6,
-    0x35,
-    0xC,
-    0xCA,
-    0x31,
-    0xC,
-    0xC6
-    //20
-    ,
-    0x21,
-    0x10,
-    0x24,
-    0x69,
-    0x12,
-    0xC2,
-    0x31,
-    0x14,
-    0xC4,
-    0x71,
-    8,
-    0x4A,
-    0x22,
-    0x49,
-    0xAB,
-    0x6A,
-    0xA8,
-    0xAC,
-    0x49,
-    0x51,
-    0x32,
-    0xD5,
-    0x52,
-    0x88,
-    0x93,
-    0x6C,
-    0x94,
-    0x22,
-    0x15,
-    0x54,
-    0xD2,
-    0x25
-    //40
-    ,
-    0x96,
-    0xD4,
-    0x50,
-    0xA5,
-    0x46,
-    0x21,
-    8,
-    0x85,
-    0x6B,
-    0x18,
-    0xC4,
-    0x63,
-    0x10,
-    0xCE,
-    0x6B,
-    0x18,
-    0x8C,
-    0x71,
-    0x19,
-    0x8C,
-    0x63,
-    0x35,
-    0xC,
-    0xC6,
-    0x33,
-    0x99,
-    0xCC,
-    0x6C,
-    0xB5,
-    0x4E,
-    0xA2,
-    0x99
-    //60
-    ,
-    0x46,
-    0x21,
-    0x28,
-    0x82,
-    0x95,
-    0x2E,
-    0xE3,
-    0x30,
-    0x9C,
-    0xC5,
-    0x30,
-    0x9C,
-    0xA2,
-    0xB1,
-    0x9C,
-    0x67,
-    0x31,
-    0x88,
-    0x66,
-    0x59,
-    0x2C,
-    0x53,
-    0x18,
-    0x84,
-    0x67,
-    0x50,
-    0xCA,
-    0xE3,
-    0xA,
-    0xAC,
-    0xAB,
-    0x30
-    //80
-    ,
-    0xAC,
-    0x62,
-    0x30,
-    0x8C,
-    0x63,
-    0x10,
-    0x94,
-    0x62,
-    0xB1,
-    0x8C,
-    0x82,
-    0x28,
-    0x96,
-    0x33,
-    0x98,
-    0xD6,
-    0xB5,
-    0x4C,
-    0x62,
-    0x29,
-    0xA5,
-    0x4A,
-    0xB5,
-    0x9C,
-    0xC6,
-    0x31,
-    0x14,
-    0xD6,
-    0x38,
-    0x9C,
-    0x4B,
-    0xB4
-    //A0
-    ,
-    0x86,
-    0x65,
-    0x18,
-    0xAE,
-    0x67,
-    0x1C,
-    0xA6,
-    0x63,
-    0x19,
-    0x96,
-    0x23,
-    0x19,
-    0x84,
-    0x13,
-    8,
-    0xA6,
-    0x52,
-    0xAC,
-    0xCA,
-    0x22,
-    0x89,
-    0x6E,
-    0xAB,
-    0x19,
-    0x8C,
-    0x62,
-    0x34,
-    0xC4,
-    0x62,
-    0x19,
-    0x86,
-    0x63
-    //C0
-    ,
-    0x18,
-    0xC4,
-    0x23,
-    0x58,
-    0xD6,
-    0xA3,
-    0x50,
-    0x42,
-    0x54,
-    0x4A,
-    0xAD,
-    0x4A,
-    0x25,
-    0x11,
-    0x6B,
-    0x64,
-    0x89,
-    0x4A,
-    0x63,
-    0x39,
-    0x8A,
-    0x23,
-    0x31,
-    0x2A,
-    0xEA,
-    0xA2,
-    0xA9,
-    0x44,
-    0xC5,
-    0x12,
-    0xCD,
-    0x42
-    //E0
-    ,
-    0x34,
-    0x8C,
-    0x62,
-    0x18,
-    0x8C,
-    0x63,
-    0x11,
-    0x48,
-    0x66,
-    0x31,
-    0x9D,
-    0x44,
-    0x33,
-    0x1D,
-    0x46,
-    0x31,
-    0x9C,
-    0xC6,
-    0xB1,
-    0xC,
-    0xCD,
-    0x32,
-    0x88,
-    0xC4,
-    0x73,
-    0x18,
-    0x86,
-    0x73,
-    8,
-    0xD6,
-    0x63,
-    0x58
-    //100
-    ,
-    7,
-    0x81,
-    0xE0,
-    0xF0,
-    0x3C,
-    7,
-    0x87,
-    0x90,
-    0x3C,
-    0x7C,
-    0xF,
-    0xC7,
-    0xC0,
-    0xC0,
-    0xF0,
-    0x7C,
-    0x1E,
-    7,
-    0x80,
-    0x80,
-    0,
-    0x1C,
-    0x78,
-    0x70,
-    0xF1,
-    0xC7,
-    0x1F,
-    0xC0,
-    0xC,
-    0xFE,
-    0x1C,
-    0x1F
-    //120
-    ,
-    0x1F,
-    0xE,
-    0xA,
-    0x7A,
-    0xC0,
-    0x71,
-    0xF2,
-    0x83,
-    0x8F,
-    3,
-    0xF,
-    0xF,
-    0xC,
-    0,
-    0x79,
-    0xF8,
-    0x61,
-    0xE0,
-    0x43,
-    0xF,
-    0x83,
-    0xE7,
-    0x18,
-    0xF9,
-    0xC1,
-    0x13,
-    0xDA,
-    0xE9,
-    0x63,
-    0x8F,
-    0xF,
-    0x83
-    //140
-    ,
-    0x83,
-    0x87,
-    0xC3,
-    0x1F,
-    0x3C,
-    0x70,
-    0xF0,
-    0xE1,
-    0xE1,
-    0xE3,
-    0x87,
-    0xB8,
-    0x71,
-    0xE,
-    0x20,
-    0xE3,
-    0x8D,
-    0x48,
-    0x78,
-    0x1C,
-    0x93,
-    0x87,
-    0x30,
-    0xE1,
-    0xC1,
-    0xC1,
-    0xE4,
-    0x78,
-    0x21,
-    0x83,
-    0x83,
-    0xC3
-    //160
-    ,
-    0x87,
-    6,
-    0x39,
-    0xE5,
-    0xC3,
-    0x87,
-    7,
-    0xE,
-    0x1C,
-    0x1C,
-    0x70,
-    0xF4,
-    0x71,
-    0x9C,
-    0x60,
-    0x36,
-    0x32,
-    0xC3,
-    0x1E,
-    0x3C,
-    0xF3,
-    0x8F,
-    0xE,
-    0x3C,
-    0x70,
-    0xE3,
-    0xC7,
-    0x8F,
-    0xF,
-    0xF,
-    0xE,
-    0x3C
-    //180
-    ,
-    0x78,
-    0xF0,
-    0xE3,
-    0x87,
-    6,
-    0xF0,
-    0xE3,
-    7,
-    0xC1,
-    0x99,
-    0x87,
-    0xF,
-    0x18,
-    0x78,
-    0x70,
-    0x70,
-    0xFC,
-    0xF3,
-    0x10,
-    0xB1,
-    0x8C,
-    0x8C,
-    0x31,
-    0x7C,
-    0x70,
-    0xE1,
-    0x86,
-    0x3C,
-    0x64,
-    0x6C,
-    0xB0,
-    0xE1
-    //1A0
-    ,
-    0xE3,
-    0xF,
-    0x23,
-    0x8F,
-    0xF,
-    0x1E,
-    0x3E,
-    0x38,
-    0x3C,
-    0x38,
-    0x7B,
-    0x8F,
-    7,
-    0xE,
-    0x3C,
-    0xF4,
-    0x17,
-    0x1E,
-    0x3C,
-    0x78,
-    0xF2,
-    0x9E,
-    0x72,
-    0x49,
-    0xE3,
-    0x25,
-    0x36,
-    0x38,
-    0x58,
-    0x39,
-    0xE2,
-    0xDE
-    //1C0
-    ,
-    0x3C,
-    0x78,
-    0x78,
-    0xE1,
-    0xC7,
-    0x61,
-    0xE1,
-    0xE1,
-    0xB0,
-    0xF0,
-    0xF0,
-    0xC3,
-    0xC7,
-    0xE,
-    0x38,
-    0xC0,
-    0xF0,
-    0xCE,
-    0x73,
-    0x73,
-    0x18,
-    0x34,
-    0xB0,
-    0xE1,
-    0xC7,
-    0x8E,
-    0x1C,
-    0x3C,
-    0xF8,
-    0x38,
-    0xF0,
-    0xE1
-    //1E0
-    ,
-    0xC1,
-    0x8B,
-    0x86,
-    0x8F,
-    0x1C,
-    0x78,
-    0x70,
-    0xF0,
-    0x78,
-    0xAC,
-    0xB1,
-    0x8F,
-    0x39,
-    0x31,
-    0xDB,
-    0x38,
-    0x61,
-    0xC3,
-    0xE,
-    0xE,
-    0x38,
-    0x78,
-    0x73,
-    0x17,
-    0x1E,
-    0x39,
-    0x1E,
-    0x38,
-    0x64,
-    0xE1,
-    0xF1,
-    0xC1
-    //200
-    ,
-    0x4E,
-    0xF,
-    0x40,
-    0xA2,
-    2,
-    0xC5,
-    0x8F,
-    0x81,
-    0xA1,
-    0xFC,
-    0x12,
-    8,
-    0x64,
-    0xE0,
-    0x3C,
-    0x22,
-    0xE0,
-    0x45,
-    7,
-    0x8E,
-    0xC,
-    0x32,
-    0x90,
-    0xF0,
-    0x1F,
-    0x20,
-    0x49,
-    0xE0,
-    0xF8,
-    0xC,
-    0x60,
-    0xF0
-    //220
-    ,
-    0x17,
-    0x1A,
-    0x41,
-    0xAA,
-    0xA4,
-    0xD0,
-    0x8D,
-    0x12,
-    0x82,
-    0x1E,
-    0x1E,
-    3,
-    0xF8,
-    0x3E,
-    3,
-    0xC,
-    0x73,
-    0x80,
-    0x70,
-    0x44,
-    0x26,
-    3,
-    0x24,
-    0xE1,
-    0x3E,
-    4,
-    0x4E,
-    4,
-    0x1C,
-    0xC1,
-    9,
-    0xCC
-    //240
-    ,
-    0x9E,
-    0x90,
-    0x21,
-    7,
-    0x90,
-    0x43,
-    0x64,
-    0xC0,
-    0xF,
-    0xC6,
-    0x90,
-    0x9C,
-    0xC1,
-    0x5B,
-    3,
-    0xE2,
-    0x1D,
-    0x81,
-    0xE0,
-    0x5E,
-    0x1D,
-    3,
-    0x84,
-    0xB8,
-    0x2C,
-    0xF,
-    0x80,
-    0xB1,
-    0x83,
-    0xE0,
-    0x30,
-    0x41
-    //260
-    ,
-    0x1E,
-    0x43,
-    0x89,
-    0x83,
-    0x50,
-    0xFC,
-    0x24,
-    0x2E,
-    0x13,
-    0x83,
-    0xF1,
-    0x7C,
-    0x4C,
-    0x2C,
-    0xC9,
-    0xD,
-    0x83,
-    0xB0,
-    0xB5,
-    0x82,
-    0xE4,
-    0xE8,
-    6,
-    0x9C,
-    7,
-    0xA0,
-    0x99,
-    0x1D,
-    7,
-    0x3E,
-    0x82,
-    0x8F
-    //280
-    ,
-    0x70,
-    0x30,
-    0x74,
-    0x40,
-    0xCA,
-    0x10,
-    0xE4,
-    0xE8,
-    0xF,
-    0x92,
-    0x14,
-    0x3F,
-    6,
-    0xF8,
-    0x84,
-    0x88,
-    0x43,
-    0x81,
-    0xA,
-    0x34,
-    0x39,
-    0x41,
-    0xC6,
-    0xE3,
-    0x1C,
-    0x47,
-    3,
-    0xB0,
-    0xB8,
-    0x13,
-    0xA,
-    0xC2
-    //2A0
-    ,
-    0x64,
-    0xF8,
-    0x18,
-    0xF9,
-    0x60,
-    0xB3,
-    0xC0,
-    0x65,
-    0x20,
-    0x60,
-    0xA6,
-    0x8C,
-    0xC3,
-    0x81,
-    0x20,
-    0x30,
-    0x26,
-    0x1E,
-    0x1C,
-    0x38,
-    0xD3,
-    1,
-    0xB0,
-    0x26,
-    0x40,
-    0xF4,
-    0xB,
-    0xC3,
-    0x42,
-    0x1F,
-    0x85,
-    0x32
-    //2C0
-    ,
-    0x26,
-    0x60,
-    0x40,
-    0xC9,
-    0xCB,
-    1,
-    0xEC,
-    0x11,
-    0x28,
-    0x40,
-    0xFA,
-    4,
-    0x34,
-    0xE0,
-    0x70,
-    0x4C,
-    0x8C,
-    0x1D,
-    7,
-    0x69,
-    3,
-    0x16,
-    0xC8,
-    4,
-    0x23,
-    0xE8,
-    0xC6,
-    0x9A,
-    0xB,
-    0x1A,
-    3,
-    0xE0
-    //2E0
-    ,
-    0x76,
-    6,
-    5,
-    0xCF,
-    0x1E,
-    0xBC,
-    0x58,
-    0x31,
-    0x71,
-    0x66,
-    0,
-    0xF8,
-    0x3F,
-    4,
-    0xFC,
-    0xC,
-    0x74,
-    0x27,
-    0x8A,
-    0x80,
-    0x71,
-    0xC2,
-    0x3A,
-    0x26,
-    6,
-    0xC0,
-    0x1F,
-    5,
-    0xF,
-    0x98,
-    0x40,
-    0xAE
-    //300
-    ,
-    1,
-    0x7F,
-    0xC0,
-    7,
-    0xFF,
-    0,
-    0xE,
-    0xFE,
-    0,
-    3,
-    0xDF,
-    0x80,
-    3,
-    0xEF,
-    0x80,
-    0x1B,
-    0xF1,
-    0xC2,
-    0,
-    0xE7,
-    0xE0,
-    0x18,
-    0xFC,
-    0xE0,
-    0x21,
-    0xFC,
-    0x80,
-    0x3C,
-    0xFC,
-    0x40,
-    0xE,
-    0x7E
-    //320
-    ,
-    0,
-    0x3F,
-    0x3E,
-    0,
-    0xF,
-    0xFE,
-    0,
-    0x1F,
-    0xFF,
-    0,
-    0x3E,
-    0xF0,
-    7,
-    0xFC,
-    0,
-    0x7E,
-    0x10,
-    0x3F,
-    0xFF,
-    0,
-    0x3F,
-    0x38,
-    0xE,
-    0x7C,
-    1,
-    0x87,
-    0xC,
-    0xFC,
-    0xC7,
-    0,
-    0x3E,
-    4
-    //340
-    ,
-    0xF,
-    0x3E,
-    0x1F,
-    0xF,
-    0xF,
-    0x1F,
-    0xF,
-    2,
-    0x83,
-    0x87,
-    0xCF,
-    3,
-    0x87,
-    0xF,
-    0x3F,
-    0xC0,
-    7,
-    0x9E,
-    0x60,
-    0x3F,
-    0xC0,
-    3,
-    0xFE,
-    0,
-    0x3F,
-    0xE0,
-    0x77,
-    0xE1,
-    0xC0,
-    0xFE,
-    0xE0,
-    0xC3
-    //360
-    ,
-    0xE0,
-    1,
-    0xDF,
-    0xF8,
-    3,
-    7,
-    0,
-    0x7E,
-    0x70,
-    0,
-    0x7C,
-    0x38,
-    0x18,
-    0xFE,
-    0xC,
-    0x1E,
-    0x78,
-    0x1C,
-    0x7C,
-    0x3E,
-    0xE,
-    0x1F,
-    0x1E,
-    0x1E,
-    0x3E,
-    0,
-    0x7F,
-    0x83,
-    7,
-    0xDB,
-    0x87,
-    0x83
-    //380
-    ,
-    7,
-    0xC7,
-    7,
-    0x10,
-    0x71,
-    0xFF,
-    0,
-    0x3F,
-    0xE2,
-    1,
-    0xE0,
-    0xC1,
-    0xC3,
-    0xE1,
-    0,
-    0x7F,
-    0xC0,
-    5,
-    0xF0,
-    0x20,
-    0xF8,
-    0xF0,
-    0x70,
-    0xFE,
-    0x78,
-    0x79,
-    0xF8,
-    2,
-    0x3F,
-    0xC,
-    0x8F,
-    3
-    //3a0
-    ,
-    0xF,
-    0x9F,
-    0xE0,
-    0xC1,
-    0xC7,
-    0x87,
-    3,
-    0xC3,
-    0xC3,
-    0xB0,
-    0xE1,
-    0xE1,
-    0xC1,
-    0xE3,
-    0xE0,
-    0x71,
-    0xF0,
-    0,
-    0xFC,
-    0x70,
-    0x7C,
-    0xC,
-    0x3E,
-    0x38,
-    0xE,
-    0x1C,
-    0x70,
-    0xC3,
-    0xC7,
-    3,
-    0x81,
-    0xC1
-    //3c0
-    ,
-    0xC7,
-    0xE7,
-    0,
-    0xF,
-    0xC7,
-    0x87,
-    0x19,
-    9,
-    0xEF,
-    0xC4,
-    0x33,
-    0xE0,
-    0xC1,
-    0xFC,
-    0xF8,
-    0x70,
-    0xF0,
-    0x78,
-    0xF8,
-    0xF0,
-    0x61,
-    0xC7,
-    0,
-    0x1F,
-    0xF8,
-    1,
-    0x7C,
-    0xF8,
-    0xF0,
-    0x78,
-    0x70,
-    0x3C
-    //3e0
-    ,
-    0x7C,
-    0xCE,
-    0xE,
-    0x21,
-    0x83,
-    0xCF,
-    8,
-    7,
-    0x8F,
-    8,
-    0xC1,
-    0x87,
-    0x8F,
-    0x80,
-    0xC7,
-    0xE3,
-    0,
-    7,
-    0xF8,
-    0xE0,
-    0xEF,
-    0,
-    0x39,
-    0xF7,
-    0x80,
-    0xE,
-    0xF8,
-    0xE1,
-    0xE3,
-    0xF8,
-    0x21,
-    0x9F
-    //400
-    ,
-    0xC0,
-    0xFF,
-    3,
-    0xF8,
-    7,
-    0xC0,
-    0x1F,
-    0xF8,
-    0xC4,
-    4,
-    0xFC,
-    0xC4,
-    0xC1,
-    0xBC,
-    0x87,
-    0xF0,
-    0xF,
-    0xC0,
-    0x7F,
-    5,
-    0xE0,
-    0x25,
-    0xEC,
-    0xC0,
-    0x3E,
-    0x84,
-    0x47,
-    0xF0,
-    0x8E,
-    3,
-    0xF8,
-    3
-    //420
-    ,
-    0xFB,
-    0xC0,
-    0x19,
-    0xF8,
-    7,
-    0x9C,
-    0xC,
-    0x17,
-    0xF8,
-    7,
-    0xE0,
-    0x1F,
-    0xA1,
-    0xFC,
-    0xF,
-    0xFC,
-    1,
-    0xF0,
-    0x3F,
-    0,
-    0xFE,
-    3,
-    0xF0,
-    0x1F,
-    0,
-    0xFD,
-    0,
-    0xFF,
-    0x88,
-    0xD,
-    0xF9,
-    1
-    //440
-    ,
-    0xFF,
-    0,
-    0x70,
-    7,
-    0xC0,
-    0x3E,
-    0x42,
-    0xF3,
-    0xD,
-    0xC4,
-    0x7F,
-    0x80,
-    0xFC,
-    7,
-    0xF0,
-    0x5E,
-    0xC0,
-    0x3F,
-    0,
-    0x78,
-    0x3F,
-    0x81,
-    0xFF,
-    1,
-    0xF8,
-    1,
-    0xC3,
-    0xE8,
-    0xC,
-    0xE4,
-    0x64,
-    0x8F
-    ////460
-    ,
-    0xE4,
-    0xF,
-    0xF0,
-    7,
-    0xF0,
-    0xC2,
-    0x1F,
-    0,
-    0x7F,
-    0xC0,
-    0x6F,
-    0x80,
-    0x7E,
-    3,
-    0xF8,
-    7,
-    0xF0,
-    0x3F,
-    0xC0,
-    0x78,
-    0xF,
-    0x82,
-    7,
-    0xFE,
-    0x22,
-    0x77,
-    0x70,
-    2,
-    0x76,
-    3,
-    0xFE,
-    0
-    //480
-    ,
-    0xFE,
-    0x67,
-    0,
-    0x7C,
-    0xC7,
-    0xF1,
-    0x8E,
-    0xC6,
-    0x3B,
-    0xE0,
-    0x3F,
-    0x84,
-    0xF3,
-    0x19,
-    0xD8,
-    3,
-    0x99,
-    0xFC,
-    9,
-    0xB8,
-    0xF,
-    0xF8,
-    0,
-    0x9D,
-    0x24,
-    0x61,
-    0xF9,
-    0xD,
-    0,
-    0xFD,
-    3,
-    0xF0
-    //4a0
-    ,
-    0x1F,
-    0x90,
-    0x3F,
-    1,
-    0xF8,
-    0x1F,
-    0xD0,
-    0xF,
-    0xF8,
-    0x37,
-    1,
-    0xF8,
-    7,
-    0xF0,
-    0xF,
-    0xC0,
-    0x3F,
-    0,
-    0xFE,
-    3,
-    0xF8,
-    0xF,
-    0xC0,
-    0x3F,
-    0,
-    0xFA,
-    3,
-    0xF0,
-    0xF,
-    0x80,
-    0xFF,
-    1
-    //4c0
-    ,
-    0xB8,
-    7,
-    0xF0,
-    1,
-    0xFC,
-    1,
-    0xBC,
-    0x80,
-    0x13,
-    0x1E,
-    0,
-    0x7F,
-    0xE1,
-    0x40,
-    0x7F,
-    0xA0,
-    0x7F,
-    0xB0,
-    0,
-    0x3F,
-    0xC0,
-    0x1F,
-    0xC0,
-    0x38,
-    0xF,
-    0xF0,
-    0x1F,
-    0x80,
-    0xFF,
-    1,
-    0xFC,
-    3
-    //4e0
-    ,
-    0xF1,
-    0x7E,
-    1,
-    0xFE,
-    1,
-    0xF0,
-    0xFF,
-    0,
-    0x7F,
-    0xC0,
-    0x1D,
-    7,
-    0xF0,
-    0xF,
-    0xC0,
-    0x7E,
-    6,
-    0xE0,
-    7,
-    0xE0,
-    0xF,
-    0xF8,
-    6,
-    0xC1,
-    0xFE,
-    1,
-    0xFC,
-    3,
-    0xE0,
-    0xF,
-    0,
-    0xFC};
-
-////////////////////////////////////////////////////////////////////////////////////////////
-//
-//           Render
-//
-////////////////////////////////////////////////////////////////////////////////////////////
-
-unsigned char pitches[256]; // tab43008
-
-unsigned char frequency1[256];
-unsigned char frequency2[256];
-unsigned char frequency3[256];
-
-unsigned char amplitude1[256];
-unsigned char amplitude2[256];
-unsigned char amplitude3[256];
-
-unsigned char sampledConsonantFlag[256]; // tab44800
-
-////////////////////////////////////////////////////////////////////////////////////////////
-//
-//           Sam
-//
-////////////////////////////////////////////////////////////////////////////////////////////
-
-unsigned char stress[256]; //numbers from 0 to 8
-unsigned char phonemeLength[256]; //tab40160
-unsigned char phonemeindex[256];
-
-////////////////////////////////////////////////////////////////////////////////////////////
-//
-//           ReciterTabs
-//
-////////////////////////////////////////////////////////////////////////////////////////////
-
-//some flags
-const unsigned char tab36376[] = {
-    0,   0,   0,   0,   0,   0,   0,   0, // 0-7
-    0,   0,   0,   0,   0,   0,   0,   0, // 8-15
-    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-    0,   2,   2,   2,   2,   2,   2,   130, // ' ', '!'
-    0,   0,   2,   2,   2,   2,   2,   2,   3,   3,   3,   3,   3,   3,   3,   3,
-    3,   3,   2,   2,   2,   2,   2,   2,   2,   192, 168, 176, 172, 192, 160, 184, // '@', 'A'
-    160, 192, 188, 160, 172, 168, 172, 192, 160, 160, 172, 180, 164, 192, 168, 168,
-    176, 192, 188, 0,   0,   0,   2,   0, // 'X', 'Y', 'Z', '[',
-    32,  32,  155, 32,  192, 185, 32,  205, 163, 76,  138, 142};
-
-const unsigned char rules[] = {
-    ']',        'A' | 0x80, ' ',        '(',        'A',        '.',        ')',        '=',
-    'E',        'H',        '4',        'Y',        '.',        ' ' | 0x80, '(',        'A',
-    ')',        ' ',        '=',        'A',        'H' | 0x80, ' ',        '(',        'A',
-    'R',        'E',        ')',        ' ',        '=',        'A',        'A',        'R' | 0x80,
-    ' ',        '(',        'A',        'R',        ')',        'O',        '=',        'A',
-    'X',        'R' | 0x80, '(',        'A',        'R',        ')',        '#',        '=',
-    'E',        'H',        '4',        'R' | 0x80, ' ',        '^',        '(',        'A',
-    'S',        ')',        '#',        '=',        'E',        'Y',        '4',        'S' | 0x80,
-    '(',        'A',        ')',        'W',        'A',        '=',        'A',        'X' | 0x80,
-    '(',        'A',        'W',        ')',        '=',        'A',        'O',        '5' | 0x80,
-    ' ',        ':',        '(',        'A',        'N',        'Y',        ')',        '=',
-    'E',        'H',        '4',        'N',        'I',        'Y' | 0x80, '(',        'A',
-    ')',        '^',        '+',        '#',        '=',        'E',        'Y',        '5' | 0x80,
-    '#',        ':',        '(',        'A',        'L',        'L',        'Y',        ')',
-    '=',        'U',        'L',        'I',        'Y' | 0x80, ' ',        '(',        'A',
-    'L',        ')',        '#',        '=',        'U',        'L' | 0x80, '(',        'A',
-    'G',        'A',        'I',        'N',        ')',        '=',        'A',        'X',
-    'G',        'E',        'H',        '4',        'N' | 0x80, '#',        ':',        '(',
-    'A',        'G',        ')',        'E',        '=',        'I',        'H',        'J' | 0x80,
-    '(',        'A',        ')',        '^',        '%',        '=',        'E',        'Y' | 0x80,
-    '(',        'A',        ')',        '^',        '+',        ':',        '#',        '=',
-    'A',        'E' | 0x80, ' ',        ':',        '(',        'A',        ')',        '^',
-    '+',        ' ',        '=',        'E',        'Y',        '4' | 0x80, ' ',        '(',
-    'A',        'R',        'R',        ')',        '=',        'A',        'X',        'R' | 0x80,
-    '(',        'A',        'R',        'R',        ')',        '=',        'A',        'E',
-    '4',        'R' | 0x80, ' ',        '^',        '(',        'A',        'R',        ')',
-    ' ',        '=',        'A',        'A',        '5',        'R' | 0x80, '(',        'A',
-    'R',        ')',        '=',        'A',        'A',        '5',        'R' | 0x80, '(',
-    'A',        'I',        'R',        ')',        '=',        'E',        'H',        '4',
-    'R' | 0x80, '(',        'A',        'I',        ')',        '=',        'E',        'Y',
-    '4' | 0x80, '(',        'A',        'Y',        ')',        '=',        'E',        'Y',
-    '5' | 0x80, '(',        'A',        'U',        ')',        '=',        'A',        'O',
-    '4' | 0x80, '#',        ':',        '(',        'A',        'L',        ')',        ' ',
-    '=',        'U',        'L' | 0x80, '#',        ':',        '(',        'A',        'L',
-    'S',        ')',        ' ',        '=',        'U',        'L',        'Z' | 0x80, '(',
-    'A',        'L',        'K',        ')',        '=',        'A',        'O',        '4',
-    'K' | 0x80, '(',        'A',        'L',        ')',        '^',        '=',        'A',
-    'O',        'L' | 0x80, ' ',        ':',        '(',        'A',        'B',        'L',
-    'E',        ')',        '=',        'E',        'Y',        '4',        'B',        'U',
-    'L' | 0x80, '(',        'A',        'B',        'L',        'E',        ')',        '=',
-    'A',        'X',        'B',        'U',        'L' | 0x80, '(',        'A',        ')',
-    'V',        'O',        '=',        'E',        'Y',        '4' | 0x80, '(',        'A',
-    'N',        'G',        ')',        '+',        '=',        'E',        'Y',        '4',
-    'N',        'J' | 0x80, '(',        'A',        'T',        'A',        'R',        'I',
-    ')',        '=',        'A',        'H',        'T',        'A',        'A',        '4',
-    'R',        'I',        'Y' | 0x80, '(',        'A',        ')',        'T',        'O',
-    'M',        '=',        'A',        'E' | 0x80, '(',        'A',        ')',        'T',
-    'T',        'I',        '=',        'A',        'E' | 0x80, ' ',        '(',        'A',
-    'T',        ')',        ' ',        '=',        'A',        'E',        'T' | 0x80, ' ',
-    '(',        'A',        ')',        'T',        '=',        'A',        'H' | 0x80, '(',
-    'A',        ')',        '=',        'A',        'E' | 0x80,
-
-    ']',        'B' | 0x80, ' ',        '(',        'B',        ')',        ' ',        '=',
-    'B',        'I',        'Y',        '4' | 0x80, ' ',        '(',        'B',        'E',
-    ')',        '^',        '#',        '=',        'B',        'I',        'H' | 0x80, '(',
-    'B',        'E',        'I',        'N',        'G',        ')',        '=',        'B',
-    'I',        'Y',        '4',        'I',        'H',        'N',        'X' | 0x80, ' ',
-    '(',        'B',        'O',        'T',        'H',        ')',        ' ',        '=',
-    'B',        'O',        'W',        '4',        'T',        'H' | 0x80, ' ',        '(',
-    'B',        'U',        'S',        ')',        '#',        '=',        'B',        'I',
-    'H',        '4',        'Z' | 0x80, '(',        'B',        'R',        'E',        'A',
-    'K',        ')',        '=',        'B',        'R',        'E',        'Y',        '5',
-    'K' | 0x80, '(',        'B',        'U',        'I',        'L',        ')',        '=',
-    'B',        'I',        'H',        '4',        'L' | 0x80, '(',        'B',        ')',
-    '=',        'B' | 0x80,
-
-    ']',        'C' | 0x80, ' ',        '(',        'C',        ')',        ' ',        '=',
-    'S',        'I',        'Y',        '4' | 0x80, ' ',        '(',        'C',        'H',
-    ')',        '^',        '=',        'K' | 0x80, '^',        'E',        '(',        'C',
-    'H',        ')',        '=',        'K' | 0x80, '(',        'C',        'H',        'A',
-    ')',        'R',        '#',        '=',        'K',        'E',        'H',        '5' | 0x80,
-    '(',        'C',        'H',        ')',        '=',        'C',        'H' | 0x80, ' ',
-    'S',        '(',        'C',        'I',        ')',        '#',        '=',        'S',
-    'A',        'Y',        '4' | 0x80, '(',        'C',        'I',        ')',        'A',
-    '=',        'S',        'H' | 0x80, '(',        'C',        'I',        ')',        'O',
-    '=',        'S',        'H' | 0x80, '(',        'C',        'I',        ')',        'E',
-    'N',        '=',        'S',        'H' | 0x80, '(',        'C',        'I',        'T',
-    'Y',        ')',        '=',        'S',        'I',        'H',        'T',        'I',
-    'Y' | 0x80, '(',        'C',        ')',        '+',        '=',        'S' | 0x80, '(',
-    'C',        'K',        ')',        '=',        'K' | 0x80, '(',        'C',        'O',
-    'M',        'M',        'O',        'D',        'O',        'R',        'E',        ')',
-    '=',        'K',        'A',        'A',        '4',        'M',        'A',        'H',
-    'D',        'O',        'H',        'R' | 0x80, '(',        'C',        'O',        'M',
-    ')',        '=',        'K',        'A',        'H',        'M' | 0x80, '(',        'C',
-    'U',        'I',        'T',        ')',        '=',        'K',        'I',        'H',
-    'T' | 0x80, '(',        'C',        'R',        'E',        'A',        ')',        '=',
-    'K',        'R',        'I',        'Y',        'E',        'Y' | 0x80, '(',        'C',
-    ')',        '=',        'K' | 0x80,
-
-    ']',        'D' | 0x80, ' ',        '(',        'D',        ')',        ' ',        '=',
-    'D',        'I',        'Y',        '4' | 0x80, ' ',        '(',        'D',        'R',
-    '.',        ')',        ' ',        '=',        'D',        'A',        'A',        '4',
-    'K',        'T',        'E',        'R' | 0x80, '#',        ':',        '(',        'D',
-    'E',        'D',        ')',        ' ',        '=',        'D',        'I',        'H',
-    'D' | 0x80, '.',        'E',        '(',        'D',        ')',        ' ',        '=',
-    'D' | 0x80, '#',        ':',        '^',        'E',        '(',        'D',        ')',
-    ' ',        '=',        'T' | 0x80, ' ',        '(',        'D',        'E',        ')',
-    '^',        '#',        '=',        'D',        'I',        'H' | 0x80, ' ',        '(',
-    'D',        'O',        ')',        ' ',        '=',        'D',        'U',        'W' | 0x80,
-    ' ',        '(',        'D',        'O',        'E',        'S',        ')',        '=',
-    'D',        'A',        'H',        'Z' | 0x80, '(',        'D',        'O',        'N',
-    'E',        ')',        ' ',        '=',        'D',        'A',        'H',        '5',
-    'N' | 0x80, '(',        'D',        'O',        'I',        'N',        'G',        ')',
-    '=',        'D',        'U',        'W',        '4',        'I',        'H',        'N',
-    'X' | 0x80, ' ',        '(',        'D',        'O',        'W',        ')',        '=',
-    'D',        'A',        'W' | 0x80, '#',        '(',        'D',        'U',        ')',
-    'A',        '=',        'J',        'U',        'W' | 0x80, '#',        '(',        'D',
-    'U',        ')',        '^',        '#',        '=',        'J',        'A',        'X' | 0x80,
-    '(',        'D',        ')',        '=',        'D' | 0x80,
-
-    ']',        'E' | 0x80, ' ',        '(',        'E',        ')',        ' ',        '=',
-    'I',        'Y',        'I',        'Y',        '4' | 0x80, '#',        ':',        '(',
-    'E',        ')',        ' ',        '=' | 0x80, '\'',       ':',        '^',        '(',
-    'E',        ')',        ' ',        '=' | 0x80, ' ',        ':',        '(',        'E',
-    ')',        ' ',        '=',        'I',        'Y' | 0x80, '#',        '(',        'E',
-    'D',        ')',        ' ',        '=',        'D' | 0x80, '#',        ':',        '(',
-    'E',        ')',        'D',        ' ',        '=' | 0x80, '(',        'E',        'V',
-    ')',        'E',        'R',        '=',        'E',        'H',        '4',        'V' | 0x80,
-    '(',        'E',        ')',        '^',        '%',        '=',        'I',        'Y',
-    '4' | 0x80, '(',        'E',        'R',        'I',        ')',        '#',        '=',
-    'I',        'Y',        '4',        'R',        'I',        'Y' | 0x80, '(',        'E',
-    'R',        'I',        ')',        '=',        'E',        'H',        '4',        'R',
-    'I',        'H' | 0x80, '#',        ':',        '(',        'E',        'R',        ')',
-    '#',        '=',        'E',        'R' | 0x80, '(',        'E',        'R',        'R',
-    'O',        'R',        ')',        '=',        'E',        'H',        '4',        'R',
-    'O',        'H',        'R' | 0x80, '(',        'E',        'R',        'A',        'S',
-    'E',        ')',        '=',        'I',        'H',        'R',        'E',        'Y',
-    '5',        'S' | 0x80, '(',        'E',        'R',        ')',        '#',        '=',
-    'E',        'H',        'R' | 0x80, '(',        'E',        'R',        ')',        '=',
-    'E',        'R' | 0x80, ' ',        '(',        'E',        'V',        'E',        'N',
-    ')',        '=',        'I',        'Y',        'V',        'E',        'H',        'N' | 0x80,
-    '#',        ':',        '(',        'E',        ')',        'W',        '=' | 0x80, '@',
-    '(',        'E',        'W',        ')',        '=',        'U',        'W' | 0x80, '(',
-    'E',        'W',        ')',        '=',        'Y',        'U',        'W' | 0x80, '(',
-    'E',        ')',        'O',        '=',        'I',        'Y' | 0x80, '#',        ':',
-    '&',        '(',        'E',        'S',        ')',        ' ',        '=',        'I',
-    'H',        'Z' | 0x80, '#',        ':',        '(',        'E',        ')',        'S',
-    ' ',        '=' | 0x80, '#',        ':',        '(',        'E',        'L',        'Y',
-    ')',        ' ',        '=',        'L',        'I',        'Y' | 0x80, '#',        ':',
-    '(',        'E',        'M',        'E',        'N',        'T',        ')',        '=',
-    'M',        'E',        'H',        'N',        'T' | 0x80, '(',        'E',        'F',
-    'U',        'L',        ')',        '=',        'F',        'U',        'H',        'L' | 0x80,
-    '(',        'E',        'E',        ')',        '=',        'I',        'Y',        '4' | 0x80,
-    '(',        'E',        'A',        'R',        'N',        ')',        '=',        'E',
-    'R',        '5',        'N' | 0x80, ' ',        '(',        'E',        'A',        'R',
-    ')',        '^',        '=',        'E',        'R',        '5' | 0x80, '(',        'E',
-    'A',        'D',        ')',        '=',        'E',        'H',        'D' | 0x80, '#',
-    ':',        '(',        'E',        'A',        ')',        ' ',        '=',        'I',
-    'Y',        'A',        'X' | 0x80, '(',        'E',        'A',        ')',        'S',
-    'U',        '=',        'E',        'H',        '5' | 0x80, '(',        'E',        'A',
-    ')',        '=',        'I',        'Y',        '5' | 0x80, '(',        'E',        'I',
-    'G',        'H',        ')',        '=',        'E',        'Y',        '4' | 0x80, '(',
-    'E',        'I',        ')',        '=',        'I',        'Y',        '4' | 0x80, ' ',
-    '(',        'E',        'Y',        'E',        ')',        '=',        'A',        'Y',
-    '4' | 0x80, '(',        'E',        'Y',        ')',        '=',        'I',        'Y' | 0x80,
-    '(',        'E',        'U',        ')',        '=',        'Y',        'U',        'W',
-    '5' | 0x80, '(',        'E',        'Q',        'U',        'A',        'L',        ')',
-    '=',        'I',        'Y',        '4',        'K',        'W',        'U',        'L' | 0x80,
-    '(',        'E',        ')',        '=',        'E',        'H' | 0x80,
-
-    ']',        'F' | 0x80, ' ',        '(',        'F',        ')',        ' ',        '=',
-    'E',        'H',        '4',        'F' | 0x80, '(',        'F',        'U',        'L',
-    ')',        '=',        'F',        'U',        'H',        'L' | 0x80, '(',        'F',
-    'R',        'I',        'E',        'N',        'D',        ')',        '=',        'F',
-    'R',        'E',        'H',        '5',        'N',        'D' | 0x80, '(',        'F',
-    'A',        'T',        'H',        'E',        'R',        ')',        '=',        'F',
-    'A',        'A',        '4',        'D',        'H',        'E',        'R' | 0x80, '(',
-    'F',        ')',        'F',        '=' | 0x80, '(',        'F',        ')',        '=',
-    'F' | 0x80,
-
-    ']',        'G' | 0x80, ' ',        '(',        'G',        ')',        ' ',        '=',
-    'J',        'I',        'Y',        '4' | 0x80, '(',        'G',        'I',        'V',
-    ')',        '=',        'G',        'I',        'H',        '5',        'V' | 0x80, ' ',
-    '(',        'G',        ')',        'I',        '^',        '=',        'G' | 0x80, '(',
-    'G',        'E',        ')',        'T',        '=',        'G',        'E',        'H',
-    '5' | 0x80, 'S',        'U',        '(',        'G',        'G',        'E',        'S',
-    ')',        '=',        'G',        'J',        'E',        'H',        '4',        'S' | 0x80,
-    '(',        'G',        'G',        ')',        '=',        'G' | 0x80, ' ',        'B',
-    '#',        '(',        'G',        ')',        '=',        'G' | 0x80, '(',        'G',
-    ')',        '+',        '=',        'J' | 0x80, '(',        'G',        'R',        'E',
-    'A',        'T',        ')',        '=',        'G',        'R',        'E',        'Y',
-    '4',        'T' | 0x80, '(',        'G',        'O',        'N',        ')',        'E',
-    '=',        'G',        'A',        'O',        '5',        'N' | 0x80, '#',        '(',
-    'G',        'H',        ')',        '=' | 0x80, ' ',        '(',        'G',        'N',
-    ')',        '=',        'N' | 0x80, '(',        'G',        ')',        '=',        'G' | 0x80,
-
-    ']',        'H' | 0x80, ' ',        '(',        'H',        ')',        ' ',        '=',
-    'E',        'Y',        '4',        'C',        'H' | 0x80, ' ',        '(',        'H',
-    'A',        'V',        ')',        '=',        '/',        'H',        'A',        'E',
-    '6',        'V' | 0x80, ' ',        '(',        'H',        'E',        'R',        'E',
-    ')',        '=',        '/',        'H',        'I',        'Y',        'R' | 0x80, ' ',
-    '(',        'H',        'O',        'U',        'R',        ')',        '=',        'A',
-    'W',        '5',        'E',        'R' | 0x80, '(',        'H',        'O',        'W',
-    ')',        '=',        '/',        'H',        'A',        'W' | 0x80, '(',        'H',
-    ')',        '#',        '=',        '/',        'H' | 0x80, '(',        'H',        ')',
-    '=' | 0x80,
-
-    ']',        'I' | 0x80, ' ',        '(',        'I',        'N',        ')',        '=',
-    'I',        'H',        'N' | 0x80, ' ',        '(',        'I',        ')',        ' ',
-    '=',        'A',        'Y',        '4' | 0x80, '(',        'I',        ')',        ' ',
-    '=',        'A',        'Y' | 0x80, '(',        'I',        'N',        ')',        'D',
-    '=',        'A',        'Y',        '5',        'N' | 0x80, 'S',        'E',        'M',
-    '(',        'I',        ')',        '=',        'I',        'Y' | 0x80, ' ',        'A',
-    'N',        'T',        '(',        'I',        ')',        '=',        'A',        'Y' | 0x80,
-    '(',        'I',        'E',        'R',        ')',        '=',        'I',        'Y',
-    'E',        'R' | 0x80, '#',        ':',        'R',        '(',        'I',        'E',
-    'D',        ')',        ' ',        '=',        'I',        'Y',        'D' | 0x80, '(',
-    'I',        'E',        'D',        ')',        ' ',        '=',        'A',        'Y',
-    '5',        'D' | 0x80, '(',        'I',        'E',        'N',        ')',        '=',
-    'I',        'Y',        'E',        'H',        'N' | 0x80, '(',        'I',        'E',
-    ')',        'T',        '=',        'A',        'Y',        '4',        'E',        'H' | 0x80,
-    '(',        'I',        '\'',       ')',        '=',        'A',        'Y',        '5' | 0x80,
-    ' ',        ':',        '(',        'I',        ')',        '^',        '%',        '=',
-    'A',        'Y',        '5' | 0x80, ' ',        ':',        '(',        'I',        'E',
-    ')',        ' ',        '=',        'A',        'Y',        '4' | 0x80, '(',        'I',
-    ')',        '%',        '=',        'I',        'Y' | 0x80, '(',        'I',        'E',
-    ')',        '=',        'I',        'Y',        '4' | 0x80, ' ',        '(',        'I',
-    'D',        'E',        'A',        ')',        '=',        'A',        'Y',        'D',
-    'I',        'Y',        '5',        'A',        'H' | 0x80, '(',        'I',        ')',
-    '^',        '+',        ':',        '#',        '=',        'I',        'H' | 0x80, '(',
-    'I',        'R',        ')',        '#',        '=',        'A',        'Y',        'R' | 0x80,
-    '(',        'I',        'Z',        ')',        '%',        '=',        'A',        'Y',
-    'Z' | 0x80, '(',        'I',        'S',        ')',        '%',        '=',        'A',
-    'Y',        'Z' | 0x80, 'I',        '^',        '(',        'I',        ')',        '^',
-    '#',        '=',        'I',        'H' | 0x80, '+',        '^',        '(',        'I',
-    ')',        '^',        '+',        '=',        'A',        'Y' | 0x80, '#',        ':',
-    '^',        '(',        'I',        ')',        '^',        '+',        '=',        'I',
-    'H' | 0x80, '(',        'I',        ')',        '^',        '+',        '=',        'A',
-    'Y' | 0x80, '(',        'I',        'R',        ')',        '=',        'E',        'R' | 0x80,
-    '(',        'I',        'G',        'H',        ')',        '=',        'A',        'Y',
-    '4' | 0x80, '(',        'I',        'L',        'D',        ')',        '=',        'A',
-    'Y',        '5',        'L',        'D' | 0x80, ' ',        '(',        'I',        'G',
-    'N',        ')',        '=',        'I',        'H',        'G',        'N' | 0x80, '(',
-    'I',        'G',        'N',        ')',        ' ',        '=',        'A',        'Y',
-    '4',        'N' | 0x80, '(',        'I',        'G',        'N',        ')',        '^',
-    '=',        'A',        'Y',        '4',        'N' | 0x80, '(',        'I',        'G',
-    'N',        ')',        '%',        '=',        'A',        'Y',        '4',        'N' | 0x80,
-    '(',        'I',        'C',        'R',        'O',        ')',        '=',        'A',
-    'Y',        '4',        'K',        'R',        'O',        'H' | 0x80, '(',        'I',
-    'Q',        'U',        'E',        ')',        '=',        'I',        'Y',        '4',
-    'K' | 0x80, '(',        'I',        ')',        '=',        'I',        'H' | 0x80,
-
-    ']',        'J' | 0x80, ' ',        '(',        'J',        ')',        ' ',        '=',
-    'J',        'E',        'Y',        '4' | 0x80, '(',        'J',        ')',        '=',
-    'J' | 0x80,
-
-    ']',        'K' | 0x80, ' ',        '(',        'K',        ')',        ' ',        '=',
-    'K',        'E',        'Y',        '4' | 0x80, ' ',        '(',        'K',        ')',
-    'N',        '=' | 0x80, '(',        'K',        ')',        '=',        'K' | 0x80,
-
-    ']',        'L' | 0x80, ' ',        '(',        'L',        ')',        ' ',        '=',
-    'E',        'H',        '4',        'L' | 0x80, '(',        'L',        'O',        ')',
-    'C',        '#',        '=',        'L',        'O',        'W' | 0x80, 'L',        '(',
-    'L',        ')',        '=' | 0x80, '#',        ':',        '^',        '(',        'L',
-    ')',        '%',        '=',        'U',        'L' | 0x80, '(',        'L',        'E',
-    'A',        'D',        ')',        '=',        'L',        'I',        'Y',        'D' | 0x80,
-    ' ',        '(',        'L',        'A',        'U',        'G',        'H',        ')',
-    '=',        'L',        'A',        'E',        '4',        'F' | 0x80, '(',        'L',
-    ')',        '=',        'L' | 0x80,
-
-    ']',        'M' | 0x80, ' ',        '(',        'M',        ')',        ' ',        '=',
-    'E',        'H',        '4',        'M' | 0x80, ' ',        '(',        'M',        'R',
-    '.',        ')',        ' ',        '=',        'M',        'I',        'H',        '4',
-    'S',        'T',        'E',        'R' | 0x80, ' ',        '(',        'M',        'S',
-    '.',        ')',        '=',        'M',        'I',        'H',        '5',        'Z' | 0x80,
-    ' ',        '(',        'M',        'R',        'S',        '.',        ')',        ' ',
-    '=',        'M',        'I',        'H',        '4',        'S',        'I',        'X',
-    'Z' | 0x80, '(',        'M',        'O',        'V',        ')',        '=',        'M',
-    'U',        'W',        '4',        'V' | 0x80, '(',        'M',        'A',        'C',
-    'H',        'I',        'N',        ')',        '=',        'M',        'A',        'H',
-    'S',        'H',        'I',        'Y',        '5',        'N' | 0x80, 'M',        '(',
-    'M',        ')',        '=' | 0x80, '(',        'M',        ')',        '=',        'M' | 0x80,
-
-    ']',        'N' | 0x80, ' ',        '(',        'N',        ')',        ' ',        '=',
-    'E',        'H',        '4',        'N' | 0x80, 'E',        '(',        'N',        'G',
-    ')',        '+',        '=',        'N',        'J' | 0x80, '(',        'N',        'G',
-    ')',        'R',        '=',        'N',        'X',        'G' | 0x80, '(',        'N',
-    'G',        ')',        '#',        '=',        'N',        'X',        'G' | 0x80, '(',
-    'N',        'G',        'L',        ')',        '%',        '=',        'N',        'X',
-    'G',        'U',        'L' | 0x80, '(',        'N',        'G',        ')',        '=',
-    'N',        'X' | 0x80, '(',        'N',        'K',        ')',        '=',        'N',
-    'X',        'K' | 0x80, ' ',        '(',        'N',        'O',        'W',        ')',
-    ' ',        '=',        'N',        'A',        'W',        '4' | 0x80, 'N',        '(',
-    'N',        ')',        '=' | 0x80, '(',        'N',        'O',        'N',        ')',
-    'E',        '=',        'N',        'A',        'H',        '4',        'N' | 0x80, '(',
-    'N',        ')',        '=',        'N' | 0x80,
-
-    ']',        'O' | 0x80, ' ',        '(',        'O',        ')',        ' ',        '=',
-    'O',        'H',        '4',        'W' | 0x80, '(',        'O',        'F',        ')',
-    ' ',        '=',        'A',        'H',        'V' | 0x80, ' ',        '(',        'O',
-    'H',        ')',        ' ',        '=',        'O',        'W',        '5' | 0x80, '(',
-    'O',        'R',        'O',        'U',        'G',        'H',        ')',        '=',
-    'E',        'R',        '4',        'O',        'W' | 0x80, '#',        ':',        '(',
-    'O',        'R',        ')',        ' ',        '=',        'E',        'R' | 0x80, '#',
-    ':',        '(',        'O',        'R',        'S',        ')',        ' ',        '=',
-    'E',        'R',        'Z' | 0x80, '(',        'O',        'R',        ')',        '=',
-    'A',        'O',        'R' | 0x80, ' ',        '(',        'O',        'N',        'E',
-    ')',        '=',        'W',        'A',        'H',        'N' | 0x80, '#',        '(',
-    'O',        'N',        'E',        ')',        ' ',        '=',        'W',        'A',
-    'H',        'N' | 0x80, '(',        'O',        'W',        ')',        '=',        'O',
-    'W' | 0x80, ' ',        '(',        'O',        'V',        'E',        'R',        ')',
-    '=',        'O',        'W',        '5',        'V',        'E',        'R' | 0x80, 'P',
-    'R',        '(',        'O',        ')',        'V',        '=',        'U',        'W',
-    '4' | 0x80, '(',        'O',        'V',        ')',        '=',        'A',        'H',
-    '4',        'V' | 0x80, '(',        'O',        ')',        '^',        '%',        '=',
-    'O',        'W',        '5' | 0x80, '(',        'O',        ')',        '^',        'E',
-    'N',        '=',        'O',        'W' | 0x80, '(',        'O',        ')',        '^',
-    'I',        '#',        '=',        'O',        'W',        '5' | 0x80, '(',        'O',
-    'L',        ')',        'D',        '=',        'O',        'W',        '4',        'L' | 0x80,
-    '(',        'O',        'U',        'G',        'H',        'T',        ')',        '=',
-    'A',        'O',        '5',        'T' | 0x80, '(',        'O',        'U',        'G',
-    'H',        ')',        '=',        'A',        'H',        '5',        'F' | 0x80, ' ',
-    '(',        'O',        'U',        ')',        '=',        'A',        'W' | 0x80, 'H',
-    '(',        'O',        'U',        ')',        'S',        '#',        '=',        'A',
-    'W',        '4' | 0x80, '(',        'O',        'U',        'S',        ')',        '=',
-    'A',        'X',        'S' | 0x80, '(',        'O',        'U',        'R',        ')',
-    '=',        'O',        'H',        'R' | 0x80, '(',        'O',        'U',        'L',
-    'D',        ')',        '=',        'U',        'H',        '5',        'D' | 0x80, '(',
-    'O',        'U',        ')',        '^',        'L',        '=',        'A',        'H',
-    '5' | 0x80, '(',        'O',        'U',        'P',        ')',        '=',        'U',
-    'W',        '5',        'P' | 0x80, '(',        'O',        'U',        ')',        '=',
-    'A',        'W' | 0x80, '(',        'O',        'Y',        ')',        '=',        'O',
-    'Y' | 0x80, '(',        'O',        'I',        'N',        'G',        ')',        '=',
-    'O',        'W',        '4',        'I',        'H',        'N',        'X' | 0x80, '(',
-    'O',        'I',        ')',        '=',        'O',        'Y',        '5' | 0x80, '(',
-    'O',        'O',        'R',        ')',        '=',        'O',        'H',        '5',
-    'R' | 0x80, '(',        'O',        'O',        'K',        ')',        '=',        'U',
-    'H',        '5',        'K' | 0x80, 'F',        '(',        'O',        'O',        'D',
-    ')',        '=',        'U',        'W',        '5',        'D' | 0x80, 'L',        '(',
-    'O',        'O',        'D',        ')',        '=',        'A',        'H',        '5',
-    'D' | 0x80, 'M',        '(',        'O',        'O',        'D',        ')',        '=',
-    'U',        'W',        '5',        'D' | 0x80, '(',        'O',        'O',        'D',
-    ')',        '=',        'U',        'H',        '5',        'D' | 0x80, 'F',        '(',
-    'O',        'O',        'T',        ')',        '=',        'U',        'H',        '5',
-    'T' | 0x80, '(',        'O',        'O',        ')',        '=',        'U',        'W',
-    '5' | 0x80, '(',        'O',        '\'',       ')',        '=',        'O',        'H' | 0x80,
-    '(',        'O',        ')',        'E',        '=',        'O',        'W' | 0x80, '(',
-    'O',        ')',        ' ',        '=',        'O',        'W' | 0x80, '(',        'O',
-    'A',        ')',        '=',        'O',        'W',        '4' | 0x80, ' ',        '(',
-    'O',        'N',        'L',        'Y',        ')',        '=',        'O',        'W',
-    '4',        'N',        'L',        'I',        'Y' | 0x80, ' ',        '(',        'O',
-    'N',        'C',        'E',        ')',        '=',        'W',        'A',        'H',
-    '4',        'N',        'S' | 0x80, '(',        'O',        'N',        '\'',       'T',
-    ')',        '=',        'O',        'W',        '4',        'N',        'T' | 0x80, 'C',
-    '(',        'O',        ')',        'N',        '=',        'A',        'A' | 0x80, '(',
-    'O',        ')',        'N',        'G',        '=',        'A',        'O' | 0x80, ' ',
-    ':',        '^',        '(',        'O',        ')',        'N',        '=',        'A',
-    'H' | 0x80, 'I',        '(',        'O',        'N',        ')',        '=',        'U',
-    'N' | 0x80, '#',        ':',        '(',        'O',        'N',        ')',        '=',
-    'U',        'N' | 0x80, '#',        '^',        '(',        'O',        'N',        ')',
-    '=',        'U',        'N' | 0x80, '(',        'O',        ')',        'S',        'T',
-    '=',        'O',        'W' | 0x80, '(',        'O',        'F',        ')',        '^',
-    '=',        'A',        'O',        '4',        'F' | 0x80, '(',        'O',        'T',
-    'H',        'E',        'R',        ')',        '=',        'A',        'H',        '5',
-    'D',        'H',        'E',        'R' | 0x80, 'R',        '(',        'O',        ')',
-    'B',        '=',        'R',        'A',        'A' | 0x80, '^',        'R',        '(',
-    'O',        ')',        ':',        '#',        '=',        'O',        'W',        '5' | 0x80,
-    '(',        'O',        'S',        'S',        ')',        ' ',        '=',        'A',
-    'O',        '5',        'S' | 0x80, '#',        ':',        '^',        '(',        'O',
-    'M',        ')',        '=',        'A',        'H',        'M' | 0x80, '(',        'O',
-    ')',        '=',        'A',        'A' | 0x80,
-
-    ']',        'P' | 0x80, ' ',        '(',        'P',        ')',        ' ',        '=',
-    'P',        'I',        'Y',        '4' | 0x80, '(',        'P',        'H',        ')',
-    '=',        'F' | 0x80, '(',        'P',        'E',        'O',        'P',        'L',
-    ')',        '=',        'P',        'I',        'Y',        '5',        'P',        'U',
-    'L' | 0x80, '(',        'P',        'O',        'W',        ')',        '=',        'P',
-    'A',        'W',        '4' | 0x80, '(',        'P',        'U',        'T',        ')',
-    ' ',        '=',        'P',        'U',        'H',        'T' | 0x80, '(',        'P',
-    ')',        'P',        '=' | 0x80, '(',        'P',        ')',        'S',        '=' | 0x80,
-    '(',        'P',        ')',        'N',        '=' | 0x80, '(',        'P',        'R',
-    'O',        'F',        '.',        ')',        '=',        'P',        'R',        'O',
-    'H',        'F',        'E',        'H',        '4',        'S',        'E',        'R' | 0x80,
-    '(',        'P',        ')',        '=',        'P' | 0x80,
-
-    ']',        'Q' | 0x80, ' ',        '(',        'Q',        ')',        ' ',        '=',
-    'K',        'Y',        'U',        'W',        '4' | 0x80, '(',        'Q',        'U',
-    'A',        'R',        ')',        '=',        'K',        'W',        'O',        'H',
-    '5',        'R' | 0x80, '(',        'Q',        'U',        ')',        '=',        'K',
-    'W' | 0x80, '(',        'Q',        ')',        '=',        'K' | 0x80, ']',        'R' | 0x80,
-    ' ',        '(',        'R',        ')',        ' ',        '=',        'A',        'A',
-    '5',        'R' | 0x80, ' ',        '(',        'R',        'E',        ')',        '^',
-    '#',        '=',        'R',        'I',        'Y' | 0x80, '(',        'R',        ')',
-    'R',        '=' | 0x80, '(',        'R',        ')',        '=',        'R' | 0x80,
-
-    ']',        'S' | 0x80, ' ',        '(',        'S',        ')',        ' ',        '=',
-    'E',        'H',        '4',        'S' | 0x80, '(',        'S',        'H',        ')',
-    '=',        'S',        'H' | 0x80, '#',        '(',        'S',        'I',        'O',
-    'N',        ')',        '=',        'Z',        'H',        'U',        'N' | 0x80, '(',
-    'S',        'O',        'M',        'E',        ')',        '=',        'S',        'A',
-    'H',        'M' | 0x80, '#',        '(',        'S',        'U',        'R',        ')',
-    '#',        '=',        'Z',        'H',        'E',        'R' | 0x80, '(',        'S',
-    'U',        'R',        ')',        '#',        '=',        'S',        'H',        'E',
-    'R' | 0x80, '#',        '(',        'S',        'U',        ')',        '#',        '=',
-    'Z',        'H',        'U',        'W' | 0x80, '#',        '(',        'S',        'S',
-    'U',        ')',        '#',        '=',        'S',        'H',        'U',        'W' | 0x80,
-    '#',        '(',        'S',        'E',        'D',        ')',        '=',        'Z',
-    'D' | 0x80, '#',        '(',        'S',        ')',        '#',        '=',        'Z' | 0x80,
-    '(',        'S',        'A',        'I',        'D',        ')',        '=',        'S',
-    'E',        'H',        'D' | 0x80, '^',        '(',        'S',        'I',        'O',
-    'N',        ')',        '=',        'S',        'H',        'U',        'N' | 0x80, '(',
-    'S',        ')',        'S',        '=' | 0x80, '.',        '(',        'S',        ')',
-    ' ',        '=',        'Z' | 0x80, '#',        ':',        '.',        'E',        '(',
-    'S',        ')',        ' ',        '=',        'Z' | 0x80, '#',        ':',        '^',
-    '#',        '(',        'S',        ')',        ' ',        '=',        'S' | 0x80, 'U',
-    '(',        'S',        ')',        ' ',        '=',        'S' | 0x80, ' ',        ':',
-    '#',        '(',        'S',        ')',        ' ',        '=',        'Z' | 0x80, '#',
-    '#',        '(',        'S',        ')',        ' ',        '=',        'Z' | 0x80, ' ',
-    '(',        'S',        'C',        'H',        ')',        '=',        'S',        'K' | 0x80,
-    '(',        'S',        ')',        'C',        '+',        '=' | 0x80, '#',        '(',
-    'S',        'M',        ')',        '=',        'Z',        'U',        'M' | 0x80, '#',
-    '(',        'S',        'N',        ')',        '\'',       '=',        'Z',        'U',
-    'M' | 0x80, '(',        'S',        'T',        'L',        'E',        ')',        '=',
-    'S',        'U',        'L' | 0x80, '(',        'S',        ')',        '=',        'S' | 0x80,
-
-    ']',        'T' | 0x80, ' ',        '(',        'T',        ')',        ' ',        '=',
-    'T',        'I',        'Y',        '4' | 0x80, ' ',        '(',        'T',        'H',
-    'E',        ')',        ' ',        '#',        '=',        'D',        'H',        'I',
-    'Y' | 0x80, ' ',        '(',        'T',        'H',        'E',        ')',        ' ',
-    '=',        'D',        'H',        'A',        'X' | 0x80, '(',        'T',        'O',
-    ')',        ' ',        '=',        'T',        'U',        'X' | 0x80, ' ',        '(',
-    'T',        'H',        'A',        'T',        ')',        '=',        'D',        'H',
-    'A',        'E',        'T' | 0x80, ' ',        '(',        'T',        'H',        'I',
-    'S',        ')',        ' ',        '=',        'D',        'H',        'I',        'H',
-    'S' | 0x80, ' ',        '(',        'T',        'H',        'E',        'Y',        ')',
-    '=',        'D',        'H',        'E',        'Y' | 0x80, ' ',        '(',        'T',
-    'H',        'E',        'R',        'E',        ')',        '=',        'D',        'H',
-    'E',        'H',        'R' | 0x80, '(',        'T',        'H',        'E',        'R',
-    ')',        '=',        'D',        'H',        'E',        'R' | 0x80, '(',        'T',
-    'H',        'E',        'I',        'R',        ')',        '=',        'D',        'H',
-    'E',        'H',        'R' | 0x80, ' ',        '(',        'T',        'H',        'A',
-    'N',        ')',        ' ',        '=',        'D',        'H',        'A',        'E',
-    'N' | 0x80, ' ',        '(',        'T',        'H',        'E',        'M',        ')',
-    ' ',        '=',        'D',        'H',        'A',        'E',        'N' | 0x80, '(',
-    'T',        'H',        'E',        'S',        'E',        ')',        ' ',        '=',
-    'D',        'H',        'I',        'Y',        'Z' | 0x80, ' ',        '(',        'T',
-    'H',        'E',        'N',        ')',        '=',        'D',        'H',        'E',
-    'H',        'N' | 0x80, '(',        'T',        'H',        'R',        'O',        'U',
-    'G',        'H',        ')',        '=',        'T',        'H',        'R',        'U',
-    'W',        '4' | 0x80, '(',        'T',        'H',        'O',        'S',        'E',
-    ')',        '=',        'D',        'H',        'O',        'H',        'Z' | 0x80, '(',
-    'T',        'H',        'O',        'U',        'G',        'H',        ')',        ' ',
-    '=',        'D',        'H',        'O',        'W' | 0x80, '(',        'T',        'O',
-    'D',        'A',        'Y',        ')',        '=',        'T',        'U',        'X',
-    'D',        'E',        'Y' | 0x80, '(',        'T',        'O',        'M',        'O',
-    ')',        'R',        'R',        'O',        'W',        '=',        'T',        'U',
-    'M',        'A',        'A',        '5' | 0x80, '(',        'T',        'O',        ')',
-    'T',        'A',        'L',        '=',        'T',        'O',        'W',        '5' | 0x80,
-    ' ',        '(',        'T',        'H',        'U',        'S',        ')',        '=',
-    'D',        'H',        'A',        'H',        '4',        'S' | 0x80, '(',        'T',
-    'H',        ')',        '=',        'T',        'H' | 0x80, '#',        ':',        '(',
-    'T',        'E',        'D',        ')',        '=',        'T',        'I',        'X',
-    'D' | 0x80, 'S',        '(',        'T',        'I',        ')',        '#',        'N',
-    '=',        'C',        'H' | 0x80, '(',        'T',        'I',        ')',        'O',
-    '=',        'S',        'H' | 0x80, '(',        'T',        'I',        ')',        'A',
-    '=',        'S',        'H' | 0x80, '(',        'T',        'I',        'E',        'N',
-    ')',        '=',        'S',        'H',        'U',        'N' | 0x80, '(',        'T',
-    'U',        'R',        ')',        '#',        '=',        'C',        'H',        'E',
-    'R' | 0x80, '(',        'T',        'U',        ')',        'A',        '=',        'C',
-    'H',        'U',        'W' | 0x80, ' ',        '(',        'T',        'W',        'O',
-    ')',        '=',        'T',        'U',        'W' | 0x80, '&',        '(',        'T',
-    ')',        'E',        'N',        ' ',        '=' | 0x80, '(',        'T',        ')',
-    '=',        'T' | 0x80,
-
-    ']',        'U' | 0x80, ' ',        '(',        'U',        ')',        ' ',        '=',
-    'Y',        'U',        'W',        '4' | 0x80, ' ',        '(',        'U',        'N',
-    ')',        'I',        '=',        'Y',        'U',        'W',        'N' | 0x80, ' ',
-    '(',        'U',        'N',        ')',        '=',        'A',        'H',        'N' | 0x80,
-    ' ',        '(',        'U',        'P',        'O',        'N',        ')',        '=',
-    'A',        'X',        'P',        'A',        'O',        'N' | 0x80, '@',        '(',
-    'U',        'R',        ')',        '#',        '=',        'U',        'H',        '4',
-    'R' | 0x80, '(',        'U',        'R',        ')',        '#',        '=',        'Y',
-    'U',        'H',        '4',        'R' | 0x80, '(',        'U',        'R',        ')',
-    '=',        'E',        'R' | 0x80, '(',        'U',        ')',        '^',        ' ',
-    '=',        'A',        'H' | 0x80, '(',        'U',        ')',        '^',        '^',
-    '=',        'A',        'H',        '5' | 0x80, '(',        'U',        'Y',        ')',
-    '=',        'A',        'Y',        '5' | 0x80, ' ',        'G',        '(',        'U',
-    ')',        '#',        '=' | 0x80, 'G',        '(',        'U',        ')',        '%',
-    '=' | 0x80, 'G',        '(',        'U',        ')',        '#',        '=',        'W' | 0x80,
-    '#',        'N',        '(',        'U',        ')',        '=',        'Y',        'U',
-    'W' | 0x80, '@',        '(',        'U',        ')',        '=',        'U',        'W' | 0x80,
-    '(',        'U',        ')',        '=',        'Y',        'U',        'W' | 0x80,
-
-    ']',        'V' | 0x80, ' ',        '(',        'V',        ')',        ' ',        '=',
-    'V',        'I',        'Y',        '4' | 0x80, '(',        'V',        'I',        'E',
-    'W',        ')',        '=',        'V',        'Y',        'U',        'W',        '5' | 0x80,
-    '(',        'V',        ')',        '=',        'V' | 0x80,
-
-    ']',        'W' | 0x80, ' ',        '(',        'W',        ')',        ' ',        '=',
-    'D',        'A',        'H',        '4',        'B',        'U',        'L',        'Y',
-    'U',        'W' | 0x80, ' ',        '(',        'W',        'E',        'R',        'E',
-    ')',        '=',        'W',        'E',        'R' | 0x80, '(',        'W',        'A',
-    ')',        'S',        'H',        '=',        'W',        'A',        'A' | 0x80, '(',
-    'W',        'A',        ')',        'S',        'T',        '=',        'W',        'E',
-    'Y' | 0x80, '(',        'W',        'A',        ')',        'S',        '=',        'W',
-    'A',        'H' | 0x80, '(',        'W',        'A',        ')',        'T',        '=',
-    'W',        'A',        'A' | 0x80, '(',        'W',        'H',        'E',        'R',
-    'E',        ')',        '=',        'W',        'H',        'E',        'H',        'R' | 0x80,
-    '(',        'W',        'H',        'A',        'T',        ')',        '=',        'W',
-    'H',        'A',        'H',        'T' | 0x80, '(',        'W',        'H',        'O',
-    'L',        ')',        '=',        '/',        'H',        'O',        'W',        'L' | 0x80,
-    '(',        'W',        'H',        'O',        ')',        '=',        '/',        'H',
-    'U',        'W' | 0x80, '(',        'W',        'H',        ')',        '=',        'W',
-    'H' | 0x80, '(',        'W',        'A',        'R',        ')',        '#',        '=',
-    'W',        'E',        'H',        'R' | 0x80, '(',        'W',        'A',        'R',
-    ')',        '=',        'W',        'A',        'O',        'R' | 0x80, '(',        'W',
-    'O',        'R',        ')',        '^',        '=',        'W',        'E',        'R' | 0x80,
-    '(',        'W',        'R',        ')',        '=',        'R' | 0x80, '(',        'W',
-    'O',        'M',        ')',        'A',        '=',        'W',        'U',        'H',
-    'M' | 0x80, '(',        'W',        'O',        'M',        ')',        'E',        '=',
-    'W',        'I',        'H',        'M' | 0x80, '(',        'W',        'E',        'A',
-    ')',        'R',        '=',        'W',        'E',        'H' | 0x80, '(',        'W',
-    'A',        'N',        'T',        ')',        '=',        'W',        'A',        'A',
-    '5',        'N',        'T' | 0x80, 'A',        'N',        'S',        '(',        'W',
-    'E',        'R',        ')',        '=',        'E',        'R' | 0x80, '(',        'W',
-    ')',        '=',        'W' | 0x80,
-
-    ']',        'X' | 0x80, ' ',        '(',        'X',        ')',        ' ',        '=',
-    'E',        'H',        '4',        'K',        'R' | 0x80, ' ',        '(',        'X',
-    ')',        '=',        'Z' | 0x80, '(',        'X',        ')',        '=',        'K',
-    'S' | 0x80,
-
-    ']',        'Y' | 0x80, ' ',        '(',        'Y',        ')',        ' ',        '=',
-    'W',        'A',        'Y',        '4' | 0x80, '(',        'Y',        'O',        'U',
-    'N',        'G',        ')',        '=',        'Y',        'A',        'H',        'N',
-    'X' | 0x80, ' ',        '(',        'Y',        'O',        'U',        'R',        ')',
-    '=',        'Y',        'O',        'H',        'R' | 0x80, ' ',        '(',        'Y',
-    'O',        'U',        ')',        '=',        'Y',        'U',        'W' | 0x80, ' ',
-    '(',        'Y',        'E',        'S',        ')',        '=',        'Y',        'E',
-    'H',        'S' | 0x80, ' ',        '(',        'Y',        ')',        '=',        'Y' | 0x80,
-    'F',        '(',        'Y',        ')',        '=',        'A',        'Y' | 0x80, 'P',
-    'S',        '(',        'Y',        'C',        'H',        ')',        '=',        'A',
-    'Y',        'K' | 0x80, '#',        ':',        '^',        '(',        'Y',        ')',
-    '=',        'I',        'Y' | 0x80, '#',        ':',        '^',        '(',        'Y',
-    ')',        'I',        '=',        'I',        'Y' | 0x80, ' ',        ':',        '(',
-    'Y',        ')',        ' ',        '=',        'A',        'Y' | 0x80, ' ',        ':',
-    '(',        'Y',        ')',        '#',        '=',        'A',        'Y' | 0x80, ' ',
-    ':',        '(',        'Y',        ')',        '^',        '+',        ':',        '#',
-    '=',        'I',        'H' | 0x80, ' ',        ':',        '(',        'Y',        ')',
-    '^',        '#',        '=',        'A',        'Y' | 0x80, '(',        'Y',        ')',
-    '=',        'I',        'H' | 0x80,
-
-    ']',        'Z' | 0x80, ' ',        '(',        'Z',        ')',        ' ',        '=',
-    'Z',        'I',        'Y',        '4' | 0x80, '(',        'Z',        ')',        '=',
-    'Z' | 0x80, 'j' | 0x80};
-
-const unsigned char rules2[] = {
-    '(',        'A',        ')',        '=' | 0x80, '(',        '!',        ')',        '=',
-    '.' | 0x80, '(',        '"',        ')',        ' ',        '=',        '-',        'A',
-    'H',        '5',        'N',        'K',        'W',        'O',        'W',        'T',
-    '-' | 0x80, '(',        '"',        ')',        '=',        'K',        'W',        'O',
-    'W',        '4',        'T',        '-' | 0x80, '(',        '#',        ')',        '=',
-    ' ',        'N',        'A',        'H',        '4',        'M',        'B',        'E',
-    'R' | 0x80, '(',        '$',        ')',        '=',        ' ',        'D',        'A',
-    'A',        '4',        'L',        'E',        'R' | 0x80, '(',        '%',        ')',
-    '=',        ' ',        'P',        'E',        'R',        'S',        'E',        'H',
-    '4',        'N',        'T' | 0x80, '(',        '&',        ')',        '=',        ' ',
-    'A',        'E',        'N',        'D' | 0x80, '(',        '\'',       ')',        '=' | 0x80,
-    '(',        '*',        ')',        '=',        ' ',        'A',        'E',        '4',
-    'S',        'T',        'E',        'R',        'I',        'H',        'S',        'K' | 0x80,
-    '(',        '+',        ')',        '=',        ' ',        'P',        'L',        'A',
-    'H',        '4',        'S' | 0x80, '(',        ',',        ')',        '=',        ',' | 0x80,
-    ' ',        '(',        '-',        ')',        ' ',        '=',        '-' | 0x80, '(',
-    '-',        ')',        '=' | 0x80, '(',        '.',        ')',        '=',        ' ',
-    'P',        'O',        'Y',        'N',        'T' | 0x80, '(',        '/',        ')',
-    '=',        ' ',        'S',        'L',        'A',        'E',        '4',        'S',
-    'H' | 0x80, '(',        '0',        ')',        '=',        ' ',        'Z',        'I',
-    'Y',        '4',        'R',        'O',        'W' | 0x80, ' ',        '(',        '1',
-    'S',        'T',        ')',        '=',        'F',        'E',        'R',        '4',
-    'S',        'T' | 0x80, ' ',        '(',        '1',        '0',        'T',        'H',
-    ')',        '=',        'T',        'E',        'H',        '4',        'N',        'T',
-    'H' | 0x80, '(',        '1',        ')',        '=',        ' ',        'W',        'A',
-    'H',        '4',        'N' | 0x80, ' ',        '(',        '2',        'N',        'D',
-    ')',        '=',        'S',        'E',        'H',        '4',        'K',        'U',
-    'N',        'D' | 0x80, '(',        '2',        ')',        '=',        ' ',        'T',
-    'U',        'W',        '4' | 0x80, ' ',        '(',        '3',        'R',        'D',
-    ')',        '=',        'T',        'H',        'E',        'R',        '4',        'D' | 0x80,
-    '(',        '3',        ')',        '=',        ' ',        'T',        'H',        'R',
-    'I',        'Y',        '4' | 0x80, '(',        '4',        ')',        '=',        ' ',
-    'F',        'O',        'H',        '4',        'R' | 0x80, ' ',        '(',        '5',
-    'T',        'H',        ')',        '=',        'F',        'I',        'H',        '4',
-    'F',        'T',        'H' | 0x80, '(',        '5',        ')',        '=',        ' ',
-    'F',        'A',        'Y',        '4',        'V' | 0x80, ' ',        '(',        '6',
-    '4',        ')',        ' ',        '=',        'S',        'I',        'H',        '4',
-    'K',        'S',        'T',        'I',        'Y',        ' ',        'F',        'O',
-    'H',        'R' | 0x80, '(',        '6',        ')',        '=',        ' ',        'S',
-    'I',        'H',        '4',        'K',        'S' | 0x80, '(',        '7',        ')',
-    '=',        ' ',        'S',        'E',        'H',        '4',        'V',        'U',
-    'N' | 0x80, ' ',        '(',        '8',        'T',        'H',        ')',        '=',
-    'E',        'Y',        '4',        'T',        'H' | 0x80, '(',        '8',        ')',
-    '=',        ' ',        'E',        'Y',        '4',        'T' | 0x80, '(',        '9',
-    ')',        '=',        ' ',        'N',        'A',        'Y',        '4',        'N' | 0x80,
-    '(',        ':',        ')',        '=',        '.' | 0x80, '(',        ';',        ')',
-    '=',        '.' | 0x80, '(',        '<',        ')',        '=',        ' ',        'L',
-    'E',        'H',        '4',        'S',        ' ',        'D',        'H',        'A',
-    'E',        'N' | 0x80, '(',        '=',        ')',        '=',        ' ',        'I',
-    'Y',        '4',        'K',        'W',        'U',        'L',        'Z' | 0x80, '(',
-    '>',        ')',        '=',        ' ',        'G',        'R',        'E',        'Y',
-    '4',        'T',        'E',        'R',        ' ',        'D',        'H',        'A',
-    'E',        'N' | 0x80, '(',        '?',        ')',        '=',        '?' | 0x80, '(',
-    '@',        ')',        '=',        ' ',        'A',        'E',        '6',        'T' | 0x80,
-    '(',        '^',        ')',        '=',        ' ',        'K',        'A',        'E',
-    '4',        'R',        'I',        'X',        'T' | 0x80, ']',        'A' | 0x80};
-
-//26 items. From 'A' to 'Z'
-// positions for mem62 and mem63 for each character
-const unsigned char tab37489[] = {0,   149, 247, 162, 57, 197, 6,  126, 199, 38, 55, 78, 145,
-                                  241, 85,  161, 254, 36, 69,  45, 167, 54,  83, 46, 71, 218};
-
-const unsigned char tab37515[] = {125, 126, 126, 127, 128, 129, 130, 130, 130, 132, 132, 132, 132,
-                                  132, 133, 135, 135, 136, 136, 137, 138, 139, 139, 140, 140, 140};
-
-void STM32SAM::Output8BitAry(int index, unsigned char ary[5]) {
-    int k;
-
-    uint32_t bufferposOld = bufferpos;
-
-    bufferpos += timetable[oldtimetableindex][index];
-    oldtimetableindex = index;
-
-    int sample_uS = bufferpos - bufferposOld;
-
-    uint32_t f = 0;
-
-    // write a little bit in advance
-    for(k = 0; k < 5; k++) {
-        //   buffer[bufferpos / 50 + k] = ary[k];
-
-        // f = micros() + sample_uS / (_STM32SAM_SPEED + 1);
-        // while(micros() < f) {
-        // };
-        f = sample_uS / (_STM32SAM_SPEED + 1);
-        furi_delay_us(f);
-        SetAUDIO(ary[k]);
-        //  delayMicroseconds(sample_uS / 5 );
-    }
-
-    //  SetAUDIO(ary[0]);
-}
-
-void STM32SAM::Output8Bit(int index, unsigned char A) {
-    unsigned char ary[5] = {A, A, A, A, A};
-    Output8BitAry(index, ary);
-}
-
-//written by me because of different table positions.
-// mem[47] = ...
-// 168=pitches
-// 169=frequency1
-// 170=frequency2
-// 171=frequency3
-// 172=amplitude1
-// 173=amplitude2
-// 174=amplitude3
-unsigned char STM32SAM::Read(unsigned char p, unsigned char Y) {
-    switch(p) {
-    case 168:
-        return pitches[Y];
-    case 169:
-        return frequency1[Y];
-    case 170:
-        return frequency2[Y];
-    case 171:
-        return frequency3[Y];
-    case 172:
-        return amplitude1[Y];
-    case 173:
-        return amplitude2[Y];
-    case 174:
-        return amplitude3[Y];
-    }
-    // Serial1.println("Error reading to tables");
-    return 0;
-}
-
-void STM32SAM::Write(unsigned char p, unsigned char Y, unsigned char value) {
-    switch(p) {
-    case 168:
-        pitches[Y] = value;
-        return;
-    case 169:
-        frequency1[Y] = value;
-        return;
-    case 170:
-        frequency2[Y] = value;
-        return;
-    case 171:
-        frequency3[Y] = value;
-        return;
-    case 172:
-        amplitude1[Y] = value;
-        return;
-    case 173:
-        amplitude2[Y] = value;
-        return;
-    case 174:
-        amplitude3[Y] = value;
-        return;
-    }
-    //Serial1.println("Error writing to tables\n");
-}
-
-// -------------------------------------------------------------------------
-//Code48227
-// Render a sampled sound from the sampleTable.
-//
-//   Phoneme   Sample Start   Sample End
-//   32: S*    15             255
-//   33: SH    257            511
-//   34: F*    559            767
-//   35: TH    583            767
-//   36: /H    903            1023
-//   37: /X    1135           1279
-//   38: Z*    84             119
-//   39: ZH    340            375
-//   40: V*    596            639
-//   41: DH    596            631
-//
-//   42: CH
-//   43: **    399            511
-//
-//   44: J*
-//   45: **    257            276
-//   46: **
-//
-//   66: P*
-//   67: **    743            767
-//   68: **
-//
-//   69: T*
-//   70: **    231            255
-//   71: **
-//
-// The SampledPhonemesTable[] holds flags indicating if a phoneme is
-// voiced or not. If the upper 5 bits are zero, the sample is voiced.
-//
-// Samples in the sampleTable are compressed, with bits being converted to
-// bytes from high bit to low, as follows:
-//
-//   unvoiced 0 bit   -> X
-//   unvoiced 1 bit   -> 5
-//
-//   voiced 0 bit     -> 6
-//   voiced 1 bit     -> 24
-//
-// Where X is a value from the table:
-//
-//   { 0x18, 0x1A, 0x17, 0x17, 0x17 };
-//
-// The index into this table is determined by masking off the lower
-// 3 bits from the SampledPhonemesTable:
-//
-//        index = (SampledPhonemesTable[i] & 7) - 1;
-//
-// For voices samples, samples are interleaved between voiced output.
-
-// Code48227()
-void STM32SAM::RenderSample(unsigned char* mem66) {
-    int tempA;
-    // current phoneme's index
-    mem49 = Y;
-
-    // mask low three bits and subtract 1 get value to
-    // convert 0 bits on unvoiced samples.
-    A = mem39 & 7;
-    X = A - 1;
-
-    // store the result
-    mem56 = X;
-
-    // determine which offset to use from table { 0x18, 0x1A, 0x17, 0x17, 0x17 }
-    // T, S, Z                0          0x18
-    // CH, J, SH, ZH          1          0x1A
-    // P, F*, V, TH, DH       2          0x17
-    // /H                     3          0x17
-    // /X                     4          0x17
-
-    // get value from the table
-    mem53 = tab48426[X];
-    mem47 = X; //46016+mem[56]*256
-
-    // voiced sample?
-    A = mem39 & 248;
-    if(A == 0) {
-        // voiced phoneme: Z*, ZH, V*, DH
-        Y = mem49;
-        A = pitches[mem49] >> 4;
-
-        // jump to voiced portion
-        goto pos48315;
-    }
-
-    Y = A ^ 255;
-pos48274:
-
-    // step through the 8 bits in the sample
-    mem56 = 8;
-
-    // get the next sample from the table
-    // mem47*256 = offset to start of samples
-    A = sampleTable[mem47 * 256 + Y];
-pos48280:
-
-    // left shift to get the high bit
-    tempA = A;
-    A = A << 1;
-    //48281: BCC 48290
-
-    // bit not set?
-    if((tempA & 128) == 0) {
-        // convert the bit to value from table
-        X = mem53;
-        //mem[54296] = X;
-        // output the byte
-        Output8Bit(1, (X & 0x0f) * 16);
-        // if X != 0, exit loop
-        if(X != 0) goto pos48296;
-    }
-
-    // output a 5 for the on bit
-    Output8Bit(2, 5 * 16);
-
-    //48295: NOP
-pos48296:
-
-    X = 0;
-
-    // decrement counter
-    mem56--;
-
-    // if not done, jump to top of loop
-    if(mem56 != 0) goto pos48280;
-
-    // increment position
-    Y++;
-    if(Y != 0) goto pos48274;
-
-    // restore values and return
-    mem44 = 1;
-    Y = mem49;
-    return;
-
-    unsigned char phase1;
-
-pos48315:
-    // handle voiced samples here
-
-    // number of samples?
-    phase1 = A ^ 255;
-
-    Y = *mem66;
-    do {
-        //pos48321:
-
-        // shift through all 8 bits
-        mem56 = 8;
-        //A = Read(mem47, Y);
-
-        // fetch value from table
-        A = sampleTable[mem47 * 256 + Y];
-
-        // loop 8 times
-        //pos48327:
-        do {
-            //48327: ASL A
-            //48328: BCC 48337
-
-            // left shift and check high bit
-            tempA = A;
-            A = A << 1;
-            if((tempA & 128) != 0) {
-                // if bit set, output 26
-                X = 26;
-                Output8Bit(3, (X & 0xf) * 16);
-            } else {
-                //timetable 4
-                // bit is not set, output a 6
-                X = 6;
-                Output8Bit(4, (X & 0xf) * 16);
-            }
-
-            mem56--;
-        } while(mem56 != 0);
-
-        // move ahead in the table
-        Y++;
-
-        // continue until counter done
-        phase1++;
-
-    } while(phase1 != 0);
-    //  if (phase1 != 0) goto pos48321;
-
-    // restore values and return
-    A = 1;
-    mem44 = 1;
-    *mem66 = Y;
-    Y = mem49;
-    return;
-}
-
-// RENDER THE PHONEMES IN THE LIST
-//
-// The phoneme list is converted into sound through the steps:
-//
-// 1. Copy each phoneme <length> number of times into the frames list,
-//    where each frame represents 10 milliseconds of sound.
-//
-// 2. Determine the transitions lengths between phonemes, and linearly
-//    interpolate the values across the frames.
-//
-// 3. Offset the pitches by the fundamental frequency.
-//
-// 4. Render the each frame.
-
-//void Code47574()
-void STM32SAM::Render() {
-    unsigned char phase1 = 0; //mem43
-    unsigned char phase2 = 0;
-    unsigned char phase3 = 0;
-    unsigned char mem66 = 0;
-    unsigned char mem38 = 0;
-    unsigned char mem40 = 0;
-    unsigned char speedcounter = 0; //mem45
-    unsigned char mem48 = 0;
-    int i;
-    if(phonemeIndexOutput[0] == 255) return; //exit if no data
-
-    A = 0;
-    X = 0;
-    mem44 = 0;
-
-    // CREATE FRAMES
-    //
-    // The length parameter in the list corresponds to the number of frames
-    // to expand the phoneme to. Each frame represents 10 milliseconds of time.
-    // So a phoneme with a length of 7 = 7 frames = 70 milliseconds duration.
-    //
-    // The parameters are copied from the phoneme to the frame verbatim.
-
-    // pos47587:
-    do {
-        // get the index
-        Y = mem44;
-        // get the phoneme at the index
-        A = phonemeIndexOutput[mem44];
-        mem56 = A;
-
-        // if terminal phoneme, exit the loop
-        if(A == 255) break;
-
-        // period phoneme *.
-        if(A == 1) {
-            // add rising inflection
-            A = 1;
-            mem48 = 1;
-            //goto pos48376;
-            AddInflection(mem48, phase1);
-        }
-        /*
-      if (A == 2) goto pos48372;
-    */
-
-        // question mark phoneme?
-        if(A == 2) {
-            // create falling inflection
-            mem48 = 255;
-            AddInflection(mem48, phase1);
-        }
-        //  pos47615:
-
-        // get the stress amount (more stress = higher pitch)
-        phase1 = tab47492[stressOutput[Y] + 1];
-
-        // get number of frames to write
-        phase2 = phonemeLengthOutput[Y];
-        Y = mem56;
-
-        // copy from the source to the frames list
-        do {
-            frequency1[X] = freq1data[Y]; // F1 frequency
-            frequency2[X] = freq2data[Y]; // F2 frequency
-            frequency3[X] = freq3data[Y]; // F3 frequency
-            amplitude1[X] = ampl1data[Y]; // F1 amplitude
-            amplitude2[X] = ampl2data[Y]; // F2 amplitude
-            amplitude3[X] = ampl3data[Y]; // F3 amplitude
-            sampledConsonantFlag[X] =
-                sampledConsonantFlags[Y]; // phoneme data for sampled consonants
-            pitches[X] = pitch + phase1; // pitch
-            X++;
-            phase2--;
-        } while(phase2 != 0);
-        mem44++;
-    } while(mem44 != 0);
-    // -------------------
-    //pos47694:
-
-    // CREATE TRANSITIONS
-    //
-    // Linear transitions are now created to smoothly connect the
-    // end of one sustained portion of a phoneme to the following
-    // phoneme.
-    //
-    // To do this, three tables are used:
-    //
-    //  Table         Purpose
-    //  =========     ==================================================
-    //  blendRank     Determines which phoneme's blend values are used.
-    //
-    //  blendOut      The number of frames at the end of the phoneme that
-    //                will be used to transition to the following phoneme.
-    //
-    //  blendIn       The number of frames of the following phoneme that
-    //                will be used to transition into that phoneme.
-    //
-    // In creating a transition between two phonemes, the phoneme
-    // with the HIGHEST rank is used. Phonemes are ranked on how much
-    // their identity is based on their transitions. For example,
-    // vowels are and diphthongs are identified by their sustained portion,
-    // rather than the transitions, so they are given low values. In contrast,
-    // stop consonants (P, B, T, K) and glides (Y, L) are almost entirely
-    // defined by their transitions, and are given high rank values.
-    //
-    // Here are the rankings used by SAM:
-    //
-    //     Rank    Type                         Phonemes
-    //     2       All vowels                   IY, IH, etc.
-    //     5       Diphthong endings            YX, WX, ER
-    //     8       Terminal liquid consonants   LX, WX, YX, N, NX
-    //     9       Liquid consonants            L, RX, W
-    //     10      Glide                        R, OH
-    //     11      Glide                        WH
-    //     18      Voiceless fricatives         S, SH, F, TH
-    //     20      Voiced fricatives            Z, ZH, V, DH
-    //     23      Plosives, stop consonants    P, T, K, KX, DX, CH
-    //     26      Stop consonants              J, GX, B, D, G
-    //     27-29   Stop consonants (internal)   **
-    //     30      Unvoiced consonants          /H, /X and Q*
-    //     160     Nasal                        M
-    //
-    // To determine how many frames to use, the two phonemes are
-    // compared using the blendRank[] table. The phoneme with the
-    // higher rank is selected. In case of a tie, a blend of each is used:
-    //
-    //      if blendRank[phoneme1] ==  blendRank[phomneme2]
-    //          // use lengths from each phoneme
-    //          outBlendFrames = outBlend[phoneme1]
-    //          inBlendFrames = outBlend[phoneme2]
-    //      else if blendRank[phoneme1] > blendRank[phoneme2]
-    //          // use lengths from first phoneme
-    //          outBlendFrames = outBlendLength[phoneme1]
-    //          inBlendFrames = inBlendLength[phoneme1]
-    //      else
-    //          // use lengths from the second phoneme
-    //          // note that in and out are SWAPPED!
-    //          outBlendFrames = inBlendLength[phoneme2]
-    //          inBlendFrames = outBlendLength[phoneme2]
-    //
-    // Blend lengths can't be less than zero.
-    //
-    // Transitions are assumed to be symetrical, so if the transition
-    // values for the second phoneme are used, the inBlendLength and
-    // outBlendLength values are SWAPPED.
-    //
-    // For most of the parameters, SAM interpolates over the range of the last
-    // outBlendFrames-1 and the first inBlendFrames.
-    //
-    // The exception to this is the Pitch[] parameter, which is interpolates the
-    // pitch from the CENTER of the current phoneme to the CENTER of the next
-    // phoneme.
-    //
-    // Here are two examples. First, For example, consider the word "SUN" (S AH N)
-    //
-    //    Phoneme   Duration    BlendWeight    OutBlendFrames    InBlendFrames
-    //    S         2           18             1                 3
-    //    AH        8           2              4                 4
-    //    N         7           8              1                 2
-    //
-    // The formant transitions for the output frames are calculated as follows:
-    //
-    //     flags ampl1 freq1 ampl2 freq2 ampl3 freq3 pitch
-    //    ------------------------------------------------
-    // S
-    //    241     0     6     0    73     0    99    61   Use S (weight 18) for transition instead of AH (weight 2)
-    //    241     0     6     0    73     0    99    61   <-- (OutBlendFrames-1) = (1-1) = 0 frames
-    // AH
-    //      0     2    10     2    66     0    96    59 * <-- InBlendFrames = 3 frames
-    //      0     4    14     3    59     0    93    57 *
-    //      0     8    18     5    52     0    90    55 *
-    //      0    15    22     9    44     1    87    53
-    //      0    15    22     9    44     1    87    53
-    //      0    15    22     9    44     1    87    53   Use N (weight 8) for transition instead of AH (weight 2).
-    //      0    15    22     9    44     1    87    53   Since N is second phoneme, reverse the IN and OUT values.
-    //      0    11    17     8    47     1    98    56 * <-- (InBlendFrames-1) = (2-1) = 1 frames
-    // N
-    //      0     8    12     6    50     1   109    58 * <-- OutBlendFrames = 1
-    //      0     5     6     5    54     0   121    61
-    //      0     5     6     5    54     0   121    61
-    //      0     5     6     5    54     0   121    61
-    //      0     5     6     5    54     0   121    61
-    //      0     5     6     5    54     0   121    61
-    //      0     5     6     5    54     0   121    61
-    //
-    // Now, consider the reverse "NUS" (N AH S):
-    //
-    //     flags ampl1 freq1 ampl2 freq2 ampl3 freq3 pitch
-    //    ------------------------------------------------
-    // N
-    //     0     5     6     5    54     0   121    61
-    //     0     5     6     5    54     0   121    61
-    //     0     5     6     5    54     0   121    61
-    //     0     5     6     5    54     0   121    61
-    //     0     5     6     5    54     0   121    61
-    //     0     5     6     5    54     0   121    61   Use N (weight 8) for transition instead of AH (weight 2)
-    //     0     5     6     5    54     0   121    61   <-- (OutBlendFrames-1) = (1-1) = 0 frames
-    // AH
-    //     0     8    11     6    51     0   110    59 * <-- InBlendFrames = 2
-    //     0    11    16     8    48     0    99    56 *
-    //     0    15    22     9    44     1    87    53   Use S (weight 18) for transition instead of AH (weight 2)
-    //     0    15    22     9    44     1    87    53   Since S is second phoneme, reverse the IN and OUT values.
-    //     0     9    18     5    51     1    90    55 * <-- (InBlendFrames-1) = (3-1) = 2
-    //     0     4    14     3    58     1    93    57 *
-    // S
-    //   241     2    10     2    65     1    96    59 * <-- OutBlendFrames = 1
-    //   241     0     6     0    73     0    99    61
-
-    A = 0;
-    mem44 = 0;
-    mem49 = 0; // mem49 starts at as 0
-    X = 0;
-    while(1) //while No. 1
-    {
-        // get the current and following phoneme
-        Y = phonemeIndexOutput[X];
-        A = phonemeIndexOutput[X + 1];
-        X++;
-
-        // exit loop at end token
-        if(A == 255) break; //goto pos47970;
-
-        // get the ranking of each phoneme
-        X = A;
-        mem56 = blendRank[A];
-        A = blendRank[Y];
-
-        // compare the rank - lower rank value is stronger
-        if(A == mem56) {
-            // same rank, so use out blend lengths from each phoneme
-            phase1 = outBlendLength[Y];
-            phase2 = outBlendLength[X];
-        } else if(A < mem56) {
-            // first phoneme is stronger, so us it's blend lengths
-            phase1 = inBlendLength[X];
-            phase2 = outBlendLength[X];
-        } else {
-            // second phoneme is stronger, so use it's blend lengths
-            // note the out/in are swapped
-            phase1 = outBlendLength[Y];
-            phase2 = inBlendLength[Y];
-        }
-
-        Y = mem44;
-        A = mem49 + phonemeLengthOutput[mem44]; // A is mem49 + length
-        mem49 = A; // mem49 now holds length + position
-        A = A + phase2; //Maybe Problem because of carry flag
-
-        //47776: ADC 42
-        speedcounter = A;
-        mem47 = 168;
-        phase3 = mem49 - phase1; // what is mem49
-        A = phase1 + phase2; // total transition?
-        mem38 = A;
-
-        X = A;
-        X -= 2;
-        if((X & 128) == 0)
-            do //while No. 2
-            {
-                //pos47810:
-
-                // mem47 is used to index the tables:
-                // 168  pitches[]
-                // 169  frequency1
-                // 170  frequency2
-                // 171  frequency3
-                // 172  amplitude1
-                // 173  amplitude2
-                // 174  amplitude3
-
-                mem40 = mem38;
-
-                if(mem47 == 168) // pitch
-                {
-                    // unlike the other values, the pitches[] interpolates from
-                    // the middle of the current phoneme to the middle of the
-                    // next phoneme
-
-                    unsigned char mem36, mem37;
-                    // half the width of the current phoneme
-                    mem36 = phonemeLengthOutput[mem44] >> 1;
-                    // half the width of the next phoneme
-                    mem37 = phonemeLengthOutput[mem44 + 1] >> 1;
-                    // sum the values
-                    mem40 = mem36 + mem37; // length of both halves
-                    mem37 += mem49; // center of next phoneme
-                    mem36 = mem49 - mem36; // center index of current phoneme
-                    A = Read(
-                        mem47, mem37); // value at center of next phoneme - end interpolation value
-                    //A = mem[address];
-
-                    Y = mem36; // start index of interpolation
-                    mem53 = A - Read(mem47, mem36); // value to center of current phoneme
-                } else {
-                    // value to interpolate to
-                    A = Read(mem47, speedcounter);
-                    // position to start interpolation from
-                    Y = phase3;
-                    // value to interpolate from
-                    mem53 = A - Read(mem47, phase3);
-                }
-
-                //Code47503(mem40);
-                // ML : Code47503 is division with remainder, and mem50 gets the sign
-
-                // calculate change per frame
-                signed char m53 = (signed char)mem53;
-                mem50 = mem53 & 128;
-                unsigned char m53abs = abs(m53);
-                mem51 = m53abs % mem40; //abs((char)m53) % mem40;
-                mem53 = (unsigned char)((signed char)(m53) / mem40);
-
-                // interpolation range
-                X = mem40; // number of frames to interpolate over
-                Y = phase3; // starting frame
-
-                // linearly interpolate values
-
-                mem56 = 0;
-                //47907: CLC
-                //pos47908:
-                while(1) //while No. 3
-                {
-                    A = Read(mem47, Y) + mem53; //carry alway cleared
-
-                    mem48 = A;
-                    Y++;
-                    X--;
-                    if(X == 0) break;
-
-                    mem56 += mem51;
-                    if(mem56 >= mem40) //???
-                    {
-                        mem56 -= mem40; //carry? is set
-                        //if ((mem56 & 128)==0)
-                        if((mem50 & 128) == 0) {
-                            //47935: BIT 50
-                            //47937: BMI 47943
-                            if(mem48 != 0) mem48++;
-                        } else
-                            mem48--;
-                    }
-                    //pos47945:
-                    Write(mem47, Y, mem48);
-                } //while No. 3
-
-                //pos47952:
-                mem47++;
-                //if (mem47 != 175) goto pos47810;
-            } while(mem47 != 175); //while No. 2
-        //pos47963:
-        mem44++;
-        X = mem44;
-    } //while No. 1
-
-    //goto pos47701;
-    //pos47970:
-
-    // add the length of this phoneme
-    mem48 = mem49 + phonemeLengthOutput[mem44];
-
-    // ASSIGN PITCH CONTOUR
-    //
-    // This subtracts the F1 frequency from the pitch to create a
-    // pitch contour. Without this, the output would be at a single
-    // pitch level (monotone).
-
-    // don't adjust pitch if in sing mode
-    if(!singmode) {
-        // iterate through the buffer
-        for(i = 0; i < 256; i++) {
-            // subtract half the frequency of the formant 1.
-            // this adds variety to the voice
-            pitches[i] -= (frequency1[i] >> 1);
-        }
-    }
-
-    phase1 = 0;
-    phase2 = 0;
-    phase3 = 0;
-    mem49 = 0;
-    speedcounter = 72; //sam standard speed
-
-    // RESCALE AMPLITUDE
-    //
-    // Rescale volume from a linear scale to decibels.
-    //
-
-    //amplitude rescaling
-    for(i = 255; i >= 0; i--) {
-        amplitude1[i] = amplitudeRescale[amplitude1[i]];
-        amplitude2[i] = amplitudeRescale[amplitude2[i]];
-        amplitude3[i] = amplitudeRescale[amplitude3[i]];
-    }
-
-    Y = 0;
-    A = pitches[0];
-    mem44 = A;
-    X = A;
-    mem38 = A - (A >> 2); // 3/4*A ???
-
-    // PROCESS THE FRAMES
-    //
-    // In traditional vocal synthesis, the glottal pulse drives filters, which
-    // are attenuated to the frequencies of the formants.
-    //
-    // SAM generates these formants directly with sin and rectangular waves.
-    // To simulate them being driven by the glottal pulse, the waveforms are
-    // reset at the beginning of each glottal pulse.
-
-    //finally the loop for sound output
-    //pos48078:
-    while(1) {
-        // get the sampled information on the phoneme
-        A = sampledConsonantFlag[Y];
-        mem39 = A;
-
-        // unvoiced sampled phoneme?
-        A = A & 248;
-        if(A != 0) {
-            // render the sample for the phoneme
-            RenderSample(&mem66);
-
-            // skip ahead two in the phoneme buffer
-            Y += 2;
-            mem48 -= 2;
-        } else {
-            // simulate the glottal pulse and formants
-            unsigned char ary[5];
-            unsigned int p1 =
-                phase1 * 256; // Fixed point integers because we need to divide later on
-            unsigned int p2 = phase2 * 256;
-            unsigned int p3 = phase3 * 256;
-            int k;
-            for(k = 0; k < 5; k++) {
-                signed char sp1 = (signed char)sinus[0xff & (p1 >> 8)];
-                signed char sp2 = (signed char)sinus[0xff & (p2 >> 8)];
-                signed char rp3 = (signed char)rectangle[0xff & (p3 >> 8)];
-                signed int sin1 = sp1 * ((unsigned char)amplitude1[Y] & 0x0f);
-                signed int sin2 = sp2 * ((unsigned char)amplitude2[Y] & 0x0f);
-                signed int rect = rp3 * ((unsigned char)amplitude3[Y] & 0x0f);
-                signed int mux = sin1 + sin2 + rect;
-                mux /= 32;
-                mux += 128; // Go from signed to unsigned amplitude
-                ary[k] = mux;
-                p1 += frequency1[Y] * 256 / 4; // Compromise, this becomes a shift and works well
-                p2 += frequency2[Y] * 256 / 4;
-                p3 += frequency3[Y] * 256 / 4;
-            }
-            // output the accumulated value
-            Output8BitAry(0, ary);
-            speedcounter--;
-            if(speedcounter != 0) goto pos48155;
-            Y++; //go to next amplitude
-
-            // decrement the frame count
-            mem48--;
-        }
-
-        // if the frame count is zero, exit the loop
-        if(mem48 == 0) return;
-        speedcounter = speed;
-    pos48155:
-
-        // decrement the remaining length of the glottal pulse
-        mem44--;
-
-        // finished with a glottal pulse?
-        if(mem44 == 0) {
-        pos48159:
-            // fetch the next glottal pulse length
-            A = pitches[Y];
-            mem44 = A;
-            A = A - (A >> 2);
-            mem38 = A;
-
-            // reset the formant wave generators to keep them in
-            // sync with the glottal pulse
-            phase1 = 0;
-            phase2 = 0;
-            phase3 = 0;
-            continue;
-        }
-
-        // decrement the count
-        mem38--;
-
-        // is the count non-zero and the sampled flag is zero?
-        if((mem38 != 0) || (mem39 == 0)) {
-            // reset the phase of the formants to match the pulse
-            phase1 += frequency1[Y];
-            phase2 += frequency2[Y];
-            phase3 += frequency3[Y];
-            continue;
-        }
-
-        // voiced sampled phonemes interleave the sample with the
-        // glottal pulse. The sample flag is non-zero, so render
-        // the sample for the phoneme.
-        RenderSample(&mem66);
-        goto pos48159;
-    } //while
-
-    // The following code is never reached. It's left over from when
-    // the voiced sample code was part of this loop, instead of part
-    // of RenderSample();
-
-    //pos48315:
-    int tempA;
-    phase1 = A ^ 255;
-    Y = mem66;
-    do {
-        //pos48321:
-
-        mem56 = 8;
-        A = Read(mem47, Y);
-
-        //pos48327:
-        do {
-            //48327: ASL A
-            //48328: BCC 48337
-            tempA = A;
-            A = A << 1;
-            if((tempA & 128) != 0) {
-                X = 26;
-                // mem[54296] = X;
-                bufferpos += 150;
-                //
-                //
-                //        buffer[bufferpos / 50] = (X & 15) * 16;
-                //
-                //
-
-            } else {
-                //mem[54296] = 6;
-                X = 6;
-                bufferpos += 150;
-                //
-                //        buffer[bufferpos / 50] = (X & 15) * 16;
-                //
-                //
-            }
-
-            for(X = wait2; X > 0; X--)
-                ; //wait
-            mem56--;
-        } while(mem56 != 0);
-
-        Y++;
-        phase1++;
-
-    } while(phase1 != 0);
-    //  if (phase1 != 0) goto pos48321;
-    A = 1;
-    mem44 = 1;
-    mem66 = Y;
-    Y = mem49;
-    return;
-}
-
-// Create a rising or falling inflection 30 frames prior to
-// index X. A rising inflection is used for questions, and
-// a falling inflection is used for statements.
-
-void STM32SAM::AddInflection(unsigned char mem48, unsigned char phase1) {
-    //pos48372:
-    //  mem48 = 255;
-    //pos48376:
-
-    // store the location of the punctuation
-    mem49 = X;
-    A = X;
-    int Atemp = A;
-
-    // backup 30 frames
-    A = A - 30;
-    // if index is before buffer, point to start of buffer
-    if(Atemp <= 30) A = 0;
-    X = A;
-
-    // FIXME: Explain this fix better, it's not obvious
-    // ML : A =, fixes a problem with invalid pitch with '.'
-    while((A = pitches[X]) == 127) X++;
-
-pos48398:
-    //48398: CLC
-    //48399: ADC 48
-
-    // add the inflection direction
-    A += mem48;
-    phase1 = A;
-
-    // set the inflection
-    pitches[X] = A;
-pos48406:
-
-    // increment the position
-    X++;
-
-    // exit if the punctuation has been reached
-    if(X == mem49) return; //goto pos47615;
-    if(pitches[X] == 255) goto pos48406;
-    A = phase1;
-    goto pos48398;
-}
-
-/*
-    SAM's voice can be altered by changing the frequencies of the
-    mouth formant (F1) and the throat formant (F2). Only the voiced
-    phonemes (5-29 and 48-53) are altered.
-*/
-void STM32SAM::SetMouthThroat() {
-    unsigned char initialFrequency;
-    unsigned char newFrequency = 0;
-    //unsigned char mouth; //mem38880
-    //unsigned char throat; //mem38881
-
-    // mouth formants (F1) 5..29
-    unsigned char mouthFormants5_29[30] = {0,  0,  0,  0,  0,  10, 14, 19, 24, 27,
-                                           23, 21, 16, 20, 14, 18, 14, 18, 18, 16,
-                                           13, 15, 11, 18, 14, 11, 9,  6,  6,  6};
-
-    // throat formants (F2) 5..29
-    unsigned char throatFormants5_29[30] = {255, 255, 255, 255, 255, 84, 73, 67, 63, 40,
-                                            44,  31,  37,  45,  73,  49, 36, 30, 51, 37,
-                                            29,  69,  24,  50,  30,  24, 83, 46, 54, 86};
-
-    // there must be no zeros in this 2 tables
-    // formant 1 frequencies (mouth) 48..53
-    unsigned char mouthFormants48_53[6] = {19, 27, 21, 27, 18, 13};
-
-    // formant 2 frequencies (throat) 48..53
-    unsigned char throatFormants48_53[6] = {72, 39, 31, 43, 30, 34};
-
-    unsigned char pos = 5; //mem39216
-    //pos38942:
-    // recalculate formant frequencies 5..29 for the mouth (F1) and throat (F2)
-    while(pos != 30) {
-        // recalculate mouth frequency
-        initialFrequency = mouthFormants5_29[pos];
-        if(initialFrequency != 0) newFrequency = trans(mouth, initialFrequency);
-        freq1data[pos] = newFrequency;
-
-        // recalculate throat frequency
-        initialFrequency = throatFormants5_29[pos];
-        if(initialFrequency != 0) newFrequency = trans(throat, initialFrequency);
-        freq2data[pos] = newFrequency;
-        pos++;
-    }
-
-    //pos39059:
-    // recalculate formant frequencies 48..53
-    pos = 48;
-    Y = 0;
-    while(pos != 54) {
-        // recalculate F1 (mouth formant)
-        initialFrequency = mouthFormants48_53[Y];
-        newFrequency = trans(mouth, initialFrequency);
-        freq1data[pos] = newFrequency;
-
-        // recalculate F2 (throat formant)
-        initialFrequency = throatFormants48_53[Y];
-        newFrequency = trans(throat, initialFrequency);
-        freq2data[pos] = newFrequency;
-        Y++;
-        pos++;
-    }
-}
-
-//return = (mem39212*mem39213) >> 1
-unsigned char STM32SAM::trans(unsigned char mem39212, unsigned char mem39213) {
-    //pos39008:
-    unsigned char carry;
-    int temp;
-    unsigned char mem39214, mem39215;
-    A = 0;
-    mem39215 = 0;
-    mem39214 = 0;
-    X = 8;
-    do {
-        carry = mem39212 & 1;
-        mem39212 = mem39212 >> 1;
-        if(carry != 0) {
-            /*
-                  39018: LSR 39212
-                  39021: BCC 39033
-      */
-            carry = 0;
-            A = mem39215;
-            temp = (int)A + (int)mem39213;
-            A = A + mem39213;
-            if(temp > 255) carry = 1;
-            mem39215 = A;
-        }
-        temp = mem39215 & 1;
-        mem39215 = (mem39215 >> 1) | (carry ? 128 : 0);
-        carry = temp;
-        //39033: ROR 39215
-        X--;
-    } while(X != 0);
-    temp = mem39214 & 128;
-    mem39214 = (mem39214 << 1) | (carry ? 1 : 0);
-    carry = temp;
-    temp = mem39215 & 128;
-    mem39215 = (mem39215 << 1) | (carry ? 1 : 0);
-    carry = temp;
-
-    return mem39215;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////
-//
-//           Sam
-//
-////////////////////////////////////////////////////////////////////////////////////////////
-
-//char input[]={"/HAALAOAO MAYN NAAMAEAE IHSTT SAEBAASTTIHAAN \x9b\x9b\0"};
-//unsigned char input[]={"/HAALAOAO \x9b\0"};
-//unsigned char input[]={"AA \x9b\0"};
-//unsigned char input[] = {"GUH5DEHN TAEG\x9b\0"};
-
-//unsigned char input[]={"AY5 AEM EY TAO4LXKIHNX KAX4MPYUX4TAH. GOW4 AH/HEH3D PAHNK.MEYK MAY8 DEY.\x9b\0"};
-//unsigned char input[]={"/HEH3LOW2, /HAW AH YUX2 TUXDEY. AY /HOH3P YUX AH FIYLIHNX OW4 KEY.\x9b\0"};
-//unsigned char input[]={"/HEY2, DHIHS IH3Z GREY2T. /HAH /HAH /HAH.AYL BIY5 BAEK.\x9b\0"};
-//unsigned char input[]={"/HAH /HAH /HAH \x9b\0"};
-//unsigned char input[]={"/HAH /HAH /HAH.\x9b\0"};
-//unsigned char input[]={".TUW BIY5Y3,, OHR NAA3T - TUW BIY5IYIY., DHAE4T IHZ DHAH KWEH4SCHAHN.\x9b\0"};
-//unsigned char input[]={"/HEY2, DHIHS \x9b\0"};
-
-//unsigned char input[]={" IYIHEHAEAAAHAOOHUHUXERAXIX  \x9b\0"};
-//unsigned char input[]={" RLWWYMNNXBDGJZZHVDH \x9b\0"};
-//unsigned char input[]={" SSHFTHPTKCH/H \x9b\0"};
-
-//unsigned char input[]={" EYAYOYAWOWUW ULUMUNQ YXWXRXLX/XDX\x9b\0"};
-
-void STM32SAM::SetInput(char* _input) {
-    int i, l;
-    l = strlen(_input);
-    if(l > 254) l = 254;
-    for(i = 0; i < l; i++) {
-        input[i] = _input[i];
-    }
-    input[l] = 0;
-}
-
-// 168=pitches
-// 169=frequency1
-// 170=frequency2
-// 171=frequency3
-// 172=amplitude1
-// 173=amplitude2
-// 174=amplitude3
-
-void STM32SAM::Init() {
-    bufferpos = 0;
-    int i;
-    SetMouthThroat();
-
-    bufferpos = 0;
-    // TODO, check for free the memory, 10 seconds of output should be more than enough
-    //buffer = malloc(22050*10);
-
-    // buffer = (char*) calloc(1, sizeof(char));
-
-    /*
-    freq2data = &mem[45136];
-    freq1data = &mem[45056];
-    freq3data = &mem[45216];
-  */
-    //pitches = &mem[43008];
-    /*
-    frequency1 = &mem[43264];
-    frequency2 = &mem[43520];
-    frequency3 = &mem[43776];
-  */
-    /*
-    amplitude1 = &mem[44032];
-    amplitude2 = &mem[44288];
-    amplitude3 = &mem[44544];
-  */
-    //phoneme = &mem[39904];
-    /*
-    ampl1data = &mem[45296];
-    ampl2data = &mem[45376];
-    ampl3data = &mem[45456];
-  */
-
-    for(i = 0; i < 256; i++) {
-        stress[i] = 0;
-        phonemeLength[i] = 0;
-    }
-
-    for(i = 0; i < 60; i++) {
-        phonemeIndexOutput[i] = 0;
-        stressOutput[i] = 0;
-        phonemeLengthOutput[i] = 0;
-    }
-    phonemeindex[255] =
-        255; //to prevent buffer overflow // ML : changed from 32 to 255 to stop freezing with long inputs
-}
-
-//int Code39771()
-int STM32SAM::SAMMain() {
-    Init();
-    phonemeindex[255] = 32; //to prevent buffer overflow
-
-    if(!Parser1()) {
-        return 0;
-    }
-
-    Parser2();
-    CopyStress();
-    SetPhonemeLength();
-    AdjustLengths();
-    Code41240();
-    do {
-        A = phonemeindex[X];
-        if(A > 80) {
-            phonemeindex[X] = 255;
-            break; // error: delete all behind it
-        }
-        X++;
-    } while(X != 0);
-
-    //pos39848:
-    InsertBreath();
-
-    //mem[40158] = 255;
-
-    PrepareOutput();
-
-    return 1;
-}
-
-//void Code48547()
-void STM32SAM::PrepareOutput() {
-    A = 0;
-    X = 0;
-    Y = 0;
-
-    //pos48551:
-    while(1) {
-        A = phonemeindex[X];
-        if(A == 255) {
-            A = 255;
-            phonemeIndexOutput[Y] = 255;
-            Render();
-            return;
-        }
-        if(A == 254) {
-            X++;
-            int temp = X;
-            //mem[48546] = X;
-            phonemeIndexOutput[Y] = 255;
-            Render();
-            //X = mem[48546];
-            X = temp;
-            Y = 0;
-            continue;
-        }
-
-        if(A == 0) {
-            X++;
-            continue;
-        }
-
-        phonemeIndexOutput[Y] = A;
-        phonemeLengthOutput[Y] = phonemeLength[X];
-        stressOutput[Y] = stress[X];
-        X++;
-        Y++;
-    }
-}
-
-//void Code41014()
-void STM32SAM::Insert(
-    unsigned char position /*var57*/,
-    unsigned char mem60,
-    unsigned char mem59,
-    unsigned char mem58) {
-    int i;
-    for(i = 253; i >= position; i--) // ML : always keep last safe-guarding 255
-    {
-        phonemeindex[i + 1] = phonemeindex[i];
-        phonemeLength[i + 1] = phonemeLength[i];
-        stress[i + 1] = stress[i];
-    }
-
-    phonemeindex[position] = mem60;
-    phonemeLength[position] = mem59;
-    stress[position] = mem58;
-    return;
-}
-
-//void Code48431()
-void STM32SAM::InsertBreath() {
-    unsigned char mem54;
-    unsigned char mem55;
-    unsigned char index; //variable Y
-    mem54 = 255;
-    X++;
-    mem55 = 0;
-    unsigned char mem66 = 0;
-    while(1) {
-        //pos48440:
-        X = mem66;
-        index = phonemeindex[X];
-        if(index == 255) return;
-        mem55 += phonemeLength[X];
-
-        if(mem55 < 232) {
-            if(index != 254) // ML : Prevents an index out of bounds problem
-            {
-                A = flags2[index] & 1;
-                if(A != 0) {
-                    X++;
-                    mem55 = 0;
-                    Insert(X, 254, mem59, 0);
-                    mem66++;
-                    mem66++;
-                    continue;
-                }
-            }
-            if(index == 0) mem54 = X;
-            mem66++;
-            continue;
-        }
-        X = mem54;
-        phonemeindex[X] = 31; // 'Q*' glottal stop
-        phonemeLength[X] = 4;
-        stress[X] = 0;
-        X++;
-        mem55 = 0;
-        Insert(X, 254, mem59, 0);
-        X++;
-        mem66 = X;
-    }
-}
-
-// Iterates through the phoneme buffer, copying the stress value from
-// the following phoneme under the following circumstance:
-
-//     1. The current phoneme is voiced, excluding plosives and fricatives
-//     2. The following phoneme is voiced, excluding plosives and fricatives, and
-//     3. The following phoneme is stressed
-//
-//  In those cases, the stress value+1 from the following phoneme is copied.
-//
-// For example, the word LOITER is represented as LOY5TER, with as stress
-// of 5 on the diphtong OY. This routine will copy the stress value of 6 (5+1)
-// to the L that precedes it.
-
-//void Code41883()
-void STM32SAM::CopyStress() {
-    // loop thought all the phonemes to be output
-    unsigned char pos = 0; //mem66
-    while(1) {
-        // get the phomene
-        Y = phonemeindex[pos];
-
-        // exit at end of buffer
-        if(Y == 255) return;
-
-        // if CONSONANT_FLAG set, skip - only vowels get stress
-        if((flags[Y] & 64) == 0) {
-            pos++;
-            continue;
-        }
-        // get the next phoneme
-        Y = phonemeindex[pos + 1];
-        if(Y == 255) //prevent buffer overflow
-        {
-            pos++;
-            continue;
-        } else
-            // if the following phoneme is a vowel, skip
-            if((flags[Y] & 128) == 0) {
-                pos++;
-                continue;
-            }
-
-        // get the stress value at the next position
-        Y = stress[pos + 1];
-
-        // if next phoneme is not stressed, skip
-        if(Y == 0) {
-            pos++;
-            continue;
-        }
-
-        // if next phoneme is not a VOWEL OR ER, skip
-        if((Y & 128) != 0) {
-            pos++;
-            continue;
-        }
-
-        // copy stress from prior phoneme to this one
-        stress[pos] = Y + 1;
-
-        // advance pointer
-        pos++;
-    }
-}
-
-// The input[] buffer contains a string of phonemes and stress markers along
-// the lines of:
-//
-//     DHAX KAET IHZ AH5GLIY. <0x9B>
-//
-// The byte 0x9B marks the end of the buffer. Some phonemes are 2 bytes
-// long, such as "DH" and "AX". Others are 1 byte long, such as "T" and "Z".
-// There are also stress markers, such as "5" and ".".
-//
-// The first character of the phonemes are stored in the table signInputTable1[].
-// The second character of the phonemes are stored in the table signInputTable2[].
-// The stress characters are arranged in low to high stress order in stressInputTable[].
-//
-// The following process is used to parse the input[] buffer:
-//
-// Repeat until the <0x9B> character is reached:
-//
-//        First, a search is made for a 2 character match for phonemes that do not
-//        end with the '*' (wildcard) character. On a match, the index of the phoneme
-//        is added to phonemeIndex[] and the buffer position is advanced 2 bytes.
-//
-//        If this fails, a search is made for a 1 character match against all
-//        phoneme names ending with a '*' (wildcard). If this succeeds, the
-//        phoneme is added to phonemeIndex[] and the buffer position is advanced
-//        1 byte.
-//
-//        If this fails, search for a 1 character match in the stressInputTable[].
-//        If this succeeds, the stress value is placed in the last stress[] table
-//        at the same index of the last added phoneme, and the buffer position is
-//        advanced by 1 byte.
-//
-//        If this fails, return a 0.
-//
-// On success:
-//
-//    1. phonemeIndex[] will contain the index of all the phonemes.
-//    2. The last index in phonemeIndex[] will be 255.
-//    3. stress[] will contain the stress value for each phoneme
-
-// input[] holds the string of phonemes, each two bytes wide
-// signInputTable1[] holds the first character of each phoneme
-// signInputTable2[] holds te second character of each phoneme
-// phonemeIndex[] holds the indexes of the phonemes after parsing input[]
-//
-// The parser scans through the input[], finding the names of the phonemes
-// by searching signInputTable1[] and signInputTable2[]. On a match, it
-// copies the index of the phoneme into the phonemeIndexTable[].
-//
-// The character <0x9B> marks the end of text in input[]. When it is reached,
-// the index 255 is placed at the end of the phonemeIndexTable[], and the
-// function returns with a 1 indicating success.
-int STM32SAM::Parser1() {
-    int i;
-    unsigned char sign1;
-    unsigned char sign2;
-    unsigned char position = 0;
-    X = 0;
-    A = 0;
-    Y = 0;
-
-    // CLEAR THE STRESS TABLE
-    for(i = 0; i < 256; i++) stress[i] = 0;
-
-    // THIS CODE MATCHES THE PHONEME LETTERS TO THE TABLE
-    // pos41078:
-    while(1) {
-        // GET THE FIRST CHARACTER FROM THE PHONEME BUFFER
-        sign1 = input[X];
-        // TEST FOR 155 (�) END OF LINE MARKER
-        if(sign1 == 155) {
-            // MARK ENDPOINT AND RETURN
-            phonemeindex[position] = 255; //mark endpoint
-            // REACHED END OF PHONEMES, SO EXIT
-            return 1; //all ok
-        }
-
-        // GET THE NEXT CHARACTER FROM THE BUFFER
-        X++;
-        sign2 = input[X];
-
-        // NOW sign1 = FIRST CHARACTER OF PHONEME, AND sign2 = SECOND CHARACTER OF PHONEME
-
-        // TRY TO MATCH PHONEMES ON TWO TWO-CHARACTER NAME
-        // IGNORE PHONEMES IN TABLE ENDING WITH WILDCARDS
-
-        // SET INDEX TO 0
-        Y = 0;
-    pos41095:
-
-        // GET FIRST CHARACTER AT POSITION Y IN signInputTable
-        // --> should change name to PhonemeNameTable1
-        A = signInputTable1[Y];
-
-        // FIRST CHARACTER MATCHES?
-        if(A == sign1) {
-            // GET THE CHARACTER FROM THE PhonemeSecondLetterTable
-            A = signInputTable2[Y];
-            // NOT A SPECIAL AND MATCHES SECOND CHARACTER?
-            if((A != '*') && (A == sign2)) {
-                // STORE THE INDEX OF THE PHONEME INTO THE phomeneIndexTable
-                phonemeindex[position] = Y;
-
-                // ADVANCE THE POINTER TO THE phonemeIndexTable
-                position++;
-                // ADVANCE THE POINTER TO THE phonemeInputBuffer
-                X++;
-
-                // CONTINUE PARSING
-                continue;
-            }
-        }
-
-        // NO MATCH, TRY TO MATCH ON FIRST CHARACTER TO WILDCARD NAMES (ENDING WITH '*')
-
-        // ADVANCE TO THE NEXT POSITION
-        Y++;
-        // IF NOT END OF TABLE, CONTINUE
-        if(Y != 81) goto pos41095;
-
-        // REACHED END OF TABLE WITHOUT AN EXACT (2 CHARACTER) MATCH.
-        // THIS TIME, SEARCH FOR A 1 CHARACTER MATCH AGAINST THE WILDCARDS
-
-        // RESET THE INDEX TO POINT TO THE START OF THE PHONEME NAME TABLE
-        Y = 0;
-    pos41134:
-        // DOES THE PHONEME IN THE TABLE END WITH '*'?
-        if(signInputTable2[Y] == '*') {
-            // DOES THE FIRST CHARACTER MATCH THE FIRST LETTER OF THE PHONEME
-            if(signInputTable1[Y] == sign1) {
-                // SAVE THE POSITION AND MOVE AHEAD
-                phonemeindex[position] = Y;
-
-                // ADVANCE THE POINTER
-                position++;
-
-                // CONTINUE THROUGH THE LOOP
-                continue;
-            }
-        }
-        Y++;
-        if(Y != 81) goto pos41134; //81 is size of PHONEME NAME table
-
-        // FAILED TO MATCH WITH A WILDCARD. ASSUME THIS IS A STRESS
-        // CHARACTER. SEARCH THROUGH THE STRESS TABLE
-
-        // SET INDEX TO POSITION 8 (END OF STRESS TABLE)
-        Y = 8;
-
-        // WALK BACK THROUGH TABLE LOOKING FOR A MATCH
-        while((sign1 != stressInputTable[Y]) && (Y > 0)) {
-            // DECREMENT INDEX
-            Y--;
-        }
-
-        // REACHED THE END OF THE SEARCH WITHOUT BREAKING OUT OF LOOP?
-        if(Y == 0) {
-            //mem[39444] = X;
-            //41181: JSR 42043 //Error
-            // FAILED TO MATCH ANYTHING, RETURN 0 ON FAILURE
-            return 0;
-        }
-        // SET THE STRESS FOR THE PRIOR PHONEME
-        stress[position - 1] = Y;
-    } //while
-}
-
-//change phonemelength depedendent on stress
-//void Code41203()
-void STM32SAM::SetPhonemeLength() {
-    unsigned char A;
-    int position = 0;
-    while(phonemeindex[position] != 255) {
-        A = stress[position];
-        //41218: BMI 41229
-        if((A == 0) || ((A & 128) != 0)) {
-            phonemeLength[position] = phonemeLengthTable[phonemeindex[position]];
-        } else {
-            phonemeLength[position] = phonemeStressedLengthTable[phonemeindex[position]];
-        }
-        position++;
-    }
-}
-
-void STM32SAM::Code41240() {
-    unsigned char pos = 0;
-
-    while(phonemeindex[pos] != 255) {
-        unsigned char index; //register AC
-        X = pos;
-        index = phonemeindex[pos];
-        if((flags[index] & 2) == 0) {
-            pos++;
-            continue;
-        } else if((flags[index] & 1) == 0) {
-            Insert(pos + 1, index + 1, phonemeLengthTable[index + 1], stress[pos]);
-            Insert(pos + 2, index + 2, phonemeLengthTable[index + 2], stress[pos]);
-            pos += 3;
-            continue;
-        }
-
-        do {
-            X++;
-            A = phonemeindex[X];
-        } while(A == 0);
-
-        if(A != 255) {
-            if((flags[A] & 8) != 0) {
-                pos++;
-                continue;
-            }
-            if((A == 36) || (A == 37)) {
-                pos++; // '/H' '/X'
-                continue;
-            }
-        }
-
-        Insert(pos + 1, index + 1, phonemeLengthTable[index + 1], stress[pos]);
-        Insert(pos + 2, index + 2, phonemeLengthTable[index + 2], stress[pos]);
-        pos += 3;
-    }
-}
-
-// Rewrites the phonemes using the following rules:
-//
-//       <DIPHTONG ENDING WITH WX> -> <DIPHTONG ENDING WITH WX> WX
-//       <DIPHTONG NOT ENDING WITH WX> -> <DIPHTONG NOT ENDING WITH WX> YX
-//       UL -> AX L
-//       UM -> AX M
-//       <STRESSED VOWEL> <SILENCE> <STRESSED VOWEL> -> <STRESSED VOWEL> <SILENCE> Q <VOWEL>
-//       T R -> CH R
-//       D R -> J R
-//       <VOWEL> R -> <VOWEL> RX
-//       <VOWEL> L -> <VOWEL> LX
-//       G S -> G Z
-//       K <VOWEL OR DIPHTONG NOT ENDING WITH IY> -> KX <VOWEL OR DIPHTONG NOT ENDING WITH IY>
-//       G <VOWEL OR DIPHTONG NOT ENDING WITH IY> -> GX <VOWEL OR DIPHTONG NOT ENDING WITH IY>
-//       S P -> S B
-//       S T -> S D
-//       S K -> S G
-//       S KX -> S GX
-//       <ALVEOLAR> UW -> <ALVEOLAR> UX
-//       CH -> CH CH' (CH requires two phonemes to represent it)
-//       J -> J J' (J requires two phonemes to represent it)
-//       <UNSTRESSED VOWEL> T <PAUSE> -> <UNSTRESSED VOWEL> DX <PAUSE>
-//       <UNSTRESSED VOWEL> D <PAUSE>  -> <UNSTRESSED VOWEL> DX <PAUSE>
-
-//void Code41397()
-void STM32SAM::Parser2() {
-    unsigned char pos = 0; //mem66;
-    unsigned char mem58 = 0;
-
-    // Loop through phonemes
-    while(1) {
-        // SET X TO THE CURRENT POSITION
-        X = pos;
-        // GET THE PHONEME AT THE CURRENT POSITION
-        A = phonemeindex[pos];
-
-        // Is phoneme pause?
-        if(A == 0) {
-            // Move ahead to the
-            pos++;
-            continue;
-        }
-
-        // If end of phonemes flag reached, exit routine
-        if(A == 255) return;
-
-        // Copy the current phoneme index to Y
-        Y = A;
-
-        // RULE:
-        //       <DIPHTONG ENDING WITH WX> -> <DIPHTONG ENDING WITH WX> WX
-        //       <DIPHTONG NOT ENDING WITH WX> -> <DIPHTONG NOT ENDING WITH WX> YX
-        // Example: OIL, COW
-
-        // Check for DIPHTONG
-        if((flags[A] & 16) == 0) goto pos41457;
-
-        // Not a diphthong. Get the stress
-        mem58 = stress[pos];
-
-        // End in IY sound?
-        A = flags[Y] & 32;
-
-        // If ends with IY, use YX, else use WX
-        if(A == 0)
-            A = 20;
-        else
-            A = 21; // 'WX' = 20 'YX' = 21
-        //pos41443:
-        // Insert at WX or YX following, copying the stress
-
-        Insert(pos + 1, A, mem59, mem58);
-        X = pos;
-        // Jump to ???
-        goto pos41749;
-
-    pos41457:
-
-        // RULE:
-        //       UL -> AX L
-        // Example: MEDDLE
-
-        // Get phoneme
-        A = phonemeindex[X];
-        // Skip this rule if phoneme is not UL
-        if(A != 78) goto pos41487; // 'UL'
-        A = 24; // 'L'                 //change 'UL' to 'AX L'
-
-    pos41466:
-        // Get current phoneme stress
-        mem58 = stress[X];
-
-        // Change UL to AX
-        phonemeindex[X] = 13; // 'AX'
-        // Perform insert. Note code below may jump up here with different values
-        Insert(X + 1, A, mem59, mem58);
-        pos++;
-        // Move to next phoneme
-        continue;
-
-    pos41487:
-
-        // RULE:
-        //       UM -> AX M
-        // Example: ASTRONOMY
-
-        // Skip rule if phoneme != UM
-        if(A != 79) goto pos41495; // 'UM'
-        // Jump up to branch - replaces current phoneme with AX and continues
-        A = 27; // 'M'  //change 'UM' to  'AX M'
-
-        goto pos41466;
-    pos41495:
-
-        // RULE:
-        //       UN -> AX N
-        // Example: FUNCTION
-
-        // Skip rule if phoneme != UN
-        if(A != 80) goto pos41503; // 'UN'
-
-        // Jump up to branch - replaces current phoneme with AX and continues
-        A = 28; // 'N' //change UN to 'AX N'
-
-        goto pos41466;
-    pos41503:
-
-        // RULE:
-        //       <STRESSED VOWEL> <SILENCE> <STRESSED VOWEL> -> <STRESSED VOWEL> <SILENCE> Q <VOWEL>
-        // EXAMPLE: AWAY EIGHT
-
-        Y = A;
-        // VOWEL set?
-        A = flags[A] & 128;
-
-        // Skip if not a vowel
-        if(A != 0) {
-            // Get the stress
-            A = stress[X];
-
-            // If stressed...
-            if(A != 0) {
-                // Get the following phoneme
-                X++;
-                A = phonemeindex[X];
-                // If following phoneme is a pause
-
-                if(A == 0) {
-                    // Get the phoneme following pause
-                    X++;
-                    Y = phonemeindex[X];
-
-                    // Check for end of buffer flag
-                    if(Y == 255) //buffer overflow
-                        // ??? Not sure about these flags
-                        A = 65 & 128;
-                    else
-                        // And VOWEL flag to current phoneme's flags
-                        A = flags[Y] & 128;
-
-                    // If following phonemes is not a pause
-                    if(A != 0) {
-                        // If the following phoneme is not stressed
-                        A = stress[X];
-                        if(A != 0) {
-                            // 31 = 'Q'
-                            Insert(X, 31, mem59, 0);
-                            pos++;
-                            continue;
-                        }
-                    }
-                }
-            }
-        }
-
-        // RULES FOR PHONEMES BEFORE R
-        //        T R -> CH R
-        // Example: TRACK
-
-        // Get current position and phoneme
-        X = pos;
-        A = phonemeindex[pos];
-        if(A != 23) goto pos41611; // 'R'
-
-        // Look at prior phoneme
-        X--;
-        A = phonemeindex[pos - 1];
-        //pos41567:
-        if(A == 69) // 'T'
-        {
-            phonemeindex[pos - 1] = 42;
-            goto pos41779;
-        }
-
-        // RULES FOR PHONEMES BEFORE R
-        //        D R -> J R
-        // Example: DRY
-
-        // Prior phonemes D?
-        if(A == 57) // 'D'
-        {
-            // Change D to J
-            phonemeindex[pos - 1] = 44;
-
-            goto pos41788;
-        }
-
-        // RULES FOR PHONEMES BEFORE R
-        //        <VOWEL> R -> <VOWEL> RX
-        // Example: ART
-
-        // If vowel flag is set change R to RX
-        A = flags[A] & 128;
-
-        if(A != 0) phonemeindex[pos] = 18; // 'RX'
-
-        // continue to next phoneme
-        pos++;
-        continue;
-
-    pos41611:
-
-        // RULE:
-        //       <VOWEL> L -> <VOWEL> LX
-        // Example: ALL
-
-        // Is phoneme L?
-        if(A == 24) // 'L'
-        {
-            // If prior phoneme does not have VOWEL flag set, move to next phoneme
-            if((flags[phonemeindex[pos - 1]] & 128) == 0) {
-                pos++;
-                continue;
-            }
-            // Prior phoneme has VOWEL flag set, so change L to LX and move to next phoneme
-
-            phonemeindex[X] = 19; // 'LX'
-            pos++;
-            continue;
-        }
-
-        // RULE:
-        //       G S -> G Z
-        //
-        // Can't get to fire -
-        //       1. The G -> GX rule intervenes
-        //       2. Reciter already replaces GS -> GZ
-
-        // Is current phoneme S?
-        if(A == 32) // 'S'
-        {
-            // If prior phoneme is not G, move to next phoneme
-            if(phonemeindex[pos - 1] != 60) {
-                pos++;
-                continue;
-            }
-            // Replace S with Z and move on
-
-            phonemeindex[pos] = 38; // 'Z'
-            pos++;
-            continue;
-        }
-
-        // RULE:
-        //             K <VOWEL OR DIPHTONG NOT ENDING WITH IY> -> KX <VOWEL OR DIPHTONG NOT ENDING WITH IY>
-        // Example: COW
-
-        // Is current phoneme K?
-        if(A == 72) // 'K'
-        {
-            // Get next phoneme
-            Y = phonemeindex[pos + 1];
-            // If at end, replace current phoneme with KX
-            if(Y == 255)
-                phonemeindex[pos] = 75; // ML : prevents an index out of bounds problem
-            else {
-                // VOWELS AND DIPHTONGS ENDING WITH IY SOUND flag set?
-                A = flags[Y] & 32;
-
-                // Replace with KX
-                if(A == 0) phonemeindex[pos] = 75; // 'KX'
-            }
-        } else
-
-            // RULE:
-            //             G <VOWEL OR DIPHTONG NOT ENDING WITH IY> -> GX <VOWEL OR DIPHTONG NOT ENDING WITH IY>
-            // Example: GO
-
-            // Is character a G?
-            if(A == 60) // 'G'
-            {
-                // Get the following character
-                unsigned char index = phonemeindex[pos + 1];
-
-                // At end of buffer?
-                if(index == 255) //prevent buffer overflow
-                {
-                    pos++;
-                    continue;
-                } else
-                    // If diphtong ending with YX, move continue processing next phoneme
-                    if((flags[index] & 32) != 0) {
-                        pos++;
-                        continue;
-                    }
-                // replace G with GX and continue processing next phoneme
-
-                phonemeindex[pos] = 63; // 'GX'
-                pos++;
-                continue;
-            }
-
-        // RULE:
-        //      S P -> S B
-        //      S T -> S D
-        //      S K -> S G
-        //      S KX -> S GX
-        // Examples: SPY, STY, SKY, SCOWL
-
-        Y = phonemeindex[pos];
-        //pos41719:
-        // Replace with softer version?
-        A = flags[Y] & 1;
-        if(A == 0) goto pos41749;
-        A = phonemeindex[pos - 1];
-        if(A != 32) // 'S'
-        {
-            A = Y;
-            goto pos41812;
-        }
-        // Replace with softer version
-
-        phonemeindex[pos] = Y - 12;
-        pos++;
-        continue;
-
-    pos41749:
-
-        // RULE:
-        //      <ALVEOLAR> UW -> <ALVEOLAR> UX
-        //
-        // Example: NEW, DEW, SUE, ZOO, THOO, TOO
-
-        //       UW -> UX
-
-        A = phonemeindex[X];
-        if(A == 53) // 'UW'
-        {
-            // ALVEOLAR flag set?
-            Y = phonemeindex[X - 1];
-            A = flags2[Y] & 4;
-            // If not set, continue processing next phoneme
-            if(A == 0) {
-                pos++;
-                continue;
-            }
-
-            phonemeindex[X] = 16;
-            pos++;
-            continue;
-        }
-    pos41779:
-
-        // RULE:
-        //       CH -> CH CH' (CH requires two phonemes to represent it)
-        // Example: CHEW
-
-        if(A == 42) // 'CH'
-        {
-            //        pos41783:
-
-            Insert(X + 1, A + 1, mem59, stress[X]);
-            pos++;
-            continue;
-        }
-
-    pos41788:
-
-        // RULE:
-        //       J -> J J' (J requires two phonemes to represent it)
-        // Example: JAY
-
-        if(A == 44) // 'J'
-        {
-            Insert(X + 1, A + 1, mem59, stress[X]);
-            pos++;
-            continue;
-        }
-
-        // Jump here to continue
-    pos41812:
-
-        // RULE: Soften T following vowel
-        // NOTE: This rule fails for cases such as "ODD"
-        //       <UNSTRESSED VOWEL> T <PAUSE> -> <UNSTRESSED VOWEL> DX <PAUSE>
-        //       <UNSTRESSED VOWEL> D <PAUSE>  -> <UNSTRESSED VOWEL> DX <PAUSE>
-        // Example: PARTY, TARDY
-
-        // Past this point, only process if phoneme is T or D
-
-        if(A != 69) // 'T'
-            if(A != 57) {
-                pos++; // 'D'
-                continue;
-            }
-        //pos41825:
-
-        // If prior phoneme is not a vowel, continue processing phonemes
-        if((flags[phonemeindex[X - 1]] & 128) == 0) {
-            pos++;
-            continue;
-        }
-
-        // Get next phoneme
-        X++;
-        A = phonemeindex[X];
-        //pos41841
-        // Is the next phoneme a pause?
-        if(A != 0) {
-            // If next phoneme is not a pause, continue processing phonemes
-            if((flags[A] & 128) == 0) {
-                pos++;
-                continue;
-            }
-            // If next phoneme is stressed, continue processing phonemes
-            // FIXME: How does a pause get stressed?
-            if(stress[X] != 0) {
-                pos++;
-                continue;
-            }
-            //pos41856:
-            // Set phonemes to DX
-
-            phonemeindex[pos] = 30; // 'DX'
-        } else {
-            A = phonemeindex[X + 1];
-            if(A == 255) //prevent buffer overflow
-                A = 65 & 128;
-            else
-                // Is next phoneme a vowel or ER?
-                A = flags[A] & 128;
-
-            if(A != 0) phonemeindex[pos] = 30; // 'DX'
-        }
-
-        pos++;
-
-    } // while
-} // parser 2
-
-// Applies various rules that adjust the lengths of phonemes
-//
-//         Lengthen <FRICATIVE> or <VOICED> between <VOWEL> and <PUNCTUATION> by 1.5
-//         <VOWEL> <RX | LX> <CONSONANT> - decrease <VOWEL> length by 1
-//         <VOWEL> <UNVOICED PLOSIVE> - decrease vowel by 1/8th
-//         <VOWEL> <UNVOICED CONSONANT> - increase vowel by 1/2 + 1
-//         <NASAL> <STOP CONSONANT> - set nasal = 5, consonant = 6
-//         <VOICED STOP CONSONANT> {optional silence} <STOP CONSONANT> - shorten both to 1/2 + 1
-//         <LIQUID CONSONANT> <DIPHTONG> - decrease by 2
-
-//void Code48619()
-void STM32SAM::AdjustLengths() {
-    // LENGTHEN VOWELS PRECEDING PUNCTUATION
-    //
-    // Search for punctuation. If found, back up to the first vowel, then
-    // process all phonemes between there and up to (but not including) the punctuation.
-    // If any phoneme is found that is a either a fricative or voiced, the duration is
-    // increased by (length * 1.5) + 1
-
-    // loop index
-    X = 0;
-    unsigned char index;
-
-    // iterate through the phoneme list
-    unsigned char loopIndex = 0;
-    while(1) {
-        // get a phoneme
-        index = phonemeindex[X];
-
-        // exit loop if end on buffer token
-        if(index == 255) break;
-
-        // not punctuation?
-        if((flags2[index] & 1) == 0) {
-            // skip
-            X++;
-            continue;
-        }
-
-        // hold index
-        loopIndex = X;
-
-        // Loop backwards from this point
-    pos48644:
-
-        // back up one phoneme
-        X--;
-
-        // stop once the beginning is reached
-        if(X == 0) break;
-
-        // get the preceding phoneme
-        index = phonemeindex[X];
-
-        if(index != 255) //inserted to prevent access overrun
-            if((flags[index] & 128) == 0) goto pos48644; // if not a vowel, continue looping
-
-        //pos48657:
-        do {
-            // test for vowel
-            index = phonemeindex[X];
-
-            if(index != 255) //inserted to prevent access overrun
-                // test for fricative/unvoiced or not voiced
-                if(((flags2[index] & 32) == 0) || ((flags[index] & 4) != 0)) //nochmal �berpr�fen
-                {
-                    //A = flags[Y] & 4;
-                    //if(A == 0) goto pos48688;
-
-                    // get the phoneme length
-                    A = phonemeLength[X];
-
-                    // change phoneme length to (length * 1.5) + 1
-                    A = (A >> 1) + A + 1;
-
-                    phonemeLength[X] = A;
-                }
-            // keep moving forward
-            X++;
-        } while(X != loopIndex);
-        //  if (X != loopIndex) goto pos48657;
-        X++;
-    } // while
-
-    // Similar to the above routine, but shorten vowels under some circumstances
-
-    // Loop throught all phonemes
-    loopIndex = 0;
-    //pos48697
-
-    while(1) {
-        // get a phoneme
-        X = loopIndex;
-        index = phonemeindex[X];
-
-        // exit routine at end token
-        if(index == 255) return;
-
-        // vowel?
-        A = flags[index] & 128;
-        if(A != 0) {
-            // get next phoneme
-            X++;
-            index = phonemeindex[X];
-
-            // get flags
-            if(index == 255)
-                mem56 = 65; // use if end marker
-            else
-                mem56 = flags[index];
-
-            // not a consonant
-            if((flags[index] & 64) == 0) {
-                // RX or LX?
-                if((index == 18) || (index == 19)) // 'RX' & 'LX'
-                {
-                    // get the next phoneme
-                    X++;
-                    index = phonemeindex[X];
-
-                    // next phoneme a consonant?
-                    if((flags[index] & 64) != 0) {
-                        // RULE: <VOWEL> RX | LX <CONSONANT>
-
-                        // decrease length of vowel by 1 frame
-                        phonemeLength[loopIndex]--;
-                    }
-                    // move ahead
-                    loopIndex++;
-                    continue;
-                }
-                // move ahead
-                loopIndex++;
-                continue;
-            }
-
-            // Got here if not <VOWEL>
-
-            // not voiced
-            if((mem56 & 4) == 0) {
-                // Unvoiced
-                // *, .*, ?*, ,*, -*, DX, S*, SH, F*, TH, /H, /X, CH, P*, T*, K*, KX
-
-                // not an unvoiced plosive?
-                if((mem56 & 1) == 0) {
-                    // move ahead
-                    loopIndex++;
-                    continue;
-                }
-
-                // P*, T*, K*, KX
-
-                // RULE: <VOWEL> <UNVOICED PLOSIVE>
-                // <VOWEL> <P*, T*, K*, KX>
-
-                // move back
-                X--;
-
-                // decrease length by 1/8th
-                mem56 = phonemeLength[X] >> 3;
-                phonemeLength[X] -= mem56;
-
-                // move ahead
-                loopIndex++;
-                continue;
-            }
-
-            // RULE: <VOWEL> <VOICED CONSONANT>
-            // <VOWEL> <WH, R*, L*, W*, Y*, M*, N*, NX, DX, Q*, Z*, ZH, V*, DH, J*, B*, D*, G*, GX>
-
-            // decrease length
-            A = phonemeLength[X - 1];
-            phonemeLength[X - 1] = (A >> 2) + A + 1; // 5/4*A + 1
-
-            // move ahead
-            loopIndex++;
-            continue;
-        }
-
-        // WH, R*, L*, W*, Y*, M*, N*, NX, Q*, Z*, ZH, V*, DH, J*, B*, D*, G*, GX
-
-        //pos48821:
-
-        // RULE: <NASAL> <STOP CONSONANT>
-        //       Set punctuation length to 6
-        //       Set stop consonant length to 5
-
-        // nasal?
-        if((flags2[index] & 8) != 0) {
-            // M*, N*, NX,
-
-            // get the next phoneme
-            X++;
-            index = phonemeindex[X];
-
-            // end of buffer?
-            if(index == 255)
-                A = 65 & 2; //prevent buffer overflow
-            else
-                A = flags[index] & 2; // check for stop consonant
-
-            // is next phoneme a stop consonant?
-            if(A != 0)
-
-            // B*, D*, G*, GX, P*, T*, K*, KX
-
-            {
-                // set stop consonant length to 6
-                phonemeLength[X] = 6;
-
-                // set nasal length to 5
-                phonemeLength[X - 1] = 5;
-            }
-            // move to next phoneme
-            loopIndex++;
-            continue;
-        }
-
-        // WH, R*, L*, W*, Y*, Q*, Z*, ZH, V*, DH, J*, B*, D*, G*, GX
-
-        // RULE: <VOICED STOP CONSONANT> {optional silence} <STOP CONSONANT>
-        //       Shorten both to (length/2 + 1)
-
-        // (voiced) stop consonant?
-        if((flags[index] & 2) != 0) {
-            // B*, D*, G*, GX
-
-            // move past silence
-            do {
-                // move ahead
-                X++;
-                index = phonemeindex[X];
-            } while(index == 0);
-
-            // check for end of buffer
-            if(index == 255) //buffer overflow
-            {
-                // ignore, overflow code
-                if((65 & 2) == 0) {
-                    loopIndex++;
-                    continue;
-                }
-            } else if((flags[index] & 2) == 0) {
-                // if another stop consonant, move ahead
-                loopIndex++;
-                continue;
-            }
-
-            // RULE: <UNVOICED STOP CONSONANT> {optional silence} <STOP CONSONANT>
-
-            // X gets overwritten, so hold prior X value for debug statement
-            // int debugX = X;
-            // shorten the prior phoneme length to (length/2 + 1)
-            phonemeLength[X] = (phonemeLength[X] >> 1) + 1;
-            X = loopIndex;
-
-            // also shorten this phoneme length to (length/2 +1)
-            phonemeLength[loopIndex] = (phonemeLength[loopIndex] >> 1) + 1;
-
-            // move ahead
-            loopIndex++;
-            continue;
-        }
-
-        // WH, R*, L*, W*, Y*, Q*, Z*, ZH, V*, DH, J*, **,
-
-        // RULE: <VOICED NON-VOWEL> <DIPHTONG>
-        //       Decrease <DIPHTONG> by 2
-
-        // liquic consonant?
-        if((flags2[index] & 16) != 0) {
-            // R*, L*, W*, Y*
-
-            // get the prior phoneme
-            index = phonemeindex[X - 1];
-
-            // prior phoneme a stop consonant>
-            if((flags[index] & 2) != 0) {
-                // Rule: <LIQUID CONSONANT> <DIPHTONG>
-
-                // decrease the phoneme length by 2 frames (20 ms)
-                phonemeLength[X] -= 2;
-            }
-        }
-
-        // move to next phoneme
-        loopIndex++;
-        continue;
-    }
-    //            goto pos48701;
-}
-
-// -------------------------------------------------------------------------
-// ML : Code47503 is division with remainder, and mem50 gets the sign
-void STM32SAM::Code47503(unsigned char mem52) {
-    Y = 0;
-    if((mem53 & 128) != 0) {
-        mem53 = -mem53;
-        Y = 128;
-    }
-    mem50 = Y;
-    A = 0;
-    for(X = 8; X > 0; X--) {
-        int temp = mem53;
-        mem53 = mem53 << 1;
-        A = A << 1;
-        if(temp >= 128) A++;
-        if(A >= mem52) {
-            A = A - mem52;
-            mem53++;
-        }
-    }
-
-    mem51 = A;
-    if((mem50 & 128) != 0) mem53 = -mem53;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////
-//
-//           Reciter
-//
-////////////////////////////////////////////////////////////////////////////////////////////
-
-void STM32SAM::Code37055(unsigned char mem59) {
-    X = mem59;
-    X--;
-    A = inputtemp[X];
-    Y = A;
-    A = tab36376[Y];
-    return;
-}
-
-void STM32SAM::Code37066(unsigned char mem58) {
-    X = mem58;
-    X++;
-    A = inputtemp[X];
-    Y = A;
-    A = tab36376[Y];
-}
-
-unsigned char STM32SAM::GetRuleByte(unsigned short mem62, unsigned char Y) {
-    unsigned int address = mem62;
-
-    if(mem62 >= 37541) {
-        address -= 37541;
-        return rules2[address + Y];
-    }
-    address -= 32000;
-    return rules[address + Y];
-}
-
-int STM32SAM::TextToPhonemes(unsigned char* input) // Code36484
-{
-    //unsigned char *tab39445 = &mem[39445];   //input and output
-    //unsigned char mem29;
-    unsigned char mem56; //output position for phonemes
-    unsigned char mem57;
-    unsigned char mem58;
-    unsigned char mem59;
-    unsigned char mem60;
-    unsigned char mem61;
-    unsigned short mem62; // memory position of current rule
-
-    unsigned char mem64; // position of '=' or current character
-    unsigned char mem65; // position of ')'
-    unsigned char mem66; // position of '('
-    unsigned char mem36653;
-
-    inputtemp[0] = 32;
-
-    // secure copy of input
-    // because input will be overwritten by phonemes
-    X = 1;
-    Y = 0;
-    do {
-        //pos36499:
-        A = input[Y] & 127;
-        if(A >= 112)
-            A = A & 95;
-        else if(A >= 96)
-            A = A & 79;
-
-        inputtemp[X] = A;
-        X++;
-        Y++;
-    } while(Y != 255);
-
-    X = 255;
-    inputtemp[X] = 27;
-    mem61 = 255;
-
-pos36550:
-    A = 255;
-    mem56 = 255;
-
-pos36554:
-    while(1) {
-        mem61++;
-        X = mem61;
-        A = inputtemp[X];
-        mem64 = A;
-        if(A == '[') {
-            mem56++;
-            X = mem56;
-            A = 155;
-            input[X] = 155;
-            //goto pos36542;
-            //          Code39771();    //Code39777();
-            return 1;
-        }
-
-        //pos36579:
-        if(A != '.') break;
-        X++;
-        Y = inputtemp[X];
-        A = tab36376[Y] & 1;
-        if(A != 0) break;
-        mem56++;
-        X = mem56;
-        A = '.';
-        input[X] = '.';
-    } //while
-
-    //pos36607:
-    A = mem64;
-    Y = A;
-    A = tab36376[A];
-    mem57 = A;
-    if((A & 2) != 0) {
-        mem62 = 37541;
-        goto pos36700;
-    }
-
-    //pos36630:
-    A = mem57;
-    if(A != 0) goto pos36677;
-    A = 32;
-    inputtemp[X] = ' ';
-    mem56++;
-    X = mem56;
-    if(X > 120) goto pos36654;
-    input[X] = A;
-    goto pos36554;
-
-    // -----
-
-    //36653 is unknown. Contains position
-
-pos36654:
-    input[X] = 155;
-    A = mem61;
-    mem36653 = A;
-    //  mem29 = A; // not used
-    //  Code36538(); das ist eigentlich
-    return 1;
-    //Code39771();
-    //go on if there is more input ???
-    mem61 = mem36653;
-    goto pos36550;
-
-pos36677:
-    A = mem57 & 128;
-    if(A == 0) {
-        //36683: BRK
-        return 0;
-    }
-
-    // go to the right rules for this character.
-    X = mem64 - 'A';
-    mem62 = tab37489[X] | (tab37515[X] << 8);
-
-    // -------------------------------------
-    // go to next rule
-    // -------------------------------------
-
-pos36700:
-
-    // find next rule
-    Y = 0;
-    do {
-        mem62 += 1;
-        A = GetRuleByte(mem62, Y);
-    } while((A & 128) == 0);
-    Y++;
-
-    //pos36720:
-    // find '('
-    while(1) {
-        A = GetRuleByte(mem62, Y);
-        if(A == '(') break;
-        Y++;
-    }
-    mem66 = Y;
-
-    //pos36732:
-    // find ')'
-    do {
-        Y++;
-        A = GetRuleByte(mem62, Y);
-    } while(A != ')');
-    mem65 = Y;
-
-    //pos36741:
-    // find '='
-    do {
-        Y++;
-        A = GetRuleByte(mem62, Y);
-        A = A & 127;
-    } while(A != '=');
-    mem64 = Y;
-
-    X = mem61;
-    mem60 = X;
-
-    // compare the string within the bracket
-    Y = mem66;
-    Y++;
-    //pos36759:
-    while(1) {
-        mem57 = inputtemp[X];
-        A = GetRuleByte(mem62, Y);
-        if(A != mem57) goto pos36700;
-        Y++;
-        if(Y == mem65) break;
-        X++;
-        mem60 = X;
-    }
-
-    // the string in the bracket is correct
-
-    //pos36787:
-    A = mem61;
-    mem59 = mem61;
-
-pos36791:
-    while(1) {
-        mem66--;
-        Y = mem66;
-        A = GetRuleByte(mem62, Y);
-        mem57 = A;
-        //36800: BPL 36805
-        if((A & 128) != 0) goto pos37180;
-        X = A & 127;
-        A = tab36376[X] & 128;
-        if(A == 0) break;
-        X = mem59 - 1;
-        A = inputtemp[X];
-        if(A != mem57) goto pos36700;
-        mem59 = X;
-    }
-
-    //pos36833:
-    A = mem57;
-    if(A == ' ') goto pos36895;
-    if(A == '#') goto pos36910;
-    if(A == '.') goto pos36920;
-    if(A == '&') goto pos36935;
-    if(A == '@') goto pos36967;
-    if(A == '^') goto pos37004;
-    if(A == '+') goto pos37019;
-    if(A == ':') goto pos37040;
-    //  Code42041();    //Error
-    //36894: BRK
-    return 0;
-
-    // --------------
-
-pos36895:
-    Code37055(mem59);
-    A = A & 128;
-    if(A != 0) goto pos36700;
-pos36905:
-    mem59 = X;
-    goto pos36791;
-
-    // --------------
-
-pos36910:
-    Code37055(mem59);
-    A = A & 64;
-    if(A != 0) goto pos36905;
-    goto pos36700;
-
-    // --------------
-
-pos36920:
-    Code37055(mem59);
-    A = A & 8;
-    if(A == 0) goto pos36700;
-pos36930:
-    mem59 = X;
-    goto pos36791;
-
-    // --------------
-
-pos36935:
-    Code37055(mem59);
-    A = A & 16;
-    if(A != 0) goto pos36930;
-    A = inputtemp[X];
-    if(A != 72) goto pos36700;
-    X--;
-    A = inputtemp[X];
-    if((A == 67) || (A == 83)) goto pos36930;
-    goto pos36700;
-
-    // --------------
-
-pos36967:
-    Code37055(mem59);
-    A = A & 4;
-    if(A != 0) goto pos36930;
-    A = inputtemp[X];
-    if(A != 72) goto pos36700;
-    if((A != 84) && (A != 67) && (A != 83)) goto pos36700;
-    mem59 = X;
-    goto pos36791;
-
-    // --------------
-
-pos37004:
-    Code37055(mem59);
-    A = A & 32;
-    if(A == 0) goto pos36700;
-
-pos37014:
-    mem59 = X;
-    goto pos36791;
-
-    // --------------
-
-pos37019:
-    X = mem59;
-    X--;
-    A = inputtemp[X];
-    if((A == 'E') || (A == 'I') || (A == 'Y')) goto pos37014;
-    goto pos36700;
-    // --------------
-
-pos37040:
-    Code37055(mem59);
-    A = A & 32;
-    if(A == 0) goto pos36791;
-    mem59 = X;
-    goto pos37040;
-
-    //---------------------------------------
-
-pos37077:
-    X = mem58 + 1;
-    A = inputtemp[X];
-    if(A != 'E') goto pos37157;
-    X++;
-    Y = inputtemp[X];
-    X--;
-    A = tab36376[Y] & 128;
-    if(A == 0) goto pos37108;
-    X++;
-    A = inputtemp[X];
-    if(A != 'R') goto pos37113;
-pos37108:
-    mem58 = X;
-    goto pos37184;
-pos37113:
-    if((A == 83) || (A == 68)) goto pos37108; // 'S' 'D'
-    if(A != 76) goto pos37135; // 'L'
-    X++;
-    A = inputtemp[X];
-    if(A != 89) goto pos36700;
-    goto pos37108;
-
-pos37135:
-    if(A != 70) goto pos36700;
-    X++;
-    A = inputtemp[X];
-    if(A != 85) goto pos36700;
-    X++;
-    A = inputtemp[X];
-    if(A == 76) goto pos37108;
-    goto pos36700;
-
-pos37157:
-    if(A != 73) goto pos36700;
-    X++;
-    A = inputtemp[X];
-    if(A != 78) goto pos36700;
-    X++;
-    A = inputtemp[X];
-    if(A == 71) goto pos37108;
-    //pos37177:
-    goto pos36700;
-
-    // -----------------------------------------
-
-pos37180:
-
-    A = mem60;
-    mem58 = A;
-
-pos37184:
-    Y = mem65 + 1;
-
-    //37187: CPY 64
-    //  if(? != 0) goto pos37194;
-    if(Y == mem64) goto pos37455;
-    mem65 = Y;
-    //37196: LDA (62),y
-    A = GetRuleByte(mem62, Y);
-    mem57 = A;
-    X = A;
-    A = tab36376[X] & 128;
-    if(A == 0) goto pos37226;
-    X = mem58 + 1;
-    A = inputtemp[X];
-    if(A != mem57) goto pos36700;
-    mem58 = X;
-    goto pos37184;
-pos37226:
-    A = mem57;
-    if(A == 32) goto pos37295; // ' '
-    if(A == 35) goto pos37310; // '#'
-    if(A == 46) goto pos37320; // '.'
-    if(A == 38) goto pos37335; // '&'
-    if(A == 64) goto pos37367; // ''
-    if(A == 94) goto pos37404; // ''
-    if(A == 43) goto pos37419; // '+'
-    if(A == 58) goto pos37440; // ':'
-    if(A == 37) goto pos37077; // '%'
-    //pos37291:
-    //  Code42041(); //Error
-    //37294: BRK
-    return 0;
-
-    // --------------
-pos37295:
-    Code37066(mem58);
-    A = A & 128;
-    if(A != 0) goto pos36700;
-pos37305:
-    mem58 = X;
-    goto pos37184;
-
-    // --------------
-
-pos37310:
-    Code37066(mem58);
-    A = A & 64;
-    if(A != 0) goto pos37305;
-    goto pos36700;
-
-    // --------------
-
-pos37320:
-    Code37066(mem58);
-    A = A & 8;
-    if(A == 0) goto pos36700;
-
-pos37330:
-    mem58 = X;
-    goto pos37184;
-
-    // --------------
-
-pos37335:
-    Code37066(mem58);
-    A = A & 16;
-    if(A != 0) goto pos37330;
-    A = inputtemp[X];
-    if(A != 72) goto pos36700;
-    X++;
-    A = inputtemp[X];
-    if((A == 67) || (A == 83)) goto pos37330;
-    goto pos36700;
-
-    // --------------
-
-pos37367:
-    Code37066(mem58);
-    A = A & 4;
-    if(A != 0) goto pos37330;
-    A = inputtemp[X];
-    if(A != 72) goto pos36700;
-    if((A != 84) && (A != 67) && (A != 83)) goto pos36700;
-    mem58 = X;
-    goto pos37184;
-
-    // --------------
-
-pos37404:
-    Code37066(mem58);
-    A = A & 32;
-    if(A == 0) goto pos36700;
-pos37414:
-    mem58 = X;
-    goto pos37184;
-
-    // --------------
-
-pos37419:
-    X = mem58;
-    X++;
-    A = inputtemp[X];
-    if((A == 69) || (A == 73) || (A == 89)) goto pos37414;
-    goto pos36700;
-
-    // ----------------------
-
-pos37440:
-
-    Code37066(mem58);
-    A = A & 32;
-    if(A == 0) goto pos37184;
-    mem58 = X;
-    goto pos37440;
-pos37455:
-    Y = mem64;
-    mem61 = mem60;
-
-pos37461:
-    //37461: LDA (62),y
-    A = GetRuleByte(mem62, Y);
-    mem57 = A;
-    A = A & 127;
-    if(A != '=') {
-        mem56++;
-        X = mem56;
-        input[X] = A;
-    }
-
-    //37478: BIT 57
-    //37480: BPL 37485  //not negative flag
-    if((mem57 & 128) == 0) goto pos37485; //???
-    goto pos36554;
-pos37485:
-    Y++;
-    goto pos37461;
-}
-
-// Constructor
-
-STM32SAM::STM32SAM(uint32_t STM32SAM_SPEED /* = 5 */) {
-    STM32SAM_SPEED = STM32SAM_SPEED & 0x1f; // limit it from 0 to 31
-
-    _STM32SAM_SPEED = STM32SAM_SPEED;
-
-    // set default voice
-
-    speed = 72;
-    pitch = 64;
-    mouth = 128;
-    throat = 128;
-
-    phonetic = 0;
-    singmode = 0;
-
-    wait1 = 7;
-    wait2 = 6;
-
-    mem59 = 0;
-
-    oldtimetableindex = 0;
-}
-
-STM32SAM::STM32SAM() {
-    _STM32SAM_SPEED = 7;
-
-    // set default voice
-
-    speed = 72;
-    pitch = 64;
-    mouth = 128;
-    throat = 128;
-
-    phonetic = 0;
-    singmode = 0;
-
-    wait1 = 7;
-    wait2 = 6;
-
-    mem59 = 0;
-
-    oldtimetableindex = 0;
-}
-
-/*
-  STM32SAM::~STM32SAM() {
-  {
-  // TODO: end();
-  }
-*/
-
-////////////////////////////////////////////////////////////////////////////////////////////
-//
-//           STM32SAM sam  (variable string,  phonetic, sing, pitch, speed, mouth, throat)
-//           STM32SAM say (sing off, phonetic off) (const string)
-//           STM32SAM say (sing off, phonetic off) (variable string)
-//           STM32SAM sing (sing on, phonetic off) (const string)
-//           STM32SAM sing (sing on, phonetic off) (variable string)
-//           STM32SAM sayPhonetic (sing off, phonetic on) (const string)
-//           STM32SAM sayPhonetic (sing off, phonetic on) (variable string)
-//           STM32SAM singPhonetic (sing on, phonetic on) (const string)
-//           STM32SAM singPhonetic (sing on, phonetic on) (variable string)
-//           STM32SAM voice (pitch, speed, mouth, throat)
-//           STM32SAM setPitch (pitch)
-//           STM32SAM setSpeed (speed)
-//           STM32SAM setMouth (mouth)
-//           STM32SAM setThroat (throat)
-//
-//
-////////////////////////////////////////////////////////////////////////////////////////////
-
-////////////////////////////////////////////////////////////////////////////////////////////
-//
-//           STM32SAM sam  (const string,  phonetic, sing, pitch, speed, mouth, throat)
-//
-////////////////////////////////////////////////////////////////////////////////////////////
-
-char to_upper_case(char c) {
-    if(c >= 'a' && c <= 'z') {
-        return c - 'a' + 'A';
-    }
-    return c;
-}
-
-void STM32SAM::sam(
-    const char* argv,
-    unsigned char _phonetic,
-    unsigned char _singmode,
-    unsigned char _pitch,
-    unsigned char _speed,
-    unsigned char _mouth,
-    unsigned char _throat) {
-    phonetic = _phonetic;
-    singmode = _singmode;
-    pitch = _pitch;
-    speed = _speed;
-    mouth = _mouth;
-    throat = _throat;
-
-    int i;
-
-    for(i = 0; i < 256; i++) {
-        input[i] = argv[i];
-    }
-
-    for(i = 0; input[i] != 0; i++) {
-        if(i != 0) {
-            input[i] = to_upper_case((int)argv[i]);
-        }
-    }
-
-    if(!phonetic) {
-        strncat(input, "[", 256);
-        if(!TextToPhonemes((unsigned char*)input)) {
-            // PrintUsage();
-            return;
-        }
-
-    } else {
-        strncat(input, "\x9b", 256);
-    }
-
-    SetInput(input);
-
-    if(!SAMMain()) {
-        return;
-    }
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////
-//
-//           STM32SAM sam  (variable string,  phonetic, sing, pitch, speed, mouth, throat)
-//
-////////////////////////////////////////////////////////////////////////////////////////////
-
-void STM32SAM::sam(
-    char* argv,
-    unsigned char _phonetic,
-    unsigned char _singmode,
-    unsigned char _pitch,
-    unsigned char _speed,
-    unsigned char _mouth,
-    unsigned char _throat) {
-    phonetic = _phonetic;
-    singmode = _singmode;
-    pitch = _pitch;
-    speed = _speed;
-    mouth = _mouth;
-    throat = _throat;
-
-    int i;
-
-    for(i = 0; i < 256; i++) {
-        input[i] = argv[i];
-    }
-
-    for(i = 0; input[i] != 0; i++) {
-        if(i != 0) {
-            input[i] = to_upper_case((int)argv[i]);
-        }
-    }
-
-    if(!phonetic) {
-        strncat(input, "[", 256);
-        if(!TextToPhonemes((unsigned char*)input)) {
-            // PrintUsage();
-            return;
-        }
-
-    } else {
-        strncat(input, "\x9b", 256);
-    }
-
-    SetInput(input);
-
-    if(!SAMMain()) {
-        return;
-    }
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////
-//
-//           STM32SAM say(sing off, phonetic off) (const string)
-//
-////////////////////////////////////////////////////////////////////////////////////////////
-
-void STM32SAM::say(const char* argv) {
-    int i;
-
-    phonetic = 0;
-    singmode = 0;
-
-    char const_input[256];
-
-    for(i = 0; i < 256; i++) {
-        const_input[i] = argv[i];
-    }
-
-    sam(const_input, phonetic, singmode, pitch, speed, mouth, throat);
-}
-
-void STM32SAM::say(char* argv) {
-    int i;
-
-    phonetic = 0;
-    singmode = 0;
-
-    char const_input[256];
-
-    for(i = 0; i < 256; i++) {
-        const_input[i] = argv[i];
-    }
-
-    sam(const_input, phonetic, singmode, pitch, speed, mouth, throat);
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////
-//
-//           STM32SAM sing (sing on, phonetic off)
-//
-////////////////////////////////////////////////////////////////////////////////////////////
-
-void STM32SAM::sing(const char* argv) {
-    int i;
-
-    phonetic = 0;
-    singmode = 1;
-
-    char const_input[256];
-
-    for(i = 0; i < 256; i++) {
-        const_input[i] = argv[i];
-    }
-
-    sam(const_input, phonetic, singmode, pitch, speed, mouth, throat);
-}
-
-void STM32SAM::sing(char* argv) {
-    int i;
-
-    phonetic = 0;
-    singmode = 1;
-
-    char const_input[256];
-
-    for(i = 0; i < 256; i++) {
-        const_input[i] = argv[i];
-    }
-
-    sam(const_input, phonetic, singmode, pitch, speed, mouth, throat);
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////
-//
-//           STM32SAM sayPhonetic (sing off, phonetic on)
-//
-////////////////////////////////////////////////////////////////////////////////////////////
-
-void STM32SAM::sayPhonetic(const char* argv) {
-    int i;
-
-    phonetic = 1;
-    singmode = 0;
-
-    char const_input[256];
-
-    for(i = 0; i < 256; i++) {
-        const_input[i] = argv[i];
-    }
-
-    sam(const_input, phonetic, singmode, pitch, speed, mouth, throat);
-}
-
-void STM32SAM::sayPhonetic(char* argv) {
-    int i;
-
-    phonetic = 1;
-    singmode = 0;
-
-    char const_input[256];
-
-    for(i = 0; i < 256; i++) {
-        const_input[i] = argv[i];
-    }
-
-    sam(const_input, phonetic, singmode, pitch, speed, mouth, throat);
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////
-//
-//           STM32SAM singPhonetic (sing on, phonetic on)
-//
-////////////////////////////////////////////////////////////////////////////////////////////
-
-void STM32SAM::singPhonetic(const char* argv) {
-    int i;
-
-    phonetic = 1;
-    singmode = 1;
-
-    char const_input[256];
-
-    for(i = 0; i < 256; i++) {
-        const_input[i] = argv[i];
-    }
-
-    sam(const_input, phonetic, singmode, pitch, speed, mouth, throat);
-}
-
-void STM32SAM::singPhonetic(char* argv) {
-    int i;
-
-    phonetic = 1;
-    singmode = 0;
-
-    char const_input[256];
-
-    for(i = 0; i < 256; i++) {
-        const_input[i] = argv[i];
-    }
-
-    sam(const_input, phonetic, singmode, pitch, speed, mouth, throat);
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////
-//
-//           STM32SAM voice (pitch, speed, mouth, throat)
-//
-////////////////////////////////////////////////////////////////////////////////////////////
-
-void STM32SAM::setVoice(
-    unsigned char _pitch /* = 64 */,
-    unsigned char _speed /* = 72 */,
-    unsigned char _mouth /* = 128 */,
-    unsigned char _throat /* = 128 */) {
-    pitch = _pitch;
-    speed = _speed;
-    mouth = _mouth;
-    throat = _throat;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////
-//
-//           STM32SAM setPitch (pitch)
-//
-////////////////////////////////////////////////////////////////////////////////////////////
-
-void STM32SAM::setPitch(unsigned char _pitch /* = 64 */) {
-    pitch = _pitch;
-}
-////////////////////////////////////////////////////////////////////////////////////////////
-//
-//           STM32SAM setSpeed (speed)
-//
-////////////////////////////////////////////////////////////////////////////////////////////
-
-void STM32SAM::setSpeed(unsigned char _speed /* = 72 */) {
-    speed = _speed;
-}
-////////////////////////////////////////////////////////////////////////////////////////////
-//
-//           STM32SAM setMouth (mouth)
-//
-////////////////////////////////////////////////////////////////////////////////////////////
-
-void STM32SAM::setMouth(unsigned char _mouth /* = 128 */) {
-    mouth = _mouth;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////
-//
-//           STM32SAM setThroat (throat)
-//
-////////////////////////////////////////////////////////////////////////////////////////////
-
-void STM32SAM::setThroat(unsigned char _throat /* = 128 */) {
-    throat = _throat;
-}
-////////////////////////////////////////////////////////////////////////////////////////////
-//
-//           Hardware
-//
-////////////////////////////////////////////////////////////////////////////////////////////
-// Hardware specifics, for easier porting to other microcontrollers
-
-//
-// Set PA8 pin as PWM, at 256 timer ticks overflow (8bit resolution)
-
-#include <math.h>
-#include <stm32wbxx_ll_tim.h>
-
-#define FURI_HAL_SPEAKER_TIMER TIM16
-#define FURI_HAL_SPEAKER_CHANNEL LL_TIM_CHANNEL_CH1
-
-void STM32SAM::begin(void) {
-#ifdef USE_ROGER_CORE
-
-    pinMode(PA8, PWM); //   audio output pin
-
-    Timer1.setPeriod(
-        4); // Can't set at 256 ticks, only in uS. First nearest uS is 4 (Roger core is only for bluepill, that means 72*4=288 ticks, or 128*4=512 ticks when overclocked. It's ok, just overall volume will be lower, because maximum volume will be 256/288 or 256/512)
-
-#endif
-
-#ifdef USE_STM32duino_CORE
-    pinMode(PA8, OUTPUT);
-
-    PWM->pause();
-    PWM->setMode(1, TIMER_OUTPUT_COMPARE_PWM1, PA8); // TIM1 CH1 (PA8)
-    PWM->setPrescaleFactor(1);
-    PWM->setOverflow(256, TICK_FORMAT); // 256 ticks overflow, no matter the CPU (timer) speed
-    PWM->resume();
-
-#endif
-
-    LL_TIM_InitTypeDef TIM_InitStruct;
-    memset(&TIM_InitStruct, 0, sizeof(LL_TIM_InitTypeDef));
-    TIM_InitStruct.Prescaler = 4;
-    TIM_InitStruct.Autoreload = 255;
-    LL_TIM_Init(FURI_HAL_SPEAKER_TIMER, &TIM_InitStruct);
-
-    LL_TIM_OC_InitTypeDef TIM_OC_InitStruct;
-    memset(&TIM_OC_InitStruct, 0, sizeof(LL_TIM_OC_InitTypeDef));
-    TIM_OC_InitStruct.OCMode = LL_TIM_OCMODE_PWM1;
-    TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_ENABLE;
-    TIM_OC_InitStruct.CompareValue = 127;
-    LL_TIM_OC_Init(FURI_HAL_SPEAKER_TIMER, FURI_HAL_SPEAKER_CHANNEL, &TIM_OC_InitStruct);
-
-    LL_TIM_EnableAllOutputs(FURI_HAL_SPEAKER_TIMER);
-    LL_TIM_EnableCounter(FURI_HAL_SPEAKER_TIMER);
-} // begin
-
-inline void STM32SAM::SetAUDIO(unsigned char main_volume) {
-#ifdef USE_ROGER_CORE
-    Timer1.setCompare(TIMER_CH1, main_volume);
-#endif
-
-#ifdef USE_STM32duino_CORE
-    PWM->setCaptureCompare(1, main_volume, TICK_COMPARE_FORMAT);
-#endif
-
-    // if(main_volume > 64) {
-    //     LL_TIM_OC_SetCompareCH1(FURI_HAL_SPEAKER_TIMER, 127);
-    // } else {
-    //     LL_TIM_OC_SetCompareCH1(FURI_HAL_SPEAKER_TIMER, main_volume);
-    // }
-
-    float data = main_volume;
-    data /= 255.0f;
-    data -= 0.5f;
-    data *= 4.0f;
-    data = tanhf(data);
-
-    data += 0.5f;
-    data *= 255.0f;
-
-    if(data < 0) {
-        data = 0;
-    } else if(data > 255) {
-        data = 255;
-    }
-
-    LL_TIM_OC_SetCompareCH1(FURI_HAL_SPEAKER_TIMER, data);
-}

+ 0 - 96
sam/stm32_sam.h

@@ -1,96 +0,0 @@
-#include <furi.h>
-
-#ifndef __STM32SAM__
-#define __STM32SAM__
-
-// SAM Text-To-Speech (TTS), ported from https://github.com/s-macke/SAM
-
-class STM32SAM {
-public:
-    STM32SAM(uint32_t STM32SAM_SPEED);
-    STM32SAM();
-
-    void begin(void);
-
-    void
-        sam(const char* argv,
-            unsigned char phonetic,
-            unsigned char singmode,
-            unsigned char pitch,
-            unsigned char speed,
-            unsigned char mouth,
-            unsigned char throat);
-    void
-        sam(char* argv,
-            unsigned char phonetic,
-            unsigned char singmode,
-            unsigned char pitch,
-            unsigned char speed,
-            unsigned char mouth,
-            unsigned char throat);
-
-    void say(const char* argv);
-    void say(char* argv);
-    void sing(const char* argv);
-    void sing(char* argv);
-    void sayPhonetic(const char* argv);
-    void sayPhonetic(char* argv);
-    void singPhonetic(const char* argv);
-    void singPhonetic(char* argv);
-    void setVoice(
-        unsigned char _pitch = 64,
-        unsigned char _speed = 72,
-        unsigned char _mouth = 128,
-        unsigned char _throat = 128);
-    void setPitch(unsigned char _pitch = 64);
-    void setSpeed(unsigned char _speed = 72);
-    void setMouth(unsigned char _mouth = 128);
-    void setThroat(unsigned char _throat = 128);
-
-private:
-    void SetAUDIO(unsigned char main_volume);
-
-    void Output8BitAry(int index, unsigned char ary[5]);
-    void Output8Bit(int index, unsigned char A);
-    unsigned char Read(unsigned char p, unsigned char Y);
-    void Write(unsigned char p, unsigned char Y, unsigned char value);
-    void RenderSample(unsigned char* mem66);
-    void Render();
-    void AddInflection(unsigned char mem48, unsigned char phase1);
-    void SetMouthThroat();
-    unsigned char trans(unsigned char mem39212, unsigned char mem39213);
-    void SetInput(char* _input);
-    void Init();
-    int SAMMain();
-    void PrepareOutput();
-    void Insert(
-        unsigned char position /*var57*/,
-        unsigned char mem60,
-        unsigned char mem59,
-        unsigned char mem58);
-    void InsertBreath();
-    void CopyStress();
-    int Parser1();
-    void SetPhonemeLength();
-    void Code41240();
-    void Parser2();
-    void AdjustLengths();
-    void Code47503(unsigned char mem52);
-    void Code37055(unsigned char mem59);
-    void Code37066(unsigned char mem58);
-    unsigned char GetRuleByte(unsigned short mem62, unsigned char Y);
-    int TextToPhonemes(unsigned char* input); // Code36484
-
-    uint32_t _STM32SAM_SPEED;
-
-    unsigned char speed;
-    unsigned char pitch;
-    unsigned char mouth;
-    unsigned char throat;
-
-    unsigned char phonetic;
-    unsigned char singmode;
-
-}; // STM32SAM class
-
-#endif