Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save gwthompson/59bac4ac4af56696d47eb151c4effa8e to your computer and use it in GitHub Desktop.
Save gwthompson/59bac4ac4af56696d47eb151c4effa8e to your computer and use it in GitHub Desktop.
Trinkey MIDI Theramin (will also work on any other CircuitPyton devices with `touchio`)
# Trinkey Theramin!
# 2021 @todbot
#
import time
import board
import neopixel
import touchio
import usb_midi
import adafruit_midi
from adafruit_midi.note_on import NoteOn
from adafruit_midi.control_change import ControlChange
midi = adafruit_midi.MIDI(midi_out=usb_midi.ports[1], out_channel=0)
leds = neopixel.NeoPixel(board.NEOPIXEL, 4, brightness=0.2, auto_write=True)
# announce we're alive and wait for things to stabilize
# before creating touch pins so their raw_value baseline are okay
leds.fill(0xff00ff)
time.sleep(1.0)
leds.fill(0)
touch1_pin = touchio.TouchIn(board.TOUCH1)
touch2_pin = touchio.TouchIn(board.TOUCH2)
# a litlte helper class for noise filtering
class RunningAverage:
def __init__(self,count):
self.count = count
self.i = 0
self.buf = [0] * self.count
def add_value(self,val):
self.buf[self.i] = val
self.i = (self.i + 1) % self.count
def average(self):
return sum(self.buf)/self.count
base1 = int(touch1_pin.raw_value * 1.02)
base2 = int(touch2_pin.raw_value * 1.02)
avg1 = RunningAverage(8)
avg2 = RunningAverage(8)
note_on = False
note = 60 # C4 in MIDI land
velocity = 64 # half
while True:
avg1.add_value( touch1_pin.raw_value )
avg2.add_value( touch2_pin.raw_value )
r = 0
g = min(max(avg1.average()-base1, 0),255)
b = min(max(avg2.average()-base2, 0),255)
leds.fill( (r,g,b) )
if g > 10: # hand present
if not note_on:
midi.send(NoteOn(note, velocity))
print(time.monotonic(),"******* ON!")
note_on = True
else:
if note_on:
midi.send(NoteOn(note, 0)) # release
print("------ OFF!")
note_on = False
if g > 10: # hand present
midi.send(ControlChange(10, 64+int(g//4))) # 10 = filter cutoff
if b > 10: # hand present
midi.send(ControlChange(7, 64+int(b//4))) # 7 = filter resonance
time.sleep(0.001)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment