A library to send and receive MIDI messages over USB using the default USB-MIDI drivers on Win/Mac

Dependents:   USBMIDI_HelloWorld USBMIDI_DrumExample USBMIDI_MonoSynth MIDI_Interface_ver_1 ... more

Files at this revision

API Documentation at this revision

Comitter:
simon
Date:
Sun Feb 06 17:26:29 2011 +0000
Child:
1:ff74eabe02cd
Commit message:

Changed in this revision

MIDIMessage.h Show annotated file Show diff for this revision Revisions of this file
USBMIDI.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MIDIMessage.h	Sun Feb 06 17:26:29 2011 +0000
@@ -0,0 +1,161 @@
+/* MIDI Message Format
+ * 
+ * [ msg(4) | channel(4) ] [ 0 | n(7) ] [ 0 | m(7) ]
+ *
+ * MIDI Data Messages (Channel Specific)
+ *
+ * Message               msg n    m
+ * ---------------------------------------------
+ * Note Off	             0x8 Key        Velocity
+ * Note On	             0x9 Key        Velocity
+ * Polyphonic Aftertouch 0xA Key        Pressure
+ * Control Change        0xB Controller Value
+ * Program Change        0xC Program    -
+ * Channel Aftertouch    0xD Pressure   -
+ * Pitch Wheel           0xE LSB        MSB
+ */
+
+
+#ifndef MBED_MIDIMESSAGE_H
+#define MBED_MIDIMESSAGE_H
+
+class MIDIMessage {
+public:
+	
+	// create messages
+	
+	static MIDIMessage NoteOff(int key, int velocity = 127, int channel = 0) {
+		MIDIMessage msg;
+		msg.data[0] = 0x80 | (channel & 0x0F);
+		msg.data[1] = key & 0x7F;
+		msg.data[2] = velocity & 0x7F; 
+		return msg;
+	}
+	
+	static MIDIMessage NoteOn(int key, int velocity = 127, int channel = 0) {
+		MIDIMessage msg;
+		msg.data[0] = 0x90 | (channel & 0x0F);
+		msg.data[1] = key & 0x7F;
+		msg.data[2] = velocity & 0x7F; 				
+		return msg;
+	}
+	
+	static MIDIMessage PolyphonicAftertouch(int key, int pressure, int channel = 0) {
+		MIDIMessage msg;
+		msg.data[0] = 0xA0 | (channel & 0x0F);
+		msg.data[1] = key & 0x7F;
+		msg.data[2] = pressure & 0x7F; 		
+		return msg;
+	}
+	
+	static MIDIMessage ControlChange(int control, int value, int channel = 0) {
+		MIDIMessage msg;
+		msg.data[0] = 0xB0 | (channel & 0x0F);
+		msg.data[1] = control & 0x7F;
+		msg.data[2] = value & 0x7F; 		
+		return msg;
+	}
+	
+	static MIDIMessage ProgramChange(int program, int channel = 0) {
+		MIDIMessage msg;
+		msg.data[0] = 0xC0 | (channel & 0x0F);
+		msg.data[1] = program & 0x7F;
+		msg.data[2] = 0x00; 		
+		return msg;
+	}
+	
+	static MIDIMessage ChannelAftertouch(int pressure, int channel = 0) {
+		MIDIMessage msg;
+		msg.data[0] = 0xD0 | (channel & 0x0F);
+		msg.data[1] = pressure & 0x7F;
+		msg.data[2] = 0x00; 		
+		return msg;
+	}
+	
+	static MIDIMessage PitchWheel(int pitch = 0, int channel = 0) {
+		MIDIMessage msg;
+		int p = pitch + 8192;	// 0 - 16383, 8192 is center
+		msg.data[0] = 0xE0 | (channel & 0x0F);
+		msg.data[1] = p & 0x7F;
+		msg.data[2] = (p >> 7) & 0x7F; 				
+		return msg;
+	}
+	
+	static MIDIMessage AllNotesOff(int channel = 0) {
+		return ControlChange(123, 0, channel);
+	}
+	
+	// decode messages
+	enum MIDIMessageType {
+		ErrorType,
+		NoteOffType,
+		NoteOnType,
+		PolyphonicAftertouchType,
+		ControlChangeType,
+		ProgramChangeType,
+		ChannelAftertouchType,
+		PitchWheelType,
+		AllNotesOffType
+	};
+	
+	MIDIMessageType type() {
+		switch((data[0] >> 4) & 0xF) {
+			case 0x8: return NoteOffType;
+			case 0x9: return NoteOnType;
+			case 0xA: return PolyphonicAftertouchType;
+			case 0xB: 
+				if(controller() < 120) { // standard controllers
+					return ControlChangeType;
+				} else if(controller() == 123) {
+					return AllNotesOffType;
+				} else {
+					return ErrorType; // unsupported atm
+				}
+			case 0xC: return ProgramChangeType;
+			case 0xD: return ChannelAftertouchType;
+			case 0xE: return PitchWheelType;
+			default: return ErrorType;
+		}
+	}
+	
+	int channel() {
+		return (data[0] & 0x0F);
+	}
+	
+	int key() {
+		return (data[1] & 0x7F);		
+	}
+	
+	int velocity() {
+		return (data[2] & 0x7F);		
+	}
+
+	int value() {
+		return (data[2] & 0x7F);		
+	}
+	
+	int pressure() {
+		if(type() == PolyphonicAftertouchType) {
+			return (data[2] & 0x7F);		
+		} else {
+			return (data[1] & 0x7F);		
+		}
+	}
+
+	int controller() {
+		return (data[1] & 0x7F);		
+	}
+
+	int program() {
+		return (data[1] & 0x7F);		
+	}
+	
+	int pitch() {
+		int p = ((data[2] & 0x7F) << 7) | (data[1] & 0x7F);
+		return p - 8192; // 0 - 16383, 8192 is center
+	}
+	
+	uint8_t data[3];
+};	
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBMIDI.h	Sun Feb 06 17:26:29 2011 +0000
@@ -0,0 +1,26 @@
+#ifndef MBED_USBMIDI_H
+#define MBED_USBMIDI_H
+
+#include "MIDIMessage.h"
+
+class USBMIDI {
+public:
+	USBMIDI() {}
+	~USBMIDI() {}
+		
+	// write messages
+	void write(MIDIMessage m) {}
+	int writeable() { return 0; }
+		
+	// read messages
+	MIDIMessage read() { return MIDIMessage::NoteOn(0); }
+	int readable() { return 0; }
+		
+	// notification of incoming message
+	void attach(void (*fptr)(void)) {}
+	
+	template <class T>
+	void attach(T *tptr, void (T::*mptr)(void)) {}
+}; 
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Sun Feb 06 17:26:29 2011 +0000
@@ -0,0 +1,38 @@
+#include "mbed.h"
+#include "USBMIDI.h"
+
+USBMIDI midi;
+
+int main() {
+    // send some notes
+	for(int i=0; i<127; i++) {
+		midi.write(MIDIMessage::NoteOn(i));
+		wait(0.25);
+		midi.write(MIDIMessage::NoteOff(i));
+		wait(0.5);
+	}
+
+    // recieve notes
+	while(1) {
+		if(midi.readable()) {
+			MIDIMessage msg = midi.read();
+			switch(msg.type()) {
+				case MIDIMessage::NoteOnType:
+				    printf("NoteOn key:%d, velocity: %d, channel: %d\n", msg.key(), msg.velocity(), msg.channel());
+				    break;
+				case MIDIMessage::NoteOffType:
+				    printf("NoteOff key:%d, velocity: %d, channel: %d\n", msg.key(), msg.velocity(), msg.channel());
+				    break;
+				case MIDIMessage::ControlChangeType:	
+				    printf("ControlChange controller: %d, data: %d\n", msg.controller(), msg.value());
+				    break;
+				case MIDIMessage::PitchWheelType:
+				    printf("PitchWheel channel: %d, pitch: %d\n", msg.channel(), msg.pitch());
+				    break;
+				default:
+				    printf("Another message\n");
+				
+			}
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Sun Feb 06 17:26:29 2011 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/9a9732ce53a1