Added preset to args
| Author | Mitja Felicijan <mitja.felicijan@gmail.com> | 2024-10-09 18:32:27 +0200 |
| Committer | Mitja Felicijan <mitja.felicijan@gmail.com> | 2024-10-09 18:32:27 +0200 |
| Commit | ac6283f92b0579c0e820e13a83715389455d3171 (patch) |
|
-rw-r--r-- |
README.md | 9 | |
-rw-r--r-- |
main.c | 24 | |
-rw-r--r-- |
midi.c | 1 | |
-rw-r--r-- |
mutex.h | 1 | |
-rw-r--r-- |
synth.c | 4 | |
-rw-r--r-- |
synth.h | 1 |
6 files changed, 29 insertions, 11 deletions
| diff --git a/README.md b/README.md | |||
| ... | |||
| 4 | experimentation and learning more about audio, MIDI and terminal applications |
4 | experimentation and learning more about audio, MIDI and terminal applications |
| 5 | in general. |
5 | in general. |
| 6 | 6 | ||
| 7 | ## Compile and run |
||
| 8 | |||
| 9 | ```sh |
||
| 10 | make |
||
| 11 | ./ttdaw -c 28:0 -s soundfonts/general-808.sf2 -p 1 |
||
| 12 | ``` |
||
| 13 | |||
| 14 | List all available MIDI devices with `acconect -l`. |
||
| 15 | |||
| 7 | ## Soundfonts |
16 | ## Soundfonts |
| 8 | 17 | ||
| 9 | - https://dev.nando.audio/pages/soundfonts.html |
18 | - https://dev.nando.audio/pages/soundfonts.html |
| ... | |||
| diff --git a/main.c b/main.c | |||
| ... | |||
| 13 | printf("Usage: %s [options]\n" |
13 | printf("Usage: %s [options]\n" |
| 14 | "\nAvailable options:\n" |
14 | "\nAvailable options:\n" |
| 15 | " -l,--list list available devices\n" |
15 | " -l,--list list available devices\n" |
| 16 | " -p,--port=client:port device port\n" |
16 | " -c,--client=client:port device client and port\n" |
| 17 | " -s,--soundfont=file.sf2 soundfont file\n" |
17 | " -s,--soundfont=file.sf2 soundfont file\n" |
| 18 | " -p,--preset=1 soundfont preset\n" |
||
| 18 | " -h,--help this help\n" |
19 | " -h,--help this help\n" |
| 19 | " -v,--version show version\n", |
20 | " -v,--version show version\n", |
| 20 | argv0); |
21 | argv0); |
| 21 | } |
22 | } |
| 22 | 23 | ||
| 23 | int main(int argc, char *argv[]) { |
24 | int main(int argc, char *argv[]) { |
| 24 | const char short_options[] = "lp:s:hv"; |
25 | const char short_options[] = "lc:s:p:hv"; |
| 25 | const struct option long_options[] = { |
26 | const struct option long_options[] = { |
| 26 | { "list", 0, NULL, 'l' }, |
27 | { "list", 0, NULL, 'l' }, |
| 27 | { "port", 1, NULL, 'p' }, |
28 | { "client", 1, NULL, 'c' }, |
| 28 | { "soundfont", 1, NULL, 's' }, |
29 | { "soundfont", 1, NULL, 's' }, |
| 30 | { "preset", 1, NULL, 'p' }, |
||
| 29 | { "help", 0, NULL, 'h' }, |
31 | { "help", 0, NULL, 'h' }, |
| 30 | { "version", 0, NULL, 'v' }, |
32 | { "version", 0, NULL, 'v' }, |
| 31 | { 0 }, |
33 | { 0 }, |
| ... | |||
| 33 | 35 | ||
| 34 | char *port_name = NULL; |
36 | char *port_name = NULL; |
| 35 | char *soundfont_file = NULL; |
37 | char *soundfont_file = NULL; |
| 38 | int soundfont_preset = -1; |
||
| 36 | 39 | ||
| 37 | int opt; |
40 | int opt; |
| 38 | while ((opt = getopt_long(argc, argv, short_options, long_options, NULL)) != -1) { |
41 | while ((opt = getopt_long(argc, argv, short_options, long_options, NULL)) != -1) { |
| ... | |||
| 40 | case 'l': |
43 | case 'l': |
| 41 | fprintf(stderr, "List feature is NOT implemented yet.\n"); |
44 | fprintf(stderr, "List feature is NOT implemented yet.\n"); |
| 42 | return 0; |
45 | return 0; |
| 43 | case 'p': |
46 | case 'c': |
| 44 | port_name = optarg; |
47 | port_name = optarg; |
| 45 | break; |
48 | break; |
| 46 | case 's': |
49 | case 's': |
| 47 | soundfont_file = optarg; |
50 | soundfont_file = optarg; |
| 48 | break; |
51 | break; |
| 52 | case 'p': |
||
| 53 | soundfont_preset = atoi(optarg); |
||
| 54 | break; |
||
| 49 | case 'h': |
55 | case 'h': |
| 50 | help(argv[0]); |
56 | help(argv[0]); |
| 51 | return 0; |
57 | return 0; |
| ... | |||
| 62 | } |
68 | } |
| 63 | } |
69 | } |
| 64 | 70 | ||
| 65 | if (port_name == NULL || soundfont_file == NULL) { |
71 | if (port_name == NULL || soundfont_file == NULL || soundfont_preset < 0) { |
| 66 | fprintf(stdout, "Missing options. Check help.\n"); |
72 | fprintf(stdout, "Missing options. Check help.\n"); |
| 67 | fprintf(stdout, "Port and soundfile are required fields.\n"); |
73 | fprintf(stdout, "Port, soundfile and preset are required fields.\n"); |
| 68 | return 1; |
74 | return 1; |
| 69 | } |
75 | } |
| 70 | 76 | ||
| 71 | fprintf(stdout, "> Device port: %s\n", port_name); |
77 | fprintf(stdout, "> Device port: %s\n", port_name); |
| 72 | fprintf(stdout, "> Soundfont: %s\n", soundfont_file); |
78 | fprintf(stdout, "> Soundfont: %s\n", soundfont_file); |
| 79 | fprintf(stdout, "> SF preset: %d\n", soundfont_preset); |
||
| 73 | 80 | ||
| 74 | // Create mutex. |
81 | // Create mutex. |
| 75 | initialize_mutex(); |
82 | initialize_mutex(); |
| 76 | 83 | ||
| 77 | // Create synth thread. |
84 | // Create synth thread. |
| 78 | pthread_t synth_thread; |
85 | pthread_t synth_thread; |
| 79 | SynthArgs synth_args = { soundfont_file }; |
86 | SynthArgs synth_args = { |
| 87 | .soundfont_file = soundfont_file, |
||
| 88 | .soundfont_preset = soundfont_preset, |
||
| 89 | }; |
||
| 80 | 90 | ||
| 81 | if (pthread_create(&synth_thread, NULL, synth, (void*)&synth_args) != 0) { |
91 | if (pthread_create(&synth_thread, NULL, synth, (void*)&synth_args) != 0) { |
| 82 | fprintf(stderr, "Error creating synth thread\n"); |
92 | fprintf(stderr, "Error creating synth thread\n"); |
| ... | |||
| diff --git a/midi.c b/midi.c | |||
| ... | |||
| 109 | } |
109 | } |
| 110 | 110 | ||
| 111 | shared_data.action = 1; |
111 | shared_data.action = 1; |
| 112 | shared_data.preset = 3; |
||
| 113 | 112 | ||
| 114 | pthread_cond_signal(&cond_synth); |
113 | pthread_cond_signal(&cond_synth); |
| 115 | pthread_mutex_unlock(&mutex); |
114 | pthread_mutex_unlock(&mutex); |
| ... | |||
| diff --git a/mutex.h b/mutex.h | |||
| ... | |||
| 7 | int note; |
7 | int note; |
| 8 | int state; |
8 | int state; |
| 9 | int velocity; |
9 | int velocity; |
| 10 | int preset; |
||
| 11 | int action; |
10 | int action; |
| 12 | } SharedData; |
11 | } SharedData; |
| 13 | 12 | ||
| ... | |||
| diff --git a/synth.c b/synth.c | |||
| ... | |||
| 65 | SDL_LockMutex(g_Mutex); |
65 | SDL_LockMutex(g_Mutex); |
| 66 | 66 | ||
| 67 | if (shared_data.state == 0) { |
67 | if (shared_data.state == 0) { |
| 68 | tsf_note_off(g_TinySoundFont, shared_data.preset, shared_data.note); |
68 | tsf_note_off(g_TinySoundFont, args->soundfont_preset, shared_data.note); |
| 69 | } else { |
69 | } else { |
| 70 | float normalized_velocity = (float)shared_data.velocity / 127.0f; |
70 | float normalized_velocity = (float)shared_data.velocity / 127.0f; |
| 71 | tsf_note_on(g_TinySoundFont, shared_data.preset, shared_data.note, normalized_velocity); |
71 | tsf_note_on(g_TinySoundFont, args->soundfont_preset, shared_data.note, normalized_velocity); |
| 72 | } |
72 | } |
| 73 | 73 | ||
| 74 | SDL_UnlockMutex(g_Mutex); |
74 | SDL_UnlockMutex(g_Mutex); |
| ... | |||
| diff --git a/synth.h b/synth.h | |||
| ... | |||
| 7 | 7 | ||
| 8 | typedef struct { |
8 | typedef struct { |
| 9 | char *soundfont_file; |
9 | char *soundfont_file; |
| 10 | int soundfont_preset; |
||
| 10 | } SynthArgs; |
11 | } SynthArgs; |
| 11 | 12 | ||
| 12 | void *synth(void *arg); |
13 | void *synth(void *arg); |
| ... | |||