The "performance" of events takes place via voice objects. Event properties are assumed to be independent of the parameters of any synthesis instrument or algorithm. A voice object is a "property-to-parameter mapper" that knows about one or more output or input formats for Smoke data. There are voice "device drivers" for common file storage formats--such as note lists file formats for various software sound synthesis packages or MIDI files--or for use with real-time schedulers connected to MIDI or OSC drivers. These classes can be refined to add new event and signal file formats or multilevel mapping (e.g., for MIDI system exclusive messages) in an abstract way.
Voice objects can also read input streams (e.g., real-time controller data or output from a coprocess), and send messages to other voices, schedulers, event modifiers or event generators. This is how one uses the system for real-time control of complex structures.
The actual property-to-parameter mapping is often controlled by a dictionary that takes the properties of an event and creates a statement of command for some output format. this allows the user to customize the voices at run-time.
Voices and Schedulers
Some voices are "timeless" (e.g., MIDI file readers); they operate at full speed regardless of the relative time of the event list they read or write. Others assume that some scheduler hands events to their voices in real time during performance. The EventScheduler does just this; it can be used to sequence and synchronize event lists that may include a variety of voices.
Examples
Create a random event list and write it out to notelist files in any of several formats. Edit the file.
[CmixVoice randomExampleToFileAndEdit]
[CmusicVoice randomExampleToFileAndEdit]
[CsoundVoice randomExampleToFileAndEdit]
[SuperColliderVoice randomExampleToFileAndEdit]
Create an event list of 20 notes with semi-random values and play it on a MIDI output voice.
[(EventList randomExample: 20) playOn: MIDIVoice default]
Use the same random list creation method, but add three lists in parallel.
[((EventList newNamed: #pRand)
addAll: (EventList randomExample: 40);
addAll: (EventList randomExample: 40);
addAll: (EventList randomExample: 40))
playOn: MIDIVoice default]
Read MIDI, turn it into a Siren event list, and play it. (BROKEN in 7.2)
[((MIDIFileReader scoreFromFileNamed: 'BWV775.MID') asEventList) play]
Complex Multimedia Example: Generate and play a mixed-voice event list; a cloud plays alternating notes on MIDI and built-in synthesis, and a list of action events flashes screen rectangles in parallel.
[ | el |
el := (Cloud dur: 6 "Create a 6-second stochastic cloud"
pitch: (48 to: 60) "choose pitches in this range"
ampl: (40 to: 70) "choose amplitudes in this range"
"select from these 2 voices"
voice: (Array with: (MIDIVoice default) with: (OSCVoice default))
density: 5) eventList. "play 5 notes per sec. and get the events"
"add some animation events"
el addAll: ActionEvent listExample.
el play] "and play the merged event list"