The Ugliest Music on Synthesizer

Recently I saw a TEDx video by Scott Rickard about “The world’s ugliest music”; and I suggest you to watch it.
Usually good music is characterized by a balance between repetition and variation, applied to one or many of the components of the music itself: melody, texture, rhythm, form, and harmony. So what happens if we try to completely remove the repetitions?

In Scott’s music a math formula is used to generate all the 88 notes of a piano and their duration: starting from value 1, the next value is generated multiplying by 3 the previous one. If the value exceeds 88 then 89 is repeatedly subtracted until the value falls back in the 1-88 range:

1, 3, 9, 27, 81, 243–>154–>65, 195–>106–>17, … and so on

Sequences of this type are known as Costas Arrays (or Costas permutations) ; they have been studied by John Costas during his search for ideal sonar waveforms (‘pings’).

The duration of the notes are calculated using a Golomb ruler : each note is placed on the timeline in a special position (“mark”) in order to avoid any recognizable rythmic pattern. Indeed in a Golomb ruler the positions of the marks are such that all distances between them are distinct. The sequence of 88 note durations (expressed in 1/16th)  used in the ugliest music is the following:

33, 3, 45, 10, 18, 47, 30, 311, 96, 46, 145, 37, 14, 17, 71, 22, 175, 132, 8, 66,
41, 251, 11, 50, 67, 59, 39, 23, 56, 34, 241, 2, 133, 35, 157, 204, 6, 108, 29,
57, 122, 52, 60, 89, 49, 85, 147, 218, 21, 32, 72, 44, 100, 19, 111, 16, 27,
178, 12, 181, 26, 38, 103, 99, 183, 20, 131, 78, 80, 4, 180, 15, 25, 212, 24,
286, 54, 9, 92, 5, 159, 7, 87, 42, 172, 13, 69, 1

You can listen to the music played on piano in the last part of the TEDx video; the title of the piece is “Costas Golomb N.1: The Perfect Ping” … and it is quite ugly. But I like creating “bleeps and bloops” on a modular synthesizer (actually I’m using VCV-Rack and a semimodular Behringer Neutron), and sometimes the results are often not really melodic … so I tried to make a patch and play the ugliest music on it.

I also made a simple sketch in Processing 3 in which the 88×88 grid (notes are from left-to-right, top-to-bottom) are displayed and a “sonar ping” is generated when each note is played.

If you want to experiment yourself you can download:

… and the Neutron patch:

Visual Meditation with Tibetan Singing Bowls

A Processing 3 sketch of four slowly evolving polygons and a meditative soundscape created by a few Tibetan Singing Bowls.

The algorithm is very simple:

  • place each vertex of each polygon in a random position
  • assign to each vertex a random direction (all polygons have the same scalar velocity)
  • at every frame move each vertex, if the new position is outside a border, simply make it bounce (reverse the velocity component orthogonal to the border)
  • assign a different color to each polygon and draw only its outer border (no fill)

The source code can be dowloaded here.

I made a video of the animation (starting from 4 rectangles) and added a soundscape made with sampled Tibetan Singing Bowls.

Other implementation ideas:

  • change the speed of each vertex
  • slowly change the color of each polygon
  • generate a MIDI message each time a vertex hits a border and send it to a virtual instrument or synth

If you improve the code or implement other variations let me know in the comments below.

Imitating Nature Ep.1 – The Cuckoo (sound synthesis)

This is the first post about “artisanal” sound synthesis techniques that can be used to imitate (try-to imitate 😉 ) the wonderful sounds of nature. I tried to replicate the chirping of cuckoos that in this period can be heard near my house (North Italy).

I started with a raw and noisy recording of one of them, made with the nice Tascam DR-40 recorder:

Note that the cuckoo is far away and it is barely audible in the recording.

I ampified the wav file using the free (and powerful) tool Audacity: CTRL+A to select all the sound; Effect→ Amplify , set new peak to -3dB. Then the cuckoo is audible (five chirps), though there are another bird chirping, a dog is barking and there are some noises from the road:

Continue reading

Conway’s Game of Life variations

