5
5
use 16 faders to create the single cycle waveform
6
6
rotary encoder adjusts other synth parameters
7
7
audio output: line level over 3.5mm TRS
8
- CV output via DAC '''
8
+ optional CV output via DAC '''
9
9
10
10
import board
11
11
import busio
12
12
import ulab .numpy as np
13
13
import rotaryio
14
- import neopixel
15
14
from digitalio import DigitalInOut , Pull
16
15
import displayio
17
16
from adafruit_display_text import label
17
+ from adafruit_display_shapes .rect import Rect
18
18
import terminalio
19
19
import synthio
20
20
import audiomixer
30
30
31
31
displayio .release_displays ()
32
32
33
+ DEBUG = False # turn on print debugging messages
33
34
ITSY_TYPE = 0 # Pick your ItsyBitsy: 0=M4, 1=RP2040
34
35
35
36
# neopixel setup for RP2040 only
36
37
if ITSY_TYPE == 1 :
38
+ import neopixel
37
39
pixel = neopixel .NeoPixel (board .NEOPIXEL , 1 , brightness = 0.3 )
38
40
pixel .fill (0x004444 )
39
41
42
44
midi = adafruit_midi .MIDI (midi_in = usb_midi .ports [0 ], in_channel = 0 )
43
45
44
46
NUM_FADERS = 16
45
- num_oscs = 2 # how many oscillators for each note
46
- detune = 0.003 # how much to detune the oscillators
47
+ num_oscs = 1 # how many oscillators for each note to start
48
+ detune = 0.000 # how much to detune the oscillators
47
49
volume = 0.6 # mixer volume
48
50
lpf_freq = 12000 # user Low Pass Filter frequency setting
49
51
lpf_basef = 500 # filter lowest frequency
54
56
55
57
# Initialize ADS7830
56
58
adc_a = ADC .ADS7830 (i2c , address = 0x48 ) # default address 0x48
57
- adc_b = ADC .ADS7830 (i2c , address = 0x4A ) # A0 jumper 0x49, A1 0x4A
59
+ adc_b = ADC .ADS7830 (i2c , address = 0x49 ) # A0 jumper 0x49, A1 0x4A
58
60
59
61
faders = [] # list for fader objects on first ADC
60
62
for fdr in range (8 ): # add first group to list
92
94
93
95
# Create display group
94
96
group = displayio .Group ()
95
- # Create background rectangle
96
- # bg_rect = Rect(0, 0, display.width, display.height, fill=0x0)
97
- # group.append(bg_rect)
97
+
98
98
# Set the font for the text label
99
99
font = terminalio .FONT
100
100
101
101
# Create text label
102
- title = label .Label (font , x = 2 , y = 4 , text = ("Faderwave Synthesizer " ), color = 0xffffff )
102
+ title = label .Label (font , x = 2 , y = 4 , text = ("FADERWAVE SYNTHESIZER " ), color = 0xffffff )
103
103
group .append (title )
104
104
105
- title2 = label . Label ( font , x = 2 , y = 10 , text = ( "---------------------" ), color = 0xffffff )
106
- group . append ( title2 )
105
+ column_x = ( 8 , 60 , 100 )
106
+ row_y = ( 22 , 34 , 46 , 58 )
107
107
108
- column_x = (20 , 90 )
109
- row_y = (22 , 34 , 48 , 60 )
108
+ midi_lbl_rect = Rect (column_x [2 ]- 3 , row_y [0 ]- 5 , 28 , 10 , fill = 0xffffff )
109
+ group .append (midi_lbl_rect )
110
+ midi_lbl = label .Label (font , x = column_x [2 ], y = row_y [0 ], text = "MIDI" , color = 0x000000 )
111
+ group .append (midi_lbl )
112
+ midi_rect = Rect (column_x [2 ]- 3 , row_y [1 ]- 5 , 28 , 10 , fill = 0xffffff )
113
+ group .append (midi_rect )
114
+ midi_counter_lbl = label .Label (font , x = column_x [2 ]+ 8 , y = row_y [1 ], text = '-' , color = 0x000000 )
115
+ group .append (midi_counter_lbl )
110
116
111
117
# Create menu selector
112
118
menu_sel = 0
113
- menu_sel_txt = label .Label (font , text = ("- >" ), color = 0xffffff )
114
- menu_sel_txt .x = column_x [0 ]- 16
119
+ menu_sel_txt = label .Label (font , text = (">" ), color = 0xffffff )
120
+ menu_sel_txt .x = column_x [0 ]- 10
115
121
menu_sel_txt .y = row_y [menu_sel ]
116
122
group .append (menu_sel_txt )
117
123
118
124
# Create detune text
119
- det_txt_a = label .Label (font , text = ("Detune..... " ), color = 0xffffff )
125
+ det_txt_a = label .Label (font , text = ("Detune " ), color = 0xffffff )
120
126
det_txt_a .x = column_x [0 ]
121
127
det_txt_a .y = row_y [0 ]
122
128
group .append (det_txt_a )
123
129
124
- det_txt_b = label .Label (font , text = (str (0.003 )), color = 0xffffff )
130
+ det_txt_b = label .Label (font , text = (str (detune )), color = 0xffffff )
125
131
det_txt_b .x = column_x [1 ]
126
132
det_txt_b .y = row_y [0 ]
127
133
group .append (det_txt_b )
128
134
129
135
# Create number of oscs text
130
- num_oscs_txt_a = label .Label (font , text = ("Num Oscs... " ), color = 0xffffff )
136
+ num_oscs_txt_a = label .Label (font , text = ("Num Oscs " ), color = 0xffffff )
131
137
num_oscs_txt_a .x = column_x [0 ]
132
138
num_oscs_txt_a .y = row_y [1 ]
133
139
group .append (num_oscs_txt_a )
138
144
group .append (num_oscs_txt_b )
139
145
140
146
# Create volume text
141
- vol_txt_a = label .Label (font , text = ("Volume..... " ), color = 0xffffff )
147
+ vol_txt_a = label .Label (font , text = ("Volume " ), color = 0xffffff )
142
148
vol_txt_a .x = column_x [0 ]
143
149
vol_txt_a .y = row_y [2 ]
144
150
group .append (vol_txt_a )
148
154
vol_txt_b .y = row_y [2 ]
149
155
group .append (vol_txt_b )
150
156
151
-
152
157
# Create lpf frequency text
153
- lpf_txt_a = label .Label (font , text = ("LPF........ " ), color = 0xffffff )
158
+ lpf_txt_a = label .Label (font , text = ("LPF " ), color = 0xffffff )
154
159
lpf_txt_a .x = column_x [0 ]
155
160
lpf_txt_a .y = row_y [3 ]
156
161
group .append (lpf_txt_a )
160
165
lpf_txt_b .y = row_y [3 ]
161
166
group .append (lpf_txt_b )
162
167
163
-
164
168
# Show the display group
165
169
display .root_group = group
166
170
185
189
186
190
def faders_to_wave ():
187
191
for j in range (NUM_FADERS ):
188
- wave_user [j ] = int (map_range (faders_pos [j ], 0 , 255 , - 32768 , 32767 ))
192
+ wave_user [j ] = int (map_range (faders_pos [j ], 0 , 127 , - 32768 , 32767 ))
189
193
190
194
notes_pressed = {} # which notes being pressed. key=midi note, val=note object
191
195
@@ -198,6 +202,7 @@ def note_on(n):
198
202
f = fo * (1 + k * detune )
199
203
voices .append (synthio .Note (frequency = f , filter = lpf , envelope = amp_env , waveform = wave_user ))
200
204
synth .press (voices )
205
+ note_off (n ) # help to prevent double note_on for same note which can get stuck
201
206
notes_pressed [n ] = voices
202
207
203
208
def note_off (n ):
@@ -209,25 +214,39 @@ def note_off(n):
209
214
def map_range (s , a1 , a2 , b1 , b2 ):
210
215
return b1 + ((s - a1 ) * (b2 - b1 ) / (a2 - a1 ))
211
216
217
+ notes_on = 0
218
+
219
+ print ("Welcome to Faderwave" )
220
+
212
221
213
222
while True :
214
223
# get midi messages
215
224
msg = midi .receive ()
216
225
if isinstance (msg , NoteOn ) and msg .velocity != 0 :
217
226
note_on (msg .note )
218
- elif isinstance (msg , NoteOff ) or isinstance (msg , NoteOn ) and msg .velocity == 0 :
227
+ notes_on = notes_on + 1
228
+ if DEBUG :
229
+ print ("MIDI notes on: " , msg .note , " Polyphony:" , " " * notes_on , notes_on )
230
+ midi_counter_lbl .text = str (msg .note )
231
+ elif isinstance (msg , NoteOff ) or (isinstance (msg , NoteOn ) and msg .velocity == 0 ):
219
232
note_off (msg .note )
233
+ notes_on = notes_on - 1
234
+ if DEBUG :
235
+ print ("MIDI notes off:" , msg .note , " Polyphony:" , " " * notes_on , notes_on )
236
+ midi_counter_lbl .text = "-"
220
237
221
238
# check faders
222
239
for i in range (len (faders )):
223
- faders_pos [i ] = faders [i ].value // 256
240
+ faders_pos [i ] = faders [i ].value // 512
224
241
if faders_pos [i ] is not last_faders_pos [i ]:
225
242
faders_to_wave ()
226
243
last_faders_pos [i ] = faders_pos [i ]
244
+ if DEBUG :
245
+ print ("fader" , [i ], faders_pos [i ])
227
246
228
247
# send out a DAC value based on fader 0
229
- if i == 0 :
230
- dac .value = faders [0 ].value
248
+ # if i == 1 :
249
+ # dac.value = faders[1 ].value
231
250
232
251
# check encoder button
233
252
button .update ()
@@ -247,7 +266,7 @@ def map_range(s, a1, a2, b1, b2):
247
266
248
267
elif menu_sel == 1 :
249
268
num_oscs = num_oscs + delta
250
- num_oscs = min (max (num_oscs , 1 ), 8 )
269
+ num_oscs = min (max (num_oscs , 1 ), 5 )
251
270
formatted_num_oscs = str (num_oscs )
252
271
num_oscs_txt_b .text = formatted_num_oscs
253
272
0 commit comments