diff options
| -rw-r--r-- | Makefile | 4 | ||||
| -rw-r--r-- | main.c | 13 | ||||
| -rw-r--r-- | synth.c | 67 | ||||
| -rw-r--r-- | synth.h | 11 |
4 files changed, 92 insertions, 3 deletions
@@ -1,7 +1,7 @@ CC := cc -CFLAGS := -Wall -Wextra -Wshadow -Wunused -Wswitch-enum -Wpedantic -Wundef +CFLAGS := -Wall -Wextra -Wshadow -Wunused -Wswitch-enum -Wpedantic -ggdb LDFLAGS := -lm -ldl -lpthread -lasound -FILES := main.c midi.c minisdl_audio.c +FILES := main.c midi.c synth.c minisdl_audio.c PROG := ttdaw $(PROG): main.c @@ -6,6 +6,7 @@ #include "version.h" #include "midi.h" +#include "synth.h" void help(const char *argv0) { printf("Usage: %s [options]\n" @@ -69,7 +70,16 @@ int main(int argc, char *argv[]) { fprintf(stdout, "> Device port: %s\n", port_name); fprintf(stdout, "> Soundfont: %s\n", soundfont_file); - // Create and start MIDI thread. + // Create synth thread. + pthread_t synth_thread; + SynthArgs synth_args = { soundfont_file }; + + if (pthread_create(&synth_thread, NULL, synth, (void*)&synth_args) != 0) { + fprintf(stderr, "Error creating synth thread\n"); + return 1; + } + + // Create MIDI thread. pthread_t midi_thread; MidiArgs midi_args = { port_name }; @@ -79,6 +89,7 @@ int main(int argc, char *argv[]) { } pthread_join(midi_thread, NULL); + pthread_join(synth_thread, NULL); fprintf(stdout, "Exiting...\n"); return 0; @@ -0,0 +1,67 @@ +#include <stdio.h> +#include <unistd.h> + +#include "synth.h" +#include "minisdl_audio.h" + +#define TSF_IMPLEMENTATION +#include "tsf.h" + +static tsf* g_TinySoundFont; +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. + SDL_LockMutex(g_Mutex); // Get exclusive lock. + tsf_render_float(g_TinySoundFont, (float*)stream, SampleCount, 0); + SDL_UnlockMutex(g_Mutex); +} + +void *synth(void *arg) { + SynthArgs* args = (SynthArgs*)arg; + + SDL_AudioSpec OutputAudioSpec; + OutputAudioSpec.freq = 44100; + OutputAudioSpec.format = AUDIO_F32; + OutputAudioSpec.channels = 2; + OutputAudioSpec.samples = 4096; + OutputAudioSpec.callback = AudioCallback; + + // Initialize the audio system. + if (SDL_AudioInit(TSF_NULL) < 0) { + fprintf(stderr, "Could not initialize audio hardware or driver\n"); + exit(1); + } + + // Load the SoundFont from a file. + g_TinySoundFont = tsf_load_filename(args->soundfont_file); + if (!g_TinySoundFont) { + fprintf(stderr, "Could not load SoundFont\n"); + exit(1); + } + + // Set the SoundFont rendering output mode. + tsf_set_output(g_TinySoundFont, TSF_STEREO_INTERLEAVED, OutputAudioSpec.freq, 0); + + // Create the mutex. + g_Mutex = SDL_CreateMutex(); + + // Request the desired audio output format. + if (SDL_OpenAudio(&OutputAudioSpec, TSF_NULL) < 0) { + fprintf(stderr, "Could not open the audio hardware or the desired audio output format\n"); + exit(1); + } + + SDL_PauseAudio(0); + + while (1) { + sleep(1); + + SDL_LockMutex(g_Mutex); + tsf_note_off(g_TinySoundFont, 1, 50); + tsf_note_on(g_TinySoundFont, 1, 50, 1.0f); + SDL_UnlockMutex(g_Mutex); + } +} + @@ -0,0 +1,11 @@ +#ifndef SYNTH_H_ +#define SYNTH_H_ + +typedef struct { + char *soundfont_file; +} SynthArgs; + +void *synth(void *arg); + +#endif // SYNTH_H_ + |
