Smoothly fading samples and synths

Hi,

for quite some time I was trying to figure out how I could fade in (and out) bits of music (resp. live_loops). I did not want the fade to be dependant on the runtime of the loop (such as to set amp of a sample or synth using a line I am ticking through). So I came up with this solution:

# Fading in and out a sample
use_bpm 120

live_loop :fade_inout_amen do

  vol = (line 0, 1, inclusive: true, steps: 24).mirror

  s = sample :loop_amen, beat_stretch: 4, amp: vol.tick
  puts "---------- Vol 1: #{vol.look} ----------"
  control s, amp_slide: 4, amp: vol.tick
  puts "---------- Vol 2: #{vol.look} ----------"
  sleep 4
end
# Fading in and out a synth pattern
use_bpm 120

live_loop :fade_inout_synth do
  vol = (line 0, 1, inclusive: true, steps: 125).mirror
  notes = (scale :e3, :minor_pentatonic, num_octaves: 2).shuffle
  s = synth :dtri, cutoff: 70, note: :e3, sustain: 8, release: 0, amp: vol.tick(:v)
  puts "---------- Vol 1: #{vol.look(:v)} ----------"
  32.times do
    control s, note: notes.tick, note_slide: 0.005, amp_slide: 0.125, amp: vol.tick(:v)
    puts "---------- Vol 1: #{vol.look(:v)} ----------"
    sleep 0.25
  end
end

Probably trivial for the real coders amongst us but a tiny revelation for me. I suspect more complex situations where this might not work but in these two cases it does.

Just one downside: My ear tells me that the line should increase more in the lower registers (probably the values have to increase ā€˜logarithmicā€™ in the right way). The blending seems to become slower as it is getting louderā€¦

In this context you might enjoy:

8 Likes

One more thing: I have an example saved by @robin.newman who did that already in a similar way using control: https://gist.github.com/rbnpi/a08f866d7a72e0f58b6f59d23a44a89d. Anyway: always nice to find out something on your own, even if it has been done before :wink:

dear @Martin this argument is very interesting for me.
i am a newbie of sonic pi and i am discovering all potentialities of this software.
one of my fatigues is just discover how to make fade in and fade out of the samples and synths but also the tracks themselves.
i would like not to use editing to create new tracks :face_with_raised_eyebrow:
so: can i ask u again to explain it to me?! :persevere:
sorry and thanks a lot

Hi @MarieRose,

I am not really sure, what you mean by that:

I havenā€™t had the need/wish to fade in a whole track (which in Sonic Pi somehow means: to fade in a buffer or even more than one). It probably depends on how you create your tracks. I usually use several live_loops and will teak the track while it is running. If you wanā€™t to create complete, linear tracks (usually using in_thread and loops with a defined number of iterations) this might be a different thing.

You might come to a result by using the with_fx :level which is basically a volume knob.

In my example above the basic idea is to gradually increase the amp-option (of a sample or synth). This can be achieved with tick and look (see e. g. here); the slightly more complicated but quite useful addition is to also use control (see above). But maybe you wonā€™t need that for now. You should however have a look at the tutorial and check out control. It bears interesting options!

Do you care to post an example of one of your track which you want to fade in? If not me probably someone else comes up with ideas!

2 Likes

thank u so much @Martin :heart_eyes:
thanks to your suggestions i discovered new ideas

ok, i post here an example:

in_thread do
sleep 2
loop do
32.times do
with_fx :reverb, room: 0.3 do
sample :bd_boom, amp: 15, rate: 0.5
sleep 4
end

  with_fx :echo, mix: 0.4, phase: 0.50 do
    sample :guit_harmonics, rate: 0.5, amp: 0.5
    sleep 10
    with_fx :echo, mix: 0.4, phase: 0.25 do
      with_fx :reverb, room: 0.5 do
        sample :guit_em9, rate: -2, amp: 0.1
        sleep 6
      end
    end
    
    in_thread do
      sleep 8
      use_synth :dark_ambience
      with_fx :reverb, mix: 0.3 do
        
        
      end
      
      in_thread do
        sleep 12
        with_fx :echo, mix: 0.4, phase: 0.25 do
          with_fx :reverb, room: 0.3, mix: 1 do
            sample :guit_em9, rate: 0.5, amp: 0.2
            sleep 4
          end
        end
        
        
        
        in_thread do
          sleep 10
          use_synth :dark_ambience
          with_fx :reverb, mix: 0.3 do
            live_loop :note1 do
              play choose([:D4,:E4]), attack: 6, release: 6
              sleep 4
            end
          end
        end
        
        live_loop :note2 do
          play choose([:Fs4,:A4]), attack: 4, release: 5
          sleep 4
        end
        
        
      end
      
      
    end
  end
end

end
end

i have many questions about this example (i built it to learn from your suggestions :sweat: )
1.i would like to learn how to fade out the track (and how to fade in)
2.how can i introduce the track with the bass drum in solo mode and then, after 4/6 shots, let the other elements in? i would like to let the elements in one after oneā€¦but i canā€™t put them in a thread cause if i do it they move together

just these two questions for the moment are enough :sweat_smile:

thank u so much

ps:

i would like to use only sonic pi for the moment and donā€™t use other softs to make editing or to transform the tracks that i build with sonic piā€¦by now

Apologies: My machine had a serious hickup. Thatā€™s why the code did not run. If youā€™ve already read, what I have wrote, forget about it. Now the code runs smoothly so I might be able to provide some ideas how to fade ā€¦ Will take some timeā€¦

One thing: I have never used in_thread and live_loop together. Does not really make sense to me. As a rule of thumb (no dogma, just a model to get started) you can go with this:

in_thread: building tunes which run (for the time of all sleeps added up including loops) and end automatically. A linear and traditional way to build a track. If you evaluate several times (= press the run-button), you will create a new running tune (more precisely: you will create new threads any time you press run)

live_loop: live playing, tweaking the code while it runs, potentially never ending execpt you stop the whole buffer (press the stop-button) or one live_loop by inserting stop and run the code again. By pressing run there will be no new instances of your existing live_loops. Sonic Pi just looks at whether new code has been added. This way extend and tweak your tracks during runtime.

1 Like

I must admit, thatā€™s too tricky for me.

I try to go into detail (which others might be much more able than me):

One tricky thing is that you have nested in_threads. This makes the code quite complicated. It is much easier if theyā€™re all on the same level (not nested). I have no idea how to fade in a whole track (though this is surely possible).

Letā€™s assume you have a set of not-nested in_thread-blocks. A sleep within one block (or several added up) determine how long this block runs (e. g. 16 beats which is 4 bars assumed we have a four-four time). sleeps outside the in_thread-blocks separate the blocks from each other(s) in time. The time is crucial, not only to determine how long the track takes and which parts play together but also if you want to change values (such as the volume) automatically.

To manipulate the volume, you will have to dynamically increase/decrease your amp levels. This must somehow happen in time and cannot (be easily) done independant from all your sleeps. So usually the runtime of a loop (or live_loop) determines not only how long your music or some musical element plays but also how fast or slow you can fade (or teak any other value automatically during runtime).

Here is a simple example, which might provide a base for futher experiments. I hope my comments make things clear

# set a variable which contains a list of values
# (ramp 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9)
# the .ramp takes care that once the max. volume is
# reached it stays; without it the volume goes back to
# 0.1 once it has reached 0.9 because the data structure
# will be a 'ring', not a 'ramp' (see language reference).
# If you swap 0 and 1 to `(line 1, 0, steps: 10) you'll get
# a fadeout. If you take 30 instead of 10 you'll get
# a slower fade.
vol = (line 0, 1, steps: 10).ramp

in_thread do
  32.times do
    # with each run grap the next value from 'vol'
    # see 'tick' and 'look' in the language reference
    sample :bd_boom, amp: vol.tick
    sleep 1
  end
end

Sorry I canā€™t come up with a solution for your case right now.

2 Likes

Hi Martin,

Itā€™s a bit rough n ready but I use this as a master fade in/out on my
Soundcloud tracksā€¦

I added a little randomised arp gen to while away the 'sleep 32ā€™
when you watch it workingā€¦

Eliā€¦

# arpeggios
use_bpm 60
set_volume! 0
sleep 1 # stops an annoying 'click when setting volume...

fade_in = line(0,5, steps: 10,inclusive: true)
fade_out = line(0,5, steps: 10,inclusive: true).reverse

define :master_fade_in do
  in_thread do
    fade_in.each do
      tick
      set_volume! fade_in.look
      sleep 1
    end
    stop
  end
end

define :master_fade_out do
  in_thread do
    fade_out.each{
      tick
      set_volume! fade_out.look
      sleep 1
    }
    stop
  end
end

in_thread do
  master_fade_in
  sleep 32 #do something like play a tune...
  master_fade_out
end


b = chord(:b, :minor)
g = chord(:g, :major)
a = chord(:a, :minor)
e = chord(:e, :minor)
c = chord(:c, :major)
d = chord(:d, :major)

chords = [b, g, a, e, c, d]

