LMUSe version 0.7b
12/24/98
david sharp
dsharp@interport.net

Note: The information on this page applies to the DOS version of LMUSe, not (necessarily) to the Java version

To LMUSe intro / download page



c o n t e n t s

Process Overview
L-Systems (general)
Context Sensitivity and Stochastic Rules
Symbol Alphabet
Commands specific to music
Direction commands
Movement / Play commands
State stack commands
Increment and Decrement commands
Colors and intrument timbre commands
Rule File Format

Map
Menus
Production menu
Map
Edit Menu
Mutate menu
Options menu
Map Files
Play Screen
Scales
Rules Files Compatibility
Command Line parameters
Troubles
Credits


Process Overview:
The basic sequence of operations to make music from a set of transformation rules is:
  1. Load a Rule file
  2. Make a "production string" from the axiom and rules.
  3. Interpret the production string as music
  4. Play the music.
"Load, Make and Interpret" takes you through all 4 steps.


L-Systems
L-systems were invented by Aristid Lindenmayer and others to model the development of living organisms by recursively applying a set of transformation rules to a simple initial string of symbols and interpreting the resulting (usually more complex) string of symbols as structure elements of the organsism. L-systems also provide a concise grammar for generating classic fractals like von Koch snowflakes, dragon curves and space filling curves, as well as for modeling organic growth.

An L-system starts in generation 0 with a simple string of symbols, and for each subsequent generation, symbols are replaced by new symbols or strings of symbols according to a set of rules. The idea is easiest to see by example. Say our starting string, (called the 'axiom'), is just

A

The replacement rules show how each symbol in the current generation should be replaced. Two simple rules (for example) are

A=B
B=BA


According to the first rule, every 'A' in the current generation should be replaced by a 'B', and each 'B' in the current generation will be replaced with 'BA' in the next generation.

generation 0: A (the axiom)
generation 1: B (the A was replaced with B )
generation 2: BA (the B of generation 1 was replaced with BA)
generation 3: BAB (the B of gen 2 replaced with BA and the A replaced with B)
generation 4: BABBA

Note how the replacements for each generation occur in 'parallel'. We will call the number of generations the "recursion level". When the symbols are interpreted as graphics commands, reading from left to right, the resulting pictures can get very complex. In most L-system implementations the symbol 'F' is interpreted as a command to "draw a line". Because of the recursive way the production string is made, L-systems are a concise way to generate the 'self-similar' nature of fractals.

