Godtone (talk | contribs)
→My Python 3 code: FIX CODE!!! (and add new features)
Godtone (talk | contribs)
ADD NEW COLOURING MODE!!! (autorelative=True on all models but relative=True on Launchpad Pro MK3 only for now (will make applicable to all in future)). ALSO: (hopefully) fix highlighting subsets for nontrivial rainbows, add 33- & 37-colour rainbows for more completeness and add notes about likely duplicate factory colors/colours found
Line 1,541: Line 1,541:
rb36br = [45, 80, 69, 49, 81, 94, 53, 82, 95, 57, 58, 120] # len-1=11 53 or 82 to be removed for smoothness; 80 to be removed for distinctness
rb36br = [45, 80, 69, 49, 81, 94, 53, 82, 95, 57, 58, 120] # len-1=11 53 or 82 to be removed for smoothness; 80 to be removed for distinctness
rb36 = rb36ry[:-1] + rb36yg[:-1] + rb36gb[:-1] + rb36br[:-1] # maximal, but uneven, rainbow
rb36 = rb36ry[:-1] + rb36yg[:-1] + rb36gb[:-1] + rb36br[:-1] # maximal, but uneven, rainbow
rb37 = [6] + rb36
rb35 = [c for c in rb36 if c!=126]
rb35 = [c for c in rb36 if c!=126]
rb34 = [c for c in rb36 if c not in [61,62]]
rb34 = [c for c in rb36 if c not in [61,62]]
Line 1,552: Line 1,553:
rb31 = [120, 5] + rb30[1:]
rb31 = [120, 5] + rb30[1:]
rb32 = [c for c in rb34 if c not in [85,96]]
rb32 = [c for c in rb34 if c not in [85,96]]
rb33 = [c for c in rb34 if c!=85]
rb29 = [c for c in rb30 if c!=75]
rb29 = [c for c in rb30 if c!=75]
# 29 colours is a fairly ideal rainbow; we use it for indexing into, so as to derive a 17-colour palette.
# 29 colours is a fairly ideal rainbow; we use it for indexing into, so as to derive a 17-colour palette.
Line 1,564: Line 1,566:
rb25 = [c for c in rb26 if c!=74]
rb25 = [c for c in rb26 if c!=74]


colmaps = { 12: rb12, 13: rb13, 16: cm16, 17: rb17v2, 18: rb18, 19: rb19, 25: rb25, 26: rb26, 27: rb27, 28: rb28, 29: rb29, 30: rb30, 31: rb31, 32: rb32, 34: rb34, 35: rb35, 36: rb36 }
colmaps = { 12: rb12, 13: rb13, 16: cm16, 17: rb17v2, 18: rb18, 19: rb19, 25: rb25, 26: rb26, 27: rb27, 28: rb28, 29: rb29, 30: rb30, 31: rb31, 32: rb32, 33: rb33, 34: rb34, 35: rb35, 36: rb36, 37: rb37 }
# IMPORTANT: SUSPECTED DUPLICATE COLOURS: 45 = 67, 97 = 124, (a duplicate red i need to refind)
 


# for example, if you're using 34 EDO and you want a 1\2 = 17\34 period
# for example, if you're using 34 EDO and you want a 1\2 = 17\34 period
Line 1,628: Line 1,632:
# use the same midi/mido output (mo) for the entire session: (the port is opened when you import the library)
# use the same midi/mido output (mo) for the entire session: (the port is opened when you import the library)
mo = mido.open_output() if platform.system()!='Windows' else mido.open_output([ port for port in mido.get_output_names() if 'loop' in port ][0])
mo = mido.open_output() if platform.system()!='Windows' else mido.open_output([ port for port in mido.get_output_names() if 'loop' in port ][0])


# IMPORTANT: to highlight a scale, use [a,b,c,...,p] where p is the number of MIDI notes corresponding to your period and a>0.
# IMPORTANT: to highlight a scale, use [a,b,c,...,p] where p is the number of MIDI notes corresponding to your period and a>0.
# SEE: genindices() to generate a rank 2 scale and mode() to rotate an arbitrary scale.
# SEE: genindices() to generate a rank 2 scale and mode() to rotate an arbitrary scale.
def iso(x=5, y=1, colmap_in=[34], highlight=[], **args):
def iso(x=5, y=1, colmap_in=[34], highlight=[], **args):
autorelative = args.get('autorelative') or False
relative = args.get('relative') or autorelative
last_tuning_note = 0
global mo
global mo
colmap = colmap_in # make default value immutable
colmap = colmap_in # make default value immutable
Line 1,647: Line 1,655:
print('no colmap in colmaps for',colmap,'notes; using default colmap')
print('no colmap in colmaps for',colmap,'notes; using default colmap')
colmap = [4,5,6,7]
colmap = [4,5,6,7]
if highlight:
highlight = sorted(list(set(highlight)))
mul = math.lcm(len(colmap),highlight[-1])
colmap = [( colmap*mul )[i%len(colmap)] if i%highlight[-1] in [0]+highlight else 3 for i in range(mul)]
# get arguments with default values
# get arguments with default values
bottomleftnote = args.get('bottomleftnote') or args.get('blnote') or args.get('bl') or args.get('b') or 0 # WARNING: NOTE: used to be min(x,y) by default!
bottomleftnote = args.get('bottomleftnote') or args.get('blnote') or args.get('bl') or args.get('b') or 0 # WARNING: NOTE: used to be min(x,y) by default!
Line 1,684: Line 1,688:
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
colmap = circle(g,colmap)
colmap = circle(g,colmap)
if highlight: # highlight subset scale
                highlight = sorted(list(set(highlight)))
                mul = math.lcm(len(colmap),highlight[-1])
                colmap = [( colmap*mul )[i%len(colmap)] if i%highlight[-1] in [0]+highlight else 3 for i in range(mul)]
# find launchpad output (what we send colour (col) data to)
# find launchpad output (what we send colour (col) data to)
Line 1,725: Line 1,733:
note_state[transform(k)] = 0
note_state[transform(k)] = 0
shift_held = False
with mido.open_input(launchpad_mi) as mi, mido.open_output(launchpad_col) as col:
with mido.open_input(launchpad_mi) as mi, mido.open_output(launchpad_col) as col:
print('\ncolouring...')
print('\ncolouring...')
Line 1,731: Line 1,740:
note=k, velocity=colmap[ transform(k) % len(colmap) ]
note=k, velocity=colmap[ transform(k) % len(colmap) ]
))
))
print('starting midi event processing...')
print('starting midi event processing...')
# transform the launchpad's midi input (mi) into custom midi output (mo)
# transform the launchpad's midi input (mi) into custom midi output (mo)
Line 1,738: Line 1,748:
note_vel = 0
note_vel = 0
is_half_button = False
is_half_button = False
is_shift = False
if 'control' in str(msg):
if 'control' in str(msg):
key = msg.control
key = msg.control
note_vel = vel if msg.value else 0
note_vel = vel if msg.value else 0
is_half_button = msg.control > 100 or msg.control < 10
is_half_button = msg.control > 100 or msg.control < 10
is_shift = key==90
if is_shift:
shift_held = bool(note_vel)
elif str(msg).startswith('note'):
elif str(msg).startswith('note'):
key = msg.note
key = msg.note
Line 1,751: Line 1,765:
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)
print('tuning:',tuning_note,'midi:',midi_note)
if note_vel: # if we're pressing a key
if relative and (sum([ note_state[i] for i in note_state ])==0 and autorelative or shift_held):
last_tuning_note = tuning_note
# only in the situation where the last_tuning_note is set can the grid possibly be fully recoloured
if autorelative or shift_held:
for k in key_codes:
col.send(mido.Message( 'note_on', channel=0,
note=k, velocity=colmap[ (transform(k) - tuning_note) % len(colmap) ]
))
if note_vel and (not is_shift or not relative or relative and autorelative): # if we're pressing a key
note_vel = min(127,round( note_vel * 2**( -(tuning_note-bottomleftnote)/half ) ))
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
Line 1,771: Line 1,793:
if note_state[tuning_note]==0: # if we turn off all keys as a result... turn off
if note_state[tuning_note]==0: # if we turn off all keys as a result... turn off
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)
print('col='+str(colmap[ tuning_note % len(colmap) ]),to_send)
print('col='+str(colmap[ (tuning_note - last_tuning_note) % len(colmap) ]),to_send)
mo.send(to_send) # turn off equivalent midi note
mo.send(to_send) # turn off equivalent midi note
for k in key_codes:
for k in key_codes:
if transform(k)==tuning_note: # if equivalent... set key to unpressed col
if transform(k)==tuning_note: # if equivalent... set key to unpressed col
col.send(mido.Message('note_on', channel=0,
col.send(mido.Message('note_on', channel=0,
note=k, velocity=colmap[ transform(k) % len(colmap) ]
note=k, velocity=colmap[ (transform(k) - last_tuning_note) % len(colmap) ]
))
))
</syntaxhighlight>
</syntaxhighlight>