Your Basic Siren Demo Script

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

Create and view some example sounds
   [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]