The purpose of LMUSe is to interpret the resulting symbol strings as musical directions. For example, 'F' is interpreted as "play the note". (See 'Symbols' for the complete list of interpretations) LMUSe starts with a 'rule file' which contains an axiom string, a set of replacement rules, a default recursion level, and another parameter the 'angle' (a number of the specially interpreted symbols have to do with changing the drawing turtle's direction and orientation).

#=== Sample Rules file ====
5 #recursion level
10 #angle
AB #axiom
A=+FB # first rule
B=AF # second rule
#===========================

In LMUSe, '#' is a special 'comment' symbol. Everything on a line after a '#' is ignored. The rules are applied to the axiom to make a 'production string' (the first generation). The rules are then applied to that production string in turn, making a new production string (the second generation), which is run through the rules, the process repeated "recursion level" number of times. The result at the end is just called the "production string".

By itself, the production string is just a string of symbols. The production string is then 'interpreted'. That is, the symbols are mapped to drawing and/or music playing commands.

Context Sensitivity and Stochastic Rules

Rules like A=AB, and X=FB^&F, are called 'context-free' because the symbol to be replaced (on the left of the '=') is replaced by the right side of the '=' no matter what other symbols happen to surround the symbol to be replaced. 'Context-sensitive' rules are rules whose application does depend on the surrounding symbols. In LMUSE, context-sensitivity of a rule is denoted with '>' or '<' directly after the symbol to be replaced and before the '='.

For examples:
A>B=AB # "if B is to the immediate right of A replace the A with AB".
A "if F is to the left of A, replace the A with FFAB"

In LMUSE rules, the symbol to be replaced is always the first symbol in the rule's line. ('>' and '<' "point" to the "context side" of the symbol to be replaced.) If the above pair of rules were in the same rules file and both conditions were true, (for example if the production contained the sequence "FAB") only the first rule would be actually applied. This is because once a rule is applied to a symbol, all following rules for that symbol are ignored. Also, "A is to the left of B" is True if all that separates A and B is a number or a number in parentheses, or, of course, if A is directly adjacent to B.

To combine both '<', and '>' in a single rule condition, the two conditions must be in that order so that:

AC=X

would only match the sequence BAC (B to the left and C to the right), and X would replace the A.


LMUSe also implements 'stochastic rules'.

simply replaces every occurence of A by BBA.

A(.5)=BBA

will replace A with BBA only 50% of the time. Just which particular A's will be replaced by BBA is randomly determined by LMUSe. The pair of rules:

A(.5)=BBA
A=ABA

will replace A with BBA 50% of the time, but otherwise (the other 50% of the time) A is replaced with AAB. The order of these two rules is important. Reversing them:

A=ABA
A(.5)=BBA

will always replace A with ABA. This is because the first (A=ABA) is not a stochastic rule (no probability in parentheses) and since it comes first, it is applied. Once a rule is applied to a symbol, the rest of the rules for that symbol are skipped, so the second line has no effect at all.

To have three stochastic rules each with a probability of 1/3, you would write:

A(.33)=BBA
A(.5)=ABA
A=BABB

The way it works is, the probability in parentheses is the probability that the rule will be applied if LMUSE gets to that rule, and the rules are looked at sequentially. That is, there is a .33 probability that the first rule will be applied. If it isn't applied (probability .67), then the second rule is attempted. Half the time the second rule is attempted, it is applied. That is 1/2 of .67 =.335 probability that the second rule will be applied. And finally, if and only if neither of the first two are applied, the last rule is applied. Again, once a rule is applied to a symbol, following rules are skipped. The last rule, without a stochastic condition in parentheses, guarantees that at least one of the three rules will be applied. If the last rule was, instead:

A(.5)=BABB

then 1/6 of the time the last rule would be applied, leaving another 1/6 of the time when A would not be transformed at all.

To combine a stochastic condition with a context-sensitive condition, the stochastic condition must come at the end (after the contexts):

FB(.5)=FF

Any combination not in the right order will match up to, but not including, the first condition that is recognized as out of order going from left to right.

F(.5)B=FF

would test for the probablility ("toss the coin") since it is OK to have a probability directly follow the symbol to be replaced, but then the two context conditions will be ignored.

Stochastically applied rules only have their random effect as the production string is being built. Once the production string is done you would have to do another 'Make' to see any difference due to the randomness. LMUSe transformation rules can contain another type of randomness. The '~' (tilde) changes, randomly, the current turtle state's direction. And '~(x)' changes the direction randomly up to a maximum of x degrees. The '~' does its 'work' at the time of interpretation and will give (probably) different results every time the production string is interpreted. To avoid these differences between interpretations, you can do 'ReMap' instead of 'Remake'.

The State and Stacks
In interpreting the production string, the string is treated as sequence of commands to a 'turtle'. These commands alter the turtle's state and/or cause the turtle to draw or make sound.

In LMUSe, the turtle's state consists of the turtle's position (x, y, and z coordinates), a 'forward' vector telling it what direction it is facing, an 'up' vector tells what direction the top of its head is pointing, and a 'left' vector telling what direction is to the turtle's left. The state also holds the current 'length' and 'thickness', color or instrument timbre, the size of the basic turning angle, and which map the turtle is using to convert its current state into pitches, durations, and volumes. In addition, the state holds what 'time' it is (when the notes it is making are to be played), and how far to transpose pitches.

Each of these components of the turtle's state can change and 'develop' as the production string is interpreted.

There is only one turtle, so in order for it to make branching structures, or polyphonic musical lines, it needs some sort of memory of where it has been so that it can go back to certain points in its development to pick up where it left off. The turtle's state stack acts like the turtle's memory. The command which tells the turtle to put its state onto the stack is called 'push', and a command which tells the turtle to retrieve its old state from the stack is called a 'pop'. When a state is 'pushed' it is always placed on 'top' of the stack, and when the turtle does a 'pop' it always gets its new state off the top of the stack ('last in, first out').

The symbol '{' is used to push the turtle's state and time and the accompanying 'pop state and time' symbol is '}'.

To push the state of the turtle, but not time (that is, so that a 'pop' will send the turtle back to where it was, but not back in time), you use '[', and naturally the accompanying pop symbol is ']'.

It is often convenient to just push and pop the time (to allow the turtle to continue developing, but parallel in time to its previous development). The LMUSe symbols for pushing and popping just the time are '\' (push) and '/' (pop).


The LMUSe Symbol Alphabet

Most of this list was 'cut and pasted' from Laurens Lapre's lparser.txt

Commands specific to music

t(x) transpose up (+x ) or down (-x ) by x semitones
t transpose 0
d(x) multiply note durations by x
d multiply note durations by 1.0 (cancels d(x))
v(x) multiply velocities (volume) by x
v multiply velocities by 1.0 (cancels v(x))
*(x) write to MIDI channel x
* write to MIDI channel 0
m(x) interpret using map number x

also see the T(x), D(x) , and V(x) commands under Stack commands.

Direction commands

+ turn left around up vector
+(x) turn x degrees left around up vector
- turn right around up vector
-(x) turn x degrees right around up vector
& pitch down around left vector
&(x) pitch x degrees down around left vector
^ pitch up around left vector
^(x) pitch x degrees up around left vector
< roll counter clockwise around forward vector
<(x) roll x degrees left around forward vector
> roll clockwise around forward vector
>(x) roll x degrees clockwise around forward vector
| turn 180 degrees around up vector
% roll 180 degrees around forward vector
$ roll until horizontal
~ turn/pitch/roll in a random direction
~(x) turn/pitch/roll in random direction to a maximum of x degrees

Movement / Play commands

F draw full length forward

play

F(x) draw x length forward

play

Z draw half length forward

play

Z(x) draw x length forward

play

f move forward full length, draw within {}

play within {}, otherwise rest

f(x) move forward x, draw within {}

play within {}, otherwise rest

z move forward half length, draw if within {}

play within {}, otherwise rest

z(x) move forward x, draw if within {}

play within {}, otherwise rest

g move forward full length

rest

g(x) move forward x

rest

. don't move

Stack commands

[ push current state but not event time
] pop current state but not event time
{ push current state and time
{x push current state and time, writing to MIDI channel x
} pop current state and time
\ push just the time
\x push just time, writing to MIDI channel x
/ pop just the time.
only use '/' to pop a time that was 'pushed' with '\'
T(x) (*) push pitch transposition by x onto the transpose stack
D (*) pop transposition from the transpose stack
D(x) (*) push duration multiplier x onto the duration multiplier stack
D (*) pop duration multiplier from the duration multiplier stack
V(x) (*) push velocity multiplier x onto the velocity multiplier stack
V (*) pop velocity multiplier from the velocity multiplier stack
* The default is for the transpose stack and the duration and velocity multiplier stacks to be disabled. This is just to 'conserve' symbols. Enable them from the "Map dialog".

Increment/Decrement commands

" increment length (times 1.1)
' decrement length (times 1/1.1)
"(x)
'(
x)
multiply length with x
; increment angle (times 1.1)
: decrement angle (times 1/1.1)
:(x)
;(
x)
multiply angle with x
? increment thickness (times 1.4)
! decrement thickness (times 1/1.4)
?(x)
!(
x)
multiply thickness with x

Color / timbre-instrument commands

c increment color index

increments instrument program number

c(x) set color index to x

sets instrument program number to x

@ end of rules (optional)


Rule File Format

The format for rule files follows the format of Lparser. Each rule file must be organized in this order, line by line:

recursion level
angle (in degrees)
thickness (optional in LMUSe, required by Lparser)
axiom
transformation rule 1
transformation rule 2
more rules, one to a line

@ (end of rules marker, optional in LMUSe, required by Lparser)

In addition, the file can contain comments. Anything after "#" on a line is ignored by LMUSe.

An example:

# this whole line is ignored
4 # default recursion level
25 # basic angle of 25 degrees
50 # thickness is 50% of length
A # the axiom
A=+B^FA # rule 1
B=BBt(12)F # rule 2
@ # end


Menus
Production menu
(Also see Process Overview) Making the production string and interpreting can take a long time, depending on recursion level and how long the production string gets. You can cancel/abort a 'Make' or 'Interpret' with the ESC key or clicking the right mouse button . Depending on how far the interpretation gets, you may have enough to play.

From the production screen, you can save the drawing to a PCX file by hitting `CTRL-d'. Also, from the production screen or the play screen, you can do a `screen dump' to a PCX file by hitting `CTRL-p'.

Load, Make, and Interpret
Gets the name of the rule file to use, and makes the production string. Then it goes ahead and interprets the string and plays the result. Use this to load a file and make music with the least fuss. Pressing ESC interrupts and aborts the process.
Load Rules
Gets the name of a rule file and loads the rules into memory. (Doesn't make a production)
Make Production
Just makes the production string from axiom and rules already in memory. (But doesn't interpret or play it). Pressing ESC or clicking the right mouse button interrupts and aborts making the production string.
Interpret Production
Interprets an already made production string. You are asked how you want the production string interpreted. That is, what parameter should be mapped to pitch, what maps to note durations and note volume. Pressing ESC or clicking the right mouse button aborts the interpretting.
Remake and Interpret
Makes and interprets the production string using the rules which are currently in memory. Remake and Interpret also recalculates the necessary screen dimensions and state limits. Reinterpret (Remap) (see below) does not and so it is maybe safer to use Remake and Interpret, although it is more time consuming. Pressing ESC or clicking the right mouse button aborts/cancels the process.
Reinterpet (Remap)
Reinterpret the already made production string, going through the mapping process anew. Note that if the rule file contains stochastic rules, you will need to Remake the production string to get different results from rules's stochastic nature. Remap will just reinterpret the production. On the other hand, certain symbols, like '~', yield stochastic results during interpretation. Pressing ESC or clicking the right mouse button aborts the remapping.

Play
Go to the 'Play' screen to hear your interpreted production.

Save Rule File As
Saves current transformation rules, the rules in LMUSe's memory, to disk. The recursion level and basic angle included will be the ones current in LMUSe.

If the rules were originally loaded from disk, be aware that 'Save Rules' does not keep comments you may have added to the original file. In other words, those nice comments you put in to let you know what the rules are about will not be in the saved file. To keep the original file, save the rules with a modified name so the original file isn't overwritten.


Get Production
Read a previously saved production string from disk. Since this production string is already 'made', the only Production Menu opotions that make sense to use on it are 'Interpret' or 'Reinterpret/Remap'. ('Make' will make a new production string from whatever rules are currently in use which may have nothing to do with the production string you have loaded from disk. In this case the production string is overwritten and will no longer be in memory). When a production string is saved, the map parameters and the rule file angle are not saved, so when you 'Get' a production, you will have to either remember these or supply new ones (or use the defaults)
View/Save Production
Look at the current production string. Option to save the production string (as *.out).

Save MIDI
Saves your music as a (SMF format 1, multitrack) MIDI file. MIDI files are widely supportedby sequencing programs, sound cards, and web browsers on nearly every type of computer. There are utilities available for converting MIDI files into CSound scores and other formats.
Options available when you save a MIDI file:
  • Split Tracks by Program: With this off, LMUSe writes MIDI files just as they were interpreted, which means that the file may have multi-program tracks. Some sequencing programs and midi-file players don't treat such files very well. With this toggled to on (checked), tracks containing multiple programs (instruments) will be split up and each instrument is given its own MIDI channel. There is no limit to the number of tracks that might be written into the MIDI file.
  • Write info into MIDI file: Toggles writing certain LMUSe information (the rule file name, map file name, mutations, etc) into a text field in saved MIDI files. In some sequencers this field is visible as the name of track 0.
  • Save (number) Loop(s): Choose how many repetitions of the interpretation to save.

Load Map
Gets parameters (map, scale, etc) from a previously saved map file.
Save Map
Save parameters (maps, scales, etc) to a map file.

Play a MIDI file
Load and play a previously created MIDI file.
Stop MIDI - Ctrl-s
Stops the playing of a MIDI file.

DOS shell
Shell to DOS command prompt.

Quit
Quits LMUSe

Map menu
Map
Opens the map dialog. connections dialogFor the most part this is not necessary since you are automatically presented with this map dialog on every Interpret.

The map(s) determine how the L-system production string (the list of symbols resulting from the recursive rewriting of the axiom) is interpreted as notes to be played. The production string itself can contain directions as to which map should be used (the m(x) symbol; see Help/Symbols).

You can load a previously saved map with the 'Load Map' button. (See 'Map Files' below). If the map file does not contain a mapnumber, the map will be loaded into the currently viewed map.

In the Map dialog, the fields are all part of the map (except the basic angle) and will be saved as part of the map file (except the basic angle).

Click on the 'Pitch' box with the mouse and drag a line to the parameter you want to dictate the pitches to be played. Similarly for 'Durations' and 'Volume'. LMUSE keeps track of the x, y, and z coordinates of an interpreted production. At all times the interpretation has three directions: forward (where the line is headed), up, and left. These are unit vectors each with x, y, and z components. The difference between 'state length' and 'draw length' is that the 'state length' only changes with the length incrementing and decrementing commands (see Symbols under Help). The 'draw length' comes from the actual length being drawn (or not drawn) on the screen. The draw length is affected by the difference between F and F(5) for example, or the difference between F and Z. (see Symbols).

Use the three "spread" sliders to amplify the interpreted range of the parameters. For example, by making the "pitch spread" greater than 1.00, the mapped pitches will be spread out further from middle c. A pitch spread between 0 and 1.00 causes the mapped pitches to be squeezed closer to middle c. Basically, increasing the "spread" makes changes in pitch, duration, or volume more dramatic. A negative value for the spread `inverts' the map. For example, when the duration spread is positive and duration is mapped to `draw length', longer lines make for longer note durations, but if a negative value is chosen for the duration spread, longer lines will yield shorter notes.

The "Scale" button is for choosing a musical scale into which the generated notes are "forced".
How the notes are forced into a scale is determined with the scale function button. (see Help/Scales)

Multiply durations slider is for stretching or compressing all musical event times. Multiplying by a number greater than 1.0 stretches out the notes, while multiplying durations by a number less than 1.0 compresses all the notes. Similar to changing tempo .

"Use Transpose stack" enables "T(x) ... T" transpose stack.
"Factor stacks" enables the "D(x) ... D" and "V(x) ... V" duration and velocity multiplier stacks.
If you aren't using these constructs in a set of transformation rules, it is safest to turn this off (unchecked).

"Load a Map" loads a previously save map file.

Edit Menu

Edit
Spawns an external editor that you have picked. If there is a currently loaded rule file, the name of the rule file is passed to the editor as a command line parameter. When you quit the editor, you should be returned to LMUSe and the rule file is reloaded from disk. If, while you are using the editor, you change files to edit one other than the one currently loaded into LMUSe and you want to run that other file, you will have to load the other file explicitly. LMUSe has no idea of what you are actually doing in the editor.
Edit Memory Rules
Writes the rules from memory to a temporary file, then spawns an external editor to edit the temporary file.
Pick editor
LMUSE does not contain an editor of its own. To use the Edit function, you must specify an external DOS editor, hopefully one that accepts filenames as a command line parameter.. (And don't specify a Windows editor, like 'Write' or 'WinWord', etc).

Mutate Menu

Mutate CTRL-m
Makes a random change/mutation to the currently loaded rules. These mutations include things like appending one replacement string to another, changing directions in a rule, etc. Hitting 'Mutate' once may have no effect on the production or it may have a devastating effect. It is, after all, random. It is common, after mutating to try and make a production string only to have LMUSE tell you it ran out of string space. Also, on occasion interpreting mutated rules leads to some arithmetic exception which I have not succeeded in tracking down. "Mutate" just mutates; it doesn't make a new production string. To go ahead and make a new production string and interpret it, use "Mutate, Remake/Interpret". There is only one set of rules in memory at any one time. To retrieve the original (before mutations) rules, use "Production/Make and Interpret" to reload the original rule file.
Mutate & Remake/Interpret
Does a mutation just like Mutate, but then makes a production string using the mutated rules, then interprets the new string. If you want to make, say, 5 mutations at once, hit "Mutate" 4 times (equivalently hit CTRL-m 4 times), then the last time use "Mutate & Remake/Interpret"
Save Mutated Rules
Saves the mutated version of the transformation rules as a rule file. The default extension for these 'mutated rule files' is '.lm' just to distinguish between the original rule file and the mutated version.

Options Menu

Sound
Turn off/on sound output.
Draw
Turn off/on drawing the graphical L-system. The drawing mostly just shows how the MIDI interpretation is progressing. Turning off drawing has a noticeable effect speeding up the interpretation step.
Autoplay
Turn off/on automatically playing the interpretation when it is done. (after "Load, Make, and Interpret", "Interpret", "Remake", and "Remap")
View
Choose the viewing plane for the drawing, and the size of the drawing. These have no effect on the musical interpretation.
Maximum Production String Size
Allows you to change the amount of memory allocated for the production strings. On occasion, a production can run out of space. In this case, LMUSe aborts the production and tells you that it ran out of production string space. The 'Maximum Production String Size' is how many megabytes are allocated for the production string. The default is 2 Megabytes, but can be anything from 1 to 99 Megabytes.


Map Files

A 'map' file is a file that contains the map parameters (basically, the parameters you choose in the map dialog). The format of these files is a list of "parameter=value" statements. The hash ('#') is used as a comment starter (everything on a line after a hash symbol is ignored). An example file is LMUSe.INI.

# LMUSe v0.7a map file LMUSE.INI
# Fri Oct 16 01:12:27 1998
# Current rulefile: (none) 
# Everything to the right of '#' on a line is ignored.
# Each map line is of the form 'parameter=value'.
# Including any of these parameter fields is optional.
# Letter cases in map files are ignored.

# tempo in beats per minute
tempo=120

# transposestack is a special stack for transposing the generated
# pitches. (L-system symbols T(x) ... T ).
# transposestack=1 enables this stack.
transposestack=0

# factorstacks are special stacks for holding duration and volume
# multipliers. (L-system symbols D(x) ... D , and V(x) ... V ).
# factorstacks=1 enables these stacks.
factorstacks=0

# randomseed is an (unsigned) integer
# To actually use this seed you need to
# uncheck 'Random Seed' in the dialog presented
# when doing a 'Make' or 'Remake'
randomseed=220

# mapnumber tells which map (0 thru 9) the following
# (up to the next mapnumber statement) are supposed to go
# into when the file is loaded. mapnumber statements are
# necessary to include several maps in a single map file
mapnumber=0

# pitch, duration, and volume of notes are each determined by
# any one of the following L-system variables:
# x          - the x coordinate of the turtle's position
# y          - the y coordinate of the turtle's position
# z          - the z coordinate of the turtle's position
# forwardx   - (or 'fx') the x component of the turtle's forward direction
# forwardy   - (or 'fy') the y component of the turtle's forward direction
# forwardz   - (or 'fz') the z component of the turtle's forward direction
# leftx      - (or 'lx') the x component of the turtle's 'left' orientation
# lefty      - (or 'ly') the y component of the turtle's 'left' orientation
# leftz      - (or 'lz') the z component of the turtle's 'left' orientation
# upx        - the x component of the turtle's 'up' orientation
# upy        - the y component of the turtle's 'up' orientation
# upz        - the z component of the turtle's 'up' orientation
# length     - (or 'statelength') the state length of the L-system
# drawlength - the 'draw length' (affected by temporary length modifiers)
# thickness  - the Lparser line thickness
pitch=x
duration=drawlength
volume=forwardx

# pspread, dspread, and vspread are magnifiers for the influence
# of the pitch, duration and volume parameters on the notes generated.
# Recommended to stay in interval -4.0 to 4.0
pspread=1.000000
dspread=1.000000
vspread=1.000000

# 'scale=scalename' tells LMUSe what scale to use.
# The predefined scale choices are 'Major', 'minor', 'Blue1', 'Penta1',
# 'diminished', 'Twelvetone', or 'whole'.
# Alternatively, you can give a list of number halfsteps from
# starting with the number '1'. For example, a major scale
# could be given by: scale=1,3,5,6,8,10,12
scale=Major

# scalefn is the algorithm used to get the pitches to conform to the
# desired musical scale. (see LMUSe.txt)
# Choices are: slideto, steps, constant, ignore
scalefn=slideto

# transpose amount
transpose=0

# duration multiplier
dmultiplier=1.000000

mapnumber=1
pitch=x
duration=drawlength
volume=forwardx
pspread=1.000000
dspread=1.000000
vspread=1.000000
scale=Major
scalefn=slideto
transpose=0
dmultiplier=1.000000

# maps 2 thru 8 could go here. (order is not important)

mapnumber=9
pitch=x
duration=drawlength
volume=forwardx
pspread=1.000000
dspread=1.000000
vspread=1.000000
scale=Major
scalefn=slideto
transpose=0
dmultiplier=1.000000


The Play Screenplay screen screendump

'Play' starts the music at the beginning.
With 'Loop ' checked, the music will loop around to the beginning every time it gets to the end.

Clicking on 'Pause' stops the music until you click on 'Pause' again.

'Save Midi' saves the piece as a standard midi file (format 1).

'New' and 'Exit' are functionally identical. Either one stops the playing and sends you back to the production screen.

The note display shows pitch by height in the box, and duration of a note by length of its drawn line. At the bottom of the box where the notes are displayed is a 'ticker' which shows you where in time the piece is playing. If you move the mouse cursor into this area and click the mouse, the piece will jump to that time and start playing from there.


Using Musical Scales

You can choose a musical scale in the Map dialog box under "Scale". The scales are described below.

'User' choice is for defining your own scale. If you pick 'User', you are given a box where you type in some scale steps and the scale you type in will be used. The scale you type in should start with '1' (lowest note of the scale) and thereafter each following number denotes the next higher note in the scale, in 'half tones'. Put spaces or commas between different scale notes. For example:

1 3 5 6 8 10 12

would make a major scale.

The scales in the list are defined, either by convention or by me, as:

twelve tone 1 2 3 4 5 6 7 8 9 10 11 12 c c# d d# e f f# g g# a a# b
Major 1 3 5 6 8 10 12 c d e f g a b
Penta 1 1 5 8 10 11 c e g a a#
minor 1 3 4 6 8 9 12 c d d# f g g# b
blues 1 1 3 4 5 8 9 10 11 c d d# e g g# a a#
whole tone 1 3 5 7 9 11 c d e f# g# a#
diminished 1 2 4 5 7 8 10 11 c c# d# e f# g a a#

Scale Function
Below the button for choosing a scale is the 'scale function button. LMUSE gets note pitches from some L-system state variable, as chosen in the 'connect' box in the Map dialog. These variables are actually numbers. If you want to use a scale, those numbers need to end up being notes in the scale. LMUSE lets you choose between two (three) ways to do this.

The 'slide to' setting finds the lowest note greater than or equal to the generated number. It finds the next note by going 'up' the scale until reaches the number or greater. It uses semi-tones to step up.

'steps' uses the generated number to count directly up the scale. That is, it uses the scale itself to step.

'constant' is just a way to get a constant pitch rather than a scale.


Rules Files Compatibility

Lparser *.LS files should all work in LMUSe (meaning only that they will be accepted and interpreted by LMUSe). Be aware, though, that files that work in LMUSe won't necessarily work with Lparser. The LMUSe parser was designed to interpret the large number of LParser files available but LParser won't accept some of the LMUSe rules (context sensitive or stochastic rules).. On the other hand, while LParser can make beautiful graphics, LMUSE can't. The drawing that LMUSe does while interpreting is intended mainly as a 'progress indicator'. LMUSE is for generating music and it is just great that some of the LParser files do make nice music when fed to LMUSE.

I have tried to keep the file extensions of the examples consistent. A file with just an 'L' extension is an LMUSe rules file which does not contain a 'thickness' (the third non-comment in Lparser files is the starting thickness of lines as a percent of their length and must be present for the file to work properly with LParser), or if it contains stochastic rules (a la A(.5)=ABB) or context sensitive rules (e.g. A). If I believe a file is compatible with Lparser (for example, contains a thickness and no context sensitieve or stochastic rules), it should have the 'ls' extension. A file that has been mutated by LMUSe (saved after 'mutating') is given the 'lm' extension. 'lm' files which were originally 'ls' files before mutation should still be compatible with Lparser, but I haven't checked all of them.

Certain of the symbols are interpreted differently in the two programs. For example 't(x)' in LMUSE transposes the following notes by x semitones. In LParser, t(x) is interpreted as a 'tropism' or gravity influence. This interpretation of 't(x)' is completely ignored by LMUSE. In LMUSE, '{' and '}' are mostly for creating parallel in time (polyphonic) musical lines. Their use in LParser is for making polygons like leaves, flower petals, etc). LMUSE does not know 'polygons' at all and so the generated graphics often look different from what you might expect from seeing the same file interpreted by LParser.

Another popular program for doing L-systems is Fractint. Fractint L-system files (*.l) are 2-dimensional. To use them with LMUSe requires some easy adaptations to the Fractint file. First, a Fractint 'L' file can contain many sets of L-system rules. The different L-system rule sets have to be isolated in their own file to be used in LMUSe. Fractint L-system rules, parameters and axioms are also enclosed in curly brackets. You have to erase those. Plus you have to get rid of the labels like 'Angle' and Axiom'. and insert a recursion level on the first line. Also, the comment character in LMUSE is '#' while in the Fractint .L files it is ';'. And the angle in the Fractint files is a division of 360 degrees rather than the number of degrees itself. One other major difference in symbols is that @nnn in Fractint systems is the command to multiply line segment lengths by nnn, while the corresponding LMUSE command is "(nnn). (a double quotation mark followed by the multiplier).

Also note that Fractint's interpretation of .L files is case insensitive (e.g. 'F'='f'). LMUSe is sensitive to case. (e.g. 'F' and 'f' are interpreted differently).

Actually, now that I have gotten to this point I realize there are a number of other differences and I guess I am not prepared to detail them all.

An example conversion (grabbed from fractint.l):

Koch1 { ; Adrian Mariano ; from The Fractal Geometry of Nature by Mandelbrot
Angle 6
Axiom F--F--F F=F+F--F+F }

would become (koch1.ls):

# Adrian Mariano
# from The Fractal Geometry of Nature by Mandelbrot
3 # recursion level
60 # 60 degrees = 360 degrees/ 6
F--F--F # Axiom
F=F+F--F+F

Some very symmetric L-systems make static/boring music. One thing that 'helps' such files is changing the basic angle. Naturally this will 'screw up' the picture, but often gives the music more life.


Command Line parameters

LMUSe can take certain command line parameters. From the DOS command line you can start LMUSe with:

LMUS [-sS] [-dD] [-mM] [-iI] [-g[G]]
-sS
S is the number of kilobytes to reserve for production string space. e.g. -s2048 reserves 2048 kilobytes, or 2 megabytes. Note that LMUSe actually allocates for twice this much (making two strings).
-dD
D is a code number for digital sound cards. Acceptable codes currently go from -1, 0, 1 thru 8 (this list is copied directly from Shawn Hargreave's Allegro library documentation):
-1 = Let LMUSe detect the appropriate sound card (this is the default).
0 = No digital sound.
1 = Sound Blaster (autodetect type)
2 = SB 1.0 (8 bit mono single shot dma)
3 = SB 1.5 (8 bit mono single shot dma)
4 = SB 2.0 (8 bit mono auto-initialised dma)
5 = SB Pro (8 bit stereo)
6 = SB16 (16 bit stereo)
7 = Gravis Ultrasound (not written yet)
8 = ESS AudioDrive
-mM
M is a code number for midi cards. Acceptable codes currently go from -1, 0, 1 thru 9 (this list is copied directly from Shawn Hargreave's Allegro library documentation):
-1 = Let LMUSe detect the appropriate MIDI card (this is the default).
0 = No midi sound.
1 = Adlib or SB FM synth (autodetect type)
2 = OPL2 synth (mono, used in Adlib and SB)
3 = dual OPL2 synths (stereo, used in SB Pro-I)
4 = OPL3 synth (stereo, SB Pro-II and above)
5 = SB MIDI interface
6 = MPU-401 MIDI interface
7 = Gravis Ultrasound (not written yet)
8 = sample-based software wavetable player
9 = AWE32 (EMU8000 chip)
For example, to run LMUSe without sound you could use the command line
LMUS -m0 -d0
-iI
I is the path and name of a map file to load.
-g
(no parameter) Gives the option to choose a video card card and video mode for the screen display on startup.
-gG
G is a code number for video resolution:
  • 1 = 640x480
  • 2 = 800x600
  • 3 = 1024x768
  • 4 = 1280x1024
  • 5 = 1600x1200

Each of these parameters is optional. That is, none are normally needed.


Trouble

Please email dsharp@interport.net for any problems not listed here. I have accumulated some fixes for problems on particular systems.

It doesn't run under Windows 95/98.
The MIDI sound doesn't work.
If you are running LMUSe in a DOS window or DOS box (Win 95), try running LMUSe after rebooting to DOS. This is pretty common generic advice, but it is the best I can offer without more details. If it still doesn't work, please email me at dsharp@interport.net with as many details of the situation as you can manage.

One work around for most related problems is to use the command line version of LMUSe. It has no graphics, sound, or interface with the user (beyond the command line, rule file, and map file), but it does dump a midi file at the end.

Also, LMUSe fails if it can't find the file 'LMUS.DAT'. If LMUS.DAT is not in the directory LMUSe is run from, you need to set the environmental variable LMUSDATA to the directory where LMUS.DAT is. For example, on the DOS command line, you can type:
SET LMUSDATA=C:\LMUSE\LMUS.DAT
assuming LMUS.DAT is in C:\LMUSE. The above line could be added to your AUTOEXEC.BAT file.

The screen appears messed up
You can try starting LMUSe with the command line:
LMUS -g
which allows you to pick your video card and a video mode from lists. But, in fact, this is unlikely to solve any problem.

HELP functions don't work.
This is probably because LMUSe can't find the file HELP.DAT. The HELP.DAT file must be in the same directory that you are running LMUSe from, or you can set the environmental variable LMUSHELP to the path to HELP.DAT . For example, on the DOS command line, you can enter:
SET LMUSHELP=C:\LMUSE\HELP.DAT
replacing C:\LMUSE\HELP.DAT with the path to HELP.DAT

Running out of production string space:
The default limit for production string space is 2 megabytes. You can increase this limit under the 'Options' menu, or in the dialog box presented as LMUSe starts to make the production string ("Make", "Make and Interpret", or "Remake"). The box titled "max production length" is the maximum length of a production in megabytes. You can also use the command line option "-sXXXX" where "XXXX" is the number of kilobytes of string space to allocate. For example, "-s4000" will allocate room for 4 megabyte production strings. Be aware, however, that LMUSe actually allocates for two strings of this size. That is, a "4" in the 'max production length' field or -s4000 on the command line will actually allocate for two 4 megabyte strings.

Running out of stack space:
If you are finding that the stack space is often too small, let me know. Running out of stack space is most likely to occur when trying to run a mutation. The real remedy is to increase the stack space by recompiling LMUSE with a larger stack size. (The current size is 2K). A workaround to try is to reduce the recursion level you are attempting, if the recursion level is not critical to your project.

Arithmetic errors:
A mutated set of rules can sometimes cause an "arithmetic error" during interpretation. This is usually because a mutation has caused the l-system object to grow out of control. LMUSe should then just quit interpreting and tell you that it encountered an arithmetic error. However, if LMUSe exits or actually crashes due to an arithmetic/floating point error, please send me details.

The drawing runs off the screen:
When Re-interpret(Remap) is run and a new view is chosen, LMUSE uses its previous view parameters. That is, Remap does not figure the screen limits of the new drawing. The "solution" is to use "Remake and Re- Interpret" instead, even though it does take longer.

Invisible characters:
Another 'known bug' is that when viewing the current transformation rules in LMUSe's View Rules box, extended ASCII characters (ASCII code higher than 127) don't show. They are still used in the production and interpreted, you just can't see them in the 'View Rules' box. Some of these characters are in the 3dartist.ls file that comes with Lparser, just in case you want to see what I am talking about.

Sequencer chokes on LMUSe MIDI files
Turn off "Write Info into MIDI file" and turn on "Split Tracks by Program" when saving MIDI files. If this doesn't fix the problem, please send me a note.

The drawing does not resemble the LParser rendering:
There are a number of LParser's drawing symbols which are interpreted differently (or not at all) by LMUSE. Probably most important (i.e. having the most dramatic effect on the drawings) is that LParser polygons, "{....}", are not supported by LMUSE. In a minimal attempt at compatiblility, LMUSE takes a stab at drawing the polygons by treating them as normal (non-polygon) drawing commands, but actually does a pretty poor job. Also, while LMUSe does keep track of line 'thickness' (you can map note parameters to it), line thickness is completely ignored in the drawing. The drawing is mainly meant to be a progress indicator while LMUSe is turning the production string into music.


Credits

Special thanks to:

D J Delorie for DJGPP v2
DJGPP web site

Shawn Hargreaves for Allegro v3.0
shawn@talula.demon.co.uk
http://www.talula.demon.co.uk/

Laurens Lapre for LParser.
ljlapre@xs4all.nl
http://www.xs4all.nl/~ljlapre/

Tim Thompson and Michael Czeiszperger for `midifile.c'

End of File

1