Shifting Rings from Spread

Hello Folks

I’ve been using spread a lot to generate euclidean rhythms, and they work really well. One thing I can’t seem to figure out is how to shift them. For instance, spread(2,16) gives me a hit on 1 and 8, which sounds off when I try to add snares from one measure to the next. Is there an easy way to “pre-tick” it 4 times, so i get a hit on 5 and 13 instead?

aka. from
(ring true, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false)
to
(ring false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false)

Hi @chris.krakou,

lovely question! You can skip or “rotate” a spread an arbitrary number of times using the .rotate modifier:

(spread 2,16).rotate(4)  

You can use positive or negative values for the rotate amount.

I hope that this helps :slight_smile:

1 Like

Hi @samaaron,

according to my tests

v = 1
spread(2, 8, rotate: v)

will always return:

(ring true, false, false, false, true, false, false, false)

no matter what value v has. At least in my SP 3.1.0

which is consitant with the documentation:

“… rotate to the next strong beat allowing for easy permutations of the original rhythmic grouping …”.

I would be glad if I am wrong because I was already looking for an easy way to shift beats irrespective of them being week or strong.

Hi @Martin,

yes, that would make sense. The option rotate: is different from the modifier .rotate. In other words, the option rotate: is specific to the spread function whereas the modifier .rotate works on any ring.

Note the difference:

(spread 2, 8, rotate: 4)
(spread 2, 8).rotate(4)

Hope that this helps :slight_smile:

1 Like

Ahh!! Great! Thanks for clearing up my misunderstanding and misreading.

1 Like

That’s exactly what i needed. Thanks @samaaron!

The .rotate function doesn’t appear anywhere in the built-in documentation. Finding the functions built into rings (beyond the tutorial) is generally a bit difficult, it would be nice if all the functions were listed in the ring entry.

I could write a bit about it if you want. Just give a hint as to where I should put it.

1 Like

Hi Chris,

I think .rotate is really a Ruby construct, and as such not documented in the SP help…

There are others, .mirror, .reverse, which come to mind, which were mentioned in another
much older post, somewhere.

Sam usually says they aren’t formally supported, even though they might work, and may not
work in future versions… which would be a shame, as they are damn useful.

Eli…

… and here: https://github.com/samaaron/sonic-pi/blob/master/etc/doc/tutorial/08.5-Ring-Chains.md

What he said. :slight_smile:

I sat down and went through the ruby array operators to check which ones work and which ones don’t as of today (version 3.1.0), in case someone else comes across this thread.

###########
# WORKS
###########

# Transformations
puts (scale :a1, :minor) << 88
puts (scale :a1, :minor).unshift(33)
puts (scale :a1, :minor).push(33)
puts (scale :a1, :minor).pop
puts (scale :a1, :minor).shift
puts (scale :a1, :minor).delete_at(1)
puts (scale :a1, :minor).reverse

# Combining
puts (scale :c1,:major) + (scale :c2,:major)
puts (scale :c1,:major) + (scale :d1,:major).uniq
puts (scale :c1,:major) - (scale :d1,:major)

# Removing Duplicates
puts (scale :c1,:major).concat((scale :d1, :major))

# Moving
puts (scale :c1,:major).reverse
puts (scale :c1,:major).rotate
puts (scale :c1,:major).rotate(-2)

# Querying
puts (scale :c1,:major).include? 29
puts (scale :c1,:major).count 29
puts (scale :c1,:major).size

# Iterations
(scale :c1, :major).each {|i| puts i}
(scale :c1, :major).reverse_each {|i| puts i}
(scale :c1, :major).each_with_index do |note,index|
  puts "#{note} at #{index} "
end

###########
# DOESN'T WORK
###########

# boolean operators
puts testring & (scale :d1,:minor)
puts testring | (scale :d1,:minor)

# Joining
puts (ring "hello","world").join
2 Likes