1TONE_INDEX_DICT = {"C" : 0, "C#" : 1, "D" : 2, "D#" : 3, "E" : 4, "F" : 5, "F#" : 6, "G" : 7, "G#" : 8, "A" : 9, "A#" : 10, "B" : 11}
2TONE_VALUE_LIST = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]
3INTERVAL_VALUE_LIST = ["unison", "minor 2nd", "major 2nd", "minor 3rd", "major 3rd", "perfect 4th", "diminished 5th", "perfect 5th", "minor 6th", "major 6th", "minor 7th", "major 7th"]
4MAX_INDEX = 12
5
6class Tone:
7 def __init__(self, name):
8 self.name = name
9
10 def __str__(self):
11 return self.name
12
13 def __add__(self, other):
14 if isinstance(other, Tone):
15 return Chord(self, other)
16 if isinstance(other, Interval):
17 total_len = other.lenght + self.index
18 correct_index = int(total_len / MAX_INDEX)
19 correct_len = total_len - correct_index*MAX_INDEX
20 return Tone(TONE_VALUE_LIST[correct_len])
21
22 def __sub__(self, other):
23 if isinstance(other, Tone):
24 len = self.index - other.index
25 if self.index < other.index:
26 len = self.index + MAX_INDEX - other.index
27 return Interval(len)
28 if isinstance(other, Interval):
29 wanted_index = self.index - other.lenght
30 if self.index < other.lenght:
31 wanted_index = self.index - other.lenght + MAX_INDEX
32 return TONE_VALUE_LIST[wanted_index]
33
34 @property
35 def index(self):
36 return TONE_INDEX_DICT[self.name]
37
38class Interval:
39 def __init__(self, lenght):
40 correct_index = int(lenght / MAX_INDEX)
41 self.lenght = lenght - correct_index*MAX_INDEX
42
43 def __str__(self):
44 return INTERVAL_VALUE_LIST[self.lenght]
45
46 def __add__(self,other):
47 if isinstance(other,Tone):
48 raise TypeError("Invalid operation")
49 if isinstance(other,Interval):
50 total_len = self.lenght + other.lenght
51 correct_index = int(total_len / MAX_INDEX)
52 correct_len = total_len - correct_index*MAX_INDEX
53 return INTERVAL_VALUE_LIST[correct_len]
54
55 def __sub__(self,other):
56 if isinstance(other,Tone):
57 raise TypeError("Invalid operation")
58
59 def __neg__(self):
60 return Interval(MAX_INDEX - self.lenght)
61
62class Chord:
63 def __init_sorted_tones(self):
64 main_index = self.main_tone.index
65 tones_dict = {self.main_tone.name : main_index}
66 self.all_tones_list_objs = [self.main_tone]
67 for tone_name in self.unique_tones:
68 tone_index = Tone(tone_name).index
69 self.without_main_tones_list_objs.append(Tone(tone_name))
70 self.all_tones_list_objs.append(Tone(tone_name))
71 if main_index > tone_index:
72 tones_dict[tone_name] = tone_index + MAX_INDEX
73 else:
74 tones_dict[tone_name] = tone_index
75 self.sorted_tones = [key for key, value in sorted(tones_dict.items(), key=lambda item: item[1])]
76
77 def __init__(self, main_tone, *tones):
78 self.main_tone = main_tone
79 self.unique_tones= set()
80 self.sorted_tones = []
81 self.all_tones_list_objs = []
82 self.without_main_tones_list_objs = []
83 self.unique_tones.add(main_tone.name)
84 for tone in tones:
85 self.unique_tones.add(tone.name)
86 valid_len = len(self.unique_tones)
87 if valid_len <= 1:
88 raise TypeError("Cannot have a chord made of only 1 unique tone")
89 self.unique_tones.discard(main_tone.name)
90 self.__init_sorted_tones()
91
92 def __add__(self, other):
93 new_tones = self.without_main_tones_list_objs
94 if isinstance(other, Tone):
95 new_tones.append(other)
96 if isinstance(other,Chord):
97 for tone in other.all_tones_list_objs:
98 new_tones.append(tone)
99 return Chord(self.main_tone, *new_tones)
100
101 def __sub__(self, other):
102 if other.name not in self.sorted_tones:
103 raise TypeError(f"Cannot remove tone {other.name} from chord {self}")
104 if len(self.unique_tones) < 2:
105 raise TypeError("Cannot have a chord made of only 1 unique tone")
106 new_tones = self.without_main_tones_list_objs
107 main_tone = self.main_tone
108 if isinstance(other, Tone):
109 if main_tone.name == other.name:
110 main_tone = self.without_main_tones_list_objs[0]
111 new_tones = filter(lambda tone: tone.name != main_tone.name, new_tones)
112 else:
113 new_tones = filter(lambda tone: tone.name != other.name, new_tones)
114 return Chord(main_tone, *new_tones)
115
116 def __str__(self):
117 return "-".join(self.sorted_tones)
118
119 def is_minor(self):
120 for tone in self.without_main_tones_list_objs:
121 interval = tone - self.main_tone
122 if str(interval) == "minor 3rd":
123 return True
124 return False
125
126 def is_major(self):
127 for tone in self.without_main_tones_list_objs:
128 interval = tone - self.main_tone
129 if str(interval) == "major 3rd":
130 return True
131 return False
132
133 def is_power_chord(self):
134 return not self.is_major() and not self.is_minor()
135
136 def transposed(self, interval):
137 transposed_tones = [tone + interval for tone in self.all_tones_list_objs]
138 return Chord(transposed_tones[0], *transposed_tones[1:])
........................FFF.FF.......
======================================================================
FAIL: test_interval_addition (test.TestOperations.test_interval_addition)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 240, in test_interval_addition
self.assertIsInstance(major_3rd, Interval)
AssertionError: 'major 3rd' is not an instance of <class 'solution.Interval'>
======================================================================
FAIL: test_interval_addition_overflow (test.TestOperations.test_interval_addition_overflow)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 246, in test_interval_addition_overflow
self.assertIsInstance(unison, Interval)
AssertionError: 'unison' is not an instance of <class 'solution.Interval'>
======================================================================
FAIL: test_subtract_interval_from_tone (test.TestOperations.test_subtract_interval_from_tone)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 216, in test_subtract_interval_from_tone
self.assertIsInstance(f_sharp, Tone)
AssertionError: 'F#' is not an instance of <class 'solution.Tone'>
======================================================================
FAIL: test_subtract_interval_from_tone_oveflow (test.TestOperations.test_subtract_interval_from_tone_oveflow)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 228, in test_subtract_interval_from_tone_oveflow
self.assertIsInstance(g, Tone)
AssertionError: 'G' is not an instance of <class 'solution.Tone'>
======================================================================
FAIL: test_subtract_interval_from_tone_same_tone (test.TestOperations.test_subtract_interval_from_tone_same_tone)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 222, in test_subtract_interval_from_tone_same_tone
self.assertIsInstance(still_g, Tone)
AssertionError: 'G' is not an instance of <class 'solution.Tone'>
----------------------------------------------------------------------
Ran 37 tests in 0.002s
FAILED (failures=5)
Виктор Бечев
06.11.2024 13:34Търсим интервалът между двата, релативен спрямо основния тон. Как ще го имплементираш зависи от теб, но `tone - main_tone` ми звучи правилно.
|
Дейвид Барух
05.11.2024 22:28Един последен дразнещ въпрос, при мажорите вадим от тона roota нали, за да намерим разстоянитето между тях . Демек (tone - main_tone)
|
Дейвид Барух
05.11.2024 16:08Да разбрах на обратно от мойте разбирания е. Разстоянието примерно А-С е разстоянието между С и А
|
Виктор Бечев
05.11.2024 15:24Добре, разбирам от къде идва объркването.
Все пак - спазвай примера от по-долу, където съм ти дал за `A-C` и `C-A`. Приеми го за аксиома, ако го смяташ за неинтуитивно.
|
Дейвид Барух
05.11.2024 11:06Не сър на примера не е C -G 😂😂 a e G -C демек от G до C e g#,a,a#,b,c, поне аз схващам че G-C e разстоянието от G до C освен ако не визирате обратното
|
Виктор Бечев
05.11.2024 10:32
- 0 - unison
- 1 - minor 2nd
- 2 - major 2nd
- 3 - minor 3rd
- 4 - major 3rd
- 5 - perfect 4th
- 6 - diminished 5th
- **7 - perfect 5th**
- 8 - minor 6th
- 9 - major 6th
- 10 - minor 7th
- 11 - major 7th
|
Дейвид Барух
05.11.2024 00:06е то на примера е G-C сър, c, g = Tone("C"), Tone("G"); interval = g - c, трябва да е perfect 4th
|
Виктор Бечев
04.11.2024 23:00Полутоновете между G и C са 5. Между C и G са 7.
Ако си представиш, че всеки тон си има индекс, ако C е с индекс 0, то G би било с индекс 7. `g - c` -> 7. 7 полутона разстояние е `"perfect 5th"`.
|
Дейвид Барух
04.11.2024 18:14тук не е ли perfect 4th защото полутоновете между C и G са 5 : c, g = Tone("C"), Tone("G")
result_interval = g - c # result_interval е обект от тип Interval
print(result_interval) "perfect 5th"
|
Виктор Бечев
04.11.2024 18:11Да. Но с посока, а не абсолютна стойност.
Затова между A и C имаме 3 полутона, а между C и A - 9.
Ако говорим за операция изваждане - `A-C=9`, `C-A=3`.
|
Дейвид Барух
04.11.2024 17:12Извинявай, но се обърках малко. Разстоянието(боря полутонове) между два тона е разликата им нали?
|
Виктор Бечев
04.11.2024 16:14Имаме цикличност, но имаме и релативност спрямо основния тон. Разстоянието между A и C е 3 полутона _(A#, B, C)_, но между C и А _(в случай, когато root е C)_ - 9 полутона.
С други думи за F#-D-E имаме 8 полутона между F# и D.
|
Дейвид Барух
04.11.2024 15:45демек така както го правя сега е грешно?
|
Дейвид Барух
04.11.2024 15:43и за разлика на тонове приерно А-C ще се даде 2 не 9 , защото си поддържаме цикличност?
|
Дейвид Барух
04.11.2024 15:38за ismajor и isminor ако имаме нещо от сорта F#-D-E , то тогава за разстоянието между F# и D примерно приемаме че имаме 4 или 9 демек да се продължваме по цикъла един вид ?
|
Виктор Бечев
03.11.2024 21:19Да, интервалите са циклични.
|
Дейвид Барух
03.11.2024 14:21За интервалите имали също цикличност примерно за последния пример да дадем : d_minor_chord = c_minor_chord.transposed(Interval(20)) то да се приеме като Interval(8)?
|
| f | 1 | TONE_INDEX_DICT = {"C" : 0, "C#" : 1, "D" : 2, "D#" : 3, "E" : 4, "F" : 5, "F#" : 6, "G" : 7, "G#" : 8, "A" : 9, "A#" : 10, "B" : 11} | f | 1 | TONE_INDEX_DICT = {"C" : 0, "C#" : 1, "D" : 2, "D#" : 3, "E" : 4, "F" : 5, "F#" : 6, "G" : 7, "G#" : 8, "A" : 9, "A#" : 10, "B" : 11} |
| 2 | TONE_VALUE_LIST = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"] | 2 | TONE_VALUE_LIST = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"] | ||
| 3 | INTERVAL_VALUE_LIST = ["unison", "minor 2nd", "major 2nd", "minor 3rd", "major 3rd", "perfect 4th", "diminished 5th", "perfect 5th", "minor 6th", "major 6th", "minor 7th", "major 7th"] | 3 | INTERVAL_VALUE_LIST = ["unison", "minor 2nd", "major 2nd", "minor 3rd", "major 3rd", "perfect 4th", "diminished 5th", "perfect 5th", "minor 6th", "major 6th", "minor 7th", "major 7th"] | ||
| 4 | MAX_INDEX = 12 | 4 | MAX_INDEX = 12 | ||
| 5 | 5 | ||||
| 6 | class Tone: | 6 | class Tone: | ||
| 7 | def __init__(self, name): | 7 | def __init__(self, name): | ||
| 8 | self.name = name | 8 | self.name = name | ||
| 9 | 9 | ||||
| 10 | def __str__(self): | 10 | def __str__(self): | ||
| 11 | return self.name | 11 | return self.name | ||
| 12 | 12 | ||||
| 13 | def __add__(self, other): | 13 | def __add__(self, other): | ||
| 14 | if isinstance(other, Tone): | 14 | if isinstance(other, Tone): | ||
| 15 | return Chord(self, other) | 15 | return Chord(self, other) | ||
| 16 | if isinstance(other, Interval): | 16 | if isinstance(other, Interval): | ||
| 17 | total_len = other.lenght + self.index | 17 | total_len = other.lenght + self.index | ||
| 18 | correct_index = int(total_len / MAX_INDEX) | 18 | correct_index = int(total_len / MAX_INDEX) | ||
| 19 | correct_len = total_len - correct_index*MAX_INDEX | 19 | correct_len = total_len - correct_index*MAX_INDEX | ||
| 20 | return Tone(TONE_VALUE_LIST[correct_len]) | 20 | return Tone(TONE_VALUE_LIST[correct_len]) | ||
| 21 | 21 | ||||
| 22 | def __sub__(self, other): | 22 | def __sub__(self, other): | ||
| 23 | if isinstance(other, Tone): | 23 | if isinstance(other, Tone): | ||
| n | 24 | # len = other.index - self.index | n | ||
| 25 | # if self.index > other.index: | ||||
| 26 | # len = other.index + MAX_INDEX - self.index | ||||
| 27 | # return Interval(len) | ||||
| 28 | len = self.index - other.index | 24 | len = self.index - other.index | ||
| 29 | if self.index < other.index: | 25 | if self.index < other.index: | ||
| 30 | len = self.index + MAX_INDEX - other.index | 26 | len = self.index + MAX_INDEX - other.index | ||
| 31 | return Interval(len) | 27 | return Interval(len) | ||
| 32 | if isinstance(other, Interval): | 28 | if isinstance(other, Interval): | ||
| 33 | wanted_index = self.index - other.lenght | 29 | wanted_index = self.index - other.lenght | ||
| 34 | if self.index < other.lenght: | 30 | if self.index < other.lenght: | ||
| 35 | wanted_index = self.index - other.lenght + MAX_INDEX | 31 | wanted_index = self.index - other.lenght + MAX_INDEX | ||
| 36 | return TONE_VALUE_LIST[wanted_index] | 32 | return TONE_VALUE_LIST[wanted_index] | ||
| 37 | 33 | ||||
| 38 | @property | 34 | @property | ||
| 39 | def index(self): | 35 | def index(self): | ||
| 40 | return TONE_INDEX_DICT[self.name] | 36 | return TONE_INDEX_DICT[self.name] | ||
| 41 | 37 | ||||
| 42 | class Interval: | 38 | class Interval: | ||
| 43 | def __init__(self, lenght): | 39 | def __init__(self, lenght): | ||
| 44 | correct_index = int(lenght / MAX_INDEX) | 40 | correct_index = int(lenght / MAX_INDEX) | ||
| 45 | self.lenght = lenght - correct_index*MAX_INDEX | 41 | self.lenght = lenght - correct_index*MAX_INDEX | ||
| 46 | 42 | ||||
| 47 | def __str__(self): | 43 | def __str__(self): | ||
| t | 48 | print(f"len is {self.lenght}") | t | ||
| 49 | return INTERVAL_VALUE_LIST[self.lenght] | 44 | return INTERVAL_VALUE_LIST[self.lenght] | ||
| 50 | 45 | ||||
| 51 | def __add__(self,other): | 46 | def __add__(self,other): | ||
| 52 | if isinstance(other,Tone): | 47 | if isinstance(other,Tone): | ||
| 53 | raise TypeError("Invalid operation") | 48 | raise TypeError("Invalid operation") | ||
| 54 | if isinstance(other,Interval): | 49 | if isinstance(other,Interval): | ||
| 55 | total_len = self.lenght + other.lenght | 50 | total_len = self.lenght + other.lenght | ||
| 56 | correct_index = int(total_len / MAX_INDEX) | 51 | correct_index = int(total_len / MAX_INDEX) | ||
| 57 | correct_len = total_len - correct_index*MAX_INDEX | 52 | correct_len = total_len - correct_index*MAX_INDEX | ||
| 58 | return INTERVAL_VALUE_LIST[correct_len] | 53 | return INTERVAL_VALUE_LIST[correct_len] | ||
| 59 | 54 | ||||
| 60 | def __sub__(self,other): | 55 | def __sub__(self,other): | ||
| 61 | if isinstance(other,Tone): | 56 | if isinstance(other,Tone): | ||
| 62 | raise TypeError("Invalid operation") | 57 | raise TypeError("Invalid operation") | ||
| 63 | 58 | ||||
| 64 | def __neg__(self): | 59 | def __neg__(self): | ||
| 65 | return Interval(MAX_INDEX - self.lenght) | 60 | return Interval(MAX_INDEX - self.lenght) | ||
| 66 | 61 | ||||
| 67 | class Chord: | 62 | class Chord: | ||
| 68 | def __init_sorted_tones(self): | 63 | def __init_sorted_tones(self): | ||
| 69 | main_index = self.main_tone.index | 64 | main_index = self.main_tone.index | ||
| 70 | tones_dict = {self.main_tone.name : main_index} | 65 | tones_dict = {self.main_tone.name : main_index} | ||
| 71 | self.all_tones_list_objs = [self.main_tone] | 66 | self.all_tones_list_objs = [self.main_tone] | ||
| 72 | for tone_name in self.unique_tones: | 67 | for tone_name in self.unique_tones: | ||
| 73 | tone_index = Tone(tone_name).index | 68 | tone_index = Tone(tone_name).index | ||
| 74 | self.without_main_tones_list_objs.append(Tone(tone_name)) | 69 | self.without_main_tones_list_objs.append(Tone(tone_name)) | ||
| 75 | self.all_tones_list_objs.append(Tone(tone_name)) | 70 | self.all_tones_list_objs.append(Tone(tone_name)) | ||
| 76 | if main_index > tone_index: | 71 | if main_index > tone_index: | ||
| 77 | tones_dict[tone_name] = tone_index + MAX_INDEX | 72 | tones_dict[tone_name] = tone_index + MAX_INDEX | ||
| 78 | else: | 73 | else: | ||
| 79 | tones_dict[tone_name] = tone_index | 74 | tones_dict[tone_name] = tone_index | ||
| 80 | self.sorted_tones = [key for key, value in sorted(tones_dict.items(), key=lambda item: item[1])] | 75 | self.sorted_tones = [key for key, value in sorted(tones_dict.items(), key=lambda item: item[1])] | ||
| 81 | 76 | ||||
| 82 | def __init__(self, main_tone, *tones): | 77 | def __init__(self, main_tone, *tones): | ||
| 83 | self.main_tone = main_tone | 78 | self.main_tone = main_tone | ||
| 84 | self.unique_tones= set() | 79 | self.unique_tones= set() | ||
| 85 | self.sorted_tones = [] | 80 | self.sorted_tones = [] | ||
| 86 | self.all_tones_list_objs = [] | 81 | self.all_tones_list_objs = [] | ||
| 87 | self.without_main_tones_list_objs = [] | 82 | self.without_main_tones_list_objs = [] | ||
| 88 | self.unique_tones.add(main_tone.name) | 83 | self.unique_tones.add(main_tone.name) | ||
| 89 | for tone in tones: | 84 | for tone in tones: | ||
| 90 | self.unique_tones.add(tone.name) | 85 | self.unique_tones.add(tone.name) | ||
| 91 | valid_len = len(self.unique_tones) | 86 | valid_len = len(self.unique_tones) | ||
| 92 | if valid_len <= 1: | 87 | if valid_len <= 1: | ||
| 93 | raise TypeError("Cannot have a chord made of only 1 unique tone") | 88 | raise TypeError("Cannot have a chord made of only 1 unique tone") | ||
| 94 | self.unique_tones.discard(main_tone.name) | 89 | self.unique_tones.discard(main_tone.name) | ||
| 95 | self.__init_sorted_tones() | 90 | self.__init_sorted_tones() | ||
| 96 | 91 | ||||
| 97 | def __add__(self, other): | 92 | def __add__(self, other): | ||
| 98 | new_tones = self.without_main_tones_list_objs | 93 | new_tones = self.without_main_tones_list_objs | ||
| 99 | if isinstance(other, Tone): | 94 | if isinstance(other, Tone): | ||
| 100 | new_tones.append(other) | 95 | new_tones.append(other) | ||
| 101 | if isinstance(other,Chord): | 96 | if isinstance(other,Chord): | ||
| 102 | for tone in other.all_tones_list_objs: | 97 | for tone in other.all_tones_list_objs: | ||
| 103 | new_tones.append(tone) | 98 | new_tones.append(tone) | ||
| 104 | return Chord(self.main_tone, *new_tones) | 99 | return Chord(self.main_tone, *new_tones) | ||
| 105 | 100 | ||||
| 106 | def __sub__(self, other): | 101 | def __sub__(self, other): | ||
| 107 | if other.name not in self.sorted_tones: | 102 | if other.name not in self.sorted_tones: | ||
| 108 | raise TypeError(f"Cannot remove tone {other.name} from chord {self}") | 103 | raise TypeError(f"Cannot remove tone {other.name} from chord {self}") | ||
| 109 | if len(self.unique_tones) < 2: | 104 | if len(self.unique_tones) < 2: | ||
| 110 | raise TypeError("Cannot have a chord made of only 1 unique tone") | 105 | raise TypeError("Cannot have a chord made of only 1 unique tone") | ||
| 111 | new_tones = self.without_main_tones_list_objs | 106 | new_tones = self.without_main_tones_list_objs | ||
| 112 | main_tone = self.main_tone | 107 | main_tone = self.main_tone | ||
| 113 | if isinstance(other, Tone): | 108 | if isinstance(other, Tone): | ||
| 114 | if main_tone.name == other.name: | 109 | if main_tone.name == other.name: | ||
| 115 | main_tone = self.without_main_tones_list_objs[0] | 110 | main_tone = self.without_main_tones_list_objs[0] | ||
| 116 | new_tones = filter(lambda tone: tone.name != main_tone.name, new_tones) | 111 | new_tones = filter(lambda tone: tone.name != main_tone.name, new_tones) | ||
| 117 | else: | 112 | else: | ||
| 118 | new_tones = filter(lambda tone: tone.name != other.name, new_tones) | 113 | new_tones = filter(lambda tone: tone.name != other.name, new_tones) | ||
| 119 | return Chord(main_tone, *new_tones) | 114 | return Chord(main_tone, *new_tones) | ||
| 120 | 115 | ||||
| 121 | def __str__(self): | 116 | def __str__(self): | ||
| 122 | return "-".join(self.sorted_tones) | 117 | return "-".join(self.sorted_tones) | ||
| 123 | 118 | ||||
| 124 | def is_minor(self): | 119 | def is_minor(self): | ||
| 125 | for tone in self.without_main_tones_list_objs: | 120 | for tone in self.without_main_tones_list_objs: | ||
| 126 | interval = tone - self.main_tone | 121 | interval = tone - self.main_tone | ||
| 127 | if str(interval) == "minor 3rd": | 122 | if str(interval) == "minor 3rd": | ||
| 128 | return True | 123 | return True | ||
| 129 | return False | 124 | return False | ||
| 130 | 125 | ||||
| 131 | def is_major(self): | 126 | def is_major(self): | ||
| 132 | for tone in self.without_main_tones_list_objs: | 127 | for tone in self.without_main_tones_list_objs: | ||
| 133 | interval = tone - self.main_tone | 128 | interval = tone - self.main_tone | ||
| 134 | if str(interval) == "major 3rd": | 129 | if str(interval) == "major 3rd": | ||
| 135 | return True | 130 | return True | ||
| 136 | return False | 131 | return False | ||
| 137 | 132 | ||||
| 138 | def is_power_chord(self): | 133 | def is_power_chord(self): | ||
| 139 | return not self.is_major() and not self.is_minor() | 134 | return not self.is_major() and not self.is_minor() | ||
| 140 | 135 | ||||
| 141 | def transposed(self, interval): | 136 | def transposed(self, interval): | ||
| 142 | transposed_tones = [tone + interval for tone in self.all_tones_list_objs] | 137 | transposed_tones = [tone + interval for tone in self.all_tones_list_objs] | ||
| 143 | return Chord(transposed_tones[0], *transposed_tones[1:]) | 138 | return Chord(transposed_tones[0], *transposed_tones[1:]) | ||
| 144 | 139 |
| Legends | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
| |||||||||
| f | 1 | TONE_INDEX_DICT = {"C" : 0, "C#" : 1, "D" : 2, "D#" : 3, "E" : 4, "F" : 5, "F#" : 6, "G" : 7, "G#" : 8, "A" : 9, "A#" : 10, "B" : 11} | f | 1 | TONE_INDEX_DICT = {"C" : 0, "C#" : 1, "D" : 2, "D#" : 3, "E" : 4, "F" : 5, "F#" : 6, "G" : 7, "G#" : 8, "A" : 9, "A#" : 10, "B" : 11} |
| 2 | TONE_VALUE_LIST = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"] | 2 | TONE_VALUE_LIST = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"] | ||
| 3 | INTERVAL_VALUE_LIST = ["unison", "minor 2nd", "major 2nd", "minor 3rd", "major 3rd", "perfect 4th", "diminished 5th", "perfect 5th", "minor 6th", "major 6th", "minor 7th", "major 7th"] | 3 | INTERVAL_VALUE_LIST = ["unison", "minor 2nd", "major 2nd", "minor 3rd", "major 3rd", "perfect 4th", "diminished 5th", "perfect 5th", "minor 6th", "major 6th", "minor 7th", "major 7th"] | ||
| 4 | MAX_INDEX = 12 | 4 | MAX_INDEX = 12 | ||
| 5 | 5 | ||||
| 6 | class Tone: | 6 | class Tone: | ||
| 7 | def __init__(self, name): | 7 | def __init__(self, name): | ||
| 8 | self.name = name | 8 | self.name = name | ||
| 9 | 9 | ||||
| 10 | def __str__(self): | 10 | def __str__(self): | ||
| 11 | return self.name | 11 | return self.name | ||
| 12 | 12 | ||||
| 13 | def __add__(self, other): | 13 | def __add__(self, other): | ||
| 14 | if isinstance(other, Tone): | 14 | if isinstance(other, Tone): | ||
| 15 | return Chord(self, other) | 15 | return Chord(self, other) | ||
| 16 | if isinstance(other, Interval): | 16 | if isinstance(other, Interval): | ||
| 17 | total_len = other.lenght + self.index | 17 | total_len = other.lenght + self.index | ||
| 18 | correct_index = int(total_len / MAX_INDEX) | 18 | correct_index = int(total_len / MAX_INDEX) | ||
| 19 | correct_len = total_len - correct_index*MAX_INDEX | 19 | correct_len = total_len - correct_index*MAX_INDEX | ||
| 20 | return Tone(TONE_VALUE_LIST[correct_len]) | 20 | return Tone(TONE_VALUE_LIST[correct_len]) | ||
| 21 | 21 | ||||
| 22 | def __sub__(self, other): | 22 | def __sub__(self, other): | ||
| 23 | if isinstance(other, Tone): | 23 | if isinstance(other, Tone): | ||
| n | 24 | len = other.index - self.index | n | 24 | # len = other.index - self.index |
| 25 | if self.index > other.index: | 25 | # if self.index > other.index: | ||
| 26 | print("here") | ||||
| 27 | len = other.index + MAX_INDEX - self.index | 26 | # len = other.index + MAX_INDEX - self.index | ||
| 27 | # return Interval(len) | ||||
| 28 | len = self.index - other.index | ||||
| 29 | if self.index < other.index: | ||||
| 30 | len = self.index + MAX_INDEX - other.index | ||||
| 28 | return Interval(len) | 31 | return Interval(len) | ||
| 29 | if isinstance(other, Interval): | 32 | if isinstance(other, Interval): | ||
| 30 | wanted_index = self.index - other.lenght | 33 | wanted_index = self.index - other.lenght | ||
| 31 | if self.index < other.lenght: | 34 | if self.index < other.lenght: | ||
| 32 | wanted_index = self.index - other.lenght + MAX_INDEX | 35 | wanted_index = self.index - other.lenght + MAX_INDEX | ||
| 33 | return TONE_VALUE_LIST[wanted_index] | 36 | return TONE_VALUE_LIST[wanted_index] | ||
| 34 | 37 | ||||
| 35 | @property | 38 | @property | ||
| 36 | def index(self): | 39 | def index(self): | ||
| 37 | return TONE_INDEX_DICT[self.name] | 40 | return TONE_INDEX_DICT[self.name] | ||
| 38 | 41 | ||||
| 39 | class Interval: | 42 | class Interval: | ||
| 40 | def __init__(self, lenght): | 43 | def __init__(self, lenght): | ||
| 41 | correct_index = int(lenght / MAX_INDEX) | 44 | correct_index = int(lenght / MAX_INDEX) | ||
| 42 | self.lenght = lenght - correct_index*MAX_INDEX | 45 | self.lenght = lenght - correct_index*MAX_INDEX | ||
| 43 | 46 | ||||
| 44 | def __str__(self): | 47 | def __str__(self): | ||
| n | n | 48 | print(f"len is {self.lenght}") | ||
| 45 | return INTERVAL_VALUE_LIST[self.lenght] | 49 | return INTERVAL_VALUE_LIST[self.lenght] | ||
| 46 | 50 | ||||
| 47 | def __add__(self,other): | 51 | def __add__(self,other): | ||
| 48 | if isinstance(other,Tone): | 52 | if isinstance(other,Tone): | ||
| 49 | raise TypeError("Invalid operation") | 53 | raise TypeError("Invalid operation") | ||
| 50 | if isinstance(other,Interval): | 54 | if isinstance(other,Interval): | ||
| 51 | total_len = self.lenght + other.lenght | 55 | total_len = self.lenght + other.lenght | ||
| 52 | correct_index = int(total_len / MAX_INDEX) | 56 | correct_index = int(total_len / MAX_INDEX) | ||
| 53 | correct_len = total_len - correct_index*MAX_INDEX | 57 | correct_len = total_len - correct_index*MAX_INDEX | ||
| 54 | return INTERVAL_VALUE_LIST[correct_len] | 58 | return INTERVAL_VALUE_LIST[correct_len] | ||
| 55 | 59 | ||||
| 56 | def __sub__(self,other): | 60 | def __sub__(self,other): | ||
| 57 | if isinstance(other,Tone): | 61 | if isinstance(other,Tone): | ||
| 58 | raise TypeError("Invalid operation") | 62 | raise TypeError("Invalid operation") | ||
| 59 | 63 | ||||
| 60 | def __neg__(self): | 64 | def __neg__(self): | ||
| 61 | return Interval(MAX_INDEX - self.lenght) | 65 | return Interval(MAX_INDEX - self.lenght) | ||
| 62 | 66 | ||||
| 63 | class Chord: | 67 | class Chord: | ||
| 64 | def __init_sorted_tones(self): | 68 | def __init_sorted_tones(self): | ||
| 65 | main_index = self.main_tone.index | 69 | main_index = self.main_tone.index | ||
| 66 | tones_dict = {self.main_tone.name : main_index} | 70 | tones_dict = {self.main_tone.name : main_index} | ||
| 67 | self.all_tones_list_objs = [self.main_tone] | 71 | self.all_tones_list_objs = [self.main_tone] | ||
| 68 | for tone_name in self.unique_tones: | 72 | for tone_name in self.unique_tones: | ||
| 69 | tone_index = Tone(tone_name).index | 73 | tone_index = Tone(tone_name).index | ||
| 70 | self.without_main_tones_list_objs.append(Tone(tone_name)) | 74 | self.without_main_tones_list_objs.append(Tone(tone_name)) | ||
| 71 | self.all_tones_list_objs.append(Tone(tone_name)) | 75 | self.all_tones_list_objs.append(Tone(tone_name)) | ||
| 72 | if main_index > tone_index: | 76 | if main_index > tone_index: | ||
| 73 | tones_dict[tone_name] = tone_index + MAX_INDEX | 77 | tones_dict[tone_name] = tone_index + MAX_INDEX | ||
| 74 | else: | 78 | else: | ||
| 75 | tones_dict[tone_name] = tone_index | 79 | tones_dict[tone_name] = tone_index | ||
| 76 | self.sorted_tones = [key for key, value in sorted(tones_dict.items(), key=lambda item: item[1])] | 80 | self.sorted_tones = [key for key, value in sorted(tones_dict.items(), key=lambda item: item[1])] | ||
| 77 | 81 | ||||
| 78 | def __init__(self, main_tone, *tones): | 82 | def __init__(self, main_tone, *tones): | ||
| 79 | self.main_tone = main_tone | 83 | self.main_tone = main_tone | ||
| 80 | self.unique_tones= set() | 84 | self.unique_tones= set() | ||
| 81 | self.sorted_tones = [] | 85 | self.sorted_tones = [] | ||
| 82 | self.all_tones_list_objs = [] | 86 | self.all_tones_list_objs = [] | ||
| 83 | self.without_main_tones_list_objs = [] | 87 | self.without_main_tones_list_objs = [] | ||
| 84 | self.unique_tones.add(main_tone.name) | 88 | self.unique_tones.add(main_tone.name) | ||
| 85 | for tone in tones: | 89 | for tone in tones: | ||
| 86 | self.unique_tones.add(tone.name) | 90 | self.unique_tones.add(tone.name) | ||
| 87 | valid_len = len(self.unique_tones) | 91 | valid_len = len(self.unique_tones) | ||
| 88 | if valid_len <= 1: | 92 | if valid_len <= 1: | ||
| 89 | raise TypeError("Cannot have a chord made of only 1 unique tone") | 93 | raise TypeError("Cannot have a chord made of only 1 unique tone") | ||
| 90 | self.unique_tones.discard(main_tone.name) | 94 | self.unique_tones.discard(main_tone.name) | ||
| 91 | self.__init_sorted_tones() | 95 | self.__init_sorted_tones() | ||
| 92 | 96 | ||||
| 93 | def __add__(self, other): | 97 | def __add__(self, other): | ||
| 94 | new_tones = self.without_main_tones_list_objs | 98 | new_tones = self.without_main_tones_list_objs | ||
| 95 | if isinstance(other, Tone): | 99 | if isinstance(other, Tone): | ||
| 96 | new_tones.append(other) | 100 | new_tones.append(other) | ||
| 97 | if isinstance(other,Chord): | 101 | if isinstance(other,Chord): | ||
| 98 | for tone in other.all_tones_list_objs: | 102 | for tone in other.all_tones_list_objs: | ||
| 99 | new_tones.append(tone) | 103 | new_tones.append(tone) | ||
| 100 | return Chord(self.main_tone, *new_tones) | 104 | return Chord(self.main_tone, *new_tones) | ||
| 101 | 105 | ||||
| 102 | def __sub__(self, other): | 106 | def __sub__(self, other): | ||
| 103 | if other.name not in self.sorted_tones: | 107 | if other.name not in self.sorted_tones: | ||
| 104 | raise TypeError(f"Cannot remove tone {other.name} from chord {self}") | 108 | raise TypeError(f"Cannot remove tone {other.name} from chord {self}") | ||
| 105 | if len(self.unique_tones) < 2: | 109 | if len(self.unique_tones) < 2: | ||
| 106 | raise TypeError("Cannot have a chord made of only 1 unique tone") | 110 | raise TypeError("Cannot have a chord made of only 1 unique tone") | ||
| 107 | new_tones = self.without_main_tones_list_objs | 111 | new_tones = self.without_main_tones_list_objs | ||
| 108 | main_tone = self.main_tone | 112 | main_tone = self.main_tone | ||
| 109 | if isinstance(other, Tone): | 113 | if isinstance(other, Tone): | ||
| 110 | if main_tone.name == other.name: | 114 | if main_tone.name == other.name: | ||
| 111 | main_tone = self.without_main_tones_list_objs[0] | 115 | main_tone = self.without_main_tones_list_objs[0] | ||
| 112 | new_tones = filter(lambda tone: tone.name != main_tone.name, new_tones) | 116 | new_tones = filter(lambda tone: tone.name != main_tone.name, new_tones) | ||
| 113 | else: | 117 | else: | ||
| 114 | new_tones = filter(lambda tone: tone.name != other.name, new_tones) | 118 | new_tones = filter(lambda tone: tone.name != other.name, new_tones) | ||
| 115 | return Chord(main_tone, *new_tones) | 119 | return Chord(main_tone, *new_tones) | ||
| 116 | 120 | ||||
| 117 | def __str__(self): | 121 | def __str__(self): | ||
| 118 | return "-".join(self.sorted_tones) | 122 | return "-".join(self.sorted_tones) | ||
| 119 | 123 | ||||
| 120 | def is_minor(self): | 124 | def is_minor(self): | ||
| 121 | for tone in self.without_main_tones_list_objs: | 125 | for tone in self.without_main_tones_list_objs: | ||
| n | 122 | interval = self.main_tone - tone | n | 126 | interval = tone - self.main_tone |
| 123 | if str(interval) == "minor 3rd": | 127 | if str(interval) == "minor 3rd": | ||
| 124 | return True | 128 | return True | ||
| 125 | return False | 129 | return False | ||
| 126 | 130 | ||||
| 127 | def is_major(self): | 131 | def is_major(self): | ||
| 128 | for tone in self.without_main_tones_list_objs: | 132 | for tone in self.without_main_tones_list_objs: | ||
| t | 129 | interval = self.main_tone - tone | t | 133 | interval = tone - self.main_tone |
| 130 | if str(interval) == "major 3rd": | 134 | if str(interval) == "major 3rd": | ||
| 131 | return True | 135 | return True | ||
| 132 | return False | 136 | return False | ||
| 133 | 137 | ||||
| 134 | def is_power_chord(self): | 138 | def is_power_chord(self): | ||
| 135 | return not self.is_major() and not self.is_minor() | 139 | return not self.is_major() and not self.is_minor() | ||
| 136 | 140 | ||||
| 137 | def transposed(self, interval): | 141 | def transposed(self, interval): | ||
| 138 | transposed_tones = [tone + interval for tone in self.all_tones_list_objs] | 142 | transposed_tones = [tone + interval for tone in self.all_tones_list_objs] | ||
| 139 | return Chord(transposed_tones[0], *transposed_tones[1:]) | 143 | return Chord(transposed_tones[0], *transposed_tones[1:]) | ||
| 140 | 144 |
| Legends | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
| |||||||||
| f | 1 | TONE_INDEX_DICT = {"C" : 0, "C#" : 1, "D" : 2, "D#" : 3, "E" : 4, "F" : 5, "F#" : 6, "G" : 7, "G#" : 8, "A" : 9, "A#" : 10, "B" : 11} | f | 1 | TONE_INDEX_DICT = {"C" : 0, "C#" : 1, "D" : 2, "D#" : 3, "E" : 4, "F" : 5, "F#" : 6, "G" : 7, "G#" : 8, "A" : 9, "A#" : 10, "B" : 11} |
| 2 | TONE_VALUE_LIST = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"] | 2 | TONE_VALUE_LIST = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"] | ||
| 3 | INTERVAL_VALUE_LIST = ["unison", "minor 2nd", "major 2nd", "minor 3rd", "major 3rd", "perfect 4th", "diminished 5th", "perfect 5th", "minor 6th", "major 6th", "minor 7th", "major 7th"] | 3 | INTERVAL_VALUE_LIST = ["unison", "minor 2nd", "major 2nd", "minor 3rd", "major 3rd", "perfect 4th", "diminished 5th", "perfect 5th", "minor 6th", "major 6th", "minor 7th", "major 7th"] | ||
| 4 | MAX_INDEX = 12 | 4 | MAX_INDEX = 12 | ||
| 5 | 5 | ||||
| 6 | class Tone: | 6 | class Tone: | ||
| 7 | def __init__(self, name): | 7 | def __init__(self, name): | ||
| 8 | self.name = name | 8 | self.name = name | ||
| 9 | 9 | ||||
| 10 | def __str__(self): | 10 | def __str__(self): | ||
| 11 | return self.name | 11 | return self.name | ||
| 12 | 12 | ||||
| 13 | def __add__(self, other): | 13 | def __add__(self, other): | ||
| 14 | if isinstance(other, Tone): | 14 | if isinstance(other, Tone): | ||
| 15 | return Chord(self, other) | 15 | return Chord(self, other) | ||
| 16 | if isinstance(other, Interval): | 16 | if isinstance(other, Interval): | ||
| n | 17 | total_len = other.lenght + TONE_INDEX_DICT[self.name] | n | 17 | total_len = other.lenght + self.index |
| 18 | correct_index = int(total_len / MAX_INDEX) | 18 | correct_index = int(total_len / MAX_INDEX) | ||
| 19 | correct_len = total_len - correct_index*MAX_INDEX | 19 | correct_len = total_len - correct_index*MAX_INDEX | ||
| 20 | return Tone(TONE_VALUE_LIST[correct_len]) | 20 | return Tone(TONE_VALUE_LIST[correct_len]) | ||
| 21 | 21 | ||||
| 22 | def __sub__(self, other): | 22 | def __sub__(self, other): | ||
| 23 | if isinstance(other, Tone): | 23 | if isinstance(other, Tone): | ||
| n | 24 | return Interval(abs(self.index - other.index)) | n | 24 | len = other.index - self.index |
| 25 | if self.index > other.index: | ||||
| 26 | print("here") | ||||
| 27 | len = other.index + MAX_INDEX - self.index | ||||
| 28 | return Interval(len) | ||||
| 25 | if isinstance(other, Interval): | 29 | if isinstance(other, Interval): | ||
| n | 26 | cur_index = TONE_INDEX_DICT[self.name] | n | 30 | wanted_index = self.index - other.lenght |
| 31 | if self.index < other.lenght: | ||||
| 27 | wanted_index = cur_index - other.lenght + MAX_INDEX | 32 | wanted_index = self.index - other.lenght + MAX_INDEX | ||
| 28 | return TONE_VALUE_LIST[wanted_index] | 33 | return TONE_VALUE_LIST[wanted_index] | ||
| 29 | 34 | ||||
| 30 | @property | 35 | @property | ||
| 31 | def index(self): | 36 | def index(self): | ||
| 32 | return TONE_INDEX_DICT[self.name] | 37 | return TONE_INDEX_DICT[self.name] | ||
| 33 | 38 | ||||
| 34 | class Interval: | 39 | class Interval: | ||
| 35 | def __init__(self, lenght): | 40 | def __init__(self, lenght): | ||
| 36 | correct_index = int(lenght / MAX_INDEX) | 41 | correct_index = int(lenght / MAX_INDEX) | ||
| 37 | self.lenght = lenght - correct_index*MAX_INDEX | 42 | self.lenght = lenght - correct_index*MAX_INDEX | ||
| 38 | 43 | ||||
| 39 | def __str__(self): | 44 | def __str__(self): | ||
| 40 | return INTERVAL_VALUE_LIST[self.lenght] | 45 | return INTERVAL_VALUE_LIST[self.lenght] | ||
| 41 | 46 | ||||
| 42 | def __add__(self,other): | 47 | def __add__(self,other): | ||
| 43 | if isinstance(other,Tone): | 48 | if isinstance(other,Tone): | ||
| 44 | raise TypeError("Invalid operation") | 49 | raise TypeError("Invalid operation") | ||
| 45 | if isinstance(other,Interval): | 50 | if isinstance(other,Interval): | ||
| 46 | total_len = self.lenght + other.lenght | 51 | total_len = self.lenght + other.lenght | ||
| 47 | correct_index = int(total_len / MAX_INDEX) | 52 | correct_index = int(total_len / MAX_INDEX) | ||
| 48 | correct_len = total_len - correct_index*MAX_INDEX | 53 | correct_len = total_len - correct_index*MAX_INDEX | ||
| 49 | return INTERVAL_VALUE_LIST[correct_len] | 54 | return INTERVAL_VALUE_LIST[correct_len] | ||
| 50 | 55 | ||||
| 51 | def __sub__(self,other): | 56 | def __sub__(self,other): | ||
| 52 | if isinstance(other,Tone): | 57 | if isinstance(other,Tone): | ||
| 53 | raise TypeError("Invalid operation") | 58 | raise TypeError("Invalid operation") | ||
| 54 | 59 | ||||
| 55 | def __neg__(self): | 60 | def __neg__(self): | ||
| 56 | return Interval(MAX_INDEX - self.lenght) | 61 | return Interval(MAX_INDEX - self.lenght) | ||
| 57 | 62 | ||||
| 58 | class Chord: | 63 | class Chord: | ||
| 59 | def __init_sorted_tones(self): | 64 | def __init_sorted_tones(self): | ||
| 60 | main_index = self.main_tone.index | 65 | main_index = self.main_tone.index | ||
| 61 | tones_dict = {self.main_tone.name : main_index} | 66 | tones_dict = {self.main_tone.name : main_index} | ||
| 62 | self.all_tones_list_objs = [self.main_tone] | 67 | self.all_tones_list_objs = [self.main_tone] | ||
| 63 | for tone_name in self.unique_tones: | 68 | for tone_name in self.unique_tones: | ||
| 64 | tone_index = Tone(tone_name).index | 69 | tone_index = Tone(tone_name).index | ||
| 65 | self.without_main_tones_list_objs.append(Tone(tone_name)) | 70 | self.without_main_tones_list_objs.append(Tone(tone_name)) | ||
| 66 | self.all_tones_list_objs.append(Tone(tone_name)) | 71 | self.all_tones_list_objs.append(Tone(tone_name)) | ||
| 67 | if main_index > tone_index: | 72 | if main_index > tone_index: | ||
| 68 | tones_dict[tone_name] = tone_index + MAX_INDEX | 73 | tones_dict[tone_name] = tone_index + MAX_INDEX | ||
| 69 | else: | 74 | else: | ||
| 70 | tones_dict[tone_name] = tone_index | 75 | tones_dict[tone_name] = tone_index | ||
| 71 | self.sorted_tones = [key for key, value in sorted(tones_dict.items(), key=lambda item: item[1])] | 76 | self.sorted_tones = [key for key, value in sorted(tones_dict.items(), key=lambda item: item[1])] | ||
| 72 | 77 | ||||
| 73 | def __init__(self, main_tone, *tones): | 78 | def __init__(self, main_tone, *tones): | ||
| 74 | self.main_tone = main_tone | 79 | self.main_tone = main_tone | ||
| 75 | self.unique_tones= set() | 80 | self.unique_tones= set() | ||
| 76 | self.sorted_tones = [] | 81 | self.sorted_tones = [] | ||
| 77 | self.all_tones_list_objs = [] | 82 | self.all_tones_list_objs = [] | ||
| 78 | self.without_main_tones_list_objs = [] | 83 | self.without_main_tones_list_objs = [] | ||
| 79 | self.unique_tones.add(main_tone.name) | 84 | self.unique_tones.add(main_tone.name) | ||
| 80 | for tone in tones: | 85 | for tone in tones: | ||
| 81 | self.unique_tones.add(tone.name) | 86 | self.unique_tones.add(tone.name) | ||
| 82 | valid_len = len(self.unique_tones) | 87 | valid_len = len(self.unique_tones) | ||
| 83 | if valid_len <= 1: | 88 | if valid_len <= 1: | ||
| 84 | raise TypeError("Cannot have a chord made of only 1 unique tone") | 89 | raise TypeError("Cannot have a chord made of only 1 unique tone") | ||
| 85 | self.unique_tones.discard(main_tone.name) | 90 | self.unique_tones.discard(main_tone.name) | ||
| 86 | self.__init_sorted_tones() | 91 | self.__init_sorted_tones() | ||
| 87 | 92 | ||||
| 88 | def __add__(self, other): | 93 | def __add__(self, other): | ||
| 89 | new_tones = self.without_main_tones_list_objs | 94 | new_tones = self.without_main_tones_list_objs | ||
| 90 | if isinstance(other, Tone): | 95 | if isinstance(other, Tone): | ||
| 91 | new_tones.append(other) | 96 | new_tones.append(other) | ||
| 92 | if isinstance(other,Chord): | 97 | if isinstance(other,Chord): | ||
| 93 | for tone in other.all_tones_list_objs: | 98 | for tone in other.all_tones_list_objs: | ||
| 94 | new_tones.append(tone) | 99 | new_tones.append(tone) | ||
| 95 | return Chord(self.main_tone, *new_tones) | 100 | return Chord(self.main_tone, *new_tones) | ||
| 96 | 101 | ||||
| 97 | def __sub__(self, other): | 102 | def __sub__(self, other): | ||
| 98 | if other.name not in self.sorted_tones: | 103 | if other.name not in self.sorted_tones: | ||
| 99 | raise TypeError(f"Cannot remove tone {other.name} from chord {self}") | 104 | raise TypeError(f"Cannot remove tone {other.name} from chord {self}") | ||
| 100 | if len(self.unique_tones) < 2: | 105 | if len(self.unique_tones) < 2: | ||
| 101 | raise TypeError("Cannot have a chord made of only 1 unique tone") | 106 | raise TypeError("Cannot have a chord made of only 1 unique tone") | ||
| n | 102 | new_tones = self.all_tones_list_objs | n | 107 | new_tones = self.without_main_tones_list_objs |
| 103 | main_tone = self.main_tone | 108 | main_tone = self.main_tone | ||
| 104 | if isinstance(other, Tone): | 109 | if isinstance(other, Tone): | ||
| 105 | if main_tone.name == other.name: | 110 | if main_tone.name == other.name: | ||
| n | 106 | main_tone = Tone(self.sorted_tones[0]) | n | 111 | main_tone = self.without_main_tones_list_objs[0] |
| 107 | new_tones = filter(lambda tone: tone.name != main_tone.name, new_tones) | 112 | new_tones = filter(lambda tone: tone.name != main_tone.name, new_tones) | ||
| 108 | else: | 113 | else: | ||
| 109 | new_tones = filter(lambda tone: tone.name != other.name, new_tones) | 114 | new_tones = filter(lambda tone: tone.name != other.name, new_tones) | ||
| 110 | return Chord(main_tone, *new_tones) | 115 | return Chord(main_tone, *new_tones) | ||
| 111 | 116 | ||||
| 112 | def __str__(self): | 117 | def __str__(self): | ||
| 113 | return "-".join(self.sorted_tones) | 118 | return "-".join(self.sorted_tones) | ||
| 114 | 119 | ||||
| 115 | def is_minor(self): | 120 | def is_minor(self): | ||
| n | 116 | main_index = self.main_tone.index | n | ||
| 117 | for tone in self.without_main_tones_list_objs: | 121 | for tone in self.without_main_tones_list_objs: | ||
| n | 118 | interval = Interval(abs(main_index - tone.index)) | n | 122 | interval = self.main_tone - tone |
| 119 | if str(interval) == "minor 3rd": | 123 | if str(interval) == "minor 3rd": | ||
| 120 | return True | 124 | return True | ||
| 121 | return False | 125 | return False | ||
| 122 | 126 | ||||
| 123 | def is_major(self): | 127 | def is_major(self): | ||
| n | 124 | main_index = self.main_tone.index | n | ||
| 125 | for tone in self.without_main_tones_list_objs: | 128 | for tone in self.without_main_tones_list_objs: | ||
| n | 126 | interval = Interval(abs(main_index - tone.index)) | n | 129 | interval = self.main_tone - tone |
| 127 | if str(interval) == "major 3rd": | 130 | if str(interval) == "major 3rd": | ||
| 128 | return True | 131 | return True | ||
| 129 | return False | 132 | return False | ||
| 130 | 133 | ||||
| 131 | def is_power_chord(self): | 134 | def is_power_chord(self): | ||
| 132 | return not self.is_major() and not self.is_minor() | 135 | return not self.is_major() and not self.is_minor() | ||
| 133 | 136 | ||||
| 134 | def transposed(self, interval): | 137 | def transposed(self, interval): | ||
| 135 | transposed_tones = [tone + interval for tone in self.all_tones_list_objs] | 138 | transposed_tones = [tone + interval for tone in self.all_tones_list_objs] | ||
| 136 | return Chord(transposed_tones[0], *transposed_tones[1:]) | 139 | return Chord(transposed_tones[0], *transposed_tones[1:]) | ||
| 137 | 140 | ||||
| t | 138 | t |
| Legends | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
| |||||||||
| f | 1 | TONE_INDEX_DICT = {"C" : 0, "C#" : 1, "D" : 2, "D#" : 3, "E" : 4, "F" : 5, "F#" : 6, "G" : 7, "G#" : 8, "A" : 9, "A#" : 10, "B" : 11} | f | 1 | TONE_INDEX_DICT = {"C" : 0, "C#" : 1, "D" : 2, "D#" : 3, "E" : 4, "F" : 5, "F#" : 6, "G" : 7, "G#" : 8, "A" : 9, "A#" : 10, "B" : 11} |
| 2 | TONE_VALUE_LIST = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"] | 2 | TONE_VALUE_LIST = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"] | ||
| 3 | INTERVAL_VALUE_LIST = ["unison", "minor 2nd", "major 2nd", "minor 3rd", "major 3rd", "perfect 4th", "diminished 5th", "perfect 5th", "minor 6th", "major 6th", "minor 7th", "major 7th"] | 3 | INTERVAL_VALUE_LIST = ["unison", "minor 2nd", "major 2nd", "minor 3rd", "major 3rd", "perfect 4th", "diminished 5th", "perfect 5th", "minor 6th", "major 6th", "minor 7th", "major 7th"] | ||
| 4 | MAX_INDEX = 12 | 4 | MAX_INDEX = 12 | ||
| 5 | 5 | ||||
| 6 | class Tone: | 6 | class Tone: | ||
| 7 | def __init__(self, name): | 7 | def __init__(self, name): | ||
| 8 | self.name = name | 8 | self.name = name | ||
| 9 | 9 | ||||
| 10 | def __str__(self): | 10 | def __str__(self): | ||
| 11 | return self.name | 11 | return self.name | ||
| 12 | 12 | ||||
| 13 | def __add__(self, other): | 13 | def __add__(self, other): | ||
| 14 | if isinstance(other, Tone): | 14 | if isinstance(other, Tone): | ||
| 15 | return Chord(self, other) | 15 | return Chord(self, other) | ||
| 16 | if isinstance(other, Interval): | 16 | if isinstance(other, Interval): | ||
| 17 | total_len = other.lenght + TONE_INDEX_DICT[self.name] | 17 | total_len = other.lenght + TONE_INDEX_DICT[self.name] | ||
| 18 | correct_index = int(total_len / MAX_INDEX) | 18 | correct_index = int(total_len / MAX_INDEX) | ||
| 19 | correct_len = total_len - correct_index*MAX_INDEX | 19 | correct_len = total_len - correct_index*MAX_INDEX | ||
| 20 | return Tone(TONE_VALUE_LIST[correct_len]) | 20 | return Tone(TONE_VALUE_LIST[correct_len]) | ||
| 21 | 21 | ||||
| 22 | def __sub__(self, other): | 22 | def __sub__(self, other): | ||
| 23 | if isinstance(other, Tone): | 23 | if isinstance(other, Tone): | ||
| 24 | return Interval(abs(self.index - other.index)) | 24 | return Interval(abs(self.index - other.index)) | ||
| 25 | if isinstance(other, Interval): | 25 | if isinstance(other, Interval): | ||
| 26 | cur_index = TONE_INDEX_DICT[self.name] | 26 | cur_index = TONE_INDEX_DICT[self.name] | ||
| 27 | wanted_index = cur_index - other.lenght + MAX_INDEX | 27 | wanted_index = cur_index - other.lenght + MAX_INDEX | ||
| 28 | return TONE_VALUE_LIST[wanted_index] | 28 | return TONE_VALUE_LIST[wanted_index] | ||
| 29 | 29 | ||||
| 30 | @property | 30 | @property | ||
| 31 | def index(self): | 31 | def index(self): | ||
| 32 | return TONE_INDEX_DICT[self.name] | 32 | return TONE_INDEX_DICT[self.name] | ||
| 33 | 33 | ||||
| 34 | class Interval: | 34 | class Interval: | ||
| 35 | def __init__(self, lenght): | 35 | def __init__(self, lenght): | ||
| 36 | correct_index = int(lenght / MAX_INDEX) | 36 | correct_index = int(lenght / MAX_INDEX) | ||
| 37 | self.lenght = lenght - correct_index*MAX_INDEX | 37 | self.lenght = lenght - correct_index*MAX_INDEX | ||
| 38 | 38 | ||||
| 39 | def __str__(self): | 39 | def __str__(self): | ||
| 40 | return INTERVAL_VALUE_LIST[self.lenght] | 40 | return INTERVAL_VALUE_LIST[self.lenght] | ||
| 41 | 41 | ||||
| 42 | def __add__(self,other): | 42 | def __add__(self,other): | ||
| 43 | if isinstance(other,Tone): | 43 | if isinstance(other,Tone): | ||
| 44 | raise TypeError("Invalid operation") | 44 | raise TypeError("Invalid operation") | ||
| 45 | if isinstance(other,Interval): | 45 | if isinstance(other,Interval): | ||
| 46 | total_len = self.lenght + other.lenght | 46 | total_len = self.lenght + other.lenght | ||
| 47 | correct_index = int(total_len / MAX_INDEX) | 47 | correct_index = int(total_len / MAX_INDEX) | ||
| 48 | correct_len = total_len - correct_index*MAX_INDEX | 48 | correct_len = total_len - correct_index*MAX_INDEX | ||
| 49 | return INTERVAL_VALUE_LIST[correct_len] | 49 | return INTERVAL_VALUE_LIST[correct_len] | ||
| 50 | 50 | ||||
| 51 | def __sub__(self,other): | 51 | def __sub__(self,other): | ||
| 52 | if isinstance(other,Tone): | 52 | if isinstance(other,Tone): | ||
| 53 | raise TypeError("Invalid operation") | 53 | raise TypeError("Invalid operation") | ||
| 54 | 54 | ||||
| 55 | def __neg__(self): | 55 | def __neg__(self): | ||
| 56 | return Interval(MAX_INDEX - self.lenght) | 56 | return Interval(MAX_INDEX - self.lenght) | ||
| 57 | 57 | ||||
| 58 | class Chord: | 58 | class Chord: | ||
| 59 | def __init_sorted_tones(self): | 59 | def __init_sorted_tones(self): | ||
| 60 | main_index = self.main_tone.index | 60 | main_index = self.main_tone.index | ||
| 61 | tones_dict = {self.main_tone.name : main_index} | 61 | tones_dict = {self.main_tone.name : main_index} | ||
| n | n | 62 | self.all_tones_list_objs = [self.main_tone] | ||
| 62 | for tone in self.uniques_to_list_objs_tones: | 63 | for tone_name in self.unique_tones: | ||
| 63 | tone_index = tone.index | 64 | tone_index = Tone(tone_name).index | ||
| 65 | self.without_main_tones_list_objs.append(Tone(tone_name)) | ||||
| 66 | self.all_tones_list_objs.append(Tone(tone_name)) | ||||
| 64 | if main_index > tone_index: | 67 | if main_index > tone_index: | ||
| n | 65 | tones_dict[tone.name] = tone_index + MAX_INDEX | n | 68 | tones_dict[tone_name] = tone_index + MAX_INDEX |
| 66 | else: | 69 | else: | ||
| n | 67 | tones_dict[tone.name] = tone_index | n | 70 | tones_dict[tone_name] = tone_index |
| 68 | self.sorted_tones = [key for key, value in sorted(tones_dict.items(), key=lambda item: item[1])] | 71 | self.sorted_tones = [key for key, value in sorted(tones_dict.items(), key=lambda item: item[1])] | ||
| n | 69 | n | |||
| 70 | @property | ||||
| 71 | def sorted_to_list_objs_tones(self): | ||||
| 72 | tones_objs_list = [] | ||||
| 73 | for tone in self.sorted_tones: | ||||
| 74 | tones_objs_list.append(Tone(tone)) | ||||
| 75 | return tones_objs_list | ||||
| 76 | |||||
| 77 | @property | ||||
| 78 | def uniques_to_list_objs_tones(self): | ||||
| 79 | tones_objs_list = [] | ||||
| 80 | for tone in self.unique_tones: | ||||
| 81 | tones_objs_list.append(Tone(tone)) | ||||
| 82 | return tones_objs_list | ||||
| 83 | 72 | ||||
| 84 | def __init__(self, main_tone, *tones): | 73 | def __init__(self, main_tone, *tones): | ||
| 85 | self.main_tone = main_tone | 74 | self.main_tone = main_tone | ||
| 86 | self.unique_tones= set() | 75 | self.unique_tones= set() | ||
| 87 | self.sorted_tones = [] | 76 | self.sorted_tones = [] | ||
| n | n | 77 | self.all_tones_list_objs = [] | ||
| 78 | self.without_main_tones_list_objs = [] | ||||
| 88 | self.unique_tones.add(main_tone.name) | 79 | self.unique_tones.add(main_tone.name) | ||
| 89 | for tone in tones: | 80 | for tone in tones: | ||
| 90 | self.unique_tones.add(tone.name) | 81 | self.unique_tones.add(tone.name) | ||
| 91 | valid_len = len(self.unique_tones) | 82 | valid_len = len(self.unique_tones) | ||
| 92 | if valid_len <= 1: | 83 | if valid_len <= 1: | ||
| 93 | raise TypeError("Cannot have a chord made of only 1 unique tone") | 84 | raise TypeError("Cannot have a chord made of only 1 unique tone") | ||
| 94 | self.unique_tones.discard(main_tone.name) | 85 | self.unique_tones.discard(main_tone.name) | ||
| 95 | self.__init_sorted_tones() | 86 | self.__init_sorted_tones() | ||
| 96 | 87 | ||||
| 97 | def __add__(self, other): | 88 | def __add__(self, other): | ||
| n | 98 | new_tones = self.uniques_to_list_objs_tones | n | 89 | new_tones = self.without_main_tones_list_objs |
| 99 | if isinstance(other, Tone): | 90 | if isinstance(other, Tone): | ||
| 100 | new_tones.append(other) | 91 | new_tones.append(other) | ||
| 101 | if isinstance(other,Chord): | 92 | if isinstance(other,Chord): | ||
| n | 102 | for tone in other.sorted_to_list_objs_tones: | n | 93 | for tone in other.all_tones_list_objs: |
| 103 | new_tones.append(tone) | 94 | new_tones.append(tone) | ||
| 104 | return Chord(self.main_tone, *new_tones) | 95 | return Chord(self.main_tone, *new_tones) | ||
| 105 | 96 | ||||
| 106 | def __sub__(self, other): | 97 | def __sub__(self, other): | ||
| 107 | if other.name not in self.sorted_tones: | 98 | if other.name not in self.sorted_tones: | ||
| 108 | raise TypeError(f"Cannot remove tone {other.name} from chord {self}") | 99 | raise TypeError(f"Cannot remove tone {other.name} from chord {self}") | ||
| 109 | if len(self.unique_tones) < 2: | 100 | if len(self.unique_tones) < 2: | ||
| 110 | raise TypeError("Cannot have a chord made of only 1 unique tone") | 101 | raise TypeError("Cannot have a chord made of only 1 unique tone") | ||
| n | 111 | new_tones = self.sorted_to_list_objs_tones | n | 102 | new_tones = self.all_tones_list_objs |
| 112 | main_tone = self.main_tone | 103 | main_tone = self.main_tone | ||
| 113 | if isinstance(other, Tone): | 104 | if isinstance(other, Tone): | ||
| 114 | if main_tone.name == other.name: | 105 | if main_tone.name == other.name: | ||
| 115 | main_tone = Tone(self.sorted_tones[0]) | 106 | main_tone = Tone(self.sorted_tones[0]) | ||
| 116 | new_tones = filter(lambda tone: tone.name != main_tone.name, new_tones) | 107 | new_tones = filter(lambda tone: tone.name != main_tone.name, new_tones) | ||
| 117 | else: | 108 | else: | ||
| 118 | new_tones = filter(lambda tone: tone.name != other.name, new_tones) | 109 | new_tones = filter(lambda tone: tone.name != other.name, new_tones) | ||
| 119 | return Chord(main_tone, *new_tones) | 110 | return Chord(main_tone, *new_tones) | ||
| 120 | 111 | ||||
| 121 | def __str__(self): | 112 | def __str__(self): | ||
| 122 | return "-".join(self.sorted_tones) | 113 | return "-".join(self.sorted_tones) | ||
| 123 | 114 | ||||
| 124 | def is_minor(self): | 115 | def is_minor(self): | ||
| 125 | main_index = self.main_tone.index | 116 | main_index = self.main_tone.index | ||
| n | 126 | for tone in self.uniques_to_list_objs_tones: | n | 117 | for tone in self.without_main_tones_list_objs: |
| 127 | interval = Interval(abs(main_index - tone.index)) | 118 | interval = Interval(abs(main_index - tone.index)) | ||
| 128 | if str(interval) == "minor 3rd": | 119 | if str(interval) == "minor 3rd": | ||
| 129 | return True | 120 | return True | ||
| 130 | return False | 121 | return False | ||
| 131 | 122 | ||||
| 132 | def is_major(self): | 123 | def is_major(self): | ||
| 133 | main_index = self.main_tone.index | 124 | main_index = self.main_tone.index | ||
| n | 134 | for tone in self.uniques_to_list_objs_tones: | n | 125 | for tone in self.without_main_tones_list_objs: |
| 135 | interval = Interval(abs(main_index - tone.index)) | 126 | interval = Interval(abs(main_index - tone.index)) | ||
| 136 | if str(interval) == "major 3rd": | 127 | if str(interval) == "major 3rd": | ||
| 137 | return True | 128 | return True | ||
| 138 | return False | 129 | return False | ||
| 139 | 130 | ||||
| 140 | def is_power_chord(self): | 131 | def is_power_chord(self): | ||
| 141 | return not self.is_major() and not self.is_minor() | 132 | return not self.is_major() and not self.is_minor() | ||
| 142 | 133 | ||||
| 143 | def transposed(self, interval): | 134 | def transposed(self, interval): | ||
| t | 144 | transposed_tones = [tone + interval for tone in self.sorted_to_list_objs_tones] | t | 135 | transposed_tones = [tone + interval for tone in self.all_tones_list_objs] |
| 145 | return Chord(transposed_tones[0], *transposed_tones[1:]) | 136 | return Chord(transposed_tones[0], *transposed_tones[1:]) | ||
| 146 | 137 | ||||
| 147 | 138 |
| Legends | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
| |||||||||
| f | 1 | TONE_INDEX_DICT = {"C" : 0, "C#" : 1, "D" : 2, "D#" : 3, "E" : 4, "F" : 5, "F#" : 6, "G" : 7, "G#" : 8, "A" : 9, "A#" : 10, "B" : 11} | f | 1 | TONE_INDEX_DICT = {"C" : 0, "C#" : 1, "D" : 2, "D#" : 3, "E" : 4, "F" : 5, "F#" : 6, "G" : 7, "G#" : 8, "A" : 9, "A#" : 10, "B" : 11} |
| 2 | TONE_VALUE_LIST = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"] | 2 | TONE_VALUE_LIST = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"] | ||
| 3 | INTERVAL_VALUE_LIST = ["unison", "minor 2nd", "major 2nd", "minor 3rd", "major 3rd", "perfect 4th", "diminished 5th", "perfect 5th", "minor 6th", "major 6th", "minor 7th", "major 7th"] | 3 | INTERVAL_VALUE_LIST = ["unison", "minor 2nd", "major 2nd", "minor 3rd", "major 3rd", "perfect 4th", "diminished 5th", "perfect 5th", "minor 6th", "major 6th", "minor 7th", "major 7th"] | ||
| 4 | MAX_INDEX = 12 | 4 | MAX_INDEX = 12 | ||
| 5 | 5 | ||||
| 6 | class Tone: | 6 | class Tone: | ||
| 7 | def __init__(self, name): | 7 | def __init__(self, name): | ||
| 8 | self.name = name | 8 | self.name = name | ||
| 9 | 9 | ||||
| 10 | def __str__(self): | 10 | def __str__(self): | ||
| 11 | return self.name | 11 | return self.name | ||
| 12 | 12 | ||||
| 13 | def __add__(self, other): | 13 | def __add__(self, other): | ||
| 14 | if isinstance(other, Tone): | 14 | if isinstance(other, Tone): | ||
| 15 | return Chord(self, other) | 15 | return Chord(self, other) | ||
| 16 | if isinstance(other, Interval): | 16 | if isinstance(other, Interval): | ||
| 17 | total_len = other.lenght + TONE_INDEX_DICT[self.name] | 17 | total_len = other.lenght + TONE_INDEX_DICT[self.name] | ||
| 18 | correct_index = int(total_len / MAX_INDEX) | 18 | correct_index = int(total_len / MAX_INDEX) | ||
| 19 | correct_len = total_len - correct_index*MAX_INDEX | 19 | correct_len = total_len - correct_index*MAX_INDEX | ||
| 20 | return Tone(TONE_VALUE_LIST[correct_len]) | 20 | return Tone(TONE_VALUE_LIST[correct_len]) | ||
| 21 | 21 | ||||
| 22 | def __sub__(self, other): | 22 | def __sub__(self, other): | ||
| 23 | if isinstance(other, Tone): | 23 | if isinstance(other, Tone): | ||
| 24 | return Interval(abs(self.index - other.index)) | 24 | return Interval(abs(self.index - other.index)) | ||
| 25 | if isinstance(other, Interval): | 25 | if isinstance(other, Interval): | ||
| 26 | cur_index = TONE_INDEX_DICT[self.name] | 26 | cur_index = TONE_INDEX_DICT[self.name] | ||
| 27 | wanted_index = cur_index - other.lenght + MAX_INDEX | 27 | wanted_index = cur_index - other.lenght + MAX_INDEX | ||
| 28 | return TONE_VALUE_LIST[wanted_index] | 28 | return TONE_VALUE_LIST[wanted_index] | ||
| 29 | 29 | ||||
| 30 | @property | 30 | @property | ||
| 31 | def index(self): | 31 | def index(self): | ||
| 32 | return TONE_INDEX_DICT[self.name] | 32 | return TONE_INDEX_DICT[self.name] | ||
| 33 | 33 | ||||
| 34 | class Interval: | 34 | class Interval: | ||
| 35 | def __init__(self, lenght): | 35 | def __init__(self, lenght): | ||
| 36 | correct_index = int(lenght / MAX_INDEX) | 36 | correct_index = int(lenght / MAX_INDEX) | ||
| 37 | self.lenght = lenght - correct_index*MAX_INDEX | 37 | self.lenght = lenght - correct_index*MAX_INDEX | ||
| 38 | 38 | ||||
| 39 | def __str__(self): | 39 | def __str__(self): | ||
| 40 | return INTERVAL_VALUE_LIST[self.lenght] | 40 | return INTERVAL_VALUE_LIST[self.lenght] | ||
| 41 | 41 | ||||
| 42 | def __add__(self,other): | 42 | def __add__(self,other): | ||
| 43 | if isinstance(other,Tone): | 43 | if isinstance(other,Tone): | ||
| 44 | raise TypeError("Invalid operation") | 44 | raise TypeError("Invalid operation") | ||
| 45 | if isinstance(other,Interval): | 45 | if isinstance(other,Interval): | ||
| 46 | total_len = self.lenght + other.lenght | 46 | total_len = self.lenght + other.lenght | ||
| 47 | correct_index = int(total_len / MAX_INDEX) | 47 | correct_index = int(total_len / MAX_INDEX) | ||
| 48 | correct_len = total_len - correct_index*MAX_INDEX | 48 | correct_len = total_len - correct_index*MAX_INDEX | ||
| 49 | return INTERVAL_VALUE_LIST[correct_len] | 49 | return INTERVAL_VALUE_LIST[correct_len] | ||
| 50 | 50 | ||||
| 51 | def __sub__(self,other): | 51 | def __sub__(self,other): | ||
| 52 | if isinstance(other,Tone): | 52 | if isinstance(other,Tone): | ||
| 53 | raise TypeError("Invalid operation") | 53 | raise TypeError("Invalid operation") | ||
| 54 | 54 | ||||
| 55 | def __neg__(self): | 55 | def __neg__(self): | ||
| t | 56 | correct_index = int(self.lenght / MAX_INDEX) | t | ||
| 57 | self.lenght = self.lenght - correct_index*MAX_INDEX | ||||
| 58 | return Interval(MAX_INDEX-self.lenght) | 56 | return Interval(MAX_INDEX - self.lenght) | ||
| 59 | 57 | ||||
| 60 | class Chord: | 58 | class Chord: | ||
| 61 | def __init_sorted_tones(self): | 59 | def __init_sorted_tones(self): | ||
| 62 | main_index = self.main_tone.index | 60 | main_index = self.main_tone.index | ||
| 63 | tones_dict = {self.main_tone.name : main_index} | 61 | tones_dict = {self.main_tone.name : main_index} | ||
| 64 | for tone in self.uniques_to_list_objs_tones: | 62 | for tone in self.uniques_to_list_objs_tones: | ||
| 65 | tone_index = tone.index | 63 | tone_index = tone.index | ||
| 66 | if main_index > tone_index: | 64 | if main_index > tone_index: | ||
| 67 | tones_dict[tone.name] = tone_index + MAX_INDEX | 65 | tones_dict[tone.name] = tone_index + MAX_INDEX | ||
| 68 | else: | 66 | else: | ||
| 69 | tones_dict[tone.name] = tone_index | 67 | tones_dict[tone.name] = tone_index | ||
| 70 | self.sorted_tones = [key for key, value in sorted(tones_dict.items(), key=lambda item: item[1])] | 68 | self.sorted_tones = [key for key, value in sorted(tones_dict.items(), key=lambda item: item[1])] | ||
| 71 | 69 | ||||
| 72 | @property | 70 | @property | ||
| 73 | def sorted_to_list_objs_tones(self): | 71 | def sorted_to_list_objs_tones(self): | ||
| 74 | tones_objs_list = [] | 72 | tones_objs_list = [] | ||
| 75 | for tone in self.sorted_tones: | 73 | for tone in self.sorted_tones: | ||
| 76 | tones_objs_list.append(Tone(tone)) | 74 | tones_objs_list.append(Tone(tone)) | ||
| 77 | return tones_objs_list | 75 | return tones_objs_list | ||
| 78 | 76 | ||||
| 79 | @property | 77 | @property | ||
| 80 | def uniques_to_list_objs_tones(self): | 78 | def uniques_to_list_objs_tones(self): | ||
| 81 | tones_objs_list = [] | 79 | tones_objs_list = [] | ||
| 82 | for tone in self.unique_tones: | 80 | for tone in self.unique_tones: | ||
| 83 | tones_objs_list.append(Tone(tone)) | 81 | tones_objs_list.append(Tone(tone)) | ||
| 84 | return tones_objs_list | 82 | return tones_objs_list | ||
| 85 | 83 | ||||
| 86 | def __init__(self, main_tone, *tones): | 84 | def __init__(self, main_tone, *tones): | ||
| 87 | self.main_tone = main_tone | 85 | self.main_tone = main_tone | ||
| 88 | self.unique_tones= set() | 86 | self.unique_tones= set() | ||
| 89 | self.sorted_tones = [] | 87 | self.sorted_tones = [] | ||
| 90 | self.unique_tones.add(main_tone.name) | 88 | self.unique_tones.add(main_tone.name) | ||
| 91 | for tone in tones: | 89 | for tone in tones: | ||
| 92 | self.unique_tones.add(tone.name) | 90 | self.unique_tones.add(tone.name) | ||
| 93 | valid_len = len(self.unique_tones) | 91 | valid_len = len(self.unique_tones) | ||
| 94 | if valid_len <= 1: | 92 | if valid_len <= 1: | ||
| 95 | raise TypeError("Cannot have a chord made of only 1 unique tone") | 93 | raise TypeError("Cannot have a chord made of only 1 unique tone") | ||
| 96 | self.unique_tones.discard(main_tone.name) | 94 | self.unique_tones.discard(main_tone.name) | ||
| 97 | self.__init_sorted_tones() | 95 | self.__init_sorted_tones() | ||
| 98 | 96 | ||||
| 99 | def __add__(self, other): | 97 | def __add__(self, other): | ||
| 100 | new_tones = self.uniques_to_list_objs_tones | 98 | new_tones = self.uniques_to_list_objs_tones | ||
| 101 | if isinstance(other, Tone): | 99 | if isinstance(other, Tone): | ||
| 102 | new_tones.append(other) | 100 | new_tones.append(other) | ||
| 103 | if isinstance(other,Chord): | 101 | if isinstance(other,Chord): | ||
| 104 | for tone in other.sorted_to_list_objs_tones: | 102 | for tone in other.sorted_to_list_objs_tones: | ||
| 105 | new_tones.append(tone) | 103 | new_tones.append(tone) | ||
| 106 | return Chord(self.main_tone, *new_tones) | 104 | return Chord(self.main_tone, *new_tones) | ||
| 107 | 105 | ||||
| 108 | def __sub__(self, other): | 106 | def __sub__(self, other): | ||
| 109 | if other.name not in self.sorted_tones: | 107 | if other.name not in self.sorted_tones: | ||
| 110 | raise TypeError(f"Cannot remove tone {other.name} from chord {self}") | 108 | raise TypeError(f"Cannot remove tone {other.name} from chord {self}") | ||
| 111 | if len(self.unique_tones) < 2: | 109 | if len(self.unique_tones) < 2: | ||
| 112 | raise TypeError("Cannot have a chord made of only 1 unique tone") | 110 | raise TypeError("Cannot have a chord made of only 1 unique tone") | ||
| 113 | new_tones = self.sorted_to_list_objs_tones | 111 | new_tones = self.sorted_to_list_objs_tones | ||
| 114 | main_tone = self.main_tone | 112 | main_tone = self.main_tone | ||
| 115 | if isinstance(other, Tone): | 113 | if isinstance(other, Tone): | ||
| 116 | if main_tone.name == other.name: | 114 | if main_tone.name == other.name: | ||
| 117 | main_tone = Tone(self.sorted_tones[0]) | 115 | main_tone = Tone(self.sorted_tones[0]) | ||
| 118 | new_tones = filter(lambda tone: tone.name != main_tone.name, new_tones) | 116 | new_tones = filter(lambda tone: tone.name != main_tone.name, new_tones) | ||
| 119 | else: | 117 | else: | ||
| 120 | new_tones = filter(lambda tone: tone.name != other.name, new_tones) | 118 | new_tones = filter(lambda tone: tone.name != other.name, new_tones) | ||
| 121 | return Chord(main_tone, *new_tones) | 119 | return Chord(main_tone, *new_tones) | ||
| 122 | 120 | ||||
| 123 | def __str__(self): | 121 | def __str__(self): | ||
| 124 | return "-".join(self.sorted_tones) | 122 | return "-".join(self.sorted_tones) | ||
| 125 | 123 | ||||
| 126 | def is_minor(self): | 124 | def is_minor(self): | ||
| 127 | main_index = self.main_tone.index | 125 | main_index = self.main_tone.index | ||
| 128 | for tone in self.uniques_to_list_objs_tones: | 126 | for tone in self.uniques_to_list_objs_tones: | ||
| 129 | interval = Interval(abs(main_index - tone.index)) | 127 | interval = Interval(abs(main_index - tone.index)) | ||
| 130 | if str(interval) == "minor 3rd": | 128 | if str(interval) == "minor 3rd": | ||
| 131 | return True | 129 | return True | ||
| 132 | return False | 130 | return False | ||
| 133 | 131 | ||||
| 134 | def is_major(self): | 132 | def is_major(self): | ||
| 135 | main_index = self.main_tone.index | 133 | main_index = self.main_tone.index | ||
| 136 | for tone in self.uniques_to_list_objs_tones: | 134 | for tone in self.uniques_to_list_objs_tones: | ||
| 137 | interval = Interval(abs(main_index - tone.index)) | 135 | interval = Interval(abs(main_index - tone.index)) | ||
| 138 | if str(interval) == "major 3rd": | 136 | if str(interval) == "major 3rd": | ||
| 139 | return True | 137 | return True | ||
| 140 | return False | 138 | return False | ||
| 141 | 139 | ||||
| 142 | def is_power_chord(self): | 140 | def is_power_chord(self): | ||
| 143 | return not self.is_major() and not self.is_minor() | 141 | return not self.is_major() and not self.is_minor() | ||
| 144 | 142 | ||||
| 145 | def transposed(self, interval): | 143 | def transposed(self, interval): | ||
| 146 | transposed_tones = [tone + interval for tone in self.sorted_to_list_objs_tones] | 144 | transposed_tones = [tone + interval for tone in self.sorted_to_list_objs_tones] | ||
| 147 | return Chord(transposed_tones[0], *transposed_tones[1:]) | 145 | return Chord(transposed_tones[0], *transposed_tones[1:]) | ||
| 148 | 146 | ||||
| 149 | 147 |
| Legends | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
| |||||||||
| f | 1 | TONE_INDEX_DICT = {"C" : 0, "C#" : 1, "D" : 2, "D#" : 3, "E" : 4, "F" : 5, "F#" : 6, "G" : 7, "G#" : 8, "A" : 9, "A#" : 10, "B" : 11} | f | 1 | TONE_INDEX_DICT = {"C" : 0, "C#" : 1, "D" : 2, "D#" : 3, "E" : 4, "F" : 5, "F#" : 6, "G" : 7, "G#" : 8, "A" : 9, "A#" : 10, "B" : 11} |
| 2 | TONE_VALUE_LIST = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"] | 2 | TONE_VALUE_LIST = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"] | ||
| 3 | INTERVAL_VALUE_LIST = ["unison", "minor 2nd", "major 2nd", "minor 3rd", "major 3rd", "perfect 4th", "diminished 5th", "perfect 5th", "minor 6th", "major 6th", "minor 7th", "major 7th"] | 3 | INTERVAL_VALUE_LIST = ["unison", "minor 2nd", "major 2nd", "minor 3rd", "major 3rd", "perfect 4th", "diminished 5th", "perfect 5th", "minor 6th", "major 6th", "minor 7th", "major 7th"] | ||
| 4 | MAX_INDEX = 12 | 4 | MAX_INDEX = 12 | ||
| 5 | 5 | ||||
| 6 | class Tone: | 6 | class Tone: | ||
| 7 | def __init__(self, name): | 7 | def __init__(self, name): | ||
| 8 | self.name = name | 8 | self.name = name | ||
| 9 | 9 | ||||
| 10 | def __str__(self): | 10 | def __str__(self): | ||
| 11 | return self.name | 11 | return self.name | ||
| 12 | 12 | ||||
| 13 | def __add__(self, other): | 13 | def __add__(self, other): | ||
| n | 14 | if isinstance(other,Tone): | n | 14 | if isinstance(other, Tone): |
| 15 | return Chord(self,other) | 15 | return Chord(self, other) | ||
| 16 | if isinstance(other,Interval): | 16 | if isinstance(other, Interval): | ||
| 17 | total_len = other.lenght + TONE_INDEX_DICT[self.name] | 17 | total_len = other.lenght + TONE_INDEX_DICT[self.name] | ||
| 18 | correct_index = int(total_len / MAX_INDEX) | 18 | correct_index = int(total_len / MAX_INDEX) | ||
| 19 | correct_len = total_len - correct_index*MAX_INDEX | 19 | correct_len = total_len - correct_index*MAX_INDEX | ||
| 20 | return Tone(TONE_VALUE_LIST[correct_len]) | 20 | return Tone(TONE_VALUE_LIST[correct_len]) | ||
| 21 | 21 | ||||
| 22 | def __sub__(self, other): | 22 | def __sub__(self, other): | ||
| n | 23 | if isinstance(other,Tone): | n | 23 | if isinstance(other, Tone): |
| 24 | return Interval(abs(self.index - other.index)) | 24 | return Interval(abs(self.index - other.index)) | ||
| n | 25 | if isinstance(other,Interval): | n | 25 | if isinstance(other, Interval): |
| 26 | cur_index = TONE_INDEX_DICT[self.name] | 26 | cur_index = TONE_INDEX_DICT[self.name] | ||
| 27 | wanted_index = cur_index - other.lenght + MAX_INDEX | 27 | wanted_index = cur_index - other.lenght + MAX_INDEX | ||
| 28 | return TONE_VALUE_LIST[wanted_index] | 28 | return TONE_VALUE_LIST[wanted_index] | ||
| 29 | 29 | ||||
| 30 | @property | 30 | @property | ||
| 31 | def index(self): | 31 | def index(self): | ||
| 32 | return TONE_INDEX_DICT[self.name] | 32 | return TONE_INDEX_DICT[self.name] | ||
| 33 | 33 | ||||
| 34 | class Interval: | 34 | class Interval: | ||
| 35 | def __init__(self, lenght): | 35 | def __init__(self, lenght): | ||
| 36 | correct_index = int(lenght / MAX_INDEX) | 36 | correct_index = int(lenght / MAX_INDEX) | ||
| n | 37 | self.lenght = lenght - correct_index*MAX_INDEX | n | 37 | self.lenght = lenght - correct_index*MAX_INDEX |
| 38 | 38 | ||||
| 39 | def __str__(self): | 39 | def __str__(self): | ||
| n | 40 | n | |||
| 41 | return INTERVAL_VALUE_LIST[self.lenght] | 40 | return INTERVAL_VALUE_LIST[self.lenght] | ||
| 42 | 41 | ||||
| 43 | def __add__(self,other): | 42 | def __add__(self,other): | ||
| 44 | if isinstance(other,Tone): | 43 | if isinstance(other,Tone): | ||
| 45 | raise TypeError("Invalid operation") | 44 | raise TypeError("Invalid operation") | ||
| 46 | if isinstance(other,Interval): | 45 | if isinstance(other,Interval): | ||
| 47 | total_len = self.lenght + other.lenght | 46 | total_len = self.lenght + other.lenght | ||
| 48 | correct_index = int(total_len / MAX_INDEX) | 47 | correct_index = int(total_len / MAX_INDEX) | ||
| 49 | correct_len = total_len - correct_index*MAX_INDEX | 48 | correct_len = total_len - correct_index*MAX_INDEX | ||
| 50 | return INTERVAL_VALUE_LIST[correct_len] | 49 | return INTERVAL_VALUE_LIST[correct_len] | ||
| 51 | 50 | ||||
| 52 | def __sub__(self,other): | 51 | def __sub__(self,other): | ||
| 53 | if isinstance(other,Tone): | 52 | if isinstance(other,Tone): | ||
| 54 | raise TypeError("Invalid operation") | 53 | raise TypeError("Invalid operation") | ||
| 55 | 54 | ||||
| 56 | def __neg__(self): | 55 | def __neg__(self): | ||
| 57 | correct_index = int(self.lenght / MAX_INDEX) | 56 | correct_index = int(self.lenght / MAX_INDEX) | ||
| 58 | self.lenght = self.lenght - correct_index*MAX_INDEX | 57 | self.lenght = self.lenght - correct_index*MAX_INDEX | ||
| 59 | return Interval(MAX_INDEX-self.lenght) | 58 | return Interval(MAX_INDEX-self.lenght) | ||
| 60 | 59 | ||||
| 61 | class Chord: | 60 | class Chord: | ||
| 62 | def __init_sorted_tones(self): | 61 | def __init_sorted_tones(self): | ||
| 63 | main_index = self.main_tone.index | 62 | main_index = self.main_tone.index | ||
| 64 | tones_dict = {self.main_tone.name : main_index} | 63 | tones_dict = {self.main_tone.name : main_index} | ||
| 65 | for tone in self.uniques_to_list_objs_tones: | 64 | for tone in self.uniques_to_list_objs_tones: | ||
| 66 | tone_index = tone.index | 65 | tone_index = tone.index | ||
| 67 | if main_index > tone_index: | 66 | if main_index > tone_index: | ||
| 68 | tones_dict[tone.name] = tone_index + MAX_INDEX | 67 | tones_dict[tone.name] = tone_index + MAX_INDEX | ||
| 69 | else: | 68 | else: | ||
| 70 | tones_dict[tone.name] = tone_index | 69 | tones_dict[tone.name] = tone_index | ||
| 71 | self.sorted_tones = [key for key, value in sorted(tones_dict.items(), key=lambda item: item[1])] | 70 | self.sorted_tones = [key for key, value in sorted(tones_dict.items(), key=lambda item: item[1])] | ||
| 72 | 71 | ||||
| 73 | @property | 72 | @property | ||
| 74 | def sorted_to_list_objs_tones(self): | 73 | def sorted_to_list_objs_tones(self): | ||
| 75 | tones_objs_list = [] | 74 | tones_objs_list = [] | ||
| 76 | for tone in self.sorted_tones: | 75 | for tone in self.sorted_tones: | ||
| 77 | tones_objs_list.append(Tone(tone)) | 76 | tones_objs_list.append(Tone(tone)) | ||
| 78 | return tones_objs_list | 77 | return tones_objs_list | ||
| 79 | 78 | ||||
| 80 | @property | 79 | @property | ||
| 81 | def uniques_to_list_objs_tones(self): | 80 | def uniques_to_list_objs_tones(self): | ||
| 82 | tones_objs_list = [] | 81 | tones_objs_list = [] | ||
| 83 | for tone in self.unique_tones: | 82 | for tone in self.unique_tones: | ||
| 84 | tones_objs_list.append(Tone(tone)) | 83 | tones_objs_list.append(Tone(tone)) | ||
| 85 | return tones_objs_list | 84 | return tones_objs_list | ||
| 86 | 85 | ||||
| 87 | def __init__(self, main_tone, *tones): | 86 | def __init__(self, main_tone, *tones): | ||
| 88 | self.main_tone = main_tone | 87 | self.main_tone = main_tone | ||
| 89 | self.unique_tones= set() | 88 | self.unique_tones= set() | ||
| 90 | self.sorted_tones = [] | 89 | self.sorted_tones = [] | ||
| 91 | self.unique_tones.add(main_tone.name) | 90 | self.unique_tones.add(main_tone.name) | ||
| 92 | for tone in tones: | 91 | for tone in tones: | ||
| n | 93 | self.unique_tones.add(tone.name) | n | 92 | self.unique_tones.add(tone.name) |
| 94 | |||||
| 95 | valid_len = len(self.unique_tones) | 93 | valid_len = len(self.unique_tones) | ||
| 96 | if valid_len <= 1: | 94 | if valid_len <= 1: | ||
| 97 | raise TypeError("Cannot have a chord made of only 1 unique tone") | 95 | raise TypeError("Cannot have a chord made of only 1 unique tone") | ||
| 98 | self.unique_tones.discard(main_tone.name) | 96 | self.unique_tones.discard(main_tone.name) | ||
| 99 | self.__init_sorted_tones() | 97 | self.__init_sorted_tones() | ||
| 100 | 98 | ||||
| 101 | def __add__(self, other): | 99 | def __add__(self, other): | ||
| 102 | new_tones = self.uniques_to_list_objs_tones | 100 | new_tones = self.uniques_to_list_objs_tones | ||
| 103 | if isinstance(other, Tone): | 101 | if isinstance(other, Tone): | ||
| 104 | new_tones.append(other) | 102 | new_tones.append(other) | ||
| 105 | if isinstance(other,Chord): | 103 | if isinstance(other,Chord): | ||
| 106 | for tone in other.sorted_to_list_objs_tones: | 104 | for tone in other.sorted_to_list_objs_tones: | ||
| 107 | new_tones.append(tone) | 105 | new_tones.append(tone) | ||
| 108 | return Chord(self.main_tone, *new_tones) | 106 | return Chord(self.main_tone, *new_tones) | ||
| 109 | 107 | ||||
| n | 110 | n | |||
| 111 | def __sub__(self, other): | 108 | def __sub__(self, other): | ||
| 112 | if other.name not in self.sorted_tones: | 109 | if other.name not in self.sorted_tones: | ||
| 113 | raise TypeError(f"Cannot remove tone {other.name} from chord {self}") | 110 | raise TypeError(f"Cannot remove tone {other.name} from chord {self}") | ||
| 114 | if len(self.unique_tones) < 2: | 111 | if len(self.unique_tones) < 2: | ||
| 115 | raise TypeError("Cannot have a chord made of only 1 unique tone") | 112 | raise TypeError("Cannot have a chord made of only 1 unique tone") | ||
| 116 | new_tones = self.sorted_to_list_objs_tones | 113 | new_tones = self.sorted_to_list_objs_tones | ||
| 117 | main_tone = self.main_tone | 114 | main_tone = self.main_tone | ||
| 118 | if isinstance(other, Tone): | 115 | if isinstance(other, Tone): | ||
| 119 | if main_tone.name == other.name: | 116 | if main_tone.name == other.name: | ||
| 120 | main_tone = Tone(self.sorted_tones[0]) | 117 | main_tone = Tone(self.sorted_tones[0]) | ||
| 121 | new_tones = filter(lambda tone: tone.name != main_tone.name, new_tones) | 118 | new_tones = filter(lambda tone: tone.name != main_tone.name, new_tones) | ||
| 122 | else: | 119 | else: | ||
| 123 | new_tones = filter(lambda tone: tone.name != other.name, new_tones) | 120 | new_tones = filter(lambda tone: tone.name != other.name, new_tones) | ||
| 124 | return Chord(main_tone, *new_tones) | 121 | return Chord(main_tone, *new_tones) | ||
| 125 | 122 | ||||
| 126 | def __str__(self): | 123 | def __str__(self): | ||
| 127 | return "-".join(self.sorted_tones) | 124 | return "-".join(self.sorted_tones) | ||
| 128 | 125 | ||||
| 129 | def is_minor(self): | 126 | def is_minor(self): | ||
| 130 | main_index = self.main_tone.index | 127 | main_index = self.main_tone.index | ||
| 131 | for tone in self.uniques_to_list_objs_tones: | 128 | for tone in self.uniques_to_list_objs_tones: | ||
| 132 | interval = Interval(abs(main_index - tone.index)) | 129 | interval = Interval(abs(main_index - tone.index)) | ||
| 133 | if str(interval) == "minor 3rd": | 130 | if str(interval) == "minor 3rd": | ||
| 134 | return True | 131 | return True | ||
| 135 | return False | 132 | return False | ||
| 136 | 133 | ||||
| 137 | def is_major(self): | 134 | def is_major(self): | ||
| 138 | main_index = self.main_tone.index | 135 | main_index = self.main_tone.index | ||
| 139 | for tone in self.uniques_to_list_objs_tones: | 136 | for tone in self.uniques_to_list_objs_tones: | ||
| 140 | interval = Interval(abs(main_index - tone.index)) | 137 | interval = Interval(abs(main_index - tone.index)) | ||
| 141 | if str(interval) == "major 3rd": | 138 | if str(interval) == "major 3rd": | ||
| 142 | return True | 139 | return True | ||
| 143 | return False | 140 | return False | ||
| 144 | 141 | ||||
| 145 | def is_power_chord(self): | 142 | def is_power_chord(self): | ||
| 146 | return not self.is_major() and not self.is_minor() | 143 | return not self.is_major() and not self.is_minor() | ||
| 147 | 144 | ||||
| 148 | def transposed(self, interval): | 145 | def transposed(self, interval): | ||
| 149 | transposed_tones = [tone + interval for tone in self.sorted_to_list_objs_tones] | 146 | transposed_tones = [tone + interval for tone in self.sorted_to_list_objs_tones] | ||
| t | 150 | t | |||
| 151 | return Chord(transposed_tones[0], *transposed_tones[1:]) | 147 | return Chord(transposed_tones[0], *transposed_tones[1:]) | ||
| 152 | 148 | ||||
| 153 | 149 |
| Legends | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
| |||||||||
| f | 1 | TONE_INDEX_DICT = {"C" : 0, "C#" : 1, "D" : 2, "D#" : 3, "E" : 4, "F" : 5, "F#" : 6, "G" : 7, "G#" : 8, "A" : 9, "A#" : 10, "B" : 11} | f | 1 | TONE_INDEX_DICT = {"C" : 0, "C#" : 1, "D" : 2, "D#" : 3, "E" : 4, "F" : 5, "F#" : 6, "G" : 7, "G#" : 8, "A" : 9, "A#" : 10, "B" : 11} |
| n | 2 | TONE_VALUE_DICT = {0 : "C", 1: "C#" , 2 : "D" , 3 : "D#" , 4 : "E" , 5 : "F" , 6 : "F#" , 7 : "G" , 8 : "G#" , 9 : "A" , 10 : "A#" , 11 : "B" } | n | 2 | TONE_VALUE_LIST = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"] |
| 3 | INTERVAL_VALUE_DICT = {0 : "unison", 1 : "minor 2nd", 2 : "major 2nd", 3 : "minor 3rd", 4 : "major 3rd", 5 : "perfect 4th", 6 : "diminished 5th", 7 : "perfect 5th", 8 : "minor 6th", 9 : "major 6th", 10 : "minor 7th", 11 : "major 7th"} | 3 | INTERVAL_VALUE_LIST = ["unison", "minor 2nd", "major 2nd", "minor 3rd", "major 3rd", "perfect 4th", "diminished 5th", "perfect 5th", "minor 6th", "major 6th", "minor 7th", "major 7th"] | ||
| 4 | MAX_INDEX = 12 | 4 | MAX_INDEX = 12 | ||
| 5 | 5 | ||||
| 6 | class Tone: | 6 | class Tone: | ||
| 7 | def __init__(self, name): | 7 | def __init__(self, name): | ||
| 8 | self.name = name | 8 | self.name = name | ||
| 9 | 9 | ||||
| 10 | def __str__(self): | 10 | def __str__(self): | ||
| n | 11 | return f"{self.name}" | n | 11 | return self.name |
| 12 | 12 | ||||
| 13 | def __add__(self, other): | 13 | def __add__(self, other): | ||
| 14 | if isinstance(other,Tone): | 14 | if isinstance(other,Tone): | ||
| 15 | return Chord(self,other) | 15 | return Chord(self,other) | ||
| 16 | if isinstance(other,Interval): | 16 | if isinstance(other,Interval): | ||
| 17 | total_len = other.lenght + TONE_INDEX_DICT[self.name] | 17 | total_len = other.lenght + TONE_INDEX_DICT[self.name] | ||
| 18 | correct_index = int(total_len / MAX_INDEX) | 18 | correct_index = int(total_len / MAX_INDEX) | ||
| 19 | correct_len = total_len - correct_index*MAX_INDEX | 19 | correct_len = total_len - correct_index*MAX_INDEX | ||
| n | 20 | return Tone(TONE_VALUE_DICT[correct_len]) | n | 20 | return Tone(TONE_VALUE_LIST[correct_len]) |
| 21 | 21 | ||||
| 22 | def __sub__(self, other): | 22 | def __sub__(self, other): | ||
| 23 | if isinstance(other,Tone): | 23 | if isinstance(other,Tone): | ||
| n | 24 | return Interval(abs(self.get_index()-other.get_index())) | n | 24 | return Interval(abs(self.index - other.index)) |
| 25 | if isinstance(other,Interval): | 25 | if isinstance(other,Interval): | ||
| n | 26 | correct_index = int(other.lenght / MAX_INDEX) | n | ||
| 27 | correct_len = other.lenght - correct_index*MAX_INDEX | ||||
| 28 | cur_index = TONE_INDEX_DICT[self.name] | 26 | cur_index = TONE_INDEX_DICT[self.name] | ||
| n | 29 | wanted_index = cur_index - correct_len + MAX_INDEX | n | 27 | wanted_index = cur_index - other.lenght + MAX_INDEX |
| 30 | return TONE_VALUE_DICT[wanted_index] | 28 | return TONE_VALUE_LIST[wanted_index] | ||
| 31 | 29 | ||||
| 30 | @property | ||||
| 32 | def get_index(self): | 31 | def index(self): | ||
| 33 | return TONE_INDEX_DICT[self.name] | 32 | return TONE_INDEX_DICT[self.name] | ||
| 34 | 33 | ||||
| 35 | @staticmethod | ||||
| 36 | def get_index_for_name(name): | ||||
| 37 | return TONE_INDEX_DICT[name] | ||||
| 38 | |||||
| 39 | |||||
| 40 | |||||
| 41 | class Interval: | 34 | class Interval: | ||
| 42 | def __init__(self, lenght): | 35 | def __init__(self, lenght): | ||
| n | 43 | self.lenght = lenght | n | 36 | correct_index = int(lenght / MAX_INDEX) |
| 44 | 37 | self.lenght = lenght - correct_index*MAX_INDEX | |||
| 38 | |||||
| 45 | def __str__(self): | 39 | def __str__(self): | ||
| n | 46 | correct_index = int(self.lenght / MAX_INDEX) | n | 40 | |
| 47 | correct_len = self.lenght - correct_index*MAX_INDEX | ||||
| 48 | return INTERVAL_VALUE_DICT[correct_len] | 41 | return INTERVAL_VALUE_LIST[self.lenght] | ||
| 49 | 42 | ||||
| 50 | def __add__(self,other): | 43 | def __add__(self,other): | ||
| 51 | if isinstance(other,Tone): | 44 | if isinstance(other,Tone): | ||
| 52 | raise TypeError("Invalid operation") | 45 | raise TypeError("Invalid operation") | ||
| 53 | if isinstance(other,Interval): | 46 | if isinstance(other,Interval): | ||
| 54 | total_len = self.lenght + other.lenght | 47 | total_len = self.lenght + other.lenght | ||
| 55 | correct_index = int(total_len / MAX_INDEX) | 48 | correct_index = int(total_len / MAX_INDEX) | ||
| 56 | correct_len = total_len - correct_index*MAX_INDEX | 49 | correct_len = total_len - correct_index*MAX_INDEX | ||
| n | 57 | return INTERVAL_VALUE_DICT[correct_len] | n | 50 | return INTERVAL_VALUE_LIST[correct_len] |
| 58 | 51 | ||||
| 59 | def __sub__(self,other): | 52 | def __sub__(self,other): | ||
| 60 | if isinstance(other,Tone): | 53 | if isinstance(other,Tone): | ||
| 61 | raise TypeError("Invalid operation") | 54 | raise TypeError("Invalid operation") | ||
| 62 | 55 | ||||
| 63 | def __neg__(self): | 56 | def __neg__(self): | ||
| n | n | 57 | correct_index = int(self.lenght / MAX_INDEX) | ||
| 58 | self.lenght = self.lenght - correct_index*MAX_INDEX | ||||
| 64 | return Interval(-self.lenght) | 59 | return Interval(MAX_INDEX-self.lenght) | ||
| 65 | 60 | ||||
| 66 | class Chord: | 61 | class Chord: | ||
| 67 | def __init_sorted_tones(self): | 62 | def __init_sorted_tones(self): | ||
| n | 68 | main_index = self.main_tone.get_index() | n | 63 | main_index = self.main_tone.index |
| 69 | tones_dict = {self.main_tone.name : main_index} | 64 | tones_dict = {self.main_tone.name : main_index} | ||
| n | 70 | for tone_name in self.unique_tones: | n | 65 | for tone in self.uniques_to_list_objs_tones: |
| 71 | tone_index = Tone.get_index_for_name(tone_name) | 66 | tone_index = tone.index | ||
| 72 | if main_index > tone_index: | 67 | if main_index > tone_index: | ||
| n | 73 | tones_dict[tone_name] = tone_index + 10 | n | 68 | tones_dict[tone.name] = tone_index + MAX_INDEX |
| 74 | else: | 69 | else: | ||
| n | 75 | tones_dict[tone_name] = tone_index | n | 70 | tones_dict[tone.name] = tone_index |
| 76 | self.sorted_tones = [key for key, value in sorted(tones_dict.items(), key=lambda item: item[1])] | 71 | self.sorted_tones = [key for key, value in sorted(tones_dict.items(), key=lambda item: item[1])] | ||
| n | n | 72 | |||
| 73 | @property | ||||
| 74 | def sorted_to_list_objs_tones(self): | ||||
| 75 | tones_objs_list = [] | ||||
| 76 | for tone in self.sorted_tones: | ||||
| 77 | tones_objs_list.append(Tone(tone)) | ||||
| 78 | return tones_objs_list | ||||
| 79 | |||||
| 80 | @property | ||||
| 81 | def uniques_to_list_objs_tones(self): | ||||
| 82 | tones_objs_list = [] | ||||
| 83 | for tone in self.unique_tones: | ||||
| 84 | tones_objs_list.append(Tone(tone)) | ||||
| 85 | return tones_objs_list | ||||
| 77 | 86 | ||||
| 78 | def __init__(self, main_tone, *tones): | 87 | def __init__(self, main_tone, *tones): | ||
| 79 | self.main_tone = main_tone | 88 | self.main_tone = main_tone | ||
| 80 | self.unique_tones= set() | 89 | self.unique_tones= set() | ||
| 81 | self.sorted_tones = [] | 90 | self.sorted_tones = [] | ||
| 82 | self.unique_tones.add(main_tone.name) | 91 | self.unique_tones.add(main_tone.name) | ||
| 83 | for tone in tones: | 92 | for tone in tones: | ||
| 84 | self.unique_tones.add(tone.name) | 93 | self.unique_tones.add(tone.name) | ||
| 85 | 94 | ||||
| 86 | valid_len = len(self.unique_tones) | 95 | valid_len = len(self.unique_tones) | ||
| 87 | if valid_len <= 1: | 96 | if valid_len <= 1: | ||
| n | 88 | raise TypeError(f"Cannot have a chord made of only {valid_len} unique tone") | n | 97 | raise TypeError("Cannot have a chord made of only 1 unique tone") |
| 89 | self.unique_tones.discard(main_tone.name) | 98 | self.unique_tones.discard(main_tone.name) | ||
| 90 | self.__init_sorted_tones() | 99 | self.__init_sorted_tones() | ||
| 91 | 100 | ||||
| 92 | def __add__(self, other): | 101 | def __add__(self, other): | ||
| n | n | 102 | new_tones = self.uniques_to_list_objs_tones | ||
| 93 | if isinstance(other, Tone): | 103 | if isinstance(other, Tone): | ||
| n | 94 | self.unique_tones.add(other.name) | n | 104 | new_tones.append(other) |
| 95 | if isinstance(other,Chord): | 105 | if isinstance(other,Chord): | ||
| n | 96 | for tone_name in other.sorted_tones: | n | 106 | for tone in other.sorted_to_list_objs_tones: |
| 97 | self.unique_tones.add(tone_name) | 107 | new_tones.append(tone) | ||
| 98 | return self | 108 | return Chord(self.main_tone, *new_tones) | ||
| 99 | 109 | ||||
| 100 | 110 | ||||
| 101 | def __sub__(self, other): | 111 | def __sub__(self, other): | ||
| n | 102 | if not other.name in self.sorted_tones: | n | 112 | if other.name not in self.sorted_tones: |
| 103 | raise TypeError(f"Cannot remove tone {other.name} from chord {self}") | 113 | raise TypeError(f"Cannot remove tone {other.name} from chord {self}") | ||
| 104 | if len(self.unique_tones) < 2: | 114 | if len(self.unique_tones) < 2: | ||
| 105 | raise TypeError("Cannot have a chord made of only 1 unique tone") | 115 | raise TypeError("Cannot have a chord made of only 1 unique tone") | ||
| n | n | 116 | new_tones = self.sorted_to_list_objs_tones | ||
| 117 | main_tone = self.main_tone | ||||
| 106 | if isinstance(other, Tone): | 118 | if isinstance(other, Tone): | ||
| n | 107 | if self.main_tone.name == other.name: | n | 119 | if main_tone.name == other.name: |
| 108 | self.main_tone = Tone(self.sorted_tones[0]) | 120 | main_tone = Tone(self.sorted_tones[0]) | ||
| 109 | self.unique_tones.discard(self.main_tone.name) | 121 | new_tones = filter(lambda tone: tone.name != main_tone.name, new_tones) | ||
| 110 | else: | 122 | else: | ||
| n | 111 | self.unique_tones.discard(other.name) | n | 123 | new_tones = filter(lambda tone: tone.name != other.name, new_tones) |
| 112 | return self | 124 | return Chord(main_tone, *new_tones) | ||
| 113 | 125 | ||||
| 114 | def __str__(self): | 126 | def __str__(self): | ||
| n | 115 | self.__init_sorted_tones() | n | ||
| 116 | return "-".join(self.sorted_tones) | 127 | return "-".join(self.sorted_tones) | ||
| 117 | 128 | ||||
| 118 | def is_minor(self): | 129 | def is_minor(self): | ||
| n | 119 | main_index = self.main_tone.get_index() | n | 130 | main_index = self.main_tone.index |
| 120 | for tone_name in self.unique_tones: | 131 | for tone in self.uniques_to_list_objs_tones: | ||
| 121 | tone_index = Tone.get_index_for_name(tone_name) | ||||
| 122 | interval = Interval(abs(main_index - tone_index)) | 132 | interval = Interval(abs(main_index - tone.index)) | ||
| 123 | if str(interval) == "minor 3rd": | 133 | if str(interval) == "minor 3rd": | ||
| 124 | return True | 134 | return True | ||
| 125 | return False | 135 | return False | ||
| 126 | 136 | ||||
| 127 | def is_major(self): | 137 | def is_major(self): | ||
| n | 128 | main_index = self.main_tone.get_index() | n | 138 | main_index = self.main_tone.index |
| 129 | for tone_name in self.unique_tones: | 139 | for tone in self.uniques_to_list_objs_tones: | ||
| 130 | tone_index = Tone.get_index_for_name(tone_name) | ||||
| 131 | interval = Interval(abs(main_index - tone_index)) | 140 | interval = Interval(abs(main_index - tone.index)) | ||
| 132 | if str(interval) == "major 3rd": | 141 | if str(interval) == "major 3rd": | ||
| 133 | return True | 142 | return True | ||
| 134 | return False | 143 | return False | ||
| 135 | 144 | ||||
| 136 | def is_power_chord(self): | 145 | def is_power_chord(self): | ||
| 137 | return not self.is_major() and not self.is_minor() | 146 | return not self.is_major() and not self.is_minor() | ||
| 138 | 147 | ||||
| 139 | def transposed(self, interval): | 148 | def transposed(self, interval): | ||
| n | 140 | transposing = interval.lenght | n | 149 | transposed_tones = [tone + interval for tone in self.sorted_to_list_objs_tones] |
| 141 | transposed_tones = [] | 150 | |||
| 142 | tone_name_transposed = "" | 151 | return Chord(transposed_tones[0], *transposed_tones[1:]) | ||
| 143 | for tone_name in self.sorted_tones: | ||||
| 144 | index = Tone.get_index_for_name(tone_name) | ||||
| 145 | if(transposing >= 0): | ||||
| 146 | tone_name_transposed = (TONE_VALUE_DICT[index + transposing]) | ||||
| 147 | else: | ||||
| 148 | if(index + transposing < 0): | ||||
| 149 | tone_name_transposed = (TONE_VALUE_DICT[index + transposing + MAX_INDEX]) | ||||
| 150 | else: | ||||
| 151 | tone_name_transposed = (TONE_VALUE_DICT[index + transposing]) | ||||
| 152 | 152 | ||||
| 153 | 153 | ||||
| t | 154 | transposed_tones.append(Tone(tone_name_transposed)) | t | ||
| 155 | |||||
| 156 | return Chord(transposed_tones[0], *transposed_tones[1:]) | ||||
| 157 | |||||
| 158 | |||||
| 159 |
| Legends | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
| |||||||||
| f | 1 | TONE_INDEX_DICT = {"C" : 0, "C#" : 1, "D" : 2, "D#" : 3, "E" : 4, "F" : 5, "F#" : 6, "G" : 7, "G#" : 8, "A" : 9, "A#" : 10, "B" : 11} | f | 1 | TONE_INDEX_DICT = {"C" : 0, "C#" : 1, "D" : 2, "D#" : 3, "E" : 4, "F" : 5, "F#" : 6, "G" : 7, "G#" : 8, "A" : 9, "A#" : 10, "B" : 11} |
| 2 | TONE_VALUE_DICT = {0 : "C", 1: "C#" , 2 : "D" , 3 : "D#" , 4 : "E" , 5 : "F" , 6 : "F#" , 7 : "G" , 8 : "G#" , 9 : "A" , 10 : "A#" , 11 : "B" } | 2 | TONE_VALUE_DICT = {0 : "C", 1: "C#" , 2 : "D" , 3 : "D#" , 4 : "E" , 5 : "F" , 6 : "F#" , 7 : "G" , 8 : "G#" , 9 : "A" , 10 : "A#" , 11 : "B" } | ||
| 3 | INTERVAL_VALUE_DICT = {0 : "unison", 1 : "minor 2nd", 2 : "major 2nd", 3 : "minor 3rd", 4 : "major 3rd", 5 : "perfect 4th", 6 : "diminished 5th", 7 : "perfect 5th", 8 : "minor 6th", 9 : "major 6th", 10 : "minor 7th", 11 : "major 7th"} | 3 | INTERVAL_VALUE_DICT = {0 : "unison", 1 : "minor 2nd", 2 : "major 2nd", 3 : "minor 3rd", 4 : "major 3rd", 5 : "perfect 4th", 6 : "diminished 5th", 7 : "perfect 5th", 8 : "minor 6th", 9 : "major 6th", 10 : "minor 7th", 11 : "major 7th"} | ||
| 4 | MAX_INDEX = 12 | 4 | MAX_INDEX = 12 | ||
| 5 | 5 | ||||
| 6 | class Tone: | 6 | class Tone: | ||
| 7 | def __init__(self, name): | 7 | def __init__(self, name): | ||
| 8 | self.name = name | 8 | self.name = name | ||
| 9 | 9 | ||||
| 10 | def __str__(self): | 10 | def __str__(self): | ||
| 11 | return f"{self.name}" | 11 | return f"{self.name}" | ||
| 12 | 12 | ||||
| 13 | def __add__(self, other): | 13 | def __add__(self, other): | ||
| 14 | if isinstance(other,Tone): | 14 | if isinstance(other,Tone): | ||
| 15 | return Chord(self,other) | 15 | return Chord(self,other) | ||
| 16 | if isinstance(other,Interval): | 16 | if isinstance(other,Interval): | ||
| 17 | total_len = other.lenght + TONE_INDEX_DICT[self.name] | 17 | total_len = other.lenght + TONE_INDEX_DICT[self.name] | ||
| 18 | correct_index = int(total_len / MAX_INDEX) | 18 | correct_index = int(total_len / MAX_INDEX) | ||
| 19 | correct_len = total_len - correct_index*MAX_INDEX | 19 | correct_len = total_len - correct_index*MAX_INDEX | ||
| 20 | return Tone(TONE_VALUE_DICT[correct_len]) | 20 | return Tone(TONE_VALUE_DICT[correct_len]) | ||
| 21 | 21 | ||||
| 22 | def __sub__(self, other): | 22 | def __sub__(self, other): | ||
| 23 | if isinstance(other,Tone): | 23 | if isinstance(other,Tone): | ||
| 24 | return Interval(abs(self.get_index()-other.get_index())) | 24 | return Interval(abs(self.get_index()-other.get_index())) | ||
| 25 | if isinstance(other,Interval): | 25 | if isinstance(other,Interval): | ||
| 26 | correct_index = int(other.lenght / MAX_INDEX) | 26 | correct_index = int(other.lenght / MAX_INDEX) | ||
| 27 | correct_len = other.lenght - correct_index*MAX_INDEX | 27 | correct_len = other.lenght - correct_index*MAX_INDEX | ||
| 28 | cur_index = TONE_INDEX_DICT[self.name] | 28 | cur_index = TONE_INDEX_DICT[self.name] | ||
| 29 | wanted_index = cur_index - correct_len + MAX_INDEX | 29 | wanted_index = cur_index - correct_len + MAX_INDEX | ||
| 30 | return TONE_VALUE_DICT[wanted_index] | 30 | return TONE_VALUE_DICT[wanted_index] | ||
| 31 | 31 | ||||
| 32 | def get_index(self): | 32 | def get_index(self): | ||
| 33 | return TONE_INDEX_DICT[self.name] | 33 | return TONE_INDEX_DICT[self.name] | ||
| 34 | 34 | ||||
| 35 | @staticmethod | 35 | @staticmethod | ||
| 36 | def get_index_for_name(name): | 36 | def get_index_for_name(name): | ||
| 37 | return TONE_INDEX_DICT[name] | 37 | return TONE_INDEX_DICT[name] | ||
| 38 | 38 | ||||
| 39 | 39 | ||||
| 40 | 40 | ||||
| 41 | class Interval: | 41 | class Interval: | ||
| 42 | def __init__(self, lenght): | 42 | def __init__(self, lenght): | ||
| 43 | self.lenght = lenght | 43 | self.lenght = lenght | ||
| 44 | 44 | ||||
| 45 | def __str__(self): | 45 | def __str__(self): | ||
| 46 | correct_index = int(self.lenght / MAX_INDEX) | 46 | correct_index = int(self.lenght / MAX_INDEX) | ||
| 47 | correct_len = self.lenght - correct_index*MAX_INDEX | 47 | correct_len = self.lenght - correct_index*MAX_INDEX | ||
| 48 | return INTERVAL_VALUE_DICT[correct_len] | 48 | return INTERVAL_VALUE_DICT[correct_len] | ||
| 49 | 49 | ||||
| 50 | def __add__(self,other): | 50 | def __add__(self,other): | ||
| 51 | if isinstance(other,Tone): | 51 | if isinstance(other,Tone): | ||
| 52 | raise TypeError("Invalid operation") | 52 | raise TypeError("Invalid operation") | ||
| 53 | if isinstance(other,Interval): | 53 | if isinstance(other,Interval): | ||
| 54 | total_len = self.lenght + other.lenght | 54 | total_len = self.lenght + other.lenght | ||
| 55 | correct_index = int(total_len / MAX_INDEX) | 55 | correct_index = int(total_len / MAX_INDEX) | ||
| 56 | correct_len = total_len - correct_index*MAX_INDEX | 56 | correct_len = total_len - correct_index*MAX_INDEX | ||
| 57 | return INTERVAL_VALUE_DICT[correct_len] | 57 | return INTERVAL_VALUE_DICT[correct_len] | ||
| 58 | 58 | ||||
| 59 | def __sub__(self,other): | 59 | def __sub__(self,other): | ||
| 60 | if isinstance(other,Tone): | 60 | if isinstance(other,Tone): | ||
| 61 | raise TypeError("Invalid operation") | 61 | raise TypeError("Invalid operation") | ||
| 62 | 62 | ||||
| 63 | def __neg__(self): | 63 | def __neg__(self): | ||
| 64 | return Interval(-self.lenght) | 64 | return Interval(-self.lenght) | ||
| 65 | 65 | ||||
| 66 | class Chord: | 66 | class Chord: | ||
| 67 | def __init_sorted_tones(self): | 67 | def __init_sorted_tones(self): | ||
| 68 | main_index = self.main_tone.get_index() | 68 | main_index = self.main_tone.get_index() | ||
| 69 | tones_dict = {self.main_tone.name : main_index} | 69 | tones_dict = {self.main_tone.name : main_index} | ||
| 70 | for tone_name in self.unique_tones: | 70 | for tone_name in self.unique_tones: | ||
| 71 | tone_index = Tone.get_index_for_name(tone_name) | 71 | tone_index = Tone.get_index_for_name(tone_name) | ||
| 72 | if main_index > tone_index: | 72 | if main_index > tone_index: | ||
| 73 | tones_dict[tone_name] = tone_index + 10 | 73 | tones_dict[tone_name] = tone_index + 10 | ||
| 74 | else: | 74 | else: | ||
| 75 | tones_dict[tone_name] = tone_index | 75 | tones_dict[tone_name] = tone_index | ||
| 76 | self.sorted_tones = [key for key, value in sorted(tones_dict.items(), key=lambda item: item[1])] | 76 | self.sorted_tones = [key for key, value in sorted(tones_dict.items(), key=lambda item: item[1])] | ||
| 77 | 77 | ||||
| 78 | def __init__(self, main_tone, *tones): | 78 | def __init__(self, main_tone, *tones): | ||
| 79 | self.main_tone = main_tone | 79 | self.main_tone = main_tone | ||
| 80 | self.unique_tones= set() | 80 | self.unique_tones= set() | ||
| 81 | self.sorted_tones = [] | 81 | self.sorted_tones = [] | ||
| 82 | self.unique_tones.add(main_tone.name) | 82 | self.unique_tones.add(main_tone.name) | ||
| 83 | for tone in tones: | 83 | for tone in tones: | ||
| 84 | self.unique_tones.add(tone.name) | 84 | self.unique_tones.add(tone.name) | ||
| 85 | 85 | ||||
| 86 | valid_len = len(self.unique_tones) | 86 | valid_len = len(self.unique_tones) | ||
| 87 | if valid_len <= 1: | 87 | if valid_len <= 1: | ||
| 88 | raise TypeError(f"Cannot have a chord made of only {valid_len} unique tone") | 88 | raise TypeError(f"Cannot have a chord made of only {valid_len} unique tone") | ||
| 89 | self.unique_tones.discard(main_tone.name) | 89 | self.unique_tones.discard(main_tone.name) | ||
| 90 | self.__init_sorted_tones() | 90 | self.__init_sorted_tones() | ||
| 91 | 91 | ||||
| 92 | def __add__(self, other): | 92 | def __add__(self, other): | ||
| 93 | if isinstance(other, Tone): | 93 | if isinstance(other, Tone): | ||
| 94 | self.unique_tones.add(other.name) | 94 | self.unique_tones.add(other.name) | ||
| 95 | if isinstance(other,Chord): | 95 | if isinstance(other,Chord): | ||
| 96 | for tone_name in other.sorted_tones: | 96 | for tone_name in other.sorted_tones: | ||
| 97 | self.unique_tones.add(tone_name) | 97 | self.unique_tones.add(tone_name) | ||
| 98 | return self | 98 | return self | ||
| 99 | 99 | ||||
| 100 | 100 | ||||
| 101 | def __sub__(self, other): | 101 | def __sub__(self, other): | ||
| 102 | if not other.name in self.sorted_tones: | 102 | if not other.name in self.sorted_tones: | ||
| 103 | raise TypeError(f"Cannot remove tone {other.name} from chord {self}") | 103 | raise TypeError(f"Cannot remove tone {other.name} from chord {self}") | ||
| 104 | if len(self.unique_tones) < 2: | 104 | if len(self.unique_tones) < 2: | ||
| 105 | raise TypeError("Cannot have a chord made of only 1 unique tone") | 105 | raise TypeError("Cannot have a chord made of only 1 unique tone") | ||
| 106 | if isinstance(other, Tone): | 106 | if isinstance(other, Tone): | ||
| 107 | if self.main_tone.name == other.name: | 107 | if self.main_tone.name == other.name: | ||
| 108 | self.main_tone = Tone(self.sorted_tones[0]) | 108 | self.main_tone = Tone(self.sorted_tones[0]) | ||
| 109 | self.unique_tones.discard(self.main_tone.name) | 109 | self.unique_tones.discard(self.main_tone.name) | ||
| 110 | else: | 110 | else: | ||
| 111 | self.unique_tones.discard(other.name) | 111 | self.unique_tones.discard(other.name) | ||
| 112 | return self | 112 | return self | ||
| 113 | 113 | ||||
| 114 | def __str__(self): | 114 | def __str__(self): | ||
| 115 | self.__init_sorted_tones() | 115 | self.__init_sorted_tones() | ||
| 116 | return "-".join(self.sorted_tones) | 116 | return "-".join(self.sorted_tones) | ||
| 117 | 117 | ||||
| 118 | def is_minor(self): | 118 | def is_minor(self): | ||
| 119 | main_index = self.main_tone.get_index() | 119 | main_index = self.main_tone.get_index() | ||
| 120 | for tone_name in self.unique_tones: | 120 | for tone_name in self.unique_tones: | ||
| 121 | tone_index = Tone.get_index_for_name(tone_name) | 121 | tone_index = Tone.get_index_for_name(tone_name) | ||
| 122 | interval = Interval(abs(main_index - tone_index)) | 122 | interval = Interval(abs(main_index - tone_index)) | ||
| 123 | if str(interval) == "minor 3rd": | 123 | if str(interval) == "minor 3rd": | ||
| 124 | return True | 124 | return True | ||
| 125 | return False | 125 | return False | ||
| 126 | 126 | ||||
| 127 | def is_major(self): | 127 | def is_major(self): | ||
| 128 | main_index = self.main_tone.get_index() | 128 | main_index = self.main_tone.get_index() | ||
| 129 | for tone_name in self.unique_tones: | 129 | for tone_name in self.unique_tones: | ||
| 130 | tone_index = Tone.get_index_for_name(tone_name) | 130 | tone_index = Tone.get_index_for_name(tone_name) | ||
| 131 | interval = Interval(abs(main_index - tone_index)) | 131 | interval = Interval(abs(main_index - tone_index)) | ||
| 132 | if str(interval) == "major 3rd": | 132 | if str(interval) == "major 3rd": | ||
| 133 | return True | 133 | return True | ||
| 134 | return False | 134 | return False | ||
| 135 | 135 | ||||
| 136 | def is_power_chord(self): | 136 | def is_power_chord(self): | ||
| 137 | return not self.is_major() and not self.is_minor() | 137 | return not self.is_major() and not self.is_minor() | ||
| 138 | 138 | ||||
| t | 139 | def transposed(self,interval): | t | 139 | def transposed(self, interval): |
| 140 | transposing = interval.lenght | 140 | transposing = interval.lenght | ||
| 141 | transposed_tones = [] | 141 | transposed_tones = [] | ||
| 142 | tone_name_transposed = "" | 142 | tone_name_transposed = "" | ||
| 143 | for tone_name in self.sorted_tones: | 143 | for tone_name in self.sorted_tones: | ||
| 144 | index = Tone.get_index_for_name(tone_name) | 144 | index = Tone.get_index_for_name(tone_name) | ||
| 145 | if(transposing >= 0): | 145 | if(transposing >= 0): | ||
| 146 | tone_name_transposed = (TONE_VALUE_DICT[index + transposing]) | 146 | tone_name_transposed = (TONE_VALUE_DICT[index + transposing]) | ||
| 147 | else: | 147 | else: | ||
| 148 | if(index + transposing < 0): | 148 | if(index + transposing < 0): | ||
| 149 | tone_name_transposed = (TONE_VALUE_DICT[index + transposing + MAX_INDEX]) | 149 | tone_name_transposed = (TONE_VALUE_DICT[index + transposing + MAX_INDEX]) | ||
| 150 | else: | 150 | else: | ||
| 151 | tone_name_transposed = (TONE_VALUE_DICT[index + transposing]) | 151 | tone_name_transposed = (TONE_VALUE_DICT[index + transposing]) | ||
| 152 | 152 | ||||
| 153 | 153 | ||||
| 154 | transposed_tones.append(Tone(tone_name_transposed)) | 154 | transposed_tones.append(Tone(tone_name_transposed)) | ||
| 155 | 155 | ||||
| 156 | return Chord(transposed_tones[0], *transposed_tones[1:]) | 156 | return Chord(transposed_tones[0], *transposed_tones[1:]) | ||
| 157 | 157 | ||||
| 158 | 158 | ||||
| 159 | 159 |
| Legends | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
| |||||||||