aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--main.c7
-rw-r--r--midi.c16
-rw-r--r--midi.h4
-rw-r--r--mutex.c19
-rw-r--r--mutex.h24
-rw-r--r--soundfonts/general-808.sf2bin0 -> 71680 bytes
-rw-r--r--synth.c31
-rw-r--r--synth.h4
9 files changed, 96 insertions, 11 deletions
diff --git a/Makefile b/Makefile
index 8681948..fca5cb9 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
1CC := cc 1CC := cc
2CFLAGS := -Wall -Wextra -Wshadow -Wunused -Wswitch-enum -Wpedantic -ggdb 2CFLAGS := -Wall -Wextra -Wshadow -Wunused -Wswitch-enum -Wpedantic -ggdb
3LDFLAGS := -lm -ldl -lpthread -lasound 3LDFLAGS := -lm -ldl -lpthread -lasound
4FILES := main.c midi.c synth.c minisdl_audio.c 4FILES := main.c midi.c synth.c mutex.c minisdl_audio.c
5PROG := ttdaw 5PROG := ttdaw
6 6
7$(PROG): main.c 7$(PROG): main.c
diff --git a/main.c b/main.c
index 5a1916e..4eb4cf7 100644
--- a/main.c
+++ b/main.c
@@ -7,6 +7,7 @@
7#include "version.h" 7#include "version.h"
8#include "midi.h" 8#include "midi.h"
9#include "synth.h" 9#include "synth.h"
10#include "mutex.h"
10 11
11void help(const char *argv0) { 12void help(const char *argv0) {
12 printf("Usage: %s [options]\n" 13 printf("Usage: %s [options]\n"
@@ -70,6 +71,9 @@ int main(int argc, char *argv[]) {
70 fprintf(stdout, "> Device port: %s\n", port_name); 71 fprintf(stdout, "> Device port: %s\n", port_name);
71 fprintf(stdout, "> Soundfont: %s\n", soundfont_file); 72 fprintf(stdout, "> Soundfont: %s\n", soundfont_file);
72 73
74 // Create mutex.
75 initialize_mutex();
76
73 // Create synth thread. 77 // Create synth thread.
74 pthread_t synth_thread; 78 pthread_t synth_thread;
75 SynthArgs synth_args = { soundfont_file }; 79 SynthArgs synth_args = { soundfont_file };
@@ -91,6 +95,9 @@ int main(int argc, char *argv[]) {
91 pthread_join(midi_thread, NULL); 95 pthread_join(midi_thread, NULL);
92 pthread_join(synth_thread, NULL); 96 pthread_join(synth_thread, NULL);
93 97
98 // Destroy mutex.
99 destroy_mutex();
100
94 fprintf(stdout, "Exiting...\n"); 101 fprintf(stdout, "Exiting...\n");
95 return 0; 102 return 0;
96} 103}
diff --git a/midi.c b/midi.c
index 3d21f79..f389826 100644
--- a/midi.c
+++ b/midi.c
@@ -5,6 +5,7 @@
5#include <alsa/asoundlib.h> 5#include <alsa/asoundlib.h>
6 6
7#include "midi.h" 7#include "midi.h"
8#include "mutex.h"
8 9
9static snd_seq_t *seq_handle; 10static snd_seq_t *seq_handle;
10static snd_seq_addr_t *ports; 11static snd_seq_addr_t *ports;
@@ -81,8 +82,12 @@ void *midi(void *arg) {
81 } 82 }
82 83
83 if (ev) { 84 if (ev) {
85 pthread_mutex_lock(&mutex);
84 switch (ev->type) { 86 switch (ev->type) {
85 case SND_SEQ_EVENT_NOTEON: 87 case SND_SEQ_EVENT_NOTEON:
88 shared_data.note = ev->data.note.note;
89 shared_data.state = 1;
90 shared_data.velocity = ev->data.note.velocity;
86 printf("%3d:%-3dNote on %2d, note %d, velocity: %3d\n", 91 printf("%3d:%-3dNote on %2d, note %d, velocity: %3d\n",
87 ev->source.client, ev->source.port, 92 ev->source.client, ev->source.port,
88 ev->data.note.channel, 93 ev->data.note.channel,
@@ -91,14 +96,23 @@ void *midi(void *arg) {
91 break; 96 break;
92 97
93 case SND_SEQ_EVENT_NOTEOFF: 98 case SND_SEQ_EVENT_NOTEOFF:
99 shared_data.note = ev->data.note.note;
100 shared_data.state = 0;
101 shared_data.velocity = 0;
94 printf("%3d:%-3dNote off\t%2d, note %d\n", 102 printf("%3d:%-3dNote off\t%2d, note %d\n",
95 ev->source.client, ev->source.port, 103 ev->source.client, ev->source.port,
96 ev->data.note.channel, 104 ev->data.note.channel,
97 ev->data.note.note); 105 ev->data.note.note);
98 break; 106 break;
107 default:
108 break;
109 }
99 110
111 shared_data.action = 1;
112 shared_data.preset = 3;
100 113
101 } 114 pthread_cond_signal(&cond_synth);
115 pthread_mutex_unlock(&mutex);
102 } 116 }
103 } 117 }
104 118
diff --git a/midi.h b/midi.h
index 81b105b..ddbaef8 100644
--- a/midi.h
+++ b/midi.h
@@ -1,8 +1,8 @@
1#include <alsa/asoundlib.h>
2
3#ifndef MIDI_H_ 1#ifndef MIDI_H_
4#define MIDI_H_ 2#define MIDI_H_
5 3
4#include <alsa/asoundlib.h>
5
6#define CLIENT_NAME "ttdaw" 6#define CLIENT_NAME "ttdaw"
7#define MAX_MIDI_PORTS 1 7#define MAX_MIDI_PORTS 1
8 8
diff --git a/mutex.c b/mutex.c
new file mode 100644
index 0000000..007928d
--- /dev/null
+++ b/mutex.c
@@ -0,0 +1,19 @@
1#include <pthread.h>
2#include "mutex.h"
3
4SharedData shared_data;
5
6pthread_mutex_t mutex;
7pthread_cond_t cond_midi;
8pthread_cond_t cond_synth;
9
10void initialize_mutex() {
11 pthread_mutex_init(&mutex, NULL);
12 pthread_cond_init(&cond_synth, NULL);
13}
14
15void destroy_mutex() {
16 pthread_mutex_destroy(&mutex);
17 pthread_cond_destroy(&cond_synth);
18}
19
diff --git a/mutex.h b/mutex.h
new file mode 100644
index 0000000..2f3c653
--- /dev/null
+++ b/mutex.h
@@ -0,0 +1,24 @@
1#ifndef MUTEX_H
2#define MUTEX_H
3
4#include <pthread.h>
5
6typedef struct {
7 int note;
8 int state;
9 int velocity;
10 int preset;
11 int action;
12} SharedData;
13
14extern SharedData shared_data;
15
16extern pthread_mutex_t mutex;
17extern pthread_cond_t cond_midi;
18extern pthread_cond_t cond_synth;
19
20void initialize_mutex();
21void destroy_mutex();
22
23#endif // MUTEX_H
24
diff --git a/soundfonts/general-808.sf2 b/soundfonts/general-808.sf2
new file mode 100644
index 0000000..3e128d8
--- /dev/null
+++ b/soundfonts/general-808.sf2
Binary files differ
diff --git a/synth.c b/synth.c
index d391056..05c3664 100644
--- a/synth.c
+++ b/synth.c
@@ -2,6 +2,7 @@
2#include <unistd.h> 2#include <unistd.h>
3 3
4#include "synth.h" 4#include "synth.h"
5#include "mutex.h"
5#include "minisdl_audio.h" 6#include "minisdl_audio.h"
6 7
7#define TSF_IMPLEMENTATION 8#define TSF_IMPLEMENTATION
@@ -12,7 +13,7 @@ static SDL_mutex* g_Mutex;
12 13
13// Render the audio samples in float format. 14// Render the audio samples in float format.
14static void AudioCallback(void* data, Uint8 *stream, int len) { 15static void AudioCallback(void* data, Uint8 *stream, int len) {
15 int SampleCount = (len / (2 * sizeof(float))); // 2 output channels. 16 int SampleCount = (len / (AUDIO_CHANNELS * sizeof(float))); // 2 output channels.
16 SDL_LockMutex(g_Mutex); // Get exclusive lock. 17 SDL_LockMutex(g_Mutex); // Get exclusive lock.
17 tsf_render_float(g_TinySoundFont, (float*)stream, SampleCount, 0); 18 tsf_render_float(g_TinySoundFont, (float*)stream, SampleCount, 0);
18 SDL_UnlockMutex(g_Mutex); 19 SDL_UnlockMutex(g_Mutex);
@@ -22,10 +23,10 @@ void *synth(void *arg) {
22 SynthArgs* args = (SynthArgs*)arg; 23 SynthArgs* args = (SynthArgs*)arg;
23 24
24 SDL_AudioSpec OutputAudioSpec; 25 SDL_AudioSpec OutputAudioSpec;
25 OutputAudioSpec.freq = 44100; 26 OutputAudioSpec.freq = AUDIO_FREQ;
26 OutputAudioSpec.format = AUDIO_F32; 27 OutputAudioSpec.format = AUDIO_F32;
27 OutputAudioSpec.channels = 2; 28 OutputAudioSpec.channels = AUDIO_CHANNELS;
28 OutputAudioSpec.samples = 4096; 29 OutputAudioSpec.samples = AUDIO_SAMPLES;
29 OutputAudioSpec.callback = AudioCallback; 30 OutputAudioSpec.callback = AudioCallback;
30 31
31 // Initialize the audio system. 32 // Initialize the audio system.
@@ -56,12 +57,28 @@ void *synth(void *arg) {
56 SDL_PauseAudio(0); 57 SDL_PauseAudio(0);
57 58
58 while (1) { 59 while (1) {
59 sleep(1); 60 pthread_mutex_lock(&mutex);
61 while (shared_data.action == 0) {
62 pthread_cond_wait(&cond_synth, &mutex);
63 }
60 64
61 SDL_LockMutex(g_Mutex); 65 SDL_LockMutex(g_Mutex);
62 tsf_note_off(g_TinySoundFont, 1, 50); 66
63 tsf_note_on(g_TinySoundFont, 1, 50, 1.0f); 67 if (shared_data.state == 0) {
68 tsf_note_off(g_TinySoundFont, shared_data.preset, shared_data.note);
69 } else {
70 float normalized_velocity = (float)shared_data.velocity / 127.0f;
71 tsf_note_on(g_TinySoundFont, shared_data.preset, shared_data.note, normalized_velocity);
72 }
73
64 SDL_UnlockMutex(g_Mutex); 74 SDL_UnlockMutex(g_Mutex);
75
76 printf("Consumed: note=%d, state=%d velocity:%d\n", shared_data.note, shared_data.state, shared_data.velocity);
77
78 // Reset state to indicate data has been consumed.
79 shared_data.action = 0;
80
81 pthread_mutex_unlock(&mutex);
65 } 82 }
66} 83}
67 84
diff --git a/synth.h b/synth.h
index 1976745..90fd410 100644
--- a/synth.h
+++ b/synth.h
@@ -1,6 +1,10 @@
1#ifndef SYNTH_H_ 1#ifndef SYNTH_H_
2#define SYNTH_H_ 2#define SYNTH_H_
3 3
4#define AUDIO_FREQ 44100
5#define AUDIO_SAMPLES 64
6#define AUDIO_CHANNELS 2
7
4typedef struct { 8typedef struct {
5 char *soundfont_file; 9 char *soundfont_file;
6} SynthArgs; 10} SynthArgs;