Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 7 of 7

Thread: yet another Teensy based MIDI Sequencer

  1. #1

    yet another Teensy based MIDI Sequencer


    I like to present the project, I am working on currently to your.
    it is a MIDI Step Sequencer running with a Teensy 4.1 with 16MB PSRAM.

    I cannot count the times I started working on my own Sequencer (first one on Atmel chips before Arduino was a thing), but did my first real project around 2 years ago, after I realized how cheap you can order PCBs and you don’t have to use those breadboard where you need to cable every connection or build the PCB yourself.

    Tried several approaches to Sequencing and after a very modulate x0x one, that I could arrange in many ways, I committed on a layout. After ordering the PCBs I realized that is is way more inspired by a Cirklon than I thought. It is basically a Cirklon with one additional row of buttons in a smaller form factor.

    Click image for larger version. 

Name:	C578A1A6-BDC0-4718-AC00-7A00236FA6DD.jpg 
Views:	25 
Size:	84.2 KB 
ID:	30187

    Hardware First:
    Teensy 4.1
    53x MX style mechanical keys
    19x Rotary Encoders with momentary switches
    69x WS2812B RGB LEDs
    9x Multiplexers for the Buttons
    2x I2C Port Extensions (MCP23017) for the Encoders.
    A 256x64px OLED Display that I found as replacement part for some HI-FI -gear in a french onlineshop.
    a 3D Printed Case (380x114mm), 3d Printed Keycaps and a CNC routed front panel
    4 DIN MIDI in and out. 4 „devices“ as USB Device and up to 4 connected devices to the Host port.

    Click image for larger version. 

Name:	8A003F74-EF45-4793-A836-17B3D8057F79.jpg 
Views:	11 
Size:	48.2 KB 
ID:	30188

    The sequencer is a 16 Track sequencer (could be more, but currently I don’t need more and those 16 buttons make 16 so easily accessible). 16 Patterns per Track (again, the number of buttons), „unlimited“ number of bars per pattern, with between 1 and 16 steps per bar. Every pattern can be it’s own type (Mono, Poly, Drum and a few Generative experiments) and resolution.
    On mono patterns, there is one note per step with notevalue, velocity, length, offset (to move it on the 192ppqn grid), note repeats, Propability, up to 4 CC values and the possibility to chose a chord and a inversion.
    Drum and Poly patterns are just a list of events on a timeline. as the UI is based on Steps, notes are entered on those steps, it can moved around and be recorded freely. Every note has its individual configuration (like a mono step without the CC).
    CC can be places the same way as notes (and recorded that way), or drawn like Modulation curves in a DAW. i like this approach more, for most of the stuff, because as slow as midi is, too many events can „overflow“ the speed of MIDI.
    On top of that, every Track has 4 Modulation Lanes, that are lfos (and a separate Random area, for making velocity and timing less robotic with just a few clicks.

    If wanted, every can be forced to a scale, that is defined on the project.

    Currently the bars are played one after another in the order they appear in the UI. As every bar has its own length and can be repeated a number of times, possibilities are big here. I tried to make this more flexible, but that became a UI ‚and usability mess for something that sounded cool, but I don’t really need.

    Tracks hold „instruments“ that are basically configurations what output is used. MIDI Port(s), Channel(s), a „base note“ that mono patterns have as default note), if it can receive Bank Select and Program Changes, if it should be forced to scale if the project enables that. instruments have a number of multi-timbral parts. if that’s there, on the Track page a Channel-Field appears where the wanted channel is selected.
    For Drum-Instruments, the midi port and channel, as well as a Note and a name are stored to the ROW, so every individual percussion instrument can be freely configured. Some drum machines have one instrument per note, others have a midi Channel per instrument, and with adding the port to it, I am able to send single Percussions to different Sound sources.

    Last there is a Songmode that is quite similar (and easy) as the Elektron ones.
    An „unlimited“ number of rows are played In order. Every row chooses a pattern (or none) per track, a length, a tempo, a transpose value and a scale, that everything can be forced into.

    Currently MIDI recording is the least loved part. the reason why I spent so many time in trying out every sequencer out there etc. is because I am way better in programming notes than playing them.

    currently I am rewriting most of the firmware, to get rid of parts of the old hardware as well as design decisions that are based on sequencing- and hardware-concepts that I threw away. I would say I am at 90% of where I was before. Still missing is the MIDI FX section, that contained a MIDI delay (playing back notes via midi but with reduces velocity to emulate delay) and an Arpeggiator.

    Everything is can be stored on the SD Card (and loaded from there). it’s writing it’s own binary format, so save time and space. loading is fast enough so with a little work I could make them load and play without the listener noticing, but as I am not performing, I don’t need that.
    With 16Mb psram and most of the memory dynamically allocated, there should be enough to load two projects to switch between them.
    As the MIDI Sequencing itself is running in a IntervalTimer, loading, saving, IO and Display-Rendering is not effecting the MIDI performance at all.
    The MIDI clock is very tight. I wish, all of the hardware would be that tight…

    I will try to make and post better photos and maybe later a video, when I have better light in my room some day.

  2. #2
    Looks impressive and very well thought out! I can't wait to see more pictures and videos of it in action.

    Also secretly wishing for a code share because it sounds like you put a lot of thought in to timing and optimization. In my project I just put everything critical on an intervalTimer and hoped for the best.

  3. #3

    Thatís sounds more rocket science than it is: to summarize my upcoming wall of text: I just send the events first and do the evaluation second.
    On one point I redid how I evaluate the midi events. what I did was, that every pulse I check if the datastructure that holds everything has notes to play for me, if there are events from the past I need to look at (for note repeats, MIDI Delay etc), Generated the MIDI for that and send it out.
    I didnít like that, mostly because that Ąkeeping trackď part got more complicated with every new idea I had.
    I changed that in a way, that every event has a delay-time. Is it 0, the event is sent out, if itís bigger, itís stored and sent later. I already was tracking time, to know when to send note offs, so it was not something special.
    more by exident than by searching I found a bug, that caused everything to fire one pulse late. I did not notice that, and I wouldnít have looked for it. Or would I have known of it existence, if I didnít see it when looking at the code. I did tests with switching that around, and I didnít feel a different. how could I, everything that happened was, that me hitting play took 2.5ms (at 120bpm) to start the playing. I measured how much I suck in hitting play on the beat and found out, that I am more off most of the time, so I just kept it that way (but now implemented in a way, that I could just switch that off instead of relying on a bug. By beeing able to just start everything late, I am also able to do a little bit of latency correction if I had hardware that might be late. And if I would need more than 5ms, I could just Ądropď 2 pulses on play and do the evaluation 2 pulses ahead of time.
    I am quite sure, no one would notice that, luckily itís just me using it

    With this accident I switched from doing as much as I can to be as fast with preparing everything every pulse to: I love to have code as fast nice as I could, but theoretically I just need to make sure, to be done with everything before the next pulse needs to be sent.

    P.S.: As I am able to move around notes on the grid in that 192ppqn-resolution I can easily play around when I notice notes beeing early or late. even with short transients, that I move around, it takes more than 1 pulse to be noticeable. on everything non theoretical (sounds I use) I can start to hear Phase issues later.

  4. #4
    Senior Member
    Join Date
    Jan 2014
    Your "Circlone" is amazing!

    Here is a Cirklon for people who haven't seen, it is a really good sequencer with a long waiting list.

    Click image for larger version. 

Name:	cirklon-hardware-sequencer-sequentix-gmbh-xl.jpg 
Views:	8 
Size:	117.8 KB 
ID:	30203.

  5. #5
    Yeah, I am on the waiting list for a few years now. I joked around Mid 2020, that it might be more accessible and faster to just build your own sequencer, even if you have now clue about electronics (as I did). Didn't know, that I was not that far off.

  6. #6
    Senior Member fdaniels's Avatar
    Join Date
    Oct 2020
    Ostwestfalen, Germany
    Impressive! You really should implement the Cirklons concept of Aux Events, which makes the Cirklon the Cirklon and sets it apart from other sequencers. Sadly its hard to get into it without having a Circlon at hand, the manual gives just a brief glimpse of what you can do with it and sadly doesnt cut it. Yes, i own one (#290).

  7. #7
    In preparation of "someday I will get a Cirklon" I watched everything about Cirklon on YouTube. There is one that explains the AuxRow Concept quite good but I need to dive deeper into it, as soon as I have all my basic features done.
    The way, how you can add CC, Chords and ChordInversions to a Step in the Mono-Pattern is built in a way, that I can add other Parameters to manipulate steps and other parameters.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts