by Nicholas Mucherino <74012.2265@compuserve.com> 199 Yacht Street, #310-I Bridgeport, CT, USA 06605
People forget that music's soothing syrup once perscribed an ascerbic dose of mathematics. In the company of the ancient Pythagoreans, numbers were an essential part of the musical experience, and the mysteries of harmony contemplated against a backdrop of universal mathematical ratios [1].
In more recent centuries, music had been held separate from its deterministic beginnings. Musicians often adopted the poorly-defined explanations of "inspiration" and "genius" whenever a theoretical justification was called for. Concurrently, Mathematics maintained its pursuit of rigorous logical expression; reaping varied acheivements such as Newtonian mechanics and calculus.
We have drifted back in the direction of a resynthesis of these disciplines, in this half of the Twentieth Century. It does not seem perverse to contemporary engineers, to juxtapose the properties of sounds and numbers. Readers may have already benefitted from this modern correspondence, either directly, in playing an electronic instrument and using a multimedia PC, or indirectly, in listening to: a compact disk, the soundtrack in a movie theatre, or a digital stereo TV. Today, respectable mathematicians train their intuitions with "entertaining" computer-visualized exploration, and "inspired geniuses" make brazen use of the inherent number-crunching of synthesizers, sequencers, and digital signal processors. Today's union of music and math features in the creation of video-game music, synthesized e-z listening arrangements, and electronic novelties. Although this daily bombardment of notes created using math-based tools is multiplying, too often the commercial use of digital music engineering engenders a reputation for mechanistic rhythms and banal timbres.
Consider an elementary mapping for mathematical quantities and musical notes: match up each note in the musical chromatic scale, with an ordinal number.
c 1 c# 1 d 1 d# 1 e 1 f 1 f# 1 g 1 g# 1 a 1 a# 1 etc... 1 2 3 4 5 6 7 8 9 10 11For the convenience of electronic musicians, I want to point out that this is a similar mapping to the MIDI ( Musical Instrument Digital Interface) numbers for these semitones[2]. These numbers could represent actual notes played on a synthesizer, an output onto magnetic media, or just a theoretical set. Also, these quantities could represent "musical events" other than tones, but we'll consider them as if they were notes for now.
Mathematicians might call a series of musical notes notated as if it were a stairstep-like function a piecewise constant, quantized discrete-time signal. An event is constant because it is the same between start and end of the event. It is piecewise constant, because notes are constant except for the instant between different notes. Quantization means, in this case, that the notes are assumed to fall on distinct note values, on distinct irreducable points in time. I'll refer to this limited subdefinition of notes by the generic shorthand: "musical events".
Consider a graph where the horizontal axis in represents the time-axis, and the vertical represents the note or musical event number. In this numeric / musical mapping, or "musical space", simple melodies (or collections of musical events) are like one-sided functions; one-sided because events do not occur to the left of the vertical axis in this coordinate system. They will usually proceed starting at the axis-crossing point of time = zero.
Barnsley calls on many types of geometric transformations to explain his concepts, but we'll explore one of the simplest types, one that we typically meet in high school algebra:
The Linear Transformation (Equ.1).
(Equ.1) Transformation: new position = a * position + b ,
new note = c * note + d
As Barnsley explained, a linear transformation gives you a new pair of
numbers for input horizontal and vertical coordinates. It can also be thought of
as expanding or contracting an entire numeric space. Familiar one-dimensional
examples of this are the formulas for Fahrenheit / Centigrade temperature
conversion (Equations 2,3).
(Equ 2.) Fahrenheit = 9/5 * Centigrade + 32 (Equ 3.) Centigrade = 5/9 * Fahrenheit - 17.77777..Musicians and composers practice these transformations intuitively, but have been referring to them with different jargon than mathematicians.
Transposition, which is a translation along the position axis, means to play in a different key (Equ.4a).
(4a.)new note = note + constant, new position = positionInversion ( chromatic ), is like a reflection about a defined axis. It is, in a sense, playing "upside down" (Equ.4b).
(4b.)new note = -note + ( 2 * axis ), new position = positionRetrograde, which is to play the musical sequence in reverse order, can be considered as a reflection plus a normalizing translation.[Equ.4c]
(4c.)new note = note, new position = -position + endpointAugmentation, means to use longer note values. Geometrically, this is an expansion along the position axis. [Equ.4d]
(4d.)new position = ( constant > 1 ) * position, new note = noteDiminution is to use shorter note values. This is compression along the position axis. [Equ.4e]
(4e.)new position = ( 0 < constant < 1 )* position, new note = notePlaying in Rhythm, to adjust notes to fall on the beat. This is also called quantization. [Equ.4f]
(4f.)new position = INT( position ), new note = noteChange of Rhythm, or to play in a different rhythm, is like positional expansion or compresion plus quantization. [Equ. 4g]
(4g.)new position = INT( ( constant ) * position ), new note = noteRepetition, which means to copy sequences of events. [Equ. 4h]
(4h.)new position = position + constant , new note = noteYou should be able to discover many examples relative to these naive mathematical operators in the music you play or listen to.
Paradigm denotes a framework, one on which to build current and future research and experimentation. The conjecture of this chapter is the construction of a foundation based on: recursion combined with iteration. I submit an idea for a potential symbiosis that reflects the archetype of Indian music, in which relatively small parts of a composition could, in a self-referential manner, "fractalize" into a larger composition with computer assistance, analogous to the extemporaneous variations woven by raga artists. In taking advantage of the variety and self-similarity inherent in a fractal-related approach, future musical sequences could pattern a more naturalistic, improvisatory character than is currently inherent in much of the electronic repetoire. Fueled by commonplace access to multimedia computing, and with the signal processing power to easily manipulate snippets of melody, meter and rhythm, experimenters now have the means to take a step towards this horizon.
[Equ5] transform_(n): new position_(n) = a_(n) * position + b_(n) ,
new note_(n) = c_(n) * note + d_(n)
where n is of the set of odd numbers: { 1, 3, 5, . . . , N }.
These transforms are used on data which is a set of points of the form:
( position_(i), note_(i) )
where i = 0, 1, 2, ...,N, and constrained by:
position_(0) < position_(1) <= position_(2) < position_(3) <=
. . .<=position_(N)
and note_(0) = note_(1) , note_(2) = note_(3) ,
. . . note_(N-1) = note_(N).
When recursively iterated, these transforms can generate larger and larger
numbers, or return the original data points used to create the transforms.
Scaling constants or gains (c_(n)) are needed to control the rate at which this
happens. The absolute value of the scaling constant for a given transform should
be less than or equal to one, to prevent the vertical growth of the output from
heading off to infinity.
Barnsley, although he bases his fractal interpolations on mappings of a higher dimensional rank, gives suggestions for the general way to constrain a space that are useful applications, even under these simpler transformations. It simply involves setting two constraints (Equ.6.1, 6.2):
(Equ.6.1.) Transform_(n) : (position_(0) ) = (position_(n-1) ) ,
(note_(0) ) = (note_(n-1) )
The left hand-most point of entire sequence is mapped to the (n- 1)st
point of the current transform. The starting note of the entire sequence of each
transformation of the sequence is always mapped to coincide with the ending
notes of the previously transformed pair.
(Equ.6.2.) Transform_(n) : (position_(N) ) = (position_(n) ),
(note_(N) ) = (note_(n) )
The right-hand most point of entire seq. is mapped to the (n)th point of
transform. Each transformation of the end note of the whole germinating sequence
is wrapped around onto the start notes, which is geometrically like putting the
sequence onto a cylinder that is then flattened out.
In this way, the transforms you create and iterate will always contract horizontally back into a defined musical space. The generating equations that result, when combining these transform constraints with the data constraints from Equ.5, are below.
These equations are run through the iteration 1,3,5,....,N to calculate the constants for each transform_n.
a_(n) = (position_(n) - position_(n-1) ) / (position_(N) - position_(0) ) b_(n) = ( position_(N) * position_(n-1) - position_(0) * position_(n) ) / (position_(N) - position_(0) ) c_(n) = ( User specified. Absolute value <= to 1. ) d_(n) = ( note_(n) - c_(n) * note_(0) )The even numbered transforms would map the data back onto vertical lines. However, the vertical lines are understood, in the sense of the piecewise-constant definition of our output, as being the instant occuring precisely between two musical events.
{ 1 -1 -1 1 -1 1 1 -1 -1 1 1 -1 1 -1 -1 etc.}
This sequence has many interesting properties, and new ones are
continually being discovered. The property which I found the most astonishing in
accidentally running across it is: Morse-Thue is kind of a thumbnail census of
the number of powers of two in the counting numbers. In a list of the counting
numbers, starting with zero, you can immediately (and nonrecursively) determine
the corresponding one / negative one digit in the Morse-Thue sequence by
counting the number of powers of two in the countng number. An easy way to do
this is convert the numbers to binary, and add up the number of ones in the
binary number. If the count is odd, the corresponding Morse-Thue digit is -1; if
even, the digit is a 1!
Usually, this sequence is not described as being calculated in a direct manner, but by a recursive algorithm. Basically, start with a set containing a single one. Continue to double the length of the sequence by appending the complement of the previous set. {1}, {1,-1}, {1,-1,-1,1}, {1,-1,-1,1,-1,1,1,-1}, etc... Mathematically, these manipulations can be thought of as a double transformation, and these transforms which regenerate the sequence in any length are embedded in a surprisingly tiny amount of data. The Morse-Thue transforms are entirely specified by the starting and ending points of a single "one" event, followed by the Morse-Thue characteristic of appending the complement, that is, copying and "flipping" to a negative one.
note_(0) = 1, (a start point) note_(1) = 1, (an endpoint)
note_(2) = -1, (a start point) note_(3) = -1 (an endpoint)
position_(0) = 0, position_(1) = ( 2^(K-1) )-1,
position_(2) = 2^(K-1), position_(3) = 2^(K)
where N=2^(K) equals the number of points horizontally.
Coefficients:
a_(1) = .5 b_(1) = 0 c_(1) = 1 d_(1) = 0
a_(3) = .5 b_(3) = (2^(K-1)) c_(3) = -1 d_(3) = 0
For the reasons stated in the previous section, since we only receive
useful information from the transforms created by the odd numbers, we need
generate two transforms in this case:
Transforms:
transform_(1) : new position = .5 * position ( shrink ) ,
new note = note ( let alone )
transform_(3) : new position = .5 * position + 2^(n-1)( shrink + flip ),
new note = -note ( flip vertical )
This is shown as a visual analogy in Figure 5a-5d. If the initial sysmbol
"_" is a constant "one", then each succeeding drawing represents the way the
transforms above shrink, copy and flip the initial data.
Fig5a.
_____________________________________________________________________
Fig5b.
__________________________________-----------------------------------
Fig5c.
_________________----------------------------------__________________
Fig5d.
________----------------__________----------_______________----------
The whole gist of the L-idea is that of Lists of symbols, that are recursively defined. These symbols stand for actions to be taken, as events themselves, or as changes of "State". States are variables which alter or redefine the actions and events.
As an easy example, return to the Morse-Thue sequence, in the version with one and negative one. Again, the rule is: the initial germ of the sequence is one, and always append the complementary symbol(s) to whatever symbol(s) you have from the previous set.
On the left side of the the L-system rule table are what I'll call, in deference to Dr. Lindenmayer's vocation of plant biology, "germs", as they are the smallest symbolic unit. On the right side of each item are the "production rules", which are the strings which recursively replace each germ. This Morse-Thue L-system is simple to write out:
Initially : 1 germ production rule 1 --> 1 -1 -1 --> -1 1Some L-systems software brandishes elaborate "turtle" graphics, featuring state selections of any angle and direction on the two- dimensional graphics plane, as well as germ redefnition capabilities. An example of a redefinition would be if, in the Morse-Thue example above there was a command that meant "all ones will now be called negative-ones, and vice-versa". In the simplified musical space of the following examples, only 90 degree turns will be allowed, three directions in the set of states: {up, forward,down}, and no redefinitions..
Re-translating the Melody Masher into an L-system form is a bit more challenging than Morse-Thue. If you think about the example of a set extrapolated from the Musical Offering motif, it consists of recursively replacing each note in the theme with the whole group of notes (although with the gain constants, c_(1)...c_(n), all set to 1 for this L-system example.) This leads to a natural map for each note: we just place each note-symbol in the "germ" column of the rules, then, on the production side of the rules, we place the directions to: play the note explicitly, turn, go up or down the offset to the following note, and then turn forward again. This is appended by the shorthand for the remaining notes in the original sequence. See below:
An example of simple action, state, and redefinition commands:
1. F denotes either an event forward, or up or down movement,
depending on the State.
2. f denotes either a non-event (say, a rest) forward, or up or
down movement, depending on the State.
3. + changes State from Forward to up, up to down, or down to
forward.
4. - changes State from Forward to down, down to up, up to
forward.
5. R rotates counterclockwise, the roles of action or states above:
{1.,2.,3.,4.} become redefined as {2.,3.,4.,1.}.
In other words, the symbols {F f + -} are now treated as
{f + - F}.
6. S swaps, the roles of actions or states above: {1.,2.,3.,4.}
becomes {4.,2.,3.,1.}
In other words, {F f + -} becomes redefined as {- + f F}.
initially: Event1
germ production rule
Event1 -> play, +- ( to next note )+-, Event2, Event3, ..., EventN
Event2 -> Event1, play, +- ( to next note )+-, Event3, Event4,
..., EventN
Event3 -> Event1, Event2, play, +- ( to next note )+-, Event4, Event5,
..., EventN
. .
. .
. .
EventN -> Event1, Event2, . . . , EventN-1, play, +- ( back to
Event1 )+-
Example patterened after Bach's Musical Offering theme:
initially: C
germ production rule
C -> F + F F F - Eb G Ab B
go up the musical interval of a minor 3rd...
Eb -> C F + F F F F - G Ab B
go up the musical interval of a Major 3rd...
G -> C Eb F + F - Ab B
up the musical interval of a minor 2nd...
Ab -> C Eb G F - F F F F F F F F F + B
go back down the musical interval of a Major 6th...
B -> C Eb G Ab F F + F -
up a minor 2nd...
See Pseudocode 2: L-system, for a model of implementation.
The solution that led to my experiments in recursive music was in the computer language LISP, published in a book by Douglas R. Hofstader called Metamagical Themas. Professor Hofstadter's solution involved continually redefining which disk was the "current disk", which disk was the "change disk", and which was the "destination disk".
The musical analogue was to change each disk swapping to a note- event. Since the definition of each note event was continually changing, this resulted in an interesting pattern with an attractive self-similar character, that reminded me of salsa rhythm. For a given set of musical events, let's say { Event 1, Event 2, Event3 },where R and S refer to the State or Action commands given several pages earlier, and where play means to play the current first member of the set, followed by playing the third member:
initially: Notegroup_(n) germ production rule Notegroup_(n)--> S(wap), Notegroup_(n-1), Play, R(otate), Notegroup_(n-1) , R , SZ-transforms are a tool used by engineers who regularly have to deal with the complexities of iteration and recursion in audio digital signal processing. Typically, mathematical headaches crop up in the design of digital audio filters, effects, and reverbs. Z-tranforms "live" in a complex-numbered space that allows for the use of more accessable algebraic and trigonometric manipulations, rather than a tangle of difference equations and countour-integrations.
Using a Z-transform involves converting the equations or processes inherent in your system of recursive functions into a polynomial expression in terms of the complex variable Z. Polynomials expressed in terms of Z have behavior less intuitive than real-numbered linear transforms. Their actions are not easy to visualize geometrically. Z- transforms have the capability to to produce mappings that flip, shrink, expand, or invert spaces, but are also able to rotate spaces to any given angle. Their contractions or expansions can also vary locally, which can have idiosyncratic effects on the space being processed.
There are several methods to convert a function to a polynomial in Z, but the brute-force method we will use simply involves garnering an understanding of your function in terms of where the data points are multiplied, added, and have to be delayed, in order to fall out on the right sample. In D.S.P., there are graphics that symbolize those operations. A triangle symbolizes gain or multiplication. A square (with the symbol Z^(-1) inside) symbolizes a delay. A circle symbolizes a sum or adding operation.
These three elements originally represented discrete pieces of electronic hardware. A network of these "operators" ( or modules ) would be wired together to form a digital filter or reverb[ 8 ]. Currently, specialized Digital Signal Processing chips have the power, memory and speed to emulate these building blocks in real-time software. Many systems that would have been comprised of interconnected hardare modules in the recent past can now be emulated in software.
We can't process audio signals in real time on our commonplace personal computers, unless we have a high-priced dedicated D.S.P. card. Besides, where audio engineers are concerned with the finest resolution of detail at audio frequencies, that is, on a sample-by- sample basis, we are more concerned with events on a macroscopic level: event-by-event, note-by-note, etc.. It is not a great leap of insight or technology to adopt these symbolic tools and techniques to creatively manage sequences of music-events.
With the input of just a single "one" pulse ( followed by zeros ) into this system, D.S.P. theory implies that the output produced by this is the "impulse response", because it is the systems response to the single one impulse. If our system is "well-behaved", this output will completely express the character of the system. In other words, because any string of samples can be considered a scaled-up or scaled- down version of an impulse, a single one gives us all the information we need to know about how a signal-processing network will respond to any sampled signal. As a potential solution for the Morse-Thue sequence, this translates into the network diagram in Z2TRAN.GIF. The equation at the bottom of Z2TRAN.GIF is a possible expression for the "transfer function" of Morse-Thue, in the sense that it is a shorthand notation for the polynomial in Z that is the Z-transform of the Morse-Thue sequence[9].
Once you understand
the meaning of the D.S.P. symbols, our previous encounters with the Morse-Thue
algorithm help to suggest how a network would then be translated into computer
code. An array ( sized a power of two, as in previous M-T generation schemes )
of zeros, with a single ' 1 ' at the beginning, could be the initial data. The
delays would be calculated as offsets in this array's index. You could use k as
an index to run through this array repetitively, until your Morse -Thue output
reached the desired length.
In concocting a Z-transformed version of the Melody Masher algorithm, calculating the delay for each note is not an obvious linear function. The Z's exponent depends on the calculated transform constants an and bn, as well as the current iteration number, due to the recursion in which the transform results wrap around. Fortunately, enough terms cancel under the earlier stated limitations (Equ. 6.1, 6.2) that this turns out to be a relatively benign expression:
( See ZTRANS.GIF ) This expression forms the exponent of the 'Z' in the diagram in ZTRANS.GIF:
EXPR = b_(n) * ( 1 - (a_(n))^(k) ) / ( 1 - a_(n) ), where n = 1, 3, 5, . . . , n-2, n.
For i = 0, 1, 2, 3, ... , ( length h[ ] + length x[ ] ):
h[ ] and x[ ] are first padded out with zeros so they are length:
( length h[ ] + length x[ ] ).
i
___
y(i) = \ h( k ) * x( i - k )
/
---
k=0
...OR,
i
___
y(i) = \ x( k ) * h( i - k )
/
---
k=0
In an analogy to the demonstration of Morse-Thue, the output of Melody
Masher can also be interpreted as the response to the input of a single "one"
pulse, at time zero; the so-called impulse response.
By the implications of the mathematics of Digital Signal Processing, we're allowed to treat a Melody Masher impulse response as a kind of audio filter, using it to reprocess, by convolution, other melodies, rhythms, or events. An expression that is processed in this way results in output that appears to reflect the self-similar scaling behavior of the fractalized function that it has been convolved with.
In using a program based on Pseudocode 3: Convolution, it is important to experiment with the adjustment of the gain of the data with respect to the impulse-response data used for filtration. I have found that the 'gain' of the fractal impulse response should be much higher than of the data you are convolving it with, in order to produce a noticable 'fractalizing' effect. It is also important to choose data which presents coincidental spectral components to the fractal function. For example, convolving a plain sine wave with a fractal interpolation function probably isn't going to accomplish anything particularly interesting, because the harmonics of a sine wave don't share much in common with the harmonically rich, stairstep-like fractal functions cranked out by a Melody Masher system.
These algorithms are meant to produce ideas for musical events. Don't let a machine decide what sounds right. Your ear is to be the final judge of what sounds proper. Don't forget that music consists of other parameters other than notes and rhythmic strikes. Use fractal functions to re-map sequences of musical events other than meoldies and rhythms:
Temporal Rhythm Pitch-Scales Melodic Forms Harmonic Forms Contrapuntal Forms Instrumental Density Instrumental Range Instrumental dynamics Instrumental attacks Tone Quality Instrumental Registers
Description Melody Masher returns an array containing the y
coordinates of the points on the attractor.
Arguments N Number of data points. N / 2 is the number
of "events".
x[N] Array containing the x-coordinates of
the data.
x( 0 ) = 0, start of first event.
x( 1 ) = endpoint of first event.
x( 2 ) = start point of second event.
x( 3 ) = endpoint of second event.
. .
. .
. .
x( N-1 ) = start point of last event.
x( N ) = endpoint of last event.
F[N] Array containing the y-coordinates of
the data: "F-of-x".
F( 0 ) = F( 1 ) = value of first event.
F( 2 ) = F( 3 ) = value of second event.
. .
. .
. .
F( N-1 ) = F( N ) = value of last event.
pnts Number of points in the horizontal
direction in the musical space, or
on the viewscreen, as the case may be.
x( N ) = pnts, usually.
maxiter Maximum number of iterations,
either by the random iteration method,
or by the deterministic iteration method.
If using the random iteration
method, this needs to be a
large number, say 10^(N/2).
a[ N ] Array holding computed transform constants.
b[ N ] Array holding computed transform constants.
c[ N ] USER SPECIFIED transform constants;
the "GAIN" of each transform.
d[ N ] Array holding computes transform constants.
BEGIN MelodyMasher
Calculate_Coefficients: 'Determines the ( N / 2 ) transform constants.
BEGIN
for i = 1 to N STEP 2
a( i ) = [ x( i ) - x( i - 1 ) ] /
[ x( N ) - x( 0 ) ]
b( i ) = [ x( N ) * x( i - 1 ) - x( 0 ) * x( i ) ] /
[ x( N ) - x( 0 ) ]
c( i ) = specified by user, absolute value <= one.
d( i ) = F( i ) - c( i ) * F( 0 )
next i
END Calculate_Coefficients
OPTION 1:
Deterministic_Algorithm: '
oldarray[ pnts ] Holds the data about to
be transformed.
newarray[ pnts ] Holds the data after
transformation.
BEGIN
Clear oldarray and newarray.
Put initial data into oldarray.
UNTIL count = maxiter
for i = 1 to N
for j = 1 to N STEP 2
' Loop through odd-numbered transforms
newarray[ a( j ) * i + b( j ) ] =
[ c( j ) * oldarray( i ) + d( j ) ]
next j
SWAP the contents of oldarray and newarray.
Clear newarray.
*** ( Examine or plot oldarray at this
point, if desired. ) ***
next i
count = count + 1
LOOP
*** ( Or, examine / plot oldarray contents here,
after the final iteration. ) ***
END Deterministic_Algorithm
OPTION 2:
Random_Iteration_ Algorithm: '
BEGIN
Clear contents of newarray.
( Oldarray not needed here. )
t = 0 : y = 0
for i = 1 to maxiter
k = ( Odd random number between 1 and N )
t = a( k ) * t + b( k )
y = c( k ) * y + d( k )
*** ( plot or examine the pair ( t , y )
here if desired. ) ***
newarray( t ) = y
next i
*** ( plot, examine or save the final
attractor in oldarray here. ) ***
END Random_Iteration_Algorithm
END MelodyMasher
-------------------------------------------------------------
Desciption Generates a recursively-defined string of symbols. These
symbols can then be mapped by the user to musical
tones, or displayed on a graphic screen as
desired.
Arguments num Number of rules in the L-system.
string, workstring May need to be a file or
array, depending
on the size limits of
your strings.
germ[ num ] Holds an germ, the smallest
divisable symbol in your L-system.
rule[ num ] Holds the production rules
for each germ.
State A variable holding a
representation of the current
action to be taken, not taken, or
direction to be moved,
based on the current
value of State. An
action taken usually means
to change the value of State as
well.
maxiter Maximum number of iterations
for your L-system. Since they are
recursively defined,
they can expand quickly!
command Workstring for string
generation routine.
BEGIN L-System
maxiter = (number of desired iterations ).
num = ( number of Rules ).
initially = "S1" example: "V"
germ( 1 ) = "S1" : Rule( 1 ) = "play,
+- ( to next note )+-, S2, S3, ..., Snum"
example: "V" example: "F+FFF-WXYZ"
germ( 2 ) = "S2" : Rule( 2 ) = "S1, play,
+- ( to next note )+-, S3, S4, ..., Snum"
example: "V" example: "VF+FFFF-XYZ"
germ( 3 ) = "S3" : Rule( 3 ) = "S1, S2, play,
+- ( to next note )+-, S4, S5, ..., Snum"
. example: "V" example: "VWF+F-YZ"
. .
. .
. .
germ( num ) = "Snum" : Rule( num ) = "S1, S2, ...,
Snum-1, play, +- ( back to note S1 )+-"
example: "V" example: "VWXYFF+F-"
workstring = initially
string = ( empty string )
BEGIN Generate String:
for level = 1 to maxiter
for k = 1 to LengthOf( workstring )
command = ( The character at position 'k' in
workstring. )
i = 0
WHILE i < num and command <> germ( i ) DO i = i + 1.
if (command = germ( i )) THEN string =
string + Rule( i ).
next k
Copy contents of string into workstring.
next level
END Generate String
BEGIN CleanUpString:
workstring = (empty string )
for i =1 to LengthOf( string )
tempstring = ( The character at position 'i' in
string. )
IF tempstring = ( "F" or "f" or ...
(state changing / action commands) ...or "+" or "-" )
THEN workstring = workstring +
tempstring
next i
Copy contents of workstring into string.
END CleanUpString
BEGIN PlayString:
note = ( intitial value )
State = ( intitial state )
for i = 1 to LengthOf( string )
workstring = ( empty string )
workstring = ( The character at position ' i '
in workstring. )
SELECT CASE based on contents of workstring:
" F " : If State = (firststate) then Play( note ).
Elseif State = (secondstate) then State =
(otherstate/action) : Note=Note+offset
Elseif State = (thirdstate) then State =
(otherstate/action) : Note=Note+offset
. .
. .
. .
Elseif State = (laststate) then State =
(otherstate/action) : Note=Note+offset
" f " : If State = (firststate) then Play( rest ).
Elseif State = (secondstate) then State =
(otherstate/action) : Note=Note+offset
Elseif State = (thirdstate) then State =
(otherstate/action) : Note=Note+offset
. .
. .
. .
Elseif State = (laststate) then State =
(otherstate/action) : Note=Note+offset
" + " : If State = (firststate) then State =
(otherstate/action).
Elseif State = (secondstate) then State =
(otherstate/action)
Elseif State = (thirdstate) then State =
(otherstate/action)
. .
. .
. .
Elseif State = (laststate) then State =
(otherstate/action)
" - " : If State = (firststate) then State =
(otherstate/action).
Elseif State = (secondstate) then State =
(otherstate/action)
Elseif State = (thirdstate) then State =
(otherstate/action)
. .
. .
. .
Elseif State = (laststate) then State =
(otherstate/action)
END SELECT CASE
next i
END PlayNote
END L-System
------------------------------------------------------------
Title Performs the convolution of an impulse response
with data.
Arguments L Length of the impulse response array.
h[ L ] Array containing the ( fractal ) impulse
response.
M Length of the array containing data to be
convolved.
x[ M ] Array containing the data to be convolved.
( M + L ) Length of the output.
opt( M+L ) Array containing the output.
BEGIN Convolution
Pad out h( L ) with M zeros.
Pad out x( M ) with L zeros.
for n = 0 to ( M + L )
temp = 0
for k = 0 to n
temp = temp + h( k ) * x( n - k )
next k
opt( n ) = temp
next n
END Convolution
[ 1 ] Shillinger, Joseph. (1978 reprint) Shillinger System of Music Composition. Da Capo, New York. [ 2 ] Chamberlin, Hal. (1980) Musical Applications of Microprocessors. Hayden Book Company, Rochelle Pk, NJ [ 3 ] Barnsley, Michael (1988) FRACTALS EVERYWHERE. Academic Press. [ 4 ] Lipiczky, Thom. (1985) "Tihai Formulas and the Fusion of Composition and Improvisation in North Indian Music." The Musical Quarterly. V.71,(2), G.Shirmer and sons, New York, NY [ 5 ] Pickover, Clifford A. (1992) Mazes for the Mind. "The Drums of Ulupu". St. Martin's Press, NY. [ 6 ] Lindenmeyer, Aristid and Przemyslaw Prusinkiewicz. The Algorithmic Beauty of Plants. (1990) Springer-Verlag, New York. [ 7 ] Pohlmann, Ken C. (1989) Principles of Digital Audio. Howard Sams and Co. [ 8 ] Schroeder, Manfred R. (1991) Fractals, Chaos, and Power Laws. W.H.Freeman and Co.. [ 9 ] Bracewell, Ronald N.. (1965) The Fourier Transform and its Applications. McGraw-Hill, Inc., New York. [ 10 ] Antoniou, Andreas. (1979) Digital Filters: Analysis and Design. McGraw-Hill, Inc., New York [ 11 ] Saupe, D. (contributor) (1988). The Science of Fractal Imagery. Springer-Verlag, New York.
Rietman, Edward. (1989) Exploring the Geometry of Nature. Windcrest Books. Stewart, Ian. (1989) Does God Play Dice?. Basil Blackwell, Ltd. Cambridge, Mass. Massie, Dana E. (1993)"An Engineering Study of the Four-Multiply Normalized Ladder Filter." Journal of the Audio Engineering Society. 41(7/8) 564-582. Becker, Karl-Heinz and Michael Dorfler (1989) Dynamic Systems and Fractals. Cambridge University Press. Pohlmann, Ken C.. (1991) Advanced Digital Audio. Howard SAMS, Carmel, IN. Abraham, Ralph and Chrostopher Shaw. (1992) DYNAMICS. Addison-Wesley, Redwood City, CA. Pickover, Clifford A. (1990) Computers, Pattern, Chaos, and Beauty. St Martins Press, NY. Pickover, Clifford A. (1991) Computers and the Imagination. St. Martins Press, NY. Peitgen, Hans Otto and Peter H. Richter. (1986) The Beauty of Fractals. Springer-Verlag, NY Hofstadter, Douglas R. (1983) Metamagical Themas. Basic Books. Lauwerier, Hans (1991) FRACTALS. Princeton University Press. Feder, Jens. (1988) FRACTALS. Plenum Press, NY Doczi, Gyorgi. (1981) The Power of Limits. Shambhala Publications, Boulder, CO. Olson, Harry F. (1967) Music Physics and Engineering(2nd ed.) . Dover Publications, New York, NY Field, Martin and Martim Golubitsky. (1992) Symmetry in Chaos. Oxford University Press, Oxford, UK Churchill, Ruel V. (1960) Complex Variables and Applications. McGraw- Hill, New York, NY Penni, Louis L.. (1963) Elements of Complex Variables. Holt, Rinehart and Winston, New York,NY Carrier, George F. , Max Crook and Carl F. Pearson. (1966) Complex Variables. McGraw-Hill, New York, NY