Smoothly fading samples and synths


#21

Great technique, Martin.
Can use it for rate, pan, amp, release, … Opens up a whole new load of barely-music experiments :rofl:

#dueling blips

live_loop :panner do
  pann = (line -1, 1, inclusive: true, steps: 64).mirror
  vol = (line 0.1, 1, inclusive: true, steps: 32).mirror
  rat = (line 2, 4, inclusive: true, steps: 64).mirror
  
  2.times do
    if one_in(2) then
      sample :elec_blip, rate: rat.tick, pan: pann.tick, amp: 1 - vol.tick
    else
      sample :elec_blip2, rate: 6 - rat.tick, pan: pann.tick * -1, amp: vol.tick
    end
    sleep 0.2
  end
  
  with_fx :reverb, room: rrand(0.2, 0.75) do
    sample :bd_klub, amp: vol.look - 0.1 if one_in(4)
  end
  sample :bd_ada, amp: 0.2
end

#22

Be careful about using tick in multiple places. tick is local to the thread not the ring. Rings do not have state and therefore don’t have any notion of the current index.


#23

Hi,

I’d appreciate very much if someone could run my first to code examples (see top of this thread) and check if it does what I said it would (fade in/out smoothly). I did use this several times in other context and it worked (otherwise I would not have posted it :wink: ). Since a few weeks it doesn’t anymore and I wonder if there is something wrong with my installation (SP 3.1).

Cheers
Martin


#24

A while ago, I found a way to fade individual tracks(live_loops) in and out.
I use a ramped line, with minimal maths involved:

I usually use individual live_loops for ‘tracks’, so I can just use the local tick.

PS:
@Martin Both code snippets work as expected.
I run SP 3.1 on Windows.


#25

Hi @Davids-Fiddle,

thanks very much for testing!

And yes, I also do use line or range (using the syntax (range 0,1,0.1).ramp). The thing is: I was looking for a solution which is not dependant on the time a live_loop runs: So in case I have a loop which has a sleep of 4 (see the :loop_amen example) I wanted a smooth fading and not a fade where the volume increases stepwise only every four beats. That’s why I choose this approach. So now I will have to find out why my SP doesn’t do it anymore … :frowning:

Nevertheless I will check out your tutorial (which I have not yet). So thanks for sharing!


#26

So many great ideas here for fading! Thanks!

Has anyone experimented with something akin to fade groups? Particularly in a live-code context for quicker modifications of loops in progress. One thing I’d like to do is be able to target a given live_loop and apply a fade (or perhaps toggle a mute?) to it. For example:


# Apply a fade to only loops a and b, letting c play at full volume
apply_fade([:a, :b])

# Or alternately - only c and a are fading in and b is full volume.
# apply_fade([:c, :a])

live_loop :a do
  # play stuff
end

live_loop :b do
  # play stuff
end

live_loop :c do
  # play stuff
end

#27

Here is a sample progarm which can control three separate loops in this way.
The code is almost identical for each loop section.
The function apply_fade lets you control each loop with one command. setting data to 1 fades loop on
setting data to 0 fades loop off.
You could put more than one loop inside each fx :level and they would be controlled together.
Fade time can be changed by changing amp_slide times
I used sample loops for teh loops but you can put anything you want in them. You could also use a metronome loop to sync them if required.

#Program controls fade up/down of three live_loops
#fade time 1 beat, but can be adjusted using slide times
#can be different for each loop if required

define :apply_fade do |flist,fvalue|
  flist.zip(fvalue).each do |f,v| # allows lists to be linked and corresponding values to be processed
    set f,v
  end
end

apply_fade([:La,:Lb,:Lc],[0,1,0]) #set fade values 1 on, 0 off

with_fx :level,amp: 1 do |va|
  in_thread do
    loop do
      control va,amp: get(:La),amp_slide: 1
      sleep 1
    end
  end
  
  live_loop :a do
    sample :loop_amen,beat_stretch:2
    sleep 2
  end
end

with_fx :level,amp: 1 do |vb|
  in_thread do
    loop do
      control vb,amp: get(:Lb),amp_slide: 1
      sleep 1
    end
  end
  
  live_loop :b do
    sample :loop_tabla,beat_stretch:8
    sleep 8
  end
end

with_fx :level,amp: 1 do |vc|
  in_thread do
    loop do
      control vc,amp: get(:Lc),amp_slide: 1
      sleep 1
    end
  end
  
  live_loop :c do
    sample  :loop_garzul,beat_stretch:8
    sleep 8
  end
end

#28

Hi Martin,