live_loop :rando do
  r=Random.rand(1..10000)
  use_random_seed r
  chords = chords.shuffle
  sleep 4
end


live_loop :main do
  use_synth :fm
  chords.each do |chord|
    this_phase = [0125, 0.25, 0.375, 0.5].ring
    with_fx :echo, decay: 0.8, mix: 0.25, phase: this_phase.look do
      bass = [chord[0], chord.choose].choose - 24
      with_synth :hollow do
        play bass, release: 3, amp: 1
        tick
      end
      use_synth :fm
      chord.each{|n|
        play n, sustain: 0.5, amp: 0.2;
        use_synth :blade
        play n+12, sustain: 0.5,amp: 0.1;
      sleep 0.25}
    end
  end
end
2 Likes

Hi @Eli,

great! Thanks a lot for expanding my knowledge! Havenā€™t thought about using set_volume! to do that.

1 Like

@Martin no apologiesā€¦ no problem!!! but thank u for your time :heart_eyes:
this is gonna be a hard problem for me :disappointed_relieved:
but thanks to @Eli too for the suggestions
now i want to make some experiments and then i will write to u too again
i hope to discover some new things useful for everyone :sunglasses:

thanks again and see u soon

1 Like

@MarieRose,

also, on your experimental journey, if you come across any ideas you wish ā€œjust workedā€ and had a bit of code youā€™d love to be able to write and it do what you expected it to, please let me know.

I always love hearing ideas which include:

  • context (what kind of thing youā€™re trying to do)
  • a code sketch (what kind of code youā€™d like to be able to write)
  • behaviour (what the code should do)

:slight_smile:

1 Like

Hi @MarieRose,

building on @Eli suggestion to use set_volume! I coded a short example which might help. Usually I do not use in_thread but I guess, that is what you might have had in mind. I am also not sure I did the counting right (did not check twice) but I hope the comments are correct; anyway, I guess the overall principle is sketched out (surely there are other ways to achieve similar results):

# beats and bars: 
# 1 bar = 4 beats = 16 * 0.25 beats
# if you count all the sleeps, the tune is 16 bars or 64 beats long
use_bpm 120
set_volume! 0


# volume fade = 4 bars (64 x 0.25 or 16 full beats)
in_thread do
  64.times do
    set_volume! (line 0,1, steps: 64, inclusive: true).ramp.tick
    sleep 0.25
  end
end

# one loop = one bar
# let the drums play for 16 bars, 4 bars fade in
in_thread do
  16.times do
    sample :loop_amen, beat_stretch: 4
    sleep 4
  end
end

# after the 4-bar-fade start the the bassline
sleep 16

# bassline is 2 bars long (8 beats)
# let it play along the drums which will last for
# 12 bars from here on ...
in_thread do
  with_synth :fm do
    with_synth_defaults release: 0.5, cutoff: 60, depth: 2, amp: 1.5 do
      6.times do
      play :c2
      sleep 0.5
      play :c2
      sleep 4
      play :g2
      sleep 3
      play :bb2
      sleep 0.5
    end
   end
  end
end

# start the keyboard after the bass phrase has played 2 times
# = 16 beats
sleep 16

in_thread do
  with_fx :reverb, room: 0.75, mix: 0.5 do
    with_synth :dsaw do
      with_synth_defaults cutoff: 80, amp: 1.5 do
        4.times do
          play (chord :c4, :minor7), release: 0.25
          sleep 1.5
          play (chord :c4, :minor7), release: 1.25
          sleep 1.5
          play (chord :d4, :minor7), release: 0.25
          sleep 3.5
          play (chord :d4, :minor7), release: 0.25
          sleep 1.5
        end
      end
    end
  end
end

# remaining beats/beats for the track is 32 beats / 8 bars
# let 4 bars play and then fade out for 4 bars
sleep 16

# volume fade takes 64 x 0.25 = 4 bars
in_thread do
  64.times do
    set_volume! (line 1,0, steps: 64, inclusive: true).ramp.tick
    sleep 0.25
  end
end

stop
2 Likes

thank u so much @Martin
it seems working
i just need to elaborate on the language :sweat_smile:
u will probably hate me :disappointed_relieved: but i tried to do the same thing with the fx
i am trying to make a fade in and a fade out with the fx
a sort of automationā€¦

do u know how to make it?
cause i investigate in the manual but i did not find anything about it
now i would like to study ruby"ā€¦

thank u so much,

marie r.

Hi MarieRoseā€¦

I got here before Martin, but Iā€™m pretty sure he would say
much the same thingā€¦ use the ā€˜with_fx :levelā€™ command,
and a line fadeā€¦ example below:

Eliā€¦

use_bpm 120
set_volume! 3
fade_out = (line 3,0, steps: 6, inclusive: true)


in_thread do
  with_synth :fm do
    with_synth_defaults release: 0.5, cutoff: 60, depth: 2, amp: 1 do
      6.times do
        with_fx :level, amp: fade_out.tick do
          play :c4
          sleep 0.5
          play :c4
          sleep 2
          play :g4
          sleep 1.5
          play :bb4
          sleep 0.5
        end
      end
    end
  end
end
2 Likes

hi @Eli thank u so much
this evening is dedicated to coding :upside_down_face: cause i am working at the tracks for my school (conservatory)
i hope that this occasion can be good to learn coding and with your company this can happen :sunny:

thank u again

Hi @Eli,

yes, youā€™re right, I would have :wink: . The only downside is, that you do not get a continious fadeout because every loop cycle you have just one value (of fade_out); surely this can be an effect you wantā€¦ but ā€¦

ā€¦ amusingly, weā€™re now back to the beginning of the thread: If you toss in a control for :level, apply a double tick and tweak some values, youā€™ll have it:

use_bpm 120
set_volume! 3
fade_out = (line 1,0, steps: 20, inclusive: true).ramp


in_thread do
  with_synth :fm do
    with_synth_defaults release: 0.5, cutoff: 60, depth: 2, amp: 1 do
      12.times do
        with_fx :level, amp: fade_out.tick do |lev|
          control lev, amp: fade_out.tick, amp_slide: 6
          play :c4
          sleep 0.5
          play :c4
          sleep 2
          play :g4
          sleep 1.5
          play :bb4
          sleep 0.5
        end
      end
    end
  end
end
1 Like

wooow
thanks @Martin :ok_hand: :pray:

I much prefer your version. :slight_smile:

Out of interestā€¦ Iā€™ve been trying to code a ā€˜dropā€™, like
they use in a lot of hip-hop / houseā€¦

They double then triple the drums / snare / volume over
about 10 seconds, then cut it off deadā€¦ and ā€˜dropā€™
(for example), a female vocal into the quiet spot, before
restarting the drums etcā€¦

Any ideas? Iā€™ve tried depth and density, but it just doesnā€™t
seem to be right somehowā€¦

Eliā€¦

1 Like

:persevere:
sorry
but it does not seem to work
first I had forgotten a command and it seemed to work :disappointed_relieved:
sorry if I insist, probably I did not understand the code
i understand whatā€™s ā€œrampā€, whatā€™s ā€œtickā€ and the other commands but i donā€™t understand the reason why the code seems not to function.

sorry again

Looking at @josephwilkā€™s post (Making a ā€˜dropā€™) this even becomes much simpler with set_mixer_control!. Sam has taken care of that already.

But as the saying goes: detours increase the local knowledge.

# beats and bars: 
# 1 bar = 4 beats = 16 * 0.25 beats
# if you count all the sleeps, the tune is 16 bars or 64 beats long
use_bpm 120
set_mixer_control! amp: 1, amp_slide: 8

# one loop = one bar
# let the drums play for 16 bars, 4 bars fade in
in_thread do
  16.times do
    sample :loop_amen, beat_stretch: 4
    sleep 4
  end
end

# after the 4-bar-fade start the the bassline
sleep 16

# bassline is 2 bars long (8 beats)
# let it play along the drums which will last for
# 12 bars from here on ...
in_thread do
  with_synth :fm do
    with_synth_defaults release: 0.5, cutoff: 60, depth: 2, amp: 1.5 do
      6.times do
      play :c2
      sleep 0.5
      play :c2
      sleep 4
      play :g2
      sleep 3
      play :bb2
      sleep 0.5
    end
   end
  end
end

# start the keyboard after the bass phrase has played 2 times
# = 16 beats
sleep 16

in_thread do
  with_fx :reverb, room: 0.75, mix: 0.5 do
    with_synth :dsaw do
      with_synth_defaults cutoff: 80, amp: 1.5 do
        4.times do
          play (chord :c4, :minor7), release: 0.25
          sleep 1.5
          play (chord :c4, :minor7), release: 1.25
          sleep 1.5
          play (chord :d4, :minor7), release: 0.25
          sleep 3.5
          play (chord :d4, :minor7), release: 0.25
          sleep 1.5
        end
      end
    end
  end
end

# remaining beats/beats for the track is 32 beats / 8 bars
# let 4 bars play and then fade out for 4 bars
sleep 16
set_mixer_control! amp: 0, amp_slide: 8
stop