summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgramanas <anastasis.gramm2@gmail.com>2023-11-27 18:33:42 +0200
committergramanas <anastasis.gramm2@gmail.com>2023-11-27 18:33:42 +0200
commit4f7de09c753ece6f2099512522d489b0104a59a8 (patch)
treeb9983c044bee6f553b90b914bf63ee5c1aa2aaf0
parentb0128e30840dff1e7db7bcfd69e6fa4f09ed5fbe (diff)
downloadsynth-project-4f7de09c753ece6f2099512522d489b0104a59a8.tar.gz
synth-project-4f7de09c753ece6f2099512522d489b0104a59a8.tar.bz2
synth-project-4f7de09c753ece6f2099512522d489b0104a59a8.zip
cc adsr and ui
-rw-r--r--src/midi.c29
-rw-r--r--src/synth_engine.h3
-rw-r--r--src/synth_engine_v2.c23
-rw-r--r--src/synth_gui.c132
4 files changed, 164 insertions, 23 deletions
diff --git a/src/midi.c b/src/midi.c
index c65a298..11029b0 100644
--- a/src/midi.c
+++ b/src/midi.c
@@ -44,22 +44,26 @@ void midi_decode(uint32_t msg, synth_t * synth) {
printf("Aftertouch: channel=%d, note=%d, pressure=%d\n", channel, data1, data2);
break;
case 0x0B:
- // printf("Control Change: channel=%d, controller=%d, value=%d\n", channel, data1, data2);
+ printf("Control Change: channel=%d, controller=%d, value=%d\n", channel, data1, data2);
int x = data2 < 64 ? 1 : -1;
switch (data1) {
case 0:
- synth->adsr.a = synth->adsr.a + (x * 0.01);
+ cc_step(&synth->cc_adsr_a, x);
+ //synth->adsr.a = synth->adsr.a + (x * 0.01);
//synth->freq_offset = synth->freq_offset + (x*5);
//cc_step(&synth->cc_cutoff, x);
break;
case 1:
- synth->adsr.d = synth->adsr.d + (x * 0.01);
+ cc_step(&synth->cc_adsr_d, x);
+ //synth->adsr.d = synth->adsr.d + (x * 0.01);
break;
case 2:
- synth->adsr.s = synth->adsr.s + (x * 0.01);
+ cc_step(&synth->cc_adsr_s, x);
+ //synth->adsr.s = synth->adsr.s + (x * 0.01);
break;
case 3:
- synth->adsr.r = synth->adsr.r + (x * 0.01);
+ cc_step(&synth->cc_adsr_r, x);
+ //synth->adsr.r = synth->adsr.r + (x * 0.01);
break;
case 4:
cc_step(&synth->cc_cutoff, x);
@@ -69,18 +73,25 @@ void midi_decode(uint32_t msg, synth_t * synth) {
cc_step(&synth->cc_resonance, x);
break;
case 6:
- cc_step(&synth->cc_pitch, x);
+ //cc_step(&synth->cc_pitch, x);
+ cc_step(&synth->cc_lfo_freq, x);
//synth->lfo.freq = synth->lfo.freq + (x * 0.1);
break;
case 7:
- cc_reset(&synth->cc_pitch);
- synth->lfo.amp = synth->lfo.amp + (x * 0.002);
+ //cc_reset(&synth->cc_pitch);
+ cc_step(&synth->cc_lfo_amp, x);
+ //synth->lfo.amp = synth->lfo.amp + (x * 0.002);
break;
+ case 8:
+ //cc_reset(&synth->cc_pitch);
+ synth->wvt_pos = data2;
+ //synth->lfo.amp = synth->lfo.amp + (x * 0.002);
break;
case 28:
- synth->filter = x - 1;
+ if (synth->geni > 0) synth->geni--;
break;
case 29:
+ if (synth->geni < 6) synth->geni++;
break;
default:
}
diff --git a/src/synth_engine.h b/src/synth_engine.h
index 34f90b2..674c287 100644
--- a/src/synth_engine.h
+++ b/src/synth_engine.h
@@ -44,6 +44,7 @@ typedef struct {
int spectrum_enabled;
int wave_enabled;
int adsr_enabled;
+ int adsr_graph_enabled;
int osc_enabled;
int freeze;
int rate_divider;
@@ -66,6 +67,8 @@ typedef struct {
typedef struct {
PaStream *stream;
+ int wvt_pos;
+
cc_t * ccs[128];
int cci;
diff --git a/src/synth_engine_v2.c b/src/synth_engine_v2.c
index a3c6efa..9beae33 100644
--- a/src/synth_engine_v2.c
+++ b/src/synth_engine_v2.c
@@ -177,7 +177,11 @@ make_sample(synth_t * synth, unsigned int sample_rate, int frame)
rms = sqrt(rms / (float)synth->midi_active_n);
//float max = get_max_sample(synth, 20);
-
+ synth->adsr.a = CC_GET(adsr_a);
+ synth->adsr.d = CC_GET(adsr_d);
+ synth->adsr.s = CC_GET(adsr_s);
+ synth->adsr.r = CC_GET(adsr_r);
+
for (int i = 0; i < synth->midi_active_n; i++) {
note = synth->midi_active[i];
float adsr = fix_adsr(&synth->adsr,
@@ -240,7 +244,6 @@ get_frame(void *outputBuffer, synth_t *synth, int i)
float *out = (float*)outputBuffer + 2 * i;
float s = 0.0f;
-
if (!notes_active(synth)) {
synth->active = 0;
}
@@ -338,15 +341,16 @@ init_synth(void)
if (!synth) return NULL;
synth->cci = 0;
- CC(synth->cc_cutoff, "cutoff", 10, 22000, 30, 5000);
+ // CC(SYNTH, NAME, MIN, MAX, STEP, DEF)
+ CC(synth->cc_cutoff, "cutoff", 10, 22000, 30, 5000);
CC(synth->cc_resonance, "resonance", 1, 10, .02, 1);
CC(synth->cc_lfo_freq, "lfo_freq", 1, 1000, 2, 1);
CC(synth->cc_lfo_amp, "lfo_amp", 0, 1, .01f, 0);
CC(synth->cc_pitch, "pitch", -3, 4, 0.01f, 1);
- CC(synth->cc_adsr_a, "attack", 0, 3, 0.05f, 0.00);
- CC(synth->cc_adsr_d, "decay", 0, 2, 0.05f, 0.3);
- CC(synth->cc_adsr_s, "sustain", 0, 1.0f, 0.05f, 0.7f);
- CC(synth->cc_adsr_r, "release", 0, 5, 0.05f, 0.2f);
+ CC(synth->cc_adsr_a, "attack", 0, 3, 0.01f, 0.00);
+ CC(synth->cc_adsr_d, "decay", 0, 2, 0.01f, 0.3);
+ CC(synth->cc_adsr_s, "sustain", 0, 1.0f, 0.01f, 0.7f);
+ CC(synth->cc_adsr_r, "release", 0, 5, 0.01f, 0.2f);
synth->modi = 0;
@@ -424,12 +428,15 @@ init_synth(void)
synth->viz.fft_output_buffer = (float *)calloc(sizeof(float), RING_SIZE * 8);
synth->viz.fft_smooth_buffer = (float *)calloc(sizeof(float), RING_SIZE * 8);
- synth->viz.spectrum_enabled = 1;
+ synth->viz.spectrum_enabled = 0;
synth->viz.wave_enabled = 0;
synth->viz.adsr_enabled = 0;
+ synth->viz.adsr_graph_enabled = 1;
synth->viz.osc_enabled = 0;
synth->viz.freeze = 0;
synth->viz.tmp_index = 0;
+
+ synth->wvt_pos = 0;
}
void
diff --git a/src/synth_gui.c b/src/synth_gui.c
index dd4c75b..47a9125 100644
--- a/src/synth_gui.c
+++ b/src/synth_gui.c
@@ -24,7 +24,7 @@ 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)
{
@@ -47,6 +47,29 @@ mouse(synth_t *synth, PaStream *stream)
cc_step(&synth->cc_pitch, x);
}
}
+
+ 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;
+ }
}
void
@@ -399,6 +422,77 @@ 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)
+{
+
+ float total = synth->adsr.a + synth->adsr.d + synth->adsr.r + 0.3; /*sustain*/
+ int total_samples = total * SAMPLE_RATE;
+ int a = synth->adsr.a/total * width;
+ int d = synth->adsr.d/total * width;
+ int s = 0.3/total * width;
+ int r = synth->adsr.r/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,
+ 1, // note On
+ 0, // note Off
+ (float)i/width * total_samples,
+ 0);
+ } else if (i < a + d) { // draw decay
+ point = fix_adsr(&synth->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,
+ 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,
+ 0, // note On
+ 1, // note Off
+ (float)i/width * total_samples,
+ (float)(a + d + s)/width * total_samples);
+ }
+ adsr_graph[i] = point * height;
+ }
+ adsr_graph[0] = adsr_graph[1]; // remove 1st 0
+
+ for (int i = 0; i < width; i++) {
+ 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;
+ 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 - adsr_graph[j], 5, RED);
+ } else if (j < a + d + s - 1) {
+ DrawCircle(j + x , y + height - adsr_graph[j], 5, RED);
+ } else if (j > a + d + s - 1) {
+ DrawCircle(a + d + s + x , y + height - adsr_graph[a + d + s], 5, RED);
+ }
+ } 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 - adsr_graph[id], 5, RED);
+ }
+ }
+}
+
+void
draw_signals(synth_t * synth, int x, int y, int width, int height)
{
DrawRectangleLines(x, y, width, height, WHITE);
@@ -445,14 +539,36 @@ draw_signals(synth_t * synth, int x, int y, int width, int height)
if (synth->viz.osc_enabled) {
draw_osc(synth, x + width - 80, y + height - 80, 80, 80);
}
+
+ synth->viz.adsr_graph_enabled = GuiCheckBox((Rectangle){ x + width - 270, y, 16, 16 }, "adsr graph", synth->viz.adsr_graph_enabled);
+ if (synth->viz.adsr_graph_enabled) {
+ draw_adsr_graph(synth, x + 20, y + 20, width - 40, height - 40);
+ }
}
void
+draw_cc(cc_t * cc, int x, int y, int width, int height) {
+ //DrawRectangleLines(x, y, width, height, WHITE);
+
+ int min = 110;
+ int max = 110 + (360+70 - 110) * (cc->target) / (cc->max - cc->min);
+ DrawRing((Vector2){x + width/2, y + height/2}, width / 2 - 6, width / 2, min, max, 0, Fade(MAROON, 0.7f));
+ DrawCircle(x + width/2, y + height/2, width / 2 - 5, BLACK); // Draw circle sector outline
+
+ char buf[32];
+ snprintf(buf, sizeof buf, "%0.2f", cc->target);
+ DrawText(buf, x + width/2 - MeasureText(buf, 10) / 2, y + height/2 - 10 / 2, 10, GRAY);
+ snprintf(buf, sizeof buf, "%s", cc->name);
+ DrawText(buf, x + width/2 - MeasureText(buf, 10) / 2, y + height - 10 / 2, 10, GRAY);
+
+}
+
+
+void
rayrun(synth_t *synth){
PaTime current_time = 0;
PaTime prev_time = 0;
- int len;
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
@@ -467,13 +583,17 @@ rayrun(synth_t *synth){
BeginDrawing();
ClearBackground(BLACK);
+ draw_cc(&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", len);
- len = GuiSlider((Rectangle){WIDTH / 2 - 108, 150 + 42 + 42, 216, 24 }, "", buf, len , 0, 157);
- set_sound_start(len*2048);
- set_sound_len(len*2048 + 2048);
+ 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);