Subsystem

Install and connect

By the end of this chapter, Subsequence is installed on your computer, it has written a note to a MIDI file, and you have heard that note on an instrument of your own.

Subsequence makes MIDI and nothing else. The sound comes from whatever it plays: a hardware synth or drum machine, or a software instrument in a DAW.

What you need

Python

Open a terminal and ask Python for its version:

Not checked: the build does not run this.

python3 --version

On Windows, type python --version instead. If it prints a version number, Python is installed. If it says the command was not found, install Python first. Python's own documentation says how for each system: Windows, macOS, and Linux and other Unix systems.

A virtual environment

A virtual environment is a folder that holds one project's Python packages, so what you install for Subsequence never disturbs anything else on your computer. Make a folder for your music, move into it in the terminal, and create one there:

Not checked: the build does not run this.

python3 -m venv .venv
source .venv/bin/activate

On Windows, the two lines are python -m venv .venv and .venv\Scripts\activate. The second line switches the environment on, and it lasts until you close the terminal, so run it again each time you open a new one. While it is on, python and pip mean the environment's own, on every system. Python's tutorial explains virtual environments in full.

Subsequence

With the environment switched on, install Subsequence:

Not checked: the build does not run this.

pip install "subsequence @ git+https://github.com/simonholliday/subsequence@a5e0a09447dc8c49592753412f69abd2606ef380"

That line installs the version of Subsequence this guide is checked against. If your Python is too old for it, pip says so and installs nothing.

A first note, in a file

Create a file called first_note.py in your music folder, in any text editor, and put this in it:

import subsequence

composition = subsequence.Composition(bpm=120)

@composition.pattern(channel=1, beats=4)
def first_note (p):
	p.note(60, beat=0, velocity=100, duration=1)

composition.render(bars=1, filename="first-note.mid")

Then run it from the terminal:

Not checked: the build does not run this.

python first_note.py

It writes first-note.mid beside the script. Line by line, this is what it says:

Under an example, a few lines like these say what it made, bar and beat first:

tempo 120 bpm from   1  1.000
MIDI channel 1
    1  1.000  note C4 (60)  velocity 100  length 1.000

Your file holds the same: at 120 BPM, one note on MIDI channel 1, in bar 1 on beat 1, named C4 and numbered 60, at velocity 100, lasting one beat. Some instruments and DAWs name MIDI note 60 C3, and it is the same note. Open first-note.mid in a DAW to see it.

Hearing it

play sends the notes to an instrument as they happen, in time. Change the last line of first_note.py to call it instead of render:

Not checked: the build does not run this.

composition.play()

Run the script again. Subsequence looks for a MIDI port to play through. If there is one, it uses it. If there are several, it lists them and asks which you mean. If there are none, it says it found no MIDI output devices. Then it plays middle C at the start of every bar until you press Ctrl+C.

Set your instrument to listen on MIDI channel 1, or on every MIDI channel.

A hardware instrument

A synth or drum machine with a USB port appears as a MIDI port of its own once it is connected and switched on. One with only round five-pin MIDI sockets connects through a USB MIDI interface, and the interface is the port: plug its MIDI out into the instrument's MIDI in.

A software instrument

A software instrument or a DAW is another program on the same computer, so the notes travel through a virtual MIDI port that both programs can see. Subsequence plays into it, and the DAW takes its MIDI from it.

Then, in the DAW, give a track that virtual port as its MIDI input, put an instrument on the track, and arm or monitor it so it plays what arrives.

Naming the port

Rather than choosing from a list every time, tell Subsequence which port to use when you make the composition:

Not checked: the build does not run this.

composition = subsequence.Composition(bpm=120, output_device="*IAC*")

The name is matched as a pattern, so you do not have to type all of it. * stands for any run of characters, matching ignores capital letters, and a name with no * in it matches any port whose name contains it. Subsequence's README says more on naming your MIDI device, including how to keep a name working on Linux, where part of it changes between restarts.

On Linux, if opening the port fails with Permission denied, add yourself to the audio group, then log out and back in:

Not checked: the build does not run this.

sudo usermod -a -G audio $USER