Control a running synth: Ambient soundscape

#1

I must admit, the use of control is still something I am still trying to understand in all its subtleties. Especially the subject of fading and gradual changes of sound are interesting to me (in the context of live coding). Here is another snippet as a result of that quest, which some might be interested in:

use_bpm 120

live_loop :suenth do
  use_synth :tri # try different synths ...
  use_synth :dsaw
  use_synth :dtri
  use_synth_defaults attack: 0.25, release: 3
  
  n = (chord [:c3, :f3, :g3, :bb2].choose, [:sus4, :sus2].choose, num_octaves: 3)
  
  with_fx :reverb, room: 0.75, mix: 0.75 do
    with_fx :level, amp: 0 do |lvl|
      with_fx :rhpf, res: 0.85, cutoff: 30 do |rhp|
        
        with_fx :panslicer, phase: 0.5 do
          in_thread do
            64.times do
              play note: n.choose if one_in 2
              sleep 0.25
            end
          end
        end
        
        puts "Fade in ..."
        control rhp, cutoff: 90, cutoff_slide: 8
        control lvl, amp: 1, amp_slide: 8
        sleep 8
        puts "... fade out."
        
        control rhp, cutoff: 20, cutoff_slide: 8
        control lvl, amp: 0, amp_slide: 8
        sleep 8
        
      end
    end
  end
end
1 Like
#2

Very nice sounds there. I’m now looking into how to do more sophisticated sound design in Sonic Pi, and controlling synth parameters is going to be the way to do it. I was thinking along the same lines as you, but thinking about making reusable synth voices through functions. What I did, which sounds much less impressive than your version (I may steal some of your ideas :slight_smile:) is playing around with FM a bit. This is an attempt at 4op FM with controllable modulation depth.

use_bpm 120

define :envfm do |nn=60, sustain=1, dslide=0.1, amp=1|
  
  use_synth :fm
  use_synth_defaults sustain: sustain, release: 0.1, depth: 12, depth_slide: dslide
  
  voice = play note( nn ), divisor: 0.125, amp: amp * 0.5
  voice2 = play note( nn ) * 1.0005, divisor: 0.25, amp: amp * 0.3
  control voice, depth: 0
  control voice2, depth: 0
end


notes = (knit :c4, 4, :d4, 4, :g4, 4, :e4, 4)

16.times do
  tick
  envfm( notes.look, 0.3 )
  
  sleep 0.5
end

EDIT: This is a bit more FM-bongy.

use_bpm 120

define :envfm2 do |nn=60, pan=0|
  use_synth :fm
  use_synth_defaults sustain: 0, release: 1
  
  voice1 = play note( nn ), divisor: 1.0/3, depth: 7, depth_slide: 0.5, amp: 0.5, pan: pan
  voice2 = play note( nn ) * 2, divisor: 1.0/4, depth: 7, depth_slide: 0.5, amp: 0.3, pan: pan
  voice3 = play note( nn ) * 4, divisor: 1.0/5.7, depth: 7, depth_slide: 0.5, amp: 0.2, pan: pan
  
  control voice1, depth: 0
  control voice2, depth: 0
  control voice3, depth: 0
end

notes = (scale :c3, :minor_pentatonic, num_octaves: 3)

with_fx :reverb, mix: 0.7 do
  
  live_loop :bongs do
    
    envfm2( notes.choose, rrand( -1, 1 ))
    sleep 0.25
  end
end
1 Like
#3

Really nice and interesting, I need to learn this function (control), it’s fundamental for make soundscapes, I had work a lot with Csound before meeting SonicPi and until 3 minutes ago I was convinced that the synths in Sonic Pi couldn’t change their values. Fortuneally I was in error thinking that!

1 Like
#4

I prefer mine a bit more ‘Cosmic’… pass the Star-dust please !

Eli…

use_bpm 60

define :envfm2 do |nn=60, pan=0|
  
  use_synth_defaults sustain: 0, release: 1
  
  voice1 = play note( nn ), divisor: 1.0/3, depth: 7, depth_slide: 0.5, amp: 0.5, pan: pan
  voice2 = play note( nn ) * 2, divisor: 1.0/4, depth: 7, depth_slide: 0.5, amp: 0.3, pan: pan
  voice3 = play note( nn ) * 3, divisor: 1.0/5.7, depth: 7, depth_slide: 0.5, amp: 0.2, pan: pan
  
  control voice1, depth: 3
  control voice2, depth: 1
  control voice3, depth: 5
end

notes = (scale :a1, :minor_pentatonic, num_octaves: 3)
notes1 = (scale :a2, :minor_pentatonic, num_octaves: 1)

with_fx :reverb, mix: 0.7 do
  
  live_loop :bongs do
    use_synth :mod_sine
    envfm2( notes.choose, rrand( -1, 1 ))
    use_synth :piano
    envfm2( notes1.choose, rrand( -1, 1 ))
    sleep 0.25
  end
end
1 Like
#5

I can’t divorce myself from my 1980s beats :smile:

use_bpm 60

define :envfm2 do |nn=60, pan=0|
  
  use_synth_defaults sustain: 0, release: 1
  
  voice1 = play note( nn ), divisor: 1.0/3, depth: 7, depth_slide: 0.5, amp: 0.5, pan: pan
  voice2 = play note( nn ) * 2, divisor: 1.0/4, depth: 7, depth_slide: 0.5, amp: 0.3, pan: pan
  voice3 = play note( nn ) * 3, divisor: 1.0/5.7, depth: 7, depth_slide: 0.5, amp: 0.2, pan: pan
  
  control voice1, depth: 3
  control voice2, depth: 1
  control voice3, depth: 5
end

notes = (scale :a1, :minor_pentatonic, num_octaves: 3)
notes1 = (scale :a2, :minor_pentatonic, num_octaves: 1)

with_fx :reverb, mix: 0.7, amp: 0.1 do
  
  live_loop :bongs do
    use_synth :mod_sine
    envfm2( notes.choose, rrand( -1, 1 ))
    use_synth :piano
    envfm2( notes1.choose, rrand( -1, 1 ))
    sleep 0.25
  end
end

bassnotes = (ring :a2, :a1, :a1, :c2, :d2, :a1, :a1, :c2, :d2,
             :d2, :e2,  :g2, :g2, :gs2  )

live_loop :bass do
  
  use_synth :dsaw
  use_synth_defaults sustain: 0, release: 0.3, res: 0.3, cutoff: 60
  
  index = 0
  
  with_fx :eq, low_shelf: 1.2  do
    
    at [0.0, 0.25, 0.75, 1.0, 1.25, 1.75, 2,
    2.25, 2.75, 3, 3.25, 3.5, 3.75, 3.825] do
      play bassnotes[index]
      index = index + 1
    end
  end
  
  
  sleep 4
end

live_loop :drums do
  
  at [0.0, 0.375, 0.75, 1.25, 2, 2.375, 2.75, 3.25, 3.75 ] do
    sample :bd_haus
  end
  
  with_fx :reverb, mix: 0.5 do
    
    at [0.5, 1.5, 2.5, 3.5, 3.75] do
      sample :sn_dolf
    end
    
    at [0.25, 0.75, 1.25, 1.75, 2.25, 2.75, 3.25, 3.75, 3.875 ] do
      sample :drum_cymbal_closed
    end
  end
  
  sleep 4
end

2 Likes
#6

Another snippet… this time a long sustain. Quite hard to control amplitude and resonance until it fits for my taste.

use_bpm 120

live_loop :suenth do
  n = (chord [:c2, :f2, :g2, :e2].choose, :sus4, invert: [-1, 0, 1, 2].choose, num_octaves: 4)
  puts "Fade in ..."
  with_fx :rhpf, res: 0.5, cutoff: 30 do |rhp|
    
    with_fx :slicer, smooth: 0.5 do
      
      with_fx :panslicer, phase: [0.25, 0.5, 0.75].choose, smooth_down: 0.25, smooth_up: 0.25 do
        
        s = synth :dsaw, note: n, sustain: 64, cutoff: 80, amp: 0.0
        control s, amp: 1, amp_slide: 128
        control rhp, res: 0.925, res_slide: 16, cutoff: 90, cutoff_slide: 32
        sleep 32
        puts "... fade out."
        control s, amp: 0.0, amp_slide: 24
        control rhp, res: 0.65, res_slide: 16, cutoff: 50, cutoff_slide: 16
        sleep 16
        
      end
    end
    
  end
end
#7

I like this! Will have a play using it as a basis.

#8

I use control a lot while playing on the raspberry pi, since creating effect synths is really expensive. So i tend to do stuff like this (from my practice session last night). I’m getting my time states :toggle1, :fx1, :fx2 from TouchOSC in another buffer. I’ve shared the setup in another post.

live_loop :loop1 do
  if (get(:amp1) > 0) then
    with_fx :echo, reps: 32 do |f|
      control f, mix: get(:toggle1) * get(:fx1), decay: 1 + (4 * get(:fx2)), phase: get(:fx2)
      
      sample :ambi_swoosh, amp: get(:amp1),rate: rrand(0.4,0.6),pan: rrand(-1,1)
      sleep 0.25
      
    end
    
  else
    sleep 1
  end
end
1 Like
#9

Wonderful! Thank you very much!

#10

Hi @chris.krakou,

yes, I also make use of control quite often. It is a very nice way to bring live to a sound.

Currently I don’t use any external controllers so I am experimenting on controlling effects (and synth options) in an automated way (see my examples). @robin.newman did some nice work on the issue of fading.

Though this works quite well, I am still looking for an even more simple solution (which does not require prewritten functions or any other preparation) for my live coding practice.

#11

Nice.

Eli…

set :toggle1, 0.25
set :fx1, 2
set :fx2, 0.1
set :fx3, 1
set :amp1, 2

live_loop :change do
  change = (line 0.1, 2, inclusive: true, steps: 15).repeat(5)
  set :fx2, change.look
  # puts change.look
  tick
  sleep 1
end



live_loop :loop1 do
  if (get(:amp1) > 0) then
    with_fx :echo, reps: 32 do |f|
      control f, mix: get(:toggle1) * get(:fx1), decay: 1 + (1 * get(:fx2)), phase: get(:fx3)
# Or try this one...
# sample  [:bass_trance_c,:elec_blup, :elec_blip,:elec_blip2,:drum_heavy_kick].choose,      
      sample [:bass_trance_c,:elec_blup, :elec_blip,:elec_blip2,:ambi_piano].choose,

        amp: get(:amp1),rate: rrand(0.4,0.6),pan: rrand(-1,1)
      sleep 0.25
      
    end
    
  else
    sleep 1
  end
end