Godtone
Joined 17 December 2020
→Isomorphic keyboard code for launchpads with programmer mode: fix error caused by velocity going out of [0, 127] range, add a way to manually specify the midi in and midi out to use for Launchpad X, and add the ability to consider half-buttons as distinct pitches |
|||
| Line 1,469: | Line 1,469: | ||
or 1 ) # minimum velocity required (else ignored) | or 1 ) # minimum velocity required (else ignored) | ||
half = args.get('half') or args.get('h') or 40 # how many midi notes to go up from bottomleft before the velocity is halved | half = args.get('half') or args.get('h') or 40 # how many midi notes to go up from bottomleft before the velocity is halved | ||
extra = args.get('extra') or args.get('eleven') or False # whether to consider half-buttons as distinct notes of an uneven 10x11 grid on Launchpad Pro MK3 (off by default as weird to play with) | |||
# these are for if you want or need to keep the colour mapping distinct from the midi notes EG in large EDO subsets | # these are for if you want or need to keep the colour mapping distinct from the midi notes EG in large EDO subsets | ||
large = args.get('large') or (not args.get('small') and max(x*9+y*8,x*8+y*9) > 127) or False | large = args.get('large') or (not args.get('small') and max(x*9+y*8,x*8+y*9) > 127) or False | ||
coverage = 10 # | coverage = 10 # probably shouldn't mess with this unless you know what you're doing | ||
if large: | if large: | ||
print('WARNING: the midi note range of your layout is too large, so x=1, y='+str(coverage)+'=c=coverage is being used.') | print('WARNING: the midi note range of your layout is too large, so x=1, y='+str(coverage)+'=c=coverage is being used.') | ||
| Line 1,489: | Line 1,490: | ||
distinct_half_buttons = ( args.get('distinct_half_buttons') or args.get('distinct_halves') | distinct_half_buttons = ( args.get('distinct_half_buttons') or args.get('distinct_halves') | ||
or args.get('distinct_buttons') or args.get('distinct') or args.get('d') # (d for double) | or args.get('distinct_buttons') or args.get('distinct') or args.get('d') # (d for double) | ||
or False ) # whether to interpret the half-buttons as being two buttons for the same note or a single button | or False ) # whether to interpret the half-buttons as being two buttons for the same note or a single button (off by default as weird to play with) | ||
# generate circle of nths based on gen | # generate circle of nths based on gen | ||
g = args.get('g') or args.get('gen') or args.get('similar') or 1 | g = args.get('g') or args.get('gen') or args.get('similar') or 1 | ||
| Line 1,500: | Line 1,501: | ||
print(i) | print(i) | ||
print('selecting:') | print('selecting:') | ||
launchpad_col = [i for i in midi_outputs if lpselect(i)][0] | |||
print(launchpad_col) | print(launchpad_col) | ||
# find launchpad input (what we get midi input (mi) data from) | # find launchpad input (what we get midi input (mi) data from) | ||
| Line 1,510: | Line 1,509: | ||
print(i) | print(i) | ||
print('selecting:') | print('selecting:') | ||
launchpad_mi = [i for i in midi_inputs if lpselect(i)][0] | |||
print(launchpad_mi) | print(launchpad_mi) | ||
| Line 1,518: | Line 1,515: | ||
def transform(midi_note): | def transform(midi_note): | ||
if midi_note < 100: | if midi_note < 100: | ||
return midi_note%10 * x + midi_note//10 * y + bottomleftnote | return midi_note%10 * x + midi_note//10 * y + bottomleftnote + (10 if extra else 0) | ||
else: | else: | ||
return (midi_note - 100) * x + bottomleftnote | return (midi_note - 100) * x + bottomleftnote | ||
def get_midi_note(midi_note): | def get_midi_note(midi_note): | ||
if extra and midi_note < 10: | |||
return midi_note # bottom row of half buttons has correct mapping already | |||
if midi_note < 100: | if midi_note < 100: | ||
return midi_note%10 + midi_note//10 * coverage | return midi_note%10 + midi_note//10 * coverage + (10 if extra else 0) | ||
else: | else: | ||
return midi_note - 100 | return midi_note - 100 + (10 if extra else 0) | ||
key_codes = range(1,109) # includes a few key codes not corresponding to anything on launchpads but shouldn't be an issue. | key_codes = range(1,109) # includes a few key codes not corresponding to anything on launchpads but shouldn't be an issue. | ||
| Line 1,557: | Line 1,556: | ||
tuning_note = transform(key) | tuning_note = transform(key) | ||
midi_note = get_midi_note(key) if large else tuning_note | midi_note = get_midi_note(key) if large else tuning_note | ||
print('tuning:',tuning_note,'midi:',midi_note) | |||
if note_vel: # if we're pressing a key | if note_vel: # if we're pressing a key | ||
note_vel = round( note_vel * 2**( -( | note_vel = min(127,round( note_vel * 2**( -(tuning_note-bottomleftnote)/half ) )) | ||
if note_state[tuning_note]: # if one or more equivalent keys are already held | if note_state[tuning_note]: # if one or more equivalent keys are already held | ||
to_send = mido.Message('note_on', channel=0, note=midi_note, velocity=0) | to_send = mido.Message('note_on', channel=0, note=midi_note, velocity=0) | ||