Class: MIDIPort

Environment: Siren
Superclass: Siren.PortModel
Category: MusicIO-MIDI
Instance variables: inputData readProcess
Class variables: Streams
Imports: private MIDICommands.* private MIDIioctls.*
private GeneralMIDIMap.* private GeneralMIDIDrums.*

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:
readProcess The loop process to read input data.
inputData ByteArray)> The available data.
status #open or #closed
device my IO device's index

Class Variables:
Instance The sole instance, or nil.
Debug Debug mode prints all I/O to the Transcript.
UseSingleton whether to use a singleton instance (not necessary)
DefaultInputDevice the index in the driver of the default input device
DefaultOutputDevice see above

MIDI Commands Supported:
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)

accessing

input
Answer the receiver's Q of input 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

allNotesOff
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
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

eventsAvailable
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

initialize
Setup the receiver's instance variables.

release
Release--break and dependencies on the error value.

read/write

get: packet
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

functionExample
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

testRandomPlayHighLevel: num dur: dur
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

testAllNotesOff
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

dumpExample
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

testControllerCaching
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 press.

testControllerRecording
Set up uncached controller reading--make a loop that reads and prints controller 48
40 times a second for 5 seconds.

utilities

allNotesOff
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

setAllInstrumentsTo: iname
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

examples
Select and execute the following for usage examples.

scaleFrom: lo to: hi in: dur
Answer array of (start dur pitch amp)

instance creation

concreteClass
Answer the class to use for MIDI

class initialization

initializeData
Set up the dictionaries of commands, ioctl primitive selectors and arguments, and general MIDI maps.

initializeMIDITables
MIDIPort initializeMIDITables