Wow, this threads covered a lot of ground… So, heres a little
drum beat, with 2 different ‘backgrounds’, fading into each other
and providing a composite background…

Initially you only get the beat… If you take the stop out of either
background, you will hear it fade in and out.

If you take out both stop 's you get the mixed background

This isn’t really meant to teach anything to anyone… I
was just pottering around and it sort of wrote itself… :slight_smile:

Eli…

#Spiralysis
#by Eli...

use_bpm 120

bg1 = (ring 0.0,0.1,0.2,0.3,0.4,0.5,0.0,0.0).mirror
bg2 = (ring 0.5,0.4,0.3,0.2,0.1,0.0,0.0,0.0).mirror

melody_1 = [:c4,:r,:ds4,:ds4,:g4,:c4,:r,:gs4,:r,:r,:gs3,:r,:g3,:r,:r,:r].ring

live_loop :beats do
  sleep 1
end

live_loop :bar do
  sleep 4
end

live_loop :mixer do
  tick
  set :bvol1, bg1.look
  set :bvol2, bg2.look
  sync :bar
end

live_loop :kick, sync: :beats  do
  sample :bd_haus
  sleep 1.5
  sample :bd_haus
  sleep 1
  sample :bd_haus
  sample :drum_cymbal_closed
  sleep 1
  sample :bd_haus
  sample :drum_cymbal_closed
  sleep 0.5
end

live_loop :kick1, sync: :bar do
  sample :bd_ada
  sleep 1
  sample :bd_ada
  sample :sn_dolf, sustain: 0, release: 0.08, hpf: 80
  sleep 1
end

live_loop :tom, sync: :beats  do
  sample :drum_tom_lo_soft
  sleep 0.5
end

live_loop :snap, sync: :beats  do
  sleep 1
  if rand(1) < 0.75 then
    sample :perc_snap, amp: 0.5
  else
    sample :perc_snap2, amp: 0.5
  end
  sleep 1
end

with_fx :reverb, mix: 0.5, room: 0.9 do
  with_fx :ixi_techno, mix: 0.75, room: 0.9 do
    
    live_loop :background1, sync: :beats do
      
      stop
      
      this_vol = get :bvol1
      use_synth_defaults amp: this_vol * 4
      use_synth (ring :supersaw, :prophet, :prophet, :tech_saws).tick
      3.times do
        play :C4, cutoff: rrand(60,80)
        sleep 0.5
        play :G3, cutoff: rrand(60,90)
        sleep 0.5
        play :C4, cutoff: rrand(60,70)
        sleep 0.5
        play :Gs3, cutoff: rrand(60,80)
        sleep 0.25
        play :Gs3, cutoff: rrand(70,100)
        sleep 0.25
      end
      1.times do
        play :c4, cutoff: rrand(60,80), release: 1
        sleep 0.5
        play :g4, cutoff: rrand(60,90), release: 1
        sleep 0.5
        play :c4, cutoff: rrand(60,70), release: 1
        sleep 0.5
        play :gs3 + 7, cutoff: rrand(80,100), release: 1
        sleep 0.5
      end
    end
    
    live_loop :background2 do
      
      stop
      
      sync :beats if rand(1) < 0.5
      this_vol = get :bvol2
      
      use_synth_defaults cutoff: 70, release: 1.2, amp: this_vol * 4, pulse_width: rrand(0,1)
      use_synth [:subpulse, :pulse].choose
      if rand(1) < 0.75 then
        with_fx :ixi_techno, mix: 0.55, room: 0.85, damp: 0.8 do
          16.times do
            play melody_1.look - 12
            sleep 0.25
            tick
          end
        end
      else
        use_synth :prophet
        16.times do
          play melody_1.look - 12
          sleep 0.25
          tick
        end
      end
    end
  end
end

#29

Hi @Eli,

yes, that’s an interesting idea to use a live_loop to set amp-values. The only thing which keeps me from doing that, is, that, to be applied, you depend on the runtime (the added sleeps) of the live_loop which calls these values. That is why I quite like the idea of amp_slide: It gives you more freedom to control your volume manipulation (or any other option) somehow independant from the time your life_loop needs to set another amp value:

Just imagine: you could have a synth melody changing every 0.25 compared to one with a release of 8. Actually you probably will not be able to fade the second one with ticking. It just takes to long. The other thing is, that using a ring and ticking through the values in most cases actually creates a stepwise fading. If you want to have it smoothly, you will need to apply amp_slide (either within the live_loops or by using set_mixer_control! for a whole buffer).

I updated my Sonic Pi Resources and tried to collect and comment different examples for fading (1,2).