FINAL PROJECT

Professor: Fernando Lopez-Lezcano

Music 220b: Synthesis Techniques, Compositional Algorithms, Psychoacoustics and Spatial Processing

 

Course Description:

The use of high-level programming language as a compositional aid in creating musical structures. Advanced study of sound synthesis techniques. Simulation of a reverberant space and control of the position of sound within the space.

 

Sonification of Various Types of Cellular Automata (using SuperCollider3)

0. Overview

1. Continuous Cellular Automata [ Description | Code Outline | continuousCA.sc]

2. Mobile Automata [ Description | Code Outline | mobileCA.sc]

3. Turing Machine [ Description | Code Outline | turingMachine.sc]

 

[OVERVIEW]

During lecture on February 1, we were introduced to the simplest kind of one-dimensional automata, where each cell of the automata is a small state machine with just two states, and the transition between states is determined by the state of its two adjoining neighbors. The code seen in class, fabric.sc, generated such automata and allowed us to hear as well as visualize them.

I became quite fascinated by how one-dimensional automata (with such simple rules) could generate ornate nested patterns. Thus, I decided to find out more about cellular automata. The main source of reference, which was extremely relevant and helpful, was Stephen Wolfram's book, A New Kind of Science (2002). Wolfram, inspired by the potential of simple rules to generate highly complex patterns, had researched on this topic for nearly twenty years--and this book is a culminating product of such research.

Going over just the first few chapters of this massive book, I encountered many interesting variations of the original simple one-dimensional cellular automata. Some of these automata were able to (very occasionally--i.e. one every few million or even billion) generate highly complex patterns, which were neither repeating nor nested and thus seemed completely random! Among these, continuous cellular automata, mobile automata, and the Turing machine caught my attention. So I decided to implement these variants in order to hear (as well as visualize) amazing patterns that they yield.

And what I found--to my great surprise--was that despite the simplicity of their rules, the behavior of the programs was often far from simple. Indeed, even some of the very simplest programs that I looked at had behavior that was as complex as anything I had ever seen… Perhaps immediately most dramatic is that it yields a resolution to what has long been considered the single greatest mystery of the natural world: what secret it is that allows nature seemingly so effortlessly to produce so much that appears to us so complex.

--Stephen Wolfram, from Ch.1. The Foundations for a New Kind of Science


[CONTINUOUS CELLULAR AUTOMATA]

Description of Continuous Cellular Automata

Unlike the simple cellular automata with two states for each cell (i.e. discrete states of 0 or 1), continuous cellular automata has theoretically an infinite amount of states for they allow any real number values between 0 and 1.

In contrast to the discrete two-state automata for which a rule number determines the cell value based on its and its neighbors' values in the previous generation, continuous automata calculates the next generation by averaging the values of itself and its neighbors (with an option to multiply then add by a constant, which serve as a kind of rule that determines the shape of the automata). Only the fractional portion (after the decimal point) is considered, such that all values are between 0 and 1.

Here is an example of a continuous cellular automaton with the following rule (Wolfram p.157):

new gray level = (fractional part of "the average gray level of the cell and its neighbors") * 3/2.

By changing only the added constant from this rule, one is able to generate different patterns (Wolfram p.159):

The number under each picture denotes the constants used.


My Code

My code allows for controlling the width (number of cells per generation), the distribution of the initial row (1st generation), the number of generations produced, the multiplier constant, and the adder constant.

I implemented four different ways of sonifying the resulting output:

#1A: Alters amplitude based on ca values, and key number cycles up each generation. Creates an arpeggiated stream of notes.

#1B: Alters amplitude based on ca values, and key number cycles up each generation. Plays one chord per generation.

#2A: Alters key number based on ca values (by normalizing so that they fall 40~120 MIDI keynum). Creates an arpeggiated stream of notes.

#2B: Alters key number based on ca values (by normalizing so that they fall 40~120 MIDI keynum). Plays one chord per generation.


View continuousCA.sc


[MOBILE AUTOMATA]

Description of Mobile Automata

Mobile automata are similar to cellular automata except that instead of updating all cells in parallel, they have just a single active cell that gets updated at each step (71).

The active cell is denoted by a black circle in the book, and by a capital letter in the output of my program.

Here is an example of a mobile automaton (taken from Wolfram, p.71):


My Code

Because it is not trivial to come up with a general formula that defines all possible mobile automata (unlike in the simple two-state or continuous automata), I chose one rule from the book that shows a highly-complex pattern, and hard-coded this into my program. One could easily try out other rules though, by making changes to the ~calcNextRow function.

Here is a picture of the rule I chose in my program (taken from Wolfram, p.75):


My code allows for controlling the width (number of cells per generation), the distribution of the initial row (1st generation), and the number of generations produced.

I implemented two different ways of sonifying the resulting output (each generation plays one note):

#1:

Position of the active cell controls pitch (from low to high as we go from left to right)

Number of black ('b' or 'B') cells in a generation controls rhythm (the more 'b's we have, the longer the note).

#2:

Position of the active cell controls duration (longer duration as we go from left to right)

Number of black ('b' or 'B') cells in a generation controls pitch (the more 'b's we have, the higher the pitch).


View mobileCA.sc


[TURING MACHINE]

Description of a Turing Machine

Turing machines are similar to mobile automata in that they consist of a line of cells, known as the tape, together with a single active cell, known as the head. But unlike in a mobile automaton, the head in a Turing machine can have several possible states (78).

The head state is denoted by an arrow in the book, and by a number in the output of my program.

Here is an example of a mobile automaton (taken from Wolfram, p.71):

My Code

As was the case in implementing mobile automata, it is not trivial to come up with a general formula for defining the general Turing Machine. So again, I chose one rule from the book that shows a highly-complex pattern, and hard-coded this into the program. One could easily try out other rules though, by making changes to the ~calcNextRow function.

Here is a picture of the rule I chose in my program (taken from Wolfram, p.81):


My code allows for controlling the width (number of cells per generation), the distribution of the initial row (1st generation), and the number of generations produced. One could change the number of head states, but as I have hard-coded the rule to have 4 states (inside ~calcNextRow function), changing this parameter alone will not work.)

I implemented two different ways of sonifying the resulting output (each generation plays one note):

#1:

Head State = Triad Type: 0=Major, 1=Minor, 2=Augmented, 3=Diminished

Head Position = Duration (longer duration as we move left to right)

# of Black (+) Cells in a given generation = Frequency (root of the triad)

-> You'll hear a general shifting-up of the frequency as time progresses because the rule I chose is such that we get more black cells (+) per generation over time.

#2:

Head State = Triad Type: 0=Major, 1=Minor, 2=Augmented, 3=Diminished

Head Position = Frequency (root of the triad)

# of White (-) Cells in a given generation = Duration (longer duration if there are lots of white cells)

Amplitude of each note is also dependent on the prevalence of white cells

-> Analogous to how the pitch shifted up as time progressed in #1, you’ll feel the tempo speeding up with time because, overall, the number of white cells decreases with time.


View turingMachine.sc