The Official DSI/Sequential Forum

Using Python to make Music (with your Mopho)

cbx

Using Python to make Music (with your Mopho)
« on: June 18, 2017, 06:08:44 PM »
Ok, I want to help people use Python to extend how they use their synthesizers. Python is a very beginner friendly language, and while it is very powerful language and has alot of elegant programming things in it, it supports many styles of programming. You can think of it as modern Basic, but it is far more advanced than Basic compilers.

In order to use Python for Midi you need a midi package. I have chosen to use Mido because it is probably the most advanced MIDI library available for Python. To install mido is very easy. You just do this:

pip install mido
pip install python-rtmidi

If you can't find pip, it is in your Python27/Scripts directory. Or whatever version of Python you are using.

If you want GUIs, I suggest PyQT4. But, they no longer support this on windows. To install this you must download a wheel, and then pip it. You can find the wheel here

[utl]http://www.lfd.uci.edu/~gohlke/pythonlibs/#pyqt4[/url]

Now to install it, you just type pip install <filename.whl>.

There are other wheels in there for SciPy but we won't need that for simple midi programs.

cbx

Re: Using Python to make Music (with your Mopho)
« Reply #1 on: June 18, 2017, 06:11:55 PM »
So now I am going to give you a lesson on how to use Mido and Python to develop a very simple script.

One thing that is a shortcoming on the Mopho is that you can't latch the arp or sequencer. It would be useful if we could latch the sequencer, and then have it play a bass line while we jam over the bass loop on another synthesizer. This is why the SH-101 was very popular, because you could play bass lines on it while you jammed on another keyboard.

So, now I am going to go through developing a little script that will show you how to latch the keyboard while you play so you can do that like they used to do it with an SH-101.

cbx

Re: Using Python to make Music (with your Mopho)
« Reply #2 on: June 18, 2017, 06:13:57 PM »
Oops I forgot and can't edit that post. In order to install wheels you need to install the wheel first. You can google this, but I believe it is just

pip install wheel

And then you can install whatever wheels you want from that page. That is an official page so you don't have to fear it being malware or anything.

cbx

Re: Using Python to make Music (with your Mopho)
« Reply #3 on: June 18, 2017, 06:45:36 PM »
Here is the script that will let you latch the sequencer. It will latch a single note arp. To latch more complex arps requires some extra logic. To use this you must put your keyboard into local control off. It should work fine with a desktop, but I have not tested it with my desktop yet. Now, run the program and hit a key to latch the sequencer. Hit is again, and it unlatches. If you press a different key it should automatically latch the new key and unlatch the old one.


from random import *
import mido
from mido.ports import MultiPort
import array
from time import *
import os,glob
import threading
from patterns import *
import mopho


outp= mido.get_output_names()
inp = mido.get_input_names()

print "Midi inputs"
for n in inp:
   print n
   
print "\nMidi Outputs"
for n in outp:
   print n
   
MOPHO_CHANNEL=0x0

keyboard_input  = mido.open_input(inp[0])
#clk  = mido.open_input(self.clocks.currentText())
midi_output   = mido.open_output(outp[1])

def MSG(msg):
   return mido.Message.from_bytes(msg)
   
def MIDI_NoteOn(note,chan=MOPHO_CHANNEL):
   msg =
  • *3

   msg[0] = 0x90 + chan
   msg[1] = note
   msg[2] = 100
   print msg
   midi_output.send(MSG(msg))

def MIDI_NoteOff(note,chan = MOPHO_CHANNEL):
   msg=[0]*3
   msg[0]  = 0x80 + chan
   msg[1] = note
   msg[2] = 127
   midi_output.send(MSG(msg))
            

def Loop():
   
   last_key = -1
   while 1:
      
      for msg in keyboard_input:
         key = msg.bytes()
         print key
         if(key[0] == 0x90 + MOPHO_CHANNEL):
            if(key[1] == last_key):
               MIDI_NoteOff(key[1])
               continue
            
            if(last_key != -1):
               MIDI_NoteOff(last_key)
            MIDI_NoteOn(key[1])
            last_key = key[1]
         elif(key[0] < 0x80 or key[0] >= 0x8F):
            mido.send(MSG(msg))
         

if __name__ == "__main__":         
   Loop()   


That's the script and I will walk you through it. I am not a python expert, being trained in C and Basic, so there is all kinds of "Pythonic' ways to do it better, and it supports functional programming and many things that are simply beyond my knowledge. But that is why Python is useful because you can still program it in many styles. Since it's just a little script and not something that is commercial it doesn't really matter to me as long as it works.


cbx

Re: Using Python to make Music (with your Mopho)
« Reply #4 on: June 18, 2017, 06:55:30 PM »
Unfortunately I can't edit posts on the forum, and some things went wrong with that. Since I started this script off another one just now, it includes some stuff you don't need.

The first part of the script, if you don't know anything about Python, is to include some libraries.


from random import *
import mido


Hopefully the forum won't change that. That imports Mido, which is all you need for this script to work. I also import random because I just always import random into my scripts because I use it alot.

cbx

Re: Using Python to make Music (with your Mopho)
« Reply #5 on: June 18, 2017, 07:01:51 PM »
The next part is to open your midi port to your Mopho. It will depend on your system, so I will help you to understand how this works.


outp= mido.get_output_names()
inp = mido.get_input_names()

print "Midi inputs"
for n in inp:
   print n
   
print "\nMidi Outputs"
for n in outp:
   print n
   
MOPHO_CHANNEL=0x0


Now that is code I wrote. It prints out all the midi input and outputs on your computer. MOPHO_CHANNEL is hardcoded to your mopho's midi channel. Remember in computers, it begins with 0. So midi channel 1 is 0x0. If you mopho is on channel 4, then it would 3, or 0x3 in hex.

Now to open the port you look at which one is your midi. There are two ways to open the port. One is to use this array I have, and use the index that prints out. The other is to type the full text string of the port name into the mido function to open the port.

For instance if you had your mopho keyboard on USB and the output said "Mopho Keyboard 0" you would do this:


midi_output   = mido.open_output('Mopho Keyboard 0')


You can either just type the name of the string that prints out of the midi port or you can use the index into the arrays I created. Just remember you start counting at 0.

So that is how you open midi ports with Mido. You will want to look at the documentation of Mido while you do this because it can do alot of other things you might find useful.

https://mido.readthedocs.io/en/latest/

Mido is a great step forward for MIDI with Python. In the past I had used other libraries which were not easy to install requring compiling with Cython and strange libraries. Mido also supports reading and writing Midi files.

cbx

Re: Using Python to make Music (with your Mopho)
« Reply #6 on: June 18, 2017, 07:12:44 PM »
Now to work with MIDI with scripting in Python you must know the MIDI specification to know what bytes to send to perform whatever MIDI action you want. This forum doesn't allow me to edit my posts, so I want to keep it short as I no doubt make typo mistakes and poor grammar choices. Maybe later it will let me edit these posts to try to fix this terrible headache I have posted.

Ok, so you will need this guide. We are lucky in this day to have everything we need available on the internet. This site is a good place to get alot of information you will need to do your MIDI programming.

https://www.midi.org/specifications/item/table-1-summary-of-midi-message

cbx

Re: Using Python to make Music (with your Mopho)
« Reply #7 on: June 18, 2017, 07:25:01 PM »
Now the next part is a few functions that do the MIDI for us.


def MSG(msg):
   return mido.Message.from_bytes(msg)
   
def MIDI_NoteOn(note,chan=MOPHO_CHANNEL):
   msg=[0]*3   
   msg[0] = 0x90 + chan
   msg[1] = note
   msg[2] = 100
   midi_output.send(MSG(msg))

def MIDI_NoteOff(note,chan = MOPHO_CHANNEL):
   msg=[0]*3
   msg[0]  = 0x80 + chan
   msg[1] = note
   msg[2] = 127
   midi_output.send(MSG(msg))
            


MSG is just a shorthand function that converts lists of bytes back to an Midi.Message objects, so Mido can send it to the keyboard.

MIDI_NoteOn is a function to turn a MIDI Note on. If you look at the midi messages, you will see that a note on message is 0X90 + channel. So if we are sending to channel one, it is 0x90 in hex. If we send to channel 16, it would be 0x9F in hex. You can only have 16 channels on a midi port, but you could have dozens of USB midi ports connected to a computer, and each one can have up to 16 channeld.

MIDI_NoteOff is used to turn the note off. This is how the latch works, because the note will remain on until it receives a note off message. Until the keyboard is given a note off, it will latch the key and continue playing.

cbx

Re: Using Python to make Music (with your Mopho)
« Reply #8 on: June 18, 2017, 07:28:57 PM »
Now comes the main loop. In this loop the script just processes in coming messages from the keyboard (or controller). If it is a note on, there is some logic to latch keys and turn them on and off. It ignores all note off messages, because we want to latch keys. If it is not a note off, it just passes the message directly to the Mopho.


def Loop():
   
   last_key = -1
   while 1:
      
      for msg in keyboard_input:
         key = msg.bytes()
         print key
         if(key[0] == 0x90 + MOPHO_CHANNEL):
            if(key[1] == last_key):
               MIDI_NoteOff(key[1])
               continue
            
            if(last_key != -1):
               MIDI_NoteOff(last_key)
            MIDI_NoteOn(key[1])
            last_key = key[1]
         elif(key[0] < 0x80 or key[0] >= 0x8F):
            mido.send(MSG(msg))


If you want to handle arps with more than 1 key you will need to build a queue to manage all the keys that are pressed, because you have to turn them all off when you try to latch a new chord. Handling arps is tricky but I leave it as an excercise for you to do.      

cbx

Re: Using Python to make Music (with your Mopho)
« Reply #9 on: June 18, 2017, 07:37:03 PM »
There is a bug in the script, a simple typo. Since I whipped this up quickly so I could make this latch, as I was watching some old timers jam on their SH-101 and Juno-60, I realized we need this latch for the Mopho.


elif(key[0] < 0x80 or key[0] >= 0x8F):
            midi_output.send(MSG(msg))


It sould be midi_output, not mido.

Remember, that python is a white space sensitive language. I use the Wscite editor to write my scripts, and in python mode I think I just use tabs in the editor. You might encounter some problems with whitespace depending on what editor you use. If you have a python-enabled editor it should be able to automatically format whitespace. It is one quirk of the language that once you get used to you won't notice. In the old days it was a problem with different editors. I recommaned Scite or WScite for python programming.

cbx

Re: Using Python to make Music (with your Mopho)
« Reply #10 on: June 18, 2017, 07:41:01 PM »
Now you can do this kind of scripting in many DAWs. You could probably do this in Python with Reaper. I really don't use a DAW much because I experience all sorts of driver problems and lockups. But, if you know Logic you probably could do this in your sleep. Other stuff like maybe PureData, all sorts of programmable DAWs and music packages. So you aren't limited to Python, but Python is free tool with lots of very useful libraries for doing all sorts of things that would be impractical in a DAW.

cbx

Re: Using Python to make Music (with your Mopho)
« Reply #11 on: June 18, 2017, 08:47:27 PM »
Ok I now have created a new Github thing, because I made some kind of mistake with my old one. I am new to Github so I had to insure that there is a disclaimer. These scripts are not supported by DSI, they have nothing to do with them. So don't ask them about them.

Here you can find the latch script. You also find one for latching chords for the arp if you got stuck with how to handle the logic off how to unlatch them when you take your hands off the keyboard.

https://github.com/Gaultus/Mopho-Programmer-Scripts-in-Python

cbx

Re: Using Python to make Music (with your Mopho)
« Reply #12 on: June 18, 2017, 10:06:50 PM »
Now in that repository you can find all kinds of scripts which you might find useful. Or maybe not. But it's there because I care. Now i am building a DIY DAW in Python for my Tangerine Dreams dreams. I want to do all this droney sequences on the mopho and tetra's. For this I created 2 projects and am working on the sequencer and how to program the sequencer loops into a track format.

The Seq16 program is a very simple analog modular style step sequencer. The top knob is the pitch (would be CV on a modular) and the slider let's you repeat notes. Right now it can save sequences to midi files. The PPQ let's you set the length of the note, it is only 24 PPQ at this time to match midi clock pulses but I might adjust this later.

The MophoSeqLab let's you do all those tangerine dreams in the Mopho sequencer. It also has a mini editor built in so you can edit while you drone away on your orange dreams.

Another one of interest is the looper. This let's you play infinitely into the Mopho's sequencer to build all those crazy Klaus Shulze kind of sequences.

Of course you can do stuff other than Tangerine Dreams and Klaus Shulze with them.

chysn

  • *****
  • 704
Re: Using Python to make Music (with your Mopho)
« Reply #13 on: June 19, 2017, 03:24:58 AM »
Code: [Select]
   msg=[0]*3   
   msg[0] = 0x90 + chan
   msg[1] = note
   msg[2] = 100

Consider:

Code: [Select]
msg = [0x90 + chan, note, 100]
DSI: DSM01, DSM03; previously: Mopho Keyboard, Desktop Mopho, Evolver
Hardware: Eurorack, Moog Little Phatty w/ CV Outs, Arturia MicroBrute, KMI QuNexus
Software: OSX, Reaper, MuseScore
Modular Grid: https://www.modulargrid.net/e/racks/view/354385
GitHub: https://github.com/chysn

cbx

Re: Using Python to make Music (with your Mopho)
« Reply #14 on: June 19, 2017, 03:52:38 AM »
I know these are funny, so please don't hurt me. Where else can you find free music generators that can compose in C Bebop Locrian natural 5?


cbx

Re: Using Python to make Music (with your Mopho)
« Reply #15 on: June 19, 2017, 04:35:06 AM »
Oh yes, that is a cleaner way to do it. There is lot's of things you can do in Python. The main reason I use Python is how easy it is to manipulate and work with lists which is what you do in music stuff. But I am old and still sometimes program like I am using Fortran or something.

Just think of them as proof of concepts if you like it it is MIT license you are free to modify them and clean them up however you like. The only thing I mentioned is if you use them commercially to at least credit me for whatever you borrowed. Otherwise I don't care what you do with them I hope they inspire you or just entertain you when you a bored with stuff to do.

I will continue to add more musical frankensteins into that Github but I won't be posting as much. My new Sequencer is the 16x8 which, if you have a Prophet 08 or two tetras, I hope to create the ultimate Goa trance sequencer.

cbx

Re: Using Python to make Music (with your Mopho)
« Reply #16 on: June 21, 2017, 12:03:20 AM »
So my new sequencer is the Seq16x8. Originally, it was meant to be used to sequence a Prophet '08 or mophox4+tetra so it was 16 steps x 8 voices. But you technically have as many voices as you want. It uses Qt4 but the interface is pretty hideous. It is a prototype. When I am done testing all the logic I plan to rewrite the GUI with a piano roll widget I am writing so it will look and be much easier to work with it.

I have one more sequencer to prototype I just call it SeqX16, then I will write some widget and redesign the interface to look like a modern plugin.