Last active
November 23, 2022 01:23
-
-
Save Preinfarction/f1778cadf09b3faa715d599584c9a0e3 to your computer and use it in GitHub Desktop.
Septimal interval converter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import re | |
from fractions import Fraction | |
def ordinal_to_suffix(degree): | |
ds = str(degree) | |
if ds[-1] == "1": | |
if len(ds) > 1: | |
if ds[-2] == "1": | |
return "th" | |
return "st" | |
if ds[-1] == "2": | |
if len(ds) > 1: | |
if ds[-2] == "1": | |
return "th" | |
return "nd" | |
if ds[-1] == "3": | |
if len(ds) > 1: | |
if ds[-2] == "1": | |
return "th" | |
return "rd" | |
else: | |
return "th" | |
def interval_name_to_english(interval_string): | |
interval_string = re.sub(r"Sp", r"super-", interval_string) | |
interval_string = re.sub(r"Sb", r"sub-", interval_string) | |
interval_string = re.sub(r"Ac", r"acute ", interval_string) | |
interval_string = re.sub(r"Gr", r"grave ", interval_string) | |
interval_string = re.sub(r"m", r"minor ", interval_string) | |
interval_string = re.sub(r"d", r"diminished ", interval_string) | |
interval_string = re.sub(r"A", r"augmented ", interval_string) | |
interval_string = re.sub(r"M", r"major ", interval_string) | |
interval_string = re.sub(r"P", r"perfect ", interval_string) | |
return interval_string | |
def prime_basis_to_24_edo(prime_basis_interval): | |
p, q, r, s = prime_basis_interval | |
edo_divisions = (p * 24) + (q * 14) + (r * 8) + (s * 19) | |
return edo_divisions | |
def johnston_to_prime_basis(tuple): | |
l, m, n, o = tuple | |
p = 0*l + -2*m + 0*n + 1*o | |
q = 2*l + 4*m + -1*n + 0*o | |
r = -1*l - 1*m + 2*n - 3*o | |
s = -1*l + 0*m + 0*n + 0*o | |
new_tuple = (p, q, r, s) | |
return new_tuple | |
def interval_to_frequency_ratio(interval): | |
a, b, c, d = interval | |
#ratio = Fraction(64, 63) ** a * Fraction(81, 80) ** b * Fraction(25, 24) ** c * Fraction(128, 125) ** d # Leipzig | |
#ratio = Fraction(21, 20) ** a * Fraction(81, 80) ** b * Fraction(25, 24) ** c * Fraction(128, 125) ** d # Palatine | |
ratio = Fraction(36, 35) ** a * Fraction(81, 80) ** b * Fraction(25, 24) ** c * Fraction(128, 125) ** d # Johnston | |
return ratio | |
def pprint(interval_string): | |
interval_string = re.sub(r"dP", r"d", interval_string) | |
interval_string = re.sub(r"AP", r"A", interval_string) | |
interval_string = re.sub(r"SbP", r"Sb", interval_string) | |
interval_string = re.sub(r"SpP", r"Sp", interval_string) | |
interval_string = re.sub(r"GrP", r"Gr", interval_string) | |
interval_string = re.sub(r"AcP", r"Ac", interval_string) | |
interval_string = re.sub(r"dm", r"d", interval_string) | |
interval_string = re.sub(r"AM", r"A", interval_string) | |
return interval_string | |
def interval_difference(interval1, interval2): | |
interval_difference = (e1 - e2 for (e1, e2) in zip(interval1, interval2)) | |
return tuple(interval_difference) | |
def interval_sum(interval1, interval2): | |
interval_sum = (e1 + e2 for (e1, e2) in zip(interval1, interval2)) | |
return tuple(interval_sum) | |
def interval_to_quality(interval): | |
a, b, c, d = interval | |
if d >= 7: | |
return interval_to_quality(interval_difference((a, b, c, d), (0, 3, 12, 7))) | |
if d < 0: | |
return interval_to_quality(interval_sum((a, b, c, d), (0, 3, 12, 7))) | |
base_interval_to_quality = { | |
(0, 0, 0, 0): "P", | |
(0, 0, 1, 1): "m", | |
(0, 0, 2, 1): "M", | |
(0, 1, 3, 2): "m", | |
(0, 1, 4, 2): "M", | |
(0, 1, 5, 3): "P", | |
(0, 2, 7, 4): "P", | |
(0, 2, 8, 5): "m", | |
(0, 2, 9, 5): "M", | |
(0, 3, 10, 6): "m", | |
(0, 3, 11, 6): "M", | |
} | |
d_to_natural_gravity = { | |
0: 0, | |
1: 0, | |
2: 1, | |
3: 1, | |
4: 2, | |
5: 2, | |
6: 3, | |
} | |
if interval in base_interval_to_quality: | |
return base_interval_to_quality[interval] | |
if a < 0: | |
return "Sb" + interval_to_quality((a + 1, b, c, d)) | |
if a > 0: | |
return "Sp" + interval_to_quality((a - 1, b, c, d)) | |
natural_gravity = d_to_natural_gravity[d] | |
gravity_difference = b - natural_gravity | |
if gravity_difference < 0: | |
return "Gr" * abs(gravity_difference) + interval_to_quality((a, b - gravity_difference, c, d)) | |
if gravity_difference > 0: | |
return "Ac" * gravity_difference + interval_to_quality((a, b - gravity_difference, c, d)) | |
if d == 0: | |
if c < 0: | |
return "d" + interval_to_quality((a, b, c + 1, d)) | |
if c > 0: | |
return "A" + interval_to_quality((a, b, c - 1, d)) | |
if d == 1: | |
if c < 1: | |
return "d" + interval_to_quality((a, b, c + 1, d)) | |
if c > 2: | |
return "A" + interval_to_quality((a, b, c - 1, d)) | |
if d == 2: | |
if c < 3: | |
return "d" + interval_to_quality((a, b, c + 1, d)) | |
if c > 4: | |
return "A" + interval_to_quality((a, b, c - 1, d)) | |
if d == 3: | |
if c < 5: | |
return "d" + interval_to_quality((a, b, c + 1, d)) | |
if c > 5: | |
return "A" + interval_to_quality((a, b, c - 1, d)) | |
if d == 4: | |
if c < 7: | |
return "d" + interval_to_quality((a, b, c + 1, d)) | |
if c > 7: | |
return "A" + interval_to_quality((a, b, c - 1, d)) | |
if d == 5: | |
if c < 8: | |
return "d" + interval_to_quality((a, b, c + 1, d)) | |
if c > 9: | |
return "A" + interval_to_quality((a, b, c - 1, d)) | |
if d == 6: | |
if c < 10: | |
return "d" + interval_to_quality((a, b, c + 1, d)) | |
if c > 11: | |
return "A" + interval_to_quality((a, b, c - 1, d)) | |
intervals = [ | |
(0, 0, 0, 0), # unison | |
(0, 3, 12, 7), # octave | |
(0, 2, 7, 4), # perfect fifth | |
(0, 1, 4, 2), # major third | |
(-1, 3, 10, 6), # subminor seventh | |
(1, 4, 16, 10), | |
(1, 1, 3, 1), | |
(1, -1, 3, 2), | |
] | |
for interval in intervals: | |
(a, b, c, d) = interval | |
ordinal = interval[-1] + 1 | |
name = interval_to_quality(interval) + str(ordinal) | |
name = pprint(name) | |
frequency_ratio = interval_to_frequency_ratio(interval) | |
frequency = float(frequency_ratio) | |
prime_basis_interval = johnston_to_prime_basis(interval) | |
edo_divisions = prime_basis_to_24_edo(prime_basis_interval) | |
english_name = interval_name_to_english(name) + ordinal_to_suffix(ordinal) | |
print(name, "-", english_name) | |
print("Johnston basis:", list(interval)) | |
print("Reduced prime basis:", prime_basis_interval) | |
print("EDO value: 2^(" + str(edo_divisions) + "/24)", "=", 2 ** (edo_divisions / 24)) | |
print("7-limit value: " + str(frequency_ratio.numerator) + "/" + str(frequency_ratio.denominator), "=", frequency) | |
print() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment