Skip to content

Instantly share code, notes, and snippets.

@lctrt
Created May 8, 2020 14:20
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lctrt/738c35cfd6970402e4556157f10428a6 to your computer and use it in GitHub Desktop.
Save lctrt/738c35cfd6970402e4556157f10428a6 to your computer and use it in GitHub Desktop.
MS18S Sequencer - forked for JF usage
--- m185 ~ 2-voice sequencer inspired by RYK M-185
-- forked from https://github.com/jlmitch5/m18s
-- in 1: clock
-- output on channel 1 and 2 from JF
function shouldGateFire (stage, numStages, gateMode)
if stage <= numStages then
if gateMode == "all" or (gateMode == "single" and stage == 1) or
(gateMode == "every2" and (stage + 1) % 2 == 0) or
(gateMode == "every3" and (stage + 2) % 3 == 0) or
(gateMode == "every4" and (stage + 3) % 4 == 0) or
(gateMode == "random" and math.random(0, 1) == 0) or
(gateMode == "long" and numStages == 1) then
return true
end
end
return false
end
nextStep1 = 1
nextStage1 = 1
pingPongDir1 = 'forward'
fixedLengthStageCount1 = 1
note1 = 0
level1 = 8
function advance1()
local nextNote1 = seq1[nextStep1][1]
local nextNumStages1 = seq1[nextStep1][2]
local nextGateMode1 = seq1[nextStep1][3]
print("one: \t\tmode: " .. mode1 .. "\tstep: " ..nextStep1 .. "\tstage: " .. nextStage1 .. "\tfixedLengthCount: " .. fixedLengthStageCount1 .. "\tnote: " .. nextNote1 .. "\t\toct: " .. oct1 .. "\tstageCount: " .. nextNumStages1 .. "\tgateMode: " .. nextGateMode1)
if nextStage1 == 1 then
note1 = nextNote1/12 + oct1
end
if shouldGateFire(nextStage1, nextNumStages1, nextGateMode1) then
-- output[2](pulse(gateLength1, 8))
ii.jf.play_voice(1,note1,level1)
elseif nextGateMode1 == "long" and nextStage1 == 1 then
ii.jf.play_voice(1,note1,level1)
elseif nextGateMode1 == "long" and nextStage1 >= nextNumStages1 then
ii.jf.play_voice(1,note1,0)
end
if mode1 == "fixedLength" and fixedLengthStageCount1 >= fixedLength1 then
nextStep1 = 1
nextStage1 = 1
fixedLengthStageCount1 = 1
ii.jf.play_voice(1,note,0) -- just in case you need to clear out a long gate
else
if mode1 == "fixedLength" then
fixedLengthStageCount1 = fixedLengthStageCount1 + 1
end
if nextStage1 >= nextNumStages1 or nextStep1 > #seq1 then
if mode1 == "forward" or mode1 == "fixedLength" then
nextStep1 = nextStep1 % #seq1 + 1
elseif mode1 == "pingPong" then
if nextStep1 == #seq1 then
pingPongDir1 = 'reverse'
elseif nextStep1 == 1 then
pingPongDir1 = 'forward'
end
if pingPongDir1 == 'forward' then
nextStep1 = nextStep1 % #seq1 + 1
else
nextStep1 = nextStep1 % #seq1 - 1
if nextStep1 == -1 then
nextStep1 = #seq1 - 1
end
end
elseif mode1 == "random" then
nextStep1 = math.random(1, #seq1)
end
nextStage1 = 1
else
nextStage1 = nextStage1 + 1
end
end
end
nextStep2 = 1
nextStage2 = 1
pingPongDir2 = 'forward'
fixedLengthStageCount2 = 1
note2 = 0
level2 = 8
function advance2()
local nextNote2 = seq2[nextStep2][1]
local nextNumStages2 = seq2[nextStep2][2]
local nextGateMode2 = seq2[nextStep2][3]
print("two: \t\tmode: " .. mode2 .. "\tstep: " ..nextStep2 .. "\tstage: " .. nextStage2 .. "\tfixedLengthCount: " .. fixedLengthStageCount2 .. "\tnote: " .. nextNote2 .. "\t\toct: " .. oct2 .. "\tstageCount: " .. nextNumStages2 .. "\tgateMode: " .. nextGateMode2)
if nextStage2 == 1 then
note2 = nextNote2/12 + oct2
end
if shouldGateFire(nextStage2, nextNumStages2, nextGateMode2) then
-- output[4](pulse(gateLength2, 8))
ii.jf.play_voice(2,note2,level2)
elseif nextGateMode2 == "long" and nextStage2 == 1 then
ii.jf.play_voice(2,note2,level2)
elseif nextGateMode2 == "long" and nextStage2 >= nextNumStages2 then
ii.jf.play_voice(2,note2,0)
end
if mode2 == "fixedLength" and fixedLengthStageCount2 >= fixedLength2 then
nextStep2 = 1
nextStage2 = 1
fixedLengthStageCount2 = 1
ii.jf.play_voice(2,note2,0) -- just in case you need to clear out a long gate
else
if mode2 == "fixedLength" then
fixedLengthStageCount2 = fixedLengthStageCount2 + 1
end
if nextStage2 >= nextNumStages2 or nextStep2 > #seq2 then
if mode2 == "forward" or mode2 == "fixedLength" then
nextStep2 = nextStep2 % #seq2 + 1
elseif mode2 == "pingPong" then
if nextStep2 == #seq2 then
pingPongDir2 = 'reverse'
elseif nextStep2 == 1 then
pingPongDir2 = 'forward'
end
if pingPongDir2 == 'forward' then
nextStep2 = nextStep2 % #seq2 + 1
else
nextStep2 = nextStep2 % #seq2 - 1
if nextStep2 == -1 then
nextStep2 = #seq2 - 1
end
end
elseif mode2 == "random" then
nextStep2 = math.random(1, #seq2)
end
nextStage2 = 1
else
nextStage2 = nextStage2 + 1
end
end
end
count = 0
function advance()
count = count + 1
advance1()
if count % 2 == 0 then
advance2()
end
print("\n")
end
function init()
input[1]{ mode = "change", direction = "rising" }
input[1].change = advance
ii.jf.mode(1)
end
-- configuration and initialization below, this is what crow will load on boot of the script
-- scales can be any length
-- voice 1
gateLength1 = .01
mode1 = "forward"
oct1 = 0
fixedLength1 = 10
scale1 = { 0, 4, 5, 7, 9, 12, 16, 17 }
seq1 = {
{ scale1[1], 1, "off" },
{ scale1[2], 2, "single" },
{ scale1[3], 3, "all" },
{ scale1[4], 4, "every2" },
{ scale1[5], 5, "every3" },
{ scale1[6], 6, "every4" },
{ scale1[7], 7, "random" },
{ scale1[8], 8, "long" }
}
-- voice 2
gateLength2 = .01
mode2 = "forward"
oct2 = -2
fixedLength2 = 10
scale2 = { 0, 4, 5, 7, 9, 12, 16, 17 }
seq2 = {
{ scale2[1], 1, "off" },
{ scale2[2], 2, "single" },
{ scale2[3], 3, "all" },
{ scale2[4], 4, "every2" },
{ scale2[5], 5, "every3" },
{ scale2[6], 6, "every4" },
{ scale2[7], 7, "random" },
{ scale2[8], 8, "long" }
}
-- for mode/gate mode lookup use, so you don't have to remember numbers and can type the strings
ms = { "forward", "random", "pingPong", "fixedLength" }
sGMs = { "off", "single", "all", "every2", "every3", "every4", "random", "long" }
-- setters below, you can run these in druid or ^^derwydd to modify and modulate the sequence
function setMode(_v, _m) if _v == 1 then mode1 = _m else mode2 = _m end end
function setFixedLength(_v, _fL) if _v == 1 then fixedLength1 = _fL else fixedLength2 = _fL end end
function setStepNote(_v, _s, _n) if _v == 1 then seq1[_s][1] = _n else seq2[_s][1] = _n end end
function setStageCount(_v, _s, _sC) if _v == 1 then seq1[_s][2] = _sC else seq2[_s][2] = _sC end end
function setThisSequenceOntoOther(_v) if _v == 1 then seq2 = {table.unpack(seq1)} else seq1 = {table.unpack(seq2)} end end
function setStageGateMode(_v, _s, _sGM) if _v == 1 then seq1[_s][3] = _sGM else seq2[_s][3] = _sGM end end
function randomizeMode(_v) if _v == 1 then mode1 = ms[math.random(1, #ms)] else mode2 = ms[math.random(1, #ms)] end end
function randomizeStep(_v, _s)
if _v == 1 then
seq1[_s] = { scale1[math.random(1, #scale1)], math.random(1, 8), sGMs[math.random(1, #sGMs)] }
else
seq2[_s] = { scale2[math.random(1, #scale2)], math.random(1, 8), sGMs[math.random(1, #sGMs)] }
end
end
function randomizeAllSteps(_v)
local seqLength = _v == 1 and #seq1 or #seq2
for i = 1, seqLength do randomizeStep(_v, i) end
end
randomizeAllSteps(1)
randomizeAllSteps(2)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment