def mode_image(mode: Mode, fill: Colors = Colors.BLACK, background: Colors = Colors.TRANSPARENT): dot_radius = 10 radius = (mode.edo_steps() * dot_radius) / 2.5 padding = dot_radius * 2 image_side = round((radius + padding) * 2) img = Image.new('RGB', (image_side, image_side), color=background) draw = ImageDraw.Draw(img) step_angle = 2 * math.pi / mode.edo_steps() for i in range(mode.edo().steps): center_x = image_side // 2 + round(math.sin(step_angle * i) * radius) center_y = image_side // 2 - round(math.cos(step_angle * i) * radius) xy = [ center_x - dot_radius, center_y - dot_radius, center_x + dot_radius, center_y + dot_radius, ] draw.ellipse(xy=xy, fill=(fill if i == 0 or EDOInterval(i, mode.edo_steps()) in mode.intervals() else background), outline=Colors.BLACK, width=2) img.save(f"cycle {mode.edo_steps()}edo {mode.name()}.png")
def interval_counts(self): out = dict([(EDOInterval(steps, self.edo_steps()), 0) for steps in range(1, self.edo_steps())]) for mode in self.modes: for interval in mode.intervals(): out[interval] += 1 return out
def interval_vector(self): out = "< " current_degree = None counts = self.interval_counts() for i in range(1, self.edo_steps()//2 + 1): ivl = EDOInterval(i, self.edo_steps()) degree = ((ivl.cents() - 50) // 200) + 2 if degree != current_degree: current_degree = degree if i != 1: out += " | " else: out += "," out += str(counts[ivl]) return out + " >"
def genf(): mode = cycle.modes[randrange(cycle.size())] ivls = [] while len(ivls) < length: ivl = choice(mode.intervals()) if len(ivls) > 0: prev = ivls[-1] elif not progression: prev = EDOInterval(0, edo_steps) else: prev = None if prev is None or ( ivl != prev and abs(prev.cents() - ivl.cents()) <= max_leap): ivls.append(ivl) bass_note = get_bass_note(fixed_root, edo_steps) if progression: p4 = bass_note + EDOInterval.by_name("p4", edo_steps).steps p5 = bass_note + EDOInterval.by_name("p5", edo_steps).steps notes = [ EDOChord.by_name("major", edo_steps).invert(1).get_note_numbers( tonic_midi_number=p4), EDOChord.by_name("major", edo_steps).invert(1).get_note_numbers( tonic_midi_number=p5), EDOChord.by_name("major", edo_steps).get_note_numbers( tonic_midi_number=bass_note), (), ] else: notes = [(bass_note, )] notes += [(bass_note + ivl.steps, ) for ivl in ivls] answer = ",".join(ivl.name() for ivl in ivls) return answer, notes, midi_params
def genf(): interval = EDOInterval.by_name(choice(interval_names), edo_steps) bass_note = get_bass_note(fixed_root, edo_steps) answer = interval.name() if direction == "asc": notes = [(bass_note, ), (bass_note + interval.steps, )] elif direction == "desc": notes = [(bass_note + interval.steps, ), (bass_note, )] elif direction == "unison": notes = [( bass_note, bass_note + interval.steps, )] else: raise ValueError return answer, notes, midi_params
def genf(): mode_num = randrange(cycle.size()) mode = cycle.modes[mode_num] ivls = [] available_ivls = set(mode.intervals()) for i in range(groups): ivls.append(EDOInterval(0, edo_steps)) while len(ivls) < (i+1) * 4: if len(available_ivls) == 0: available_ivls = set(mode.intervals()) ivl = choice(list(available_ivls)) if ivl != ivls[-1]: ivls.append(ivl) available_ivls.remove(ivl) bass_note = get_bass_note(edo_steps) notes = [(bass_note + ivl.steps,) for ivl in ivls] answer = str(mode_num + 1) return answer, notes, midi_params
def get_note_numbers(self, *, bass_midi_number=None, tonic_midi_number=None): if bass_midi_number is not None and tonic_midi_number is None: return ( bass_midi_number, *[ bass_midi_number + ivl.steps for ivl in self.intervals() ] ) if bass_midi_number is None and tonic_midi_number is not None: tonic = self.intervals()[-self.inversion()] if self.inversion() != 0 else EDOInterval(0, self.edo_steps()) return self.get_note_numbers(bass_midi_number=tonic_midi_number - tonic.steps) raise ValueError("Exactly one of bass_midi_number and tonic_midi_number must be None")
def intervals(self): out = [self.jumps[0]] for jump in self.jumps[1:-1]: out.append(out[-1] + jump) return [EDOInterval(steps, self.edo_steps()) for steps in out]