Пример #1
0
    def run(cycle: Cycle, note_duration, velocity, mode, channel):
        if mode is None:
            cycle.play_midi(note_duration=note_duration,
                            velocity=velocity,
                            channel=channel)
        elif mode == 'all':
            for i, m in enumerate(cycle.modes):
                if i != 0:
                    time.sleep(1)
                m.play_midi(note_duration=note_duration,
                            velocity=velocity,
                            channel=channel)
        else:
            try:
                mode_number = int(mode)
            except ValueError:
                raise ScaleTheoryError(
                    "Mode should be left blank, or be 'all' or an integer")

            try:
                m = cycle.modes[mode_number - 1]
            except ValueError:
                raise ScaleTheoryError(
                    f"Mode number too high (max {len(cycle.modes)})")

            m.play_midi(note_duration=note_duration,
                        velocity=velocity,
                        channel=channel)
Пример #2
0
def scale_info(cycle: Cycle):
    print(cycle.name())

    for mode in cycle.modes:
        print("unison    ", end="")
        for jump, ivl in zip(mode.jumps, mode.intervals()):
            print(f"-{jump}->  ", ivl.name().ljust(10), end="")

        print(f"-{mode.jumps[-1]}->  ", "p8")

    for ivl in cycle.canon_mode.intervals():
        print(ivl.cents(), end=", ")
    print()

    print(
        f"Consonant interval diversity: {count_present_consonances(cycle)}/{len(cycle.edo().consonances)}"
    )
    print("Total dissonances:", count_dissonances(cycle))
    print(cycle.interval_vector())
    print(
        "Total chords:", *[
            count_chords(cycle, [third])[third]
            for third in ["septimal m3", "m3", "n3", "maj3", "septimal maj3"]
        ])
    print("Total tetrachords:")
    for name, degrees in TETRACHORDS.items():
        if count_extensions(cycle, degrees) > 0:
            print(f"  {name}: {count_extensions(cycle, degrees)}")
    print("Proper:", proper(cycle))
    # TODO
    # print("MIDI notes:", ", ".join(map(midi_to_12edo_name, get_midi_numbers(cycle))))
    print()
Пример #3
0
def count_chords(cycle: Cycle, third_names: List[str]):
    fifth = cycle.edo().approximate(JI.by_name("p5"))
    chords = dict([(name, 0) for name in third_names])
    for mode in cycle.modes:
        if fifth in mode.interval_set():
            for name, third in zip(third_names, intervals_in_edo(cycle.edo(), third_names)):
                if third in mode.interval_set():
                    chords[name] += 1
    return chords
Пример #4
0
def count_distinct_chord_roots(cycle: Cycle, third_names: List[str]):
    fifth = cycle.edo().approximate(JI.by_name("p5"))
    total = 0
    for mode in cycle.modes:
        if fifth in mode.interval_set():
            for third in intervals_in_edo(cycle.edo(), third_names):
                if third in mode.interval_set():
                    total += 1
                    break
    return total
Пример #5
0
def resolve_cycle_name(edo_steps, cycle_name):
    cycle = Cycle.by_name(edo_steps, cycle_name)
    if cycle:
        return cycle
    else:
        try:
            jumps = [int(j) for j in cycle_name.replace(" ", "").split(",")]
        except ValueError:
            raise ScaleTheoryError(f"Not a known scale name or valid comma-separated list of integers: {cycle_name}")

        if sum(jumps) != edo_steps:
            raise ScaleTheoryError(f"Jumps should add to {edo_steps}, but actually add to {sum(jumps)}")
        return Cycle(jumps)
Пример #6
0
def print_family(parent: Cycle, lengths):
    subscales = parent.children()
    named_subscales = [c for c in subscales if c.name() is not None and c.size() in lengths]
    named_subscales.sort(key=lambda cycle: cycle.size())

    for scale in named_subscales:
        scale_info(scale)

    scale_info(parent)
Пример #7
0
def proper(cycle: Cycle):
    degrees = [set() for _ in range(cycle.size() - 1)]
    for mode in cycle.modes:
        for i, ivl in enumerate(mode.intervals()):
            degrees[i].add(ivl)

    not_strict = False
    for deg1, deg2 in zip(degrees[:-1], degrees[1:]):
        x, y = max(deg1), min(deg2)
        if x > y:
            return Proper.IMPROPER
        elif x == y:
            not_strict = True

    return Proper.PROPER if not_strict else Proper.STRICTLY_PROPER
Пример #8
0
    def run(length, edo_steps):
        t = Timer()

        computed_cycles = []
        num_computed_modes = {}
        for method in METHODS:
            method.cache_clear()
            t.task(method.__name__)
            modes = list(method(length, edo_steps))
            t.clear()
            computed_cycles.append(set([Cycle(mode) for mode in modes]))
            num_computed_modes[method.__name__] = len(modes)
            t.clear()

        for c in computed_cycles[1:]:
            # we want to make sure the algorithms produce the same end result
            assert c == computed_cycles[0]

        print(len(computed_cycles[0]), "cycles found.")
        print("Number of modes computed:")
        for method_name, num_modes in num_computed_modes.items():
            print(method_name, num_modes)

        t.log()
Пример #9
0
def count_by_name(cycle: Cycle, name: str):
    return cycle.interval_counts()[cycle.edo().approximate(JI.by_name(name))]
Пример #10
0
def count_dissonances(cycle: Cycle):
    return -sum([cycle.interval_counts().get(d, 0) for d in cycle.edo().dissonances])
Пример #11
0
def count_present_consonances(cycle: Cycle):
    return len(set(cycle.edo().consonances) & cycle.interval_set())
Пример #12
0
def count_extensions(cycle: Cycle, ivl_names: List[str]):
    total = 0
    for mode in cycle.modes:
        if all(ivl in mode.interval_set() for ivl in intervals_in_edo(cycle.edo(), ivl_names)):
            total += 1
    return total
Пример #13
0
def interval_diversity(cycle: Cycle, important_intervals: List[str] = None):
    intervals = cycle.interval_set()
    if important_intervals:
        intervals = intervals & intervals_in_edo(cycle.edo(), important_intervals)

    return len(intervals)
Пример #14
0
def list_best_subcycles(cycle: Cycle, priorities, length):
    list_best_cycles_from(cycle.children(length), priorities)