Skip to content

Instantly share code, notes, and snippets.

@gamblor21
Created April 24, 2025 21:15
Show Gist options
  • Save gamblor21/e0a31217ec6dc8be68048e790f29ccb4 to your computer and use it in GitHub Desktop.
Save gamblor21/e0a31217ec6dc8be68048e790f29ccb4 to your computer and use it in GitHub Desktop.
USB Midi to CircuitPython synthio with audio effects
import time
import board
import busio
import adafruit_midi
import usb_midi
import audiobusio, audiocore, audiomixer, audiodelays, audiofilters, synthio, audiofreeverb
from waveforms import waveforms
from adafruit_midi.control_change import ControlChange
from adafruit_midi.note_off import NoteOff
from adafruit_midi.note_on import NoteOn
time.sleep(1.0)
CHANNELS=2
SRATE=44100
import ulab.numpy as np
SAMPLE_SIZE = 512
SAMPLE_VOLUME = 14000 # 0-32767
wave_sine = np.array(np.sin(np.linspace(0, 2*np.pi, SAMPLE_SIZE, endpoint=False)) * SAMPLE_VOLUME, dtype=np.int16)
i2s_bclk, i2s_lclk, i2s_data = board.GP20, board.GP21, board.GP22
audio = audiobusio.I2SOut(bit_clock=i2s_bclk, word_select=i2s_lclk, data=i2s_data)
mixer = audiomixer.Mixer(voice_count=1, channel_count=CHANNELS, sample_rate=SRATE, buffer_size=2048)
audio.play(mixer)
current_wave = 0
SAMPLE_SIZE = len(waveforms[0])
wavetable = np.zeros(SAMPLE_SIZE, dtype=np.int16) # intially all zeros (silence)
wavetable[:] = waveforms[current_wave]
synth = synthio.Synthesizer(channel_count=CHANNELS, sample_rate=SRATE)#, waveform=wavetable)
#chorus = audiodelays.Chorus(max_delay_ms=50, delay_ms=2, voices=1, buffer_size=1024, channel_count=CHANNELS, sample_rate=SRATE)
chorus = audiofreeverb.Freeverb(roomsize=0.75, damp=0.5, mix=0.4, channel_count=CHANNELS, sample_rate=SRATE)
chorus.play(synth)
#lpf = audiofilters.Filter(channel_count=CHANNELS, sample_rate=SRATE, mix=1.0)
#lpf.filter= synth.low_pass_filter(frequency=10000, Q=1.0)
#lpf.play(chorus)
#mixer.voice[0].play(lpf)
mixer.voice[0].play(chorus)
### MIDI SETUP
midi = adafruit_midi.MIDI(usb_midi.ports[0])
notes = {}
def PlayNote(msg):
print("Playing ", msg)
amplitude = msg.velocity/127.0 / 2
if msg.note not in notes:
note = synthio.Note(synthio.midi_to_hz(msg.note), amplitude=amplitude)
notes[msg.note] = note
synth.press(note)
def StopNote(msg):
print("Stopping ", msg)
note = notes.pop(msg.note, None)
if (note is not None):
synth.release(note)
def CC(msg):
global wavetable, current_wave
print("CC ", msg)
if (msg.control == 70):
if msg.value==1:
chorus.delay_ms += 0.2
else:
if chorus.delay_ms >= 0.2:
chorus.delay_ms -= 0.2
print(chorus.delay_ms)
if (msg.control == 71):
if msg.value==1:
chorus.voices += 1
else:
if chorus.voices > 1:
chorus.voices -= 1
print(chorus.voices)
if (msg.control == 72):
if msg.value==1:
if chorus.mix <= 1.0:
chorus.mix += 0.05
else:
if chorus.mix > 0.0:
chorus.mix -= 0.05
print(chorus.mix)
if (msg.control == 74):
if msg.value==1:
current_wave += 1
if (current_wave >= len(waveforms)):
current_wave = 0
else:
current_wave -= 1
if (current_wave == -1):
current_wave = len(waveforms)-1
wavetable[:] = waveforms[current_wave]
print(current_wave)
def CC_reverb(msg):
global wavetable, current_wave
print("CC ", msg)
if (msg.control == 70):
if msg.value==1:
if chorus.roomsize < 1.0:
chorus.roomsize += 0.05
else:
if chorus.roomsize >= 0.05:
chorus.roomsize -= 0.05
print(chorus.roomsize)
if (msg.control == 71):
if msg.value==1:
if chorus.damp < 1.0:
chorus.damp += 0.05
else:
if chorus.damp >= 0.05:
chorus.damp -= 0.05
print(chorus.damp)
if (msg.control == 72):
if msg.value==1:
if chorus.mix < 1.0:
chorus.mix += 0.05
else:
if chorus.mix > 0.0:
chorus.mix -= 0.05
print(chorus.mix)
if (msg.control == 74):
if msg.value==1:
current_wave += 1
if (current_wave >= len(waveforms)):
current_wave = 0
else:
current_wave -= 1
if (current_wave == -1):
current_wave = len(waveforms)-1
wavetable[:] = waveforms[current_wave]
print(current_wave)
while True:
time.sleep(0.01)
msg = midi.receive()
if isinstance(msg, NoteOn):
PlayNote(msg)
if isinstance(msg, NoteOff):
StopNote(msg)
if isinstance(msg, ControlChange):
if isinstance(chorus, audiofreeverb.Freeverb):
CC_reverb(msg)
else:
CC(msg)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment