Skip to content

Instantly share code, notes, and snippets.

@RusticFlare
Created February 13, 2016 15:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save RusticFlare/a18097c0e6186edf7ab8 to your computer and use it in GitHub Desktop.
Save RusticFlare/a18097c0e6186edf7ab8 to your computer and use it in GitHub Desktop.
The code for the initial version of forge
map = { :k => :drum_heavy_kick,
:s => :drum_snare_hard,
:c => :drum_cymbal_closed,
:et => :elec_tick,
:a1 => :forge_a1,
:ab1 => :forge_ab1,
:b1 => :forge_b1,
:bb1 => :forge_bb1,
:c2 => :forge_c2,
:cs2 => :forge_cs2,
:d2 => :forge_d2,
:e1 => :forge_e1,
:e2 => :forge_e2,
:eb2 => :forge_eb2,
:f1 => :forge_f1,
:fs1 => :forge_fs1,
:g1 => :forge_g1}
# play_anvil : anvil -> sound
define :play_anvil do |anvil|
anvil.each do |key,val|
play_thing(key,val)
end
end
define :play_thing do |name,pat|
with_fx :reverb, room: 0.9 do
with_fx :distortion, distort: 0.4 do
with_fx :flanger, feedback: 0.2 do
live_loop name do
use_synth :piano
pat.each do |act|
act[:sounds].each do |el|
play_sound(el,act[:sleep])
end
sleep act[:sleep]
end
end
end
end
end
end
define :play_sound do |sound,cutoff|
if sound.is_a? Float
play sound, vel: 0.16, hard: 0.39, release: cutoff
elsif map.has_key?(sound)
sample map[sound], sustain: 0, release: cutoff
elsif sound != :x
sample sound, sustain: 0, release: cutoff
end
end
# fills the anvil with the instructions for sound
# string_eval : (string, anvil) -> anvil
define :string_eval do |str,anvil|
str = string_convert str
if valid_string?(str)
if is_array? str
strs = split_list str
with_bpm_mul(strs.size) do
strs.each do |s|
anvil = string_eval(s,anvil)
end
end
else
strs = split_concurrent str
array_present = false
strs.each do |s|
if is_array? s
array_present = true
end
end
if array_present
strs = merge_arrays strs
with_bpm_mul(strs.size) do
strs.each do |s|
anvil = string_eval(s,anvil)
end
end
else
strs.each_index do |i|
if strs[i] =~ /\A[-+]?[0-9]*\.?[0-9]+\Z/ # is numeric
strs[i] = strs[i].to_f
else
strs[i] = strs[i].to_sym
end
end
anvil << { :sounds => strs, :sleep => current_beat_duration}
end
end
return anvil
end
end
# split_list : string -> string array
define :split_list do |str|
str = str[1,str.length-2]
strs = str.split(/\s*,\s*/,-1)
strs.each_index do |i|
while !valid_string?(strs[i])
strs[i] << ',' << strs[i+1]
strs.delete_at(i+1)
end
end
return strs
end
# split_concurrent : string -> string array
define :split_concurrent do |str|
strs = str.split(/\s+/)
strs.each_index do |i|
while !valid_string?(strs[i])
strs[i] << " " << strs[i+1]
strs.delete_at(i+1)
end
end
return strs
end
# checks if the bracketing of the input is valid
# valid_string? : string -> boolean
define :valid_string? do |str|
stack = []
symbols = { '[' => ']', '(' => ')' }
str.each_char do |c|
if symbols.key?(c)
stack << c
end
if symbols.key(c) && symbols.key(c) != stack.pop
return false
end
end
stack.empty?
end
# checks if a string is a valid array
# is_array? : string -> boolean
define :is_array? do |str|
if !str.start_with?('[')
return false
end
stack = []
symbols = { '[' => ']' }
x = 0
str.each_char do |c|
x += 1
if symbols.key?(c)
stack << c
end
if symbols.key(c) && symbols.key(c) != stack.pop
return false
end
if stack.empty? && x != str.length
return false
end
end
stack.empty?
end
# takes an array of input strings that are seperated by spaces and
# merge_arrays : string array -> string array
define :merge_arrays do |strs|
new_size = 1
strs.each_index do |i|
if !is_array? strs[i]
strs[i] = "[" + strs[i] + "]"
end
strs[i] = split_list strs[i]
new_size = new_size.lcm strs[i].length
end
sounds = Array.new(new_size)
strs.each do |str|
str.each_index do |i|
index = (i.to_r / str.length.to_r) * sounds.length
if sounds[index] == nil
sounds[index] = str[i]
else
sounds[index] << " " << str[i]
end
end
end
sounds.each_index do |i|
if sounds[i] == nil
sounds[i] = "x"
end
end
return sounds
end
# converts mult and spread values into arrays
# string_convert : string -> string
define :string_convert do |str|
str = mult_values str
return spread_values str
end
# replaces spread strings with arrays
# spread_values : string -> string
define :spread_values do |str|
str = format_input str
strs = str.split(/\(|\)/,-1)
while strs.length > 2
strs1 = strs[0].split(/\s+/)
symbol = ' ' + strs1.pop
while !valid_string? symbol
symbol = ' ' + strs1.pop + symbol
end
strs[0] = ""
strs1.each do |str1|
strs[0] = strs[0] + ' ' + str1
end
if !(strs[1] =~ /\A\s*\d+\s*,\s*\d+\s*\Z/).nil?
vals = strs[1].scan(/\d+/)
end
vals.each_index do |i|
vals[i] = vals[i].to_i
end
sprd = spread(vals[0], vals[1])
arr = Array.new(vals[1], "x")
arr.each_index do |i|
if sprd[i]
arr[i] = symbol
end
end
arr = arr.to_s
arr.gsub!(/\"/, '')
strs[0] = strs[0] + ' ' + arr + ' ' + strs[2]
strs.delete_at 1
strs.delete_at 2
end
return format_input strs[0]
end
# replaces multiplied values with arrays
# mult_values : strinf -> string
define :mult_values do |str|
str = format_input str
strs = str.split(/\s*\*\s*/)
while strs.length > 1
strs1 = strs[0].split(/\s+/)
symbol = ' ' + strs1.pop
while !valid_string? symbol
symbol = ' ' + strs1.pop + symbol
end
strs[0] = ""
strs1.each do |str1|
strs[0] = strs[0] + ' ' + str1
end
strs2 = strs[1].split(/\s+/,2)
head = strs2.shift
repeats = head.to_i
strs[1] = strs2[0] != nil ? strs2[0] : ""
arr = Array.new(repeats,symbol)
arr = arr.to_s
arr.gsub!(/\"/, '')
strs[0] = strs[0] + ' ' + arr + ' ' + strs[1]
strs.delete_at 1
end
return format_input strs[0]
end
# add spaces to an input string
# format_input string -> string
define :format_input do |str|
str.gsub!(/\[|\]|,|\(|\)/) do |s|
' ' + s + ' '
end
return str.gsub(/\s\s+/," ").strip
end
anvil = Hash.new
# forge : [symbol,string] hash -> sound
define :forge do |hash|
hash.each do |key,val|
anvil[key] = string_eval(val,[])
end
play_anvil anvil
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment