MIDI (an acronym for Musical Instrument Digital Interface) is a technical standard that describes a communications protocol, digital interface, and electrical connectors that connect a wide variety of electronic musical instruments, computers, and related audio devices for playing, editing, and recording music.

For more information about MIDI, see midi.org.

Using MIDI in Spektar

MIDI components come with default installation and should work with all MIDI hardware. Select MIDI components from help or the library to review documentation. Examples folder also has a few good examples of how to use the included components.

Encoding and decoding MIDI messages

Internally, Spektar translates MIDI messages into 32 bit format suitable for signal paths. All built-in components and scripts have full support for these transformations so this is transparent for end users that use GUI only. However, if you encounter a use case where you need to make these conversions, we have documented how this can be done below.

In scripts and scripted components

Script functions are available for conversions:

Function Description Example
int #midi:status(float $midiFloat) Get midi status from float coded message int $status = #midi:status( $midi_in );
int #midi:data1(float $midiFloat) Get midi data byte 1 from float coded message int $status = #midi:data1( $midi_in );
int #midi:data2(float $midiFloat) Get midi data byte 2 from float coded message int $status = #midi:data2( $midi_in );
float #midi:frequency(float $data1) Get midi note frequency float $freq = #midi:frequency($data1);

In Java

Utility functions are provided for conversion between float and javax.sound.midi.MidiMessage in dsp.midi.MidiDataType. Code is reproduced here:

	public ShortMessage convert(float value) {
		int rawbits = Float.floatToRawIntBits(value);
		int status = 0xff & (rawbits>>24);
		int data1 = 0xff & (rawbits>>16);
		int data2 = 0xff & (rawbits>>8);
		try {
			return new ShortMessage(status, data1, data2);
		} catch (InvalidMidiDataException e) {
			throw new RuntimeException("Invalid midi message ", e);
		}
	}

	public float convert(MidiMessage value) {
		int rawbits = 0;
		if ( value instanceof ShortMessage) {
			ShortMessage m = (ShortMessage)value;
			rawbits |= 0xff000000 & (m.getStatus()<<24);
			rawbits |= 0xff0000   & (m.getData1()<<16);
			rawbits |= 0xff00     & (m.getData2()<<8);
		}
		return Float.intBitsToFloat(rawbits);
	}
	

In C / C++ / VST / VSTi export

If you export your design to e.g. C, C++ or VSTi you may encounter a use case where you need to do this translation yourself. Here we will summarise exactly how this is done.

In pseudo-code, the routine to pack MIDI message to float may look like this:

int midiInt = 0xff000000 & (midimsg.getStatus() << 24 );
midiInt    |= 0x00ff0000 & (midimsg.getData1()  << 16 );
midiInt    |= 0x0000ff00 & (midimsg.getData2()  <<  8 );
float midiFloat = *((float*)(&midiInt));

Conversely, to unpack the value from float:

// get midiFloat from Spektar design
float midiFloat = myComponentOutput;
// now unpack
int midiInt = *((int*)(&midiFloat));
int status  = 0xff & ( midiInt >> 24 );
int data1   = 0xff & ( midiInt >> 16 );
int data2   = 0xff & ( midiInt >>  8 );

Since if most cases the data bytes actually carry only 7 bits 0xff for data1 and data2 could be replaced by 0x7f.