HOW-TO: DIY Hybrid Sequencer / MIDI USB Hub (aka PiSeq) using Raspberry Pi, and external MIDI controllers. (PART 1)

in music •  7 years ago  (edited)

HOW-TO: DIY Hybrid Sequencer / MIDI USB Hub (aka PiSeq) using Raspberry Pi, and external MIDI controllers. (PART 1)

In part 1 of the series of articles, you'll read how to build your own DIY MIDI sequencer, and MIDI USB hub. Actually, it's more of a system integration task. The actual operating instructions will be available in Part 2. We have to start somewhere, right?

Ingredients

Raspberry Pi, external MIDI controller, MIDI USB to DIN 5P adapters. Linux knowledge level: medium. Feel free to comment in case you find yourself in trouble due to wrong informations in this post. I'll answer as soon as I can, and I'll modify the troublesome sections.

What's all the buzz about? With successful completion of the steps described in this post, you get:

  • MIDI sequencer
  • MIDI USB hub
  • Advanced MIDI manipulation device
  • Endless feeling of joy!

Check images bellow how the end result looks like.

MIDI Controller and LCD Touch Screen


Sequencer being hosted on Raspberry Pi 3

And the last, but not least PROOF OF CONCEPT VIDEO.

Hardware components

  • Raspberry Pi or any other Linux flavour you prefer.
  • LCD Screen 1024x600 resolution is an absolute minimum in order to have pleasant visual overview.
  • External MIDI controller Any MIDI controller with pads will do the job. I use this one because it fits perfect within sequencer's 8x4 matrix of MIDI patterns. Akai APC Mini is other device I've been eyeing.

Have in mind that in case you want to use a regular Linux PC instead of Raspberry Pi based, everything you read in this post applies to that setup.

OS (Raspbian) Installation

You may refer to my previous post where I have explained how to install Raspbian OS, and overcome the limitations regarding the maximum number of USB audio devices that can be attached.

Software components

seq24
In order to have a working sequencer, you need some software at least. That is because even the "hardware" sequencers have an OS, and an application running on top of it. My choice is seq24 which is highly versatile, and feature rich MIDI sequencer. It can send/receive all possible MIDI events. You can draw notes, you can play and record them via external MIDI keyboard. You can record other MIDI events via external MIDI controller, or via mouse. The choice is yours. It has pattern mode, and song mode.


seq24

Seq24 is no longer being developed, so you may take sequencer64 into consideration. The latter practically functions the same way. Everything that is written here about seq24 applies to sequencer64. I have installed and used sequencer64, but I thought that seq24 installation is straightforward which is good for a typical music artist with a little Linux knowledge. Not that sequencer64 is hard to install, but still.

qjackctl
You may need this piece of software in order to have nice visual overview of all MIDI connections. Patchage also serves well. I just find qjackctl faster.

qjackctl

mididings
This awesome piece of software is the heart of the system (besides the necessary seq24). The author calls it MIDI router and processor. I call it Swiss Army Knife of MIDI processing. It's that good. It can process and send MIDI events in serial, and/or parallel manner to one or multiple outputs. It supports multiple inputs too. You can safely start more than one instance for the sake of having cleaner Python like code, and better overview in qjackctl. You better read the mididings documentation if you wish to get more of it.

One of the most pleasing tasks I do with mididings is, push a button on an external MIDI controller (NoteOn), process the event so that mididings sends multiple CC values in parallel to a particular MIDI channel. So what's the big deal here? I have just initiated a patch on a no patch memory synth (Volca Bass/Keys, Reface CS, ...).

Software installation

This is an easy one. Just type the following command in the terminal window, and answer yes by typing Y when asked:
$ sudo apt-get install seq24 mididings qjackctl

Configuration tasks

seq24 configuration
In order to use Behringer CMD LC-1 external MIDI controller for triggering MIDI sequences on a push of a button, you need to change seq24's default configuration file according to the MIDI map on the picture bellow.

Behringer CMD LC-1 MIDI Map

This table of notes and the corresponding MIDI numbering is very helpful.

MIDI Notes Numbering

