diff options
| -rw-r--r-- | Makefile | 2 | ||||
| -rw-r--r-- | main.c | 7 | ||||
| -rw-r--r-- | midi.c | 16 | ||||
| -rw-r--r-- | midi.h | 4 | ||||
| -rw-r--r-- | mutex.c | 19 | ||||
| -rw-r--r-- | mutex.h | 24 | ||||
| -rw-r--r-- | soundfonts/general-808.sf2 | bin | 0 -> 71680 bytes | |||
| -rw-r--r-- | synth.c | 31 | ||||
| -rw-r--r-- | synth.h | 4 |
9 files changed, 96 insertions, 11 deletions
@@ -1,7 +1,7 @@ CC := cc CFLAGS := -Wall -Wextra -Wshadow -Wunused -Wswitch-enum -Wpedantic -ggdb LDFLAGS := -lm -ldl -lpthread -lasound -FILES := main.c midi.c synth.c minisdl_audio.c +FILES := main.c midi.c synth.c mutex.c minisdl_audio.c PROG := ttdaw $(PROG): main.c @@ -7,6 +7,7 @@ #include "version.h" #include "midi.h" #include "synth.h" +#include "mutex.h" void help(const char *argv0) { printf("Usage: %s [options]\n" @@ -70,6 +71,9 @@ int main(int argc, char *argv[]) { fprintf(stdout, "> Device port: %s\n", port_name); fprintf(stdout, "> Soundfont: %s\n", soundfont_file); + // Create mutex. + initialize_mutex(); + // Create synth thread. pthread_t synth_thread; SynthArgs synth_args = { soundfont_file }; @@ -91,6 +95,9 @@ int main(int argc, char *argv[]) { pthread_join(midi_thread, NULL); pthread_join(synth_thread, NULL); + // Destroy mutex. + destroy_mutex(); + fprintf(stdout, "Exiting...\n"); return 0; } @@ -5,6 +5,7 @@ #include <alsa/asoundlib.h> #include "midi.h" +#include "mutex.h" static snd_seq_t *seq_handle; static snd_seq_addr_t *ports; @@ -81,8 +82,12 @@ void *midi(void *arg) { } if (ev) { + pthread_mutex_lock(&mutex); switch (ev->type) { case SND_SEQ_EVENT_NOTEON: + shared_data.note = ev->data.note.note; + shared_data.state = 1; + shared_data.velocity = ev->data.note.velocity; printf("%3d:%-3dNote on %2d, note %d, velocity: %3d\n", ev->source.client, ev->source.port, ev->data.note.channel, @@ -91,14 +96,23 @@ void *midi(void *arg) { break; case SND_SEQ_EVENT_NOTEOFF: + shared_data.note = ev->data.note.note; + shared_data.state = 0; + shared_data.velocity = 0; printf("%3d:%-3dNote off\t%2d, note %d\n", ev->source.client, ev->source.port, ev->data.note.channel, ev->data.note.note); break; + default: + break; + } + shared_data.action = 1; + shared_data.preset = 3; - } + pthread_cond_signal(&cond_synth); + pthread_mutex_unlock(&mutex); } } @@ -1,8 +1,8 @@ -#include <alsa/asoundlib.h> - #ifndef MIDI_H_ #define MIDI_H_ +#include <alsa/asoundlib.h> + #define CLIENT_NAME "ttdaw" #define MAX_MIDI_PORTS 1 @@ -0,0 +1,19 @@ +#include <pthread.h> +#include "mutex.h" + +SharedData shared_data; + +pthread_mutex_t mutex; +pthread_cond_t cond_midi; +pthread_cond_t cond_synth; + +void initialize_mutex() { + pthread_mutex_init(&mutex, NULL); + pthread_cond_init(&cond_synth, NULL); +} + +void destroy_mutex() { + pthread_mutex_destroy(&mutex); + pthread_cond_destroy(&cond_synth); +} + @@ -0,0 +1,24 @@ +#ifndef MUTEX_H +#define MUTEX_H + +#include <pthread.h> + +typedef struct { + int note; + int state; + int velocity; + int preset; + int action; +} SharedData; + +extern SharedData shared_data; + +extern pthread_mutex_t mutex; +extern pthread_cond_t cond_midi; +extern pthread_cond_t cond_synth; + +void initialize_mutex(); +void destroy_mutex(); + +#endif // MUTEX_H + diff --git a/soundfonts/general-808.sf2 b/soundfonts/general-808.sf2 Binary files differnew file mode 100644 index 0000000..3e128d8 --- /dev/null +++ b/soundfonts/general-808.sf2 @@ -2,6 +2,7 @@ #include <unistd.h> #include "synth.h" +#include "mutex.h" #include "minisdl_audio.h" #define TSF_IMPLEMENTATION @@ -12,7 +13,7 @@ static SDL_mutex* g_Mutex; // Render the audio samples in float format. static void AudioCallback(void* data, Uint8 *stream, int len) { - int SampleCount = (len / (2 * sizeof(float))); // 2 output channels. + int SampleCount = (len / (AUDIO_CHANNELS * sizeof(float))); // 2 output channels. SDL_LockMutex(g_Mutex); // Get exclusive lock. tsf_render_float(g_TinySoundFont, (float*)stream, SampleCount, 0); SDL_UnlockMutex(g_Mutex); @@ -22,10 +23,10 @@ void *synth(void *arg) { SynthArgs* args = (SynthArgs*)arg; SDL_AudioSpec OutputAudioSpec; - OutputAudioSpec.freq = 44100; + OutputAudioSpec.freq = AUDIO_FREQ; OutputAudioSpec.format = AUDIO_F32; - OutputAudioSpec.channels = 2; - OutputAudioSpec.samples = 4096; + OutputAudioSpec.channels = AUDIO_CHANNELS; + OutputAudioSpec.samples = AUDIO_SAMPLES; OutputAudioSpec.callback = AudioCallback; // Initialize the audio system. @@ -56,12 +57,28 @@ void *synth(void *arg) { SDL_PauseAudio(0); while (1) { - sleep(1); + pthread_mutex_lock(&mutex); + while (shared_data.action == 0) { + pthread_cond_wait(&cond_synth, &mutex); + } SDL_LockMutex(g_Mutex); - tsf_note_off(g_TinySoundFont, 1, 50); - tsf_note_on(g_TinySoundFont, 1, 50, 1.0f); + + if (shared_data.state == 0) { + tsf_note_off(g_TinySoundFont, shared_data.preset, shared_data.note); + } else { + float normalized_velocity = (float)shared_data.velocity / 127.0f; + tsf_note_on(g_TinySoundFont, shared_data.preset, shared_data.note, normalized_velocity); + } + SDL_UnlockMutex(g_Mutex); + + printf("Consumed: note=%d, state=%d velocity:%d\n", shared_data.note, shared_data.state, shared_data.velocity); + + // Reset state to indicate data has been consumed. + shared_data.action = 0; + + pthread_mutex_unlock(&mutex); } } @@ -1,6 +1,10 @@ #ifndef SYNTH_H_ #define SYNTH_H_ +#define AUDIO_FREQ 44100 +#define AUDIO_SAMPLES 64 +#define AUDIO_CHANNELS 2 + typedef struct { char *soundfont_file; } SynthArgs; |
