diff options
Diffstat (limited to 'src/synth_gui.c')
-rw-r--r-- | src/synth_gui.c | 432 |
1 files changed, 266 insertions, 166 deletions
diff --git a/src/synth_gui.c b/src/synth_gui.c index 47a9125..85a5be2 100644 --- a/src/synth_gui.c +++ b/src/synth_gui.c @@ -4,7 +4,7 @@ //#include "raylib.h" void -draw_text(synth_t * synth, Font f, int x, int y) +draw_text(synth_t * synth, int x, int y) { char buf[64]; int count = 0; @@ -24,7 +24,6 @@ draw_text(synth_t * synth, Font f, int x, int y) DrawRectangleLines(x - 6, y - 3, 120, 3 + (count * offset) + 3, GRAY); } -int flag =0; void mouse(synth_t *synth, PaStream *stream) { @@ -48,28 +47,28 @@ mouse(synth_t *synth, PaStream *stream) } } - if (CheckCollisionPointRec(GetMousePosition(), (Rectangle){30, 250, 30, 30})) { - SetMouseCursor(6); - if (IsMouseButtonPressed(0)) { - flag = 1; - } - } else { - SetMouseCursor(0); - } + /* if (CheckCollisionPointRec(GetMousePosition(), (Rectangle){30, 250, 30, 30})) { */ + /* SetMouseCursor(6); */ + /* if (IsMouseButtonPressed(0)) { */ + /* flag = 1; */ + /* } */ + /* } else { */ + /* SetMouseCursor(0); */ + /* } */ - if (IsMouseButtonDown(0) && flag) { - SetMouseCursor(6); - Vector2 dx = GetMouseDelta(); - int x = 1; - if (IsKeyDown(KEY_LEFT_SHIFT)) { - x = 3; - } - if (dx.y < 0) cc_step(&synth->cc_adsr_s, 1*x); - if (dx.y > 0) cc_step(&synth->cc_adsr_s, -1*x); - } - if (IsMouseButtonReleased(0)) { - flag = 0; - } + /* if (IsMouseButtonDown(0) && flag) { */ + /* SetMouseCursor(6); */ + /* Vector2 dx = GetMouseDelta(); */ + /* int x = 1; */ + /* if (IsKeyDown(KEY_LEFT_SHIFT)) { */ + /* x = 3; */ + /* } */ + /* if (dx.y < 0) cc_step(&synth->cc_adsr_s, 1*x); */ + /* if (dx.y > 0) cc_step(&synth->cc_adsr_s, -1*x); */ + /* } */ + /* if (IsMouseButtonReleased(0)) { */ + /* flag = 0; */ + /* } */ } void @@ -104,6 +103,7 @@ keyboard(synth_t * synth, PaStream *stream) synth->active = 1; } } + for (int i = 0; keys[i]; i++) { if (IsKeyReleased(keys[i])) { synth->midi_note[i].noteOff = Pa_GetStreamTime(synth->stream); @@ -111,13 +111,13 @@ keyboard(synth_t * synth, PaStream *stream) note = notes[i % 12][(synth->octave + (i / 12)) % 8]; } } - - int mods[] = {KEY_Z, KEY_X, KEY_C, KEY_V, KEY_B, KEY_N, KEY_M, 0}; + + int patates[] = {KEY_Z, KEY_X, KEY_C, KEY_V, KEY_B, KEY_N, KEY_M, 0}; synth->modi = 0; - for (int i = 0; mods[i]; i++) { - if (IsKeyDown(mods[i])) { - synth->modifiers[synth->modi++] = mods[i]; - } + for (int i = 0; patates[i]; i++) { + if (IsKeyDown(patates[i])) { + synth->modifiers[synth->modi++] = patates[i]; + } } if (IsKeyDown(265)) { // up @@ -179,77 +179,53 @@ keyboard(synth_t * synth, PaStream *stream) } } -void -draw_bars(synth_t * synth, int x, int y, int width, int height, int offset) -{ - char buf[64]; - int count = 0; - - snprintf(buf, sizeof buf, "%.3f", synth->adsr.a); - synth->adsr.a = GuiSlider((Rectangle){ x, y + count++ * (height + offset), width, height }, "A: ", buf, synth->adsr.a , 0.00001f, 2.0f); - snprintf(buf, sizeof buf, "%.3f", synth->adsr.peak); - synth->adsr.peak = GuiSlider((Rectangle){ x, y + count++ * (height + offset), width, height }, "P: ", buf, synth->adsr.peak , 0.0f, 1.0f); - snprintf(buf, sizeof buf, "%.3f", synth->adsr.d); - synth->adsr.d = GuiSlider((Rectangle){ x, y + count++ * (height + offset), width, height }, "D: ", buf, synth->adsr.d , 0.001f, 2.0f); - snprintf(buf, sizeof buf, "%.3f", synth->adsr.s); - synth->adsr.s = GuiSlider((Rectangle){ x, y + count++ * (height + offset), width, height }, "S: ", buf, synth->adsr.s , 0.0f, 1.0f); - snprintf(buf, sizeof buf, "%.3f", synth->adsr.r); - synth->adsr.r = GuiSlider((Rectangle){ x, y + count++ * (height + offset), width, height }, "R: ", buf, synth->adsr.r , 0.001f, 3.0f); - snprintf(buf, sizeof buf, "%.3f", synth->gain); - synth->gain = GuiSlider((Rectangle){ x, y + count++ * (height + offset), width, height }, "gain: ", buf, synth->gain , 0.0f, 2.0f); - snprintf(buf, sizeof buf, "%.3f", synth->del_feedback); - synth->del_feedback = GuiSlider((Rectangle){ x, y + count++ * (height + offset), width, height }, "fb: ", buf, synth->del_feedback , 0.0f, 1.0f); - snprintf(buf, sizeof buf, "%.3f", synth->del_time); - synth->del_time = GuiSlider((Rectangle){ x, y + count++ * (height + offset), width, height }, "del_time: ", buf, synth->del_time , 0.0f, 0.3f); -} - void frequencyToColor(float frequency, int *red, int *green, int *blue) { - // Assuming frequency ranges from 20 to 20000 Hz - float minFrequency = 20.0; - float maxFrequency = 20000.0; - - // Map the frequency to a value between 0 and 1 - float normalizedFrequency = (frequency - minFrequency) / (maxFrequency - minFrequency); - - // Define colors for the rainbow spectrum - float hue = normalizedFrequency * 360.0; - - // Convert HSV to RGB - float c = 1.0; - float x = c * (1.0 - fabs(fmod(hue / 60.0, 2.0) - 1.0)); - float m = 0.0; - - float r, g, b; - - if (hue >= 0 && hue < 60) { - r = c; - g = x; - b = 0; - } else if (hue >= 60 && hue < 120) { - r = x; - g = c; - b = 0; - } else if (hue >= 120 && hue < 180) { - r = 0; - g = c; - b = x; - } else if (hue >= 180 && hue < 240) { - r = 0; - g = x; - b = c; - } else if (hue >= 240 && hue < 300) { - r = x; - g = 0; - b = c; - } else { - r = c; - g = 0; - b = x; - } + // Assuming frequency ranges from 20 to 20000 Hz + float minFrequency = 20.0; + float maxFrequency = 20000.0; + + // Map the frequency to a value between 0 and 1 + float normalizedFrequency = (frequency - minFrequency) / (maxFrequency - minFrequency); + + // Define colors for the rainbow spectrum + float hue = normalizedFrequency * 360.0; + + // Convert HSV to RGB + float c = 1.0; + float x = c * (1.0 - fabs(fmod(hue / 60.0, 2.0) - 1.0)); + float m = 0.0; + + float r, g, b; + + if (hue >= 0 && hue < 60) { + r = c; + g = x; + b = 0; + } else if (hue >= 60 && hue < 120) { + r = x; + g = c; + b = 0; + } else if (hue >= 120 && hue < 180) { + r = 0; + g = c; + b = x; + } else if (hue >= 180 && hue < 240) { + r = 0; + g = x; + b = c; + } else if (hue >= 240 && hue < 300) { + r = x; + g = 0; + b = c; + } else { + r = c; + g = 0; + b = x; + } - *red = (int)((r + m) * 255); - *green = (int)((g + m) * 255); - *blue = (int)((b + m) * 255); + *red = (int)((r + m) * 255); + *green = (int)((g + m) * 255); + *blue = (int)((b + m) * 255); } #include "fftw3.h" @@ -315,66 +291,67 @@ 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; + int viz_size = width * synth->viz.rate_divider; + int fft_output_len = viz_size / 2 + 1; - fftwf_complex* output = (fftwf_complex*)fftwf_malloc(sizeof(fftwf_complex) * fft_output_len); + fftwf_complex* output = (fftwf_complex*)fftwf_malloc(sizeof(fftwf_complex) * fft_output_len); - fftwf_plan forward_plan = fftwf_plan_dft_r2c_1d(fft_output_len, synth->viz.fft_input_buffer, output, FFTW_ESTIMATE); + fftwf_plan forward_plan = fftwf_plan_dft_r2c_1d(fft_output_len, synth->viz.fft_input_buffer, output, FFTW_ESTIMATE); - fftwf_execute(forward_plan); + fftwf_execute(forward_plan); - fftwf_destroy_plan(forward_plan); + fftwf_destroy_plan(forward_plan); - // "Squash" into the Logarithmic Scale - float step = 1.06; - float lowf = 1.0f; - size_t m = 0; - float max_amp_tso = 1.0f; - for (float f = lowf; (size_t) f < fft_output_len/2; f = ceilf(f*step)) { - float f1 = ceilf(f*step); - float a = 0.0f; - for (size_t q = (size_t) f; q < fft_output_len/2 && q < (size_t) f1; ++q) { - float b = log(sqrt(output[q][0]*output[q][0] + output[q][1]*output[q][1])); - if (b > a) a = b; - } - if (max_amp_tso < a) max_amp_tso = a; - synth->viz.fft_output_buffer[m++] = a; + // "Squash" into the Logarithmic Scale + float step = 1.06; + float lowf = 1.0f; + size_t m = 0; + float max_amp_tso = 1.0f; + for (float f = lowf; (size_t) f < fft_output_len/2; f = ceilf(f*step)) { + float f1 = ceilf(f*step); + float a = 0.0f; + for (size_t q = (size_t) f; q < fft_output_len/2 && q < (size_t) f1; ++q) { + // maybe take the log? maybe not + float b = log(sqrt(output[q][0]*output[q][0] + output[q][1]*output[q][1])); + if (b > a) a = b; } + if (max_amp_tso < a) max_amp_tso = a; + synth->viz.fft_output_buffer[m++] = a; + } - // Normalize Frequencies to 0..1 range - for (size_t i = 0; i < m; ++i) { - synth->viz.fft_output_buffer[i] /= max_amp_tso; - } + // Normalize Frequencies to 0..1 range + for (size_t i = 0; i < m; ++i) { + synth->viz.fft_output_buffer[i] /= max_amp_tso; + } - // Smooth out and smear the values - for (size_t i = 0; i < m; ++i) { - float smoothness = 4; - synth->viz.fft_smooth_buffer[i] += (synth->viz.fft_output_buffer[i] - synth->viz.fft_smooth_buffer[i])*smoothness*((float)1/30); - /* float smearness = 3; */ - /* ss_smear[i] += (synth->viz.fft_smooth_buffer[i] - ss_smear[i])*smearness*((float)1/30); */ - } - // Display the Bars - float cell_width = (float)width/m; - for (size_t i = 0; i < m; ++i) { - float t = synth->viz.fft_smooth_buffer[i]; - float saturation = 0.75f; - float value = 1.0f; - float hue = (float)i/m; - Color color = ColorFromHSV(hue*360, saturation, value); - Vector2 startPos = { - x + i*cell_width + cell_width/2, - y + height - height*2/3*t, - }; - Vector2 endPos = { - x + i*cell_width + cell_width/2, - y + height, - }; - float thick = cell_width/3*sqrtf(t); - DrawLineEx(startPos, endPos, thick, BLUE); - } + // Smooth out and smear the values + for (size_t i = 0; i < m; ++i) { + float smoothness = 4; + synth->viz.fft_smooth_buffer[i] += (synth->viz.fft_output_buffer[i] - synth->viz.fft_smooth_buffer[i])*smoothness*((float)1/30); + /* float smearness = 3; */ + /* ss_smear[i] += (synth->viz.fft_smooth_buffer[i] - ss_smear[i])*smearness*((float)1/30); */ + } + // Display the Bars + float cell_width = (float)width/m; + for (size_t i = 0; i < m; ++i) { + float t = synth->viz.fft_smooth_buffer[i]; + float saturation = 0.75f; + float value = 1.0f; + float hue = (float)i/m; + Color color = ColorFromHSV(hue*360, saturation, value); + Vector2 startPos = { + x + i*cell_width + cell_width/2, + y + height - height*2/3*t, + }; + Vector2 endPos = { + x + i*cell_width + cell_width/2, + y + height, + }; + float thick = cell_width/3*sqrtf(t); + DrawLineEx(startPos, endPos, thick, BLUE); + } - fftwf_free(output); + fftwf_free(output); } void @@ -424,38 +401,45 @@ draw_osc(synth_t * synth, int x, int y, int width, int height) void draw_adsr_graph(synth_t * synth, int x, int y, int width, int height) { + adsr_t adsr; - float total = synth->adsr.a + synth->adsr.d + synth->adsr.r + 0.3; /*sustain*/ + adsr.a = synth->cc_adsr_a.target; + adsr.peak = synth->cc_adsr_peak.target; + adsr.d = synth->cc_adsr_d.target; + adsr.s = synth->cc_adsr_s.target; + adsr.r = synth->cc_adsr_r.target; + + float total = synth->cc_adsr_a.target + synth->cc_adsr_d.target + synth->cc_adsr_r.target + 0.3; /*sustain*/ int total_samples = total * SAMPLE_RATE; - int a = synth->adsr.a/total * width; - int d = synth->adsr.d/total * width; + int a = synth->cc_adsr_a.target/total * width; + int d = synth->cc_adsr_d.target/total * width; int s = 0.3/total * width; - int r = synth->adsr.r/total * width; + int r = synth->cc_adsr_r.target/total * width; float adsr_graph[width]; for (int i = 0; i < width; i++) { float point = 0; if (i < a) { //draw atack - point = fix_adsr(&synth->adsr, + point = fix_adsr(&adsr, 1, // note On 0, // note Off (float)i/width * total_samples, 0); } else if (i < a + d) { // draw decay - point = fix_adsr(&synth->adsr, + point = fix_adsr(&adsr, 1, // note On 0, // note Off (float)i/width * total_samples, 0); } else if (i < a + d + s) { // draw sustain - point = fix_adsr(&synth->adsr, + point = fix_adsr(&adsr, 1, // note On 0, // note Off (float)i/width * total_samples, 0); } else if (i < a + d + s + r) { // draw release - point = fix_adsr(&synth->adsr, + point = fix_adsr(&adsr, 0, // note On 1, // note Off (float)i/width * total_samples, @@ -545,10 +529,30 @@ 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; void -draw_cc(cc_t * cc, int x, int y, int width, int height) { +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; + } + } + + if (IsMouseButtonDown(0) && flag == cc->name) { + Vector2 dx = GetMouseDelta(); + int x = 1; + if (IsKeyDown(KEY_LEFT_SHIFT)) { + x = 3; + } + 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; + } + int min = 110; int max = 110 + (360+70 - 110) * (cc->target) / (cc->max - cc->min); @@ -563,40 +567,136 @@ draw_cc(cc_t * cc, int x, int y, int width, int height) { } +float +map(float value, float start1, float end1, float start2, float end2) { + return start2 + (end2 - start2) * ((value - start1) / (end1 - start1)); +} + + +void +draw_cc_hbar(cc_t * cc, int x, int y, int width, int height) { + char buf1[32], buf2[32]; + + Vector2 p = GetMousePosition(); + + if (CheckCollisionPointRec(p, (Rectangle){x, y, width, height})) { + if (IsMouseButtonPressed(0)) { + flag = cc->name; + } + } + if (IsMouseButtonDown(0) && flag == cc->name) { + if (p.x < x) { + cc->target = cc->min; + } else if (p.x >= x + width) { + cc->target = cc->max; + } else { + cc->target = (cc->min + (cc->max - cc->min) * ((((p.x - x) * (float)1/width) - 0) / (1 - 0))); + } + } + if (IsMouseButtonReleased(0) && flag == cc->name) { + flag = 0; + } + + 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); + + + snprintf(buf1, sizeof buf1, "%.2f", cc->target); + snprintf(buf2, sizeof buf2, "%s", cc->name); + + DrawRectangleLines(x, y, width, height, WHITE); + DrawRectangle(x+1, y+1, fill_width, height-2, Fade(MAROON, 0.7f)); + + DrawText(buf2, x + width/2 - MeasureText(buf2, 10) / 2, y + height - 10 - 2, 10, WHITE); + DrawText(buf1, x + 3, y + height / 2 - 10 / 2, 10, WHITE); +} + +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; + + Vector2 p = GetMousePosition(); + + if (CheckCollisionPointRec(p, (Rectangle){x, y, width, height})) { + if (IsMouseButtonPressed(0)) { + flag = cc->name; + } + } + if (IsMouseButtonDown(0) && flag == cc->name) { + if (p.y < y) { + cc->target = cc->max; + } else if (p.y >= y + height) { + cc->target = cc->min; + } else { + cc->target = 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) { + flag = 0; + } + + snprintf(buf1, sizeof buf1, "%.2f", cc->target); + snprintf(buf2, sizeof buf2, "%s", cc->name); + + int fill_height = map(cc->target, cc->min, cc->max, 0, height - 2); + + DrawRectangleLines(x, y, width, height, WHITE); + DrawRectangle(x + 1, y + height - fill_height - 1, width - 2, fill_height, Fade(MAROON, 0.7f)); + + DrawText(buf2, x + width/2 - MeasureText(buf2, 10) / 2, y + height + 10, 10, WHITE); + DrawText(buf1, x + width/2 - MeasureText(buf1, 10) / 2, y - 10, 10, WHITE); +} + + +void +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_del_feedback, x, y + count++ * (height + offset), width, height); + draw_cc_hbar(&synth->cc_del_time, x, y + count++ * (height + offset), width, height); +} void rayrun(synth_t *synth){ PaTime current_time = 0; PaTime prev_time = 0; + osc_sound(0); + InitWindow(WIDTH, HEIGHT, "Raylib synth"); - Font f = LoadFont("/usr/share/fonts/TTF/DejaVuSans.ttf"); SetTargetFPS(60); // Set our game to run at 60 frames-per-second while (!WindowShouldClose()) { - keyboard(synth, synth->stream); mouse(synth, synth->stream); - int prec = 100000; // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(BLACK); - draw_cc(&synth->cc_adsr_s, 30, 250, 30, 30); + draw_cc_circle(&synth->cc_pitch, 30, 250, 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); - DrawLineBezier((Vector2){30, 250}, (Vector2){30, 300}, .3, BLUE); // GUI char buf[64]; - osc_sound(0); 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); set_sound_start(synth->wvt_pos*2048); set_sound_len(synth->wvt_pos*2048 + 2048); - draw_bars(synth, 33, 20, 256, 20, 4); - draw_text(synth, f, WIDTH / 2 - 108, 20); + 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 }, "")) { synth->x = 1; |