This is a three-part post about Conway’s Game of Life and some easy-to-implement  variations that can lead to interesting visual results.

  • Part 1: adding colors
  • Part 2: extending the neighbourhood [… coming soon …]
  • Part 3: moving to the third dimension [… coming soon …]

Part 1: adding colors

The Conway’s Game of Life is a cellular automaton created by the British mathematician John Horton Conway in 1970. It is a theoretically infinite grid of cells; each cell can be in two states: dead ($0$) or alive ($1$). Initially the grid has a particular initial configuration  (for example a percentage of the cells are set to alive).  Then the cells evolve, and the state of cell $(x,y)$ at generation $N+1$ depends only on its state and the state of its eight neighbours at generation $N$. The rules are simple:

  • if a dead cell at generation $N$ is surrounded exactly by 3 alive cells then it willl be alive at generation $N+1$
  • if an alive cell at generation $N$ is surrounded by  2 or 3 alive cells, then it will stay alive, otherwise it will become a dead cell at generation $N+1$

Despite the simple rules, the Conway’s Game of Life is a Turing Complete model of computation (i.e. it can simulate any computer).

The visual configurations and the animations are also visually interesting.

A first variant can be obtained in the following way:

  • overlap three independent cell grids (one for each component Red-Green-Blue)
  • animate each grid using the standard rules, but for each cell $(x,y)$ in each grid also keep a fractional (float) value $C(x,y)$ in the range (0,1) ($C_r$ for the red grid, $C_g$ for the green grid, $C_b$ for the blue grid) and update it using the following rules:
    • if a cell becomes alive then add a fixed constant $v_1$ to it: $$C(x,y) = C(x,y)+v_1$$
    • if a cell becomes dead then subtract a fixed constant $v_0$ to it: $$C(x,y) = C(x,y) – v_0$$
  • render each cell $(x,y)$ with a square (or pixel) and color it according to the three RGB components values $C_r, C_g, C_b$ that it has in the three independent grids: $Red = C_r(x,y)*255$, $Green=C_g(x,y)*255$ , $Blue=C_b(x,y)*255$

This is a video that shows the resulting animation made with Processing 3 using $v_1=0.3$, $v_0=0.04$, starting from an initial random configuration:

The Processing source code can be downloaded here:

https://www.algoritmarte.com/vdisk/code/ColoredLife.zip

 

 

Cyclic Cellular Automata

A cyclic cellular automaton (CCA) is defined as an automaton where each cell takes one of N states 0, 1,…, N-1 and a cell in state i changes to state i+1 mod N at the next time step if it has a neighbor that is in state i+1 mod N, otherwise it remains in state i at the next time step. Classically CCA are applied on the 2-dimensional integer lattice with Von Neumann neighborhoods (nearest 4 neighbors): if cell is at coordinate (x,y), the four neighbours are those at coordinates (x+1,y), (x-1,y), (x,y+1), (x,y-1).

The cells are arranged in a bidimensional grid and initially they are in a random state. At each generation a cell in state i evolves to state i+1 mod N if at least one of its neighbors is in state i+1. The color of each cell is determined by its state.

The following image is generated using Von Neumann neighborhood:

Cyclic CA Von Neumann neighborhood

[click to enlarge]

But very interesting behaviors can also be obtained if we pick irregular/random neighborhoods.

Continue reading

My first bleeps and blops

I just bought a Behringer Neutron, a semi-modular synthesizer …

  • I spent more than one hour before even hearing a sound from it :-);
  • then I spent another hour to update its firmware;
  • then I started noodling with the cables without any external MIDI input …

I built my first (auto playing) patch … which – honestly – doesn’t sound too good 🙂

patch sheet

[click to enlarge]

Nevertheless, I decided to record it (with a poor quality smartphone) to document my first step (also the last one?!?) into real modular and this the one minute video excerpt of those bleeps and blops …

I’ll play more with the Neutron during Christmas holidays; then I’ll write my impressions on it.

 

MusiFrog

… a Musical Frog jumping around a harmonic lake!

The MusiFrog is a simple deterministic algorithm that can be used to produce nice pseudo-random melodies that I discovered while experimenting with generative-music (but perhaps someone else has already found it).

example

