Environment: Siren
An instance of a subclass of 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 an extensive test suite and demo in the class examples method and in the Siren outline view.
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.
Instance Variables:
Class Variables:
MIDI Commands Supported:
accessing
readProcess
inputData
status
device
Instance
Debug
UseSingleton
DefaultInputDevice
DefaultOutputDevice see above
0x9x pp vv -- note-on (x=channel, pp=pitch, vv=velocity)
0x8x pp vv -- note-off (x=channel, pp=pitch, vv=velocity)
0xCx cc -- program-change (x=channel, pp=pitch)
0xEx ll hh -- program-change (x=channel, ll=low 7 bits, hh=high 7 bits)
0xBx cc dd -- control change (x=channel, cc=controller, dd=data)
isActive
Answer whether the receiver is active.
reader
Answer the receiver's read process
resetInput
Reset the receiver's Q of input data.
control commands
Turn all MIDI notes off using the channel message 123.
allNotesOffVerbose
Turn all MIDI notes off (the verbose way).
controlChange: chan controller: controller to: value
Send out a control-change command now.
pitchBend: chan to: value
Send out a pitch-bend command at the given time.
programChange: chan to: value
Send out a program-change command at the given time.
sysex: command
Send out a MIDI system exclusive data packet at the given time.
open/close
Close MIDI.
open
Open the MIDI driver -- start the lower-level driver up.
openInput
Open the MIDI driver -- start the lower-level driver up.
openInput: which
Open the MIDI driver -- start the lower-level driver up.
openOutput
Open the MIDI driver -- start the lower-level driver up.
openOutput: which
Open the MIDI driver -- start the lower-level driver up.
reset
Reset the port.
ioctl
Answer the number of events in the input Q.
hasBuffer
Answer whether the MIDI driver has a time-stamped output buffer.
hasClock
Answer whether the MIDI driver has its own clock.
hasControllerCache
Answer whether the MIDI driver supports a controller data buffer.
hasDurs
Answer whether the MIDI driver supports a 1-call note-on/off command.
readLoop
polling or waiting loop
startControllerCaching
Start caching MIDI controller in the driver.
startMIDIEcho
Start echoing MIDI input from the driver.
startMIDIInput
Start the polling loop (or semaphore waiter) MIDI input.
stopControllerCaching
Stop caching MIDI controller in the driver.
stopMIDIEcho
Stop echoing MIDI input from the driver.
stopMIDIInput
Stop signalling the read semaphore on MIDI input.
initialize release
Setup the receiver's instance variables.
release
Release--break and dependencies on the error value.
read/write
Read the data from the receiver into the argument (a MIDIPacket). Answer the number of data bytes read.
nextEventInto: anEventAssociation
Record via the receiver into the argument.
nextMessage
Answer the first (length -> bytes) association from the input data collection.
play: aPitch dur: aDur amp: anAmp voice: aVoice
Play a note (on/off message pair) with the given parameters on the receiver.
play: streamID pitch: aPitch dur: aDur amp: anAmp voice: aVoice
Play a note (on/off message pair) with the given parameters on the receiver.
playOff: streamID pitch: aPitch amp: anAmp voice: aVoice
Play a note-on command with the given parameters on the receiver.
playOn: streamID pitch: aPitch amp: anAmp voice: aVoice
Play a note-on command with the given parameters on the receiver.
put: data length: size
Send the argument data to the receiver now.
readController: index
Read the given controller value.
readControllersFrom: lo to: hi into: array
Read a range of controllers
MetaClass: MIDIPort class
message tests
Demonstrate control commands by playing a note and making a crescendo with the volume pedal.
testBend
Demonstrate pitch-bend by playing two notes and bending them.
testControlContinuous
Demonstrate control commands by playing a note and making a crescendo with the volume pedal.
testProgramChange
Demonstrate program change by setting up an organ instrument to play on.
testSysex
Demonstrate system exclusive commands by loading the Santur scale
and playing a scale.
driver performance tests
Play 'num' random pitches (molto legato) spaced 'dur' msec apart.
testRandomPlayLowLevel: num dur: dur
Play 'num' random pitches spaced 'dur' msec apart.
testRollLowLevel: num dur: dur
Play a roll of 'num' notes spaced 'dur' msec apart.
output tests
Try to open and close the MIDI port.
testANote
Open MIDI, play a note.
testARandomNote
Open MIDI, play a note.
testAScale
Open MIDI, play a fast scale.
testInspect
Inspect a MIDI port.
testMouseMIDI
Open MIDI, play notes based on the mouse position.
testNoteOnOff
Open MIDI, play a note, and close it.
testOpenClose
Try to open and close the MIDI port.
testOutput
Open MIDI, play some random notes, and close it.
input tests
Set up a MIDI dump object as a dependent of the input port. Dump for 10 seconds,
then turn off. The default update: method just dumps the MIDI packet into the transcript;
customize this by writing your own update: method.
testInput
Open MIDI, try to read something--dump it to the transcript.
testInputStop
Execute this to end the input test
controller tests
Set up uncached controller reading--make a loop that reads and prints controller 48
twice a second (until you press the shift button).
testControllerCaching2
Set up uncached controller reading--read controllers 48-52 as an array and print it; stop on mouse press.
testControllerCachingFrom: lo to: hi
Set up uncached controller reading--read controllers from lo to hi (inclusive) as an array and print it;
stop on
Set up uncached controller reading--make a loop that reads and prints controller 48
40 times a second for 5 seconds.
utilities
MIDIPort allNotesOff
cleanUp
Close down and clean up all MIDI, sound IO, event lists, etc.
showInput
Open MIDI, wait to read something, then dump it to the transcript.
general MIDI patches
Set instruments 0-15 to the General MIDI name iname
setEnsemble: orch
Down-load a general MIDI patch for the given ensemble (a collection of
[chan -> name] associations).
setEnsembleInOrder: orch
Down-load a general MIDI patch for the given ensemble (a collection of symbolic keys
into the General MIDI voice map) mapping the first element to MIDI channel 1, etc.
setupDefaultGeneralMIDI
Down-load a general MIDI patch for a 16-voice percussion ensemble.
setupOrgan
Down-load a general MIDI patch for a 4-voice organ.
setupTunedPercussion
Down-load a general MIDI patch for a 16-voice percussion ensemble.
setupWindOrchestra
Down-load a general MIDI patch for a 16-voice wind ensemble.
examples
Select and execute the following for usage examples.
scaleFrom: lo to: hi in: dur
Answer array of (start dur pitch amp)
instance creation
Answer the class to use for MIDI
class initialization
Set up the dictionaries of commands, ioctl primitive selectors and arguments, and general MIDI maps.
initializeMIDITables
MIDIPort initializeMIDITables