by Gisbert Schürig

Two performers in a feedback loop, imitating each others sounds, introducing variations, playing with the timing, introducing new material, creating a musical structure in the widest sense. This is one of the constellation Phyla explored in our minimal improvisation research and that has inspired me when focusing on software to make music.

Look at my previous post to see some footage and also an emulation using Ableton live and Reaktor.

In this post, I want to show how that constellation can be used as a template for creating evolving musical structures in Sonic Pi.

I´m super happy about this piece of software because it gives me the ability to craft music in the very same way that I think about it. That is, the structure of the code of a piece of music is very close to how I think about this piece.

Let´s have a closer look at the constellation of two performers in a feedback loop to illustrate this point. There are:

– two performers
– action: producing sound
– relation: one after the other, and so on
– variation: slight changes performers make to the imitation
– regularity: the sounds following in a more regular or irregular fashion
– individuality: a tendency to either stick with one strand of sound(thus showing no individuality) or alternate between two

Sonic Pi offers procedures to emulate such a constellation, have a listen to two different realisations, the first one being rather calm…

…while the second example is more rhythmic:

Both versions are generated by the same lines of code. The first lines allow to bypass the usual determinism of Sonic Pi and get unpredictable results.
I hope my additional notes give you an idea how the code works. It is not perfect, you may get an error when trying to run it in Sonic Pi. Run it again and it will work, I´m still figuring out why that occurs. Look at the Sonic Pi Forum for details.

Have fun!

#Minimal Improvisation Imitation Simulation 3

t = Time.now.to_i#Setting the random seed according to the time
use_random_seed t#Results in different music every time
puts rand

use_synth :sine#choosing the sine synth


live_loop :variables do#defining the variables that can be changed during performance
  set :variation, 0.25#controls the amount of variation over time: 0 = no variation, 1 = maximum variation
  set :individuality, 0.5#individuality 0 results in gradual variation of one sound, maximum individuality of 1 results in two alternating sounds, each varied over time
  set :regularity, 0.6#high regularity (1 being the highest) results in less variation of inter-onset durations
  set :sprung, rrand(0.8, 1.2)#determining how far a varied pitch may differ from the previous one
  set :atk, 0.2#setting the maximum duration of the attack of the sounds
  set :rel, 2.5#setting the maximum duration of the release of the sounds
  sleep 5
end

#Setting the starting variables
#for two alternative strands of sounds
set :pitch1, rrand(45, 85)#pitch
set :lautst1, rrand(0.1, 1.2)#dynamics
set :einschwing1, rrand(0, get[:atk])#attack
set :ausklang1, rrand(0.1, get[:rel])#release
set :freq1, rrand(30, 130)#low-pass filter
set :wartezeit1, rrand(0.08, 3.8)#inter-onset duration

set :pitch2, rrand(45, 85)
set :lautst2, rrand(0.1, 1.2)
set :einschwing2, rrand(0, get[:atk])
set :ausklang2, rrand(0.1, get[:rel])
set :freq2, rrand(30, 130)
set :wartezeit2, rrand(0.08, 3.8)

set :action, [get[:pitch1], get[:pitch2]].choose#choosing which pitch to use first
set :zeit, [get[:wartezeit1], get[:wartezeit2]].choose#choosing which inter-onset intervall to use first

with_fx :reverb do
  live_loop :dialogue do
    if rand < get[:variation]#determining wether any variations on sound parameters should occur
      if rand < get[:variation]#if so, should the pitch be redifined?
        set :pitch1, rrand(45, 85)#if so, a new pitch is set randomly
      end
      if rand < get[:variation]#the same procedure applies to dynamics...
        set :lautst1, rrand(0.1, 1.2)
      end
      if rand < get[:variation]
        set :einschwing1, rrand(0, get[:atk])#...attack...
      end
      if rand < get[:variation]
        set :ausklang1, rrand(0.1, get[:rel])#...release...
      end
      if rand < get[:variation]
        set :freq1, rrand(30, 130)#...and low-pass filter.
      end
    end
    if rand > get[:regularity]#determining wether any variations regarding inter-onset intervall(that is the time between two sounds) should occur
      if rand > get[:regularity]#if so, should the first inter-onset intervall...
        if one_in(2)
          set :wartezeit1, get[:zeit]*get[:sprung]#...be multiplied...
        else
          set :wartezeit1, get[:zeit]/get[:sprung]#...or be divided?
      end
    end
    if rand > get[:regularity]#if so, should the second inter-onset intervall...
      if one_in(2)
        set :wartezeit2, get[:zeit]*get[:sprung]#...be multiplied...
      else
        set :wartezeit2, get[:zeit]/get[:sprung]#...or be divided?
        end
      end
    end
    if rand < get[:individuality]#individuality 0 results in gradual variation of one pitch, maximum individuality of 1 results in two alternating pitches
      set :action, get[:pitch1]
    end
    play get[:action], amp: get[:lautst1], attack: get[:einschwing1], release: get[:ausklang1], cutoff: get[:freq1], pan: 0.8#a sound is played
    if rand > get[:regularity]#regularity 0 results in constant redefinition of inter-onset intervalls, maximum regularity of 1 in very gradually changing inter-onset intervalls
      set :zeit, get[:wartezeit1]
    end
    sleep get[:zeit]#the inter-onset intervall is applied
    if rand < get[:variation]#the above code within the live_loop :dialogue defined the first of two possible strands of sound varied over time
      if rand < get[:variation]#what follows from here is a duplicate defining the second strand
        set :pitch1, rrand(45, 85)#I suppose there is a more efficient way to code this, any suggestions?
      end
      if rand < get[:variation]
        set :lautst1, rrand(0.1, 1.2)
      end
      if rand < get[:variation]
        set :einschwing1, rrand(0, get[:atk])
      end
      if rand < get[:variation]
        set :ausklang1, rrand(0.1, get[:rel])
      end
      if rand < get[:variation]
        set :freq1, rrand(30, 130)
      end
    end
    if rand > get[:regularity]
      if rand > get[:regularity]
        if one_in(2)
          set :wartezeit1, get[:zeit]*get[:sprung]
        else
          set :wartezeit1, get[:zeit]/get[:sprung]
      end
    end
    if rand > get[:regularity]
      if one_in(2)
        set :wartezeit2, get[:zeit]*get[:sprung]
      else
        set :wartezeit2, get[:zeit]/get[:sprung]
        end
      end
    end
    if rand < get[:individuality]
      set :action, get[:pitch2]
    end
    play get[:action], amp: get[:lautst2], attack: get[:einschwing2], release: get[:ausklang2], cutoff: get[:freq2], pan: -0.8
    if rand > get[:regularity]
      set :zeit, get[:wartezeit2]
    end
    sleep get[:zeit]
  end
end

About the Author -

Leave A Comment

Your email address will not be published. Required fields are marked *