1.0 Overview |
2.0 Constructor |
3.0 Methods |
3.1 Reading MIDI Events |
3.2 A Note About Pitch Wheel Events |
3.3 Generating MIDI Events |
3.4 Resetting MIDI Channels |
3.4.1 Input |
3.4.2 Output |
3.5 Sample Generic Script |
4.0 Data Members |
MidiMan has an internal event buffer capable of caching up to 50,000 events before older events begin to be overwritten.
MidiMan is only available for Windows platforms:
Platform | Library | |
Intel | mmoa_x86.zip |
The device name you use should correspond exactly to that used by Windows to identify MIDI devices. Case does not matter, correct spelling does. For instance, suppose you had identified the device name "SB Live! MIDI UART" as being the device channel with which you wish to interact. In order to open that device for input, you would invoke the MidiMan constructor as follows:
Example 2.1: Opening A MIDI Device For Input |
. . . midi_in = MidiMan("<SB Live! MIDI UART"); . . .Opening a device for output would be similar:
Example 2.2: Opening A MIDI Device For Outpust |
. . . midi_out = MidiMan(">SB Live! MIDI UART"); . . .If you plan to do input and output at the same time, it is more efficient to let a single instance of MidiMan manage both channels than to generate a separate instance of MidiMan for each direction:
Example 2.3: Opening Both Input And Output In The Same Instance |
. . . midi = MidiMan("<SB Live! MIDI UART",">SB Live! MIDI UART"); . . .Some pre-defined constant values have been supplied to better help you identify or designate specific MIDI events.
|
Note: It is important to note that, even if the MIDI input channel is opened successfully, events generated on that channel will not be processed by MidiMan until the channel is enabled using the startInput() method (see this entry later in this document). |
3.1 Reading MIDI Events |
The readEvent() method will query MidiMan's internal event stack, and will return the oldest event contained upon it. This method returns, in order, the MIDI command, MIDI channel number, data element #1, data element #2, and the timestamp (in milliseconds) of the event. It may be the case that the combination of the command and channel values did not generate any associated data elements. Please refer to the MIDI v1.0 specification for more info.
If no arguments are passed to readEvent(), then the oldest MIDI event in the cache is returned. If no events are available, readEvent() will return 'nil'.
Example 3.1: Reading An Event |
. . . midi_in = MidiMan("<SB Live! MIDI UART"); . . . (cmd,chn,dat1,dat2,ts) = midi_in.readEvent(); if(cmd != nil) { . . . } . . .You can also pass one or more event designators to readEvent() which will be used to filter events in the cache. Only those events matching the specified event values will be returned. Intervening events in the buffer not in the filter list will be discarded.
Example 3.2: Filtering Events |
. . . midi_in = MidiMan("<SB Live! MIDI UART"); . . . (cmd,chn,dat1,dat2,ts) = midi_in.readEvent(NOTEON,NOTEOFF); if(cmd != nil) { . . . } . . .readEvent() is only useful for reading a MIDI device that has been opened for input. If no such state exists within the Object Agent instance, then readEvent() will always return 'nil'.
3.2 A Note About Pitch Wheel Events |
The MIDI definition specifies that the Pitch Wheel has an at-rest value of 0x2000 (8192 decimal). MidiMan simplifies the process if handling Pitch Wheel events by normalizing the data value. This means that MidiMan will return an at-rest value of 0 for the Pitch Wheel, and all data events will be relative offsets from that value. If you need to use the actual specification-defined values for the Pitch Wheel, simply add 8192 to any value generated by that event.
The values return by readEvent() for the Pitch Wheel include the actual generated value in the first data element. The second data element is unused, and is set to zero (0).
3.3 Generating MIDI Events |
Using sendEvent(), you can send simple MIDI events to any device you have successfully opened for output. The argument list for sendEvent() exactly corresponds to the return list for readEvent(). The event command is provided first, followed by the MIDI channel number to receive the event. This can be a number from 1 to 16.
Two data elements can optionally be provided if the command being executed requires them. For example, the NOTEON command requires the note identifier (60 == Middle C), as well as the velocity at which the note should be played. The following example illustrates playing middle C through MIDI channel 3 on the output device:
Example 3.3: Playing Middle C |
. . . midi = MidiMan(">SB Live! MIDI UART"); midi.sendEvent(NOTEON,3,60,64); sleep(100); midi.sendEvent(NOTEOFF,3,60,64); . . .Some MIDI commands will not require extra data. For instance, System Common messages only utilize the MIDI channel value to accomplish their work:
Example 3.4: Events Without Data |
. . . midi = MidiMan(">SB Live! MIDI UART"); midi.sendEvent(SYSCOMMON,6); // tell all oscillators to tune themselves . . .
3.4 Resetting MIDI Channels |
3.4.1 Input |
The MIDI input stream can be reset using the resetInput() method. When the
input stream is reset, all input on the stream is halted, and the internal event
buffer is cleared. No further events will be processed on the input channel until
the startInput() method is called.
Aside from discarding buffered data and ignoring subsequent events, resetting the input channel has the effect of setting the timestamp settings back to zero. When the channel is re-enabled using startInput(), the timestamp values will once again begin increasing from zero.
Note: MidiMan opens the MIDI input channel but does not enable it for events. The startInput() method must be called before events on the input channel are processed by MidiMan. |
3.4.2 Output |
The MIDI output stream is reset using the resetOutput() method. When called, the device(s) associated with the output stream will cease all current activity. For instance, a synthesizer will immediately cut off all notes that might be playing when this event is broadcast.
3.5 Sample Generic Script |
The following complete Generic LScript will, in order, play the C-Major scale on the selected MIDI device, record all NOTE events until Middle-C is pressed, and finally, play back all events recorded:
Example 3.5: Exercising MidiMan |
@version 2.4 @warnings @script generic @insert "MidiMan.inc" @define MIDIDEVICE "SB Live! MIDI UART" // C-Major scale notes midi_notes = @60,62,64,65,67,69,71,72,71,69,67,65,64,62,60@; generic { // open the MIDI device for output, and play the C-Major scale on it midi = MidiMan(">" + MIDIDEVICE); for(x = 1;x <= 15;x++) { midi.sendEvent(NOTEON,1,midi_notes[x],64); sleep(150); midi.sendEvent(NOTEOFF,1,midi_notes[x],64); } // open the MIDI device for input, and record the NOTE events midi = MidiMan("<" + MIDIDEVICE); midi.startInput(); while(true) { t = midi.readEvent(NOTEON,NOTEOFF); if(t) { midi_cmd += t[1]; // Command (NOTEON or NOTEOFF) midi_chn += t[2]; // MIDI channel midi_dt1 += t[3]; // Note midi_dt2 += t[4]; // Velocity midi_ts += t[5]; // Timestamp (milliseconds) last if t[3] == 60; // Middle-C terminates record } else sleep(50); } midi.resetInput(); // disregard further input events // open the MIDI device for output, and play back the recorded events midi = MidiMan(">" + MIDIDEVICE); for(x = 1;x <= midi_cmd.size();x++) { midi.sendEvent(midi_cmd[x],midi_chn[x],midi_dt1[x],midi_dt2[x]); if(x < midi_cmd.size()) { how_long = midi_ts[x+1] - midi_ts[x]; sleep(how_long); } } }
The first data member is called input and contains a Boolean flag that indicates the state of the input MIDI channel in MidiMan. If 'true', then the input channel is open and available. This flag could be checked after the Object Agent instance is generated to ensure that required channel was successfully initialized:
Example 4.1: Checking The Input Channel |
. . . midi = MidiMan("<SB Live! MIDI UART"); if(!midi.input) { info("Could not initialize MIDI input channel!"); midi = nil; // release MidiMan return; } . . .Called output, the second data member works in a fashion similar to input. It is used to test the state of the MIDI output channel in MidiMan.
Example 4.2: Checking The Output Channel |
. . . midi = MidiMan(">SB Live! MIDI UART"); if(!midi.output) { info("Could not initialize MIDI output channel!"); midi = nil; // release MidiMan return; } . . .
Example 2.1 Opening A MIDI Device For Input |
|
Example 2.2 Opening A MIDI Device For Outpust |
|
Example 2.3 Opening Both Input And Output In The Same Instance |
|
Example 3.1 Reading An Event |
|
Example 3.2 Filtering Events |
|
Example 3.3 Playing Middle C |
|
Example 3.4 Events Without Data |
|
Example 3.5 Exercising MidiMan |
|
Example 4.1 Checking The Input Channel |
|
Example 4.2 Checking The Output Channel |