summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/Makefile.am2
-rw-r--r--src/adsr.c47
-rw-r--r--src/adsr.h15
-rw-r--r--src/synth_engine.c15
-rw-r--r--src/synth_gui.c29
5 files changed, 84 insertions, 24 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index c775183..0b69262 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -31,7 +31,7 @@ common_sources = adsr.c \
AM_CFLAGS = -O3 -march=native -fno-math-errno -funroll-loops -flto -pthread
synth_SOURCES = synth.c $(common_sources)
-synth_LDADD = -lportaudio -lrt -lm -lasound -lraylib -lportmidi
+synth_LDADD = -lportaudio -lrt -lm -lasound -lraylib -lportmidi -ljack
#cookbook_SOURCES = cookbook.c $(common_sources)
#cookbook_SOURCES = cookbook.c $(common_sources)
#cook_SOURCES = cook.c $(common_sources)
diff --git a/src/adsr.c b/src/adsr.c
new file mode 100644
index 0000000..8ef2ba9
--- /dev/null
+++ b/src/adsr.c
@@ -0,0 +1,47 @@
+#include "adsr.h"
+#include "synth_engine.h"
+#include "synth_math.h"
+
+float
+adsr_amplitude(adsr_t *adsr, float noteOn, float noteOff, unsigned long long elapsed)
+{
+ float mod = 0.0;
+ float release_amplitude = 0.0;
+
+ float lifetime = elapsed / (float)SAMPLE_RATE;
+ //float time_active = (noteOn + lifetime) - noteOff;
+ float time_active = noteOn - noteOff + lifetime;
+
+ if (noteOn != 0 && noteOff == 0) {
+ if (lifetime < adsr->a)
+ mod = (lifetime / adsr->a)*(lifetime / adsr->a) * adsr->peak;
+
+ if (lifetime >= adsr->a && lifetime <= ( adsr->a + adsr->d))
+ mod = ((lifetime - adsr->a) / adsr->d) * (adsr->s - adsr->peak) + adsr->peak;
+
+ if (lifetime > (adsr->a + adsr->d))
+ mod = adsr->s;
+ }
+ else { // Note is off
+ if (lifetime < adsr->a)
+ release_amplitude = (lifetime / adsr->a)*(lifetime / adsr->a) * adsr->peak;
+
+ if (lifetime >= adsr->a && lifetime <= (adsr->a + adsr->d))
+ release_amplitude = ((lifetime - adsr->a) / adsr->d) * (adsr->s - adsr->peak) + adsr->peak;
+
+ if (lifetime > (adsr->a + adsr->d))
+ release_amplitude = adsr->s;
+
+ mod = (time_active / adsr->r) * (0.0 - release_amplitude) + release_amplitude;
+
+ if (adsr->r < 0) {
+ mod = adsr->s;
+ }
+
+ }
+ // Amplitude should not be negative
+ if (mod <= 0.000)
+ mod = 0.0;
+
+ return clamp(mod);
+}
diff --git a/src/adsr.h b/src/adsr.h
new file mode 100644
index 0000000..713c95f
--- /dev/null
+++ b/src/adsr.h
@@ -0,0 +1,15 @@
+#ifndef ADSR_H
+#define ADSR_H
+
+typedef struct adsr_t {
+ float a;
+ float peak;
+ float d;
+ float s;
+ float r;
+ unsigned long long elapsed;
+} adsr_t;
+
+float adsr_amplitude(adsr_t *adsr, float noteOn, float noteOff, unsigned long long elapsed);
+
+#endif /* ADSR_H */
diff --git a/src/synth_engine.c b/src/synth_engine.c
index 6710ff6..8587001 100644
--- a/src/synth_engine.c
+++ b/src/synth_engine.c
@@ -138,8 +138,11 @@ make_sample(unsigned long long phase, void *synthData, unsigned int sample_rate,
continue;
sample += 0.2 * rms
- * adsr_amplitude(&synth->adsr, (float)synth->midi_note[i].noteOn, (float)synth->midi_note[i].noteOff, (float)synth->midi_note[i].elapsed)
- * synth->gen[synth->geni](synth->midi_note[i].freq + synth->midi_note[i].freq * synth->freq_offset, synth->midi_note[i].elapsed, synth->x, sample_rate);
+ * adsr_amplitude(&synth->adsr,
+ synth->midi_note[i].noteOn,
+ synth->midi_note[i].noteOff,
+ synth->midi_note[i].elapsed)
+ * synth->gen[synth->geni](synth->midi_note[i].freq + synth->freq_offset, synth->midi_note[i].elapsed, synth->x, sample_rate);
}
/* filter */
@@ -204,7 +207,6 @@ sound_gen(const void *inputBuffer, void *outputBuffer,
}
if (!notes_active(synth)) {
- //if (adsr_amplitude(synth, synth->adsr.elapsed, synth->n.noteOn, synth->n.noteOff) == 0 && synth->n.noteOff != 0) {
synth->active = 0;
*out++ = 0.0f;
*out++ = 0.0f;
@@ -219,11 +221,6 @@ sound_gen(const void *inputBuffer, void *outputBuffer,
synth->lfo.elapsed++;
synth->adsr.elapsed++;
synth->n.elapsed++;
- /* if (!synth->multi) { */
- /* if (synth->n.elapsed >= (1.0 / synth->n.freq) * SAMPLE_RATE) synth->n.elapsed = 0; */
- /* } else { */
-
- /* } */
for (int i = 0; i < MIDI_NOTES; i++) {
if (!synth->midi_note[i].active)
@@ -318,7 +315,7 @@ init_synth(synth_t * synth)
PaStreamParameters outputParameters;
- outputParameters.device = i; Pa_GetDefaultOutputDevice(); /* default output device */
+ outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
printf("-------\nSelected device: %s\n-------\n", Pa_GetDeviceInfo(outputParameters.device)->name);
outputParameters.channelCount = 2; /* stereo output */
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */
diff --git a/src/synth_gui.c b/src/synth_gui.c
index 2405d57..df219ba 100644
--- a/src/synth_gui.c
+++ b/src/synth_gui.c
@@ -100,22 +100,23 @@ draw_signals(synth_t * synth, int x, int y, int width, int height)
for (int i = x; i < WIDTH - x; i++) {
DrawCircle(i , y + height / 2 + floor(250 * synth->viz.wave[i - x]), point_radius, MAGENTA);
}
- if (synth->multi) {
- for (int i = x; i < WIDTH - x; i++) {
- //DrawCircle(i , y + height / 2 + floor(50 * make_sample(i - x, synth, SAMPLE_RATE / synth->viz.sample_rate_divider, 1)), point_radius, RED);
- }
- } else {
- for (int i = x; i < WIDTH - x; i++) {
- //DrawCircle(i , y + height / 2 + floor(50 * make_sample((i - x) % period, synth, SAMPLE_RATE / synth->viz.sample_rate_divider, 1)), point_radius, RED);
- }
- }
for (int i = x; i < WIDTH - x; i++) {
- //DrawCircle(i , y + height - 1+ floor((WIDTH / 24) * - adsr_amplitude(synth, synth->adsr.elapsed, synth->n.noteOn, synth->n.noteOff)), point_radius, GREEN);
+ for (int j = 0; j < MIDI_NOTES; j++) {
+ if (!synth->midi_note[j].active)
+ continue;
+
+ DrawCircle(i , y + height - 1 + 4.5*floor((WIDTH / 24) * - adsr_amplitude(&synth->adsr, synth->midi_note[j].noteOn, synth->midi_note[j].noteOff, synth->midi_note[j].elapsed)), point_radius, GREEN);
+ }
}
float adsr_duration = synth->adsr.a + synth->adsr.d + (synth->adsr.a + synth->adsr.d + synth->adsr.r) / 3.0 + synth->adsr.r;
for (int i = x; i < WIDTH - x; i++) {
- //DrawCircle(i , y + height - 1 + floor((WIDTH / 24) * - adsr_amplitude(synth, (i - x) * (adsr_duration * SAMPLE_RATE) / WIDTH, synth->n.noteOn, synth->n.noteOff)), point_radius, BLUE);
+ for (int j = 0; j < MIDI_NOTES; j++) {
+ if (!synth->midi_note[j].active)
+ continue;
+
+ DrawCircle(i , y + height - 1 + 4.5*floor((WIDTH / 24) * - adsr_amplitude(&synth->adsr, synth->midi_note[j].noteOn, synth->midi_note[j].noteOff, (i - x) * (adsr_duration * SAMPLE_RATE) / WIDTH)), point_radius, BLUE);
+ }
}
}
@@ -181,9 +182,9 @@ rayrun(void *synthData)
draw_signals(synth, 20, 390, WIDTH - 2*20, 200);
DrawText("THE SYNTH!!!!!!!!!!!!!!!!!!1", WIDTH / 2 - 100, 50, 20, LIGHTGRAY);
- DrawText("KEYBOARD: Q .. ] TOGGLE MULTI: ENTER", WIDTH / 2 -300, HEIGHT - 20 - 50, 20, LIGHTGRAY);
- snprintf(buf, sizeof buf, "%f", synth->viz.wave[0]);
- DrawText(buf, WIDTH / 2 -300, HEIGHT - 40 - 50, 20, LIGHTGRAY);
+ DrawText("KEYBOARD: Q .. ] TOGGLE MULTI: ENTER", WIDTH / 2 -300, HEIGHT - 300 - 50, 20, LIGHTGRAY);
+ snprintf(buf, sizeof buf, "%f stream time: %f", synth->viz.wave[0], Pa_GetStreamTime(synth->stream));
+ DrawText(buf, WIDTH / 2 -300, HEIGHT - 300, 20, LIGHTGRAY);
EndDrawing();
//----------------------------------------------------------------------------------