Browse Source

Add MIDI CC operator (!)

Fixes #20
master
cancel 5 years ago
parent
commit
d69dbb8640
  1. 13
      bank.h
  2. 27
      sim.c
  3. 60
      tui_main.c

13
bank.h

@ -2,7 +2,8 @@
#include "base.h" #include "base.h"
typedef enum { typedef enum {
Oevent_type_midi, Oevent_type_midi_note,
Oevent_type_midi_cc,
Oevent_type_osc_ints, Oevent_type_osc_ints,
Oevent_type_udp_string, Oevent_type_udp_string,
} Oevent_types; } Oevent_types;
@ -14,7 +15,12 @@ typedef struct {
typedef struct { typedef struct {
U8 oevent_type; U8 oevent_type;
U8 channel, octave, note, velocity, duration; 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 }; enum { Oevent_osc_int_count = 16 };
@ -35,7 +41,8 @@ typedef struct {
typedef union { typedef union {
Oevent_any any; Oevent_any any;
Oevent_midi midi; Oevent_midi_note midi_note;
Oevent_midi_cc midi_cc;
Oevent_osc_ints osc_ints; Oevent_osc_ints osc_ints;
Oevent_udp_string udp_string; Oevent_udp_string udp_string;
} Oevent; } Oevent;

27
sim.c

@ -262,7 +262,26 @@ BEGIN_OPERATOR(movement)
END_OPERATOR END_OPERATOR
BEGIN_OPERATOR(midicc) 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 END_OPERATOR
BEGIN_OPERATOR(comment) BEGIN_OPERATOR(comment)
@ -320,9 +339,9 @@ BEGIN_OPERATOR(midi)
if (vel_num > 127) if (vel_num > 127)
vel_num = 127; vel_num = 127;
} }
Oevent_midi *oe = Oevent_midi_note *oe =
(Oevent_midi *)oevent_list_alloc_item(extra_params->oevent_list); (Oevent_midi_note *)oevent_list_alloc_item(extra_params->oevent_list);
oe->oevent_type = (U8)Oevent_type_midi; oe->oevent_type = (U8)Oevent_type_midi_note;
oe->channel = (U8)channel_num; oe->channel = (U8)channel_num;
oe->octave = octave_num; oe->octave = octave_num;
oe->note = note_num; oe->note = note_num;

60
tui_main.c

@ -626,12 +626,19 @@ void draw_oevent_list(WINDOW *win, Oevent_list const *oevent_list) {
Oevent const *ev = oevent_list->buffer + i; Oevent const *ev = oevent_list->buffer + i;
Oevent_types evt = ev->any.oevent_type; Oevent_types evt = ev->any.oevent_type;
switch (evt) { switch (evt) {
case Oevent_type_midi: { case Oevent_type_midi_note: {
Oevent_midi const *em = &ev->midi; Oevent_midi_note const *em = &ev->midi_note;
wprintw(win, wprintw(
"MIDI\tchannel %d\toctave %d\tnote %d\tvelocity %d\tlength %d", win,
(int)em->channel, (int)em->octave, (int)em->note, "MIDI Note\tchannel %d\toctave %d\tnote %d\tvelocity %d\tlength %d",
(int)em->velocity, (int)em->duration); (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; break;
} }
case Oevent_type_osc_ints: { case Oevent_type_osc_ints: {
@ -1043,8 +1050,8 @@ void send_output_events(Oosc_dev *oosc_dev, Midi_mode const *midi_mode, Usz bpm,
break; break;
Oevent const *e = events + i; Oevent const *e = events + i;
switch ((Oevent_types)e->any.oevent_type) { switch ((Oevent_types)e->any.oevent_type) {
case Oevent_type_midi: { case Oevent_type_midi_note: {
Oevent_midi const *em = &e->midi; Oevent_midi_note const *em = &e->midi_note;
Usz note_number = (Usz)(12u * em->octave + em->note); Usz note_number = (Usz)(12u * em->octave + em->note);
if (note_number > 127) if (note_number > 127)
note_number = 127; note_number = 127;
@ -1064,6 +1071,41 @@ void send_output_events(Oosc_dev *oosc_dev, Midi_mode const *midi_mode, Usz bpm,
++midi_note_count; ++midi_note_count;
break; 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: { case Oevent_type_osc_ints: {
// kinda lame // kinda lame
if (!oosc_dev) if (!oosc_dev)
@ -1091,7 +1133,7 @@ void send_output_events(Oosc_dev *oosc_dev, Midi_mode const *midi_mode, Usz bpm,
} }
} }
if (midi_note_count > 0 && midi_mode) { if (midi_note_count > 0) {
Usz start_note_offs, end_note_offs; Usz start_note_offs, end_note_offs;
susnote_list_add_notes(susnote_list, new_susnotes, midi_note_count, susnote_list_add_notes(susnote_list, new_susnotes, midi_note_count,
&start_note_offs, &end_note_offs); &start_note_offs, &end_note_offs);

Loading…
Cancel
Save