[1]:
from automuse.midi import Player, play, change_instrument, voice, percuss
from automuse.midi import Instrument, Percussion

from time import sleep
import automuse.chord as chord
import automuse.modes as modes

Playing Notes

AutoMuse comes with a parallelised MIDI player, implemented in omusic.midi. The module exports very few components:

  • change_instrument changes the current instrument to one of omusic.midi.Instrument. Default is the Acoustic Grand Piano.

  • .Player creates a player. This player controls a MIDI port and acts as a context manager.

  • .play plays notes with a player.

  • .port returns the default MIDI port.

Playing Notes

Let’s begin with a quick example: play the \(\text{C}_5\). To make the note last, set its duration to 3 seconds.

[2]:
with Player() as player:
    play(player, "C5", duration=2)
closing

Moving on to another example, let’s try the \(\text{I}\rightarrow\text{IV}\rightarrow\text{V}\rightarrow\text{I}\) progression:

[3]:
with Player() as player:
    for _ in range(1):
        play(player, notes=chord.chord("C5", modes.MAJOR, order=0))
        sleep(0.2)
        play(player, notes=chord.chord("C5", modes.MAJOR, order=3))
        sleep(0.2)
        play(player, notes=chord.chord("C5", modes.MAJOR, order=4))
        sleep(0.2)
        play(player, notes=chord.chord("C5", modes.MAJOR, order=0))
        sleep(0.2)
closing

The play function has several parameters that “humanise” the output. These are:

  • arpeggio: Order of notes to play, can be None (no change), ascending, or descending.

  • spacing: Melodic intervals between notes, if a list is given in notes.

  • touch: Variation in note velocity (touch pressure).

The exact values, same as many things in music, are up to your creative choices. As a quick example, let’s hear what different combinations sound like:

[4]:

plan_1 = {"arpeggio": "ascending", "spacing": 0, "touch": 0, "duration": 1} plan_2 = {"arpeggio": "descending", "spacing": (0, 2), "touch": (-30, 30), "duration": 1} with Player() as player: for _ in range(1): play(player, notes=chord.chord("C5", modes.MAJOR, order=0), **plan_1) sleep(0.2) play(player, notes=chord.chord("C5", modes.MAJOR, order=3), **plan_1) sleep(0.2) play(player, notes=chord.chord("C5", modes.MAJOR, order=4), **plan_2) sleep(0.2) play(player, notes=chord.chord("C5", modes.MAJOR, order=0), **plan_2) sleep(0.2)
closing

Simple Voicing

The voice function plays a collection of notes without needing a Player. It can accept two additional arguments:

  • scheme moves notes up and down octaves.

  • play_args contains arguments to pass to the underlying player, which does all the heavy lifting.

[5]:
voice(["C5", "D5", "E5"],
      scheme=[-1, 1, 2],
      play_args={"spacing": (0.1, 0.2)})
closing

Change Instrument

The change_instrument function sends a program_change message; this message the instrument of a channel. Instrument is an Enum that contains all standard instruments.

[6]:
with Player() as player:
    change_instrument(player, 0, Instrument.Banjo)
    play(player, notes=chord.chord("C5", modes.MAJOR))
closing

Percussion

The MIDI standard reserves channel 10 for percussion, where the note specifies a percussion instrument instead of a actual pitch. The percuss function sends notes to this channel. See Percussion for available instruments.

[9]:
with Player() as player:
    percuss(player, notes=Percussion.AcousticBassDrum)
closing