Hi folks,
Every few months I get this terrible urge to code something huge and useless… think of
it as a time-wasting exercise, if you want.
So, this time around, here we have a little mixer and sequencer. I know Robin’s work on
OSC/TouchOS knocks this out the window, but I never said it was good… just that it takes up
my time…
Couple of tiny glitches to work out, which will no doubt plague me for a couple of weeks.
EDIT: Fixed an errant ‘tick’ that was setting the bpm incorrectly.
Eli…
#Rubber Soul - 4 Channel Mixer & Sequencer
#Eli... March 2018.
#======================================================================================================================================
# Use: Assign an instrument to channel 1-4, choose a bpm, drum and beat pattern, then run.
# You can have multiple instruments on the same channel. Volume defaults to 3 on all
# channels unless you are using the sequencer, in which case it uses the volume set
# in the sequncer list. If a channel has no instruments attached, nothing will play in
# the sequencer for that channel... Still a Work in Progess / Time Wasting Exercise...
#
# Enjoy... or laugh silently behind your hand... :)
# Eli...
#======================================================================================================================================
#Set BPM 60 90 100 110 120
#==========================
set_bpm = [0, 0, 0, 0, 1]
#==========================
# Instrument Channel
#====================
kick= 2
hats= 2
rim= 2
woodblock= 0
bass= 0
snap1= 2
snap2= 0
chime= 0
background1= 0
tune1= 1
#===========================================
# Drum: :bd_ada :bd_fat :bd_boom :bd_808
#===========================================
drum_select = [1, 0, 0, 0]
#===========================================
# beats/bar [1, 2, 3, 4]
#==============================
beat_select = [0, 1, 0, 1]
hat_select = [0, 1, 1, 0]
rim_select = [0, 0, 0, 0]
snap1_select = [0, 0, 1, 0]
snap2_select = [1, 0, 0, 0]
chime_select = [0, 1, 0, 0]
woodblock_select = [0, 0, 0, 0]
#==============================
ON=1
OFF=0
SINGLE=0
LOOP=1
SEQUENCER = ON
MODE = LOOP
#===============================================================
bar = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
#===============================================================
volume1 = [3, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
volume2 = [0, 0, 0, 0, 0, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0]
volume3 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
volume4 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
#==============================================================
tune1_chords = (ring :r,
(chord_degree :i,:A3,:minor,3),(chord_invert (chord :G3,:major),1),
(chord_degree :iv,:D3,:minor,4),(chord_degree :i,:A3,:minor),
)
set_volume! 5
# bass notes/rests
bass_notes = (ring :r, :r, :c2, :d3, :r, :f3, :r, :a1, :f2)
#default drum
drum_selected = :bd_ada
channel = [0, 0, 0, 0]
mixer = [0, 0, 0, 0]
mix = [0, 0, 0, 0]
define :start_channel do |i=1,x=0|
if i>0 && i<5 then
channel[i] = 2
if x > 0 then
mixer[i] = x
end
set :ch[i], 2
else
puts "Channel number outside 1-4"
end
end
define :oneshot_channel do |i|
if i>0 && i<5 then
channel[i] = 1
set :ch[i],1
else
puts "Channel number outside 1-4"
end
end
define :mute_channel do |i|
if i>0 && i<5 then
channel[i] = 0
set :ch[i],0
else
puts "Channel number outside 1-4"
end
end
define :stop_channel do |i|
if i>0 && i<5 then
channel[i] = 0
mixer[i] = 0
set :ch[i], 0
else
puts "Channel number outside 1-4"
end
end
define :loop_channel do |i|
if i>0 && i<5 then
channel[i] = 0
set :ch[i],2
else
puts "Channel number outside 1-12"
end
end
define :default_mixer_values do
set :mix [1], 0
set :mix [2], 0
set :mix [3], 0
set :mix [4], 0
end
define :set_bpm do
bpms=[60,90,100,110,120].ring
tick_reset
set_bpm.each do |x|
tick
set :bpm, bpms.look if x == 1
puts x
puts bpms.look
end
end
#This is a hack to restart tune1/background1
# with a new bpm, instead of starting a new instance.
bpms=[60,90,100,110,120].ring
temp=0
tick_reset
if tune1 > 0
temp = tune1
stop_channel tune1
end
set_bpm.each do |x|
tick
set :bpm, bpms.look if x == 1
end
if temp >0
start_channel tune1, 3
end
tick_reset
if background1 > 0
temp = background1
stop_channel background1
end
tick
set_bpm.each do |x|
set :bpm, bpms.look if x == 1
end
if temp >0
start_channel background1, 3
end
live_loop :switch_channels do
instruments = [kick,hats,rim,woodblock,bass,snap1,snap2,chime,background1,tune1]
instruments.each do |x|
start_channel x, 3 if x > 0
end
sleep 0.25
end
set_bpm
live_loop :beats do
speed = get :bpm
use_bpm speed
sleep 1
end
live_loop :bar do
sync :beats
sleep 4
end
live_loop :do_sequencer do
if SEQUENCER == ON then
if MODE == LOOP
sequence=2
else
sequence=1
end
if sequence>0 then
bar.each do |x|
sync :bar
finish=x-1
set :mix [1], volume1[x-1]
set :mix [2], volume2[x-1]
set :mix [3], volume3[x-1]
set :mix [4], volume4[x-1]
puts volume1[x-1], volume2[x-1], volume3[x-1],volume4[x-1]
if finish == 15 then
if MODE == SINGLE then
sequence = 0
end
end
end
end
if sequence == 1 then
sequence = 0
end
else
sleep 0.25
end
end
live_loop :kick do
if channel[kick]>0 then
if SEQUENCER == ON then
this_vol = get :mix [kick]
else
this_vol = 3
end
drum_selected = :bd_ada if drum_select[1] == 1
drum_selected = :bd_fat if drum_select[2] == 1
drum_selected = :bd_boom if drum_select[3] == 1
drum_selected = :bd_808 if drum_select[4] == 1
beat_select.each do |x|
sync :beats
sample drum_selected,amp: this_vol if x == 1
end
else
sleep 0.25
end
end
live_loop :hats do
if channel[hats]>0 then
if SEQUENCER == ON then
this_vol = get :mix [hats]
else
this_vol = 3
end
hat_select.each do |x|
sync :beats
sample :sn_dolf, sustain: 0, release: 0.08,amp: this_vol if x == 1
end
if channel[hats] == 1 then
channel[hats] = 0
end
else
channel[hats] = 0
sleep 0.5
end
end
with_fx :rhpf, res: 0.85, cutoff: 118, amp: 0.7 do
live_loop :woodblock do
if channel[woodblock]>0 then
if SEQUENCER == ON then
this_vol = get :mix [woodblock]
else
this_vol = 3
end
woodblock_select.each do |x|
sync :beats
sample :elec_wood, sustain: 0, release: 0.08,amp: this_vol if x == 1
end
if channel[woodblock] == 1 then
channel[woodblock] = 0
end
else
channel[woodblock] = 0
sleep 0.5
end
end
end
with_fx :rhpf, res: 0.85, cutoff: 118, amp: 0.7 do
with_fx :distortion do
live_loop :rim do
if channel[rim]>0 then
if SEQUENCER == ON then
this_vol = get :mix [rim]
else
this_vol = 3
end
rim_select.each do |x|
sync :beats
sample :elec_blip, sustain: 0.006, cutoff:110, rate: 0.8,amp: this_vol if x == 1
end
if channel[rim] == 1 then
channel[rim] = 0
end
else
channel[rim] = 0
sleep 0.5
end
end
end
end
live_loop :bass do
speed = get :bpm
use_bpm speed
if channel[bass]>0 then
if SEQUENCER == ON then
this_vol = get :mix [bass]
else
this_vol = 3
end
if rand(1) > 0.75
bass_notes = (ring :r, :r, :c2, :d3, :r, :f3, :r, :a1, :f2)
else
bass_notes=bass_notes.shuffle
end
use_synth :fm
use_transpose +0
use_synth_defaults release: 0.125 + rrand(0, 0.2), amp: this_vol, pan: rrand(-0.5, 0.5)
play bass_notes.look, cutoff: rrand(30, 130)
sleep 0.25
tick
if channel[bass] == 1 then
channel[bass] = 0
end
else
channel[bass] = 0
sleep 0.5
end
end
live_loop :snap1 do
speed = get :bpm
use_bpm speed
if channel[snap1]>0 then
if SEQUENCER == ON then
this_vol = get :mix [snap1]
else
this_vol = 3
end
snap1_select.each do |x|
sync :beats
sample :perc_snap, sustain: 0, release: 0.08,amp: this_vol if x == 1
end
if channel[snap1] == 1 then
channel[snap1] = 0
end
else
channel[snap1] = 0
sleep 0.5
end
end
live_loop :snap2 do
speed = get :bpm
use_bpm speed
if channel[snap2]>0 then
if SEQUENCER == ON then
this_vol = get :mix [snap2]
else
this_vol = 3
end
snap2_select.each do |x|
sync :beats
sample :perc_snap2, sustain: 0, release: 0.08,amp: this_vol if x == 1
end
if channel[snap2] == 1 then
channel[snap2] = 0
end
else
channel[snap2] = 0
sleep 0.5
end
end
live_loop :chime do
speed = get :bpm
use_bpm speed
if channel[chime]>0 then
if SEQUENCER == ON then
this_vol = get :mix [chime]
else
this_vol = 3
end
chime_select.each do |x|
sync :beats
sample :elec_chime,amp: this_vol if x == 1
end
if channel[chime] == 1 then
channel[chime] = 0
end
else
channel [chime] = 0
sleep 0.5
end
end
with_fx :flanger, stereo_invert_wave: 1, feedback: 0.625, amp: 0.3 do
with_fx :echo, mix: 0.8, phase: 0.75, decay: 4 do
live_loop :background1 do
speed = get :bpm
use_bpm speed / 2.0
if channel[background1]>0 then
if SEQUENCER == ON then
this_vol = get :mix [background1]
else
this_vol = 0.5
end
use_synth :tri
mynote = (note_range, :g2, :g4, pitches: (scale, :g6, :minor_pentatonic))
play mynote.choose,amp: this_vol
sleep 0.25
if channel[background1] == 1 then
channel[background1] = 0
end
else
channel[background1] = 0
sleep 0.5
end
end
end
end
live_loop :tune1 do
speed = get :bpm
use_bpm speed
if channel[tune1]>0 then
if SEQUENCER == ON then
this_vol = get :mix [tune1]
else
this_vol = 0.5
end
use_synth :prophet
use_synth_defaults attack: 0.05, sustain: 0.5, release: 0.75,
cutoff: 80,amp: this_vol
with_fx :flanger do
tune1_chords=tune1_chords.shuffle
mychord = tune1_chords.choose
if mychord == :r then
sleep 0.5
else
dur = [0.5,1].choose
play mychord, release: dur
sleep dur
if channel[tune1] == 1 then
channel[tune1] = 0
end
end
end
else
channel[tune1] = 0
sleep 0.25
end
end