diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/midi.c | 29 | ||||
-rw-r--r-- | src/synth_engine.h | 3 | ||||
-rw-r--r-- | src/synth_engine_v2.c | 23 | ||||
-rw-r--r-- | src/synth_gui.c | 132 |
4 files changed, 164 insertions, 23 deletions
@@ -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); |