Created
June 10, 2014 21:15
-
-
Save xavriley/dd6b61c24c3aed28c892 to your computer and use it in GitHub Desktop.
Funky drummer with Sonic Pi
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# The funky drummer | |
# The aim here is to experiment with | |
# a) sequencing drums | |
# b) playing with 'time feel' which is | |
# music-speak for how the beat feels, | |
# ranging from robotic (0.0 swing_time) | |
# to ultra funky Fresh Prince of Bel Air | |
# theme tune style (0.2+ swing_time) | |
current_bpm = 180.0 | |
use_bpm current_bpm | |
define :play_kick do |vol| | |
sample :drum_bass_hard, amp: vol | |
# play :A1 # uncomment for sub rattling bass | |
end | |
define :beat do |kick, index| | |
# What's going on here? | |
# We're randomizing the loudness of | |
# every drum hit to make it sound a bit | |
# more like a human drummer. | |
# The -> { ... } is called a lambda in Ruby | |
# It only gets run when we do 'ghost.call' | |
# which means it'll be a *different* random | |
# number each time | |
ghost = -> { rrand(0.2, 0.3) } | |
normal = -> { rrand(0.4, 0.6) } | |
accent = -> { rrand(0.8, 0.9) } | |
play_kick(normal.call) if kick == 1 | |
if [1,3,4,5,7,8].include? index | |
# Rand here can be really nice | |
sample :elec_triangle, amp: ((index % 2) == 0 ? ghost.call : normal.call ) if rand < 0.8 | |
end | |
with_fx :reverb, mix: 0.5 do | |
# Always have snare on 2 and 4 | |
if index == 5 | |
sample :elec_blip, amp: normal.call | |
end | |
end | |
# And sometimes on the and of 4 | |
if (index % 2) == 0 | |
sample :drum_snare_soft, amp: ghost.call if rand < 0.1 | |
end | |
end | |
define :swing_time do | |
# This is the amount of | |
# delay added to the offbeats | |
# which gives it that swing/funk feel. | |
# Play around with it! | |
swing_time = 0.1 | |
return swing_time | |
end | |
define :play_beat do | |
loop do | |
# Two ways of modelling beats - with 0s and 1s OR with indexes | |
[1, 0, 0, 0, 0, 0, 1, 0].each.with_index(1) do |kick, index| | |
beat(kick, index) | |
if(index % 2) == 0 | |
# offbeats need to be slightly late for swing | |
sleep (0.5 - swing_time) | |
else | |
sleep (0.5 + swing_time) | |
end | |
end | |
end | |
end | |
# Comment this out after the first run | |
# so that you can re-run and make adjustments | |
# the code | |
play_beat |
Very cool! Taught me a lot.
I used some of the elements for this drum sequencer: ktbaek/sonic-pi/drum_sequencer.rb
Very nice, I only had to change the "beat" function name, that name no longer permitted because of internal use. But love the realness of your beat :)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
As a new Sonic Pi explorer, this is a lot of fun!
Only one question: even with a B+ overclocked at 950MHz, I'm getting "Timing error: can't keep up" and eventually "thread got too far behind time". Any ideas on what I'm doing wrong?
This is with Sonic Pi 2.0RC11.