Created
October 29, 2015 13:27
-
-
Save euwbah/b28ca82896a9a5ae95ba to your computer and use it in GitHub Desktop.
This file contains hidden or 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
############ | |
# 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