diff options
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/adsr.c | 47 | ||||
-rw-r--r-- | src/adsr.h | 15 | ||||
-rw-r--r-- | src/synth_engine.c | 15 | ||||
-rw-r--r-- | src/synth_gui.c | 29 |
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(); //---------------------------------------------------------------------------------- |