From 9fc7653a331a6d03d1e937f1d7dd7a2619f712e2 Mon Sep 17 00:00:00 2001 From: Mitya Selivanov Date: Wed, 6 Mar 2024 00:27:04 +0100 Subject: Grid widget: work in progress --- source/saw/main.c | 226 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 151 insertions(+), 75 deletions(-) diff --git a/source/saw/main.c b/source/saw/main.c index e20b702..47c6a31 100644 --- a/source/saw/main.c +++ b/source/saw/main.c @@ -122,11 +122,22 @@ enum { TINT_WHITE = 0, TINT_ORANGE, TINT_PINK, + + UI_MAIN = 0, + UI_DEV, + + UI_TAB_COUNT, }; // Data types // +typedef struct { + i64 value; + i64 num; // numerator + i64 den; // denominator +} saw_rate_t; + typedef struct { b8 enabled; i64 time; @@ -227,9 +238,31 @@ typedef struct { } saw_ui_color_t; typedef struct { - i8 type; - str_t data; -} saw_project_token_t; + b8 enabled; + b8 selected; + i64 row; + f64 position; + f64 size; +} saw_ui_grid_item_t; + +typedef struct { + f64 x0; + f64 y0; + f64 width; + f64 height; + f64 offset_x; + f64 offset_y; + f64 scale_x; + f64 scale_y; + i64 time_begin; + i64 time_end; + i64 time_cursor; + i64 time_rate; + i64 time_num; // numerator + i64 time_den; // denominator + i64 items_size; + saw_ui_grid_item_t *items; +} saw_ui_grid_t; // ================================================================ // @@ -340,6 +373,8 @@ static i64 saw_ui_input_index = 0; static i64 saw_ui_input_active = -1; static f64 saw_ui_input_buffer = 0.; +static i32 saw_ui_tab = UI_MAIN; + // ================================================================ // // Sound @@ -348,6 +383,11 @@ static f64 saw_ui_input_buffer = 0.; // When music and signal processing procedures become stable enough // we will separate them into a library and add tests. // +// TODO +// - Apply volume during sound generation. +// - Implement proper frequency shift. +// - Unify similar logic for Oscillators and Samplers. +// // ================================================================ #ifdef __GNUC__ @@ -411,7 +451,7 @@ static void saw_tuning_pythagorean(f64 *tuning, i64 base_pitch) { } static f64 saw_random(f64 min, f64 max) { - if (max - min < .000001) + if (max - min < EPS) return min; u64 x = mt64_generate(&saw_rng_mt64); u64 range = (u64) ((max - min) * 10000 + 0.5); @@ -434,10 +474,6 @@ static f64 saw_envelope(f64 t, f64 attack, f64 decay, f64 sustain, return a; } -static f64 saw_pitch_frequency(i64 pitch) { - return pow(2., 5.5 + pitch / 12.); -} - static f64 saw_pitch_amplitude(i64 pitch) { return .2 / exp(0.02 * pitch); } @@ -457,9 +493,6 @@ static void saw_play_voice(saw_track_t *track, saw_roll_t *roll, f64 frequency = roll->tuning[pitch]; switch (track->instrument) { - // FIXME - // Apply volume during sound generation. - case INSTRUMENT_OSCILLATOR: { saw_oscillator_t *osc = &track->oscillator; @@ -529,9 +562,6 @@ static f64 saw_oscillator(i32 type, f64 frequency, f64 phase, static f64 saw_sampler(saw_sampler_t *sam, i32 channel, f64 frequency, i64 t) { - // FIXME - // Implement proper frequency shift. - i64 i = (i64) floor((t * frequency) / sam->base_frequency + .5) * 2 + channel; @@ -543,9 +573,6 @@ static f64 saw_sampler(saw_sampler_t *sam, i32 channel, f64 frequency, } static void saw_audio_render(void) { - // FIXME - // Improve performance. - i64 frame_count = (BUFFER_SIZE / CHANNEL_COUNT); if (mtx_lock(&saw_playback_mutex) != thrd_success) { @@ -608,9 +635,6 @@ static void saw_audio_render(void) { saw_track_t *track = saw_tracks + saw_voices[n].track; switch (track->instrument) { - // FIXME - // Unify similar logic for Oscillators and Samplers. - case INSTRUMENT_OSCILLATOR: { saw_oscillator_t *osc = &track->oscillator; @@ -1863,6 +1887,11 @@ static void saw_ui_value_list(f64 x0, f64 y0, f64 width, f64 height, ++saw_ui_input_index; } +static void saw_ui_grid(saw_ui_grid_t *grid) { + // TODO + // +} + static void saw_ui_reset_offset(void) { if (saw_current_roll != -1) { saw_rolls[saw_current_roll].ui_offset_x = 0.; @@ -3345,18 +3374,23 @@ static void saw_frame(void) { // Process input // { + // Playback + // if (saw_key_pressed[SAPP_KEYCODE_SPACE]) saw_playback_on = !saw_playback_on; if (saw_key_pressed[SAPP_KEYCODE_ENTER]) saw_playback_frame = 0; - if (saw_key_pressed[SAPP_KEYCODE_ESCAPE]) - saw_ui_reset_offset(); + + // Duplicate + // if (saw_key_pressed[SAPP_KEYCODE_D] || (saw_edit_mode == EDIT_MODE_CLONE && saw_lbutton_click)) saw_compose.duplicate_input = 1; // Panning control // + if (saw_key_pressed[SAPP_KEYCODE_ESCAPE]) + saw_ui_reset_offset(); for (i64 i = 0; i < ROLL_COUNT; i++) { if (saw_rolls[i].ui_offset_x_input) saw_rolls[i].ui_offset_x += saw_mouse_dx; @@ -3367,6 +3401,11 @@ static void saw_frame(void) { saw_compose.ui_offset_x += saw_mouse_dx; saw_compose.ui_offset_y += saw_mouse_dy; } + + // Tabs + // + if (saw_key_pressed[SAPP_KEYCODE_TAB]) + saw_ui_tab = (saw_ui_tab + 1) % UI_TAB_COUNT; } // Render UI @@ -3378,66 +3417,103 @@ static void saw_frame(void) { // correctly. saw_ui_begin(); - // Adjust UI layout - // - i64 track_width = frame_width / 5; - if (track_width < 330) - track_width = 330; - if (track_width > frame_width / 2) - track_width = frame_width / 2; - - i64 header_height = 80; - i64 roll_height = (frame_height * 3) / 5; - i64 compose_height = frame_height - roll_height - header_height; - i64 track_height = frame_height - header_height; - - // Render header - // + switch (saw_ui_tab) { + case UI_MAIN: { + // Adjust UI layout + // + i64 track_width = frame_width / 5; + if (track_width < 330) + track_width = 330; + if (track_width > frame_width / 2) + track_width = frame_width / 2; + + i64 header_height = 80; + i64 roll_height = (frame_height * 3) / 5; + i64 compose_height = frame_height - roll_height - + header_height; + i64 track_height = frame_height - header_height; + + // Render header + // - saw_ui_header(0, // x0 - frame_height - header_height, // y0 - frame_width, // width - header_height // height - ); + saw_ui_header(0, // x0 + frame_height - header_height, // y0 + frame_width, // width + header_height // height + ); - // Render compose view - // - saw_ui_compose(0, // x0 - roll_height, // y0 - frame_width - track_width, // width - compose_height // height - ); - - if (saw_current_track != -1) { - // Render track view - // + // Render compose view + // + saw_ui_compose(0, // x0 + roll_height, // y0 + frame_width - track_width, // width + compose_height // height + ); + + if (saw_current_track != -1) { + // Render track view + // + + c8 buf[64]; + sprintf(buf, "Track %lld", saw_current_track + 1); + + saw_ui_track(saw_tracks + saw_current_track, // track + frame_width - track_width, // x0 + 0, // y0 + track_width, // width + track_height, // height + kit_str(strlen(buf), buf) // label + ); + } - c8 buf[64]; - sprintf(buf, "Track %lld", saw_current_track + 1); + if (saw_current_roll != -1) { + // Render roll view + // - saw_ui_track(saw_tracks + saw_current_track, // track - frame_width - track_width, // x0 - 0, // y0 - track_width, // width - track_height, // height - kit_str(strlen(buf), buf) // label - ); - } + c8 buf[64]; + sprintf(buf, "Sheet %lld", saw_current_roll + 1); - if (saw_current_roll != -1) { - // Render roll view - // + saw_ui_roll(saw_rolls + saw_current_roll, // roll + 0, // x0 + 0, // y0 + frame_width - track_width, // width + roll_height, // height + kit_str(strlen(buf), buf) // label + ); + } - c8 buf[64]; - sprintf(buf, "Sheet %lld", saw_current_roll + 1); + } break; + + case UI_DEV: { + // FIXME + + i64 time_rate = 256; + saw_ui_grid_item_t items[100] = { 0 }; + + saw_ui_grid_t grid = { + .x0 = 20., + .y0 = 20., + .width = frame_width - 40., + .height = frame_height - 40., + .offset_x = 0., + .offset_y = 0., + .scale_x = 1., + .scale_y = 1., + .time_begin = 0, + .time_end = time_rate * 10, + .time_cursor = (saw_playback_frame * time_rate) / + SAMPLE_RATE, + .time_rate = time_rate, + .time_num = 4, + .time_den = 4, + .items_size = sizeof items / sizeof *items, + .items = items, + }; - saw_ui_roll(saw_rolls + saw_current_roll, // roll - 0, // x0 - 0, // y0 - frame_width - track_width, // width - roll_height, // height - kit_str(strlen(buf), buf) // label - ); + saw_ui_grid(&grid); + } break; + + default:; } saw_ui_end(); -- cgit v1.2.3