diff options
Diffstat (limited to 'src/synth_gui.c')
-rw-r--r-- | src/synth_gui.c | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/src/synth_gui.c b/src/synth_gui.c index 169d057..da90f52 100644 --- a/src/synth_gui.c +++ b/src/synth_gui.c @@ -482,6 +482,85 @@ draw_adsr_graph(synth_t * synth, int x, int y, int width, int height) } void +draw_filter_adsr_graph(synth_t * synth, int x, int y, int width, int height) +{ + adsr_t f_adsr; + + f_adsr.a = synth->cc_f_adsr_a.target; + f_adsr.peak = synth->cc_f_adsr_peak.target; + f_adsr.d = synth->cc_f_adsr_d.target; + f_adsr.s = synth->cc_f_adsr_s.target; + f_adsr.r = synth->cc_f_adsr_r.target; + + float total = synth->cc_f_adsr_a.target + synth->cc_f_adsr_d.target + synth->cc_f_adsr_r.target + 0.3; /*sustain*/ + int total_samples = total * SAMPLE_RATE; + int a = synth->cc_f_adsr_a.target/total * width; + int d = synth->cc_f_adsr_d.target/total * width; + int s = 0.3/total * width; + int r = synth->cc_f_adsr_r.target/total * width; + + float f_adsr_graph[width]; + for (int i = 0; i < width; i++) { + float point = 0; + + if (i < a) { //draw attack + point = fix_adsr(&f_adsr, + 1, // note On + 0, // note Off + (float)i/width * total_samples, + 0); + } else if (i < a + d) { // draw decay + point = fix_adsr(&f_adsr, + 1, // note On + 0, // note Off + (float)i/width * total_samples, + 0); + } else if (i < a + d + s) { // draw sustain + point = fix_adsr(&f_adsr, + 1, // note On + 0, // note Off + (float)i/width * total_samples, + 0); + } else if (r && i < a + d + s + r) { // draw release + point = fix_adsr(&f_adsr, + 0, // note On + 1, // note Off + (float)i/width * total_samples, + (float)(a + d + s)/width * total_samples); + } + f_adsr_graph[i] = point * height; + } + f_adsr_graph[0] = f_adsr_graph[1]; // remove 1st 0 + + // Draw filter ADSR in blue to distinguish from amplitude ADSR + for (int i = 0; i < width; i++) { + DrawPixel(i + x , y + height - f_adsr_graph[i], BLUE); + } + + // Draw current position indicators for active notes + for (int i = 0; i < synth->midi_active_n; i++) { + midi_note_t * note = synth->midi_active[i]; + int elapsed_samples = note->elapsed; + float elapsed_secs = (float)elapsed_samples / SAMPLE_RATE; + int j = elapsed_secs / total * width; + + if (note->noteOff == 0) { + if (j < a + d) { + DrawCircle(j + x , y + height - f_adsr_graph[j], 3, BLUE); + } else if (j < a + d + s - 1) { + DrawCircle(j + x , y + height - f_adsr_graph[j], 3, BLUE); + } else if (j > a + d + s - 1) { + DrawCircle(a + d + s + x , y + height - f_adsr_graph[a + d + s], 3, BLUE); + } + } else { // note off + int id = a + d + s + (float)(note->elapsed - note->noteOffSample)/SAMPLE_RATE / total * width; + if (id > 0 && id < width) + DrawCircle(id + x , y + height - f_adsr_graph[id], 3, BLUE); + } + } +} + +void draw_signals(synth_t * synth, int x, int y, int width, int height) { DrawRectangleLines(x, y, width, height, WHITE); @@ -533,6 +612,11 @@ draw_signals(synth_t * synth, int x, int y, int width, int height) if (synth->viz.adsr_graph_enabled) { draw_adsr_graph(synth, x + 20, y + 20, width - 40, height - 40); } + + synth->viz.filter_adsr_graph_enabled = GuiCheckBox((Rectangle){ x + width - 370, y, 16, 16 }, "filter adsr", synth->viz.filter_adsr_graph_enabled); + if (synth->viz.filter_adsr_graph_enabled) { + draw_filter_adsr_graph(synth, x + 20, y + 20, width - 40, height - 40); + } } char * flag = NULL; |