Arduino Based MIDI Sequencer

I’ve programmed a sequencer for the Arduino microcontroller platform, designed to be used with the Sparkfun MIDI Shield. The sequencer combines an arpeggiating sequencer like that found on the Access Virus with a transposable recording sequencer, similar to the one on the Roland SH-101.

get it here.

I make fairly extensive use of MIDI in my own setup, so I’ve tried to keep the sequencer fully compatable with all MIDI data, SYSEX included. Any data not used by the sequencer channel should be passed to the output, and the sequencer has a ‘bypass’ function for which all MIDI data is passed directly to the output. The sequencer also stores and sequences velocity data along with the note data.

The mode is selected with the ‘A0‘ knob – if it’s all the way counter-clockwise, the sequencer works in recording mode. Other positions select pre-defined sequences to use in apeggiating sequence mode.

There are three selectable ‘trigger modes’ for the sequencer – inspired by the sequencer modes on the DSI Evolver. By default, the sequence runs normally, but can be set to run in ‘note gate’ or ‘note retrigger’ modes. In these modes, the sequencer only plays when notes are held. In ‘note gate’ the sequencer runs muted, and unmutes with notes held. In ‘note retrigger’ mode, the sequencer restarts when a new note is played (after all notes have been released).

The D4 and D3 buttons work as ‘shifts’ – holding these give the knobs and other buttons different functions. Here’s a summary of the controls:

A0: sequence select
A1: note length
D2: start/stop playing, or restart sequence if synchronised to external MIDI clock
D4: erase notes when recording

shift D4+A0: tempo, or step duration if clocked externally (from 32nd notes to dotted 8ths).
shift D4+A1: sequence loop length – fully clockwise, the entire sequence is played. turning counter-clockwise shortens the number of steps the pattern is looped by adjusting the end position.
shift D4+D2: temporarily mute sequencer (inverted for ‘note gate’ trigger modes).

shift D3+A1: trigger mode – counter-clockwise is normal, in the middle is ‘note gate’ and clockwise is ‘note retrigger’.
shift D3+D2: arm record when in transposable recorder mode (A0 fully counter-clockwise). The red LED will come on, and blink on the first step of the sequence.
shift D3+D4: bypass. The green LED will come on fully to show the sequencer is bypassed.

some more information on the modes:

Transposable Recording Sequencer
Turn A0 completely counter-clockwise, press play (D2) or start the master MIDI sequencer, then hold D3 and press D2 – the red LED should light. The sequence is now recording. any notes received on the sequencer channel will be recorded and looped continuously (overdubbed). To erase notes, press and hold D4 – only steps that would be played while D4 is held will be erased.
To exit recording mode, hold D3 and press D2 again – the red LED will go out. The sequencer is now in transpose mode, using the lowest note recorded as the transpose basis. Any note pressed above or below the basis note will transpose the entire sequence up or down. Transpose can also be used in combination with ‘note gate’ and ‘note retrigger’ modes.

Arpeggiating Sequencer
There are currently seven stored patterns that this mode can use. Changing these patterns, or adding more, is pretty easy to do in the Arduino sketch. One of the patterns, for example, looks like:
{1,0,2,0,3,0,4,0,5,0,6,0,7,0,8,0}
Each number represents one of 16 steps. The zeros are rests – no note gets played on that step. The other numbers represent the order of the notes in the chord that was last played. If less than 8 notes were played, the numbers ‘wrap’. For example, say a C-Major chord is played, C-E-G, in that order. The sequence would then be:
{C,-,E,-,G,-,C,-,E,-,G,-,C,-,E,-}
Going back to C again on the first step of the sequence.

Installation
The Arduino sketch is included here.
I’ve also included the version of the FortySevenEffects MIDI library I used to compile. This is the current ‘dev’ branch of that library and includes some MIDI thru functions that might not be in the main library. It’s what I used for testing, so everything should work as expected if you include it in your /libraries/ folder ‘as is’ when compiling.

Code Stuff
If you want to dive into the provided code, there are a few things that are simple to change. At the top, the CHANNEL define number can be easiliy changed to allow the sequencer to operate on a different MIDI channel, and this should cause the data on other MIDI channels to be passed to the output. Note that the MIDI channels are not zero indexed – channel 1 is 1 and channel 16 is 16.
The sequence length can be changed with ‘const int maxSeqLength=16;’ Note that the data in int ‘noteSeq[numberSequences][maxSeqLength]’ will have to be amended accordingly.
Finally, the maximum number of notes that can be held in a chord is currently 8. Holding more will push out the earlier notes (as will releasing only some notes and pressing new ones). If you’d like to increase or decrese this from 8, change ‘const int holdNotes=8;’ and update the ‘activeNotes’ and ‘activeVelo’ arrays accordingly. The ‘noteSeq’ data will also have to be changed to reflect the reduced or expanded number of notes available.
There is also a ‘hidden function’ I haven’t mentioned, but should be evident from the sketch :)

