From 500b9a07b93d6cd3e771edc5698e06d163da60f1 Mon Sep 17 00:00:00 2001 From: grm Date: Sat, 22 Feb 2025 02:36:27 +0200 Subject: a year of changes (web, better soundcard handling, biquad) --- src/synth_gui.c | 179 +++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 137 insertions(+), 42 deletions(-) (limited to 'src/synth_gui.c') diff --git a/src/synth_gui.c b/src/synth_gui.c index 85a5be2..6f8e06b 100644 --- a/src/synth_gui.c +++ b/src/synth_gui.c @@ -1,4 +1,5 @@ #include "synth_gui.h" +#include #define RAYGUI_IMPLEMENTATION #include "raygui.h" //#include "raylib.h" @@ -24,8 +25,9 @@ draw_text(synth_t * synth, int x, int y) DrawRectangleLines(x - 6, y - 3, 120, 3 + (count * offset) + 3, GRAY); } + void -mouse(synth_t *synth, PaStream *stream) +mouse(synth_t *synth) { float m = GetMouseWheelMove(); int x = 0; @@ -72,11 +74,11 @@ mouse(synth_t *synth, PaStream *stream) } void -keyboard(synth_t * synth, PaStream *stream) +keyboard(synth_t * synth) { int keys[] = {KEY_Q, KEY_TWO, KEY_W, KEY_THREE, KEY_E, KEY_R, KEY_FIVE, KEY_T, KEY_SIX, KEY_Y, KEY_SEVEN, KEY_U, KEY_I, KEY_NINE, KEY_O, KEY_ZERO, KEY_P, KEY_LEFT_BRACKET, KEY_EQUAL, KEY_RIGHT_BRACKET, 0}; - float note; + //float note; for (int i = 0; keys[i]; i++) { if (IsKeyPressed(keys[i])) { @@ -108,7 +110,7 @@ keyboard(synth_t * synth, PaStream *stream) if (IsKeyReleased(keys[i])) { synth->midi_note[i].noteOff = Pa_GetStreamTime(synth->stream); synth->midi_note[i].noteOffSample = synth->midi_note[i].elapsed; - note = notes[i % 12][(synth->octave + (i / 12)) % 8]; + //note = notes[i % 12][(synth->octave + (i / 12)) % 8]; } } @@ -244,19 +246,19 @@ draw_adsr(synth_t *synth, int x, int y, int width, int height) int x_prev = x; for (int i = 0; i < synth->midi_active_n; i++) { int rec_y = y + height - 1 + - 4.5 * floor( (WIDTH / 24) * + 4.5 * floor( (width / 24) * - fix_adsr(&synth->adsr, synth->midi_active[i]->noteOn, synth->midi_active[i]->noteOff, synth->midi_active[i]->elapsed, synth->midi_active[i]->noteOffSample)); - int rec_width = (WIDTH - x - x) / synth->midi_active_n; - int rec_height = HEIGHT - rec_y; + int rec_width = width / synth->midi_active_n; + int rec_height = rec_y; int red, green, blue; frequencyToColor(synth->midi_active[i]->freq * 25, &red, &green, &blue); - DrawRectangleGradientV(x_prev, rec_y - 10, rec_width, rec_height, ColorAlpha(BLUE, .2) ,ColorAlpha((Color) {red, green, blue}, .2)); + DrawRectangleGradientV(x_prev, rec_y - 10, rec_width, rec_height, ColorAlpha(BLUE, .2) ,ColorAlpha((Color) {red, green, blue, 1}, .2)); //DrawRectangleGradientV(x_prev, rec_y - 10, rec_width, rec_height, ColorAlpha(GREEN, .2) ,ColorAlpha(RED, .2)); //DrawRectangleLines(x_prev, rec_y - 10, rec_width, rec_height, GRAY); x_prev += rec_width; @@ -291,8 +293,8 @@ draw_wave(synth_t *synth, int x, int y, int width, int height) void draw_fft(synth_t *synth, int x, int y, int width, int height) { - int viz_size = width * synth->viz.rate_divider; - int fft_output_len = viz_size / 2 + 1; + size_t viz_size = width * synth->viz.rate_divider; + size_t fft_output_len = viz_size / 2 + 1; fftwf_complex* output = (fftwf_complex*)fftwf_malloc(sizeof(fftwf_complex) * fft_output_len); @@ -348,7 +350,7 @@ draw_fft(synth_t *synth, int x, int y, int width, int height) y + height, }; float thick = cell_width/3*sqrtf(t); - DrawLineEx(startPos, endPos, thick, BLUE); + DrawLineEx(startPos, endPos, thick, color); } fftwf_free(output); @@ -438,7 +440,7 @@ draw_adsr_graph(synth_t * synth, int x, int y, int width, int height) 0, // note Off (float)i/width * total_samples, 0); - } else if (i < a + d + s + r) { // draw release + } else if (r && i < a + d + s + r) { // draw release point = fix_adsr(&adsr, 0, // note On 1, // note Off @@ -453,7 +455,6 @@ draw_adsr_graph(synth_t * synth, int x, int y, int width, int height) DrawPixel(i + x , y + height - adsr_graph[i], RED); } - int off_idx = a + d + s; for (int i = 0; i < synth->midi_active_n; i++) { midi_note_t * note = synth->midi_active[i]; int elapsed_samples = note->elapsed; @@ -482,7 +483,7 @@ draw_signals(synth_t * synth, int x, int y, int width, int height) DrawRectangleLines(x, y, width, height, WHITE); if (synth->viz.wave_enabled || synth->viz.spectrum_enabled) - synth->viz.rate_divider = GuiSlider((Rectangle){ x + (width / 2) / 2, y - 12, width / 2, 12 }, "", NULL, synth->viz.rate_divider , 1, 150); + synth->viz.rate_divider = GuiSlider((Rectangle){ x + (width / 2.0) / 2, y - 12, width / 2.0, 12 }, "", NULL, synth->viz.rate_divider , 1, 150); int viz_size = width * synth->viz.rate_divider; @@ -529,30 +530,33 @@ draw_signals(synth_t * synth, int x, int y, int width, int height) draw_adsr_graph(synth, x + 20, y + 20, width - 40, height - 40); } } + char * flag = NULL; +char * flag_circle = NULL; void draw_cc_circle(cc_t * cc, int x, int y, int width, int height) { //DrawRectangleLines(x, y, width, height, WHITE); if (CheckCollisionPointRec(GetMousePosition(), (Rectangle){x, y, width, height})) { if (IsMouseButtonPressed(0)) { - flag = cc->name; + flag_circle = cc->name; } } - if (IsMouseButtonDown(0) && flag == cc->name) { + if (IsMouseButtonDown(0) && flag_circle == cc->name) { Vector2 dx = GetMouseDelta(); int x = 1; if (IsKeyDown(KEY_LEFT_SHIFT)) { x = 3; + // test x that steps cc in 10 segments + x = (cc->max - cc->min) / (10 * cc->step); } if (dx.y < 0) cc_step(cc, 1*x); if (dx.y > 0) cc_step(cc, -1*x); } - if (IsMouseButtonReleased(0) && flag == cc->name) { - flag = 0; + if (IsMouseButtonReleased(0) && flag_circle == cc->name) { + flag_circle = 0; } - int min = 110; int max = 110 + (360+70 - 110) * (cc->target) / (cc->max - cc->min); @@ -572,7 +576,8 @@ map(float value, float start1, float end1, float start2, float end2) { return start2 + (end2 - start2) * ((value - start1) / (end1 - start1)); } - +#define CC_SET(cc, value) cc->mod = value - cc->target +#include "web.h" void draw_cc_hbar(cc_t * cc, int x, int y, int width, int height) { char buf1[32], buf2[32]; @@ -586,18 +591,24 @@ draw_cc_hbar(cc_t * cc, int x, int y, int width, int height) { } if (IsMouseButtonDown(0) && flag == cc->name) { if (p.x < x) { - cc->target = cc->min; + //cc->target = cc->min; + cc_set(cc, cc->min); } else if (p.x >= x + width) { - cc->target = cc->max; + //cc->target = cc->max; + cc_set(cc, cc->max); } else { - cc->target = (cc->min + (cc->max - cc->min) * ((((p.x - x) * (float)1/width) - 0) / (1 - 0))); + //cc->target = (cc->min + (cc->max - cc->min) * ((((p.x - x) * (float)1/width) - 0) / (1 - 0))); + cc_set(cc, (cc->min + (cc->max - cc->min) * ((((p.x - x) * (float)1/width) - 0) / (1 - 0)))); } + char tmp[128] = ""; + sprintf(tmp, "%f", cc->value); + ws_send_message(tmp); } if (IsMouseButtonReleased(0) && flag == cc->name) { flag = 0; } - int current = width * (cc->target - cc->min) / (cc->max - cc->min) + cc->min; + //int current = width * (cc->target - cc->min) / (cc->max - cc->min) + cc->min; int fill_width = map(cc->target, cc->min, cc->max, 0, width - 2); @@ -614,7 +625,7 @@ draw_cc_hbar(cc_t * cc, int x, int y, int width, int height) { void draw_cc_vbar(cc_t * cc, int x, int y, int width, int height) { char buf1[32], buf2[32]; - int current = height * (cc->target - cc->min) / (cc->max - cc->min) + cc->min - 1; + //int current = height * (cc->target - cc->min) / (cc->max - cc->min) + cc->min - 1; Vector2 p = GetMousePosition(); @@ -625,11 +636,14 @@ draw_cc_vbar(cc_t * cc, int x, int y, int width, int height) { } if (IsMouseButtonDown(0) && flag == cc->name) { if (p.y < y) { - cc->target = cc->max; + //cc->target = cc->max; + cc_set(cc, cc->max); } else if (p.y >= y + height) { - cc->target = cc->min; + //cc->target = cc->min; + cc_set(cc, cc->min); } else { - cc->target = cc->min + cc->max - (cc->min + (cc->max - cc->min) * ((((p.y - y) * (float)1/height) - 0) / (1 - 0))); + //cc->target = cc->min + cc->max - (cc->min + (cc->max - cc->min) * ((((p.y - y) * (float)1/height) - 0) / (1 - 0))); + cc_set(cc, (cc->min + cc->max - (cc->min + (cc->max - cc->min) * ((((p.y - y) * (float)1/height) - 0) / (1 - 0))))); } } if (IsMouseButtonReleased(0) && flag == cc->name) { @@ -654,16 +668,21 @@ draw_bars(synth_t * synth, int x, int y, int width, int height, int offset) { int count = 0; - draw_cc_hbar(&synth->cc_adsr_a, x, y + count++ * (height + offset), width, height); - draw_cc_hbar(&synth->cc_adsr_peak, x, y + count++ * (height + offset), width, height); - draw_cc_hbar(&synth->cc_adsr_d, x, y + count++ * (height + offset), width, height); - draw_cc_hbar(&synth->cc_adsr_s, x, y + count++ * (height + offset), width, height); - draw_cc_hbar(&synth->cc_adsr_r, x, y + count++ * (height + offset), width, height); - draw_cc_hbar(&synth->cc_gain, x, y + count++ * (height + offset), width, height); + draw_cc_hbar(&synth->cc_adsr_a , x, y + count++ * (height + offset), width, height); + synth->f_adsr_enabled = GuiCheckBox((Rectangle){ x + width + offset, y + (count - 1) * (height + offset), height, 16 }, "", synth->f_adsr_enabled); + draw_cc_hbar(&synth->cc_adsr_peak , x, y + count++ * (height + offset), width, height); + draw_cc_hbar(&synth->cc_adsr_d , x, y + count++ * (height + offset), width, height); + draw_cc_hbar(&synth->cc_adsr_s , x, y + count++ * (height + offset), width, height); + draw_cc_hbar(&synth->cc_adsr_r , x, y + count++ * (height + offset), width, height); + draw_cc_hbar(&synth->cc_gain, x, y + count++ * (height + offset), width, height); + synth->autogain = GuiCheckBox((Rectangle){ x + width + offset, y + (count - 1) * (height + offset), height, 16 }, "", synth->autogain); draw_cc_hbar(&synth->cc_del_feedback, x, y + count++ * (height + offset), width, height); - draw_cc_hbar(&synth->cc_del_time, x, y + count++ * (height + offset), width, height); + draw_cc_hbar(&synth->cc_del_time , x, y + count++ * (height + offset), width, height); } +#include "sound.h" +#include "midi.h" + void rayrun(synth_t *synth){ PaTime current_time = 0; @@ -671,18 +690,40 @@ rayrun(synth_t *synth){ osc_sound(0); + char *midi_devices = get_midi_devices(); + //char *midi_devices = "test1;test2;test3"; + char *soundcards = get_soundcards(); + int old_soundcard_id = synth->soundcard_id; + int old_midi_device_id = synth->midi_device_id; + InitWindow(WIDTH, HEIGHT, "Raylib synth"); SetTargetFPS(60); // Set our game to run at 60 frames-per-second while (!WindowShouldClose()) { - keyboard(synth, synth->stream); - mouse(synth, synth->stream); + keyboard(synth); + mouse(synth); // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(BLACK); - draw_cc_circle(&synth->cc_pitch, 30, 250, 30, 30); + int fb = 0; + int foffset = 9; + draw_cc_circle(&synth->cc_adsr_a, 30 + (30 + foffset) * fb++, 180, 30, 30); + draw_cc_circle(&synth->cc_adsr_peak, 30 + (30 + foffset) * fb++, 180, 30, 30); + draw_cc_circle(&synth->cc_adsr_d, 30 + (30 + foffset) * fb++, 180, 30, 30); + draw_cc_circle(&synth->cc_adsr_s, 30 + (30 + foffset) * fb++, 180, 30, 30); + draw_cc_circle(&synth->cc_adsr_r, 30 + (30 + foffset) * fb++, 180, 30, 30); + + draw_cc_circle(&synth->cc_pitch, 30, 220, 30, 30); + + fb = 0; + draw_cc_circle(&synth->cc_f_adsr_a, 30 + (30 + foffset) * fb++, 260, 30, 30); + draw_cc_circle(&synth->cc_f_adsr_peak, 30 + (30 + foffset) * fb++, 260, 30, 30); + draw_cc_circle(&synth->cc_f_adsr_d, 30 + (30 + foffset) * fb++, 260, 30, 30); + draw_cc_circle(&synth->cc_f_adsr_s, 30 + (30 + foffset) * fb++, 260, 30, 30); + draw_cc_circle(&synth->cc_f_adsr_r, 30 + (30 + foffset) * fb++, 260, 30, 30); + draw_cc_hbar(&synth->cc_cutoff, 30, 300, 256, 24); draw_cc_vbar(&synth->cc_resonance, 330, 20, 24, 256); //draw_cc_vbar(&synth->cc_adsr_s, 30, 250, 30, 30); @@ -691,20 +732,32 @@ rayrun(synth_t *synth){ // GUI char buf[64]; snprintf(buf, sizeof buf, "%d", synth->wvt_pos); - synth->wvt_pos = GuiSlider((Rectangle){WIDTH / 2 - 108, 150 + 42 + 42, 216, 24 }, "", buf, synth->wvt_pos , 0, 127); + synth->wvt_pos = GuiSlider((Rectangle){WIDTH / 2.0 - 108, 150 + 42 + 42, 216, 24 }, "", buf, synth->wvt_pos , 0, 127); set_sound_start(synth->wvt_pos*2048); set_sound_len(synth->wvt_pos*2048 + 2048); draw_bars(synth, 20, 20, 200, 16, 3); draw_text(synth, WIDTH / 2 - 108, 20); - if ( GuiButton((Rectangle){ WIDTH / 2 - 108, 150 - 6 - 6 + 42, 216, 6 }, "")) { + if ( GuiButton((Rectangle){ WIDTH / 2.0 - 108, 150 - 6 - 6 + 42, 216, 6 }, "")) { synth->x = 1; } snprintf(buf, sizeof buf, "%.1f", synth->x); - synth->x = GuiSlider((Rectangle){ WIDTH / 2 - 108, 150 + 42, 216, 24 }, "x", buf, synth->x , 0.0f, 2.0f); + synth->x = GuiSlider((Rectangle){ WIDTH / 2.0 - 108, 150 + 42, 216, 24 }, "x", buf, synth->x , 0.0f, 2.0f); - synth->filter = GuiToggle((Rectangle){ WIDTH - 100 - 50 - 100 - 50 , 50 , 100, 24 }, "FILTER", synth->filter); + synth->filter = GuiToggle((Rectangle){ WIDTH - 100 - 50 - 100 - 50 , 50 , 46, 24 }, "LP", synth->filter); + synth->biquad = GuiToggle((Rectangle){ WIDTH - 100 - 50 - 100 - 50 + 46 + 8 , 50 , 46, 24 }, "bq", synth->biquad); + if (synth->biquad) { + if (GuiToggle((Rectangle){WIDTH - 100 - 50 - 100 - 50 , 50 + 24 + 6 + 24 + 6, 24, 24}, "l", synth->biquad_type == 'l')) { + synth->biquad_type = 'l'; + } + if (GuiToggle((Rectangle){WIDTH - 100 - 50 - 100 - 50 + 24 + 8, 50 + 24 + 6 + 24 + 6, 24, 24}, "b", synth->biquad_type == 'b')) { + synth->biquad_type = 'b'; + } + if (GuiToggle((Rectangle){WIDTH - 100 - 50 - 100 - 50 + 24 + 8 + 24 + 8 , 50 + 24 + 6 + 24 + 6, 24, 24}, "h", synth->biquad_type == 'h')) { + synth->biquad_type = 'h'; + } + } GuiSpinner((Rectangle){ WIDTH - 100 - 50 , 50, 100, 24 }, "oct: ", &(synth->octave), 0, 7, 0); snprintf(buf, sizeof buf, "generator %d --> ", synth->geni); @@ -712,6 +765,17 @@ rayrun(synth_t *synth){ synth->clamp = GuiToggle((Rectangle){ WIDTH - 100 - 50, 50 + 24 + 6 + 24 + 6, 100, 24 }, "clamp", synth->clamp); synth->delay = GuiToggle((Rectangle){ WIDTH - 100 - 50, 50 + 24 + 6 + 24 + 6 + 24 + 6, 100, 24 }, "delay", synth->delay); + + if ( GuiButton((Rectangle){ WIDTH - 100 - 50, 50 + 24 + 6 + 24 + 6 + 24 + 6 + 24 + 6 + 24 + 6, 100, 24 }, "SAVE!")) { + save_synth(synth, "asdas"); + } + + if ( GuiButton((Rectangle){ WIDTH - 100 - 50, 50 + 24 + 6 + 24 + 6 + 24 + 6 + 24 + 6 + 24 + 6 + 24 + 6, 100, 24 }, "LOAD!")) { + load_synth(synth, "asdas"); + } + + static int edit_midi = 0; + static int edit_sound = 0; // signals draw_signals(synth, 20, 390, WIDTH - 2*20, 200); @@ -722,6 +786,34 @@ rayrun(synth_t *synth){ /* snprintf(buf, sizeof buf, "stream time: %f", Pa_GetStreamTime(synth->stream)); */ /* DrawText(buf, WIDTH / 2 -300, HEIGHT - 300, 11, LIGHTGRAY); */ + // midi dev + if (GuiDropdownBox( + (Rectangle){WIDTH - 200 - 50, + 50 + 24 + 6 + 24 + 6 + 24 + 6 + 24 + 6 , 200, + 24}, + midi_devices, &synth->midi_device_id, edit_midi)) { + edit_midi = !edit_midi; + } + + if (old_midi_device_id != synth->midi_device_id) { + old_midi_device_id = synth->midi_device_id; + change_midi_device(synth); + } + + // audio dev + if (GuiDropdownBox( + (Rectangle){WIDTH - 300 - 50, + 12, 300, + 24}, + soundcards, &synth->soundcard_id, edit_sound)) { + edit_sound = !edit_sound; + } + + if (old_soundcard_id != synth->soundcard_id) { + old_soundcard_id = synth->soundcard_id; + change_soundcard(synth); + } + EndDrawing(); //---------------------------------------------------------------------------------- @@ -729,6 +821,9 @@ rayrun(synth_t *synth){ //printf("%f :: %ld\n", current_time - prev_time, phase); prev_time = current_time; + (void)prev_time; } + free(soundcards); + free(midi_devices); CloseWindow(); } -- cgit v1.2.3