Created
May 8, 2020 14:20
-
-
Save lctrt/738c35cfd6970402e4556157f10428a6 to your computer and use it in GitHub Desktop.
MS18S Sequencer - forked for JF usage
This file contains 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
--- 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