Simple test

Ensure your device works with this simple test.

examples/keymanager_simpletest.py
 1# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries
 2# SPDX-FileCopyrightText: Copyright (c) 2024 Cooper Dalrymple
 3#
 4# SPDX-License-Identifier: Unlicense
 5
 6from relic_keymanager import Keyboard
 7
 8keyboard = Keyboard()
 9
10keyboard.on_voice_press = lambda voice: print(f"Pressed: {voice.note.notenum:d}")
11keyboard.on_voice_release = lambda voice: print(f"Released: {voice.note.notenum:d}")
12
13for i in range(1, 4):
14    keyboard.append(i)
15for i in range(3, 0, -1):
16    keyboard.remove(i)

Keys

Use a digital input to trigger a note.

examples/keymanager_keys.py
 1# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries
 2# SPDX-FileCopyrightText: Copyright (c) 2024 Cooper Dalrymple
 3#
 4# SPDX-License-Identifier: Unlicense
 5
 6import asyncio
 7
 8import board
 9from keypad import Keys
10
11from relic_keymanager import Keyboard
12
13keyboard = Keyboard(
14    keys=Keys((board.USER_SW,), value_when_pressed=False, pull=False),
15)
16
17keyboard.on_voice_press = lambda voice: print(f"Pressed: {voice.note.notenum:d}")
18keyboard.on_voice_release = lambda voice: print(f"Released: {voice.note.notenum:d}")
19
20asyncio.run(keyboard.update())

Arpeggiator

Demonstration of the arpeggiator.

examples/keymanager_arpeggiator.py
 1# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries
 2# SPDX-FileCopyrightText: Copyright (c) 2024 Cooper Dalrymple
 3#
 4# SPDX-License-Identifier: Unlicense
 5
 6import asyncio
 7
 8from relic_keymanager import Arpeggiator, ArpeggiatorMode, Keyboard, TimerStep
 9
10keyboard = Keyboard()
11
12keyboard.on_voice_press = lambda voice: print(f"Pressed: {voice.note.notenum:d}")
13
14keyboard.arpeggiator = Arpeggiator(steps=TimerStep.QUARTER, mode=ArpeggiatorMode.UPDOWN)
15keyboard.arpeggiator.octaves = 1
16keyboard.arpeggiator.active = True
17
18for i in range(1, 4):
19    keyboard.append(i)
20
21asyncio.run(keyboard.arpeggiator.update())

Sequencer

Demonstration of the sequencer.

examples/keymanager_sequencer.py
 1# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries
 2# SPDX-FileCopyrightText: Copyright (c) 2024 Cooper Dalrymple
 3#
 4# SPDX-License-Identifier: Unlicense
 5
 6import asyncio
 7
 8from relic_keymanager import Keyboard, Sequencer
 9
10keyboard = Keyboard()
11
12keyboard.on_voice_press = lambda voice: print(f"Pressed: {voice.note.notenum:d}")
13
14sequencer = Sequencer()
15sequencer.active = True
16
17for i in range(4):
18    sequencer.set_note(i * 4, 1)
19    sequencer.set_note(i * 4 + 2, i % 2 + 2)
20
21sequencer.on_press = lambda notenum, velocity: keyboard.append(notenum, velocity)
22sequencer.on_release = lambda notenum: keyboard.remove(notenum)
23
24asyncio.run(sequencer.update())

synthio & MIDI

Use the relic_keymanager.Keyboard class to help allocate MIDI notes into a limited set of synthio.Note objects using USB MIDI input and DAC/PWM audio playback.

examples/keymanager_synthio.py
 1# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries
 2# SPDX-FileCopyrightText: Copyright (c) 2024 Cooper Dalrymple
 3#
 4# SPDX-License-Identifier: Unlicense
 5
 6import adafruit_midi
 7import audiopwmio
 8import board
 9import digitalio
10import synthio
11import usb_midi
12from adafruit_midi.control_change import ControlChange
13from adafruit_midi.note_off import NoteOff
14from adafruit_midi.note_on import NoteOn
15from adafruit_midi.pitch_bend import PitchBend
16
17from relic_keymanager import Keyboard
18
19led = digitalio.DigitalInOut(board.LED)
20led.direction = digitalio.Direction.OUTPUT
21
22audio = audiopwmio.PWMAudioOut(board.A0)
23synth = synthio.Synthesizer()
24audio.play(synth)
25
26notes = tuple(
27    [
28        synthio.Note(
29            frequency=440.0,
30            bend=synthio.Math(
31                synthio.MathOperation.SUM, synthio.LFO(rate=8.0, scale=0.0), 0.0, 0.0
32            ),
33        )
34        for i in range(4)
35    ]
36)
37
38keyboard = Keyboard(max_voices=len(notes))
39
40
41def press(voice):
42    notes[voice.index].frequency = synthio.midi_to_hz(voice.note.notenum)
43    synth.press(notes[voice.index])
44    led.value = True
45
46
47keyboard.on_voice_press = press
48
49
50def release(voice):
51    synth.release(notes[voice.index])
52    if not synth.pressed:
53        led.value = False
54
55
56keyboard.on_voice_release = release
57
58midi = adafruit_midi.MIDI(
59    midi_in=usb_midi.ports[0], in_channel=0, midi_out=usb_midi.ports[1], out_channel=0
60)
61
62while True:
63    msg = midi.receive()
64    if isinstance(msg, NoteOn) and msg.velocity != 0:
65        keyboard.append(msg.note, msg.velocity / 127.0)
66    elif isinstance(msg, NoteOff) or (isinstance(msg, NoteOn) and msg.velocity == 0):
67        keyboard.remove(msg.note)
68    elif isinstance(msg, ControlChange):
69        if msg.control == 1:  # Mod Wheel
70            for note in notes:
71                note.bend.a.scale = msg.value / 127 / 12.0
72        elif msg.control == 64:  # Sustain Pedal
73            keyboard.sustain = msg.value >= 64
74    elif isinstance(msg, PitchBend):
75        for note in notes:
76            note.bend.b = (msg.pitch_bend / 8192) - 1.0