Load
First, use load to load the first example into Stella.
[The opus1.cm example file is located in the same directory as this tutorial. On a Macintosh you can load files using the "Load..." File menu item.. If you prefer typing file names remember that the directory delimiter is `:' rather than `/' on the Mac.]
Stella [Top Level]: load /Lisp/cm/doc/tutorials/stella/opus1 Loading /Lisp/cm/doc/tutorials/stella/opus1.cm Syntax set to MIDI Stella [Top-Level]:load loads a Lisp file. By default load looks for .cm archive files. Archive files contain Lisp code that recreates the archived objects.
Stella [Top-Level]: list Top-Level: 1. #<THREAD: Pulse> 2. #<ALGORITHM: Sinus> Stella [Top-Level]:If list is invoked without any arguments the current focus object is listed. The current focus is Top-Level, a system container holding all the named objects currently defined. There are currently two objects, a thread named Pulse and an algorithm named Sinus. list prints the name of the listed container in the first column, and each indented line shows the position and the object at that position in the listed container (the #<> delimiters always indicate an object of some sort.
Stella [Top-Level]: show pulse,sinus Object: Pulse Type: Thread Status: Normal Objects: 80 Start: unset Object: Sinus Type: Algorithm Status: Normal Code: (algorithm sinus midi-note (length 80 amplitude 0.5 rhythm 0.1 duration 0.1) (setf note (round (rescale (sin (* 2pi (/ count length) 4)) -1 1 20 100)))) Stella [Top-Level]:Show prints information about an object. The first three lines include the name of the object, its class and its current status (an object might be "hidden", "deleted" or "frozen", etc.) Following the basic information comes information specific to the type of object shown. For threads, this information includes the current output start time and the number of sub-objects that the thread contains. For algorithms, the information includes a "pretty printed" version of the algorithm's program.
Stella [Top-Level]: open midi port a Stream: #<Port: Midi to A>. Stella [Top-Level]: mix pulse Start time offset: (<cr>=None) 1 Stella [Top-Level]: [Sound starts after 1 second. Wait until the example is though before continuing.] Stella [Top-Level]: mix sinus 1 [Sound starts after 1 second.] Stella [Top-Level]:
Here are a few examples of using open to initialize various types of event streams:
Open MIDI on port A: open midi port a Open a CLM sound file: open /zap/test.snd srate 44100 Open a CMN postscript file: open aaa.eps size 16 metronome 120 Open a CSound score file: open test.sco orchestra "test.orc" Open a CLM score file: open test.clm
There are several commands similar to mix. Seq processes objects in sequential, rather than parallel, order. Seq prompts for the number of times to sequence the objects and an optional pause amount between repetitions. As you may have guessed, seq uses a thread to process its material. The commands Write, Swrite, Listen, and Slisten are also similar to Mix and Seq. They are available for historical reasons, and require that you distinguish between types of streams. Avoid using them because they will be removed in some future release.
Stella [Top-Level]: mix pulse,sinus Start time offset: (<cr>=None) <cr> [output messages elided] Stella [Top-Level]:Now offset Sinus by two seconds relative to Pulse:
Stella [Top-Level]: mix pulse,sinus Start time offset: (<cr>=None) * Start time offset for Pulse: (<cr>=None) <cr> Start time offset for Sinus: (<cr>=None) 2 [output messages elided] Stella [Top-Level]:Now repeat the example, but specify offsets directly on the command line:
Stella [Top-Level]: mix pulse,sinus 0,2 [output messages elided] Stella [Top-Level]:Start time offsets specified to Mix and Seq affect the current processing pass only. A single offset becomes the global offset for all the objects. A sequence of offsets (delimited by comma) will be applied to a corresponding sequence of object in left to right order. If * is specified you will be prompted for each offset. In addition to their obvious compositional role, offsets are useful for solving problems related to real time processing. Sometimes a complex algorithm will not be able to "keep up" with the speed at which it schedules output. Providing a start time offset will give the algorithm that much "head start" before output starts sounding.
In adddition to clock time, output streams may have time scalers associated with them. This scaler is normally set to 1, so time can usually be thought of as clock time.
When musical processing is initiated by commands like mix or seq, the associated event stream first resets its clock to zero before musical events are processed. As each event is processed its time slot is "stamped" with the current time. Every object in Stella has a time slot as one of its basic attributes. Instead of setting time directly, the composer sets either start time offsets for containers or relative time increments for musical data, using the rhythm slot that all data objects possess. A rest object may be used anywhere to increment time without sound output.
In this next example we look inside Pulse, a thread containing eighty midi notes.
Stella [Top-Level]: list pulse Pulse: 1. #<MIDI-NOTE | C5| 0.100| 0.100| 0.250| 0> 2. #<MIDI-NOTE | D4| 0.100| 0.100| 0.321| 0> [listing elided] 49. #<MIDI-NOTE | G4| 0.100| 0.100| 0.250| 0> 50. #<MIDI-NOTE |GS4| 0.100| 0.100| 0.321| 0> More unlisted objects. Stella [Top-Level]:Note that when midi-note objects are listed they do not look like threads or algorithms. The format of a midi-note display is:
#<MIDI-NOTE |note|rhythm|duration|amplitude|channel>Note is the frequency of the midi note, rhythm is the time increment to the next note, duration is the amount of time the note sounds, amplitude is a logical amplitude 0.0<=1.0 or MIDI velocity 0<=127 and channel is its MIDI channel >=0. See the midi-note for a full explanation of midi notes.
Only certain types of objects, called containers, have names. Howver, all objects have a position relative to some container, if only the Top-Level container. The focus object provides a context for selecting objects by position. For example, the contents of Pulse can also be listed by specifying Pulse's position in the current focus container (Top-Level):
Stella [Top-Level]: list 1 Pulse: 1. #<MIDI-NOTE | C5| 0.100| 0.100| 0.250| 0> 2. #<MIDI-NOTE | D4| 0.100| 0.100| 0.321| 0> [listing elided] Stella [Top-Level]:In general, we can replace the name of an object by its path relative to another object. So in the examples that follow the index 1 may be substituted for the name Pulse and 2 may be substituted for the name Sinus as long as we remain inside the Top-Level container.
Stella [Top-Level]: list 1[1] Pulse: 1. #<MIDI-NOTE | C5| 0.100| 0.100| 0.250| 0> Stella [Top-Level]:Sub-object references are specified using an array-like syntax
container[ref]where container is the name (or position) of a container and ref is the sub-object specification. For example, Pulse[1]is a reference to the first object in Pulse, and Pulse[1:10,15] is a reference to objects 1 to 10 and 15. Each element of the reference inside [] can be specified using (up to) four fields delimited by colon:
[low:high:step:width]where low is the low bound of the reference, high is the inclusive upper bound, step is the stepping increment between low and high, and width is the number of sub-objects to reference in parallel.
It is only necessary to specify as many fields as are needed to adequately describe the reference. The editor currently distinguishes between five types of references:
Reference fields may be elided if the default value for that field applies, in which case only the delimiter for that field need be specified. The default values for the fields are 1:*:1:1. So, for example, ::2 means the same as 1:*:2 and defines an iteration over every other sub-object; :56::4 defines a four element group ranging over the first fifty-six objects.
Stella [Top-Level]: list 1[1:3] Pulse: 1. #<MIDI-NOTE | C5| 0.100| 0.100| 0.250| 0> 2. #<MIDI-NOTE | D4| 0.100| 0.100| 0.321| 0> 3. #<MIDI-NOTE | C5| 0.100| 0.100| 0.393| 0> Stella [Top-Level]:To list every third element between the first and the tenth elements of Pulse:
Stella [Top-Level]: list Pulse[1:10:3] Pulse: 1. #<MIDI-NOTE | C5| 0.100| 0.100| 0.250| 0> 4. #<MIDI-NOTE | G4| 0.100| 0.100| 0.464| 0> 7. #<MIDI-NOTE |GS4| 0.100| 0.100| 0.679| 0> 10. #<MIDI-NOTE | C4| 0.100| 0.100| 0.321| 0> Stella [Top-Level]:To list the first, fifth through tenth, and sixteenth element of Pulse:
Stella [Top-Level]: list Pulse[1,5:10,16] Pulse: 1. #<MIDI-NOTE | C5| 0.100| 0.100| 0.250| 0> Pulse: 5. #<MIDI-NOTE | D4| 0.100| 0.100| 0.536| 0> 6. #<MIDI-NOTE | G4| 0.100| 0.100| 0.607| 0> 7. #<MIDI-NOTE |GS4| 0.100| 0.100| 0.679| 0> 8. #<MIDI-NOTE |GS4| 0.100| 0.100| 0.750| 0> 9. #<MIDI-NOTE | C4| 0.100| 0.100| 0.250| 0> 10. #<MIDI-NOTE | C4| 0.100| 0.100| 0.321| 0> Pulse: 16. #<MIDI-NOTE |GS4| 0.100| 0.100| 0.750| 0> Stella [Top-Level]:To compare the first two objects with the last two:
Stella [Top-Level]: list 1[1:2], 1[end-2:end] Pulse: 1. #<MIDI-NOTE | C5| 0.100| 0.100| 0.250| 0> 2. #<MIDI-NOTE | D4| 0.100| 0.100| 0.321| 0> Pulse: 79. #<MIDI-NOTE |AS4| 0.100| 0.100| 0.679| 0> 80. #<MIDI-NOTE | G4| 0.100| 0.100| 0.750| 0> Stella [Top-Level]:To list from the seventy-fifth position to the end of Pulse:
Stella [Top-Level]: list Pulse[75:*] Pulse: 75. #<MIDI-NOTE | C5| 0.100| 0.100| 0.393| 0> 76. #<MIDI-NOTE | G4| 0.100| 0.100| 0.464| 0> 77. #<MIDI-NOTE |AS4| 0.100| 0.100| 0.536| 0> 78. #<MIDI-NOTE | C5| 0.100| 0.100| 0.607| 0> 79. #<MIDI-NOTE |AS4| 0.100| 0.100| 0.679| 0> 80. #<MIDI-NOTE | G4| 0.100| 0.100| 0.750| 0> Stella [Top-Level]:
Next Chapter
Previous Chapter
Table of Contents
Last Modified: 6-Mar-1998