If we pair previous two pictures, we come to seq24 configuration that has to be applied. You have to modify .seq24rc file which resides in your $HOME directory.
[midi-control]
74
0 [1 0 144 35 127 127] [0 0 0 0 0 0] [0 0 0 0 0 0]
1 [1 0 144 34 127 127] [0 0 0 0 0 0] [0 0 0 0 0 0]
2 [1 0 144 33 127 127] [0 0 0 0 0 0] [0 0 0 0 0 0]
3 [1 0 144 32 127 127] [0 0 0 0 0 0] [0 0 0 0 0 0]
4 [1 0 144 39 127 127] [0 0 0 0 0 0] [0 0 0 0 0 0]
5 [1 0 144 38 127 127] [0 0 0 0 0 0] [0 0 0 0 0 0]
6 [1 0 144 37 127 127] [0 0 0 0 0 0] [0 0 0 0 0 0]
7 [1 0 144 36 127 127] [0 0 0 0 0 0] [0 0 0 0 0 0]
8 [1 0 144 43 127 127] [0 0 0 0 0 0] [0 0 0 0 0 0]
9 [1 0 144 42 127 127] [0 0 0 0 0 0] [0 0 0 0 0 0]
10 [1 0 144 41 127 127] [0 0 0 0 0 0] [0 0 0 0 0 0]
11 [1 0 144 40 127 127] [0 0 0 0 0 0] [0 0 0 0 0 0]
12 [1 0 144 47 127 127] [0 0 0 0 0 0] [0 0 0 0 0 0]
13 [1 0 144 46 127 127] [0 0 0 0 0 0] [0 0 0 0 0 0]
14 [1 0 144 45 127 127] [0 0 0 0 0 0] [0 0 0 0 0 0]
15 [1 0 144 44 127 127] [0 0 0 0 0 0] [0 0 0 0 0 0]
16 [1 0 144 51 127 127] [0 0 0 0 0 0] [0 0 0 0 0 0]
17 [1 0 144 50 127 127] [0 0 0 0 0 0] [0 0 0 0 0 0]
18 [1 0 144 49 127 127] [0 0 0 0 0 0] [0 0 0 0 0 0]
19 [1 0 144 48 127 127] [0 0 0 0 0 0] [0 0 0 0 0 0]
20 [1 0 144 55 127 127] [0 0 0 0 0 0] [0 0 0 0 0 0]
21 [1 0 144 54 127 127] [0 0 0 0 0 0] [0 0 0 0 0 0]
22 [1 0 144 53 127 127] [0 0 0 0 0 0] [0 0 0 0 0 0]
23 [1 0 144 52 127 127] [0 0 0 0 0 0] [0 0 0 0 0 0]
24 [1 0 144 59 127 127] [0 0 0 0 0 0] [0 0 0 0 0 0]
25 [1 0 144 58 127 127] [0 0 0 0 0 0] [0 0 0 0 0 0]
26 [1 0 144 57 127 127] [0 0 0 0 0 0] [0 0 0 0 0 0]
27 [1 0 144 56 127 127] [0 0 0 0 0 0] [0 0 0 0 0 0]
28 [1 0 144 63 127 127] [0 0 0 0 0 0] [0 0 0 0 0 0]
29 [1 0 144 62 127 127] [0 0 0 0 0 0] [0 0 0 0 0 0]
30 [1 0 144 61 127 127] [0 0 0 0 0 0] [0 0 0 0 0 0]
31 [1 0 144 60 127 127] [0 0 0 0 0 0] [0 0 0 0 0 0]
Modified section of .seq24rc file

Refer to seq24 manual for more details. Now, you can trigger individual MIDI sequences by both Behringer CMD LC-1, and the PC keyboard. Note that if you use PC keyboard, the corresponding button on the external MIDI controller will not be lit. In order to lit controller's button we need the help of mididings.

mididings script
We have to write that mididings script first. And make the first choice. Do we need it? As I already said, mididings is the brain of the setup. In this case, it's the necessary component to lit and dim buttons on Behringer CMD LC-1 external MIDI controller. There are great many things we'll do in the following parts of this how-to series, so we'll need mididings for sure. Other option is to control seq24 via PC keyboard. In this case, forget about mididings and omit the line in the "scroll down for details" live.sh script containing mididings command(s).

