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











Leave A Comment