From 98b7009f2c05afbd4cc68869a6f544ae67f696c1 Mon Sep 17 00:00:00 2001 From: Mitya Selivanov Date: Fri, 29 Sep 2023 00:20:07 +0200 Subject: Cursor indicators; Note volume adjustment --- TODO | 2 + source/saw/main.c | 162 ++++++++++++++++++++++++++++++++++++------------------ 2 files changed, 112 insertions(+), 52 deletions(-) diff --git a/TODO b/TODO index 35cfbf9..dc4b78a 100644 --- a/TODO +++ b/TODO @@ -29,6 +29,8 @@ To-Do list - Sound: Sampler - Sound: Sample loading - Sound: Sample rendering +- UI: Matrix view +- UI: Graph view Done diff --git a/source/saw/main.c b/source/saw/main.c index fdcda68..77ec5df 100644 --- a/source/saw/main.c +++ b/source/saw/main.c @@ -28,7 +28,7 @@ enum { SAW_SAMPLE_RATE = 44100, VOICE_COUNT = 16, - ROLL_SIZE = 60, + ROLL_SIZE = 80, SHEET_SIZE = 200, ROLL_COUNT = 16, @@ -40,6 +40,7 @@ typedef struct { i64 time; f64 duration; f64 frequency; + f64 amplitude; } saw_voice_t; typedef struct { @@ -61,7 +62,8 @@ typedef struct { i8 grid_input; i32 grid_note; i32 grid_time; - i8 offset_input; + i8 offset_x_input; + i8 offset_y_input; i64 offset_x; i64 offset_y; } saw_roll_t; @@ -135,6 +137,10 @@ 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); +} + static void saw_playback(i32 frame_count) { if (!saw_playback_on) return; @@ -167,6 +173,7 @@ static void saw_playback(i32 frame_count) { .time = 0, .duration = ((f64) p->duration) / roll->rate, .frequency = saw_pitch_frequency(p->pitch), + .amplitude = saw_pitch_amplitude(p->pitch), }; } } @@ -191,7 +198,7 @@ static void saw_audio(ma_device *device, void *void_out_, f64 period = M_PI * 2.; f64 frequency = saw_voices[n].frequency; - f64 amplitude = .2; + f64 amplitude = saw_voices[n].amplitude; // envelope f64 attack = .007; @@ -394,20 +401,21 @@ static void saw_ui_compose(i64 x0, i64 y0, i64 width, i64 height) { } saw_rolls[n] = (saw_roll_t) { - .enabled = 1, - .track = track, - .last_index = -1, - .turned_off = { 0 }, - .rate = 6, - .notes = { 0 }, - .frame = frame, - .size = 6 / grid_rate, - .grid_input = 0, - .grid_note = 0, - .grid_time = 0, - .offset_input = 0, - .offset_x = 0, - .offset_y = ROLL_DEFAULT_OFFSET_Y, + .enabled = 1, + .track = track, + .last_index = -1, + .turned_off = { 0 }, + .rate = 6, + .notes = { 0 }, + .frame = frame, + .size = 6 / grid_rate, + .grid_input = 0, + .grid_note = 0, + .grid_time = 0, + .offset_x_input = 0, + .offset_y_input = 0, + .offset_x = 0, + .offset_y = ROLL_DEFAULT_OFFSET_Y, }; saw_current_roll = n; @@ -483,6 +491,23 @@ static void saw_ui_compose(i64 x0, i64 y0, i64 width, i64 height) { nvgFillColor(saw_nvg, nvgRGBA(240, 240, 80, 180)); nvgFill(saw_nvg); } + + // Cursor indicator + // + if (saw_mouse_x >= x0 && saw_mouse_x < x0 + width && + saw_mouse_y >= frame_height - y0 - height && + saw_mouse_y < frame_height - y0) { + i32 dx = x0 + saw_compose.offset_x; + i32 s = grid_scale / grid_rate; + i32 x = dx + ((saw_mouse_x - dx + s / 2) / s) * s; + i32 w = border * 4; + + nvgBeginPath(saw_nvg); + nvgRect(saw_nvg, x - w / 2, frame_height - y0 - height, w, + height); + nvgFillColor(saw_nvg, nvgRGBA(80, 80, 240, 160)); + nvgFill(saw_nvg); + } } static void saw_ui_roll(saw_roll_t *roll, i64 x0, i64 y0, i64 width, @@ -561,7 +586,8 @@ static void saw_ui_roll(saw_roll_t *roll, i64 x0, i64 y0, i64 width, .enabled = 1, .time = 0, .duration = .6, - .frequency = saw_pitch_frequency(pitch) + .frequency = saw_pitch_frequency(pitch), + .amplitude = saw_pitch_amplitude(pitch), }; } @@ -575,12 +601,21 @@ static void saw_ui_roll(saw_roll_t *roll, i64 x0, i64 y0, i64 width, if (!hover_any) roll->last_index = -1; - if (saw_mbutton_click && saw_mouse_x >= x0 && - saw_mouse_y >= frame_height - y0 - height && - saw_mouse_x < x0 + width && saw_mouse_y < frame_height - y0) - roll->offset_input = 1; - if (!saw_mbutton_down && roll->offset_input) - roll->offset_input = 0; + // Offset input + if (saw_mbutton_click) { + if (saw_mouse_x >= x0 + pianokey_width + sheet_offset && + saw_mouse_y >= frame_height - y0 - height && + saw_mouse_x < x0 + width && saw_mouse_y < frame_height - y0) + roll->offset_x_input = 1; + if (saw_mouse_x >= x0 && + saw_mouse_y >= frame_height - y0 - height && + saw_mouse_x < x0 + width && saw_mouse_y < frame_height - y0) + roll->offset_y_input = 1; + } + if (!saw_mbutton_down) { + roll->offset_x_input = 0; + roll->offset_y_input = 0; + } // Draw music sheet // @@ -759,21 +794,42 @@ static void saw_ui_roll(saw_roll_t *roll, i64 x0, i64 y0, i64 width, // Playback indicator // + { + i32 x = x0 + pianokey_width + sheet_offset + roll->offset_x - + border * 2 + + ((saw_playback_frame - roll->frame) * roll->rate * + sheet_scale + + SAW_SAMPLE_RATE / 2) / + SAW_SAMPLE_RATE; + i32 w = border * 4; + + if (x >= x0 + pianokey_width + sheet_offset - border * 2 && + x < x0 + width) { + nvgBeginPath(saw_nvg); + nvgRect(saw_nvg, x, frame_height - y0 - height + text_height, w, + height - text_height); + nvgFillColor(saw_nvg, nvgRGBA(240, 240, 80, 180)); + nvgFill(saw_nvg); + } + } - i32 x = x0 + pianokey_width + sheet_offset + roll->offset_x - - border * 2 + - ((saw_playback_frame - roll->frame) * roll->rate * - sheet_scale + - SAW_SAMPLE_RATE / 2) / - SAW_SAMPLE_RATE; - i32 w = border * 4; + // Cursor indicator + // + if (saw_mouse_x >= x0 + pianokey_width + sheet_offset && + saw_mouse_x < x0 + width && + saw_mouse_y >= frame_height - y0 - height && + saw_mouse_y < frame_height - y0) { + i32 dx = x0 + pianokey_width + sheet_offset + roll->offset_x; + i32 x = dx + + ((saw_mouse_x - dx + sheet_scale / 2) / sheet_scale) * + sheet_scale; + i32 w = border * 4; - if (x >= x0 + pianokey_width + sheet_offset - border * 2 && - x < x0 + width) { nvgBeginPath(saw_nvg); - nvgRect(saw_nvg, x, frame_height - y0 - height + text_height, w, + nvgRect(saw_nvg, x - w / 2, + frame_height - y0 - height + text_height, w, height - text_height); - nvgFillColor(saw_nvg, nvgRGBA(240, 240, 80, 180)); + nvgFillColor(saw_nvg, nvgRGBA(80, 80, 240, 160)); nvgFill(saw_nvg); } } @@ -813,20 +869,21 @@ static void saw_init(void) { saw_compose.rolls[i] = (i == 0 ? 0 : -1); saw_rolls[i] = (saw_roll_t) { - .enabled = (i == 0), - .track = 0, - .last_index = -1, - .turned_off = { 0 }, - .rate = 6, - .notes = { 0 }, - .frame = 0, - .size = 48, - .grid_input = 0, - .grid_note = 0, - .grid_time = 0, - .offset_input = 0, - .offset_x = 0, - .offset_y = ROLL_DEFAULT_OFFSET_Y, + .enabled = (i == 0), + .track = 0, + .last_index = -1, + .turned_off = { 0 }, + .rate = 6, + .notes = { 0 }, + .frame = 0, + .size = 48, + .grid_input = 0, + .grid_note = 0, + .grid_time = 0, + .offset_x_input = 0, + .offset_y_input = 0, + .offset_x = 0, + .offset_y = ROLL_DEFAULT_OFFSET_Y, }; } } @@ -880,11 +937,12 @@ static void saw_event(sapp_event const *event) { saw_mouse_x = event->mouse_x; saw_mouse_y = event->mouse_y; - for (i64 i = 0; i < ROLL_COUNT; i++) - if (saw_rolls[i].offset_input) { + for (i64 i = 0; i < ROLL_COUNT; i++) { + if (saw_rolls[i].offset_x_input) saw_rolls[i].offset_x += event->mouse_dx; + if (saw_rolls[i].offset_y_input) saw_rolls[i].offset_y += event->mouse_dy; - } + } break; -- cgit v1.2.3