コード例 #1
0
ファイル: cycle.py プロジェクト: cstuartroe/scale-theory
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")
コード例 #2
0
ファイル: scales.py プロジェクト: cstuartroe/scale-theory
    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
コード例 #3
0
ファイル: scales.py プロジェクト: cstuartroe/scale-theory
    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 + " >"
コード例 #4
0
        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
コード例 #5
0
        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
コード例 #6
0
ファイル: mode_quiz.py プロジェクト: cstuartroe/scale-theory
        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
コード例 #7
0
ファイル: scales.py プロジェクト: cstuartroe/scale-theory
    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")
コード例 #8
0
ファイル: scales.py プロジェクト: cstuartroe/scale-theory
 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]