Skip to content

Commit cf37ba3

Browse files
committed
improved offsets calculation, better launchpad support
1 parent 1c28ab4 commit cf37ba3

4 files changed

Lines changed: 124 additions & 66 deletions

File tree

src/core.py

Lines changed: 67 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
error("The project dependencies have changed! Run the requirements setup command again!")
4848

4949
class Core:
50+
CORE = None
5051

5152
def rotate_mode(self, notes: str, mode: int):
5253
"""Rotates a mode string (see: scales.yaml strings with x and .)"""
@@ -135,7 +136,7 @@ def set_light(self, x, y, col, index=None, mark=False): # col is [1,11], 0 rese
135136
return
136137

137138
if not index:
138-
index = self.get_note_index(x, y)
139+
index = self.get_note_index(x, y, transpose=False)
139140

140141
self.mark_lights[y][x] = mark
141142
if self.linn_out:
@@ -169,8 +170,8 @@ def set_light(self, x, y, col, index=None, mark=False): # col is [1,11], 0 rese
169170

170171
def reset_light(self, x, y, reset_red=True):
171172
"""Reset the light at x, y"""
172-
note = self.get_note_index(x, y)
173-
# print(note)
173+
note = self.get_note_index(x, y, transpose=False)
174+
174175
if self.is_split():
175176
split_chan = self.channel_from_split(x, self.board_h - y - 1)
176177
if split_chan:
@@ -197,7 +198,7 @@ def reset_light(self, x, y, reset_red=True):
197198

198199
def reset_launchpad_light(self, x, y, launchpad=None):
199200
"""Reset the launchpad light at x, y"""
200-
note = self.get_note_index(x, 8-y-1)
201+
note = self.get_note_index(x, 8-y-1, transpose=False)
201202
# if self.is_split():
202203
# split_chan = self.channel_from_split(x, self.board_h - y - 1)
203204
# if split_chan:
@@ -270,28 +271,30 @@ def reset_lights(self):
270271
# except IndexError:
271272
# pass
272273

273-
def xy_to_midi(self, x, y):
274+
def xy_to_midi(self, x, y, transpose=True):
274275
"""x, y coordinate to midi note based on layout (this can be improved)"""
275276
y = self.board_h - y - 1
276277
column_offset = self.options.column_offset
277278
row_offset = self.options.row_offset
278279
xx = x + self.options.base_offset
279-
r = row_offset * y + column_offset * xx
280+
r = row_offset * y + (column_offset * (xx + self.position.x))
280281
r += 24
281282
if self.flipped:
282283
r += 7
284+
r += self.tonic if transpose else 0
283285
# print(x, y, r)
284286
return r
285287

286288
def get_note_index(self, x, y, transpose=True):
287289
"""Get the note index (0-11) for a given x, y"""
288290
y += self.flipped
289-
x += self.transpose
291+
x += self.position.x
290292
column_offset = self.options.column_offset
291293
row_offset = self.options.row_offset
292294
y = self.board_h - y - 1
293295
x += self.options.base_offset
294-
return (row_offset * y + column_offset * x) % len(NOTES)
296+
tr = self.tonic if transpose else 0
297+
return (row_offset * y + column_offset * x + tr) % len(NOTES)
295298
# ofs = (self.board_h - y) // 2 + BASE_OFFSET
296299
# step = 2 if WHOLETONE else 1
297300
# tr = self.tonic if transpose else 0
@@ -307,7 +310,7 @@ def get_note(self, x, y, transpose=True):
307310
def get_color(self, x, y):
308311
"""Get color for x, y"""
309312
# return NOTE_COLORS[get_note_index(x, y)]
310-
note = self.get_note_index(x, y)
313+
note = self.get_note_index(x, y, transpose=False)
311314
# note = (note - self.tonic) % 12
312315
# if self.is_split():
313316
# split_chan = self.channel_from_split(x, self.board_h - y - 1)
@@ -448,11 +451,11 @@ def get_octave(self, x, y):
448451
# if self.flipped:
449452
# if self.tonic % 2 == 0:
450453
# y -= 1
451-
# octave = int(x + 4 + self.transpose + y * 2.5) // 6
454+
# octave = int(x + 4 + self.position.x + y * 2.5) // 6
452455
# else:
453456
if self.tonic % 2:
454457
y -= 1
455-
octave = int(x + 4 + self.transpose + y * 2.5) // 6
458+
octave = int(x + 4 + self.position.x + y * 2.5) // 6
456459
return octave
457460

