I came across a youtube video which shows an Axoloti set up to emulate an SH101 style sequencer being trigged by an incoming note.
I had not seen this style of sequencer before, and was interested in the patterns that can be generated particularly when you have say a 7 step sequence that has 8 triggers per bar, so the resulting pattern kind of slides around the main rhythm.
Since I don’t yet have an Axoloti I put toget a UniMIDI script to get the same result. I use this with my Electribe 2 Sampler, which is connected via USB to my Macbook running the script.
On the E2S I have a pattern set up as follows:
Part 1 – this is set so Osc = ‘Audio In Mono’ – which makes it effectively muted. The E2S sequencer has every step to this part off. Keys pressed on this part get sent out on Midi Channel 1.
Part 2 – this is set to one of the built in wave forms (not a sample). Also, the ‘AMP EG’ must be selected with a highish decay/release value. The E2S sequencer has every step to this part off. The decay/release is needed because the incoming notes will have a not off immediately after the note on, so the actual audible duration depends on the decay time. This is also why samples don’t work too well, the envelope generator only works how it needs to for the built in waveforms.
Parts 3-15 – Set up with whatever Osc and pattern you like.
Part 16 – this is set so Osc = ‘Audio In Mono’ – which makes it effectively muted. Any note sent on this channel (e.g. via the E2S sequenver) will act as a trigger for the SH101 style sequencer.
To use:
Set up the E2S as above. Then go to ‘part 1′ and press the ‘IFX on’ button so it lights red. This puts the SH101 script into ‘record mode’. Any notes you play on part 1 in this mode get added to the sequence (and also echoed back on Channel 2). Press ‘IFX On’ again (so light goes off) to put the SH101 sequencer into ‘play’ mode. Now go to ‘part 16′ and turn on/off whatever steps you want to trigger a note. Press play.
Going to ‘part 1′ and pressing another note key while in play mode will transpose the current sequence.
—-
!– HTML generated using hilite.me –>
#!/usr/bin/ruby dir = File.dirname(File.expand_path(__FILE__)) $LOAD_PATH.unshift dir + "/../lib" require "unimidi" IN_CHANNEL=1 TRIGGER_CHANNEL=16 OUT_CHANNEL=2 REC_MODE_CC=0x68 #on my electribe 2, this is triggered by pressing the 'IFX ON' button. DEBUG_LEVEL=1 #0=silent,1=major events, 2=all events @input = UniMIDI::Input.gets @output = UniMIDI::Output.gets @rec_mode=false @seq_length=0 @seq=[] @seq_ptr=0 @transpose_amount=0 def debug_log (s,level) puts s unless level>DEBUG_LEVEL end def execute_status(s) debug_log("#{"%2X" % s[0]},#{s[1]},#{s[2]}",2) if ((s[0])==0xb0+IN_CHANNEL-1) && (s[1]==REC_MODE_CC)then new_rec_mode=(s[2]>64) if (@rec_mode==false) && (new_rec_mode==true) then @seq=[] @seq_length=0 @seq_ptr=0 end @rec_mode=new_rec_mode debug_log("REC_MODE: #{@rec_mode}",1) end if (s[0]==0x90+IN_CHANNEL-1) && (s[2]>1)then #it's a note-on event on input channel if (@rec_mode) then @seq[@seq_length]=s[1] @seq_length+=1 @output.puts(0x8F+OUT_CHANNEL, s[1], 64) #echo so can hear what was just played @output.puts(0x8F+OUT_CHANNEL, s[1], 0) #immediate note off debug_log("added note - seq length #{@seq_length}",1) end if (!@rec_mode) && (@seq_length>0) && (IN_CHANNEL!=TRIGGER_CHANNEL) then # not recording or a trigger so do a transpose @transpose_amount=s[1]-@seq[0] debug_log("transpose amount now - #{@transpose_amount}",1) end end if (s[0]==0x90+TRIGGER_CHANNEL-1) && (s[2]>1)then #it's a note-on event on trigger channel if (!@rec_mode) then if @seq_length>1 then debug_log( "play note - seq ptr #{@seq_ptr}",1) @output.puts(0x8F+OUT_CHANNEL, @seq[@seq_ptr]+@transpose_amount, 64) @output.puts(0x8F+OUT_CHANNEL, @seq[@seq_ptr]+@transpose_amount, 0) #immediate note off @seq_ptr+=1 @seq_ptr=0 if @seq_ptr==@seq_length else debug_log("skipping - no sequence",1) end end end end status=[] begin loop do m = @input.gets_data m.each do |b| next if b==0xf8 #ignore clock beats if (b<0x80) then status<<b else status=[b] end if status.length==3 then execute_status(status) cmd_byte=status[0]#keep original first byte for short form commands status=[cmd_byte] end end end ensure @output.puts(0xAF+OUT_CHANNEL, 0x7B, 0) #all notes off end