Hey! This doesn’t work any more, as CircuitPython changed and I haven’t found a way to update it with the new interpreter.
Since there are seven touch pads on a Circuit Playground Express, that’s enough for traditional 3-chord (â… , â…£, â…¤) songs in the keys of C, D and G. That leaves one pad extra for a â…¥min chord for so you can play Neutral Milk Hotel songs in G, of course.
CircuitPython source and samples: cpx-chord_guitar.zip. Alternatively, on github: v1.0 from scruss/cpx_chord_guitar
The code is really simple: poll the seven touch pads on the CPX, and if one of them is touched, play a sample and pause for a short time:
# Circuit Playground Express Chord Guitar
# scruss - 2017-12
# these libraries should be installed by default in CircuitPython
import touchio
import board
import time
import neopixel
import digitalio
import audioio
# touch pins, anticlockwise from battery connector
touch_pins= [
touchio.TouchIn(board.A1),
touchio.TouchIn(board.A2),
touchio.TouchIn(board.A3),
touchio.TouchIn(board.A4),
touchio.TouchIn(board.A5),
touchio.TouchIn(board.A6),
touchio.TouchIn(board.A7)
]
# 16 kHz 16-bit mono audio files, in same order as pins
chord_files = [
"chord-C.wav",
"chord-D.wav",
"chord-E.wav",
"chord-Em.wav",
"chord-F.wav",
"chord-G.wav",
"chord-A.wav"
]
# nearest pixels to touch pads
chord_pixels = [ 6, 8, 9, 0, 1, 3, 4 ]
# set up neopixel access
pixels = neopixel.NeoPixel(board.NEOPIXEL, 10, brightness=.2)
pixels.fill((0, 0, 0))
pixels.show()
# set up speaker output
speaker_enable = digitalio.DigitalInOut(board.SPEAKER_ENABLE)
speaker_enable.switch_to_output(value=True)
# poll touch pins
while True:
for i in range(len(touch_pins)):
# if a pin is touched
if touch_pins[i].value:
# set nearest pixel
pixels[chord_pixels[i]] = (0, 0x10, 0)
pixels.show()
# open and play corresponding file
f=open(chord_files[i], "rb")
a = audioio.AudioOut(board.A0, f)
a.play()
# blank nearest pixel
pixels[chord_pixels[i]] = (0, 0, 0)
pixels.show()
# short delay to let chord sound
# might want to try this a little shorter for faster play
time.sleep(0.2)
This is roughly how I synthesized the samples, but I made them quieter (the MEMS speaker on the CPX went all buzzy at full volume, and not in a good way) and added a bit of reverb. Here’s the sox command from the modified script:
sox -n -r 16000 -b 16 "chord-${chord}.wav" synth 1 pl "$first" pl "$third" pl "$fifth" delay 0 .05 .1 remix - fade p 0 1 0.5 norm -5 reverb
Really, you do want to take a look at shortening the delay between the samples: you want it long enough for all of the notes of the chord to sound, but short enough that you can play faster songs. I came up with something that worked for me, kinda, and quickly; it’s worth fixing if you have the time.