def simple_transpose(c, full, interval, up): # determine whether can transpose by a full octave (only want to # transpose to nearest octave) # TODO: introduce recursive calls so track transposes itself # until it is within range, using full octave jumps unless # necessary to do half steps if (full): for i in range(len(c)): for j in range(len(c[i])): for k in range(len(c[i][j])): for l in range(len(c[i][j][k][2])): if (up): c[i][j][k][2][l].octave_up() else: c[i][j][k][2][l].octave_down() else: for i in range(len(c)): for j in range(len(c[i])): for k in range(len(c[i][j])): for l in range(len(c[i][j][k][2])): n = Note() if (up): c[i][j][k][2][l] = n.from_int(Note.__int__(c[i][j][k][2][l]) + interval) else: c[i][j][k][2][l] = n.from_int(Note.__int__(c[i][j][k][2][l]) - interval) ''' else: for i in range(len(c)): c[i] = c[i].transpose(interval, up) ''' return c
def notes_to_lsa_bin(notes, xylo, lsa_ordering): # convert to int so that sharps of one note and flat of next mean # the same thing keys = [ Note.__int__(Note(n)) for n in lsa_ordering ] vals = range(len(lsa_ordering)) # first lsa's note mapped to 0, second lsa's note mapped to 1, ... lsa_dict = dict(zip(keys, vals)) bnry = ['0'] * len(lsa_dict) for note in notes: # flip LSA to 'on' state for that note bnry[lsa_dict[Note.__int__(note)]] = '1' # so that number of leading zeros do not affect place of 'on' LSAs bnry.reverse() bnry = ''.join(bnry) # int whose binary represents the on and off states of all LSAs # at a given time combo = int(bnry, 2) return combo
def transposer(c, lowest, highest, xylo): ''' 5 cases: 1) lowest < xylo.range[0] and highest > xylo.range[1] 2) lowest < xylo.range[0] and highest < xylo.range[0] 3) lowest > xylo.range[1] and highest > xylo.range[1] 4) lowest < xylo.range[0] 5) highest > xylo.range[1] (1) definitely requires better_transpose (2) and (4) require better_transpose if highest + (xylo.range[0] - lowest) > xylo.range[1] (3) and (5) require better_transpose if lowest - (highest - xylo.range[1]) < xylo.range[0] ''' xylo_low = Note.__int__(xylo.range[0]) xylo_high = Note.__int__(xylo.range[1]) if (lowest < xylo_low and highest > xylo_high): c = better_transpose('foo', 'bar') elif (lowest < xylo_low): # minimum number of half steps to transpose by such that lowest # note in the entire composition is within the range of the # instrument interval = xylo_low - lowest if (highest + interval > xylo_high): c = better_transpose('foo', 'bar') else: # whether you can transpose a full octave full = False if (highest + interval + 12 <= xylo_high): full = True c = simple_transpose(c, full, interval, up = True) elif (highest > xylo_high): interval = highest - xylo_high if (lowest - interval < xylo_low): c = better_transpose('foo', 'bar') else: full = False if (lowest - interval - 12 >= xylo_low): full = True c = simple_transpose(c, full, interval, up = False) return c
def rebuild_composition(old, xylo, cutoff): lowest = Note.__int__(Note('C', 8)) highest = Note.__int__(Note('C', 0)) new = Composition() for i in old.selected_tracks: t = Track() t.instrument = xylo for bar in old[i]: b = Bar() b.key.name = bar.key.name b.set_meter(bar.meter) # note value per beat == the denominator in time signature dem = b.meter[1] for lst in bar: value = lst[1] if (is_garbage(value, dem, cutoff[old.selected_tracks.index(i)])): continue # do not include lists without notes if (not lst[2]): continue nc = NoteContainer() for note in lst[2]: if (Note.__int__(note) < lowest): lowest = Note.__int__(note) if (Note.__int__(note) > highest): highest = Note.__int__(note) nc + note b.place_notes(nc, value) t.add_bar(b) new.add_track(t) # can't do the transposing until all notes in all tracks have been # compared against lowest and highest, which is why it is done here n1 = Note() n2 = Note() low = n1.from_int(lowest) high = n2.from_int(highest) # print("lowest and highest notes:", low, high) if (not xylo.notes_in_range([low, high])): new = transposer(new, lowest, highest, xylo) return new