# Fading live\_loop in /out?

**URL:** <https://in-thread.sonic-pi.net/t/fading-live-loop-in-out/2464>\
**Category:** Support, Help & Resources\
**Created:** [June 10, 2019, 5:32am UTC](https://in-thread.sonic-pi.net/t/fading-live-loop-in-out/2464 "2019-06-10T05:32:00Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Julien](https://dub1.discourse-cdn.com/flex017/user_avatar/in-thread.sonic-pi.net/julien/32/998_2.png) [@Julien](https://in-thread.sonic-pi.net/u/Julien)\
**Post date:** [June 10, 2019, 5:32am UTC](https://in-thread.sonic-pi.net/t/fading-live-loop-in-out/2464/1 "2019-06-10T05:32:00Z")

</div>

Hello everyone, I’m new to Sonic Pi and to this forum, from which I have already gathered some precious information.

Now, I would like to find a simple way to fade sample live\_loops in and out.

Can you help me?

---

<div class="post-metadata">

**Author:** ![chris.krakou](https://avatars.discourse-cdn.com/v4/letter/c/e5b9ba/32.png) [@chris.krakou](https://in-thread.sonic-pi.net/u/chris.krakou)\
**Post date:** [June 10, 2019, 5:59am UTC](https://in-thread.sonic-pi.net/t/fading-live-loop-in-out/2464/2 "2019-06-10T05:59:35Z")

</div>

I normally fade in my synths using a ramp ring. These rings are different in that when you tick to the end, they don’t wrap around but stay at the last value. You can reverse the ring to fade out.

```
live_loop :fade_in do  
  synth :beep, note: (chord :c3, :min).tick, amp: (line 0,1,steps: 32, inclusive: true).ramp.look
  sleep 0.25
end

```

You can reset ticks using tick\_reset or tick\_reset\_all, but I don’t know how to do that within a look once instead of on all iterations. Perhaps someone else can help out?

---

<div class="post-metadata">

**Author:** ![Martin](https://dub1.discourse-cdn.com/flex017/user_avatar/in-thread.sonic-pi.net/martin/32/157_2.png) [@Martin](https://in-thread.sonic-pi.net/u/Martin)\
**Post date:** [June 10, 2019, 6:22am UTC](https://in-thread.sonic-pi.net/t/fading-live-loop-in-out/2464/3 "2019-06-10T06:22:19Z")

</div>

Hi @Julien,

I am wondering how to do this in an easy way for quite a while (and I do not yet have that easy solution).

Have a look at [http://in-thread.sonic-pi.net/t/smoothly-fading-samples-and-synths/528](http://in-thread.sonic-pi.net/t/smoothly-fading-samples-and-synths/528); towards the end @robin.newman proposes a smart solution, though it is not as concise as I would wish it to be for a live coding situation.

In case you want to fade the whole buffer (fade the whole track), you can always use something like:

```ruby
set_mixer_control! amp: 0, amp_slide: 16

```

For fading single `live_loop`s I currently also use the approach @chris.krakou mentions (of course you can control any parameter with it, such as a low pass filter); the problem with that is, that you will have a stepwise fade (in the above example each fading step takes 0.25 beats).

If your `live_loop` has a runtime of e. g. 8 beats you can apply `control` (see some ideas of how to do that in the [mentioned thread](http://in-thread.sonic-pi.net/t/smoothly-fading-samples-and-synths/528)).

---

<div class="post-metadata">

**Author:** ![PiEaterAndPlayer](https://avatars.discourse-cdn.com/v4/letter/p/ce7236/32.png) [@PiEaterAndPlayer](https://in-thread.sonic-pi.net/u/PiEaterAndPlayer)\
**Post date:** [June 10, 2019, 9:54am UTC](https://in-thread.sonic-pi.net/t/fading-live-loop-in-out/2464/4 "2019-06-10T09:54:16Z")

</div>

This is something I’ve thought about in the past, but I haven’t really come up with a good solution. The method I’ve used is cludgy because I use set and get to get a reference to a with\_fx block to control outside the block itself. And, I’d presume that Sam’s intention in the syntax of the with\_fx block is to prevent this.

Here’s a bit of sample code using the methods I’ve used before. This assumes that all fading in/out occurs over a bar or multiple whole bars. The code could be changed to have more flexible level changes.

```ruby
use_bpm 127
use_debug false

#
# First live loop to control
#

with_fx :level, amp: 0 do |level|
  
  set :leveller1, level
  
  live_loop :drums do
    use_random_seed 13237
    
    at [0, 1, 2, 3] do
      sample :bd_haus
    end
    
    at [1, 3] do
      sample :sn_dolf
    end
    
    16.times do |i|
      
      if one_in( 2 )
        
        at i / 4.0 do
          sample :drum_cymbal_closed, pan: -0.7
        end
      end
      
    end
    
    sleep 4
  end
end

# second live loop to control

tscale = (scale :e4, :minor_pentatonic )

with_fx :level, amp: 0 do |level|
  set :leveller2, level
  
  live_loop :melo do
    use_synth :dsaw
    use_synth_defaults cutoff: 80, res: 0.9, sustain: 0, release: 0.35
    use_random_seed 8123
    
    8.times do
      play tscale.choose if one_in(2)
      sleep 0.5
    end
    
    
  end
end

#
# level targets per bar for each loop. Note that
# each number is a target and this code pans
# smoothly throughout a bar to the target from the
# previous value.
#
# To have pans of different lengths, different code
# will be needed, but that wouldn't be too complicated
#
#

levels1 = [0.3, 0.6, 1, 1, 1, 1, 0.5, 0.5, 0.2, 1, 1, 1, 1, 0.75, 0.5, 0.25, 0]
last1 = 0

levels2 = [0.7, 1, 1, 1, 0.5, 0.5, 0.2, 1, 1, 1, 1, 1, 1, 0.75, 0.5, 0.25, 0]
last2 = 0

#
# both arrays must be the same length or this
# won't work. This print statement checks
#

print "levels1.length: ", levels1.length,
  "levels2.length: ", levels2.length

#
# Allow loops to get going
#

sleep 0.05

#
# Cludgy, but get references to the with_fx blocks
#

sn1 = get :leveller1
sn2 = get :leveller2

#
# For each bar, do the fade
#

levels1.length.times do |i|
  lev1 = levels1[i]
  lev2 = levels2[i]
  
  print "Targets 1: ", lev1, " 2: ", lev2
  
  incr1 = ( lev1 - last1 ) / 40.0
  incr2 = ( lev2 - last2 ) / 40.0
  
  #
  # Now fade in/out over 40 divisions of a bar
  #
  
  40.times do
    last1 = last1 + incr1
    
    # mathematical inaccuracies can put us out of
    # range
    
    if last1 < 0
      last1 = 0
    end
    
    if last1 > 1
      last1 = 1
    end
    
    # udate volume of loop
    
    control sn1, amp: last1
    
    last2 = last2 + incr2
    
    if last2 < 0
      last2 = 0
    end
    
    if last2 > 1
      last2 = 1
    end
    
    control sn2, amp: last2
    sleep 0.1
  end
  
  #
  # Prevent drift due to mathematical uncertainties
  #
  
  last1 = lev1
  last2 = lev2
end

#
# All panning has finished. Stop everything
#

print "Finished"

stop

```

---

<div class="post-metadata">

**Author:** ![Julien](https://dub1.discourse-cdn.com/flex017/user_avatar/in-thread.sonic-pi.net/julien/32/998_2.png) [@Julien](https://in-thread.sonic-pi.net/u/Julien)\
**Post date:** [June 10, 2019, 10:03am UTC](https://in-thread.sonic-pi.net/t/fading-live-loop-in-out/2464/5 "2019-06-10T10:03:28Z")

</div>

Thank you all for your answers !

Chris, your solution is simple and works right way for synths.

Perhaps it is a stupid question but is there a way this simple to fade samples like this ? I mean gradually play on the amp of a sample.

Thanks again !

---

<div class="post-metadata">

**Author:** ![PiEaterAndPlayer](https://avatars.discourse-cdn.com/v4/letter/p/ce7236/32.png) [@PiEaterAndPlayer](https://in-thread.sonic-pi.net/u/PiEaterAndPlayer)\
**Post date:** [June 10, 2019, 10:28am UTC](https://in-thread.sonic-pi.net/t/fading-live-loop-in-out/2464/6 "2019-06-10T10:28:26Z")

</div>

After I post the above, I realise that it would be best to have three arrays per controlled loop. One being times at which automation occurs. The other being the target level, and the third being the slide time. That makes things more flexible.

Using at to schedule volume changes inside a function, this appears to work:

```ruby
use_bpm 127
use_debug false

set :stop, false

#
# First live loop to control
#

with_fx :level, amp: 0 do |level|
  
  set :leveller1, level
  
  live_loop :drums do
    
    if get :stop
      stop
    end
    
    
    use_random_seed 13237
    
    at [0, 1, 2, 3] do
      sample :bd_haus
    end
    
    at [1, 3] do
      sample :sn_dolf
    end
    
    16.times do |i|
      
      if one_in( 2 )
        
        at i / 4.0 do
          sample :drum_cymbal_closed, pan: -0.7
        end
      end
      
    end
    
    sleep 4
  end
end

# second live loop to control

tscale = (scale :e4, :minor_pentatonic )

with_fx :level, amp: 0 do |level|
  set :leveller2, level
  
  live_loop :melo do
    
    if get :stop
      stop
    end
    
    use_synth :dsaw
    use_synth_defaults cutoff: 80, res: 0.9, sustain: 0, release: 0.35
    use_random_seed 8123
    
    8.times do
      play tscale.choose if one_in(2)
      sleep 0.5
    end
    
    
  end
end

#
# level targets per bar for each loop. Note that
# each number is a target and this code pans
# smoothly throughout a bar to the target from the
# previous value.
#
# To have pans of different lengths, different code
# will be needed, but that wouldn't be too complicated
#
#

times1 = [0, 4, 8, 12, 20, 24, 25]
levels1 = [0.3, 1, 0, 1, 0, 0.5, 0]
slides1 = [0.5, 0.5, 0.1, 0.1, 0.5, 1.5, 0.5]

times2 = [0, 2, 4, 8, 20, 25, 26]
levels2 = [0, 1, 0, 1, 0, 1, 0]
slides2 = [0.5, 0.5, 0.5, 1.5, 1.5, 2, 0.5]

#
# Allow loops to get going
#

sleep 0.05

#
# Cludgy, but get references to the with_fx blocks
#

sn1 = get :leveller1
sn2 = get :leveller2

define :setup do |fx, the_times, levels, slides|
  
  the_times.length.times do |i|
    print "time: ", the_times[i],
      " slide: ", slides[i],
      " level: ", levels[i]
    
    at the_times[i] do
      control fx, amp_slide: slides[i]
      control fx, amp: levels[i]
    end
    
  end
end

setup sn1, times1, levels1, slides1
setup sn2, times2, levels2, slides2

at 28 do
  set :stop, true
end

```

---

<div class="post-metadata">

**Author:** ![chris.krakou](https://avatars.discourse-cdn.com/v4/letter/c/e5b9ba/32.png) [@chris.krakou](https://in-thread.sonic-pi.net/u/chris.krakou)\
**Post date:** [June 10, 2019, 2:34pm UTC](https://in-thread.sonic-pi.net/t/fading-live-loop-in-out/2464/7 "2019-06-10T14:34:25Z")

</div>

Since `amp:` is a parameter for samples as well, my method should work on those as well.

---

<div class="post-metadata">

**Author:** ![samaaron](https://dub1.discourse-cdn.com/flex017/user_avatar/in-thread.sonic-pi.net/samaaron/32/7_2.png) [@samaaron](https://in-thread.sonic-pi.net/u/samaaron)\
**Post date:** [June 10, 2019, 2:36pm UTC](https://in-thread.sonic-pi.net/t/fading-live-loop-in-out/2464/8 "2019-06-10T14:36:23Z")

</div>

I think what we’re running into here is a limitation in Sonic Pi’s current approach.

What I’m leaning towards here is having a default mixer synth per live loop. This would allow amplitude, lpf, hpf, and other basic FX to be controlled dynamically by referencing the live loop’s name.

Would this provide a solution to what you’re looking for?

```ruby
# :foo here is the name of a live loop
control :foo, amp_slide: 8, amp: 0

```

---

<div class="post-metadata">

**Author:** ![Martin](https://dub1.discourse-cdn.com/flex017/user_avatar/in-thread.sonic-pi.net/martin/32/157_2.png) [@Martin](https://in-thread.sonic-pi.net/u/Martin)\
**Post date:** [June 10, 2019, 3:02pm UTC](https://in-thread.sonic-pi.net/t/fading-live-loop-in-out/2464/9 "2019-06-10T15:02:33Z")

</div>

As far as I can see it would. Looks like a great feature!

---

<div class="post-metadata">

**Author:** ![perpetual\_monday](https://dub1.discourse-cdn.com/flex017/user_avatar/in-thread.sonic-pi.net/perpetual_monday/32/955_2.png) [@perpetual\_monday](https://in-thread.sonic-pi.net/u/perpetual_monday)\
**Post date:** [June 10, 2019, 3:06pm UTC](https://in-thread.sonic-pi.net/t/fading-live-loop-in-out/2464/10 "2019-06-10T15:06:28Z")

</div>

That seems like a good approach. I see (and use) this type of boilerplate often within `live_loop`:

```ruby
if get :stop
  stop
end

```

Could it work to also have a play/stop flag available?

`control :foo, stopped: true`

---

<div class="post-metadata">

**Author:** ![samaaron](https://dub1.discourse-cdn.com/flex017/user_avatar/in-thread.sonic-pi.net/samaaron/32/7_2.png) [@samaaron](https://in-thread.sonic-pi.net/u/samaaron)\
**Post date:** [June 10, 2019, 3:08pm UTC](https://in-thread.sonic-pi.net/t/fading-live-loop-in-out/2464/11 "2019-06-10T15:08:41Z")

</div>

> [@perpetual\_monday](#):
>
> control :foo, stopped: true

That would be combining the synth node semantics (which is what `control` is currently designed to do) with thread life-cycle semantics (which is what a `live_loop` is).

Would you be looking for an external way to stop a running `live_loop`? If so, would stopping a live loop at the loop boundary (i.e. when it repeats) be good enough? This appears to be the behaviour of your current boiler plate code.

---

<div class="post-metadata">

**Author:** ![perpetual\_monday](https://dub1.discourse-cdn.com/flex017/user_avatar/in-thread.sonic-pi.net/perpetual_monday/32/955_2.png) [@perpetual\_monday](https://in-thread.sonic-pi.net/u/perpetual_monday)\
**Post date:** [June 10, 2019, 3:13pm UTC](https://in-thread.sonic-pi.net/t/fading-live-loop-in-out/2464/12 "2019-06-10T15:13:27Z")

</div>

> [@samaaron](#):
>
> Would you be looking for an external way to stop a running `live_loop` ? If so, would stopping a live loop at the loop boundary (i.e. when it repeats) be good enough?

Yes, I’d use that if it were available 🙂

---

<div class="post-metadata">

**Author:** ![Julien](https://dub1.discourse-cdn.com/flex017/user_avatar/in-thread.sonic-pi.net/julien/32/998_2.png) [@Julien](https://in-thread.sonic-pi.net/u/Julien)\
**Post date:** [June 10, 2019, 3:52pm UTC](https://in-thread.sonic-pi.net/t/fading-live-loop-in-out/2464/13 "2019-06-10T15:52:30Z")

</div>

Hello Sam, thanks for your answer. It looks great but I can’t seem to make it work, could you give me an example in context ? I’d be very grateful.

Here’s what I have:

````ruby
  sample :bd_fat, amp: 2
  sleep 0.5
  control :fade_in, amp: 0, amp_slide: 8
end```
````

---

<div class="post-metadata">

**Author:** ![samaaron](https://dub1.discourse-cdn.com/flex017/user_avatar/in-thread.sonic-pi.net/samaaron/32/7_2.png) [@samaaron](https://in-thread.sonic-pi.net/u/samaaron)\
**Post date:** [June 10, 2019, 4:00pm UTC](https://in-thread.sonic-pi.net/t/fading-live-loop-in-out/2464/14 "2019-06-10T16:00:42Z")

</div>

Hi Julien,

it doesn’t work because I haven’t implemented it yet. I was just suggesting it as something that could be built so I could get your feedback. Sorry for the confusion.

---

<div class="post-metadata">

**Author:** ![Julien](https://dub1.discourse-cdn.com/flex017/user_avatar/in-thread.sonic-pi.net/julien/32/998_2.png) [@Julien](https://in-thread.sonic-pi.net/u/Julien)\
**Post date:** [June 10, 2019, 4:10pm UTC](https://in-thread.sonic-pi.net/t/fading-live-loop-in-out/2464/15 "2019-06-10T16:10:00Z")

</div>

Hi !

Oh OK, my bad !😃

---

<div class="post-metadata">

**Author:** ![PiEaterAndPlayer](https://avatars.discourse-cdn.com/v4/letter/p/ce7236/32.png) [@PiEaterAndPlayer](https://in-thread.sonic-pi.net/u/PiEaterAndPlayer)\
**Post date:** [June 10, 2019, 4:14pm UTC](https://in-thread.sonic-pi.net/t/fading-live-loop-in-out/2464/16 "2019-06-10T16:14:12Z")

</div>

Being able to effectively mix live loops would be, I think, a big improvement to Sonic Pi. It would make programming live\_loops easier as coders wouldn’t have to worry about mixing when they’re writing the loop. They could leave that to later.

```ruby
use_bpm 127

bassd = live_loop :bdrum do
  sync :timer
  
  at [0, 1, 2, 3] do
    sample :bd_haus
  end
end

snared = live_loop :snare do
  sync :timer
  
  at [1, 3] do
    sample :sn_dolf
  end
end

hats = live_loop :hats do
  sync :timer
  use_random_seed 3125
  
  8.times do |i|
    
    if (i % 2) == 0
      if one_in(2)
        
        at i / 2.0 do
          sample :drum_cymbal_open, sustain: 0.4 if one_in(2)
        end
      end
    else
      2.times do |j|
        if one_in(2)
          at (i*2+j) / 4.0 do
            sample :drum_cymbal_closed
          end
        end
      end
    end
  end
end

live_loop :metro do
  cue :timer
  sleep 4
end  

control bassd, amp: 0.7, pan: 0, lpf: 70
control snared, amp: 0.5, pan: -0.3, hpf: 70
control hats, amp: 0.35, pan: 0.4, hpf: 70

```

Having with\_fx return an object similar to how synth, sample, or play does would also help make mixing easier. But, what if someone wants to apply several effects in a chain to a live\_loop. Something like:

```ruby
object = with_fx :level do
    with_fx :reverb do
       sample :loop_amen_full
    end
end

```

then how could the internal reverb be accessed?

I’m wondering if there is a way to have simple and easy mixing of the type that would be possible to have easy and flexible mixing without making the language convoluted or unsuitable for beginners.

If ALL of synth, with\_fx, and live\_loop returned an object that could be controlled through control, then that would be simple and easy to learn.

I’m curious about more sophisticated mixing, and wonder if there is a way to fake it in Sonic Pi. I’m going to give it a go.

PS: I too would definitely use stopping a loop at a loop boundary. I do, anyway.

---

<div class="post-metadata">

**Author:** ![Julien](https://dub1.discourse-cdn.com/flex017/user_avatar/in-thread.sonic-pi.net/julien/32/998_2.png) [@Julien](https://in-thread.sonic-pi.net/u/Julien)\
**Post date:** [June 10, 2019, 4:14pm UTC](https://in-thread.sonic-pi.net/t/fading-live-loop-in-out/2464/17 "2019-06-10T16:14:34Z")

</div>

Hi Chris,

I have tried your solution with a sample but I must be doing it wrong.

Here’s what I got:

````ruby
  sample :bd_808.tick, amp: (line 0,1,steps: 32, inclusive: true).ramp.look
  sleep 0.25
end```
````

---

<div class="post-metadata">

**Author:** ![PiEaterAndPlayer](https://avatars.discourse-cdn.com/v4/letter/p/ce7236/32.png) [@PiEaterAndPlayer](https://in-thread.sonic-pi.net/u/PiEaterAndPlayer)\
**Post date:** [June 10, 2019, 4:17pm UTC](https://in-thread.sonic-pi.net/t/fading-live-loop-in-out/2464/18 "2019-06-10T16:17:16Z")

</div>

Sorry if I’m sticking my nose in, but for @Julien, the following works

```ruby
live_loop :fade_in do
  sample :bd_808, amp: (line 0,1,steps: 32, inclusive: true).tick
  sleep 0.25
end

```

---

<div class="post-metadata">

**Author:** ![Julien](https://dub1.discourse-cdn.com/flex017/user_avatar/in-thread.sonic-pi.net/julien/32/998_2.png) [@Julien](https://in-thread.sonic-pi.net/u/Julien)\
**Post date:** [June 10, 2019, 4:20pm UTC](https://in-thread.sonic-pi.net/t/fading-live-loop-in-out/2464/19 "2019-06-10T16:20:16Z")

</div>

Hi

It does ! Thank you very much. Now what if I wanted to keep it running at the same volume after the fade in ? Would it be possible ?

---

<div class="post-metadata">

**Author:** ![PiEaterAndPlayer](https://avatars.discourse-cdn.com/v4/letter/p/ce7236/32.png) [@PiEaterAndPlayer](https://in-thread.sonic-pi.net/u/PiEaterAndPlayer)\
**Post date:** [June 10, 2019, 4:25pm UTC](https://in-thread.sonic-pi.net/t/fading-live-loop-in-out/2464/20 "2019-06-10T16:25:37Z")

</div>

This works, but I think there will be a much easier way. I thought there was a data structure in Sonic Pi that returns the last value for indexes greater than the length of the array. But, I can’t remember what it’s called.

```ruby
live_loop :fade_in do
  if look < 31
    sample :bd_808, amp: (line 0,1,steps: 32, inclusive: true).tick
  else
    sample :bd_808, amp: 1.0
  end
  
  sleep 0.25
end

```

[Next page](https://in-thread.sonic-pi.net/t/fading-live-loop-in-out/2464.md?page=2)
