Siren includes a portable MIDI I/O framework that consists of an abstract I/O port class (MIDIPort), a plug-in that uses the DLLCC interface, and a C-language interface module that talks to the host platform's native MIDI driver (in our case, the platform-independent portmidi library).
The higher-level model is that a MIDI voice object holds onto a MIDI device and a channel. The MIDI device object is connected to a MIDI port. For example, the verbose way to create the default MIDI voice would be to say
MIDIVoice on: (MIDIDevice on: (MIDIPort default openOutput))
The voice object gives us the standard voice behavior (like event mapping and scheduling). The MIDI device allows us to model the device-specific messages supported by some devices. (I used to use micro-tonal extended messages on a few different hardware synths.) The MIDIPort is used for the interface betweeen Siren and external MIDI drivers and devices. It implements both note-oriented (e.g., play: pitch at: aDelay dur: aDur amp: anAmp voice: voice), and data-oriented (e.g., put: data at: delay length: size) behaviors for MIDI I/O.
There is typically only one instance of MIDIPort; the messages new, default, and instance all answer the sole instance. MIDIPorts use dependency to signal input data--objects wishing to receive input should register themselves as dependents of a port. In the default Siren implementation, the scheduler is all in Smalltalk, and only the simplest MIDI driver is assumed.
MIDI Implementation: The class PortMIDIPort implements the low-level MIDI I/O messages by talking to the PortMidiInterface external class, which is a front-end to C-language glue code that talks to the portmidi library.
MIDI Tests and Examples
Basic Tests
"Try to open and close the MIDI port (report to transcript)."
[MIDIPort testOpenClose]
"Open MIDI, play a 1-sec. note."
[MIDIPort testANote]
"Open MIDI, play a fast scale."
[MIDIPort testAScale]
"Open MIDI, play notes based on the mouse position (x --> voice; y --> pitch) until mouse down."
[MIDIPort testMouseMIDI]
"Close down and clean up."
[MIDIPort cleanUp]
General MIDI Maps and Program Changes
"Demonstrate program change by setting up an organ instrument to play on."
[MIDIPort testProgramChange]
"Down-load a general MIDI patch for a 4-voice organ."
[MIDIPort setupOrgan. Cluster example1]
"Down-load a general MIDI patch for a 16-voice percussion ensemble."
[MIDIPort setupTunedPercussion. MIDIPort testAScale]
"Reset the GM map"
[MIDIPort resetEnsemble]
MIDI Input
"Open MIDI, try to read something--dump it to the transcript."
[MIDIPort testInput]
"Execute this to end the input test"
[MIDIPort testInputStop]
"Get the port''s pending input."
[MIDIPort default eventsAvailable]
[MIDIPort default readAll]
[MIDIPort default input]
[MIDIPort default resetInput]
"Set up a MIDI dump object as a dependent of the input port. Dump for 30 seconds,
then turn off. The default update: method just dumps the MIDI packet into the transcript;
customize this by writing your own update: method."
[MIDIPort dumpExample]
"Set up uncached controller reading and dump input to the transcript."
[MIDIPort testControllerInput]
[MIDIPort testInputStop]
"Set up uncached controller reading--read controllers from lo to hi as an array and print it;
stop on mouse press."
[MIDIPort testControllerCachingFrom: 48 to: 52]
Real-time Performance Tests
"Play ''num'' random pitches spaced ''dur'' msec apart."
"This test creates the messages and does the scheduling right here."
[MIDIPort testRandomPlayLowLevel: 64 dur: 80]
"Play a roll of ''num'' notes spaced ''dur'' msec apart."
"This test creates the messages and does the scheduling right here."
[ObjectMemory compactingGC.
MIDIPort testRollLowLevel: 20 dur: 80]
[ObjectMemory compactingGC.
MIDIPort testRollLowLevel: 200 dur: 40]
Continuous Control Tests
"Demonstrate control commands by playing a note and making a crescendo with the volume pedal."
[MIDIPort testControlContinuous]
"Demonstrate pitch-bend by playing two notes and bending them."
[MIDIPort testBend]
Utilities
"ANO"
[MIDIPort allNotesOff]
"Close down and clean up."
[MIDIPort cleanUp]