It is based on a frog that jumps over a sequence of stones. Each stone has a jump value and is associated with a musical note. Initially the frog is on stone 1 and suppose it has jump value X. The note associated with stone 1 is played, and the frog jumps forward X steps on stone N=1+X; the jump value of stone 1 is increased by 1. Then the note associated with stone N is played, the frog jump forward according to the jump value of the stone which is then incremented by one. The process is repeated and when the frog jumps off the last stone it “wraps-up” and return to the beginning of the sequence.

Continue reading

Return to the Forbidden Planet

Forbidden Planet is a 1956 American Science Fiction film; one of the best SF films of those years (and of all time); all science fiction fans should see it (on a regular basis :-). Forbidden Planet – directed by Fred M. Wilcox – pioneered several elements that were resumed and developed later in many other SF films: humans traveling in a faster-than-light starship; it was the first to be set entirely on another planet far away from Earth; a robot with its own personality that has an active role on the plot.

Forbidden Planet Movie

Continue reading

The Random Clock

The Random ClockThe Random Clock is a short experiment that combines a sequence of random notes with a random colored pattern that moves clockwise. The notes are “arranged” in two “voices” and, at the beginning, their pitches and the intervals between them are completely random. As times passes, the notes “converge” to the single note E2 and also the tempo “converges” to ~120 bpm. When each note is played, a random box is drawed on the screen; its distance form the centre is proportional to the pitch and the angle increases at a constant speed.

The notes are played using a basic synth built in Reaktor Blocks (by Native Instruments), essentially they are sine waves.

The Random Clock This is the final video:

If you’re interested in the source code (Processing 3), let me know.

More ideas: try to mimic a real clock with the two clock hands rotating at different speeds; the speed and length of the clock hands should be initially random, then they should stabilize to a fixed speed and lenght towards the end.

The Collatz Tree

The Collatz sequence is a sequence of numbers that follows these simple rules (or “algorithm”):

  1. we start from a positive integer number N
  2. if N is odd then we multiply it by 3 and add 1 (N’ = 3*N +1)
    if N is even then we divide it by 2 (N’ = N / 2)
  3. we repeat the rule 2 for the new number N’ and generate another new number N”, and so on …

For example if we start from number 7 the sequence is:

7→ 22→ 11→ 34→ 17→ 52→ 26→ 13→ 40→ 20→ 10→ 5→ 16→ 8→ 4→ 2→ 1→ 4→ 2→ 1→….

the final sequence 4→2→1 repeats forever.

Using computers we have checked the sequence generated by the first 10^20 numbers and all sequences soon or later reaches the value 1.

The Collatz conjecture says that ALL numbers converge to 1 … though the problem is simple, no one has been able to prove (or disprove) it formally. Jeffrey Lagarias stated in 2010 that the Collatz conjecture “is an extraordinarily difficult problem, completely out of reach of present day mathematics”.

I recently found a very interesting and well done video explaining how the Collatz sequences can be visualized graphically. Using simple rules they can be used to build an interesting tree-like pattern. For further details see the original video on the Numberphile channel.

I decided to implement the visualization in Processing and tried to vary some parameters that generate the Collatz-tree. Slowly varying those parameters results in a hypnotic abstract animation. I recorded it (saving each frame and combining them with the free ffmpeg tool) and added an abstract music (the music itself is partially generated using a Collatz sequence and manually adjusted trying to make it more harmonious).

This is the final video:

This is the Processing code; you can experiment with it and freely modify it; let me know if you find interesting variants (you can also download the code CollatzTtree.7z):

/**
 * The Collatz Tree v1.0
 *
 * Put this file in a directory named CollatzTree and open it with Processing.
 * ... for futher informtion read the full article at 
 * https://www.algoritmarte.com/the-collatz-tree/
 *
 *
 *  Some PARAMETERS to play with ...
 *
 */
float FIRST_BRANCHLEN = 26;   // the length of the first branch of the tree
float START_AEVEN =  4;       // angle increase for even branches (degrees) 
float START_AODD  = -8;       // angle increse for odd branches (degrees)
int BRANCHES = 24;            // number of branches 
float SPEED_AEVEN = 0.4;      // "speed" of even angle (degrees per second)
float SPEED_AODD = -0.3;      // "speed" of odd angle (degrees per second)
int rollcol = 3;              // seconds between the roll of palette
int currscene = 1;            // current scene (used in animation) 0=static 1=forward 2=backward

// ------------------------------------------------------------
/**
 * Other parameters used for the animation
 */

boolean frecord = false;             // set to true if you want to generate the frames
String recorddir = "D:/tmp/video/"; // where the frames are generated (warning they can occupy a lot of space)
int numsaved;
long scenelen[] = {
  //0, 2000, 3000
  //0,  8000, 124000
  0,  8000, 100000
};
// ------------------------------------------------------------

/**
 * "internal" parameters
 */
int FPS = 30; // frames per second
float ae = START_AEVEN * (PI/90); // convert start angle even in radiants
float ao = START_AODD * (PI/90);  // convert start angle odd in radiants
float acce = 0.001; // acceleration even
float acco = 0.001; // acceleration odd
float currspeede = 0;  // speed even 
float currspeedo = 0;  // speed odd
float target_speede = SPEED_AEVEN;
float target_speedo = SPEED_AODD;
float zoom = 1;
float maxy, miny;
float cx, cy;
boolean fsetup = true;

int colray[] = { 
0xff0000ff,0xff2000ff,0xff4000ff,0xff6000ff,
0xff8000ff,0xffA000ff,0xffC000ff,0xffE000ff,
0xffff00E0,0xffff00C0,0xffff00A0,0xffff0080,
0xffff0060,0xffff0040,0xffff6020,0xffff8000,
0xffffA000,0xffffC000,0xffffE000,0xffffff00,

0xffffE000,0xffffC000,0xffffA000,0xffff8000,
0xffff6020,0xffff0040,0xffff0060,0xffff0080,
0xffff00A0,0xffff00C0,0xffff00E0,0xffE000ff,
0xffC000ff,0xffA000ff,0xff8000ff,0xff6000ff,
0xff4000ff,0xff2000ff,
};

// ------------------------------------------------------------
// Surge Verb Pad
int coff;       // value for shifting colors
long tm0 = 0;   // milliseconds at first draw
long maintimer; // current milliseconds
long tmbye;
/**
 * A Collatz number
 */
class TCollatzPoint {
  float branchlen = FIRST_BRANCHLEN;
  float x, y, angle;
  int num;
  public TCollatzPoint( int num, float x, float y, float angle ) {
    this.num = num; this.x = x; this.y = y; this.angle = angle;
  }  
  public TCollatzPoint branch( int num2, float deltaangle ) {    
    float angle2 = angle + deltaangle;
    float x2 = x + branchlen * cos( angle2 ) * zoom;
    float y2 = y + branchlen * sin( angle2 ) * zoom;
    TCollatzPoint res = new TCollatzPoint( num2, x2, y2, angle2 );
    return res;   
  }  
}

/**
 * Initilization stuff
 */
void setup() {
  frameRate( FPS );
  size( 1280, 720, JAVA2D);
  background(0);
  cx = width / 2;
  cy = height / 2;
  if ( frecord ) currscene = 0;
  zoom = 1;
  cy = height-height/10;
  drawCollatz(  ae , ao, BRANCHES );
  drawCollatz(  ae , ao, BRANCHES );
  fsetup = false;
}

/**
 * Draw the Collatz tree
 */
void drawCollatz( float aeven, float aodd, int maxdepth ) {
  TCollatzPoint buf[] = new TCollatzPoint[1024];
  TCollatzPoint buf2[] = new TCollatzPoint[1024];
  TCollatzPoint bufswap[];
  int depth = 0;
  int n = 0, m;
  buf[n++] = new TCollatzPoint( 1, 0, 0, PI / 4 );
  maxy = 0;
  miny = 0;
  strokeWeight( 2 ) ;  
  noFill();  
  while ( depth < maxdepth ) {
    if (currscene == 0) {
      stroke( 0xffffffff ); 
    } else {
      int c = colray[(coff + depth) % colray.length]; 
      //c = (c % 0xffffff) | 0x80000000;
      stroke( c ); 
    }
    m = 0;
    for (int i = 0; i < n; i++) {
      TCollatzPoint p = buf[i];
      int num2 = p.num * 2;
      if ( m >= buf.length - 1 ) break;
      TCollatzPoint p2 = buf[i].branch( num2, aeven );
      if (!fsetup) line( cx + p.x, cy - p.y, cx + p2.x, cy - p2.y );
      if ( p2.y > maxy ) maxy = p2.y;
      if ( p2.y < miny ) miny = p2.y;
      
      buf2[m++] = p2;
      if ( p.num > 1 && (p.num - 1 ) % 3 == 0) {
        num2 = (p.num - 1) / 3;
        p2 = buf[i].branch( num2, aodd );
        if (!fsetup) line( cx + p.x, cy - p.y, cx + p2.x, cy - p2.y );
        if ( p2.y > maxy ) maxy = p2.y;
        if ( p2.y < miny ) miny = p2.y;
        buf2[m++] = p2;
      }      
    }
    n = m;
    bufswap = buf2;
    buf2 = buf;
    buf = bufswap;
    depth++;
  } 
  strokeWeight( 2 ) ;  
  stroke( 0xff00ff00);
  fill(0xffffffff );
  for (int i = 0; i < n; i++) {
    TCollatzPoint p = buf[i];
    if ( ! fsetup) ellipse( cx + p.x, cy - p.y, 7, 7 );
  } 
  float f = (maxy - miny) / height;
  float fy = (maxy + miny) / 2;
  if ( fsetup) {
      zoom += (0.92 - f );
      cy += (height/2 + fy - cy);
  } else {
    if ( currscene == 0 ) {
      //println( "maxy=" + maxy + " miny="+miny + " fy="+fy + " cy="+cy + " f="+f );
      //zoom = 1 / f;
      //cy = height;
    } else {
      zoom += (0.92 - f )/10;
      cy += (height/2 + fy - cy)/100;
    }
  }
}

/**
 * Current elapsed millisecodns (measured differenty if recording)
 */
long elapsedMs() {
  if ( frecord ) {
    return (long) 1000.0*(frameCount-1) /FPS; 
  } else {
    return millis() - tm0;
  }
}

/**
 * Check if we've reached a new scene; if it has changed change the animation parameters
 */
void checkScene() {
  int sc = 0;
  for (int i = 0; i < scenelen.length; i++) {
    if (maintimer > scenelen[i]) sc = i;
  }
  if ( abs( ae ) < 11*PI/180 && abs( ao ) < 11*PI/180 ) sc = 3;
  if (sc != currscene) {
    currscene = sc;
    switch( currscene ) {
      case 1 : 
        break;
      case 2 :
        target_speede = -SPEED_AEVEN;
        target_speedo = -SPEED_AODD;
        break;
      case 3 :
        acce *= 2; acco *= 2;
        tmbye = maintimer + 10000;
        target_speede = 0;
        target_speedo = 0;
        break;
    }
  }
}

/**
 * Very naive speed management
 */
float changeSpeed( float curr, float target, float acc ) {
  if ( curr < target ) {
    curr += acc;
    if ( curr > target ) curr = target;
  }
  if ( curr > target ) {
    curr -= acc;
    if ( curr < target ) curr = target;
  }
  return curr;
}
/**
 * Main draw routine
 */
void draw() {
  maintimer = elapsedMs();
  background(0);
  drawCollatz(  ae , ao, BRANCHES );
  if ( currscene > 0) {
    ae += currspeede * (PI/90) / FPS;
    ao += currspeedo * (PI/90) / FPS;
    currspeede = changeSpeed( currspeede, target_speede, acce );
    currspeedo = changeSpeed( currspeedo, target_speedo, acco );
    
    if ( ( frameCount % (rollcol*FPS) ) == 0 && currscene < 3) coff++;
  }
  if ( frecord ) {
    checkScene();  
    if ( tmbye == 0 || maintimer < tmbye ) {
      numsaved = frameCount;
      saveFrame( recorddir + "vid-######.tga" );      
    } else {
      strokeWeight( 1 );
      stroke(0xffffffff);
      fill(0xffffffff);
      text( "VIDEO ENDED RECORDED FRAMES: " + numsaved, 50, 50 );
    }
  } 
}