About Siren MIDI

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]