From e919ad41b01595d2cd8fb0771bd3542817ec1058 Mon Sep 17 00:00:00 2001 From: gramanas Date: Thu, 20 Apr 2023 18:52:53 +0300 Subject: Midi also plays notes now --- src/midi.c | 20 ++++++++++++--- src/synth.c | 73 +++--------------------------------------------------- src/synth_engine.c | 46 ++++++++++++++++++++++++++++++++++ src/synth_engine.h | 2 ++ src/synth_gui.c | 6 ++--- src/synth_gui.h | 2 +- 6 files changed, 73 insertions(+), 76 deletions(-) (limited to 'src') diff --git a/src/midi.c b/src/midi.c index 46608cb..e1797c8 100644 --- a/src/midi.c +++ b/src/midi.c @@ -1,8 +1,9 @@ #include "midi.h" +#include "notes.h" #include -void midi_decode(uint32_t msg) { +void midi_decode(uint32_t msg, synth_t * synth) { // printf("MIDI message: 0x%X\n", msg); uint8_t status = msg; uint8_t data1 = (msg >> 8) & 0xFF; @@ -13,9 +14,21 @@ void midi_decode(uint32_t msg) { switch (message) { case 0x08: printf("Note Off: channel=%d, note=%d, velocity=%d\n", channel, data1, data2); + if (synth->n.key == data1) { + synth->n.noteOff = Pa_GetStreamTime(synth->stream); + } break; case 0x09: printf("Note On: channel=%d, note=%d, velocity=%d\n", channel, data1, data2); + synth->n.key = data1; + synth->n.freq = notes[data1 % 12][(data1 / 12) % 8]; + synth->n.noteOn = Pa_GetStreamTime(synth->stream); + synth->n.noteOff = 0; + synth->n.elapsed = 0; + synth->adsr.elapsed = 0; + synth->active = 1; + synth->gain = data2 / 127.0; + break; case 0x0A: printf("Aftertouch: channel=%d, note=%d, pressure=%d\n", channel, data1, data2); @@ -51,7 +64,7 @@ midiCallback(PtTimestamp timestamp, void *userData) { Pm_Read(m->stream, &buf, 1); //printf("%d\n", buf.message); - midi_decode(buf.message); + midi_decode(buf.message, m->synth); } @@ -59,7 +72,8 @@ void init_midi(midi_t *m, synth_t *synth) { m->stream = NULL; - + m->synth = synth; + Pm_Initialize(); printf("midi devs: %d\n", Pm_CountDevices()); diff --git a/src/synth.c b/src/synth.c index 29c44e7..1113a56 100644 --- a/src/synth.c +++ b/src/synth.c @@ -41,84 +41,19 @@ #define WAVE_SIZE (44100) -static void -StreamFinished( void* synthData ) -{ - synth_t *synth = (synth_t *) synthData; - printf( "Stream Completed\n"); -} - int main(void) { - PaStreamParameters outputParameters; - PaStream *stream; - PaError err; - int i; synth_t synth; midi_t midi; init_synth(&synth); init_midi(&midi, &synth); + rayrun(&synth); - err = Pa_Initialize(); - if( err != paNoError ) goto error; - - const PaDeviceInfo *deviceInfo; - for( i=0; i< Pa_GetDeviceCount(); i++ ) { - deviceInfo = Pa_GetDeviceInfo( i ); - //if (!strcmp("HyperX Cloud II Wireless: USB Audio (hw:0,0)", deviceInfo->name)) break; - printf("dev: %s || %f\n", deviceInfo->name, deviceInfo->defaultSampleRate); - if (!strcmp("HDA Intel PCH: ALC1220 Analog (hw:0,0)", deviceInfo->name)) break; - } - - - outputParameters.device = i; Pa_GetDefaultOutputDevice(); /* default output device */ - printf("-------\nSelected device: %s\n-------\n", Pa_GetDeviceInfo(outputParameters.device)->name); - if (outputParameters.device == paNoDevice) { - fprintf(stderr,"Error: No default output device.\n"); - goto error; - } - outputParameters.channelCount = 2; /* stereo output */ - outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */ - outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency; - outputParameters.hostApiSpecificStreamInfo = NULL; - - err = Pa_OpenStream(&stream, - NULL, /* no input */ - &outputParameters, - SAMPLE_RATE, - FRAMES_PER_BUFFER, - paClipOff, /* we won't output out of range samples so don't bother clipping them */ - sound_gen, - &synth ); - if( err != paNoError ) goto error; - - err = Pa_SetStreamFinishedCallback( stream, &StreamFinished ); - if( err != paNoError ) goto error; - - err = Pa_StartStream( stream ); - if( err != paNoError ) goto error; - - rayrun(&synth, stream); - - err = Pa_StopStream( stream ); - if( err != paNoError ) goto error; - - err = Pa_CloseStream( stream ); - if( err != paNoError ) goto error; - - Pa_Terminate(); - printf("Test finished.\n"); - - return err; - error: - Pa_Terminate(); - free_synth(&synth); terminate_midi(&midi); - fprintf( stderr, "An error occurred while using the portaudio stream\n" ); - fprintf( stderr, "Error number: %d\n", err ); - fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) ); - return err; + free_synth(&synth); + + return 0; } diff --git a/src/synth_engine.c b/src/synth_engine.c index 56ab771..11586da 100644 --- a/src/synth_engine.c +++ b/src/synth_engine.c @@ -2,6 +2,8 @@ #include "lowpass.h" #include "filter.h" +#include + /* 1d convolution */ void convole(float *signal, float *filter, size_t signal_size, size_t filter_size, float *out) { @@ -230,6 +232,13 @@ sound_gen(const void *inputBuffer, void *outputBuffer, return paContinue; } + +static void +StreamFinished( void* synthData ) +{ + synth_t *synth = (synth_t *) synthData; +} + void init_synth(synth_t * synth) { @@ -273,11 +282,48 @@ init_synth(synth_t * synth) LowPass_Init(); synth->fff = create_bw_low_pass_filter(2, SAMPLE_RATE, 400); synth->fff2 = create_bw_band_stop_filter(8, SAMPLE_RATE, 15000, 22000); + + Pa_Initialize(); + + int i; + const PaDeviceInfo *deviceInfo; + for( i=0; i< Pa_GetDeviceCount(); i++ ) { + deviceInfo = Pa_GetDeviceInfo( i ); + //if (!strcmp("HyperX Cloud II Wireless: USB Audio (hw:0,0)", deviceInfo->name)) break; + printf("dev: %s || %f\n", deviceInfo->name, deviceInfo->defaultSampleRate); + if (!strcmp("HDA Intel PCH: ALC1220 Analog (hw:0,0)", deviceInfo->name)) break; + } + + + PaStreamParameters outputParameters; + outputParameters.device = i; 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 */ + outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency; + outputParameters.hostApiSpecificStreamInfo = NULL; + + Pa_OpenStream(&(synth->stream), + NULL, /* no input */ + &outputParameters, + SAMPLE_RATE, + FRAMES_PER_BUFFER, + paClipOff, /* we won't output out of range samples so don't bother clipping them */ + sound_gen, + synth ); + + Pa_SetStreamFinishedCallback(synth->stream, &StreamFinished); + Pa_StartStream(synth->stream); } void free_synth(synth_t * synth) { + Pa_StopStream( synth->stream ); + Pa_CloseStream( synth->stream ); + Pa_Terminate(); + + free_bw_low_pass(synth->fff); free_bw_band_stop(synth->fff2); } diff --git a/src/synth_engine.h b/src/synth_engine.h index 86cfe1a..b88f3d5 100644 --- a/src/synth_engine.h +++ b/src/synth_engine.h @@ -45,6 +45,8 @@ typedef struct { } viz_t; typedef struct { + PaStream *stream; + float freq_offset; float gain; float x; diff --git a/src/synth_gui.c b/src/synth_gui.c index 6b44595..fc4e5fa 100644 --- a/src/synth_gui.c +++ b/src/synth_gui.c @@ -104,7 +104,7 @@ draw_signals(synth_t * synth, int x, int y, int width, int height) } void -rayrun(void *synthData, PaStream *stream) +rayrun(void *synthData) { synth_t * synth = (synth_t *)synthData; PaTime current_time = 0; @@ -114,7 +114,7 @@ rayrun(void *synthData, PaStream *stream) SetTargetFPS(60); // Set our game to run at 60 frames-per-second while (!WindowShouldClose()) { - keyboard(synth, stream); + keyboard(synth, synth->stream); int prec = 100000; if (IsKeyPressed(KEY_ENTER)) { @@ -172,7 +172,7 @@ rayrun(void *synthData, PaStream *stream) EndDrawing(); //---------------------------------------------------------------------------------- - current_time = Pa_GetStreamTime(stream); + current_time = Pa_GetStreamTime(synth->stream); //printf("%f :: %ld\n", current_time - prev_time, phase); prev_time = current_time; diff --git a/src/synth_gui.h b/src/synth_gui.h index 73bdbdf..d08a7f4 100644 --- a/src/synth_gui.h +++ b/src/synth_gui.h @@ -5,6 +5,6 @@ #include "synth_engine.h" -void rayrun(void *synthData, PaStream *stream); +void rayrun(void *synthData); #endif /* SYNTH_GUI_H */ -- cgit v1.2.3