/* This file was generated by scramble.py. */
#line 1 "src/music.py"
#include "music.h"
#line 4
static LandSound * samples [128] [64];
#line 47
static NotesPlayer global_player;
static char const * current_tune;
#line 50
char const * music_tune1 = "\n"
    "X: 0\n"
    "T: Allefant Song\n"
    "M: 2/4\n"
    "L: 1/8\n"
    "K: Am\n"
    "| \"Am\" A2 ^A2 B2 \"F\" c3d1c4z2 | \"Am\"A2^A2B2 \"F\" c3d1c4z2 | \"F\" f2c2A2F2 \"C\"  F2E1G3z2 | \"C\" ^A2G2G2 \"F\" E1 F7z2\n"
    "| \"Am\" A2 ^A2 B2 \"F\" c3d1c4z2 | \"Am\"A2^A2B2 \"F\" c3d1c4z2 | \"F\" f2c2A2F2 \"C\"  F2E1G3z2 | \"C\" ^A2G2G2 \"F\" E1 F7z2\n"
    "| \"C\" E2 G2 c1 \"F\" x1 B4 A2 F2 z2 | \"Bdim\" D2F2B2 \"C\" A4G2E2 z2\n"
    "| \"C\" E2 G2 c1 \"F\" x1 B4 A2 F2 z2 | \"Bdim\" D2F2B2 \"C\" A4G2E2 z2\n"
    "";
#line 62
char const * music_tune2 = "\n"
    "X:1\n"
    "T:Alphabet Song\n"
    "T:(Twinkle, Twinkle Little Star)\n"
    "C:Traditional Kid's Song\n"
    "M:4/4\n"
    "L:1/4\n"
    "Q:1/4=100\n"
    "K:D\n"
    "|\"D\"D D A A|\"G\"B B \"D\"A2|\"G\"G G \"D\"F F|\"A\"E/2E/2E/2E/2 \"D\"D2|A A \"G\"G G|\"D\"F F \"A\"E2|\"D\"A A \"G\"G G|\"D\"F F \"A\"E2\n"
    "\"D\"D   D    A    A|\"G\"B B \"D\"A2|\"G\"G    G \"D\"F    F|\"A\"E     E \"D\"D2|\n"
    "";
#line 75
char const * music_tune3 = "\n"
    "X: 1\n"
    "T: Sasha  [Dm]\n"
    "O: Russia\n"
    "B: \"Ska' Vi Danse\", Claus Jørgensen (Edition Wilhelm Hansen, Copenhagen)\n"
    "M: 2/4\n"
    "L: 1/8\n"
    "K: Dm\n"
    "| \"Dm\"AA z2 | AA z2 | \"A7\"A2 A2 | A2 z2\n"
    "| \"Dm\"AA AF | AA AF | \"A7\"EE A>G | \"Dm\"FD D2\n"
    "| \"Dm\"AA AF | AA AF | \"A7\"EE A>G | \"Dm\"FD D2\n"
    "| \"Gm\"B2 B2 | \"Dm\"A2 A2 | \"A7\"AG FE | \"Dm\"D2 D2\n"
    "| \"Gm\"B2 B2 | \"Dm\"A2 A2 | \"A7\"AG FE | \"Dm\"D2 D2\n"
    "K:D\n"
    "| \"D\"F2 A2 | d3 c | dc BA | \"Em\"G3 F | \"A7\"E2 G2 | c3 B |cB AG | \"D\"F3 E\n"
    "| \"D\"F2 A2 | d3 c | dc BA | \"Em\"G3 F | \"A7\"E2 G2 | c3 B |\"A7\"cA Bc | \"D\"d2 d2\n"
    "";
#line 93
char const * music_tune4 = "\n"
    "X:1001\n"
    "T:Aiken Drum\n"
    "T:Willie Wood\n"
    "T:There's a Man Came to our Town\n"
    "R:Reel\n"
    "C:Trad. Before 1820\n"
    "O:Scotland\n"
    "M:4/4\n"
    "L:1/8\n"
    "Q:1/4=140\n"
    "K:D\n"
    "|\"D\"f2 f2 gfed|\"G\"B4 d3 B|\"D\"A3 B d2 A2|\"E7\"f2 e2 \"A7\"e2 de|\"D\"f2 f2 gfed|\"G\"B4 d3 B|\"A7\"A2 A2 B2 c2|\"D\"d6 de\n"
    "|\"D\"f2 f2 gfed|\"G\"B4 d3 B|\"D\"A3 B d2 A2|\"E7\"f2 e2 \"A7\"e2 de|\"D\"f2 f2 gfed|\"G\"B4 d3 B|\"A7\"A2 A2 B2 c2|\"D\"d6 de\n"
    "|\"D\"f2 f2 f2 ed|\"G\"g2 g2 b3 g|\"D\"f2 a2 f2 d2|\"Em\"f2 e2 \"A7\"e2 de|\"D\"f2 f2 gfed|\"G\"B4 d3 B|\"A7\"A2 A2 B2 c2|\"D\"d6 de\n"
    "|\"D\"f2 f2 f2 ed|\"G\"g2 g2 b3 g|\"D\"f2 a2 f2 d2|\"Em\"f2 e2 \"A7\"e2 de|\"D\"f2 f2 gfed|\"G\"B4 d3 B|\"A7\"A2 A2 B2 c2|\"D\"d6 de\n"
    "";
#line 111
static LandStream * stream;
#line 117
static int const notevals [3] [7] = { {0, 2, 4, 5, 7, 9, 11}, /* major */ {0, 2, 3, 5, 7, 8, 10}, /* minor */ {0, 2, 3, 5, 7, 9, 10} , /* dorian */ };
#line 119
int noteval(int key, int scale, int note) {
    /* key: 0..6
     * note: 0..6
     * scale: 0: major
     * 1: minor
     * 2: dorian
     */
#line 128
    int table [8];
    int base = notevals [0] [key];
    for (int i = 0; i < 7; i += 1) {
        int j = (key + i) % 7;
        table [j] = (base + notevals [scale] [i]) % 12;
    }
    return table [note];
}
static void read_fraction(char const * s, int * num, int * den) {
    bool divide = 0;
    int l = strlen(s);
    for (int i = 0; i < l; i += 1) {
        int c = s [i];
        if (c >= '0' && c <= '9') {
            if (divide) {
#line 142
                * den = c - '0';
            }
#line 142
            else {
                * num = c - '0';
            }
        }
#line 144
        else if (c == '/') {
            divide = 1;
        }
    }
}
#line 147
static char const * note_names [12] = {"C", "^C", "D", "^D", "E", "F", "^F", "G", "^G", "A", "^A", "B"};
#line 155
static int chords [] [5] = { {99}, {0, 4, 7, 99}, /* major */ {0, 3, 7, 99}, /* minor */ {0, 4, 7, 10, 99}, /* major 7th */ {0, 3, 6, 99} , /* diminished */ };
#line 157
char * note_string(int note, char * out) {
    out [0] = 0;
    if (note == 0) {
        strcat(out, "-");
    }
#line 161
    else if (note == 128) {
        strcat(out, "z");
    }
#line 162
    else {
#line 164
        int octave = note / 12;
        note %= 12;
        strcat(out, note_names [note]);
        if (octave < 5) {
            for (int i = 0; i < 5 - octave; i += 1) {
                strcat(out, ",");
            }
        }
#line 170
        else if (octave >= 6) {
            out [strlen(out) - 1] += 'a' - 'A';
#line 173
            for (int i = 7; i < octave; i += 1) {
                strcat(out, "'");
            }
        }
    }
#line 175
    return out;
}
static void note_add(NotesPlayer * player, int note, int ticks, int timestamp) {
    int prev = player->last_note;
    int i = player->highest_index++;
    if (i == 0) {
        i++;
        player->highest_index++;
        if (player->highest_index >= 8192) {
            player->highest_index--;
            printf("FIXME: music is fixed length right now!\n");
        }
    }
#line 187
    if (prev) {
        while (prev) {
            if (timestamp > player->notes [prev].timestamp) {
#line 189
                break;
            }
#line 190
            prev = player->notes [prev].prev_index;
        }
    }
#line 192
    if (prev) {
        player->notes [i].prev_index = prev;
        player->notes [i].next_index = player->notes [prev].next_index;
        player->notes [prev].next_index = i;
    }
#line 195
    else {
#line 197
        player->notes [i].prev_index = 0;
        player->notes [i].next_index = player->first_note;
        player->first_note = i;
    }
    if (player->notes [i].next_index) {
        player->notes [player->notes [i].next_index].prev_index = i;
    }
#line 202
    else {
#line 204
        player->last_note = i;
    }
    player->notes [i].timestamp = timestamp;
    player->notes [i].ticks = ticks;
    player->notes [i].note = note;
}
//printf("%d <- %d -> %d (%d..%d)\n", notes[i].prev_index, i,
//    notes[i].next_index, first_note, last_note)
#line 213
static int letter_to_note(int c) {
    c -= 'C';
    if (c < 0) {
#line 215
        c += 7;
    }
#line 216
    return c;
}
static void parse_note(ABCParser * abc) {
    int note = 0;
    int duration = 0;
    int octave = 0;
    bool divide = 0;
    int divisor = 1;
    int half = 0;
    bool string = 0;
    char stringval [100];
#line 228
    while (1) {
        int c = abc->tune [abc->pos];
#line 231
        if (! c) {
            break;
        }
#line 233
        if (c == '\n') {
            break;
        }
        abc->pos++;
#line 238
        int next_c = abc->tune [abc->pos];
#line 240
        if (string) {
            int s = strlen(stringval);
            if (c == '"') {
                abc->chord_note = letter_to_note(stringval [0]);
                abc->chord_type = 1;
                if (s >= 2) {
                    if (stringval [1] == 'm') {
                        abc->chord_type = 2;
                    }
#line 248
                    else if (stringval [1] == '7') {
                        abc->chord_type = 3;
                    }
#line 250
                    else if (stringval [1] == 'd') {
                        abc->chord_type = 4;
                    }
                }
#line 252
                string = 0;
            }
#line 252
            else {
#line 254
                stringval [s] = c;
                stringval [s + 1] = 0;
            }
#line 256
            continue;
        }
        if (c == '"') {
            stringval [0] = 0;
            string = 1;
        }
#line 261
        else if (c >= 'A' && c <= 'G') {
            if (note) {
#line 262
                abc->pos--;
#line 262
                break;
            }
#line 263
            note = 60 + noteval(abc->key_note, abc->key_scale, letter_to_note(c));
        }
        else if (c >= 'a' && c <= 'g') {
            if (note) {
#line 266
                abc->pos--;
#line 266
                break;
            }
#line 267
            note = 60 + noteval(abc->key_note, abc->key_scale, letter_to_note(c + 'C' - 'c')) + 12;
        }
        else if (c == 'z') {
            if (note) {
#line 270
                abc->pos--;
#line 270
                break;
            }
#line 271
            note = 128;
        }
#line 272
        else if (c == '(') {
            if (note) {
#line 273
                abc->pos--;
#line 273
                break;
            }
#line 274
            if (next_c >= '0' && next_c <= '9') {
                abc->pos++;
            }
        }
        // TODO: triplet
#line 277
        else if (c == 'x') {
            if (note) {
#line 278
                abc->pos--;
#line 278
                break;
            }
#line 279
            note = 128;
        }
#line 280
        else if (c == '^') {
            if (note) {
#line 281
                abc->pos--;
#line 281
                break;
            }
#line 282
            half = 1;
        }
#line 283
        else if (c == '_') {
            if (note) {
#line 284
                abc->pos--;
#line 284
                break;
            }
#line 285
            half = - 1;
        }
#line 286
        else if (c == ',') {
            octave--;
        }
#line 288
        else if (c == '\'') {
            octave++;
        }
#line 290
        else if (c >= '0' && c <= '9') {
            if (divide) {
#line 291
                divisor = c - '0';
            }
#line 291
            else {
#line 293
                duration *= 10;
                duration += c - '0';
            }
        }
#line 295
        else if (c == '/') {
            divide = 1;
        }
#line 297
        else if (c == '|') {
            if (note) {
#line 298
                abc->pos--;
#line 298
                break;
            }
#line 299
            if (next_c == ':') {
                //printf("repeat start\n")
                abc->pos++;
                abc->repeat_start_pos = abc->pos;
            }
#line 303
            else if (next_c >= '0' && next_c <= '9') {
                abc->pos++;
                if (next_c == '1') {
                    if (abc->repeating) {
                        abc->repeating = 0;
                        abc->pos = abc->repeat_end_pos;
                    }
                }
            }
        }
#line 309
        else if (c == ':') {
            if (next_c == '|') {
                if (abc->repeating) {
                    abc->repeating = 0;
                }
#line 312
                else {
                    //printf("repeating\n")
#line 315
                    abc->repeat_end_pos = abc->pos;
                    abc->pos = abc->repeat_start_pos;
                    abc->repeating = 1;
                }
            }
        }
    }
#line 319
    if (! duration) {
#line 319
        duration = 1;
    }
    int ticks = abc->ticks64 * 64 * abc->note_numerator * duration;
    ticks /= divisor * abc->note_denominator;
#line 324
    if (note > 0 && note < 128) {
        note += octave * 12 + half;
        //char s[100]
        //printf("Note: %9d: %d %s%d\n", abc->timestamp, note, note_string(note, s), duration)
#line 330
        note_add(abc->player, note, ticks, abc->timestamp);
    }
    if (abc->chord_type) {
#line 334
        int chord_span = abc->ticks64 * 64 * abc->meter_numerator / abc->meter_denominator / 2;
#line 336
        while (abc->chord_tick < abc->timestamp + ticks) {
#line 338
            int i = 0;
            int chord_octave = 4;
            int base = chord_octave * 12 + notevals [0] [abc->chord_note];
#line 342
            note_add(abc->player, base + chords [abc->chord_type] [0] - 12, chord_span / 4, abc->chord_tick);
#line 345
            while (chords [abc->chord_type] [i] != 99) {
                note_add(abc->player, base + chords [abc->chord_type] [i], chord_span / 4, abc->chord_tick + chord_span / 2);
#line 348
                i++;
            }
            abc->chord_tick += chord_span;
        }
    }
#line 352
    abc->timestamp += ticks;
}
static void parse_notes(ABCParser * abc) {
    while (1) {
        char c = abc->tune [abc->pos];
        if (! c) {
#line 357
            break;
        }
#line 358
        if (c == '\n') {
#line 358
            break;
        }
#line 359
        parse_note(abc);
    }
}
#line 361
void music_parse_abc(char const * tune, NotesPlayer * player) {
    int tag = 0;
    int const OUTSIDE = 0;
    int const INSIDE = 1;
    int const COMMENT = 2;
    int mode = OUTSIDE;
    char line [1024];
#line 369
    ABCParser abc_;
    ABCParser * abc = & abc_;
    abc->player = player;
    abc->pos = 0;
    abc->tune = tune;
    abc->timestamp = 0;
    abc->key_note = 0;
    abc->key_scale = 0;
    abc->chord_note = 0;
    abc->chord_type = 0;
    abc->note_numerator = 1;
    abc->note_denominator = 8;
    abc->chord_tick = 0;
    abc->repeat_start_pos = 0;
    abc->repeating = 0;
    abc->ticks64 = 1500;
    abc->meter_numerator = 2;
    abc->meter_denominator = 4;
#line 388
    while (1) {
        char c = abc->tune [abc->pos++];
        if (! c) {
#line 390
            break;
        }
#line 391
        if (mode == OUTSIDE) {
            if (c <= 32) {
#line 392
                continue;
            }
#line 393
            if (c == '%') {
                mode = COMMENT;
                continue;
            }
            if (tune [abc->pos] == ':') {
                if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) {
                    abc->pos++;
                    tag = c;
                    mode = INSIDE;
                    line [0] = 0;
                    continue;
                }
            }
            //timestamp_start = timestamp
#line 406
            abc->pos--;
            parse_notes(abc);
        }
        //timestamp_end = timestamp
        //timestamp = timestamp_start
        else if (mode == INSIDE) {
            int s = strlen(line);
            if (c == '\n') {
                mode = OUTSIDE;
                if (tag == 'K') {
                    abc->key_note = 0;
                    abc->key_scale = 0;
                    //printf("K:%s\n", line)
                    //timestamp = timestamp_end
                    bool got_note = 0;
                    for (int i = 0; i < s; i += 1) {
                        if (! got_note) {
                            if (line [i] >= 'A' && line [i] <= 'G') {
                                abc->key_note = letter_to_note(line [i]);
                                got_note = 1;
                            }
                        }
#line 425
                        else {
#line 427
                            if (line [i] == 'm') {
                                abc->key_scale = 1;
                            }
#line 429
                            else if (line [i] == 'd') {
                                abc->key_scale = 2;
                            }
                        }
                    }
                }
#line 431
                else if (tag == 'L') {
                    read_fraction(line, & abc->note_numerator, & abc->note_denominator);
                }
                //printf("L:%s %d/%d\n", line, abc->note_numerator, abc->note_denominator)
                else if (tag == 'M') {
                    read_fraction(line, & abc->meter_numerator, & abc->meter_denominator);
                }
                //printf("M:%s %d/%d\n", line, abc->meter_numerator, abc->meter_denominator)
                else if (tag == 'V') {
                    abc->timestamp = 0;
                }
            }
#line 440
            else {
#line 442
                line [s] = c;
                line [s + 1] = 0;
            }
        }
#line 444
        else if (mode == COMMENT) {
            if (c == '\n') {
                mode = OUTSIDE;
            }
        }
    }
}
#line 448
int timestamp_to_samples(int ticks) {
    return ticks;
}
int mix_note(NotesPlayer * player, Envelope * e, Note * note, int16_t * b, int count) {
#line 453
    if (! samples [note->note] [note->ticks / 750]) {
        e->hold = note->ticks / 750 / 64.0 - e->attack - e->decay - e->release;
        samples [note->note] [note->ticks / 750] = sound_synthesize(e, note->note);
    }
    LandSound * sample = samples [note->note] [note->ticks / 750];
#line 459
    int start = timestamp_to_samples(note->timestamp);
    int n = land_sound_length(sample);
#line 462
    if (start >= player->sample_pos + count) {
#line 462
        return 1;
    }
#line 463
    if (player->sample_pos >= start + n) {
#line 463
        return - 1;
    }
    int16_t * s = land_sound_sample_pointer(sample);
#line 467
    if (start + n > player->sample_pos + count) {
        n = player->sample_pos + count - start;
    }
    if (start < player->sample_pos) {
        n += start - player->sample_pos;
        s += (player->sample_pos - start) * 2;
        start = player->sample_pos;
    }
    if (player->sample_pos < start) {
        b += (start - player->sample_pos) * 2;
    }
#define mix(a, b) \
        v = a + b; \
        if (v < - 32768) { \
            v = - 32768; \
        } \
        if (v > 32767) { \
            v = 32767; \
        } \
        a = v;
#line 484
    for (int i = 0; i < n; i += 1) {
        int v;
        mix(b [i * 2 + 0], s [i * 2 + 0]);
        mix(b [i * 2 + 1], s [i * 2 + 1]);
    }
    return 0;
}
static int start = 0;
static int repeats = 0;
static char const * current;
#line 495
void music_play_tune(char const * tune) {
    current = tune;
    NotesPlayer * player = & global_player;
#line 499
    player->highest_index = 0;
    player->first_note = 0;
    player->last_note = 0;
    music_parse_abc(tune, player);
    current_tune = tune;
    player->oldest_active_note = player->first_note;
    player->sample_pos = 0;
#line 507
    start = land_get_ticks();
    repeats = 0;
}
void music_play_tune_if_not(char const * tune) {
    if (tune == current) {
#line 511
        return ;
    }
#line 512
    music_play_tune(tune);
}
void music_tick(void) {
#line 516
    NotesPlayer * player = & global_player;
#line 518
    if (! current_tune) {
#line 518
        return ;
    }
    int fragment_samples = 2048;
#line 522
    if (! stream) {
        stream = land_stream_new(fragment_samples, 4, 48000, 16, 2);
    }
    int16_t * b = land_stream_buffer(stream);
    if (! b) {
#line 526
        return ;
    }
    memset(b, 0, fragment_samples * 4);
    //for int i in range(4096):
    //    int c = sin(((sample_pos + i) / 48000.0) * 440.0 * LAND_PI * 2) * 32767
    //    b[i * 2 + 0] = c / 2
    //    b[i * 2 + 1] = c / 2
#line 534
    if (! player->oldest_active_note) {
        player->oldest_active_note = player->first_note;
        player->sample_pos = 0;
        start = land_get_ticks();
        repeats++;
    }
    Envelope e = {.attack = 0.025, .decay = 0.025, .hold = 0, .release = 0.025, .volume = 0.05, .sustain = 0.04};
#line 548
    int ni = player->oldest_active_note;
    while (1) {
        Note * n = player->notes + ni;
        if (n->note > 0 && n->note < 128) {
            int r = mix_note(player, & e, n, b, fragment_samples);
            if (r == 1) {
#line 553
                break;
            }
#line 554
            if (r == - 1 && ni == player->oldest_active_note) {
                player->oldest_active_note = n->next_index;
            }
        }
#line 556
        ni = n->next_index;
        //printf("%d %d (%d:%d)\n", ni, player->oldest_active_note,
        //    player->notes[player->oldest_active_note].note,
        //    player->notes[player->oldest_active_note].ticks)
        if (! ni) {
            break;
        }
#line 562
        n = player->notes + ni;
    }
#line 565
    land_stream_fill(stream);
#line 567
    player->sample_pos += fragment_samples;
}
int music_ticks(void) {
    if (! current_tune) {
#line 570
        return 0;
    }
#line 571
    return land_get_ticks() - start;
}
int music_repeats(void) {
    return repeats;
}
char const * music_current(void) {
    return current;
}
/* This file was generated by scramble.py. */
