Reorg, added more sources

This commit is contained in:
UberGuidoZ
2022-12-28 22:34:27 -08:00
parent 034d4cd172
commit 24f88bf731
1646 changed files with 39096 additions and 0 deletions
@@ -0,0 +1,3 @@
#include <stdint.h>
#define SYSEX_BUFFER_LEN 16
@@ -0,0 +1,144 @@
#include "message.h"
/** Returns the data within the MidiEvent as a NoteOffEvent struct */
NoteOffEvent AsNoteOff(MidiEvent* event) {
NoteOffEvent m;
m.channel = event->channel;
m.note = event->data[0];
m.velocity = event->data[1];
return m;
}
/** Returns the data within the MidiEvent as a NoteOnEvent struct */
NoteOnEvent AsNoteOn(MidiEvent* event) {
NoteOnEvent m;
m.channel = event->channel;
m.note = event->data[0];
m.velocity = event->data[1];
return m;
}
/** Returns the data within the MidiEvent as a PolyphonicKeyPressureEvent struct */
PolyphonicKeyPressureEvent AsPolyphonicKeyPressure(MidiEvent* event) {
PolyphonicKeyPressureEvent m;
m.channel = event->channel;
m.note = event->data[0];
m.pressure = event->data[1];
return m;
}
/** Returns the data within the MidiEvent as a ControlChangeEvent struct.*/
ControlChangeEvent AsControlChange(MidiEvent* event) {
ControlChangeEvent m;
m.channel = event->channel;
m.control_number = event->data[0];
m.value = event->data[1];
return m;
}
/** Returns the data within the MidiEvent as a ProgramChangeEvent struct.*/
ProgramChangeEvent AsProgramChange(MidiEvent* event) {
ProgramChangeEvent m;
m.channel = event->channel;
m.program = event->data[0];
return m;
}
/** Returns the data within the MidiEvent as a ProgramChangeEvent struct.*/
ChannelPressureEvent AsChannelPressure(MidiEvent* event) {
ChannelPressureEvent m;
m.channel = event->channel;
m.pressure = event->data[0];
return m;
}
/** Returns the data within the MidiEvent as a PitchBendEvent struct.*/
PitchBendEvent AsPitchBend(MidiEvent* event) {
PitchBendEvent m;
m.channel = event->channel;
m.value = ((uint16_t)(event->data[1]) << 7) + (event->data[0] - 8192);
return m;
}
SystemExclusiveEvent AsSystemExclusive(MidiEvent* event) {
SystemExclusiveEvent m;
m.length = event->sysex_message_len;
for(int i = 0; i < SYSEX_BUFFER_LEN; i++) {
m.data[i] = 0;
if(i < m.length) {
m.data[i] = event->sysex_data[i];
}
}
return m;
}
MTCQuarterFrameEvent AsMTCQuarterFrame(MidiEvent* event) {
MTCQuarterFrameEvent m;
m.message_type = (event->data[0] & 0x70) >> 4;
m.value = (event->data[0]) & 0x0f;
return m;
}
SongPositionPointerEvent AsSongPositionPointer(MidiEvent* event) {
SongPositionPointerEvent m;
m.position = ((uint16_t)(event->data[1]) << 7) | (event->data[0]);
return m;
}
SongSelectEvent AsSongSelect(MidiEvent* event) {
SongSelectEvent m;
m.song = event->data[0];
return m;
}
AllSoundOffEvent AsAllSoundOff(MidiEvent* event) {
AllSoundOffEvent m;
m.channel = event->channel;
return m;
}
ResetAllControllersEvent AsResetAllControllers(MidiEvent* event) {
ResetAllControllersEvent m;
m.channel = event->channel;
m.value = event->data[1];
return m;
}
LocalControlEvent AsLocalControl(MidiEvent* event) {
LocalControlEvent m;
m.channel = event->channel;
m.local_control_off = (event->data[1] == 0);
m.local_control_on = (event->data[1] == 127);
return m;
}
AllNotesOffEvent AsAllNotesOff(MidiEvent* event) {
AllNotesOffEvent m;
m.channel = event->channel;
return m;
}
OmniModeOffEvent AsOmniModeOff(MidiEvent* event) {
OmniModeOffEvent m;
m.channel = event->channel;
return m;
}
OmniModeOnEvent AsOmniModeOn(MidiEvent* event) {
OmniModeOnEvent m;
m.channel = event->channel;
return m;
}
MonoModeOnEvent AsMonoModeOn(MidiEvent* event) {
MonoModeOnEvent m;
m.channel = event->channel;
m.num_channels = event->data[1];
return m;
}
PolyModeOnEvent AsPolyModeOn(MidiEvent* event) {
PolyModeOnEvent m;
m.channel = event->channel;
return m;
}
@@ -0,0 +1,251 @@
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include "config.h"
typedef enum {
NoteOff, /**< & */
NoteOn, /**< & */
PolyphonicKeyPressure, /**< & */
ControlChange, /**< & */
ProgramChange, /**< & */
ChannelPressure, /**< & */
PitchBend, /**< & */
SystemCommon, /**< & */
SystemRealTime, /**< & */
ChannelMode, /**< & */
MessageLast, /**< & */
} MidiMessageType;
typedef enum {
SystemExclusive, /**< & */
MTCQuarterFrame, /**< & */
SongPositionPointer, /**< & */
SongSelect, /**< & */
SCUndefined0, /**< & */
SCUndefined1, /**< & */
TuneRequest, /**< & */
SysExEnd, /**< & */
SystemCommonLast, /**< & */
} SystemCommonType;
typedef enum {
TimingClock, /**< & */
SRTUndefined0, /**< & */
Start, /**< & */
Continue, /**< & */
Stop, /**< & */
SRTUndefined1, /**< & */
ActiveSensing, /**< & */
Reset, /**< & */
SystemRealTimeLast, /**< & */
} SystemRealTimeType;
typedef enum {
AllSoundOff, /**< & */
ResetAllControllers, /**< & */
LocalControl, /**< & */
AllNotesOff, /**< & */
OmniModeOff, /**< & */
OmniModeOn, /**< & */
MonoModeOn, /**< & */
PolyModeOn, /**< & */
ChannelModeLast, /**< & */
} ChannelModeType;
/** Struct containing note, and velocity data for a given channel.
Can be made from MidiEvent
*/
typedef struct {
int channel; /**< & */
uint8_t note; /**< & */
uint8_t velocity; /**< & */
} NoteOffEvent;
/** Struct containing note, and velocity data for a given channel.
Can be made from MidiEvent
*/
typedef struct {
int channel; /**< & */
uint8_t note; /**< & */
uint8_t velocity; /**< & */
} NoteOnEvent;
/** Struct containing note, and pressure data for a given channel.
Can be made from MidiEvent
*/
typedef struct {
int channel;
uint8_t note;
uint8_t pressure;
} PolyphonicKeyPressureEvent;
/** Struct containing control number, and value for a given channel.
Can be made from MidiEvent
*/
typedef struct {
int channel; /**< & */
uint8_t control_number; /**< & */
uint8_t value; /**< & */
} ControlChangeEvent;
/** Struct containing new program number, for a given channel.
Can be made from MidiEvent
*/
typedef struct {
int channel; /**< & */
uint8_t program; /**< & */
} ProgramChangeEvent;
/** Struct containing pressure (aftertouch), for a given channel.
Can be made from MidiEvent
*/
typedef struct {
int channel; /**< & */
uint8_t pressure; /**< & */
} ChannelPressureEvent;
/** Struct containing pitch bend value for a given channel.
Can be made from MidiEvent
*/
typedef struct {
int channel; /**< & */
int16_t value; /**< & */
} PitchBendEvent;
/** Struct containing sysex data.
Can be made from MidiEvent
*/
typedef struct {
int length;
uint8_t data[SYSEX_BUFFER_LEN]; /**< & */
} SystemExclusiveEvent;
/** Struct containing QuarterFrame data.
Can be made from MidiEvent
*/
typedef struct {
uint8_t message_type; /**< & */
uint8_t value; /**< & */
} MTCQuarterFrameEvent;
/** Struct containing song position data.
Can be made from MidiEvent
*/
typedef struct {
uint16_t position; /**< & */
} SongPositionPointerEvent;
/** Struct containing song select data.
Can be made from MidiEvent
*/
typedef struct {
uint8_t song; /**< & */
} SongSelectEvent;
/** Struct containing sound off data.
Can be made from MidiEvent
*/
typedef struct {
int channel; /**< & */
} AllSoundOffEvent;
/** Struct containing ResetAllControllersEvent data.
Can be made from MidiEvent
*/
typedef struct {
int channel; /**< & */
uint8_t value; /**< & */
} ResetAllControllersEvent;
/** Struct containing LocalControlEvent data.
Can be made from MidiEvent
*/
typedef struct {
int channel; /**< & */
bool local_control_off; /**< & */
bool local_control_on; /**< & */
} LocalControlEvent;
/** Struct containing AllNotesOffEvent data.
Can be made from MidiEvent
*/
typedef struct {
int channel; /**< & */
} AllNotesOffEvent;
/** Struct containing OmniModeOffEvent data.
* Can be made from MidiEvent
*/
typedef struct {
int channel; /**< & */
} OmniModeOffEvent;
/** Struct containing OmniModeOnEvent data.
Can be made from MidiEvent
*/
typedef struct {
int channel; /**< & */
} OmniModeOnEvent;
/** Struct containing MonoModeOnEvent data.
Can be made from MidiEvent
*/
typedef struct {
int channel; /**< & */
uint8_t num_channels; /**< & */
} MonoModeOnEvent;
/** Struct containing PolyModeOnEvent data.
Can be made from MidiEvent
*/
typedef struct {
int channel; /**< & */
} PolyModeOnEvent;
/** Simple MidiEvent with message type, channel, and data[2] members.
*/
typedef struct {
MidiMessageType type;
int channel;
uint8_t data[2];
uint8_t sysex_data[SYSEX_BUFFER_LEN];
uint8_t sysex_message_len;
SystemCommonType sc_type;
SystemRealTimeType srt_type;
ChannelModeType cm_type;
} MidiEvent;
/** Returns the data within the MidiEvent as a NoteOffEvent struct */
NoteOffEvent AsNoteOff(MidiEvent* event);
/** Returns the data within the MidiEvent as a NoteOnEvent struct */
NoteOnEvent AsNoteOn(MidiEvent* event);
/** Returns the data within the MidiEvent as a PolyphonicKeyPressureEvent struct */
PolyphonicKeyPressureEvent AsPolyphonicKeyPressure(MidiEvent* event);
/** Returns the data within the MidiEvent as a ControlChangeEvent struct.*/
ControlChangeEvent AsControlChange(MidiEvent* event);
/** Returns the data within the MidiEvent as a ProgramChangeEvent struct.*/
ProgramChangeEvent AsProgramChange(MidiEvent* event);
/** Returns the data within the MidiEvent as a ProgramChangeEvent struct.*/
ChannelPressureEvent AsChannelPressure(MidiEvent* event);
/** Returns the data within the MidiEvent as a PitchBendEvent struct.*/
PitchBendEvent AsPitchBend(MidiEvent* event);
SystemExclusiveEvent AsSystemExclusive(MidiEvent* event);
MTCQuarterFrameEvent AsMTCQuarterFrame(MidiEvent* event);
SongPositionPointerEvent AsSongPositionPointer(MidiEvent* event);
SongSelectEvent AsSongSelect(MidiEvent* event);
AllSoundOffEvent AsAllSoundOff(MidiEvent* event);
ResetAllControllersEvent AsResetAllControllers(MidiEvent* event);
LocalControlEvent AsLocalControl(MidiEvent* event);
AllNotesOffEvent AsAllNotesOff(MidiEvent* event);
OmniModeOffEvent AsOmniModeOff(MidiEvent* event);
OmniModeOnEvent AsOmniModeOn(MidiEvent* event);
MonoModeOnEvent AsMonoModeOn(MidiEvent* event);
PolyModeOnEvent AsPolyModeOn(MidiEvent* event);
@@ -0,0 +1,149 @@
#include <stdlib.h>
#include "parser.h"
typedef enum {
ParserEmpty,
ParserHasStatus,
ParserHasData0,
ParserSysEx,
} ParserState;
const uint8_t kStatusByteMask = 0x80;
const uint8_t kMessageMask = 0x70;
const uint8_t kDataByteMask = 0x7F;
const uint8_t kSystemCommonMask = 0xF0;
const uint8_t kChannelMask = 0x0F;
const uint8_t kRealTimeMask = 0xF8;
const uint8_t kSystemRealTimeMask = 0x07;
struct MidiParser {
MidiMessageType status;
ParserState state;
MidiEvent incoming_message;
};
MidiParser* midi_parser_alloc(void) {
MidiParser* parser = malloc(sizeof(MidiParser));
parser->incoming_message.type = MessageLast;
parser->state = ParserEmpty;
return parser;
}
void midi_parser_free(MidiParser* parser) {
free(parser);
}
bool midi_parser_parse(MidiParser* parser, uint8_t byte) {
bool parsed = false;
MidiEvent* event = &parser->incoming_message;
switch(parser->state) {
case ParserEmpty:
// check byte for valid Status Byte
if(byte & kStatusByteMask) {
// Get MessageType, and Channel
event->channel = byte & kChannelMask;
event->type = (MidiMessageType)((byte & kMessageMask) >> 4);
// Validate, and move on.
if(event->type < MessageLast) {
parser->state = ParserHasStatus;
// Mark this status byte as running_status
parser->status = event->type;
if(parser->status == SystemCommon) {
event->channel = 0;
//system real time = 1111 1xxx
if(byte & 0x08) {
event->type = SystemRealTime;
parser->status = SystemRealTime;
event->srt_type = (SystemRealTimeType)(byte & kSystemRealTimeMask);
//short circuit to start
parser->state = ParserEmpty;
//queue_.push(incoming_message_);
parsed = true;
}
//system common
else {
event->sc_type = (SystemCommonType)(byte & 0x07);
//sysex
if(event->sc_type == SystemExclusive) {
parser->state = ParserSysEx;
event->sysex_message_len = 0;
}
//short circuit
else if(event->sc_type > SongSelect) {
parser->state = ParserEmpty;
//queue_.push(incoming_message_);
parsed = true;
}
}
}
}
// Else we'll keep waiting for a valid incoming status byte
} else {
// Handle as running status
event->type = parser->status;
event->data[0] = byte & kDataByteMask;
parser->state = ParserHasData0;
}
break;
case ParserHasStatus:
if((byte & kStatusByteMask) == 0) {
event->data[0] = byte & kDataByteMask;
if(parser->status == ChannelPressure || parser->status == ProgramChange ||
event->sc_type == MTCQuarterFrame || event->sc_type == SongSelect) {
//these are just one data byte, so we short circuit back to start
parser->state = ParserEmpty;
//queue_.push(incoming_message_);
parsed = true;
} else {
parser->state = ParserHasData0;
}
//ChannelModeMessages (reserved Control Changes)
if(parser->status == ControlChange && event->data[0] > 119) {
event->type = ChannelMode;
parser->status = ChannelMode;
event->cm_type = (ChannelModeType)(event->data[0] - 120);
}
} else {
// invalid message go back to start ;p
parser->state = ParserEmpty;
}
break;
case ParserHasData0:
if((byte & kStatusByteMask) == 0) {
event->data[1] = byte & kDataByteMask;
// At this point the message is valid, and we can add this MidiEvent to the queue
//queue_.push(incoming_message_);
parsed = true;
}
// Regardless, of whether the data was valid or not we go back to empty
// because either the message is queued for handling or its not.
parser->state = ParserEmpty;
break;
case ParserSysEx:
// end of sysex
if(byte == 0xf7) {
parser->state = ParserEmpty;
//queue_.push(incoming_message_);
parsed = true;
} else {
if(event->sysex_message_len < SYSEX_BUFFER_LEN) {
event->sysex_data[event->sysex_message_len] = byte;
event->sysex_message_len++;
}
}
break;
default:
break;
}
return parsed;
}
MidiEvent* midi_parser_get_message(MidiParser* parser) {
return &parser->incoming_message;
}
@@ -0,0 +1,14 @@
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include "message.h"
typedef struct MidiParser MidiParser;
MidiParser* midi_parser_alloc(void);
void midi_parser_free(MidiParser* parser);
bool midi_parser_parse(MidiParser* parser, uint8_t data);
MidiEvent* midi_parser_get_message(MidiParser* parser);
@@ -0,0 +1,40 @@
#include "usb_message.h"
CodeIndex code_index_from_data(uint8_t data) {
return (CodeIndex)(data & 0b00001111);
}
uint8_t cable_id_from_data(uint8_t data) {
return (data >> 4) & 0b00001111;
}
uint8_t usb_message_data_size(CodeIndex code_index) {
uint8_t data_size = 0;
switch(code_index) {
case CodeIndexCommon1Byte:
/* case CodeIndexSysExEnd1Byte: */
case CodeIndexSingleByte:
data_size = 1;
break;
case CodeIndexSysEx2Byte:
case CodeIndexSysExEnd2Byte:
case CodeIndexProgramChange:
case CodeIndexChannelPressure:
data_size = 2;
break;
case CodeIndexSysEx3Byte:
case CodeIndexSysExStart:
case CodeIndexSysExEnd3Byte:
case CodeIndexNoteOff:
case CodeIndexNoteOn:
case CodeIndexPolyKeyPress:
case CodeIndexControlChange:
case CodeIndexPitchBendChange:
data_size = 3;
break;
default:
break;
}
return data_size;
}
@@ -0,0 +1,28 @@
#pragma once
#include <stdint.h>
typedef enum {
CodeIndexMisc = 0x0, /**< Reserved, MIDI Size: 1, 2, 3 */
CodeIndexCableEvent = 0x1, /**< Reserved, MIDI Size: 1, 2, 3 */
CodeIndexSysEx2Byte = 0x2, /**< MIDI Size: 2 */
CodeIndexSysEx3Byte = 0x3, /**< MIDI Size: 3 */
CodeIndexSysExStart = 0x4, /**< MIDI Size: 3 */
CodeIndexCommon1Byte = 0x5, /**< MIDI Size: 1 */
CodeIndexSysExEnd1Byte = 0x5, /**< MIDI Size: 1 */
CodeIndexSysExEnd2Byte = 0x6, /**< MIDI Size: 2 */
CodeIndexSysExEnd3Byte = 0x7, /**< MIDI Size: 3 */
CodeIndexNoteOff = 0x8, /**< MIDI Size: 3 */
CodeIndexNoteOn = 0x9, /**< MIDI Size: 3 */
CodeIndexPolyKeyPress = 0xA, /**< MIDI Size: 3 */
CodeIndexControlChange = 0xB, /**< MIDI Size: 3 */
CodeIndexProgramChange = 0xC, /**< MIDI Size: 2 */
CodeIndexChannelPressure = 0xD, /**< MIDI Size: 2 */
CodeIndexPitchBendChange = 0xE, /**< MIDI Size: 3 */
CodeIndexSingleByte = 0xF, /**< MIDI Size: 1 */
} CodeIndex;
CodeIndex code_index_from_data(uint8_t data);
uint8_t cable_id_from_data(uint8_t data);
uint8_t usb_message_data_size(CodeIndex code_index);