458461
def held_note_count(self):
@@ -574,9 +577,12 @@ def note_on(self, data, timestamp, width=None, curve=True, mpe=None, octave=0, t
574577
x = col
575578
midinote = row_offset * y + column_offset * x
576579
midinote += 32
577-
midinote += 12 * octave
578580
if self.flipped:
579581
midinote += 7
582+
visual_midinote = midinote
583+
midinote += 12 * (octave + self.octave)
584+
midinote += self.options.column_offset * self.position.x
585+
midinote += transpose + self.tonic
580586

581587
# print(x, y, midinote)
582588
# return
@@ -604,7 +610,7 @@ def note_on(self, data, timestamp, width=None, curve=True, mpe=None, octave=0, t
604610
# data[1] += (self.octave + self.octave_base + octave) * 12
605611
# data[1] += transpose
606612
# data[1] += BASE_OFFSET
607-
# midinote = data[1] - 24 + self.transpose * 2
613+
# midinote = data[1] - 24 + self.position.x * 2
608614
col_full = x + (left_width if within_hardware_split else 0)
609615

610616
# figure out if note is on left or right side
@@ -626,8 +632,8 @@ def note_on(self, data, timestamp, width=None, curve=True, mpe=None, octave=0, t
626632
data[1] = midinote
627633

628634
if not aftertouch:
629-
self.mark(midinote - 24, 1, only_row=row)
630-
# data[1] += self.out_octave * 12 + self.transpose * 2
635+
self.mark(visual_midinote - 24, 1, only_row=row)
636+
# data[1] += self.out_octave * 12 + self.position.x * 2
631637
# if self.flipped:
632638
# data[1] += 7
633639

@@ -760,7 +766,7 @@ def note_off(self, data, timestamp, width=None, mpe=None, octave=0, transpose=0,
760766
# data[1] += (self.octave + self.octave_base + octave) * 12
761767
# data[1] += BASE_OFFSET
762768
# data[1] += transpose
763-
# midinote = data[1] - 24 + self.transpose * 2
769+
# midinote = data[1] - 24 + self.position.x * 2
764770

765771
row = data[1] // width
766772
col = data[1] % width
@@ -773,9 +779,12 @@ def note_off(self, data, timestamp, width=None, mpe=None, octave=0, transpose=0,
773779
x = col
774780
midinote = row_offset * y + column_offset * x
775781
midinote += 32
776-
midinote += 12 * octave
777782
if self.flipped:
778783
midinote += 7
784+
visual_midinote = midinote
785+
midinote += 12 * (octave + self.octave)
786+
midinote += self.options.column_offset * self.position.x
787+
midinote += transpose + self.tonic
779788
# print('off', x, y, midinote)
780789

781790
col_full = x + (left_width if within_hardware_split else 0)
@@ -794,8 +803,8 @@ def note_off(self, data, timestamp, width=None, mpe=None, octave=0, transpose=0,
794803

795804
data[1] = midinote
796805

797-
self.mark(midinote - 24, 0, only_row=y)
798-
# data[1] += self.out_octave * 12 + self.transpose * 2
806+
self.mark(visual_midinote - 24, 0, only_row=y)
807+
# data[1] += self.out_octave * 12 + self.position.x * 2
799808
# if self.flipped:
800809
# data[1] += 7
801810

@@ -1087,7 +1096,7 @@ def cb_launchpad_in(self, lp, event, timestamp=0):
10871096
note = y * 8 + x
10881097
note += 12
10891098
if not self.is_macro_button(x, 8 - y - 1):
1090-
self.note_on([160, note, event[2]], timestamp, width=8, octave=lp.octave_separation, force_channel=self.options.launchpad_channel)
1099+
self.note_on([160, note, event[2]], timestamp, width=8, transpose=lp.transpose, octave=lp.get_octave(), force_channel=self.options.launchpad_channel)
10911100
self.articulation.pressure(vel / 127)
10921101
else:
10931102
self.macro(x, 8 - y - 1, vel / 127)
@@ -1098,7 +1107,7 @@ def cb_launchpad_in(self, lp, event, timestamp=0):
10981107
self.reset_launchpad_light(x, y, launchpad=lp)
10991108
if not self.is_macro_button(x, 8 - y - 1):
11001109
note = y * 8 + x
1101-
self.note_off([128, note, event[2]], timestamp, width=8, octave=lp.octave_separation, force_channel=self.options.launchpad_channel)
1110+
self.note_off([128, note, event[2]], timestamp, width=8, transpose=lp.transpose, octave=lp.get_octave(), force_channel=self.options.launchpad_channel)
11021111
else:
11031112
self.macro(x, 8 - y - 1, False)
11041113
else: # note on
@@ -1108,23 +1117,12 @@ def cb_launchpad_in(self, lp, event, timestamp=0):
11081117
self.set_launchpad_light(x, y, -1, launchpad=lp)
11091118
if not self.is_macro_button(x, 8 - y - 1):
11101119
note = y * 8 + x
1111-
self.note_on([144, note, event[2]], timestamp, width=8, octave=lp.octave_separation, force_channel=self.options.launchpad_channel)
1120+
self.note_on([144, note, event[2]], timestamp, width=8, transpose=lp.transpose, octave=lp.get_octave(), force_channel=self.options.launchpad_channel)
11121121
else:
11131122
self.macro(x, 8 - y - 1, True)
11141123
else:
11151124
# Launchpad X buttons
1116-
if lp.mode == 'lpx':
1117-
if x == 0:
1118-
self.octave += 1
1119-
self.clear_marks(use_lights=False)
1120-
elif x == 1:
1121-
self.octave -= 1
1122-
self.clear_marks(use_lights=False)
1123-
elif x == 2:
1124-
self.move_board(-1)
1125-
elif x == 3:
1126-
self.move_board(1)
1127-
# elif x == 4:
1125+
lp.button(x, 8 - y - 1)
11281126

11291127
# uses raw events (Launchpad X)
11301128
# def cb_launchpad_in(self, event, timestamp=0):
@@ -1212,6 +1210,8 @@ def sig(self, signal, frame):
12121210
self.quit()
12131211

12141212
def __init__(self):
1213+
Core.CORE = self
1214+
12151215
signal.signal(signal.SIGINT, self.sig)
12161216
signal.signal(signal.SIGTERM, self.sig)
12171217

@@ -1448,7 +1448,8 @@ def __init__(self):
14481448
-2
14491449
) # this is for both the visualizer and the keyboard simulator marking atm
14501450
self.octave_base = -2
1451-
self.transpose = 0
1451+
# self.position.x = 0
1452+
self.position = glm.ivec2(0, 0) # only x is used right now
14521453
self.rotated = False # transpose -3 whole steps
14531454
self.flipped = False # vertically shift +1
14541455
self.config_save_timer = 1.0
@@ -1710,31 +1711,27 @@ def __init__(self):
17101711
lp = launchpad.LaunchpadPro()
17111712
if lp.Check(0):
17121713
if lp.Open(0):
1713-
self.launchpads += [Launchpad(lp, "pro", 0)]
1714+
self.launchpads += [Launchpad(self, lp, "pro", 0)]
17141715
if launchpad.LaunchpadProMk3().Check(0):
17151716
lp = launchpad.LaunchpadProMk3()
17161717
if lp.Open(0):
1717-
self.launchpads += [Launchpad(lp, "promk3", 0)]
1718+
self.launchpads += [Launchpad(self, lp, "promk3", 0)]
17181719
if launchpad.LaunchpadLPX().Check(1):
17191720
lp = launchpad.LaunchpadLPX()
17201721
if lp.Open(1):
1721-
self.launchpads += [Launchpad(lp, "lpx", 0)]
1722+
self.launchpads += [Launchpad(self, lp, "lpx", 0)]
17221723
if launchpad.LaunchpadLPX().Check(3):
17231724
lp = launchpad.LaunchpadLPX()
17241725
if lp.Open(3): # second
1725-
self.launchpads += [Launchpad(lp, "lpx", 1, self.options.octave_separation)]
1726+
self.launchpads += [Launchpad(self, lp, "lpx", 1, self.options.octave_separation)]
17261727

17271728
if self.launchpads:
17281729
print('Launchpads:', len(self.launchpads))
17291730

17301731
self.done = False
17311732

17321733
for lp in self.launchpads:
1733-
if lp.mode == "lpx":
1734-
lp.out.LedCtrlXY(0, 0, 0, 0, 63)
1735-
lp.out.LedCtrlXY(1, 0, 0, 0, 63)
1736-
lp.out.LedCtrlXY(2, 0, 63, 0, 63)
1737-
lp.out.LedCtrlXY(3, 0, 63, 0, 63)
1734+
lp.set_lights()
17381735

17391736
# if self.launchpad:
17401737
# # use the alternate colors
@@ -1899,18 +1896,19 @@ def move_board(self, val):
18991896

19001897
aval = abs(val)
19011898
if aval > 1: # more than one shift
1902-
sval = sign(val)
1903-
for rpt in range(aval):
1904-
self.move_board(sval)
1905-
self.transpose += sval
1899+
assert False
1900+
# sval = sign(val)
1901+
# for rpt in range(aval):
1902+
# self.move_board(sval)
1903+
# self.position.x += sval
19061904
elif val == 1: # shift right (add column left)
19071905
for y in range(len(self.board)):
19081906
self.board[y] = [0] + self.board[y][:-1]
1909-
self.transpose += val
1907+
self.position.x += val
19101908
elif val == -1: # shift left (add column right)
19111909
for y in range(len(self.board)):
19121910
self.board[y] = self.board[y][1:] + [0]
1913-
self.transpose += val
1911+
self.position.x += val
19141912
self.dirty = self.dirty_lights = True
19151913

19161914
def quit(self):
@@ -2008,16 +2006,23 @@ def is_split(self):
20082006
return self.split_state and self.split_out
20092007

20102008
def set_tonic(self, val):
2011-
odd = (self.tonic % 2 == 1)
2009+
self.send_all_notes_off()
2010+
20122011
self.tonic = val
2013-
new_odd = (self.tonic % 2 == 1)
2014-
if odd != new_odd:
2015-
self.flipped = not self.flipped
2016-
if new_odd:
2017-
self.transpose = (self.tonic // 2 - 3) % 6
2018-
self.transpose -= 6
2019-
else:
2020-
self.transpose = (self.tonic // 2) % 6
2012+
# print('val', val)
2013+
# odd = (self.tonic % 2 == 1)
2014+
# self.tonic = val
2015+
# print('new tonic', self.tonic)
2016+
# new_odd = (self.tonic % 2 == 1)
2017+
# # if odd != new_odd:
2018+
# # self.flipped = not self.flipped
2019+
# if new_odd:
2020+
# self.position.x = (self.tonic // 2 - 3) % 6
2021+
# self.position.x -= 6
2022+
# else:
2023+
# self.position.x = (self.tonic // 2) % 6
2024+
# print('new pos', self.position.x)
2025+
20212026
self.dirty = self.dirty_lights = True
20222027

20232028
def logic(self, dt):
@@ -2127,10 +2132,10 @@ def logic(self, dt):
21272132
# self.dirty = True
21282133
elif ev.ui_element == self.btn_rotate:
21292134
if self.rotated:
2130-
self.transpose += 3
2135+
self.position.x += 3
21312136
self.rotated = False
21322137
else:
2133-
self.transpose -= 3
2138+
self.position.x -= 3
21342139
self.rotated = True
21352140
self.dirty = self.dirty_lights = True
21362141
self.clear_marks(use_lights=False)
@@ -2300,7 +2305,7 @@ def render(self):
23002305
x = 0
23012306
for cell in row:
23022307
# write text
2303-
note = self.get_note(x, y, False)
2308+
note = self.get_note(x, y, True)
23042309

23052310
split_chan = self.channel_from_split(x, y)
23062311

src/device.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,8 @@ class DeviceSettings:
99
bend: int
1010

1111
class Device:
12-
pass
12+
def __init__(self, core):
13+
self.core = core
14+
self.octave = 0
15+
self.transpose = 0
1316

0 commit comments

Comments
 (0)