Intro

python-lpd8 is a pythonic abstraction for the Akai LPD8 midi controller. It allows you to attach callback functions to each pad and knob, making integration into your application extremely easy.

This is a minimal working example:

from lpd8mido import LPD8DeviceMido

from time import sleep

def exampleCallback(programNum: int, padNum: int, knobNum: int, value: int, noteon: int, noteoff: int, cc: int, pc: int):
    print("CB program: %s pad: %s knob: %s value: %s" % (programNum, padNum, knobNum, value))

lpd8 = LPD8DeviceMido()
for i in range(8):
    lpd8.addPadCB(0, i, exampleCallback)
    lpd8.addKnobCB(0, i, exampleCallback)

while(True):
    lpd8.tick()
    sleep(0.01)

While you’ve activated the first program and are in PAD-mode you should get messages that looks like this every time you hit a pad or turn a knob:

CB program: 0 pad: 0 knob: None value: 19
CB program: 0 pad: 1 knob: None value: 4
CB program: 0 pad: 2 knob: None value: 20
CB program: 0 pad: 3 knob: None value: 7
CB program: 0 pad: None knob: 5 value: 37
CB program: 0 pad: None knob: 5 value: 38
CB program: 0 pad: None knob: 5 value: 39
CB program: 0 pad: None knob: 5 value: 40

Quickstart

Python-lpd8 works by handling all the midi communication with the lpd8 device for you. All you have to do is decide which callback you want attached to which pad or knob. This quickstart will show you how to use python-lpd8 with mido, a MIDI library. The mido interface is currently the only one that is currently available.

Opening device

First we need to create a device instance:

from lpd8mido import LPD8DeviceMido

lpd8 = LPD8DeviceMido()

Python-lpd8 will fetch the first LPD8 device that isn’t yet occupied. If it can’t find a free device, it throws an exception.

Attaching Callbacks

Callbacks are called with the following signature:

def callback(programNum: int,
             padNum: int,
             knobNum: int,
             value: int,
             noteon: int,
             noteoff: int,
             cc: int,
             pc: int) -> None:
   pass

programNum, padNum and knobNum refer to the indices of the program and pad/knob of the pad/knob that triggered the callback.

Note

In python-lpd8 all indices are 0-indexed, while LPD8 is 1-indexed. For example: Program 1 has the index 0, pad 7 has the index 6!

value refers to either the velocity with which pads were hit or the value a knob has been turned to.

The additional parameters shall not concern us for now.

A simple callback function might look like this:

def exampleCallback(programNum: int, padNum: int, knobNum: int, value: int, noteon: int, noteoff: int, cc: int, pc: int):
    print("CB program: %s pad: %s knob: %s value: %s" % (programNum, padNum, knobNum, value))

It does nothing more than to print the program index, pad/knob index and value it receives. To have this callback called everytime we press or release pad 1, we do the following:

lpd8.addPadCB(0, 0, exampleCallback)
#lpd8.addKnobCB(0, 0, exampleCallback) # For knobs

If you press and release pad 1 you will see the following printed:

CB program: 0 pad: 0 knob: None value: 63
CB program: 0 pad: 0 knob: None value: 127

LPD8

The Akai LPD8 is a midi controller with 8 velocity-sensitive pads and 8 knobs.

Programs

The LPD8 memory bank can store 4 different programs. A program consists out of a configuration of notes and controls associated with each pad and knob.

Pads

The pads can operate in three different modes: Pad (Notes), CC (Control Change) and Prog Chng (Program Change). Depending on the mode you are using, different midi events are emitted when you press and release buttons. They also differ in how the velocity is handled.

Action Pad CC Prog Chng
Pad Down note_on control_change program_change
Pad Release note_off control_change N/A
Velocity Down 0-127 0-127 N/A
Velocity Release 127 0 N/A

All pads can be put into toggle mode. When in toggle mode, you have to press the pad a second time to trigger the release event.

When in Pad mode you can turn on and off the lights of each pad by sending a note_on or note_off midi message with the corresponding note. The state of the light will be overwritten on the next button press, so you need to resend note_on messages after a button press if you want the button to be permanently lit.

Knobs

Each knob emits a control_change message when it is turned. The value ranges from 0 to 127. It is possible to change upper and lower value limit, but this comes with a reduction in resolution and is thus not suggested.

Control Ambiguities

To prevent ambiguities, python-lpd8 checks that each pad and knob has a unique note/control/program associated with it. If an ambiguity is detected, you are left with a choice: Shall python-lpd8 throw an exception or shall it attemt to fix the problem?

By default python-lpd8 will throw an exception letting you know that there is a problem. If you want it to be fixed, call the constructor like this:

lpd8 = LPD8Device(solveAmbiguity=True)

python-lpd8 will then try to fix any ambiguity by increasing the note/control/program until it is unique across the entire device. Additionally all pad toggles will be set to off and all knob ranges are set to 0-127.

Warning

All programs on the device will be (partially) overwritten by this! Backup your programs before enabling this setting.

Callbacks

Python-lpd8 works with callbacks to let you know that a pad has been pressed or a knob has been turned. Information about which program’s pad/knob has been actuated is passed to the callback.

Signature

Any callback function must have a signature compatible to the following:

callback(programNum: int, padNum: int, knobNum: int, value: int, noteon: int, noteoff: int, cc: int, pc: int)
Parameters:
  • programNum – Index of program pad/knob belongs to
  • padNum – Index of pad that triggered call
  • knobNum – Index of knob that triggered call
  • value – Velocity for pads, value for knobs
  • noteon – midi note of noteon message
  • noteoff – midi note of noteoff message
  • cc – midi control of control change message
  • pc – midi program of program change message

The signature allows you to attach the same callback to all pads and knobs in all three modes. There are four possible calling schemes depending on the modes used:

Pad in PAD mode

In pad mode you will get one call on pad press, and another one on pad release. You can differentiate between the two by checking if noteon/noteoff is None. They will always be mutually exclusive.

Param Value press Value release
programNum 0-3 0-3
padNum 0-7 0-7
knobNum None None
value 1-127 0
noteon 0-127 None
noteoff None 0-127
cc None None
pc None None

Pad in CC mode

In cc mode you will get one call on pad press, and another one on pad release. The only way to differentiate between the
two is to check if value is 0.
Param Value press Value release
programNum 0-3 0-3
padNum 0-7 0-7
knobNum None None
value 1-127 0
noteon None None
noteoff None None
cc 0-127 0-127
pc None None

Pad in PROG CHNG mode

In program change mode you will only get a call when the button is pressed. You also get no velocity data.

Param Value press
programNum 0-3
padNum 0-7
knobNum None
value None
noteon None
noteoff None
cc None
pc 0-127

Knob

The knob behaves the same way in all three modes. You get the position of the knob as the value.

Param Value turn
programNum 0-3
padNum None
knobNum 0-7
value 0-127
noteon None
noteoff None
cc 0-127
pc None