Finally…
Big thanks to Francois Best for his excellent work on the Arduino MIDI library, and for the quick response in getting it up and running with this sketch!
Thanks also to William Bajzek for some initial inspiration from his Arduino arpeggiator project.

19 Responses

  1. Steve says:

    Thanks so much for creating this. I just got started with Arduino in order to create a sysex controller for the Kenton MIDI/CV converter in my Eurorack modular setup, and I also had my eye out for existing code with exactly this kind of functionality. Now I’ve incorporated my code into yours and they’re playing together quite well. One question: Is there a reason for the tempo range you chose? I’d like to expand it if possible, on both the high and low ends.

    • Thanks Steve! Glad it’s been helpful for you! Yes, there is a reason for the tempo range – the tempo is adjusted by hardware interrupt, which makes the timing much more stable, but can lead to overruns if the interrupt time is set too low, and this can lock up the arduino. I think it can be expanded (running it more slowly in particular should be fine), but it might be safer to adjust the timing divisions. Nice site, and good luck!

  2. Jon Pyre says:

    Thanks very much for a nice sequencer.

    The first thing that comes to mind is passing midi through when received from external sequencer and addition to code for LCD. I will send you my clumsy attempts at code but you are obviously more advanced at it than I, so if you get to it first please post.

    • Yes, I remember testing this more completely after making the video and you’re right! There are some messages that don’t get passed! I don’t know if I’ll have time to come back to this, it was nice as a trial project, but honestly the hardware limits the amount of stuff that can be crammed in there! Hopefully, the sketch will serve as a guide to future ambitious ‘duino programmers.

      At the moment, I’m working on adding some sequencing and MIDI features to Julian Schmidt’s LXR at Sonic Potions. It’s a quality piece of kit, I recommend it 😉

      • jonpyre says:

        LXR looks like a great piece of kit. Where do the samples come from? Are they re-programmable? Sample based? Looking forward to your work there. I may just have to sign up for one…

        • Yeah, the LXR is great, the sounds in this video aren’t samples – it’s a virtual analog drum synth! So it’s a bit like making drum sound patches on a Virus or Elektron kit like Machinedrum. You can import a small amount of samples, but that’s not it’s strong suit.

          The sequencer on it is pretty great, too, I have a lot of additions in mind for it… :)

  3. Ben Hohlfeld says:

    I tried to make it, but it says the following:

    Arduino: 1.5.8 (Mac OS X), Board: “Arduino Uno”

    seq_final.ino: In function ‘void setup()':
    seq_final.ino:136:30: error: ‘midi’ has not been declared
    seq_final.ino: In function ‘void HandleFrame(int)':
    seq_final.ino:692:31: error: ‘midi’ has not been declared
    seq_final.ino: In function ‘void updateControls()':
    seq_final.ino:808:40: error: ‘midi’ has not been declared
    seq_final.ino:811:40: error: ‘midi’ has not been declared

    what am I doing wrong?

    Thank you for writing it ! Great work.

    • Thanks for giving it a shot, Ben! I think I remember that I was using an older version of the arduino MIDI library, and that they changed some of the functions in updates. I have the library files stashed away somewhere, I’ll try and edit this post and put a complete copy of the files I used to build this!

    • Frank says:

      You can fix this by removing all occurences of the string midi:: from the sketch and using the latest MIDI library

  4. sam sam says:

    thanks this is amazingly useful!

    however trying to make it a 64 step sequencer. managed to ramp it up to 32 steps but it just won’t work going up to 64… would there be any reason?

    thanks

    sam

    • Peter says:

      When you use to much memmory, the (=any) code becomes unstable.
      Esspecially large data arrays consume a lot of memmory.

  5. Peter says:

    Man!! Your code rocks.
    At first I got a lot of errors that MIDI was not decalred.
    I added one line to it
    MIDI_CREATE_DEFAULT_INSTANCE();
    And then it worked flawless.
    I want to add an eprom for more storage capacity and an LCD display.

      • Peter says:

        I was messing arround yesterday with the MIDI shield with your (un modified) code.
        I was struggling with recording notes to the sequencer part because there is no metronome. The LED-s are blinking but it was still difficult to record a sequence.
        By accidient I discovered that when the shield is in record mode but not running, you can play the notes on the keyboard and press D4 when you want to insert a rest in the sequence. So you can record stepwise, without keeping the beat.
        This is perfect!!

  6. Diego says:

    Hi dear,
    is there any way to program an arduino platform in a way that
    work in the same mode of sh 101 arpeggio or sequence ( you know the “special” feature triger..)?

  7. Tormod Carstens says:

    Thank you!
    Countless hours of programming a shitty arp that doesn’t work has been replaced with your code and hours of music making. Brilliant!

  8. waxworth says:

    Hi Brendan, I’ve been playing around with the MIDI sequencer for Arduino..it’s great! I was wondering if it was possible to make the user sequencer function record polyphonic steps? Any pointers greatly appreciated! Many thanks

Leave a Reply to Steve Cancel reply

*