Recursion: A Paradigm For Future Music?

by
Nicholas Mucherino <74012.2265@compuserve.com>
199 Yacht Street, #310-I
Bridgeport, CT, USA 06605

ABSTRACT:

This speculation discusses the potential uses of recursion, iteration and complex mathematics as an extension of traditional music- compositional practice. The chapter includes an elementary introduction to fractal related tools proposed to be useful for extrapolating new sequences of musical events.

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.

Notes and Numbers

Classic composers did not consider the translation of their notes, rhythms, and musical manipulations in terms of numbers; they were able to relate to the dominant literary and poetical analogies of their time. Still, it can be shown that their compositional selections imply mathematical parallels, even when limiting this inference to the algebraic tools aavailable in previous centuries.

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     11    
For 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.

Transformations

Personal computing software for manipulating visual images and sounds has been commonly available for a long time, but it is not so common to find software for algorithmically manipulating and extrapolating series of musical events. It was the book by Michael Barnsley [3], that first prompted me to explore the analogies of the ways musicians unconsciously scaled, shifted, flipped, expanded and compressed melodies and rhythms in their mental musical spaces. It seemed that there must be extensions to which these commonplace geometric manipulations might be adapted to the work of future music composition. Music can contain the level of subtleties and variations as complex cinema special effects or works of visual / mathematical art, which rely so heavily on state-of-the-art technologies. My hope is that the mathematics of fractals can provide a gateway to experimentation for composers anticipating the next century's music.

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 = position
Inversion ( 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 = position                                     
Retrograde, 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 + endpoint
Augmentation, 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 = note                                   
Diminution is to use shorter note values. This is compression along the position axis. [Equ.4e]
(4e.)new position = ( 0 < constant < 1 )* position,   new note = note                                     
Playing in Rhythm, to adjust notes to fall on the beat. This is also called quantization. [Equ.4f]
(4f.)new position = INT( position ),         new note = note  
Change 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 = note  
Repetition, which means to copy sequences of events. [Equ. 4h]
 
(4h.)new position = position + constant ,             new note = note
You should be able to discover many examples relative to these naive mathematical operators in the music you play or listen to.

Ragas and Paradigms

India's musical / cultural tradition mandates the construction of musical developments in a recursive, non-linear way[4]. In Indian music, rhythms and melodies are spontaneously built out of a small pattern of set notes called the "raga". The raga is then syncopated, translated, rhythmically squeezed and manipulated in all manners, in order to synchronize beside benchmarks in the musical piece. This kind of juggling demands unconscious recursive "calculations", which are generated by the performer's intuitive filter of years of experience. Like our Western rock-and-roll, this Eastern form is a mixture of simple harmonies, improvisation and composition, but raga music eclipses Rock with its exotic metric and rhythmic demands on both performer and listener.

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.

Fractalization

As a prototype to explore the experimental techniques behind the neologism "fractalize", here's a basic tool: the Linear Transformation[Equation 5].
[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.

Morse-Thue Music

The Morse -Thue (pronounced like TOO) sequence is probably already familiar to the fractal-literate in the readership[5]. This important sequence of complementary binary digits figures prominemtly in fractal and chaos theory. The incarnation of the sequence I'm considering is made up of complementary 1s and negative 1s.

  { 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.
________----------------__________----------_______________----------

Melody Masher

By extension, these transforms can be created based on a set of numbers that represent actual numeric musical data. Files MOFF1.GIF thru MOFF5.GIF are included as a computer graphical analogy of the transformations that take place symbolically when the Melody Masher algorithm is applied to data based on J.S. Bach's theme to The Musical Offering ( See Pseudocode 1 :Melody Masher ). MOFF1.GIF represents the original notes, that would be used as the basis to calculate the equations for the transformations. MOFF2.GIF symbolizes the result after processing the original data through the generated transformations for a single iteration. Each succeeding Figure shows the output after processing the result of the previous transformations. Lastly, MOFF5.GIF shows the disconnected fractal-like"dust" that results when you iterate this process indefinitely.

MOFF1.GIF

MOFF2.GIF

MOFF3.GIF

MOFF4.GIF

MOFF5.GIF

L-systems Music

L-systems comprise a symbol-based method of investigating recursive, iterative sequences[6]. They were conceived by the late mathematician Aristid Lindenmayer, back in the Sixties. In the era avenues of cultural expression were expanding, Dr. Lindenmeyer was augmenting Science's appreciation of natural engineering with his landmark "Mathematical Models for Cellular Interaction in Development". In this paper, what are now called L-systems were outlined as a simulation for experimenting with and understanding plant growth.

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  1
Some 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.

Hanoi Music

My first experience with L-systems-based music has to do with the solution to a common puzzle known as the "Tower of Hanoi" (a.k.a., the Tower of Brahma). This puzzle is sometimes given as a problem to students of computer algorithms, because it demonstrates clearly shows the elegance of a recursive solution. Basically the puzzle consists of a stack of concentrically-sized disks placed onto one of three pegs. The object is to transfer the stack of disks to another peg, using the remianing peg as a "change peg". The limitation is, that no larger disk can be placed on top of a smaller disk in the process.

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 , S 

Z-transform methods.

Z-transforms, once found solely among the toolkit of the advanced theoretical mathematician, are making a comeback in music[7]. These tools have been preeminent in the invention of a bewildering inventory of audio-electronic products. While this is generally considered to be an advanced subject, I think any potential fractal musician should be aware that there are mathematics available to handle the mind-boggling mental hall of mirrors that recursion leads to. These tools will probably be as instrumental in engineering our audio future as they are in orchestrating the present technology.

Z-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.

Return of the Morse-Thue Sequence

As a demonstration of this unorthodox adaptation of the Z- transform, I again refer to the Morse-Thue sequence (Figure 13). Again, each one or negative-one ( or chain of 1s and -1s ) in the sequence gets appended with its complement, so each iteration increases the length of the sequence by a power of 2. In order to have the new half of the sequence land in the right spot, it must be delayed by half of the total length. This is inverted by multiplying by a negative one. The index variable k is used to keep track of the iteration number, so we know what total amount of delay will be needed each time around.

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].

Z2TRAN.GIF

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:

ZTRANS.GIF

EXPR = b_(n) * ( 1 - (a_(n))^(k) ) / ( 1 - a_(n) ), where

n = 1, 3, 5, . . . , n-2, n.

Convolution of Music

In audio, the sought-after property of convolution is that it is a way to multiply the frequency spectrums of two sequences, without resorting to calculus or complex representations[10]. The summation below is a common representation for the convolution equations, with the following qualifications: h[ ] is a series containing the impulse response data, and x[ ] is a series containing the sample data.

  
    
  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

PSEUDOCODE 1: Melody Masher

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
-------------------------------------------------------------

PSEUDOCODE 2: L-System

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
------------------------------------------------------------

PSEUDOCODE 3: Convolution

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

BIBLIOGRAPHY

[ 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.

Further reading...

 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