From f170fb058a07175e6e753f2a6d20283dc7200a88 Mon Sep 17 00:00:00 2001 From: gramanas Date: Wed, 28 Jun 2023 22:41:03 +0300 Subject: Add wavetable synthesis --- src/Makefile.am | 4 +++- src/midi.c | 3 ++- src/synth_engine.c | 62 ++++++++++++++++++++++++++++++------------------------ src/synth_engine.h | 3 ++- src/synth_gui.c | 23 ++++++++++---------- 5 files changed, 52 insertions(+), 43 deletions(-) (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am index ab17d84..0ef06f4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -20,7 +20,9 @@ common_sources = adsr.c \ synth_engine.h \ synth_gui.c \ synth_gui.h \ - synth_math.h + synth_math.h \ + wavetable.c \ + wavetable.h # -fwhole-program allows cross-file inlining, but only works when you put all # the source files on one gcc command-line. -flto is another way to get the diff --git a/src/midi.c b/src/midi.c index d9955d2..8452bcc 100644 --- a/src/midi.c +++ b/src/midi.c @@ -27,6 +27,7 @@ void midi_decode(uint32_t msg, synth_t * synth) { synth->midi_note[data1].velocity = (float)data2 / 127.0; synth->midi_note[data1].elapsed = 0; synth->midi_note[data1].active = 1; + synth->active = 1; break; case 0x0A: printf("Aftertouch: channel=%d, note=%d, pressure=%d\n", channel, data1, data2); @@ -144,7 +145,7 @@ init_midi(midi_t *m, synth_t *synth) void terminate_midi(midi_t *m) { - Pm_Close(m->stream); Pt_Stop(); + Pm_Close(m->stream); Pm_Terminate(); } diff --git a/src/synth_engine.c b/src/synth_engine.c index a4d3d17..9dbf2c5 100644 --- a/src/synth_engine.c +++ b/src/synth_engine.c @@ -4,6 +4,7 @@ #include "filter.h" #include "control.h" #include "sound.h" +#include "wavetable.h" #include @@ -67,47 +68,50 @@ gen110(float f, unsigned long long phase, float x, unsigned int sample_rate) } float -gen0(float f, unsigned long long phase, float x, unsigned int sample_rate) +gen0(float f, midi_note_t * midi_note, float x, unsigned int sample_rate) { - return sin_sample(1, f, phase, sample_rate); - //return chirp(phase, f); - /* return sqr_sample(0.1, f, 0.3, phase, sample_rate) */ - /* + sqr_sample(0.1, f * 3.0 / 2.0 , 0.5, phase, sample_rate) */ - /* + saw_sample(0.3, f, phase, sample_rate) */ - /* + sin_sample(0.1, f, phase, sample_rate) */ - /* + sin_sample(0.1, f * 5, phase, sample_rate) */ - /* /\* + sin_sample(0.1, freq * 50 * 1021, phase, sample_rate) *\/ */ - /* /\* + sin_sample(0.1, freq * 50 * 3531021, phase, sample_rate) *\/ */ - /* + sin_sample(0.1, f * 7, phase, sample_rate); */ + return sin_sample(1, f, midi_note->elapsed, sample_rate); + //return chirp(midi_note->elapsed, f); + /* return sqr_sample(0.1, f, 0.3, midi_note->elapsed, sample_rate) */ + /* + sqr_sample(0.1, f * 3.0 / 2.0 , 0.5, midi_note->elapsed, sample_rate) */ + /* + saw_sample(0.3, f, midi_note->elapsed, sample_rate) */ + /* + sin_sample(0.1, f, midi_note->elapsed, sample_rate) */ + /* + sin_sample(0.1, f * 5, midi_note->elapsed, sample_rate) */ + /* /\* + sin_sample(0.1, freq * 50 * 1021, midi_note->elapsed, sample_rate) *\/ */ + /* /\* + sin_sample(0.1, freq * 50 * 3531021, midi_note->elapsed, sample_rate) *\/ */ + /* + sin_sample(0.1, f * 7, midi_note->elapsed, sample_rate); */ } float -gen1(float f, unsigned long long phase, float x, unsigned int sample_rate) +gen1(float f, midi_note_t * midi_note, float x, unsigned int sample_rate) { - //return saw_sample(1, f, phase, sample_rate); - return sawX_sample(0.5, f, 5, phase, sample_rate) - + saw_sample(0.3, 2 * f / 5, phase, sample_rate) - + sin_sample(0.2, f * 5.0 / 7.0 , phase, sample_rate); + //return saw_sample(1, f, midi_note->elapsed, sample_rate); + return sawX_sample(0.5, f, 5, midi_note->elapsed, sample_rate) + + saw_sample(0.3, 2 * f / 5, midi_note->elapsed, sample_rate) + + sin_sample(0.2, f * 5.0 / 7.0 , midi_note->elapsed, sample_rate); } float -gen2(float f, unsigned long long phase, float x, unsigned int sample_rate) +gen2(float f, midi_note_t * midi_note, float x, unsigned int sample_rate) { - /* return sin_sample(0.5, f * sqrt(2) , phase, sample_rate) */ - /* + sin_sample(0.5, f, phase, sample_rate); */ + /* return sin_sample(0.5, f * sqrt(2) , midi_note->elapsed, sample_rate) */ + /* + sin_sample(0.5, f, midi_note->elapsed, sample_rate); */ - return sawX_sample(1, f, 15, phase, sample_rate); + return sawX_sample(1, f, 15, midi_note->elapsed, sample_rate); } float -gen3(float f, unsigned long long phase, float x, unsigned int sample_rate) +gen3(float f, midi_note_t * midi_note, float x, unsigned int sample_rate) { - return sqr_sample(1, f, .5, phase, sample_rate); - /* return sawX_sample(0.7, f, 5, phase, sample_rate) */ - /* + sin_sample(0.3, 4.0/17.0*f, phase, sample_rate); */ - /* return saw_sample(0.5, f * (1 + sqrt(5)) / 2, phase, sample_rate) */ - /* + sin_sample(0.3, f * x, phase, sample_rate) */ - /* + sqr_sample(0.2, f * x, 0.2 * x * x, phase, sample_rate); */ + //return sqr_sample(1, f, .5, midi_note->elapsed, sample_rate); + + return wvt_next(wvt_saw, f, sample_rate, &midi_note->wvt_index); + + /* return sawX_sample(0.7, f, 5, midi_note->elapsed, sample_rate) */ + /* + sin_sample(0.3, 4.0/17.0*f, midi_note->elapsed, sample_rate); */ + /* return saw_sample(0.5, f * (1 + sqrt(5)) / 2, midi_note->elapsed, sample_rate) */ + /* + sin_sample(0.3, f * x, midi_note->elapsed, sample_rate) */ + /* + sqr_sample(0.2, f * x, 0.2 * x * x, midi_note->elapsed, sample_rate); */ } float @@ -133,6 +137,7 @@ notes_active(synth_t *synth) synth->midi_note[i].channel = -1; synth->midi_note[i].noteOn = -1; synth->midi_note[i].noteOff = -1; + synth->midi_note[i].wvt_index = 0; synth->midi_note[i].velocity = -1; synth->midi_note[i].elapsed = -1; synth->midi_note[i].active = 0; @@ -178,7 +183,7 @@ make_sample(void *synthData, unsigned int sample_rate, int frame) float targ_freq_with_repitch = synth->midi_note[i].freq * cc_iget(&synth->cc_pitch, frame, FRAMES_PER_BUFFER); float synth_sample = synth->gen[synth->geni](targ_freq, - synth->midi_note[i].elapsed, + &synth->midi_note[i], synth->x, sample_rate); @@ -460,6 +465,7 @@ init_synth(synth_t * synth) synth->fff2 = create_bw_band_stop_filter(8, SAMPLE_RATE, 15000, 22000); init_sound(synth, sound_gen); + wvt_init(); } void diff --git a/src/synth_engine.h b/src/synth_engine.h index e2e91fd..a1f3d4a 100644 --- a/src/synth_engine.h +++ b/src/synth_engine.h @@ -38,6 +38,7 @@ typedef struct midi_note_t { PaTime noteOn; PaTime noteOff; float velocity; // normalized + size_t wvt_index; unsigned long long elapsed; adsr_t * adsr; int active; @@ -80,7 +81,7 @@ typedef struct { int modifiers[16]; int modi; - float (*gen[4]) (float freq, unsigned long long phase, float x, unsigned int sample_rate); + float (*gen[4]) (float freq, midi_note_t * midi_note, float x, unsigned int sample_rate); int geni; float cutoff; diff --git a/src/synth_gui.c b/src/synth_gui.c index d39995b..ee4ae05 100644 --- a/src/synth_gui.c +++ b/src/synth_gui.c @@ -14,18 +14,17 @@ keyboard(void *synthData, PaStream *stream) for (int i = 0; keys[i]; i++) { if (IsKeyPressed(keys[i])) { - note = notes[i % 12][(synth->octave + (i / 12)) % 8]; - if (note) { - //printf("Note On : %s[%d] %fHz\n", int_to_note(i % 12), (synth->octave + (i / 12)) % 8, note); - synth->midi_note[i].freq = 16.35160 * pow(2, (synth->octave + i / 12.0)); //notes[i % 12][(synth->octave + (i / 12)) % 8]; - //synth->midi_note[i].freq = notes[i % 12][(synth->octave + (i / 12)) % 8]; - synth->midi_note[i].channel = -1; - synth->midi_note[i].noteOn = Pa_GetStreamTime(synth->stream); - synth->midi_note[i].noteOff = 0; - synth->midi_note[i].velocity = 1.0; - synth->midi_note[i].elapsed = 0; - synth->midi_note[i].active = 1; - } + //printf("Note On : %s[%d] %fHz\n", int_to_note(i % 12), (synth->octave + (i / 12)) % 8, note); + synth->midi_note[i].freq = 16.35160 * pow(2, (synth->octave + i / 12.0)); + //synth->midi_note[i].freq = notes[i % 12][(synth->octave + (i / 12)) % 8]; + synth->midi_note[i].channel = -1; + synth->midi_note[i].noteOn = Pa_GetStreamTime(synth->stream); + synth->midi_note[i].noteOff = 0; + synth->midi_note[i].velocity = 1.0; + synth->midi_note[i].elapsed = 0; + synth->midi_note[i].active = 1; + //synth->adsr.elapsed = 0; + synth->active = 1; } } for (int i = 0; keys[i]; i++) { -- cgit v1.2.3