Skip to content

Instantly share code, notes, and snippets.

@euwbah
Created October 29, 2015 13:27
Show Gist options
  • Save euwbah/b28ca82896a9a5ae95ba to your computer and use it in GitHub Desktop.
Save euwbah/b28ca82896a9a5ae95ba to your computer and use it in GitHub Desktop.
############
# Buffer 1 #
############
use_bpm 120
firstRun = true;
startFromMeasure = 16;
currChord = nil
define :p do |n, length, ax, bx, cx|
with_fx :reverb do
use_synth :sine
use_synth_defaults release: 0.8 * length, sustain: 0.15 * length, attack: 0.05
play_chord n, amp: ax
with_transpose 12 do play_chord n, amp: ax * 0.20 + bx / 8.0 end
with_transpose 19 do play_chord n, amp: ax * 0.08 + bx / 10.0 end
with_transpose 24 do play_chord n, amp: ax * 0.03 + bx / 15.0 end
with_transpose 28 do play_chord n, amp: (ax + cx) * 0.015 end
with_transpose 31 do play_chord n, amp: (ax + cx) * 0.01 end
with_transpose 33.9 do play_chord n, amp: (ax + cx) * 0.005 end
with_transpose 36 do play_chord n, amp: (ax + cx) * 0.0025 end
end
end
define :pd do |chd, ax, c|
curr = nil
with_fx :reverb, room: 0.3, damp: 0.4, mix: 0.9, amp: 2.5 do
use_synth :fm
use_synth_defaults sustain: 20, amp_slide: 2, amp_slide_shape: 5, amp_slide_curve: 2, \
cutoff_slide: 4, cutoff_slide_shape: 1, attack: 0.03, env_curve: 1
curr = play_chord chd, amp: ax, cutoff: c
end
return curr
end
pnotes = [:c4]
pulser = {
1 => [
[:bx, 0.1],
[:cx, 0.05],
[:n, [:c4]]
],
(tq 2) => [[:n, [:c4, :d4]]],
(tq 4) => [:c4, :eb4],
(tq 6) => [:c4, :d4],
(tq 7) => [
[:bx, 0.3],
[:cx, 0.15]
],
(tq 8) => [:ab3, :c4],
(tq 10) => [
[:a, 0.7],
[:bx, 0.45],
[:cx, 0.3],
[:n, [:ab3, :c4, :d4]]
],
(tq 11) => [
[:bx, 0.6],
[:cx, 0.45]
],
(tq 12) => [:g3, :c4, :eb4],
(tq 14) => [:g3, :bb3, :d4],
(tq 16) => [:ab3, :bb3, :eb4],
(tq 17) => [:ab3, :c4, :eb4],
(tq 18) => [[:a, 0.45]],
(tq 19) => [[:a, 0.22], [:bx, 0.2]],
(tq 20) => [[:a, 0.10], [:bx, 0.0]],
(tq 21) => [[:a, 0.0]]
}
chn = {
tq(7)=>[
[:c, 60]
],
tq(8)=>[
[:n, [:bb4, :c5, :eb5, :g5]],
[:cs, 3],
[:c, 80]
],
tq(11)=>[
[:n, [:f5, :d5, :c5, :bb4]],
[:cs, 1],
[:c, 88]
],
tq(12)=>[
[:n, [:g5, :eb5, :d5, :bb4]],
[:c, 95]
],
tq(15)=>[
[:n, [:bb5, :g5, :d5, :f5]],
],
tq(16)=>[
[:n, [:g4, :eb5, :d5, :bb4]],
[:cs, 1],
[:c, 88]
],
tq(17)=>[
[:n, [:ab4, :eb5, :c5, :g4]],
[:cs, 2],
[:c, 67]
],
tq(19)=>[
[:c, 30]
],
tq(21)=>[
[:n, [:r]]
]
}
#NOTE: Units: semiquavers
chordProg = {
0 => [:c, chord(:C, '1')],#:c => Single chord
(tsq 2) => [:c, chord(:c, :sus2)],
(tsq 4) => [:c, chord(:c, :m)],
(tsq 6) => [:c, chord(:c, :m9)],
(tsq 8) => [:c, chord(:ab3, :maj9)],
(tsq 12) => [:c, chord(:c, :m9)],
(tsq 14) => [:c, chord(:g3, :m7)],
(tsq 16) => [:c, (ring chord(:ab3, :sus2), :g4)],
(tsq 17) => [:c, chord(:ab3, :maj9)],
(tsq 20) => [:cp, [[
chord(:c, :m9),
chord(:g3, :m7),
(ring chord(:ab3, :sus2), :g4),
chord(:ab3, :maj9)
], 8]]
}
pulseamp = 0.6
bxamp = 0.5
cxamp = 0
live_loop :pulse do
if firstRun then
tick_set (tq startFromMeasure)
end
tick
events = pulser[look]
if events == nil then
p pnotes, 0.5, pulseamp - ((look % 4.0) / 8.0 * pulseamp), bxamp, cxamp
elsif not events[0].kind_of?(Array) #Shortcut
p events, 0.5, pulseamp - ((look % 4.0) / 8.0 * pulseamp), bxamp, cxamp
pnotes = events
else
noteplayed = false
events.each do |event|
actionType = event[0]
param = event[1]
if actionType == :n then
p param, 0.5, pulseamp - ((look % 4) / 8.0 * pulseamp), bxamp, cxamp
noteplayed = true
pnotes = param
elsif actionType == :a then
pulseamp = param
elsif actionType == :bx then
bxamp = param
elsif actionType == :cx then
cxamp = param
end
end
if not noteplayed then
p pnotes, 0.5, pulseamp - ((look % 4) / 8.0 * pulseamp), bxamp, cxamp
end
end
sleep 0.5
end
padVar = nil
pdcurrCutoff = 70
pdcurrCutoffSlide = 1;
live_loop :pad do
if firstRun then
tick_set (tq startFromMeasure)
end
tick
events = chn[look]
if events != nil then
events.each do |event|
param = event[1]
actionType = event[0]
if actionType == :n then
padVar = pd param, 0.45, pdcurrCutoff
control padVar, cutoff_slide: pdcurrCutoffSlide
elsif actionType == :c then
control padVar, cutoff: param
pdcurrCutoff = param
elsif actionType == :cs then
control padVar, cutoff_slide: param
pdcurrCutoffSlide = param
end
end
end
#fade off once a new note or rest is coming up
nextEvents = chn[look+1]
if nextEvents != nil then
if lambda{|n_events|
n_events.each do |event|
if event[0] == :n then
return true
end
end
}.call(nextEvents) then
control padVar, amp: 0
end
end
sleep 0.5
end
currChord = nil
currChordProgression = nil
progList = nil
progStepTime = 8 #in beats
progStartTime = 0 #in semiquavers
live_loop :chord_machine, auto_cue: false do
if firstRun then
tick_set (tsq startFromMeasure)
end
tick
currTick = look
event = chordProg[currTick]
hasOverride = false
if event != nil and event.length != 0 then
action = event[0]
param = event[1]
if action == :c then
currChord = param
hasOverride = true
#puts currChord
elsif action == :cp then
currChordProgression = param
progList = param[0]
progStepTime = param[1]
progStartTime = look
elsif action == :stop then
currChordProgression = nil
end
end
if currChordProgression != nil then
if !hasOverride then
currChord = progList[((0.25 * (look - progStartTime) / progStepTime).floor) % (progList.length * progStepTime)]
#puts currChord
end
end
sleep 0.25
end
riffnotes = {
(tsq 16) => [
[:a, 0.3],#amplitude
[:bounds, [:c4, :g5]],
[:nf, [:eb5, :d5, :bb4, :g4, :f4, :eb4]],#note focus
[:rhythm, (gen_prob_curve "8oo 8oo 7o -ooo oooo", 3)],
[:ct, true],
[:rep, 1]
]
}
riff_currRhythmStartTick = 0
riff_bounds = []
riff_nf = nil
riff_rhythm = nil#Use a ring... not an array....
#When useChordTones is true:
#If nf != nil, the C.O.Fifth distance between nf tones and chord tones will determine
#the probability of the nf notes being sounded. Else, only chord tones will be used.
#When uCT is false, nf will be used in equal proportion, and when nf is nil, riff will turn off.
riff_useChordTones = false
riff_amp = 0
#The factor of encouraging repeated notes.
#1 = No change. 2 = Double the probability of repeated notes. 0.5 = Halve the probability.
riff_rep = 1;
live_loop :riff, auto_cue: false do
if firstRun
tick_set (tsq startFromMeasure)
end
tick
events = riffnotes[look]
if events != nil
events.each do |event|
param = event[1]
case event[0]
when :a
riff_amp = param
when :bounds
riff_bounds = param
when :nf
riff_nf = param
when :rhythm
riff_rhythm = param
riff_currRhythmStartTick = look
when :ct
riff_useChordTones = param
when :rep
riff_rep = param
end
end
end
if riff_rhythm != nil
currProbability = riff_rhythm[look - riff_currRhythmStartTick]
#puts currProbability
sleep 0.25
if rrand(0, 1) < currProbability
if riff_nf != nil
if riff_useChordTones
else
end
elsif riff_useChordTones && currChord != nil
end
end
end
sleep 0.25
end
live_loop :drums, auto_cue: false do
sleep 8
end
sleep 0.1
firstRun = false;
######################
# Buffer 2 (Methods) #
######################
define :tsq do |x|
return x * 16
end
define :tq do |x| #bars to quaver
return x * 8
end
define :tc do |x|
return x * 4
end
define :getDistance do |x, y|
note1 = (note x).to_i
note2 = (note y).to_i
if note1 > note2
temp = note note1
note1 = note2
note2 = temp
end
while note2 - note1 >= 12
note2 -= 12
end
ret = nil
case note2 - note1
when 0 then ret = 0
when 1, 11 then ret = 5
when 2, 10 then ret = 2
when 3, 9 then ret = 3
when 4, 8 then ret = 4
when 5, 7 then ret = 1
when 6 then ret = 6
end
ret
end
define :gen_prob_curve do |str, complexity|
returnable = []
raw = []
phaseOffset = 0
if complexity > 10 then complexity = 10 end
if complexity < 0 then complexity = 0 end
str.each_char { |c| pushed = (case c
when "8" then 8.0
when "7" then 7.0
when "6" then 6.0
when "5" then 5.0
when "4" then 4.0
when "3" then 3.0
when "2" then 2.0
when "1" then 1.0
when "o" then :filler
when "-" then :void
end)
if pushed != nil then raw << pushed end
}
isAssert = lambda{ |key|
return (if key != :filler and key != :void then true else false end);
}
while not isAssert.call raw.first
raw << raw.shift
phaseOffset += 1
end
#loop the raw array
raw << raw.first
cPosIndex = 0.0
while raw.length > 1 #The last single point is looped...
cPos = {:x => cPosIndex.to_f, :y => raw.first / 8.0};
nPos = {}
temp_nPosX = cPosIndex + 1
raw.drop(1).each do |item|
if isAssert.call item
nPos = {:x => temp_nPosX.to_f, :y => item.to_f / 8.0}
break;
end
temp_nPosX += 1
end
curveLength = nPos[:x] - cPos[:x]
Vy = (cPos[:y] + nPos[:y]) / 2.0 / Math.sqrt(101.0 - complexity**2.0);
c = cPos[:y] - Vy
d = nPos[:y] - Vy
vertex = {:x => curveLength * (c + Math.sqrt(c*d)) / (d + c) / 2 + cPosIndex,
:y => Vy}
betas = regress [cPos[:x], vertex[:x], nPos[:x]], [cPos[:y], vertex[:y], nPos[:y]], 2
#puts betas[2].to_s + ", " + betas[1].to_s + ", " + betas[0].to_s
curveFunction = lambda {|xPos| return betas[2] * xPos ** 2 + betas[1] * xPos + betas[0]}
cPosInit = cPosIndex
for xPos in cPosIndex.to_i..(nPos[:x] - 1)
returnable << (curveFunction.call xPos)
raw.shift
cPosIndex += 1.0
end
end
while phaseOffset > 0
returnable.unshift returnable.pop
end
#puts returnable
return (ring *returnable);
end
require 'matrix'
#x and y are arrays
define :regress do |x, y, degree|
#x.each {|val| puts val}
#y.each {|val| puts val}
x_data = x.map { |xi| (0..degree).map { |pow| (xi**pow).to_f }; }
mx = Matrix[*x_data]
my = Matrix.column_vector(y)
return ((mx.t * mx).inv * mx.t * my).transpose.to_a[0]
end
############
# Buffer 3 # Sonic Pi explodes
############
tempVel = gen_prob_curve "8oo 7oo 7oo 8oo 7o8o", 2
sleep 1
snareVel = gen_prob_curve "oooo 8ooo oooo 8oo4", 1
live_loop :foo do
tick
if rrand(0, 1) < tempVel[look]
sample :drum_bass_hard, amp: 0.25 + (tempVel[look]) / 1.75
end
if rrand(0, 1) < snareVel[look]
sample :drum_snare_hard, amp: 0.25 + (tempVel[look]) / 1.5
end
if look % 2 == 0
sample :drum_cymbal_closed
end
sleep 0.25
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment