summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--documents/SoundFont Technical Specification, v2.04.pdf (renamed from documents/sfspec24.pdf)bin530464 -> 530464 bytes
-rw-r--r--documents/Standard MIDI Files Specification, v1.0.pdfbin0 -> 84070 bytes
-rw-r--r--examples/sandbox.lua12
-rw-r--r--interface.c100
-rw-r--r--main.c45
-rw-r--r--midi.c30
-rw-r--r--synth.c3
7 files changed, 149 insertions, 41 deletions
diff --git a/documents/sfspec24.pdf b/documents/SoundFont Technical Specification, v2.04.pdf
index 252aff9..252aff9 100644
--- a/documents/sfspec24.pdf
+++ b/documents/SoundFont Technical Specification, v2.04.pdf
Binary files differ
diff --git a/documents/Standard MIDI Files Specification, v1.0.pdf b/documents/Standard MIDI Files Specification, v1.0.pdf
new file mode 100644
index 0000000..e422bf8
--- /dev/null
+++ b/documents/Standard MIDI Files Specification, v1.0.pdf
Binary files differ
diff --git a/examples/sandbox.lua b/examples/sandbox.lua
index 43c3ec7..d42eb6e 100644
--- a/examples/sandbox.lua
+++ b/examples/sandbox.lua
@@ -5,16 +5,16 @@
-- note_on(note, sf_preset, effect)
-- note_off(note)
-- delay(millisecons)
--- play_pattern(pattern_name, repeat)
+-- play_block(pattern_name, repeat)
-- Effects:
-- delay
-- reverb
--- This is a pattern definition.
+-- This is a block/pattern definition.
-- Columns go from A..F and rows go from 1..4.
-- This blocks will be visualized in the DAW.
-pattern("A1", function(self)
+block("A1", function(self)
for i = 1, 10 do
note_on(40 + i, 1, nil)
delay(10)
@@ -23,8 +23,8 @@ end)
-- This is the actual song timeline.
timeline(function(self)
- play_pattern("A1", 1)
- play_pattern("F2", 3)
- play_pattern("D4", 2)
+ play_block("A1", 1)
+ play_block("F2", 3)
+ play_block("D4", 2)
end)
diff --git a/interface.c b/interface.c
index 26aca55..1347ce2 100644
--- a/interface.c
+++ b/interface.c
@@ -1,16 +1,108 @@
+#include <stdlib.h>
#include <stdio.h>
+#include <locale.h>
#include <unistd.h>
#include "interface.h"
#include "mutex.h"
+#define TB_IMPL
+#include "termbox2.h"
+
+static int block_width = 14;
+static int block_height = 4;
+
+void draw_block(int x, int y, const char *label, int empty) {
+
+ tb_set_cell(x, y, 0x250C, TB_WHITE, TB_DEFAULT);
+ tb_set_cell(x+block_width-1, y, 0x2510, TB_WHITE, TB_DEFAULT);
+ tb_set_cell(x, y+block_height-1, 0x2514, TB_WHITE, TB_DEFAULT);
+ tb_set_cell(x+block_width-1, y+block_height-1, 0x2518, TB_WHITE, TB_DEFAULT);
+
+ tb_printf(x+(block_width/2) - (strlen(label)/2), y+(block_height/2)-1 ,TB_YELLOW, 0, label);
+ tb_printf(x+(block_width/2) - (strlen("empty")/2), y+(block_height/2) ,TB_DIM, 0, "empty");
+
+ tb_present();
+}
+
+void draw_blocks() {
+ int offset_x = 0;
+ int offset_y = 6;
+ char col_names[6] = {'A', 'B', 'C', 'D', 'E', 'F'};
+
+ for (int r = 0; r < 4; r++) {
+ for (int c = 0; c < 6; c++) {
+ char label[3];
+ label[0] = col_names[c];
+ label[1] = '1' + r;
+ label[2] = '\0';
+ draw_block(offset_x+(block_width*c), offset_y+(block_height*r), label, 0);
+ }
+ }
+}
+
+void draw_help_tooltip(const char* tooltip_text) {
+ tb_printf(tb_width() - strlen(tooltip_text) - 1, tb_height()-1, TB_DIM, 0, tooltip_text);
+ tb_present();
+}
+
void *interface(void *arg) {
InterfaceArgs* args = (InterfaceArgs*)arg;
- (void)args;
+
+ int ret;
+ setlocale(LC_ALL, "");
+
+ ret = tb_init();
+ if (ret) {
+ fprintf(stderr, "tb_init() failed with error code %d\n", ret);
+ exit(1);
+ }
+
+ tb_set_input_mode(TB_INPUT_ESC | TB_INPUT_MOUSE);
+ struct tb_event ev;
+
+ tb_clear();
+ tb_present();
+
+ // Show currently selected soundfont.
+ tb_printf(0, 0, TB_GREEN, 0, "Soundfont: %s", args->soundfont_file);
+ tb_printf(0, 1, TB_GREEN, 0, "Preset: %s", args->soundfont_preset);
+ tb_present();
+
+ // Draw interface.
+ draw_help_tooltip("Ctrl+q - Quit");
+ draw_blocks();
+ /* draw_block(10, 10, "A1"); */
while(1) {
- // Do the thread stuff here.
- sleep(1);
- fprintf(stdout, "hi from interface thread\n");
+ ret = tb_poll_event(&ev);
+
+ if (ret != TB_OK) {
+ if (ret == TB_ERR_POLL && tb_last_errno() == EINTR) {
+ /* Poll was interrupted, maybe by a SIGWINCH; try again */
+ continue;
+ }
+ /* Some other error occurred; bail */
+ break;
+ }
+
+ switch (ev.type) {
+ case TB_EVENT_KEY:
+ if (ev.key == TB_KEY_CTRL_Q) {
+ tb_shutdown();
+ exit(0);
+ }
+
+ if (ev.key == TB_KEY_ARROW_UP) {
+
+ }
+
+ if (ev.key == TB_KEY_ARROW_DOWN) {
+
+ }
+
+ break;
+ }
}
}
+
diff --git a/main.c b/main.c
index d1c8567..61f01f2 100644
--- a/main.c
+++ b/main.c
@@ -13,6 +13,7 @@
void help(const char *argv0) {
printf("Usage: %s [options]\n"
"\nAvailable options:\n"
+ " -n,--new creates a new song file\n"
" -l,--list list available devices\n"
" -c,--client=client:port device client and port\n"
" -s,--soundfont=file.sf2 soundfont file\n"
@@ -23,8 +24,9 @@ void help(const char *argv0) {
}
int main(int argc, char *argv[]) {
- const char short_options[] = "lc:s:p:hv";
+ const char short_options[] = "n:lc:s:p:hv";
const struct option long_options[] = {
+ { "new", 1, NULL, 'n' },
{ "list", 0, NULL, 'l' },
{ "client", 1, NULL, 'c' },
{ "soundfont", 1, NULL, 's' },
@@ -34,6 +36,7 @@ int main(int argc, char *argv[]) {
{ 0 },
};
+ char *new_song_name = NULL;
char *port_name = NULL;
char *soundfont_file = NULL;
int soundfont_preset = 0;
@@ -41,6 +44,8 @@ int main(int argc, char *argv[]) {
int opt;
while ((opt = getopt_long(argc, argv, short_options, long_options, NULL)) != -1) {
switch (opt) {
+ case 'n':
+ new_song_name = optarg;
case 'l':
fprintf(stderr, "List feature is NOT implemented yet.\n");
return 0;
@@ -69,19 +74,37 @@ int main(int argc, char *argv[]) {
}
}
+ if (new_song_name != NULL) {
+ fprintf(stdout, "Creating new song file with name %s\n", new_song_name);
+ return 0;
+ }
+
if (port_name == NULL || soundfont_file == NULL || soundfont_preset < 0) {
fprintf(stdout, "Missing options. Check help.\n");
fprintf(stdout, "Port, soundfile and preset are required fields.\n");
return 1;
}
- fprintf(stdout, "> Device port: %s\n", port_name);
- fprintf(stdout, "> Soundfont: %s\n", soundfont_file);
- fprintf(stdout, "> SF preset: %d\n", soundfont_preset);
+ /* fprintf(stdout, "> Device port: %s\n", port_name); */
+ /* fprintf(stdout, "> Soundfont: %s\n", soundfont_file); */
+ /* fprintf(stdout, "> SF preset: %d\n", soundfont_preset); */
+ /* fprintf(stdout, "> Song name: %s\n", new_song_name); */
// Create mutex.
initialize_mutex();
+ // Create UI thread.
+ pthread_t interface_thread;
+ InterfaceArgs interface_args = {
+ .soundfont_file = soundfont_file,
+ .soundfont_preset = soundfont_preset,
+ };
+
+ if (pthread_create(&interface_thread, NULL, interface, (void*)&interface_args) != 0) {
+ fprintf(stderr, "Error creating interface thread\n");
+ return 1;
+ }
+
// Create synth thread.
pthread_t synth_thread;
SynthArgs synth_args = {
@@ -103,22 +126,10 @@ int main(int argc, char *argv[]) {
return 1;
}
- // Create UI thread.
- pthread_t interface_thread;
- InterfaceArgs interface_args = {
- .soundfont_file = soundfont_file,
- .soundfont_preset = soundfont_preset,
- };
-
- if (pthread_create(&interface_thread, NULL, interface, (void*)&interface_args) != 0) {
- fprintf(stderr, "Error creating interface thread\n");
- return 1;
- }
-
// Start threads.
+ pthread_join(interface_thread, NULL);
pthread_join(midi_thread, NULL);
pthread_join(synth_thread, NULL);
- pthread_join(interface_thread, NULL);
// Destroy mutex.
destroy_mutex();
diff --git a/midi.c b/midi.c
index e924b70..341df15 100644
--- a/midi.c
+++ b/midi.c
@@ -6,6 +6,7 @@
#include "midi.h"
#include "mutex.h"
+#include "termbox2.h"
static snd_seq_t *seq_handle;
static snd_seq_addr_t *ports;
@@ -40,10 +41,10 @@ void *midi(void *arg) {
}
// Listing assigned ports.
- fprintf(stdout, "Ports:\n");
- for (int j = 0; j < MAX_MIDI_PORTS; j++) {
- fprintf(stdout, " client: %d, port: %d\n", ports[j].client, ports[j].port);
- }
+ /* fprintf(stdout, "Ports:\n"); */
+ /* for (int j = 0; j < MAX_MIDI_PORTS; j++) { */
+ /* fprintf(stdout, " client: %d, port: %d\n", ports[j].client, ports[j].port); */
+ /* } */
// Connecting ports.
for (int i = 0; i < MAX_MIDI_PORTS; ++i) {
@@ -87,21 +88,24 @@ void *midi(void *arg) {
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,
- ev->data.note.note,
- ev->data.note.velocity);
+ tb_printf(0, 3, TB_CYAN, 0, "Note: %3d", ev->data.note.note);
+ tb_printf(0, 4, TB_CYAN, 0, "Velocity: %3d", ev->data.note.velocity);
+ tb_present();
+ /* printf("%3d:%-3dNote on %2d, note %d, velocity: %3d\n", */
+ /* ev->source.client, ev->source.port, */
+ /* ev->data.note.channel, */
+ /* ev->data.note.note, */
+ /* ev->data.note.velocity); */
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);
+ /* printf("%3d:%-3dNote off\t%2d, note %d\n", */
+ /* ev->source.client, ev->source.port, */
+ /* ev->data.note.channel, */
+ /* ev->data.note.note); */
break;
diff --git a/synth.c b/synth.c
index d65ba41..3608eb3 100644
--- a/synth.c
+++ b/synth.c
@@ -4,6 +4,7 @@
#include "synth.h"
#include "mutex.h"
#include "minisdl_audio.h"
+#include "termbox2.h"
#define TSF_IMPLEMENTATION
#include "tsf.h"
@@ -73,7 +74,7 @@ void *synth(void *arg) {
SDL_UnlockMutex(g_Mutex);
- printf("Consumed: note=%d, state=%d velocity:%d\n", shared_data.note, shared_data.state, shared_data.velocity);
+ /* 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;