|
diff --git a/main.c b/main.c
|
| ... |
| 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 |
|
| 11 |
void help(const char *argv0) { |
12 |
void help(const char *argv0) { |
| 12 |
printf("Usage: %s [options]\n" |
13 |
printf("Usage: %s [options]\n" |
| ... |
| 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 }; |
| ... |
| 90 |
|
94 |
|
| 91 |
pthread_join(midi_thread, NULL); |
95 |
pthread_join(midi_thread, NULL); |
| 92 |
pthread_join(synth_thread, NULL); |
96 |
pthread_join(synth_thread, NULL); |
|
|
97 |
|
|
|
98 |
// Destroy mutex. |
|
|
99 |
destroy_mutex(); |
| 93 |
|
100 |
|
| 94 |
fprintf(stdout, "Exiting...\n"); |
101 |
fprintf(stdout, "Exiting...\n"); |
| 95 |
return 0; |
102 |
return 0; |
| ... |
|
diff --git a/midi.c b/midi.c
|
| ... |
| 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 |
|
| 9 |
static snd_seq_t *seq_handle; |
10 |
static snd_seq_t *seq_handle; |
| 10 |
static snd_seq_addr_t *ports; |
11 |
static snd_seq_addr_t *ports; |
| ... |
| 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 |
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/synth.c b/synth.c
|
| ... |
| 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 |
|
13 |
|
| 13 |
// Render the audio samples in float format. |
14 |
// Render the audio samples in float format. |
| 14 |
static void AudioCallback(void* data, Uint8 *stream, int len) { |
15 |
static 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 |
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 |
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 |
|