Go to the end of this article to get the contents of /home/pi/mididings/mididings_lc1_seq24.py. It's just too big to place it here.

DJ like MIDI controllers are designed to work with PC based DJ software. We need man in the middle to do the job of MIDI mappings towards external MIDI controllers, our beloved synths, and other MIDI controllable stuff we can not live without. And mididings is up to it. The problem is that, if we change the MIDI controller, we must change the accompanying mididings script. The one found in the appendix applies to Behringer CMD LC-1 MIDI device. This controller must be plugged in the free USB port of the Raspberry Pi before starting live.sh script. Since you can safely start more than one mididings instance at once, I tend to write one mididings script per MIDI controller. It's up to you. You may do a script per function, or set of functions.

The mididings script will do the following tasks:

  • Dim the matrix of 4x8 buttons since they are all lit when CMD LC-1 is powered on.
  • Lit controller buttons when pushed, and dim them when pushed again. This corresponds to seq24's MIDI sequence (one of the 32 per set).
  • Change MIDI set. The total number of sets is 32 ranging from 0 to 31.

At this point, the buttons that can make an action are:

  • Notes G#1 to D#4 for triggering MIDI sequences in a set. (see CMD LC-1 picture)
  • Note E4 for loading the previous set. If the current set is 0, pushing this button will load set 31. (see CMD LC-1 picture)
  • Note G#4 for loading the next set. If the current set is 31, pushing this button will load set 0. (see CMD LC-1 picture)
  • Notes C5 to D#5 to dim all automaticaly lit buttons per row when CMD LC-1 is powered on. (see CMD LC-1 picture)

I use CMD LC-1's endless rotary encoders (knobs) for sending MIDI CC=7 (volume) events to Roland JV-1080 MIDI channels 1-8. If you don't need this, there's an option to control seq24's bpm value from CMD-LC 1. I do it from other MIDI controller which will be presented in part 2 of this how-to series of articles.

Starting the applications in an elegant way

First make sure that Raspbian starts GUI upon boot. In the terminal application of your choice, make the necessary directories and files within your $HOME directory:

$ mkdir mididings
$ touch mididings/mididings_lc1_seq24.py
$ mkdir bin
$ touch bin/live.sh
$ chmod 755 bin/live.sh

Edit /home/pi/mididings/mididings_lc1_seq24.py with the content found in the APPENDIX. Use your favourite editor to edit /home/pi/bin/live.sh script.

#!/bin/bash
 
mididings -f /home/pi/mididings/mididings_lc1_seq24.py & #comment this line if not needed
qjackctl &
seq24 &

/home/pi/bin/live.sh

To fire up the applications simply type:
$ live.sh

Automating the MIDI connections

The humans are too lazy to do the same repetitive actions all the time. Making MIDI connections is one of those boring tasks. At this point there are not so many MIDI devices, but wait until we employ various others like 2 more DJ like Behringer controllers, Arturia BeatStep, MIDI keyboards, pads, and so on. It's better to have a basic script for making MIDI connections and gradually expand it. First, create the necessary files:

$ mkdir bin/live-midi-connect.sh
$ chmod 755 bin/live-midi-connect.sh

And the live-midi-connect.sh script itself. Feel free to use the editor of your choice.

LC1OUT=`aconnect -i | grep "CMD LC-1" | grep client | gawk '{print $2}'`
MIDIDINGSLC1IN=`aconnect -o | grep "mididings-lc1-seq24" | grep client | gawk '{print $2}'`
aconnect ${LC1OUT}0 ${MIDIDINGSLC1IN}0

MIDIDINGSLC1OUT=`aconnect -i | grep "mididings-lc1-seq24" | grep client | gawk '{print $2}'`
LC1IN=`aconnect -o | grep "CMD LC-1" | grep client | gawk '{print $2}'`
aconnect ${MIDIDINGSLC1OUT}2 ${LC1IN}0

live-midi-connect.sh

Finally, make the MIDI connections by typing:
live-midi-connect.sh
For extra satisfaction, watch MIDI Connections window which can be fired up from qjackctl application. Beauty, right?

Let seq24 listen to what mididings has to say

Seq24 must be configured to receive MIDI messages from mididings. Using qjackctl you can see which MIDI port number is assigned to mididings. Go to Connections, and under ALSA tab you'll see the lists of Readable and Writable Clients. Most probably mididings is assigned port 129. Go to seq24, select File > Options.... Under MIDI Input tab, select 129:2 out port. Now, seq24 will react to MIDI messages sent by mididings. In our case, for triggering MIDI sequences.

What about the synths?

We have to send some great melodies to our beloved synths. You can use USB 2 MIDI adapter. The same as the ones described in my previous post about building MIDI Thru box. It will appear as CH345 within qjackctl MIDI devices, and will be available in seq24 as CH345 device. Just select it when editing MIDI sequence, pick a channel, and draw some notes.

The feeling of joy!

That should be all regarding the initial setup of your brand new DIY MIDI sequencer. And yes, it's already a MIDI hub. Using qjackctl you can make MIDI connections between the devices manually. See what you need, end expand live-midi-connect.sh script. Here you'll find mididings ports available since it is a software defined MIDI device. Stay tuned for more advanced versions of the scripts presented here, and some new ones in part 2 of this series.

APPENDIX

The contents of /home/pi/mididings/mididings_lc1_seq24.py script
IMPORTANT NOTE: Behringer CMD LC-1 transmits, and receives MIDI messages on MIDI channel 14. It's not its default MIDI channel. I've set it using utility provided by Behringer.

from mididings import *
from mididings.event import *
from mididings.extra import Panic
 
config(
    #backend='jack-rt',
    client_name = 'mididings-lc1-seq24',
    in_ports = 1,
    out_ports = 3, # 1 seq24, 2 lc-1 ctrl, 3 jv-1080
    #data_offset = 0,
)
 
class N32:
    def __init__(self, initial):
        self.velocity = initial
    def __call__(self, note):
        if self.velocity == 2:
            self.velocity = 127
        elif self.velocity == 127:
            self.velocity = 2
        note.velocity = self.velocity
        return note
 
class N33:
    def __init__(self, initial):
        self.velocity = initial
    def __call__(self, note):
        if self.velocity == 1:
            self.velocity = 127
        elif self.velocity == 127:
            self.velocity = 1
        note.velocity = self.velocity
        return note
 
class N34:
    def __init__(self, initial):
        self.velocity = initial
    def __call__(self, note):
        if self.velocity == 1:
            self.velocity = 127
        elif self.velocity == 127:
            self.velocity = 1
        note.velocity = self.velocity
        return note
 
class N35:
    def __init__(self, initial):
        self.velocity = initial
    def __call__(self, note):
        if self.velocity == 1:
            self.velocity = 127
        elif self.velocity == 127:
            self.velocity = 1
        note.velocity = self.velocity
        return note
 
class N36:
    def __init__(self, initial):
        self.velocity = initial
    def __call__(self, note):
        if self.velocity == 4:
            self.velocity = 127
        elif self.velocity == 127:
            self.velocity = 4
        note.velocity = self.velocity
        return note
 
class N37:
    def __init__(self, initial):
        self.velocity = initial
    def __call__(self, note):
        if self.velocity == 3:
            self.velocity = 127
        elif self.velocity == 127:
            self.velocity = 3
        note.velocity = self.velocity
        return note
 
class N38:
    def __init__(self, initial):
        self.velocity = initial
    def __call__(self, note):
        if self.velocity == 3:
            self.velocity = 127
        elif self.velocity == 127:
            self.velocity = 3
        note.velocity = self.velocity
        return note
 
class N39:
    def __init__(self, initial):
        self.velocity = initial
    def __call__(self, note):
        if self.velocity == 3:
            self.velocity = 127
        elif self.velocity == 127:
            self.velocity = 3
        note.velocity = self.velocity
        return note
 
class N40:
    def __init__(self, initial):
        self.velocity = initial
    def __call__(self, note):
        if self.velocity == 6:
            self.velocity = 127
        elif self.velocity == 127:
            self.velocity = 6
        note.velocity = self.velocity
        return note
 
class N41:
    def __init__(self, initial):
        self.velocity = initial
    def __call__(self, note):
        if self.velocity == 5:
            self.velocity = 127
        elif self.velocity == 127:
            self.velocity = 5
        note.velocity = self.velocity
        return note
 
class N42:
    def __init__(self, initial):
        self.velocity = initial
    def __call__(self, note):
        if self.velocity == 5:
            self.velocity = 127
        elif self.velocity == 127:
            self.velocity = 5
        note.velocity = self.velocity
        return note
 
class N43:
    def __init__(self, initial):
        self.velocity = initial
    def __call__(self, note):
        if self.velocity == 5:
            self.velocity = 127
        elif self.velocity == 127:
            self.velocity = 5
        note.velocity = self.velocity
        return note
 
class N44:
    def __init__(self, initial):
        self.velocity = initial
    def __call__(self, note):
        if self.velocity == 8:
            self.velocity = 127
        elif self.velocity == 127:
            self.velocity = 8
        note.velocity = self.velocity
        return note
 
class N45:
    def __init__(self, initial):
        self.velocity = initial
    def __call__(self, note):
        if self.velocity == 7:
            self.velocity = 127
        elif self.velocity == 127:
            self.velocity = 7
        note.velocity = self.velocity
        return note
 
class N46:
    def __init__(self, initial):
        self.velocity = initial
    def __call__(self, note):
        if self.velocity == 7:
            self.velocity = 127
        elif self.velocity == 127:
            self.velocity = 7
        note.velocity = self.velocity
        return note
 
class N47:
    def __init__(self, initial):
        self.velocity = initial
    def __call__(self, note):
        if self.velocity == 7:
            self.velocity = 127
        elif self.velocity == 127:
            self.velocity = 7
        note.velocity = self.velocity
        return note
 
class N48:
    def __init__(self, initial):
        self.velocity = initial
    def __call__(self, note):
        if self.velocity == 2:
            self.velocity = 127
        elif self.velocity == 127:
            self.velocity = 2
        note.velocity = self.velocity
        return note
 
class N49:
    def __init__(self, initial):
        self.velocity = initial
    def __call__(self, note):
        if self.velocity == 1:
            self.velocity = 127
        elif self.velocity == 127:
            self.velocity = 1
        note.velocity = self.velocity
        return note
 
class N50:
    def __init__(self, initial):
        self.velocity = initial
    def __call__(self, note):
        if self.velocity == 1:
            self.velocity = 127
        elif self.velocity == 127:
            self.velocity = 1
        note.velocity = self.velocity
        return note
 
class N51:
    def __init__(self, initial):
        self.velocity = initial
    def __call__(self, note):
        if self.velocity == 1:
            self.velocity = 127
        elif self.velocity == 127:
            self.velocity = 1
        note.velocity = self.velocity
        return note
 
class N52:
    def __init__(self, initial):
        self.velocity = initial
    def __call__(self, note):
        if self.velocity == 4:
            self.velocity = 127
        elif self.velocity == 127:
            self.velocity = 4
        note.velocity = self.velocity
        return note
 
class N53:
    def __init__(self, initial):
        self.velocity = initial
    def __call__(self, note):
        if self.velocity == 3:
            self.velocity = 127
        elif self.velocity == 127:
            self.velocity = 3
        note.velocity = self.velocity
        return note
 
class N54:
    def __init__(self, initial):
        self.velocity = initial
    def __call__(self, note):
        if self.velocity == 3:
            self.velocity = 127
        elif self.velocity == 127:
            self.velocity = 3
        note.velocity = self.velocity
        return note
 
class N55:
    def __init__(self, initial):
        self.velocity = initial
    def __call__(self, note):
        if self.velocity == 3:
            self.velocity = 127
        elif self.velocity == 127:
            self.velocity = 3
        note.velocity = self.velocity
        return note
 
class N56:
    def __init__(self, initial):
        self.velocity = initial
    def __call__(self, note):
        if self.velocity == 6:
            self.velocity = 127
        elif self.velocity == 127:
            self.velocity = 6
        note.velocity = self.velocity
        return note
 
class N57:
    def __init__(self, initial):
        self.velocity = initial
    def __call__(self, note):
        if self.velocity == 5:
            self.velocity = 127
        elif self.velocity == 127:
            self.velocity = 5
        note.velocity = self.velocity
        return note
 
class N58:
    def __init__(self, initial):
        self.velocity = initial
    def __call__(self, note):
        if self.velocity == 5:
            self.velocity = 127
        elif self.velocity == 127:
            self.velocity = 5
        note.velocity = self.velocity
        return note
 
class N59:
    def __init__(self, initial):
        self.velocity = initial
    def __call__(self, note):
        if self.velocity == 5:
            self.velocity = 127
        elif self.velocity == 127:
            self.velocity = 5
        note.velocity = self.velocity
        return note
 
class N60:
    def __init__(self, initial):
        self.velocity = initial
    def __call__(self, note):
        if self.velocity == 8:
            self.velocity = 127
        elif self.velocity == 127:
            self.velocity = 8
        note.velocity = self.velocity
        return note
 
class N61:
    def __init__(self, initial):
        self.velocity = initial
    def __call__(self, note):
        if self.velocity == 7:
            self.velocity = 127
        elif self.velocity == 127:
            self.velocity = 7
        note.velocity = self.velocity
        return note
 
class N62:
    def __init__(self, initial):
        self.velocity = initial
    def __call__(self, note):
        if self.velocity == 7:
            self.velocity = 127
        elif self.velocity == 127:
            self.velocity = 7
        note.velocity = self.velocity
        return note
 
class N63:
    def __init__(self, initial):
        self.velocity = initial
    def __call__(self, note):
        if self.velocity == 7:
            self.velocity = 127
        elif self.velocity == 127:
            self.velocity = 7
        note.velocity = self.velocity
        return note
 
         
run(
    [
        # CMD LC-1 mappings
        ChannelFilter(14) >> [
            Filter(NOTEON) >> [
                # CLIP BUTTONS
                KeyFilter(32) >> Process(N32(127)) >> NoteOn(EVENT_NOTE, EVENT_VELOCITY) >> Channel(14) >> [Port(1), Port(2)],
                KeyFilter(33) >> Process(N33(127)) >> NoteOn(EVENT_NOTE, EVENT_VELOCITY) >> Channel(14) >> [Port(1), Port(2)],
                KeyFilter(34) >> Process(N34(127)) >> NoteOn(EVENT_NOTE, EVENT_VELOCITY) >> Channel(14) >> [Port(1), Port(2)],
                KeyFilter(35) >> Process(N35(127)) >> NoteOn(EVENT_NOTE, EVENT_VELOCITY) >> Channel(14) >> [Port(1), Port(2)],
                KeyFilter(36) >> Process(N36(127)) >> NoteOn(EVENT_NOTE, EVENT_VELOCITY) >> Channel(14) >> [Port(1), Port(2)],
                KeyFilter(37) >> Process(N37(127)) >> NoteOn(EVENT_NOTE, EVENT_VELOCITY) >> Channel(14) >> [Port(1), Port(2)],
                KeyFilter(38) >> Process(N38(127)) >> NoteOn(EVENT_NOTE, EVENT_VELOCITY) >> Channel(14) >> [Port(1), Port(2)],
                KeyFilter(39) >> Process(N39(127)) >> NoteOn(EVENT_NOTE, EVENT_VELOCITY) >> Channel(14) >> [Port(1), Port(2)],
                KeyFilter(40) >> Process(N40(127)) >> NoteOn(EVENT_NOTE, EVENT_VELOCITY) >> Channel(14) >> [Port(1), Port(2)],
                KeyFilter(41) >> Process(N41(127)) >> NoteOn(EVENT_NOTE, EVENT_VELOCITY) >> Channel(14) >> [Port(1), Port(2)],
                KeyFilter(42) >> Process(N42(127)) >> NoteOn(EVENT_NOTE, EVENT_VELOCITY) >> Channel(14) >> [Port(1), Port(2)],
                KeyFilter(43) >> Process(N43(127)) >> NoteOn(EVENT_NOTE, EVENT_VELOCITY) >> Channel(14) >> [Port(1), Port(2)],
                KeyFilter(44) >> Process(N44(127)) >> NoteOn(EVENT_NOTE, EVENT_VELOCITY) >> Channel(14) >> [Port(1), Port(2)],
                KeyFilter(45) >> Process(N45(127)) >> NoteOn(EVENT_NOTE, EVENT_VELOCITY) >> Channel(14) >> [Port(1), Port(2)],
                KeyFilter(46) >> Process(N46(127)) >> NoteOn(EVENT_NOTE, EVENT_VELOCITY) >> Channel(14) >> [Port(1), Port(2)],
                KeyFilter(47) >> Process(N47(127)) >> NoteOn(EVENT_NOTE, EVENT_VELOCITY) >> Channel(14) >> [Port(1), Port(2)],
                KeyFilter(48) >> Process(N48(127)) >> NoteOn(EVENT_NOTE, EVENT_VELOCITY) >> Channel(14) >> [Port(1), Port(2)],
                KeyFilter(49) >> Process(N49(127)) >> NoteOn(EVENT_NOTE, EVENT_VELOCITY) >> Channel(14) >> [Port(1), Port(2)],
                KeyFilter(50) >> Process(N50(127)) >> NoteOn(EVENT_NOTE, EVENT_VELOCITY) >> Channel(14) >> [Port(1), Port(2)],
                KeyFilter(51) >> Process(N51(127)) >> NoteOn(EVENT_NOTE, EVENT_VELOCITY) >> Channel(14) >> [Port(1), Port(2)],
                KeyFilter(52) >> Process(N52(127)) >> NoteOn(EVENT_NOTE, EVENT_VELOCITY) >> Channel(14) >> [Port(1), Port(2)],
                KeyFilter(53) >> Process(N53(127)) >> NoteOn(EVENT_NOTE, EVENT_VELOCITY) >> Channel(14) >> [Port(1), Port(2)],
                KeyFilter(54) >> Process(N54(127)) >> NoteOn(EVENT_NOTE, EVENT_VELOCITY) >> Channel(14) >> [Port(1), Port(2)],
                KeyFilter(55) >> Process(N55(127)) >> NoteOn(EVENT_NOTE, EVENT_VELOCITY) >> Channel(14) >> [Port(1), Port(2)],
                KeyFilter(56) >> Process(N56(127)) >> NoteOn(EVENT_NOTE, EVENT_VELOCITY) >> Channel(14) >> [Port(1), Port(2)],
                KeyFilter(57) >> Process(N57(127)) >> NoteOn(EVENT_NOTE, EVENT_VELOCITY) >> Channel(14) >> [Port(1), Port(2)],
                KeyFilter(58) >> Process(N58(127)) >> NoteOn(EVENT_NOTE, EVENT_VELOCITY) >> Channel(14) >> [Port(1), Port(2)],
                KeyFilter(59) >> Process(N59(127)) >> NoteOn(EVENT_NOTE, EVENT_VELOCITY) >> Channel(14) >> [Port(1), Port(2)],
                KeyFilter(60) >> Process(N60(127)) >> NoteOn(EVENT_NOTE, EVENT_VELOCITY) >> Channel(14) >> [Port(1), Port(2)],
                KeyFilter(61) >> Process(N61(127)) >> NoteOn(EVENT_NOTE, EVENT_VELOCITY) >> Channel(14) >> [Port(1), Port(2)],
                KeyFilter(62) >> Process(N62(127)) >> NoteOn(EVENT_NOTE, EVENT_VELOCITY) >> Channel(14) >> [Port(1), Port(2)],
                KeyFilter(63) >> Process(N63(127)) >> NoteOn(EVENT_NOTE, EVENT_VELOCITY) >> Channel(14) >> [Port(1), Port(2)],
                # SCENE SWITCH LEFT (DOWN)
                KeyFilter(64) >> [Ctrl(64, 127) >> Channel(14) >> Port(1), NoteOn(64, 2) >> Channel(14) >> Port(2), NoteOn(68, 1) >> Channel(14) >> Port(2)],
                # SCENE SWITCH RIGH (UP)
                KeyFilter(68) >> [Ctrl(68, 127) >> Channel(14) >> Port(1), NoteOn(68, 2) >> Channel(14) >> Port(2), NoteOn(64, 1) >> Channel(14) >> Port(2)],
                # RESET CLIP ROW 1
                KeyFilter(75) >> [
                    Key(35) >> Velocity(0) >> Channel(14) >> Port(2),
                    Key(39) >> Velocity(0) >> Channel(14) >> Port(2),
                    Key(43) >> Velocity(0) >> Channel(14) >> Port(2),
                    Key(47) >> Velocity(0) >> Channel(14) >> Port(2),
                    Key(51) >> Velocity(0) >> Channel(14) >> Port(2),
                    Key(55) >> Velocity(0) >> Channel(14) >> Port(2),
                    Key(59) >> Velocity(0) >> Channel(14) >> Port(2),
                    Key(63) >> Velocity(0) >> Channel(14) >> Port(2),
                ],
                # RESET CLIP ROW 2
                KeyFilter(74) >> [
                    Key(34) >> Velocity(0) >> Channel(14) >> Port(2),
                    Key(38) >> Velocity(0) >> Channel(14) >> Port(2),
                    Key(42) >> Velocity(0) >> Channel(14) >> Port(2),
                    Key(46) >> Velocity(0) >> Channel(14) >> Port(2),
                    Key(50) >> Velocity(0) >> Channel(14) >> Port(2),
                    Key(54) >> Velocity(0) >> Channel(14) >> Port(2),
                    Key(58) >> Velocity(0) >> Channel(14) >> Port(2),
                    Key(62) >> Velocity(0) >> Channel(14) >> Port(2),
                ],
                # RESET CLIP ROW 3
                KeyFilter(73) >> [
                    Key(33) >> Velocity(0) >> Channel(14) >> Port(2),
                    Key(37) >> Velocity(0) >> Channel(14) >> Port(2),
                    Key(41) >> Velocity(0) >> Channel(14) >> Port(2),
                    Key(45) >> Velocity(0) >> Channel(14) >> Port(2),
                    Key(49) >> Velocity(0) >> Channel(14) >> Port(2),
                    Key(53) >> Velocity(0) >> Channel(14) >> Port(2),
                    Key(57) >> Velocity(0) >> Channel(14) >> Port(2),
                    Key(61) >> Velocity(0) >> Channel(14) >> Port(2),
                ],
                # RESET CLIP ROW 4
                KeyFilter(72) >> [
                    Key(32) >> Velocity(0) >> Channel(14) >> Port(2),
                    Key(36) >> Velocity(0) >> Channel(14) >> Port(2),
                    Key(40) >> Velocity(0) >> Channel(14) >> Port(2),
                    Key(44) >> Velocity(0) >> Channel(14) >> Port(2),
                    Key(48) >> Velocity(0) >> Channel(14) >> Port(2),
                    Key(52) >> Velocity(0) >> Channel(14) >> Port(2),
                    Key(56) >> Velocity(0) >> Channel(14) >> Port(2),
                    Key(60) >> Velocity(0) >> Channel(14) >> Port(2),
                ],
            ],
            ~Filter(NOTEOFF),
        ]
    ]
)

/home/pi/mididings/mididings_lc1_seq24.py

Authors get paid when people like you upvote their post.
If you enjoyed what you read here, create your account today and start earning FREE STEEM!
Sort Order:  

Oh man. All I can say is we are going to be friends, mate. I’m about to launch a bunch of content controlling my eurorack rig from a push 2, but you are taking things an order of magnitude farther by rolling your own and using the pi. Hats off my man.

At your service. Everything I can help.

The @OriginalWorks bot has determined this post by @sferamusic to be original material and upvoted it!

ezgif.com-resize.gif

To call @OriginalWorks, simply reply to any post with @originalworks or !originalworks in your message!

Nice. Bookmarked. I am right now building a Midicontroller on Arduino, Might add a RasPi tothat Setup...

Fantastic post about seq24. I MUST implement that into my setup. Thanks again!

Thanks man. Cheers.