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

MIDIMessage.h

Committer:
simon
Date:
2011-02-06
Revision:
0:56b095524cf2
Child:
1:ff74eabe02cd

File content as of revision 0:56b095524cf2:

/* 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