To use this demo script, read through this text selecting the blocks enclosed in square brackets. The single character after the close-square-bracket (d,p, i, or db) denotes whether you should "do," "print," "inspect," or "debug" the block. (Typically, CTRL-D means do-it, CTRL-P means print-it, and CTRL-Q means inspect-it.)
Set-up
Test the MIDI and sound I/O drivers.
[SirenUtility open] d
See also the section above on "Siren Set-up."
MusicMagnitudes
Print these to see what kinds of music magnitude representations and operations are supported.
[440 Hz asSymbol] p "--> 'a3' pitch"
[(1/4 beat) asMsec] p "--> 250 msec"
[#mf ampl asMIDI] p "--> 70 vel"
['a4' pitch asMIDI] p
[('a4' pitch + 100 Hz) asMIDI] p
[('a4' pitch + 100 Hz) asFracMIDI] p
['mp' ampl + 3 dB] p
[('mp' ampl + 3 dB) asMIDI] p
Event Creation Messages
Create a `generic' event using a class instance creation message.
MusicEvent duration: 1/4 pitch: 'c3' ampl: 'mf'
Create one with added properties.
(MusicEvent dur: 1/4 pitch: 'c3') color: #green; accent: #sfz
Terse format: concatenation (with ',') of music magnitudes
[440 Hz, (1/4 beat), 44 dB] i
(#c4 pitch, 0.21 sec, 64 velocity) voice: IOVoice default
Event Lists
Verbose form using a class instance creation message;
a chord is simply a set of events at the same time.
(EventList newNamed: #Chord1)
add: ((1/2 beat), 'd3' pitch, 'mf' ampl) at: 0;
add: ((1/2 beat), 'fs3' pitch, 'mf' ampl) at: 0;
add: ((1/2 beat), 'a4' pitch, 'mf' ampl) at: 0
Play a scale created with a class message.
[(EventList scaleExampleFrom: 48 to: 60 in: 1500) play] d
Create 64 random events with parameters in the given ranges, play it on the default output voice.
[(EventList randomExample: 64 "make 64 notes"
from: ((#duration: -> (50 to: 200)), "duration range in msec"
(#pitch: -> (36 to: 60)), "pitch range in MIDI keys"
(#ampl: -> (48 to: 120)), "amplitude range in MIDI velocities"
(#voice: -> (1 to: 1))) "play all on voice 1"
) play] d
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] d
Play two-voice "counterpoint" on the note list score file voices.
[ | vox list |
vox := CsoundVoice onFileNamed: 'test.cs'.
list := (EventList newNamed: #pRand)
addAll: (EventList randomExample: 20);
addAll: (EventList randomExample: 20).
vox play: list.
vox close.
(Filename named: 'test.cs') edit.] d
Here's another example of creating a simple melody
[(EventList named: 'melody'
fromSelectors: #(pitch: duration:)
values: (Array with: #(c d e f g)
with: #(4 8 8 4 4) reciprocal)) play] d
You can also create event lists with snippets of code such as the following whole-tone scale.
[ | elist |
elist := EventList newAnonymous.
1 to: 12 do:
[ :index |
elist add: (1/4 beat, (index * 2 + 36) key, 'mf' ampl)].
elist play ] d
Event lists can also be nested into arbitrary structures, as in the following group of four sub-groups
[ (EventList newNamed: 'Hierarchical/4Groups')
add: (EventList randomExample: 8
from: ((#duration: -> (60 to: 120)), (#pitch: -> (36 to: 40)), (#ampl: -> #(110)))) at: 0;
add: (EventList randomExample: 8
from: ((#duration: -> (60 to: 120)), (#pitch: -> (40 to: 44)), (#ampl: -> #(100)))) at: 1;
add: (EventList randomExample: 8
from: ((#duration: -> (60 to: 120)), (#pitch: -> (44 to: 48)), (#ampl: -> #(80)))) at: 2;
add: (EventList randomExample: 8
from: ((#duration: -> (60 to: 120)), (#pitch: -> (48 to: 52)), (#ampl: -> #(70)))) at: 3;
play ] d
Smalltalk methods can also process event lists, as in this code to increase the durations of the last notes in each of the groups from the previous example.
[ (EventList named: 'Hierarchical/4Groups') eventsDo:
[ :sublist | | evnt | "Remember: this is hierarchical, to the events are the sub-groups"
evnt := sublist events last event. "get the first note of each group"
evnt duration: evnt duration * 8]. "multiply the duration by 4"
(EventList named: #groups) play ] d
...or the following to take the scale and make it slow down
[ | elist |
elist := EventList scaleExampleFrom: 60 to: 36 in: 1500.
1 to: elist size do:
[ :index | | assoc |
assoc := elist events at: index.
assoc key: (assoc key * (1 + (index / elist events size)))].
elist play ] d
Siren Scheduler
Reset
[EventScheduler initialize]
Here's how to use the event scheduler explicitly.
[EventScheduler instance addClient: (EventList randomExample: 20) in: (500 msec).
EventScheduler instance run] d
Flush and close down the scheduler
[EventScheduler instance interrupt; flush] d
Action events have arbitrary blocks of Smalltalk code as their "actions." This example creates a list of action events that flash random screen rectangles.
[ActionEvent playExample] d
Complex Multimedia Example
[ | 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"
voice: #(1) "leave the 1 nil for now"
density: 5) eventList. "play 5 notes per sec. and get the events"
1 to: el events size do: "Now plug different voices in to the events"
[ :ind | "ind is the counter"
(el events at: ind) event voice:
(ind odd "alternate between two voices"
ifTrue: [MIDIVoice default]
ifFalse: [OSCVoice default])].
"add some animation events"
el addAll: ActionEvent listExample.
el play] d "and play the merged event list"
EventGenerators
A cluster is the simplest event generator.
[(Cluster dur: 2.0
pitchSet: #(48 50 52 54 56)
ampl: 100
voice: 1) play]
Chord object can give you an event list.
[((Chord majorTetradOn: 'f4' inversion: 0) duration: 1.0) edit]
[((Chord majorTetradOn: 'f4' inversion: 1) duration: 1.0) play]
Create and play a simple drum roll--another 1-D event generator.
[((Roll length: 2000 rhythm: 50 note: 60) ampl: 80) play] d
Play a 6-second cloud that goes from low to high and soft to loud.
[(DynamicCloud dur: 6
pitch: #((30 to: 44) (50 to: 50)) "given starting and ending selection ranges"
ampl: #((20 to: 40) (90 to: 120))
voice: (1 to: 4)
density: 15) play "edit"] d
Play a selection cloud that makes a transition from one triad to another.
[(DynamicSelectionCloud dur: 6
pitch: #( #(48 50 52) #(72 74 76) ) "starting and ending pitch sets"
ampl: #(60 80 120)
voice: #(1)
density: 12) play]
Mark Lentczner's bell peals ring the changes.
[(Peal upon: #(60 65 68)) play] d
EventModifiers
One can apply functions to the properties of event lists, as in the following example, which creates a drum roll and applies a crescendo modifier to it.
[ | roll decresc |
roll := ((Roll length: 3000 rhythm: 150 note: 60) ampl: 120) eventList.
decresc := Swell new function: (ExponentialFunction from: #((0 1 4) (1 0))).
decresc applyTo: roll.
roll play]
MIDI Control
Open MIDI, play notes based on the mouse position (x --> dur; y --> pitch) until mouse down.
[MIDIPort testMouseMIDI] d
Demonstrate program change by setting up an organ instrument to play on.
[MIDIPort testProgramChange] d
Down-load a general MIDI patch for a 16-voice percussion ensemble.
[MIDIPort setupTunedPercussion. MIDIPort testAScale] d
Reset the GM map
[MIDIPort resetEnsemble]
Demonstrate control commands by playing a note and making a crescendo with the volume pedal.
[MIDIPort testControlContinuous] d
Demonstrate pitch-bend by playing two notes and bending them.
[MIDIPort testBend] d
The Siren Graphics Framework
Display rectangles in a display list view -- test zoom and scroll.
[DisplayList rectangleExample]
An alternative layout (which I prefer) places the zoom bars on the top and right. look at,
[DisplayListView open4SquareOn: (DisplayList rectanglesX: 2000 byY: 2000)]
Display random strings
[DisplayList stringExample]
Display *lots* of random poly-lines in a very large space.
[DisplayList polylineExampleHuge]
Show the result of the IndentedListLayoutManager
[DisplayListView colorClassListExample]
Music Notations
Open a sequence view on a random event list.
[TimeSequenceView randomExample] d
Try the picth-time layout
[PitchTimeView randomExample]
[PitchTimeView openOnEventList: (EventList scaleExampleFrom: 48 to: 84 in: 10000)]
Open a pitch/time view on a *very long* 3-stream event list.
[PitchTimeView randomExampleLong]
A more complete example is Hauer-Steffens notation, which has a clef and staff lines as in common-practise notation.
[HauerSteffensView randomExample]
[(EventList scaleExampleFrom: 36 to: 48 in: 3000) edit]
Sound Views
[SoundView openOn: SampledSound sawtooth]
[(SampledSound sweepDur: 10.0 rate: 44100 from: 10 to: 400 chans: 1) edit]
Read in a sound from a file
[(SampledSound fromFile: 'Data/unbelichtet.aiff') edit]
Utilities
ANO
[MIDIPort allNotesOff]
Close down and clean up.
[MIDIPort cleanUp]