Skip to content

Instantly share code, notes, and snippets.

@xavriley
Created April 19, 2015 11:46
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xavriley/5d7859a4554e8f303b68 to your computer and use it in GitHub Desktop.
Save xavriley/5d7859a4554e8f303b68 to your computer and use it in GitHub Desktop.
degrade effect in Sonic Pi

Degrade effect for Sonic Pi

Our old friend Tidal has a function I quite like - degrade

Tidal is a pattern based language and degrade simply drops an event from a pattern 50% of the time.

input: [1,1,1,1,1,1,1,1]

-> degrade(input)

output: [1,0,1,1,0,0,0,1]

Now SonicPi isn't a pattern or event based system so this is a bit tricky. I feel like you could achieve the same effect though using the code below.

It relies on the current_bpm being set to match whatever you're trying to slice. That way, a time value like 0.25 can stand in as an event at the current bpm.

Other settings are:

the probability with which an event is likely to get dropped - 0.0 drops everything, 1.0 drops nothing. the high volume and the low volume - whether it drops the sound completely or just accents some slices

Problems

This is woefully inefficient but I'm not sure how to implement it as a synthdef.

use_bpm (60.0*4)/sample_duration(:loop_amen)
live_loop :degrade do
with_fx :level do |l|
prob_threshold = 0.5
window_size = 0.25
high_amp = 1
low_amp = 0
sample :loop_amen # play the sample
# step through slices to set the volume accordingly
(range 0, 4, window_size).each do |step|
# based on a threshold, set the amp
# to a high or low value
amp_for_slice = (rand(1) < prob_threshold ? high_amp : low_amp)
control(l, amp: amp_for_slice)
sleep window_size
end
end
end
@samaaron
Copy link

I think the closest to degrade is simply adding an if rand < p to the end of each play. However, your probabilistic slicer is also nice. You'd be able to implement it using buffers - seeding a buffer with 0s and 1s then using that buffer as an amplitude mul.

@xavriley
Copy link
Author

I've just figured this out in supercollider

(
play({
    SinOsc.ar((ToggleFF.kr(CoinGate.kr(0.5, Impulse.kr(5))) * 400) + 800, 0, 0.1)
}))

@xavriley
Copy link
Author

Although now I've read your comment it might make more sense to do a seeded buffer as that would tie in nicely with the random_seed stuff in SP.

@xavriley
Copy link
Author

Also whilst I'm on the idea train, another way to achieve the same thing would be to have a degrade method with a block that would redefine the behaviour of the methods play, synth and sample to have an automatic if rand < p added to them

Could potentially use the technique described here: http://www.dan-manges.com/blog/ruby-dsls-instance-eval-with-delegation

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment