Hello all. this is my first post here.
I discovered sonic pi recently and it seems like a great tool to complete the sequencer prototype that i’ve been working on for so long.
But today when i went to continue working on my exisitng script i was unable to get it to load in sonic pi.
i get no error message.
i get nothing. i clicky the play button but i get no confirmation that the script is running and it doesnt respond to any incomming midi cc.
here mis my code.
i would really apreciate if you could help me find what the problem is.
thank you very much.
parts = {
s1: { name: “s1”, id: 2, type: 1, channel: 1 },
s2: { name: “s2”, id: 3, type: 1, channel: 2 },
s3: { name: “s3”, id: 4, type: 1, channel: 3 },
s4: { name: “s4”, id: 5, type: 2, channel: 4 },
s5: { name: “s5”, id: 6, type: 2, channel: 5 },
}
parts.each do |part,hash|
hash[:current_pattern] = 1
hash[:patterns] =
32.times do | ni |
hash[:patterns][ni] = {
part: part,
index: ni,
isempty: true,
length: 16,
interval: 16,
base_note: 24,
play_order: 0,
swing: 0,
steps:
}
64.times do |si|
hash[:patterns][ni][:steps][si] = {
index: si,
trigger: false,
notea: 127,
noteb: 127,
notec: 127,
noted: 127,
velocity: 110,
duration: 100,
probability: 100,
repeats: 1
}
end
end
end
midi_in_port = “/midi:midi_through_midi_through_port-1_14_1:1/control_change”
live_loop :midi_in do
use_real_time
event_number, event_value = sync midi_in_port
cc_input(event_number, event_value)
#puts(“e: #{event_number}, v:#{event_value}”)
end
play_status = false
$midi_daw_port = “midi_through_midi_through_port-0_14_0”
$midi_tosc_port = “midi_through_midi_through_port-1_14_1”
pattern_intervals =
pattern_intervals[0] = 4
pattern_intervals[2] = 2
pattern_intervals[4] = 1
pattern_intervals[8] = 0.5
pattern_intervals[16] = 0.25
pattern_intervals[32] = 0.125
current_part = parts[:s1]
current_pattern = current_part[:patterns][1]
current_step = current_pattern[:steps][1]
bpm = 130
use_bpm bpm
ableton_ccs = {
start: 95,
stop: 96,
record: 97,
bpm: 92,
metronome: 91,
}
sync-ccs
sync_cc = {
channel: 16,
sync_start_end: 80,
part_number: 81,
step_being_played: 82,
pattern_number: 91,
pattern_isempty: 92,
pattern_base_note: 95,
pattern_interval: 96,
pattern_play_order: 97,
pattern_swing: 98,
step_number: 101,
step_trigger: 105,
step_mute: 106,
step_notea: 110,
step_noteb: 111,
step_notec: 112,
step_noted: 113,
step_velocity: 116,
step_duration: 117,
step_repeats: 119,
step_probability: 115
}
control_ccs = {
update_step_trigger: 99,
update_step_notea: 105,
update_step_noteb: 106,
update_step_notec: 107,
update_step_noted: 108,
update_step_velocity: 109,
update_step_duration: 110,
update_step_probability: 111,
update_step_repeats: 112,
deselect_steps: 71,
select_step: 73,
stop_step: 74,
stop_all_notes: 75,
play_note_ON: 83,
play_note_OFF: 84,
select_part: 87,
select_pattern: 88,
update_pattern_length: 90,
shift_pattern:93,
toggle_play: 92,
sync_to_tosc: 85
}
define :start_loops do
midi_cc ableton_ccs[:bpm], value: bpm-40, channel: 16, port: $midi_daw_port
midi_cc ableton_ccs[:start], value: 127, channel: 16, port: $midi_daw_port
play_status = true
live_loop :playstop do
use_real_time
use_bpm bpm
unless play_status
midi_cc ableton_ccs[:stop], value: 127, channel: 16, port: $midi_daw_port
stop
play_status = false
puts “ableton stop”
end
sleep 1
end
parts.each do | name, hash|
loop_name = :“loop_#{name}”
tick_set loop_name, 0
live_loop loop_name do
use_real_time
use_bpm bpm
part = parts[name]
type = part[:type]
pattern = part[:patterns][part[:current_pattern]]
pattern = part[:patterns][part[:current_pattern]]
interval = pattern_intervals[pattern[:interval]]
next_step = tick(loop_name) % pattern[:length]
if play_status == true
step = pattern[:steps][next_step+1]
if step[:trigger] == true
if step[:duration] > 100
tie = true
duration = 0.95
else
duration = step[:duration] * 0.0095
end
repeats = step[:repeats]
rep_duration = interval/repeats
note_duration = rep_duration * duration
repeats.times do |i|
if type == 1
if part[:name] == current_part[:name]
midi_cc sync_cc[:step_being_played], value: next_step, channel: sync_cc[:channel], port: $midi_tosc_port
end
midi_note_on step[:notea] + pattern[:base_note], velocity: step[:velocity], channel: part[:channel], port: $midi_daw_port
part[:prev_notes] = step[:notea] + pattern[:base_note]
sleep note_duration
if part[:name] == current_part[:name]
midi_cc sync_cc[:step_being_played], value: 121, channel: sync_cc[:channel], port: $midi_tosc_port
end
midi_note_off step[:notea] + pattern[:base_note], velocity: step[:velocity], channel: part[:channel], port: $midi_daw_port
part.delete :prev_notes
sleep rep_duration-note_duration
elsif type == 2
if part[:name] == current_part[:name]
midi_cc sync_cc[:step_being_played], value: next_step, channel: sync_cc[:channel], port: $midi_tosc_port
end
midi_note_on step[:notea] + pattern[:base_note], velocity: step[:velocity], channel: part[:channel], port: $midi_daw_port
part[:prev_notes] = step[:notea] + pattern[:base_note]
sleep note_duration
if part[:name] == current_part[:name]
midi_cc sync_cc[:step_being_played], value: 121, channel: sync_cc[:channel], port: $midi_tosc_port
end
midi_note_off step[:notea] + pattern[:base_note], velocity: step[:velocity], channel: part[:channel], port: $midi_daw_port
part.delete :prev_notes
sleep rep_duration-note_duration
end
end
else
if part[:name] == current_part[:name]
midi_cc sync_cc[:step_being_played], value: next_step, channel: sync_cc[:channel], port: $midi_tosc_port
end
sleep interval
end
else
puts("stop #{part[:name]}")
stop
end
end
end
end
define :toggle_play do
if play_status
puts “stop”
play_status = false
else
puts “play”
play_status = true
start_loops
end
end
define :cc_input do |cc_number, cc_value|
puts “#{cc_number}-#{cc_value}”
if cc_number == control_ccs[:toggle_play]
if cc_value == 127
toggle_play
end
elsif cc_number == control_ccs[:select_part]
parts.each do |part, values|
if (cc_value == values[:id])
stop_all_notes current_part
current_part = parts[part]
puts “#{cc_value} sel-part: #{current_part[:name]}, type: #{current_part[:type]}”
current_pattern = current_part[:patterns][current_part[:current_pattern]]
break
end
end
elsif cc_number == control_ccs[:select_pattern]
stop_all_notes current_part
current_part[:current_pattern] = cc_number
current_pattern = current_part[:patterns][current_part[:current_pattern]]
puts “sel-ptrn:#{current_pattern[:part]} : #{current_pattern[:index]}”
elsif cc_number == control_ccs[:select_step]
current_step = current_pattern[:steps][cc_value]
puts “sel-step:#{cc_value} - #{current_step[:trigger]},#{current_step[:notea]},#{current_step[:noteb]},#{current_step[:notec]},#{current_step[:noted]}”
if current_step[:trigger] == true
play_step cc_value,true
else
play_step cc_value,false
end
elsif cc_number == control_ccs[:deselect_steps]
current_step = nil
puts “no-current-step”
stop_all_notes current_part
elsif cc_number == control_ccs[:play_note_ON]
puts “note-on:#{cc_value}”
play_note(cc_value, true)
elsif cc_number == control_ccs[:play_note_OFF]
puts “note-off:#{cc_value}”
play_note(cc_value, false)
elsif cc_number == control_ccs[:update_pattern_length]
current_pattern[:length] = cc_value
puts “set pattern length:#{cc_value}”
elsif cc_number == control_ccs[:shift_pattern]
shift_pattern(cc_value)
puts “SHIFT:#{cc_value}”
elsif cc_number == control_ccs[:update_step_trigger]
if(cc_value == 127)
current_step[:trigger] = true
else
current_step[:trigger] = false
end
puts “trigger:#{current_step[:trigger]} - (#{current_part[:name]} pt:#{current_pattern[:index]} s:#{current_step[:index]})”
elsif cc_number == control_ccs[:update_step_notea]
current_step[:notea] = cc_value
puts “note-a:#{current_step[:notea]} - (#{current_part[:name]} pt:#{current_pattern[:index]} s:#{current_step[:index]})”
elsif cc_number == control_ccs[:update_step_noteb]
current_step[:noteb] = cc_value
puts “note-b:#{current_step[:noteb]} - (#{current_part[:name]} pt:#{current_pattern[:index]} s:#{current_step[:index]})”
elsif cc_number == control_ccs[:update_step_notec]
current_step[:notec] = cc_value
puts “note-c:#{current_step[:notec]} - (#{current_part[:name]} pt:#{current_pattern[:index]} s:#{current_step[:index]})”
elsif cc_number == control_ccs[:update_step_noted]
current_step[:noted] = cc_value
puts “note-d:#{current_step[:noted]} - (#{current_part[:name]} pt:#{current_pattern[:index]} s:#{current_step[:index]})”
elsif cc_number == control_ccs[:update_step_velocity]
current_step[:velocity] = cc_value
puts “velocity:#{current_step[:velocity]} - (#{current_part[:name]} pt:#{current_pattern[:index]} s:#{current_step[:index]})”
elsif cc_number == control_ccs[:update_step_duration]
current_step[:duration] = cc_value
puts “duration:#{current_step[:duration]} - (#{current_part[:name]} pt:#{current_pattern[:index]} s:#{current_step[:index]})”
elsif cc_number == control_ccs[:update_step_probability]
current_step[:probability] = cc_value
puts “probability:#{current_step[:probability]} - (#{current_part[:name]} pt:#{current_pattern[:index]} s:#{current_step[:index]})”
elsif cc_number == control_ccs[:update_step_repeats]
current_step[:repeats] = cc_value
puts “repeats:#{current_step[:repeats]} - (#{current_part[:name]} pt:#{current_pattern[:index]} s:#{current_step[:index]})”
end
end
define :play_note do |note_num, value|
note_number = note_num + current_pattern[:base_note]
if current_part[:type] == 1
unless value == false
stop_all_notes current_part
current_part[:prev_notes] = note_number
midi_note_on note_number, velocity: 100, channel: current_part[:channel], port: $midi_daw_port
else
stop_all_notes current_part if current_part[:prev_notes] == note_number
end
elsif current_part[:type] == 2
unless value == false
midi_note_on note_number, velocity: 100, channel: current_part[:channel], port: $midi_daw_port
current_part[:prev_notes] = if current_part[:prev_notes] == nil
current_part[:prev_notes][note_number] = note_number
else
current_part[:prev_notes].delete note_number unless current_part[:prev_notes] == nil
midi_note_off note_number, velocity: 0, channel: current_part[:channel], port: $midi_daw_port
end
end
end
define :play_step do |step, value|
stop_all_notes current_part
if value == true
if current_step[:trigger]
if current_part[:type] == 1
midi_note_on current_step[:notea] + current_pattern[:base_note], velocity: current_step[:velocity], channel: current_part[:channel], port: $midi_daw_port
current_part[:prev_notes] = current_step[:notea] + current_pattern[:base_note]
elsif current_part[:type] == 2
midi_note_on current_step[:notea] + current_pattern[:base_note], velocity: current_step[:velocity], channel: current_part[:channel], port: $midi_daw_port
unless current_step[:noteb] > 100
midi_note_on current_step[:noteb] + current_pattern[:base_note], velocity: current_step[:velocity], channel: current_part[:channel], port: $midi_daw_port
end
unless current_step[:notec] > 100
midi_note_on current_step[:notec] + current_pattern[:base_note], velocity: current_step[:velocity], channel: current_part[:channel], port: $midi_daw_port
end
unless current_step[:noted] > 100
midi_note_on current_step[:noted] + current_pattern[:base_note], velocity: current_step[:velocity], channel: current_part[:channel], port: $midi_daw_port
end
current_part[:prev_notes] = []
current_part[:prev_notes][current_step[:notea]] = current_step[:notea] + current_pattern[:base_note]
current_part[:prev_notes][current_step[:noteb]] = current_step[:noteb] + current_pattern[:base_note]
current_part[:prev_notes][current_step[:notec]] = current_step[:notec] + current_pattern[:base_note]
current_part[:prev_notes][current_step[:noted]] = current_step[:noted] + current_pattern[:base_note]
end
end
end
end
define :stop_all_notes do | part |
if part[:type] == 1
unless part[:prev_notes] == nil
puts “killin notes: #{part[:name]}”
midi_note_off part[:prev_notes], velocity: 0, channel: part[:channel], port: $midi_daw_port
end
elsif part[:type] == 2
unless part[:prev_notes] == nil
puts “killin notes: #{part[:name]}”
part[:prev_notes].each do |k,v|
unless k == nil or k > 100
midi_note_off k, velocity: 0, channel: part[:channel], port: $midi_daw_port
end
end
end
end
part.delete :prev_notes
end
define :sync_to_tosc do
use_bpm 130
wait = 0.0088
midi_cc sync_cc[:sync_start_end], value: 127, channel: sync_cc[:channel], port: $midi_tosc_port
parts.each do |part, contents|
puts “Selecting part: #{part}”
midi_cc sync_cc[:part_number], value: tick(:part), channel: sync_cc[:channel], port: $midi_tosc_port
sleep wait
patterns = contents[:patterns]
32.times do | i|
puts “Prt: #{part}, ptrn: #{i}”
midi_cc sync_cc[:pattern_number], value: i, channel: sync_cc[:channel], port: $midi_tosc_port
if patterns[i][:isempty]
puts "Part: #{part}, Pattern: #{i} Empty."
midi_cc sync_cc[:pattern_isempty], value: 127, channel: sync_cc[:channel], port: $midi_tosc_port
sleep wait
else
midi_cc sync_cc[:pattern_play_order], value: patterns[i][:play_order], channel: sync_cc[:channel], port: $midi_tosc_port
midi_cc sync_cc[:pattern_base_note], value: patterns[i][:base_note], channel: sync_cc[:channel], port: $midi_tosc_port
midi_cc sync_cc[:pattern_interval], value: patterns[i][:interval], channel: sync_cc[:channel], port: $midi_tosc_port
midi_cc sync_cc[:pattern_swing], value: patterns[i][:swing], channel: sync_cc[:channel], port: $midi_tosc_port
sleep wait
64.times do |j|
puts "Part: #{part}, Pattern: #{i} Step: #{j}"
step = patterns[i][:steps][j]
midi_cc sync_cc[:step_number], value: j, channel: sync_cc[:channel], port: $midi_tosc_port
sleep wait
if step[:trigger] == true
midi_cc sync_cc[:step_trigger], value: 127, channel: sync_cc[:channel], port: $midi_tosc_port
midi_cc sync_cc[:step_probability], value: step[:probability], channel: sync_cc[:channel], port: $midi_tosc_port
midi_cc sync_cc[:step_notea], value: step[:notea], channel: sync_cc[:channel], port: $midi_tosc_port
midi_cc sync_cc[:step_noteb], value: step[:noteb], channel: sync_cc[:channel], port: $midi_tosc_port
midi_cc sync_cc[:step_notec], value: step[:notec], channel: sync_cc[:channel], port: $midi_tosc_port
midi_cc sync_cc[:step_noted], value: step[:noted], channel: sync_cc[:channel], port: $midi_tosc_port
midi_cc sync_cc[:step_velocity], value: step[:velocity], channel: sync_cc[:channel], port: $midi_tosc_port
midi_cc sync_cc[:step_duration], value: step[:duration], channel: sync_cc[:channel], port: $midi_tosc_port
midi_cc sync_cc[:step_repeats], value: step[:repeats], channel: sync_cc[:channel], port: $midi_tosc_port
else
midi_cc sync_cc[:step_trigger], value: 0, channel: sync_cc[:channel], port: $midi_tosc_port
end
sleep wait
end
end
end
end
midi_cc sync_cc[:sync_start_end], value: 0, channel: sync_cc[:channel], port: $midi_tosc_port
end
define :shift_pattern do |dir|
temp_pattern =
ii = 0
current_pattern[:length].times do |i|
if dir == 0
ii = ((i+1) % current_pattern[:length])
else
ii = ((i-1) % current_pattern[:length])
end
temp_pattern[ii] = {}
current_pattern[:steps][i].each do |key, value|
temp_pattern[ii][key] = value
end
temp_pattern[ii][:index] = ii
end
current_pattern[:length].times do |i|
temp_pattern[i].each do |key, value|
current_pattern[:steps][i][key] = value
end
end
end
#reset
midi_note_off 125, velocity: 1, channel: 16, port: $midi_tosc_port
parts.each do |k,v|
puts k
end