updated Faderwave code

This commit is contained in:
John Park 2023-12-15 18:31:37 -08:00
parent 4005e5f2bd
commit 458db753e0

View file

@ -5,16 +5,16 @@
use 16 faders to create the single cycle waveform
rotary encoder adjusts other synth parameters
audio output: line level over 3.5mm TRS
CV output via DAC '''
optional CV output via DAC '''
import board
import busio
import ulab.numpy as np
import rotaryio
import neopixel
from digitalio import DigitalInOut, Pull
import displayio
from adafruit_display_text import label
from adafruit_display_shapes.rect import Rect
import terminalio
import synthio
import audiomixer
@ -30,10 +30,12 @@ from adafruit_midi.note_off import NoteOff
displayio.release_displays()
DEBUG = False # turn on print debugging messages
ITSY_TYPE = 0 # Pick your ItsyBitsy: 0=M4, 1=RP2040
# neopixel setup for RP2040 only
if ITSY_TYPE == 1:
import neopixel
pixel = neopixel.NeoPixel(board.NEOPIXEL, 1, brightness=0.3)
pixel.fill(0x004444)
@ -42,8 +44,8 @@ i2c = busio.I2C(board.SCL, board.SDA, frequency=1_000_000)
midi = adafruit_midi.MIDI(midi_in=usb_midi.ports[0], in_channel=0)
NUM_FADERS = 16
num_oscs = 2 # how many oscillators for each note
detune = 0.003 # how much to detune the oscillators
num_oscs = 1 # how many oscillators for each note to start
detune = 0.000 # how much to detune the oscillators
volume = 0.6 # mixer volume
lpf_freq = 12000 # user Low Pass Filter frequency setting
lpf_basef = 500 # filter lowest frequency
@ -54,7 +56,7 @@ last_faders_pos = [0] * NUM_FADERS
# Initialize ADS7830
adc_a = ADC.ADS7830(i2c, address=0x48) # default address 0x48
adc_b = ADC.ADS7830(i2c, address=0x4A) # A0 jumper 0x49, A1 0x4A
adc_b = ADC.ADS7830(i2c, address=0x49) # A0 jumper 0x49, A1 0x4A
faders = [] # list for fader objects on first ADC
for fdr in range(8): # add first group to list
@ -92,42 +94,46 @@ display = adafruit_displayio_ssd1306.SSD1306(display_bus, width=128, height=64)
# Create display group
group = displayio.Group()
# Create background rectangle
# bg_rect = Rect(0, 0, display.width, display.height, fill=0x0)
# group.append(bg_rect)
# Set the font for the text label
font = terminalio.FONT
# Create text label
title = label.Label(font, x=2, y=4, text=("Faderwave Synthesizer"), color=0xffffff)
title = label.Label(font, x=2, y=4, text=("FADERWAVE SYNTHESIZER"), color=0xffffff)
group.append(title)
title2 = label.Label(font, x=2, y=10, text=("---------------------"), color=0xffffff)
group.append(title2)
column_x = (8, 60, 100)
row_y = (22, 34, 46, 58)
column_x = (20, 90)
row_y = (22, 34, 48, 60)
midi_lbl_rect = Rect(column_x[2]-3, row_y[0]-5, 28, 10, fill=0xffffff)
group.append(midi_lbl_rect)
midi_lbl = label.Label(font, x=column_x[2], y=row_y[0], text="MIDI", color=0x000000)
group.append(midi_lbl)
midi_rect = Rect(column_x[2]-3, row_y[1]-5, 28, 10, fill=0xffffff)
group.append(midi_rect)
midi_counter_lbl = label.Label(font, x=column_x[2]+8, y=row_y[1], text='-', color=0x000000)
group.append(midi_counter_lbl)
# Create menu selector
menu_sel = 0
menu_sel_txt = label.Label(font, text=("->"), color=0xffffff)
menu_sel_txt.x = column_x[0]-16
menu_sel_txt = label.Label(font, text=(">"), color=0xffffff)
menu_sel_txt.x = column_x[0]-10
menu_sel_txt.y = row_y[menu_sel]
group.append(menu_sel_txt)
# Create detune text
det_txt_a = label.Label(font, text=("Detune....."), color=0xffffff)
det_txt_a = label.Label(font, text=("Detune "), color=0xffffff)
det_txt_a.x = column_x[0]
det_txt_a.y = row_y[0]
group.append(det_txt_a)
det_txt_b = label.Label(font, text=(str(0.003)), color=0xffffff)
det_txt_b = label.Label(font, text=(str(detune)), color=0xffffff)
det_txt_b.x = column_x[1]
det_txt_b.y = row_y[0]
group.append(det_txt_b)
# Create number of oscs text
num_oscs_txt_a = label.Label(font, text=("Num Oscs..."), color=0xffffff)
num_oscs_txt_a = label.Label(font, text=("Num Oscs "), color=0xffffff)
num_oscs_txt_a.x = column_x[0]
num_oscs_txt_a.y = row_y[1]
group.append(num_oscs_txt_a)
@ -138,7 +144,7 @@ num_oscs_txt_b.y = row_y[1]
group.append(num_oscs_txt_b)
# Create volume text
vol_txt_a = label.Label(font, text=("Volume....."), color=0xffffff)
vol_txt_a = label.Label(font, text=("Volume "), color=0xffffff)
vol_txt_a.x = column_x[0]
vol_txt_a.y = row_y[2]
group.append(vol_txt_a)
@ -148,9 +154,8 @@ vol_txt_b.x = column_x[1]
vol_txt_b.y = row_y[2]
group.append(vol_txt_b)
# Create lpf frequency text
lpf_txt_a = label.Label(font, text=("LPF........"), color=0xffffff)
lpf_txt_a = label.Label(font, text=("LPF "), color=0xffffff)
lpf_txt_a.x = column_x[0]
lpf_txt_a.y = row_y[3]
group.append(lpf_txt_a)
@ -160,7 +165,6 @@ lpf_txt_b.x = column_x[1]
lpf_txt_b.y = row_y[3]
group.append(lpf_txt_b)
# Show the display group
display.root_group = group
@ -185,7 +189,7 @@ amp_env = synthio.Envelope(attack_time=0.3, attack_level=1, sustain_level=0.65,
def faders_to_wave():
for j in range(NUM_FADERS):
wave_user[j] = int(map_range(faders_pos[j], 0, 255, -32768, 32767))
wave_user[j] = int(map_range(faders_pos[j], 0, 127, -32768, 32767))
notes_pressed = {} # which notes being pressed. key=midi note, val=note object
@ -198,6 +202,7 @@ def note_on(n):
f = fo * (1 + k*detune)
voices.append(synthio.Note(frequency=f, filter=lpf, envelope=amp_env, waveform=wave_user))
synth.press(voices)
note_off(n) # help to prevent double note_on for same note which can get stuck
notes_pressed[n] = voices
def note_off(n):
@ -209,25 +214,39 @@ def note_off(n):
def map_range(s, a1, a2, b1, b2):
return b1 + ((s - a1) * (b2 - b1) / (a2 - a1))
notes_on = 0
print("Welcome to Faderwave")
while True:
# get midi messages
msg = midi.receive()
if isinstance(msg, NoteOn) and msg.velocity != 0:
note_on(msg.note)
elif isinstance(msg, NoteOff) or isinstance(msg, NoteOn) and msg.velocity == 0:
notes_on = notes_on + 1
if DEBUG:
print("MIDI notes on: ", msg.note, " Polyphony:", " "*notes_on, notes_on)
midi_counter_lbl.text = str(msg.note)
elif isinstance(msg, NoteOff) or (isinstance(msg, NoteOn) and msg.velocity == 0):
note_off(msg.note)
notes_on = notes_on - 1
if DEBUG:
print("MIDI notes off:", msg.note, " Polyphony:", " "*notes_on, notes_on)
midi_counter_lbl.text = "-"
# check faders
for i in range(len(faders)):
faders_pos[i] = faders[i].value//256
faders_pos[i] = faders[i].value//512
if faders_pos[i] is not last_faders_pos[i]:
faders_to_wave()
last_faders_pos[i] = faders_pos[i]
if DEBUG:
print("fader", [i], faders_pos[i])
# send out a DAC value based on fader 0
if i == 0:
dac.value = faders[0].value
# if i == 1:
# dac.value = faders[1].value
# check encoder button
button.update()
@ -247,7 +266,7 @@ while True:
elif menu_sel == 1:
num_oscs = num_oscs + delta
num_oscs = min(max(num_oscs, 1), 8)
num_oscs = min(max(num_oscs, 1), 5)
formatted_num_oscs = str(num_oscs)
num_oscs_txt_b.text = formatted_num_oscs