From 9af409de7612cd10d19b9ead384ce5ed05243d01 Mon Sep 17 00:00:00 2001 From: cancel Date: Fri, 7 Dec 2018 13:42:13 +0900 Subject: [PATCH] Add start of midi events --- bank.c | 19 ++++++++++ bank.h | 29 ++++++++++++++ cli_main.c | 5 ++- sim.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++------- sim.h | 3 +- tui_main.c | 10 +++-- 6 files changed, 156 insertions(+), 19 deletions(-) diff --git a/bank.c b/bank.c index 2738b5b..f941644 100644 --- a/bank.c +++ b/bank.c @@ -96,3 +96,22 @@ fail: *cursor = offset; return 0; } + +void oevent_list_init(Oevent_list* olist) { + olist->buffer = NULL; + olist->count = 0; + olist->capacity = 0; +} +void oevent_list_deinit(Oevent_list* olist) { free(olist->buffer); } +void oevent_list_clear(Oevent_list* olist) { olist->count = 0; } +Oevent* oevent_list_alloc_item(Oevent_list* olist) { + Usz count = olist->count; + if (olist->capacity == count) { + Usz capacity = count < 16 ? 16 : orca_round_up_power2(count); + olist->buffer = realloc(olist->buffer, capacity * sizeof(Oevent)); + olist->capacity = capacity; + } + Oevent* result = olist->buffer + count; + olist->count = count + 1; + return result; +} diff --git a/bank.h b/bank.h index 7fae139..2b7d489 100644 --- a/bank.h +++ b/bank.h @@ -29,3 +29,32 @@ Usz bank_append(Bank* restrict bank, Usz cur_size, Usz index, Usz bank_read(char const* restrict bank_data, Usz bank_size, Bank_cursor* restrict cursor, Usz index, I32* restrict dest, Usz dest_count); + +typedef enum { + Oevent_type_midi, +} Oevent_types; + +typedef struct { + U8 oevent_type; + U8 channel; + U8 octave; + U8 note; + U8 velocity; + U8 bar_divisor; +} Oevent_midi; + +typedef union { + U8 oevent_type; + Oevent_midi midi; +} Oevent; + +typedef struct { + Oevent* buffer; + Usz count; + Usz capacity; +} Oevent_list; + +void oevent_list_init(Oevent_list* olist); +void oevent_list_deinit(Oevent_list* olist); +void oevent_list_clear(Oevent_list* olist); +Oevent* oevent_list_alloc_item(Oevent_list* olist); diff --git a/cli_main.c b/cli_main.c index 92db5ff..58110d6 100644 --- a/cli_main.c +++ b/cli_main.c @@ -101,13 +101,16 @@ int main(int argc, char** argv) { markmap_reusable_ensure_size(&markmap_r, field.height, field.width); Bank bank; bank_init(&bank); + Oevent_list oevent_list; + oevent_list_init(&oevent_list); Usz max_ticks = (Usz)ticks; for (Usz i = 0; i < max_ticks; ++i) { orca_run(field.buffer, markmap_r.buffer, field.height, field.width, i, - &bank, ORCA_PIANO_BITS_NONE); + &bank, &oevent_list, ORCA_PIANO_BITS_NONE); } markmap_reusable_deinit(&markmap_r); bank_deinit(&bank); + oevent_list_deinit(&oevent_list); field_fput(&field, stdout); field_deinit(&field); return 0; diff --git a/sim.c b/sim.c index 09ed6ac..f5aa39b 100644 --- a/sim.c +++ b/sim.c @@ -87,6 +87,50 @@ ORCA_PURE static bool oper_has_neighboring_bang(Glyph const* gbuf, Usz h, Usz w, return false; } +static U8 midi_note_number_of(Glyph g) { + switch (g) { + case 'C': + return 0; + case 'c': + return 1; + case 'D': + return 2; + case 'd': + return 3; + case 'E': + return 4; + case 'F': + return 5; + case 'f': + return 6; + case 'G': + return 7; + case 'g': + return 8; + case 'A': + return 9; + case 'a': + return 10; + case 'B': + return 11; + default: + return UINT8_MAX; + } +} + +static ORCA_FORCE_NO_INLINE U8 midi_velocity_of(Glyph g) { + Usz n = index_of(g); + // scale [0,9] to [0,127] + if (n < 10) return (U8)(n * 14 + 1); + n -= 10; + // scale [0,25] to [0,127] + // js seems to send 1 when original n is < 10, and 0 when n is 11. Is that + // the intended behavior? + if (n == 0) return UINT8_C(0); + if (n >= 26) return UINT8_C(127); + return (U8)(n * 5 - 3); +} + ORCA_FORCE_NO_INLINE static void oper_movement_phase0(Gbuffer gbuf, Mbuffer mbuf, Usz const height, Usz const width, Usz const y, Usz const x, @@ -127,6 +171,7 @@ typedef struct { Bank_cursor cursor; Glyph const* vars_slots; Piano_bits piano_bits; + Oevent_list* oevent_list; } Oper_phase1_extras; static void oper_bank_store(Oper_phase0_extras* extra_params, Usz width, Usz y, @@ -145,6 +190,9 @@ static Usz oper_bank_load(Oper_phase1_extras* extra_params, Usz width, Usz y, &extra_params->cursor, index, out_vals, out_count); } +// ORCA_FORCE_NO_INLINE +// static void oper_add_midi_event(Oper_phase1_extras* extra_params, + ORCA_FORCE_STATIC_INLINE Usz usz_clamp(Usz val, Usz min, Usz max) { if (val < min) @@ -290,7 +338,8 @@ Usz usz_clamp(Usz val, Usz min, Usz max) { #define ORCA_SOLO_OPERATORS(_) \ _('!', keys) \ _('#', comment) \ - _('*', bang) + _('*', bang) \ + _(':', midi) #define ORCA_DUAL_OPERATORS(_) \ _('A', 'a', add) \ @@ -374,6 +423,36 @@ END_PHASE BEGIN_SOLO_PHASE_1(bang) END_PHASE +BEGIN_SOLO_PHASE_0(midi) + BEGIN_ACTIVE_PORTS + for (Usz i = 1; 1 < 6; ++i) { + PORT(0, (Isz)i, IN); + } + END_PORTS +END_PHASE +BEGIN_SOLO_PHASE_1(midi) + STOP_IF_NOT_BANGED; + Glyph channel_g = PEEK(0, 1); + Glyph octave_g = PEEK(0, 2); + Glyph note_g = PEEK(0, 3); + Glyph velocity_g = PEEK(0, 4); + Glyph length_g = PEEK(0, 5); + U8 octave_num = (U8)index_of(octave_g); + if (octave_num == 0) return; + if (octave_num > 9) octave_num = 9; + U8 note_num = midi_note_number_of(note_g); + if (note_num == UINT8_MAX) return; + Usz channel_num = index_of(channel_g); + if (channel_num > 15) channel_num = 15; + Oevent_midi* oe = (Oevent_midi*)oevent_list_alloc_item(extra_params->oevent_list); + oe->oevent_type = (U8)Oevent_type_midi; + oe->channel = (U8)channel_num; + oe->octave = (U8)usz_clamp(index_of(channel_g), 1, 9); + oe->note = note_num; + oe->velocity = midi_velocity_of(velocity_g); + oe->bar_divisor = (U8)usz_clamp(index_of(length_g), 1, 16); +END_PHASE + BEGIN_DUAL_PHASE_0(add) REALIZE_DUAL; BEGIN_DUAL_PORTS @@ -960,20 +1039,22 @@ static void sim_phase_1(Gbuffer gbuf, Mbuffer mbuf, Usz height, Usz width, } void orca_run(Gbuffer gbuf, Mbuffer mbuf, Usz height, Usz width, - Usz tick_number, Bank* bank, Piano_bits piano_bits) { + Usz tick_number, Bank* bank, Oevent_list* oevent_list, + Piano_bits piano_bits) { Glyph vars_slots[('Z' - 'A' + 1) + ('z' - 'a' + 1)]; memset(vars_slots, '.', sizeof(vars_slots)); mbuffer_clear(mbuf, height, width); - Oper_phase0_extras bank_write_params; - bank_write_params.bank = bank; - bank_write_params.bank_size = 0; - bank_write_params.vars_slots = &vars_slots[0]; - sim_phase_0(gbuf, mbuf, height, width, tick_number, &bank_write_params); - Oper_phase1_extras bank_read_params; - bank_read_params.bank = bank; - bank_read_params.bank_size = bank_write_params.bank_size; - bank_cursor_reset(&bank_read_params.cursor); - bank_read_params.vars_slots = &vars_slots[0]; - bank_read_params.piano_bits = piano_bits; - sim_phase_1(gbuf, mbuf, height, width, tick_number, &bank_read_params); + oevent_list_clear(oevent_list); + Oper_phase0_extras phase0_extras; + phase0_extras.bank = bank; + phase0_extras.bank_size = 0; + phase0_extras.vars_slots = &vars_slots[0]; + sim_phase_0(gbuf, mbuf, height, width, tick_number, &phase0_extras); + Oper_phase1_extras phase1_extras; + phase1_extras.bank = bank; + phase1_extras.bank_size = phase0_extras.bank_size; + bank_cursor_reset(&phase1_extras.cursor); + phase1_extras.vars_slots = &vars_slots[0]; + phase1_extras.piano_bits = piano_bits; + sim_phase_1(gbuf, mbuf, height, width, tick_number, &phase1_extras); } diff --git a/sim.h b/sim.h index 89a3428..ecc3cf3 100644 --- a/sim.h +++ b/sim.h @@ -16,4 +16,5 @@ static inline Piano_bits piano_bits_of(Glyph g) { } void orca_run(Gbuffer gbuf, Mbuffer markmap, Usz height, Usz width, - Usz tick_number, Bank* bank, Piano_bits piano_bits); + Usz tick_number, Bank* bank, Oevent_list* oevent_list, + Piano_bits piano_bits); diff --git a/tui_main.c b/tui_main.c index fd8b75c..077f5b8 100644 --- a/tui_main.c +++ b/tui_main.c @@ -386,7 +386,8 @@ static Usz adjust_humanized_snapped(Usz ruler, Usz in, Isz delta_rulers) { return delta_rulers > 0 ? ruler * (Usz)delta_rulers : 1; } // could overflow if inputs are big - if (delta_rulers < 0) in += ruler - 1; + if (delta_rulers < 0) + in += ruler - 1; Isz n = ((Isz)in - 1) / (Isz)ruler + delta_rulers; if (n < 0) n = 0; @@ -508,6 +509,8 @@ int main(int argc, char** argv) { bank_init(&bank); Undo_history undo_hist; undo_history_init(&undo_hist); + Oevent_list oevent_list; + oevent_list_init(&oevent_list); // Enable UTF-8 by explicitly initializing our locale before initializing // ncurses. @@ -587,7 +590,7 @@ int main(int argc, char** argv) { field_resize_raw_if_necessary(&scratch_field, field.height, field.width); field_copy(&field, &scratch_field); orca_run(field.buffer, markmap_r.buffer, field.height, field.width, - tick_num, &bank, piano_bits); + tick_num, &bank, &oevent_list, piano_bits); field_copy(&scratch_field, &field); needs_remarking = false; } @@ -724,7 +727,7 @@ int main(int argc, char** argv) { case AND_CTRL('f'): undo_history_push(&undo_hist, &field, tick_num); orca_run(field.buffer, markmap_r.buffer, field.height, field.width, - tick_num, &bank, piano_bits); + tick_num, &bank, &oevent_list, piano_bits); ++tick_num; piano_bits = ORCA_PIANO_BITS_NONE; needs_remarking = true; @@ -786,5 +789,6 @@ quit: field_deinit(&field); field_deinit(&scratch_field); undo_history_deinit(&undo_hist); + oevent_list_deinit(&oevent_list); return 0; }