Created
February 13, 2016 15:01
-
-
Save RusticFlare/a18097c0e6186edf7ab8 to your computer and use it in GitHub Desktop.
The code for the initial version of forge
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
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