Skip to content

Instantly share code, notes, and snippets.

@xavriley
Last active February 26, 2019 13:56
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xavriley/30444c1773434014c9ee to your computer and use it in GitHub Desktop.
Save xavriley/30444c1773434014c9ee to your computer and use it in GitHub Desktop.
Designing a DSL for slicing samples in Sonic Pi

Sample slicing DSL in Sonic Pi

I'm stealing/playing around with ideas from the tidal language here.

Tidal is more focussed on creating loop based music and manipulating samples. It has a good (although initially scary looking) DSL for this purpose.

  every 6 (density 2) $ jux (iter 8) $ every 8 rev $ 
  every 5 (0.25 <~) $ sound "[808a/4*16, 808a/2 [808a/3 ~ ~ 808b] [~ 808b/3 808b/3 ~] [~],  [~ ~ ~ [~ 808b/2]]/2]"
  |+| speed "[1 1 1 [1.5 0.8] 1 1 1 [1 0.5]]/8"
  |+| cutoff ((*0.5) <$> slow 2 sinewave1)
  |+| resonance ((*0.2) <$> slow 3 sinewave1)

You can hear what that sounds like here: http://365tidalpatterns.tumblr.com/post/72553318354/pattern-012

It would be nice to develop some of the ideas from tidal into a Sonic-Pi core method at some point. I have a feeling that with Ruby datastructures alone you can achieve quite a fine grained manipulation of sample slicing.

Explanation of the Sonic Pi code below

The striate method helps to slice a sample into a given number of pieces, then play those back in a given order (using array indices).

Enough explanation - play around with the code!

define :play_slice do |sample_name, no_of_slices, pattern_index, playback_rate, no_of_beats|
if pattern_index.kind_of? Numeric
slice_times = (0..1).step(1.0/no_of_slices).each_cons(2).to_a
st,fn = slice_times[pattern_index]
fn,st = st,fn if pattern_index < 0 # negative play backwards
sample sample_name, start: st,finish: fn, rate: playback_rate
end
# sleep if nil - allows for rests in patterns
sleep (sample_duration(sample_name, rate: playback_rate) / no_of_beats)
end
define :striate do |sample_name, no_of_slices, pattern, playback_rate, no_of_beats|
pattern ||= (1..no_of_slices).to_a
Array(pattern).each do |i|
if i.kind_of? Numeric
play_slice(:loop_amen, no_of_slices, i, playback_rate, no_of_beats)
elsif i.kind_of? Array
i.each do |i2|
play_slice(:loop_amen, no_of_slices, i2, playback_rate, ((no_of_beats) * i.length))
end
else
play_slice(:loop_amen, no_of_slices, nil)
end
end
end
define :striate_idea do
3.times do
striate :loop_amen, 16, (0..15).to_a, 0.66, 16
end
# nested arrays allow for grinding effects or cross rhythms
striate :loop_amen, 16, [2,6,6,6,4,8,8,8,[11,11],6,0,6,12,6,6,6], 0.66, 16
3.times do
striate :loop_amen, 16, (0..15).to_a, 0.66, 16
end
with_fx :reverb, mix: 0.1 do
with_fx :distortion, amp: 0.5, mix: 1.0 do
# sliced into 16ths but played back as triplets (12ths)
striate :loop_amen, 16, [4,-2,4].cycle.take(12), 0.66, 12
end
end
end
in_thread(name: :idea) do
loop {striate_idea}
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment