# Basic question about sliding controls

**URL:** <https://in-thread.sonic-pi.net/t/basic-question-about-sliding-controls/6870>\
**Category:** Support, Help & Resources\
**Created:** [June 21, 2022, 7:06pm UTC](https://in-thread.sonic-pi.net/t/basic-question-about-sliding-controls/6870 "2022-06-21T19:06:39Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![EliFieldsteel](https://avatars.discourse-cdn.com/v4/letter/e/6bbea6/32.png) [@EliFieldsteel](https://in-thread.sonic-pi.net/u/EliFieldsteel)\
**Post date:** [June 21, 2022, 7:06pm UTC](https://in-thread.sonic-pi.net/t/basic-question-about-sliding-controls/6870/1 "2022-06-21T19:06:40Z")

</div>

Hi all, getting back into Sonic Pi after a lengthy break. Pretty simple question here, I think. Let’s say I’ve got a basic sample kick pattern. I want to be able to sweep a filter cutoff over an arbitrary period of time. I assume `_slide` is a viable option — I’m close but not quite there. When I run the following code, the filter cutoff sweeps from note 40 to 100. Because this is a `live_loop`, I thought I’d be able to change 100 back to 40, run the code again, and hear the filter sweep back down. But it doesn’t, it just stays at 100. I suspect I’m overlooking something that is obvious to others. Can anyone point me in the right direction?

```ruby
with_fx :lpf, cutoff: 40, cutoff_slide: 8 do |fx|
  live_loop :q do
    sample :bd_haus
    sleep 0.5
  end
  control fx, cutoff: 100
end

```

---

<div class="post-metadata">

**Author:** ![emlyn](https://dub1.discourse-cdn.com/flex017/user_avatar/in-thread.sonic-pi.net/emlyn/32/1460_2.png) [@emlyn](https://in-thread.sonic-pi.net/u/emlyn)\
**Post date:** [June 21, 2022, 10:11pm UTC](https://in-thread.sonic-pi.net/t/basic-question-about-sliding-controls/6870/2 "2022-06-21T22:11:48Z")

</div>

This is an issue with the way things are implemented, I forget exactly what’s happening, but I think it’s something like: when you rerun the code, the :lpf fx is recreated, but the live\_loop is still executing inside the original copy of the fx, so you are not actually controlling the correct copy of it.

A work-around that seems to work for me is to `set` the fx reference into the time-state from inside the live\_loop so that you can always access the copy of the fx as seen from inside the live\_loop:

```ruby
with_fx :lpf, cutoff: 40, cutoff_slide: 8 do |fx|
  live_loop :q do
    set :fx, fx
    sample :bd_haus
    sleep 0.5
  end
  control get(:fx, fx), cutoff: 100
end

```

Note that the first time the code is executed, the `control` will run before the live\_loop has started, so I provide a default value to the `get`.

---

<div class="post-metadata">

**Author:** ![EliFieldsteel](https://avatars.discourse-cdn.com/v4/letter/e/6bbea6/32.png) [@EliFieldsteel](https://in-thread.sonic-pi.net/u/EliFieldsteel)\
**Post date:** [June 23, 2022, 7:39pm UTC](https://in-thread.sonic-pi.net/t/basic-question-about-sliding-controls/6870/3 "2022-06-23T19:39:57Z")

</div>

Thanks, this is helpful. It sort of works, but not exactly the way I imagined it. If I run the code, the cutoff sweeps up to 100 over 8 seconds. If I replace 100 with 40 and re-run, the cutoff sweeps back down. But then, if I set cutoff to 100 again, there’s no sweep back up. Do you know why this happens?

---

<div class="post-metadata">

**Author:** ![EliFieldsteel](https://avatars.discourse-cdn.com/v4/letter/e/6bbea6/32.png) [@EliFieldsteel](https://in-thread.sonic-pi.net/u/EliFieldsteel)\
**Post date:** [June 23, 2022, 8:31pm UTC](https://in-thread.sonic-pi.net/t/basic-question-about-sliding-controls/6870/4 "2022-06-23T20:31:00Z")

</div>

I feel like I’m getting a little closer. In the following example, I can change the mix value on-the-fly, but the change is immediate…how would I modify this code to allow me to produce a gradual parameter change over a longer period of time? I’ve tried adding `:mix_slide` in various places, but no results.

```ruby
live_loop :b do
  with_fx :reverb do |fx|
    control fx, :mix, 0.9
    sample :bd_haus
    sleep 0.5
  end
end

```

---

<div class="post-metadata">

**Author:** ![robin.newman](https://avatars.discourse-cdn.com/v4/letter/r/76d3ee/32.png) [@robin.newman](https://in-thread.sonic-pi.net/u/robin.newman)\
**Post date:** [June 24, 2022, 8:36am UTC](https://in-thread.sonic-pi.net/t/basic-question-about-sliding-controls/6870/5 "2022-06-24T08:36:19Z")

</div>

Have a look at this example building on your example above.  
Note  
1 the fx command is outside the live loop.  
2 the pointer to the |fx| control is stored in the time state as :fx using the set command  
3 the use of the ‘at’ command to specify new parameter lists to use at certain times  
4 the retrieval of the control pointer fx using get(:fx)

```ruby
#here is an example which starts a loop with fx_reverb but with mix: and room: set to 0
#so no reverb is heard
#the at statements then control the fx settings for mix: and room: with a given slide time
#changes occur after 5,10,15 and 20 seconds

set :fx,nil #intialise :fx
set :stop,false # intialise stop flag
with_fx :reverb, room: 0, mix: 0 do |fx|
  live_loop :b do
    stop if get(:stop) #stop the loop at the end
    set :fx,fx if get(:fx)==nil #update it once
    sample :bd_haus
    sleep 0.5
  end
end
#at has two parameter lists. The first is the time at which the event is processed
#the second is a list of lists. Eech entry contains the values for mix room and slide time
at [5,10,15,20],[[0.7,0.8,4],[0.7,0.4,2],[1,0.5,4],[0,0,5]]do |v|
  tick
  fx = get(:fx);puts"fx pointer retrieved. Next change to effect settings started"
  puts "Setting fx_reverb:,mix: #{v[0]},mix_slide: #{v[2]}, room: #{v[1]}, room_slide: #{v[2]}"
  
  #now control both mix and room opts with siding values
  # v will be a list containing mix value v[0], room value v[1] slide time v[2]
  #I am using teh same slide time for each but more parameters if you want
  control get(:fx),mix: v[0],mix_slide: v[2],room: v[1],room_slide: v[2]
end

at 25 do #use this at command to stop the loop after 25 seconds
  set :stop ,true
end

```

---

<div class="post-metadata">

**Author:** ![EliFieldsteel](https://avatars.discourse-cdn.com/v4/letter/e/6bbea6/32.png) [@EliFieldsteel](https://in-thread.sonic-pi.net/u/EliFieldsteel)\
**Post date:** [June 24, 2022, 7:26pm UTC](https://in-thread.sonic-pi.net/t/basic-question-about-sliding-controls/6870/6 "2022-06-24T19:26:00Z")

</div>

This is an useful study, thank you for providing so much detailed information. I am starting to understand the value of things like set, get, and at — and how their context matters.

However, this example doesn’t do exactly what I want — sorry for not being clearer in my earlier posts. I don’t want a predetermined “score” that specifies timings of parameter changes in advance. I want to embrace the spirit of live coding and make these changes at an _arbitrary_ point in the future, to be determined by me, while the sound is playing. Basically, I want to run some sound-making code, then edit and re-run it, to create a gradual parameter shift. Is this possible?

---

<div class="post-metadata">

**Author:** ![emlyn](https://dub1.discourse-cdn.com/flex017/user_avatar/in-thread.sonic-pi.net/emlyn/32/1460_2.png) [@emlyn](https://in-thread.sonic-pi.net/u/emlyn)\
**Post date:** [June 24, 2022, 8:16pm UTC](https://in-thread.sonic-pi.net/t/basic-question-about-sliding-controls/6870/8 "2022-06-24T20:16:59Z")

</div>

> [@EliFieldsteel](#):
>
> I want to embrace the spirit of live coding and make these changes at an _arbitrary_ point in the future, to be determined by me, while the sound is playing. Basically, I want to run some sound-making code, then edit and re-run it, to create a gradual parameter shift. Is this possible?

I think I’ve found a sort of (hacky) solution. Using @robin.newman’s idea of only setting `:fx` if it has not already been set, that allows you to keep on changing it.  
The only real issue is that you have to remember to include the `set :fx, nil` line on the first run, then comment it out for all subsequent runs, until you stop.  
Then when you run it again you have to do the same (include it only for the first run).  
I also had to include a bit of a wait before controlling the fx outside the live\_loop, as it seems that it is not set immediately (it took about 0.2 seconds on my machine), I suspect this is something to do with the `sched_ahead_time`.

```ruby
# comment this out after the first run (when you stop running, enable it again for the next first run):
set :fx, nil #intialise :fx

with_fx :lpf, cutoff: 40, cutoff_slide: 8 do |fx|
  live_loop :b do
    set :fx, fx if get(:fx) == nil #update it once
    sample :bd_haus
    sleep 0.5
  end
end

# this can take a little while the first time, wait until it's ready:
while get(:fx) == nil; sleep 0.1; end

# you can change the cutoff here and press run, and it should start sliding it each time:
control get(:fx), cutoff: 100

```

---

<div class="post-metadata">

**Author:** ![robin.newman](https://avatars.discourse-cdn.com/v4/letter/r/76d3ee/32.png) [@robin.newman](https://in-thread.sonic-pi.net/u/robin.newman)\
**Post date:** [June 24, 2022, 9:08pm UTC](https://in-thread.sonic-pi.net/t/basic-question-about-sliding-controls/6870/9 "2022-06-24T21:08:23Z")

</div>

Another possibility which I use quite frequently is to send information in via an external midi keyboard or controller, or using an osc command sent from a program in another buffer, or indeed another computer running sonic pi. These can both be used to provide inputs to a running program.  
eg

```ruby
live_loop :min do
  n = sync "/midi*/note_on"
  puts n[0]
  control get(:fx), cutoff: n[0],cutoff_slide: 2
  
end
live_loop :oin do
  n = sync "/osc*/t"
  puts n[0]
  control get(:fx), cutoff: n[0],cutoff_slide: 2
end

```

These could be added to the program  
The first one you can use a midi keyboard to send different note values to the loop which can adjust the cutoff with a 2 second fade. The second you could run this in a second boffer.

```ruby
use_osc "localhost",4560
osc "/t",100 #here 100 is the new target cutoff

```

You can have both inputs available and use either while the program is running. Just tried it and it works fine.

---

<div class="post-metadata">

**Author:** ![emlyn](https://dub1.discourse-cdn.com/flex017/user_avatar/in-thread.sonic-pi.net/emlyn/32/1460_2.png) [@emlyn](https://in-thread.sonic-pi.net/u/emlyn)\
**Post date:** [June 25, 2022, 11:03am UTC](https://in-thread.sonic-pi.net/t/basic-question-about-sliding-controls/6870/10 "2022-06-25T11:03:58Z")

</div>

I was convinced I had reproduced your problem with the reverb mix not sliding, and it was fixed by the changed synth, but prompted by @robin.newman’s comment on the PR I had another try and it seems that the synth does actually slide fine.  
I think the issue with that particular code is that you are creating a new synth each time around the live loop, so it’s not having time to hear the slide. You can make the synth run over a number of repeats with `reps: n`, then you can hear the slide:

```ruby
live_loop :b do
  with_fx :reverb, reps: 8 do |fx|
    control fx, mix: 0.9, mix_slide: 4
    sample :bd_haus
    sleep 0.5
  end
end

```

---

<div class="post-metadata">

**Author:** ![EliFieldsteel](https://avatars.discourse-cdn.com/v4/letter/e/6bbea6/32.png) [@EliFieldsteel](https://in-thread.sonic-pi.net/u/EliFieldsteel)\
**Post date:** [July 10, 2022, 8:33pm UTC](https://in-thread.sonic-pi.net/t/basic-question-about-sliding-controls/6870/11 "2022-07-10T20:33:29Z")

</div>

Thanks both for these interesting ideas. I think I’ll be able to use this information to come up with a solution that works for me.
