ref: d69dbb86405af9c82a8ae5c60027cf09e0c29034
parent: c5f0c601ae93df571ed74e52db54eefa42e63a0d
author: cancel <cancel@cancel.fm>
date: Mon Jan 20 13:55:47 EST 2020
Add MIDI CC operator (!) Fixes #20
--- a/bank.h
+++ b/bank.h
@@ -2,7 +2,8 @@
#include "base.h"
typedef enum {
- Oevent_type_midi,
+ Oevent_type_midi_note,
+ Oevent_type_midi_cc,
Oevent_type_osc_ints,
Oevent_type_udp_string,
} Oevent_types;
@@ -14,8 +15,13 @@
typedef struct {
U8 oevent_type;
U8 channel, octave, note, velocity, duration;
-} Oevent_midi;
+} Oevent_midi_note;
+typedef struct {
+ U8 oevent_type;
+ U8 channel, control, value;
+} Oevent_midi_cc;
+
enum { Oevent_osc_int_count = 16 };
typedef struct {
@@ -35,7 +41,8 @@
typedef union {
Oevent_any any;
- Oevent_midi midi;
+ Oevent_midi_note midi_note;
+ Oevent_midi_cc midi_cc;
Oevent_osc_ints osc_ints;
Oevent_udp_string udp_string;
} Oevent;
--- a/sim.c
+++ b/sim.c
@@ -262,7 +262,26 @@
END_OPERATOR
BEGIN_OPERATOR(midicc)
- // TODO unimplemented
+ for (Usz i = 1; i < 4; ++i) {
+ PORT(0, (Isz)i, IN);
+ }
+ STOP_IF_NOT_BANGED;
+ Glyph channel_g = PEEK(0, 1);
+ Glyph control_g = PEEK(0, 2);
+ Glyph value_g = PEEK(0, 3);
+ if (channel_g == '.' || control_g == '.')
+ return;
+ Usz channel = index_of(channel_g);
+ if (channel > 15)
+ return;
+ Usz control = index_of(control_g);
+ Usz value = safe_index_of(value_g) * 127 / 35;
+ Oevent_midi_cc *oe =
+ (Oevent_midi_cc *)oevent_list_alloc_item(extra_params->oevent_list);
+ oe->oevent_type = Oevent_type_midi_cc;
+ oe->channel = (U8)channel;
+ oe->control = (U8)control;
+ oe->value = (U8)value;
END_OPERATOR
BEGIN_OPERATOR(comment)
@@ -320,9 +339,9 @@
if (vel_num > 127)
vel_num = 127;
}
- Oevent_midi *oe =
- (Oevent_midi *)oevent_list_alloc_item(extra_params->oevent_list);
- oe->oevent_type = (U8)Oevent_type_midi;
+ Oevent_midi_note *oe =
+ (Oevent_midi_note *)oevent_list_alloc_item(extra_params->oevent_list);
+ oe->oevent_type = (U8)Oevent_type_midi_note;
oe->channel = (U8)channel_num;
oe->octave = octave_num;
oe->note = note_num;
--- a/tui_main.c
+++ b/tui_main.c
@@ -626,14 +626,21 @@
Oevent const *ev = oevent_list->buffer + i;
Oevent_types evt = ev->any.oevent_type;
switch (evt) {
- case Oevent_type_midi: {
- Oevent_midi const *em = &ev->midi;
- wprintw(win,
- "MIDI\tchannel %d\toctave %d\tnote %d\tvelocity %d\tlength %d",
- (int)em->channel, (int)em->octave, (int)em->note,
- (int)em->velocity, (int)em->duration);
+ case Oevent_type_midi_note: {
+ Oevent_midi_note const *em = &ev->midi_note;
+ wprintw(
+ win,
+ "MIDI Note\tchannel %d\toctave %d\tnote %d\tvelocity %d\tlength %d",
+ (int)em->channel, (int)em->octave, (int)em->note, (int)em->velocity,
+ (int)em->duration);
break;
}
+ case Oevent_type_midi_cc: {
+ Oevent_midi_cc const *ec = &ev->midi_cc;
+ wprintw(win, "MIDI CC\tchannel %d\tcontrol %d\tvalue %d",
+ (int)ec->channel, (int)ec->control, (int)ec->value);
+ break;
+ }
case Oevent_type_osc_ints: {
Oevent_osc_ints const *eo = &ev->osc_ints;
wprintw(win, "OSC\t%c\tcount: %d ", eo->glyph, eo->count, eo->count);
@@ -1043,8 +1050,8 @@
break;
Oevent const *e = events + i;
switch ((Oevent_types)e->any.oevent_type) {
- case Oevent_type_midi: {
- Oevent_midi const *em = &e->midi;
+ case Oevent_type_midi_note: {
+ Oevent_midi_note const *em = &e->midi_note;
Usz note_number = (Usz)(12u * em->octave + em->note);
if (note_number > 127)
note_number = 127;
@@ -1064,6 +1071,41 @@
++midi_note_count;
break;
}
+ case Oevent_type_midi_cc: {
+ Oevent_midi_cc const *ec = &e->midi_cc;
+ // Note that we're not preserving the exact order of MIDI events as
+ // emitted by the orca VM. Notes and CCs that are emitted in the same
+ // step will always have the CCs sent first. Not sure if this is OK or
+ // not. If it's not OK, we can either loop again a second time to always
+ // send CCs after notes, or if that's not also OK, we can make the stack
+ // buffer more complicated and interleave the CCs in it.
+ switch (midi_mode_type) {
+ case Midi_mode_type_null:
+ break;
+ case Midi_mode_type_osc_bidule: {
+ if (!oosc_dev)
+ break; // not sure if needed
+ I32 ints[3];
+ ints[0] = (0xb << 4) | ec->channel; // status
+ ints[1] = ec->control;
+ ints[2] = ec->value;
+ oosc_send_int32s(oosc_dev, midi_mode->osc_bidule.path, ints,
+ ORCA_ARRAY_COUNTOF(ints));
+ break;
+ }
+#ifdef FEAT_PORTMIDI
+ case Midi_mode_type_portmidi: {
+ int istatus = (0x9 << 4) | (int)ec->channel;
+ PmError pme = Pm_WriteShort(
+ midi_mode->portmidi.stream, 0,
+ Pm_Message(istatus, (int)ec->control, (int)ec->value));
+ (void)pme;
+ break;
+ }
+#endif
+ }
+ break;
+ }
case Oevent_type_osc_ints: {
// kinda lame
if (!oosc_dev)
@@ -1091,7 +1133,7 @@
}
}
- if (midi_note_count > 0 && midi_mode) {
+ if (midi_note_count > 0) {
Usz start_note_offs, end_note_offs;
susnote_list_add_notes(susnote_list, new_susnotes, midi_note_count,
&start_note_offs, &end_note_offs);