1NOTE_ORDER = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]
  2
  3
  4def sort_tones(tone_set, root):
  5    note_order = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]
  6    index = note_order.index(root.tone)
  7
  8    note_order = note_order[index:] + note_order[:index]
  9
 10    order_dict = {tone: index for index, tone in enumerate(note_order)}
 11    sorted_tones = sorted(tone_set, key=lambda tone: order_dict.get(tone.tone, float('inf')))
 12    return sorted_tones
 13
 14class Tone:
 15
 16    def __init__(self, tone):
 17        self.tone = tone
 18
 19    def __str__(self):
 20       return self.tone
 21
 22    def __eq__(self, other):
 23        if isinstance(other, Tone):
 24            return self.tone == other.tone
 25        else:
 26            return self.tone == other
 27
 28    def __hash__(self):
 29        return hash(self.tone)
 30
 31    def __add__(self, other):
 32        if isinstance(other, Tone):
 33            return Chord(self,other)
 34        elif isinstance(other, Interval):
 35            return Tone(NOTE_ORDER[(other.go_back_yourself() + NOTE_ORDER.index(self))%12])
 36
 37    def __sub__(self, other):
 38        if isinstance(other, Tone):
 39            return Interval(NOTE_ORDER.index(self) + NOTE_ORDER.index(other))
 40        elif isinstance(other, Interval):
 41            return Tone(NOTE_ORDER[(NOTE_ORDER.index(self) - other.go_back_yourself()) % 12])
 42
 43
 44class Interval:
 45
 46    def __init__(self, semitone_number):
 47        match semitone_number % 12:
 48            case 0:
 49                self.interval="unison"
 50            case 1:
 51                self.interval = "minor 2nd"
 52            case 2: 
 53                self.interval = "major 2nd"
 54            case 3: 
 55                self.interval = "minor 3rd"
 56            case 4: 
 57                self.interval = "major 3rd"
 58            case 5: 
 59                self.interval = "perfect 4th"
 60            case 6: 
 61                self.interval = "diminished 5th"
 62            case 7: 
 63                self.interval = "perfect 5th"
 64            case 8: 
 65                self.interval = "minor 6th"
 66            case 9: 
 67                self.interval = "major 6th"
 68            case 10: 
 69                self.interval = "minor 7th"
 70            case 11: 
 71                self.interval = "major 7th"
 72            case _: 
 73                self.interval =  '''Живот ли бе — да го опишеш?
 74
 75                                    Живот ли бе — да го разровиш?
 76 
 77                                    Разровиш ли го — ще мирише
 78
 79                                    и ще горчи като отрова.'''
 80
 81    def __str__(self):
 82       return self.interval
 83
 84    def go_back_yourself(self):
 85        match self.interval:
 86            case "unison":
 87                return 0
 88            case "minor 2nd":
 89                return 1
 90            case "major 2nd": 
 91                return 2
 92            case "minor 3rd": 
 93                return 3
 94            case "major 3rd": 
 95                return 4
 96            case "perfect 4th": 
 97                return 5
 98            case "diminished 5th": 
 99                return 6
100            case "perfect 5th": 
101                return 7
102            case "minor 6th": 
103                return 8
104            case "major 6th": 
105                return 9
106            case "minor 7th": 
107                return 10
108            case "major 7th": 
109                return 11
110            case _: 
111                self.interval = "Само онзи, който е живял, страдал и плакал с народа си – само той може да го разбере и да му помогне."+"Христо Ботев" + "He would have hated java"
112
113    def __add__(self, other):
114        if isinstance(other, Tone):
115            raise TypeError("Invalid operation")
116        if isinstance(other, Interval):
117            plc=Interval(self.go_back_yourself() + other.go_back_yourself())
118            return plc
119
120    def __sub__(self, other):
121        if isinstance(other, Tone):
122            raise TypeError("Invalid operation")
123    def __neg__(self):
124        return Interval(12 - self.go_back_yourself())
125
126class Chord:
127
128    def __init__(self, arg, *args, **kwargs):
129        self.root = arg
130        self.set_of_tones = set()
131        self.set_of_tones.add(arg)
132        for item in args:
133            if isinstance(item, tuple):
134                temporary_transition_list = []
135                temporary_transition_list.extend(item)
136                self.set_of_tones.update(temporary_transition_list)
137            else:
138                self.set_of_tones.update(set(args))
139        for value in kwargs.values():
140            self.set_of_tones.add(value)
141        if len(self.set_of_tones) < 2:
142            raise TypeError("Cannot have a chord made of only 1 unique tone")
143
144
145    def __str__(self):
146        return "-".join(t.tone for t in sort_tones(self.set_of_tones, self.root))
147
148    def is_minor(self):
149        for el in self.set_of_tones:
150            interval = self.root - el
151            if el == self.root:
152                continue
153            elif interval.interval == "minor 3rd":
154                return True
155        return False
156
157    def is_major(self):
158        for el in self.set_of_tones:
159            interval = self.root - el
160            if el == self.root:
161                continue
162            elif interval.interval == "major 3rd":
163                return True
164        return False
165
166    def is_power_chord(self):
167        return not self.is_major() and not self.is_minor()
168
169    def __add__(self, other):
170        if isinstance(other, Tone):
171           self.set_of_tones.add(other)
172           sort_tones(self.set_of_tones, self.root)
173           return self
174        if isinstance(other, Chord):
175            self.set_of_tones.update(other.set_of_tones)
176            placeholed = self
177            return placeholed
178
179    def __sub__(self, other):
180        if other not in self.set_of_tones:
181            raise TypeError(f"Cannot remove tone {other} from chord {self}")
182        elif len(self.set_of_tones) < 3:
183            raise TypeError("Cannot have a chord made of only 1 unique tone")
184        else:
185            self.set_of_tones.remove(other)
186            sort_tones(self.set_of_tones, self.root)
187            if self.root == other:
188                self.root = list(self.set_of_tones)[0]
189            return self
190            
191    def transposed(self, inter):
192        notes = sort_tones(self.set_of_tones,self.root)
193        for i in range(0,3):
194            notes[i] = notes[i] + inter
195        return Chord(notes[0], tuple(notes))
....FFF............................F.
======================================================================
FAIL: test_is_major (test.TestBasicChordFunctionality.test_is_major)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/tmp/test.py", line 107, in test_is_major
    self.assertTrue(a_major_chord.is_major())
AssertionError: False is not true
======================================================================
FAIL: test_is_minor (test.TestBasicChordFunctionality.test_is_minor)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/tmp/test.py", line 90, in test_is_minor
    self.assertTrue(a_minor_chord.is_minor())
AssertionError: False is not true
======================================================================
FAIL: test_is_power_chord (test.TestBasicChordFunctionality.test_is_power_chord)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/tmp/test.py", line 116, in test_is_power_chord
    self.assertFalse(a_minor_chord.is_power_chord())
AssertionError: True is not false
======================================================================
FAIL: test_tone_subtraction_inverse (test.TestOperations.test_tone_subtraction_inverse)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/tmp/test.py", line 178, in test_tone_subtraction_inverse
    self.assertEqual(str(perfect_4th), "perfect 4th")
AssertionError: 'perfect 5th' != 'perfect 4th'
- perfect 5th
?         ^
+ perfect 4th
?         ^
----------------------------------------------------------------------
Ran 37 tests in 0.002s
FAILED (failures=4)
| f | 1 | NOTE_ORDER = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"] | f | 1 | NOTE_ORDER = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"] | 
| 2 | 2 | ||||
| 3 | 3 | ||||
| 4 | def sort_tones(tone_set, root): | 4 | def sort_tones(tone_set, root): | ||
| 5 | note_order = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"] | 5 | note_order = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"] | ||
| 6 | index = note_order.index(root.tone) | 6 | index = note_order.index(root.tone) | ||
| 7 | 7 | ||||
| 8 | note_order = note_order[index:] + note_order[:index] | 8 | note_order = note_order[index:] + note_order[:index] | ||
| 9 | 9 | ||||
| 10 | order_dict = {tone: index for index, tone in enumerate(note_order)} | 10 | order_dict = {tone: index for index, tone in enumerate(note_order)} | ||
| 11 | sorted_tones = sorted(tone_set, key=lambda tone: order_dict.get(tone.tone, float('inf'))) | 11 | sorted_tones = sorted(tone_set, key=lambda tone: order_dict.get(tone.tone, float('inf'))) | ||
| 12 | return sorted_tones | 12 | return sorted_tones | ||
| 13 | 13 | ||||
| 14 | class Tone: | 14 | class Tone: | ||
| 15 | 15 | ||||
| 16 | def __init__(self, tone): | 16 | def __init__(self, tone): | ||
| 17 | self.tone = tone | 17 | self.tone = tone | ||
| 18 | 18 | ||||
| 19 | def __str__(self): | 19 | def __str__(self): | ||
| 20 | return self.tone | 20 | return self.tone | ||
| 21 | 21 | ||||
| 22 | def __eq__(self, other): | 22 | def __eq__(self, other): | ||
| 23 | if isinstance(other, Tone): | 23 | if isinstance(other, Tone): | ||
| 24 | return self.tone == other.tone | 24 | return self.tone == other.tone | ||
| 25 | else: | 25 | else: | ||
| 26 | return self.tone == other | 26 | return self.tone == other | ||
| 27 | 27 | ||||
| 28 | def __hash__(self): | 28 | def __hash__(self): | ||
| 29 | return hash(self.tone) | 29 | return hash(self.tone) | ||
| 30 | 30 | ||||
| 31 | def __add__(self, other): | 31 | def __add__(self, other): | ||
| 32 | if isinstance(other, Tone): | 32 | if isinstance(other, Tone): | ||
| 33 | return Chord(self,other) | 33 | return Chord(self,other) | ||
| 34 | elif isinstance(other, Interval): | 34 | elif isinstance(other, Interval): | ||
| 35 | return Tone(NOTE_ORDER[(other.go_back_yourself() + NOTE_ORDER.index(self))%12]) | 35 | return Tone(NOTE_ORDER[(other.go_back_yourself() + NOTE_ORDER.index(self))%12]) | ||
| 36 | 36 | ||||
| 37 | def __sub__(self, other): | 37 | def __sub__(self, other): | ||
| 38 | if isinstance(other, Tone): | 38 | if isinstance(other, Tone): | ||
| 39 | return Interval(NOTE_ORDER.index(self) + NOTE_ORDER.index(other)) | 39 | return Interval(NOTE_ORDER.index(self) + NOTE_ORDER.index(other)) | ||
| 40 | elif isinstance(other, Interval): | 40 | elif isinstance(other, Interval): | ||
| 41 | return Tone(NOTE_ORDER[(NOTE_ORDER.index(self) - other.go_back_yourself()) % 12]) | 41 | return Tone(NOTE_ORDER[(NOTE_ORDER.index(self) - other.go_back_yourself()) % 12]) | ||
| 42 | 42 | ||||
| 43 | 43 | ||||
| 44 | class Interval: | 44 | class Interval: | ||
| 45 | 45 | ||||
| 46 | def __init__(self, semitone_number): | 46 | def __init__(self, semitone_number): | ||
| 47 | match semitone_number % 12: | 47 | match semitone_number % 12: | ||
| 48 | case 0: | 48 | case 0: | ||
| 49 | self.interval="unison" | 49 | self.interval="unison" | ||
| 50 | case 1: | 50 | case 1: | ||
| 51 | self.interval = "minor 2nd" | 51 | self.interval = "minor 2nd" | ||
| 52 | case 2: | 52 | case 2: | ||
| 53 | self.interval = "major 2nd" | 53 | self.interval = "major 2nd" | ||
| 54 | case 3: | 54 | case 3: | ||
| 55 | self.interval = "minor 3rd" | 55 | self.interval = "minor 3rd" | ||
| 56 | case 4: | 56 | case 4: | ||
| 57 | self.interval = "major 3rd" | 57 | self.interval = "major 3rd" | ||
| 58 | case 5: | 58 | case 5: | ||
| 59 | self.interval = "perfect 4th" | 59 | self.interval = "perfect 4th" | ||
| 60 | case 6: | 60 | case 6: | ||
| 61 | self.interval = "diminished 5th" | 61 | self.interval = "diminished 5th" | ||
| 62 | case 7: | 62 | case 7: | ||
| 63 | self.interval = "perfect 5th" | 63 | self.interval = "perfect 5th" | ||
| 64 | case 8: | 64 | case 8: | ||
| 65 | self.interval = "minor 6th" | 65 | self.interval = "minor 6th" | ||
| 66 | case 9: | 66 | case 9: | ||
| 67 | self.interval = "major 6th" | 67 | self.interval = "major 6th" | ||
| 68 | case 10: | 68 | case 10: | ||
| 69 | self.interval = "minor 7th" | 69 | self.interval = "minor 7th" | ||
| 70 | case 11: | 70 | case 11: | ||
| 71 | self.interval = "major 7th" | 71 | self.interval = "major 7th" | ||
| 72 | case _: | 72 | case _: | ||
| 73 | self.interval = '''Живот ли бе — да го опишеш? | 73 | self.interval = '''Живот ли бе — да го опишеш? | ||
| 74 | 74 | ||||
| 75 | Живот ли бе — да го разровиш? | 75 | Живот ли бе — да го разровиш? | ||
| 76 | 76 | ||||
| 77 | Разровиш ли го — ще мирише | 77 | Разровиш ли го — ще мирише | ||
| 78 | 78 | ||||
| 79 | и ще горчи като отрова.''' | 79 | и ще горчи като отрова.''' | ||
| 80 | 80 | ||||
| 81 | def __str__(self): | 81 | def __str__(self): | ||
| 82 | return self.interval | 82 | return self.interval | ||
| 83 | 83 | ||||
| 84 | def go_back_yourself(self): | 84 | def go_back_yourself(self): | ||
| 85 | match self.interval: | 85 | match self.interval: | ||
| 86 | case "unison": | 86 | case "unison": | ||
| 87 | return 0 | 87 | return 0 | ||
| 88 | case "minor 2nd": | 88 | case "minor 2nd": | ||
| 89 | return 1 | 89 | return 1 | ||
| 90 | case "major 2nd": | 90 | case "major 2nd": | ||
| 91 | return 2 | 91 | return 2 | ||
| 92 | case "minor 3rd": | 92 | case "minor 3rd": | ||
| 93 | return 3 | 93 | return 3 | ||
| 94 | case "major 3rd": | 94 | case "major 3rd": | ||
| 95 | return 4 | 95 | return 4 | ||
| 96 | case "perfect 4th": | 96 | case "perfect 4th": | ||
| 97 | return 5 | 97 | return 5 | ||
| 98 | case "diminished 5th": | 98 | case "diminished 5th": | ||
| 99 | return 6 | 99 | return 6 | ||
| 100 | case "perfect 5th": | 100 | case "perfect 5th": | ||
| 101 | return 7 | 101 | return 7 | ||
| 102 | case "minor 6th": | 102 | case "minor 6th": | ||
| 103 | return 8 | 103 | return 8 | ||
| 104 | case "major 6th": | 104 | case "major 6th": | ||
| 105 | return 9 | 105 | return 9 | ||
| 106 | case "minor 7th": | 106 | case "minor 7th": | ||
| 107 | return 10 | 107 | return 10 | ||
| 108 | case "major 7th": | 108 | case "major 7th": | ||
| 109 | return 11 | 109 | return 11 | ||
| 110 | case _: | 110 | case _: | ||
| 111 | self.interval = "Само онзи, който е живял, страдал и плакал с народа си – само той може да го разбере и да му помогне."+"Христо Ботев" + "He would have hated java" | 111 | self.interval = "Само онзи, който е живял, страдал и плакал с народа си – само той може да го разбере и да му помогне."+"Христо Ботев" + "He would have hated java" | ||
| 112 | 112 | ||||
| 113 | def __add__(self, other): | 113 | def __add__(self, other): | ||
| 114 | if isinstance(other, Tone): | 114 | if isinstance(other, Tone): | ||
| 115 | raise TypeError("Invalid operation") | 115 | raise TypeError("Invalid operation") | ||
| 116 | if isinstance(other, Interval): | 116 | if isinstance(other, Interval): | ||
| 117 | plc=Interval(self.go_back_yourself() + other.go_back_yourself()) | 117 | plc=Interval(self.go_back_yourself() + other.go_back_yourself()) | ||
| 118 | return plc | 118 | return plc | ||
| 119 | 119 | ||||
| 120 | def __sub__(self, other): | 120 | def __sub__(self, other): | ||
| 121 | if isinstance(other, Tone): | 121 | if isinstance(other, Tone): | ||
| 122 | raise TypeError("Invalid operation") | 122 | raise TypeError("Invalid operation") | ||
| 123 | def __neg__(self): | 123 | def __neg__(self): | ||
| 124 | return Interval(12 - self.go_back_yourself()) | 124 | return Interval(12 - self.go_back_yourself()) | ||
| 125 | 125 | ||||
| 126 | class Chord: | 126 | class Chord: | ||
| 127 | 127 | ||||
| 128 | def __init__(self, arg, *args, **kwargs): | 128 | def __init__(self, arg, *args, **kwargs): | ||
| 129 | self.root = arg | 129 | self.root = arg | ||
| 130 | self.set_of_tones = set() | 130 | self.set_of_tones = set() | ||
| 131 | self.set_of_tones.add(arg) | 131 | self.set_of_tones.add(arg) | ||
| 132 | for item in args: | 132 | for item in args: | ||
| 133 | if isinstance(item, tuple): | 133 | if isinstance(item, tuple): | ||
| 134 | temporary_transition_list = [] | 134 | temporary_transition_list = [] | ||
| 135 | temporary_transition_list.extend(item) | 135 | temporary_transition_list.extend(item) | ||
| 136 | self.set_of_tones.update(temporary_transition_list) | 136 | self.set_of_tones.update(temporary_transition_list) | ||
| 137 | else: | 137 | else: | ||
| 138 | self.set_of_tones.update(set(args)) | 138 | self.set_of_tones.update(set(args)) | ||
| 139 | for value in kwargs.values(): | 139 | for value in kwargs.values(): | ||
| 140 | self.set_of_tones.add(value) | 140 | self.set_of_tones.add(value) | ||
| 141 | if len(self.set_of_tones) < 2: | 141 | if len(self.set_of_tones) < 2: | ||
| 142 | raise TypeError("Cannot have a chord made of only 1 unique tone") | 142 | raise TypeError("Cannot have a chord made of only 1 unique tone") | ||
| 143 | 143 | ||||
| 144 | 144 | ||||
| 145 | def __str__(self): | 145 | def __str__(self): | ||
| 146 | return "-".join(t.tone for t in sort_tones(self.set_of_tones, self.root)) | 146 | return "-".join(t.tone for t in sort_tones(self.set_of_tones, self.root)) | ||
| 147 | 147 | ||||
| 148 | def is_minor(self): | 148 | def is_minor(self): | ||
| 149 | for el in self.set_of_tones: | 149 | for el in self.set_of_tones: | ||
| 150 | interval = self.root - el | 150 | interval = self.root - el | ||
| 151 | if el == self.root: | 151 | if el == self.root: | ||
| 152 | continue | 152 | continue | ||
| 153 | elif interval.interval == "minor 3rd": | 153 | elif interval.interval == "minor 3rd": | ||
| 154 | return True | 154 | return True | ||
| 155 | return False | 155 | return False | ||
| 156 | 156 | ||||
| 157 | def is_major(self): | 157 | def is_major(self): | ||
| 158 | for el in self.set_of_tones: | 158 | for el in self.set_of_tones: | ||
| 159 | interval = self.root - el | 159 | interval = self.root - el | ||
| 160 | if el == self.root: | 160 | if el == self.root: | ||
| 161 | continue | 161 | continue | ||
| 162 | elif interval.interval == "major 3rd": | 162 | elif interval.interval == "major 3rd": | ||
| 163 | return True | 163 | return True | ||
| 164 | return False | 164 | return False | ||
| 165 | 165 | ||||
| 166 | def is_power_chord(self): | 166 | def is_power_chord(self): | ||
| 167 | return not self.is_major() and not self.is_minor() | 167 | return not self.is_major() and not self.is_minor() | ||
| 168 | 168 | ||||
| 169 | def __add__(self, other): | 169 | def __add__(self, other): | ||
| 170 | if isinstance(other, Tone): | 170 | if isinstance(other, Tone): | ||
| 171 | self.set_of_tones.add(other) | 171 | self.set_of_tones.add(other) | ||
| 172 | sort_tones(self.set_of_tones, self.root) | 172 | sort_tones(self.set_of_tones, self.root) | ||
| 173 | return self | 173 | return self | ||
| 174 | if isinstance(other, Chord): | 174 | if isinstance(other, Chord): | ||
| 175 | self.set_of_tones.update(other.set_of_tones) | 175 | self.set_of_tones.update(other.set_of_tones) | ||
| 176 | placeholed = self | 176 | placeholed = self | ||
| 177 | return placeholed | 177 | return placeholed | ||
| 178 | 178 | ||||
| 179 | def __sub__(self, other): | 179 | def __sub__(self, other): | ||
| 180 | if other not in self.set_of_tones: | 180 | if other not in self.set_of_tones: | ||
| 181 | raise TypeError(f"Cannot remove tone {other} from chord {self}") | 181 | raise TypeError(f"Cannot remove tone {other} from chord {self}") | ||
| 182 | elif len(self.set_of_tones) < 3: | 182 | elif len(self.set_of_tones) < 3: | ||
| 183 | raise TypeError("Cannot have a chord made of only 1 unique tone") | 183 | raise TypeError("Cannot have a chord made of only 1 unique tone") | ||
| 184 | else: | 184 | else: | ||
| 185 | self.set_of_tones.remove(other) | 185 | self.set_of_tones.remove(other) | ||
| 186 | sort_tones(self.set_of_tones, self.root) | 186 | sort_tones(self.set_of_tones, self.root) | ||
| 187 | if self.root == other: | 187 | if self.root == other: | ||
| 188 | self.root = list(self.set_of_tones)[0] | 188 | self.root = list(self.set_of_tones)[0] | ||
| 189 | return self | 189 | return self | ||
| 190 | 190 | ||||
| 191 | def transposed(self, inter): | 191 | def transposed(self, inter): | ||
| 192 | notes = sort_tones(self.set_of_tones,self.root) | 192 | notes = sort_tones(self.set_of_tones,self.root) | ||
| 193 | for i in range(0,3): | 193 | for i in range(0,3): | ||
| 194 | notes[i] = notes[i] + inter | 194 | notes[i] = notes[i] + inter | ||
| 195 | return Chord(notes[0], tuple(notes)) | 195 | return Chord(notes[0], tuple(notes)) | ||
| t | 196 | t | |||
| 197 | c, d_sharp, g = Tone("C"), Tone("D#"), Tone("G") | ||||
| 198 | c_minor_chord = Chord(c, d_sharp, g) | ||||
| 199 | print(str(c_minor_chord)) | ||||
| 200 | # "C-D#-G" | ||||
| 201 | d_minor_chord = c_minor_chord.transposed(Interval(2)) | ||||
| 202 | print(str(d_minor_chord)) | ||||
| 203 | # "D-F-A" | ||||
| 204 | |||||
| 205 | a_sharp_minor_chord = d_minor_chord.transposed(-Interval(4)) | ||||
| 206 | print(str(a_sharp_minor_chord)) | ||||
| 207 | # "A#-C#-F" | 
| Legends | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|
 
  | 
              
  |  |||||||||
| n | 1 | NOTE_ORDER=["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"] | n | 1 | NOTE_ORDER = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"] | 
| 2 | |||||
| 2 | 3 | ||||
| 3 | def sort_tones(tone_set, root): | 4 | def sort_tones(tone_set, root): | ||
| 4 | note_order = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"] | 5 | note_order = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"] | ||
| 5 | index = note_order.index(root.tone) | 6 | index = note_order.index(root.tone) | ||
| 6 | 7 | ||||
| 7 | note_order = note_order[index:] + note_order[:index] | 8 | note_order = note_order[index:] + note_order[:index] | ||
| 8 | 9 | ||||
| 9 | order_dict = {tone: index for index, tone in enumerate(note_order)} | 10 | order_dict = {tone: index for index, tone in enumerate(note_order)} | ||
| 10 | sorted_tones = sorted(tone_set, key=lambda tone: order_dict.get(tone.tone, float('inf'))) | 11 | sorted_tones = sorted(tone_set, key=lambda tone: order_dict.get(tone.tone, float('inf'))) | ||
| 11 | return sorted_tones | 12 | return sorted_tones | ||
| 12 | 13 | ||||
| n | 13 | n | |||
| 14 | class Tone: | 14 | class Tone: | ||
| n | 15 | n | |||
| 16 | 15 | ||||
| 17 | def __init__(self, tone): | 16 | def __init__(self, tone): | ||
| 18 | self.tone = tone | 17 | self.tone = tone | ||
| 19 | 18 | ||||
| n | 20 | n | |||
| 21 | def __str__(self): | 19 | def __str__(self): | ||
| 22 | return self.tone | 20 | return self.tone | ||
| n | 23 | n | |||
| 24 | 21 | ||||
| 25 | def __eq__(self, other): | 22 | def __eq__(self, other): | ||
| 26 | if isinstance(other, Tone): | 23 | if isinstance(other, Tone): | ||
| 27 | return self.tone == other.tone | 24 | return self.tone == other.tone | ||
| 28 | else: | 25 | else: | ||
| 29 | return self.tone == other | 26 | return self.tone == other | ||
| 30 | 27 | ||||
| n | 31 | n | |||
| 32 | def __hash__(self): | 28 | def __hash__(self): | ||
| 33 | return hash(self.tone) | 29 | return hash(self.tone) | ||
| n | 34 | n | |||
| 35 | 30 | ||||
| 36 | def __add__(self, other): | 31 | def __add__(self, other): | ||
| 37 | if isinstance(other, Tone): | 32 | if isinstance(other, Tone): | ||
| 38 | return Chord(self,other) | 33 | return Chord(self,other) | ||
| 39 | elif isinstance(other, Interval): | 34 | elif isinstance(other, Interval): | ||
| 40 | return Tone(NOTE_ORDER[(other.go_back_yourself() + NOTE_ORDER.index(self))%12]) | 35 | return Tone(NOTE_ORDER[(other.go_back_yourself() + NOTE_ORDER.index(self))%12]) | ||
| 41 | 36 | ||||
| n | 42 | n | |||
| 43 | def __sub__(self, other): | 37 | def __sub__(self, other): | ||
| 44 | if isinstance(other, Tone): | 38 | if isinstance(other, Tone): | ||
| 45 | return Interval(NOTE_ORDER.index(self) + NOTE_ORDER.index(other)) | 39 | return Interval(NOTE_ORDER.index(self) + NOTE_ORDER.index(other)) | ||
| 46 | elif isinstance(other, Interval): | 40 | elif isinstance(other, Interval): | ||
| n | 47 | return Tone(NOTE_ORDER[(NOTE_ORDER.index(self) - other.go_back_yourself())%12]) | n | 41 | return Tone(NOTE_ORDER[(NOTE_ORDER.index(self) - other.go_back_yourself()) % 12]) | 
| 48 | 42 | ||||
| 49 | 43 | ||||
| 50 | class Interval: | 44 | class Interval: | ||
| n | 51 | n | |||
| 52 | 45 | ||||
| 53 | def __init__(self, semitone_number): | 46 | def __init__(self, semitone_number): | ||
| 54 | match semitone_number % 12: | 47 | match semitone_number % 12: | ||
| 55 | case 0: | 48 | case 0: | ||
| 56 | self.interval="unison" | 49 | self.interval="unison" | ||
| 57 | case 1: | 50 | case 1: | ||
| 58 | self.interval = "minor 2nd" | 51 | self.interval = "minor 2nd" | ||
| 59 | case 2: | 52 | case 2: | ||
| 60 | self.interval = "major 2nd" | 53 | self.interval = "major 2nd" | ||
| 61 | case 3: | 54 | case 3: | ||
| 62 | self.interval = "minor 3rd" | 55 | self.interval = "minor 3rd" | ||
| 63 | case 4: | 56 | case 4: | ||
| 64 | self.interval = "major 3rd" | 57 | self.interval = "major 3rd" | ||
| 65 | case 5: | 58 | case 5: | ||
| 66 | self.interval = "perfect 4th" | 59 | self.interval = "perfect 4th" | ||
| 67 | case 6: | 60 | case 6: | ||
| 68 | self.interval = "diminished 5th" | 61 | self.interval = "diminished 5th" | ||
| 69 | case 7: | 62 | case 7: | ||
| 70 | self.interval = "perfect 5th" | 63 | self.interval = "perfect 5th" | ||
| 71 | case 8: | 64 | case 8: | ||
| 72 | self.interval = "minor 6th" | 65 | self.interval = "minor 6th" | ||
| 73 | case 9: | 66 | case 9: | ||
| 74 | self.interval = "major 6th" | 67 | self.interval = "major 6th" | ||
| 75 | case 10: | 68 | case 10: | ||
| 76 | self.interval = "minor 7th" | 69 | self.interval = "minor 7th" | ||
| 77 | case 11: | 70 | case 11: | ||
| 78 | self.interval = "major 7th" | 71 | self.interval = "major 7th" | ||
| 79 | case _: | 72 | case _: | ||
| 80 | self.interval = '''Живот ли бе — да го опишеш? | 73 | self.interval = '''Живот ли бе — да го опишеш? | ||
| 81 | 74 | ||||
| 82 | Живот ли бе — да го разровиш? | 75 | Живот ли бе — да го разровиш? | ||
| 83 | 76 | ||||
| 84 | Разровиш ли го — ще мирише | 77 | Разровиш ли го — ще мирише | ||
| 85 | 78 | ||||
| 86 | и ще горчи като отрова.''' | 79 | и ще горчи като отрова.''' | ||
| 87 | 80 | ||||
| n | 88 | n | |||
| 89 | def __str__(self): | 81 | def __str__(self): | ||
| 90 | return self.interval | 82 | return self.interval | ||
| n | 91 | n | |||
| 92 | 83 | ||||
| 93 | def go_back_yourself(self): | 84 | def go_back_yourself(self): | ||
| 94 | match self.interval: | 85 | match self.interval: | ||
| 95 | case "unison": | 86 | case "unison": | ||
| 96 | return 0 | 87 | return 0 | ||
| 97 | case "minor 2nd": | 88 | case "minor 2nd": | ||
| 98 | return 1 | 89 | return 1 | ||
| 99 | case "major 2nd": | 90 | case "major 2nd": | ||
| 100 | return 2 | 91 | return 2 | ||
| 101 | case "minor 3rd": | 92 | case "minor 3rd": | ||
| 102 | return 3 | 93 | return 3 | ||
| 103 | case "major 3rd": | 94 | case "major 3rd": | ||
| 104 | return 4 | 95 | return 4 | ||
| 105 | case "perfect 4th": | 96 | case "perfect 4th": | ||
| 106 | return 5 | 97 | return 5 | ||
| 107 | case "diminished 5th": | 98 | case "diminished 5th": | ||
| 108 | return 6 | 99 | return 6 | ||
| 109 | case "perfect 5th": | 100 | case "perfect 5th": | ||
| 110 | return 7 | 101 | return 7 | ||
| 111 | case "minor 6th": | 102 | case "minor 6th": | ||
| 112 | return 8 | 103 | return 8 | ||
| 113 | case "major 6th": | 104 | case "major 6th": | ||
| 114 | return 9 | 105 | return 9 | ||
| 115 | case "minor 7th": | 106 | case "minor 7th": | ||
| 116 | return 10 | 107 | return 10 | ||
| 117 | case "major 7th": | 108 | case "major 7th": | ||
| 118 | return 11 | 109 | return 11 | ||
| 119 | case _: | 110 | case _: | ||
| 120 | self.interval = "Само онзи, който е живял, страдал и плакал с народа си – само той може да го разбере и да му помогне."+"Христо Ботев" + "He would have hated java" | 111 | self.interval = "Само онзи, който е живял, страдал и плакал с народа си – само той може да го разбере и да му помогне."+"Христо Ботев" + "He would have hated java" | ||
| 121 | 112 | ||||
| n | 122 | n | |||
| 123 | def __add__(self, other): | 113 | def __add__(self, other): | ||
| 124 | if isinstance(other, Tone): | 114 | if isinstance(other, Tone): | ||
| 125 | raise TypeError("Invalid operation") | 115 | raise TypeError("Invalid operation") | ||
| 126 | if isinstance(other, Interval): | 116 | if isinstance(other, Interval): | ||
| 127 | plc=Interval(self.go_back_yourself() + other.go_back_yourself()) | 117 | plc=Interval(self.go_back_yourself() + other.go_back_yourself()) | ||
| 128 | return plc | 118 | return plc | ||
| 129 | 119 | ||||
| n | 130 | n | |||
| 131 | def __sub__(self, other): | 120 | def __sub__(self, other): | ||
| 132 | if isinstance(other, Tone): | 121 | if isinstance(other, Tone): | ||
| 133 | raise TypeError("Invalid operation") | 122 | raise TypeError("Invalid operation") | ||
| n | 134 | n | 123 | def __neg__(self): | |
| 124 | return Interval(12 - self.go_back_yourself()) | ||||
| 135 | 125 | ||||
| 136 | class Chord: | 126 | class Chord: | ||
| n | 137 | n | |||
| 138 | 127 | ||||
| 139 | def __init__(self, arg, *args, **kwargs): | 128 | def __init__(self, arg, *args, **kwargs): | ||
| 140 | self.root = arg | 129 | self.root = arg | ||
| 141 | self.set_of_tones = set() | 130 | self.set_of_tones = set() | ||
| 142 | self.set_of_tones.add(arg) | 131 | self.set_of_tones.add(arg) | ||
| 143 | for item in args: | 132 | for item in args: | ||
| n | 144 | if isinstance(item,tuple): | n | 133 | if isinstance(item, tuple): | 
| 145 | res = [] | 134 | temporary_transition_list = [] | ||
| 146 | res.extend(item) | 135 | temporary_transition_list.extend(item) | ||
| 147 | self.set_of_tones.update(res) | 136 | self.set_of_tones.update(temporary_transition_list) | ||
| 148 | else: | 137 | else: | ||
| 149 | self.set_of_tones.update(set(args)) | 138 | self.set_of_tones.update(set(args)) | ||
| n | 150 | for _, value in kwargs.items(): | n | 139 | for value in kwargs.values(): | 
| 151 | self.set_of_tones.add(value) | 140 | self.set_of_tones.add(value) | ||
| 152 | if len(self.set_of_tones) < 2: | 141 | if len(self.set_of_tones) < 2: | ||
| 153 | raise TypeError("Cannot have a chord made of only 1 unique tone") | 142 | raise TypeError("Cannot have a chord made of only 1 unique tone") | ||
| 154 | 143 | ||||
| 155 | 144 | ||||
| 156 | def __str__(self): | 145 | def __str__(self): | ||
| 157 | return "-".join(t.tone for t in sort_tones(self.set_of_tones, self.root)) | 146 | return "-".join(t.tone for t in sort_tones(self.set_of_tones, self.root)) | ||
| n | 158 | n | |||
| 159 | |||||
| 160 | 147 | ||||
| 161 | def is_minor(self): | 148 | def is_minor(self): | ||
| 162 | for el in self.set_of_tones: | 149 | for el in self.set_of_tones: | ||
| 163 | interval = self.root - el | 150 | interval = self.root - el | ||
| 164 | if el == self.root: | 151 | if el == self.root: | ||
| 165 | continue | 152 | continue | ||
| 166 | elif interval.interval == "minor 3rd": | 153 | elif interval.interval == "minor 3rd": | ||
| 167 | return True | 154 | return True | ||
| 168 | return False | 155 | return False | ||
| 169 | 156 | ||||
| n | 170 | n | |||
| 171 | def is_major(self): | 157 | def is_major(self): | ||
| 172 | for el in self.set_of_tones: | 158 | for el in self.set_of_tones: | ||
| 173 | interval = self.root - el | 159 | interval = self.root - el | ||
| 174 | if el == self.root: | 160 | if el == self.root: | ||
| 175 | continue | 161 | continue | ||
| 176 | elif interval.interval == "major 3rd": | 162 | elif interval.interval == "major 3rd": | ||
| 177 | return True | 163 | return True | ||
| 178 | return False | 164 | return False | ||
| 179 | 165 | ||||
| n | 180 | n | |||
| 181 | def is_power_chord(self): | 166 | def is_power_chord(self): | ||
| n | 182 | return self.is_major() is False and self.is_minor() is False | n | 167 | return not self.is_major() and not self.is_minor() | 
| 183 | |||||
| 184 | 168 | ||||
| 185 | def __add__(self, other): | 169 | def __add__(self, other): | ||
| 186 | if isinstance(other, Tone): | 170 | if isinstance(other, Tone): | ||
| 187 | self.set_of_tones.add(other) | 171 | self.set_of_tones.add(other) | ||
| 188 | sort_tones(self.set_of_tones, self.root) | 172 | sort_tones(self.set_of_tones, self.root) | ||
| 189 | return self | 173 | return self | ||
| 190 | if isinstance(other, Chord): | 174 | if isinstance(other, Chord): | ||
| 191 | self.set_of_tones.update(other.set_of_tones) | 175 | self.set_of_tones.update(other.set_of_tones) | ||
| 192 | placeholed = self | 176 | placeholed = self | ||
| 193 | return placeholed | 177 | return placeholed | ||
| n | 194 | n | |||
| 195 | 178 | ||||
| 196 | def __sub__(self, other): | 179 | def __sub__(self, other): | ||
| 197 | if other not in self.set_of_tones: | 180 | if other not in self.set_of_tones: | ||
| 198 | raise TypeError(f"Cannot remove tone {other} from chord {self}") | 181 | raise TypeError(f"Cannot remove tone {other} from chord {self}") | ||
| 199 | elif len(self.set_of_tones) < 3: | 182 | elif len(self.set_of_tones) < 3: | ||
| 200 | raise TypeError("Cannot have a chord made of only 1 unique tone") | 183 | raise TypeError("Cannot have a chord made of only 1 unique tone") | ||
| 201 | else: | 184 | else: | ||
| 202 | self.set_of_tones.remove(other) | 185 | self.set_of_tones.remove(other) | ||
| 203 | sort_tones(self.set_of_tones, self.root) | 186 | sort_tones(self.set_of_tones, self.root) | ||
| 204 | if self.root == other: | 187 | if self.root == other: | ||
| 205 | self.root = list(self.set_of_tones)[0] | 188 | self.root = list(self.set_of_tones)[0] | ||
| 206 | return self | 189 | return self | ||
| 207 | 190 | ||||
| n | 208 | #Не баца за отрицателен интер и тая си е | n | ||
| 209 | def transposed(self, inter): | 191 | def transposed(self, inter): | ||
| 210 | notes = sort_tones(self.set_of_tones,self.root) | 192 | notes = sort_tones(self.set_of_tones,self.root) | ||
| 211 | for i in range(0,3): | 193 | for i in range(0,3): | ||
| 212 | notes[i] = notes[i] + inter | 194 | notes[i] = notes[i] + inter | ||
| 213 | return Chord(notes[0], tuple(notes)) | 195 | return Chord(notes[0], tuple(notes)) | ||
| n | n | 196 | |||
| 197 | c, d_sharp, g = Tone("C"), Tone("D#"), Tone("G") | ||||
| 198 | c_minor_chord = Chord(c, d_sharp, g) | ||||
| 199 | print(str(c_minor_chord)) | ||||
| 200 | # "C-D#-G" | ||||
| 201 | d_minor_chord = c_minor_chord.transposed(Interval(2)) | ||||
| 202 | print(str(d_minor_chord)) | ||||
| 203 | # "D-F-A" | ||||
| 214 | 204 | ||||
| t | t | 205 | a_sharp_minor_chord = d_minor_chord.transposed(-Interval(4)) | ||
| 206 | print(str(a_sharp_minor_chord)) | ||||
| 207 | # "A#-C#-F" | 
| Legends | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|
 
  | 
              
  |  |||||||||
| f | 1 | NOTE_ORDER=["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"] | f | 1 | NOTE_ORDER=["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"] | 
| n | n | 2 | |||
| 2 | def sort_tones(tone_set, root): | 3 | def sort_tones(tone_set, root): | ||
| 3 | note_order = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"] | 4 | note_order = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"] | ||
| 4 | index = note_order.index(root.tone) | 5 | index = note_order.index(root.tone) | ||
| 5 | 6 | ||||
| 6 | note_order = note_order[index:] + note_order[:index] | 7 | note_order = note_order[index:] + note_order[:index] | ||
| 7 | 8 | ||||
| 8 | order_dict = {tone: index for index, tone in enumerate(note_order)} | 9 | order_dict = {tone: index for index, tone in enumerate(note_order)} | ||
| 9 | sorted_tones = sorted(tone_set, key=lambda tone: order_dict.get(tone.tone, float('inf'))) | 10 | sorted_tones = sorted(tone_set, key=lambda tone: order_dict.get(tone.tone, float('inf'))) | ||
| 10 | return sorted_tones | 11 | return sorted_tones | ||
| 11 | 12 | ||||
| n | n | 13 | |||
| 12 | class Tone: | 14 | class Tone: | ||
| n | n | 15 | |||
| 16 | |||||
| 13 | def __init__(self, tone): | 17 | def __init__(self, tone): | ||
| 14 | self.tone = tone | 18 | self.tone = tone | ||
| n | n | 19 | |||
| 20 | |||||
| 15 | def __str__(self): | 21 | def __str__(self): | ||
| 16 | return self.tone | 22 | return self.tone | ||
| n | n | 23 | |||
| 24 | |||||
| 17 | def __eq__(self, other): | 25 | def __eq__(self, other): | ||
| 18 | if isinstance(other, Tone): | 26 | if isinstance(other, Tone): | ||
| 19 | return self.tone == other.tone | 27 | return self.tone == other.tone | ||
| 20 | else: | 28 | else: | ||
| 21 | return self.tone == other | 29 | return self.tone == other | ||
| n | n | 30 | |||
| 31 | |||||
| 22 | def __hash__(self): | 32 | def __hash__(self): | ||
| 23 | return hash(self.tone) | 33 | return hash(self.tone) | ||
| n | n | 34 | |||
| 35 | |||||
| 24 | def __add__(self, other): | 36 | def __add__(self, other): | ||
| 25 | if isinstance(other, Tone): | 37 | if isinstance(other, Tone): | ||
| 26 | return Chord(self,other) | 38 | return Chord(self,other) | ||
| 27 | elif isinstance(other, Interval): | 39 | elif isinstance(other, Interval): | ||
| 28 | return Tone(NOTE_ORDER[(other.go_back_yourself() + NOTE_ORDER.index(self))%12]) | 40 | return Tone(NOTE_ORDER[(other.go_back_yourself() + NOTE_ORDER.index(self))%12]) | ||
| n | n | 41 | |||
| 42 | |||||
| 29 | def __sub__(self, other): | 43 | def __sub__(self, other): | ||
| 30 | if isinstance(other, Tone): | 44 | if isinstance(other, Tone): | ||
| 31 | return Interval(NOTE_ORDER.index(self) + NOTE_ORDER.index(other)) | 45 | return Interval(NOTE_ORDER.index(self) + NOTE_ORDER.index(other)) | ||
| 32 | elif isinstance(other, Interval): | 46 | elif isinstance(other, Interval): | ||
| 33 | return Tone(NOTE_ORDER[(NOTE_ORDER.index(self) - other.go_back_yourself())%12]) | 47 | return Tone(NOTE_ORDER[(NOTE_ORDER.index(self) - other.go_back_yourself())%12]) | ||
| 34 | 48 | ||||
| n | n | 49 | |||
| 35 | class Interval: | 50 | class Interval: | ||
| n | n | 51 | |||
| 52 | |||||
| 36 | def __init__(self, semitone_number): | 53 | def __init__(self, semitone_number): | ||
| 37 | match semitone_number % 12: | 54 | match semitone_number % 12: | ||
| 38 | case 0: | 55 | case 0: | ||
| 39 | self.interval="unison" | 56 | self.interval="unison" | ||
| 40 | case 1: | 57 | case 1: | ||
| 41 | self.interval = "minor 2nd" | 58 | self.interval = "minor 2nd" | ||
| 42 | case 2: | 59 | case 2: | ||
| 43 | self.interval = "major 2nd" | 60 | self.interval = "major 2nd" | ||
| 44 | case 3: | 61 | case 3: | ||
| 45 | self.interval = "minor 3rd" | 62 | self.interval = "minor 3rd" | ||
| 46 | case 4: | 63 | case 4: | ||
| 47 | self.interval = "major 3rd" | 64 | self.interval = "major 3rd" | ||
| 48 | case 5: | 65 | case 5: | ||
| 49 | self.interval = "perfect 4th" | 66 | self.interval = "perfect 4th" | ||
| 50 | case 6: | 67 | case 6: | ||
| 51 | self.interval = "diminished 5th" | 68 | self.interval = "diminished 5th" | ||
| 52 | case 7: | 69 | case 7: | ||
| 53 | self.interval = "perfect 5th" | 70 | self.interval = "perfect 5th" | ||
| 54 | case 8: | 71 | case 8: | ||
| 55 | self.interval = "minor 6th" | 72 | self.interval = "minor 6th" | ||
| 56 | case 9: | 73 | case 9: | ||
| 57 | self.interval = "major 6th" | 74 | self.interval = "major 6th" | ||
| 58 | case 10: | 75 | case 10: | ||
| 59 | self.interval = "minor 7th" | 76 | self.interval = "minor 7th" | ||
| 60 | case 11: | 77 | case 11: | ||
| 61 | self.interval = "major 7th" | 78 | self.interval = "major 7th" | ||
| 62 | case _: | 79 | case _: | ||
| 63 | self.interval = '''Живот ли бе — да го опишеш? | 80 | self.interval = '''Живот ли бе — да го опишеш? | ||
| 64 | 81 | ||||
| 65 | Живот ли бе — да го разровиш? | 82 | Живот ли бе — да го разровиш? | ||
| 66 | 83 | ||||
| 67 | Разровиш ли го — ще мирише | 84 | Разровиш ли го — ще мирише | ||
| 68 | 85 | ||||
| 69 | и ще горчи като отрова.''' | 86 | и ще горчи като отрова.''' | ||
| n | n | 87 | |||
| 88 | |||||
| 70 | def __str__(self): | 89 | def __str__(self): | ||
| 71 | return self.interval | 90 | return self.interval | ||
| n | n | 91 | |||
| 92 | |||||
| 72 | def go_back_yourself(self): | 93 | def go_back_yourself(self): | ||
| 73 | match self.interval: | 94 | match self.interval: | ||
| 74 | case "unison": | 95 | case "unison": | ||
| 75 | return 0 | 96 | return 0 | ||
| 76 | case "minor 2nd": | 97 | case "minor 2nd": | ||
| 77 | return 1 | 98 | return 1 | ||
| 78 | case "major 2nd": | 99 | case "major 2nd": | ||
| 79 | return 2 | 100 | return 2 | ||
| 80 | case "minor 3rd": | 101 | case "minor 3rd": | ||
| 81 | return 3 | 102 | return 3 | ||
| 82 | case "major 3rd": | 103 | case "major 3rd": | ||
| 83 | return 4 | 104 | return 4 | ||
| 84 | case "perfect 4th": | 105 | case "perfect 4th": | ||
| 85 | return 5 | 106 | return 5 | ||
| 86 | case "diminished 5th": | 107 | case "diminished 5th": | ||
| 87 | return 6 | 108 | return 6 | ||
| 88 | case "perfect 5th": | 109 | case "perfect 5th": | ||
| 89 | return 7 | 110 | return 7 | ||
| 90 | case "minor 6th": | 111 | case "minor 6th": | ||
| 91 | return 8 | 112 | return 8 | ||
| 92 | case "major 6th": | 113 | case "major 6th": | ||
| 93 | return 9 | 114 | return 9 | ||
| 94 | case "minor 7th": | 115 | case "minor 7th": | ||
| 95 | return 10 | 116 | return 10 | ||
| 96 | case "major 7th": | 117 | case "major 7th": | ||
| 97 | return 11 | 118 | return 11 | ||
| 98 | case _: | 119 | case _: | ||
| 99 | self.interval = "Само онзи, който е живял, страдал и плакал с народа си – само той може да го разбере и да му помогне."+"Христо Ботев" + "He would have hated java" | 120 | self.interval = "Само онзи, който е живял, страдал и плакал с народа си – само той може да го разбере и да му помогне."+"Христо Ботев" + "He would have hated java" | ||
| n | n | 121 | |||
| 122 | |||||
| 100 | def __add__(self, other): | 123 | def __add__(self, other): | ||
| 101 | if isinstance(other, Tone): | 124 | if isinstance(other, Tone): | ||
| 102 | raise TypeError("Invalid operation") | 125 | raise TypeError("Invalid operation") | ||
| 103 | if isinstance(other, Interval): | 126 | if isinstance(other, Interval): | ||
| 104 | plc=Interval(self.go_back_yourself() + other.go_back_yourself()) | 127 | plc=Interval(self.go_back_yourself() + other.go_back_yourself()) | ||
| 105 | return plc | 128 | return plc | ||
| n | n | 129 | |||
| 130 | |||||
| 106 | def __sub__(self, other): | 131 | def __sub__(self, other): | ||
| 107 | if isinstance(other, Tone): | 132 | if isinstance(other, Tone): | ||
| 108 | raise TypeError("Invalid operation") | 133 | raise TypeError("Invalid operation") | ||
| 109 | 134 | ||||
| 110 | 135 | ||||
| 111 | class Chord: | 136 | class Chord: | ||
| n | n | 137 | |||
| 138 | |||||
| 112 | def __init__(self, arg, *args, **kwargs): | 139 | def __init__(self, arg, *args, **kwargs): | ||
| 113 | self.root = arg | 140 | self.root = arg | ||
| 114 | self.set_of_tones = set() | 141 | self.set_of_tones = set() | ||
| 115 | self.set_of_tones.add(arg) | 142 | self.set_of_tones.add(arg) | ||
| 116 | for item in args: | 143 | for item in args: | ||
| 117 | if isinstance(item,tuple): | 144 | if isinstance(item,tuple): | ||
| 118 | res = [] | 145 | res = [] | ||
| 119 | res.extend(item) | 146 | res.extend(item) | ||
| 120 | self.set_of_tones.update(res) | 147 | self.set_of_tones.update(res) | ||
| 121 | else: | 148 | else: | ||
| 122 | self.set_of_tones.update(set(args)) | 149 | self.set_of_tones.update(set(args)) | ||
| 123 | for _, value in kwargs.items(): | 150 | for _, value in kwargs.items(): | ||
| 124 | self.set_of_tones.add(value) | 151 | self.set_of_tones.add(value) | ||
| 125 | if len(self.set_of_tones) < 2: | 152 | if len(self.set_of_tones) < 2: | ||
| 126 | raise TypeError("Cannot have a chord made of only 1 unique tone") | 153 | raise TypeError("Cannot have a chord made of only 1 unique tone") | ||
| n | n | 154 | |||
| 155 | |||||
| 127 | def __str__(self): | 156 | def __str__(self): | ||
| 128 | return "-".join(t.tone for t in sort_tones(self.set_of_tones, self.root)) | 157 | return "-".join(t.tone for t in sort_tones(self.set_of_tones, self.root)) | ||
| n | n | 158 | |||
| 159 | |||||
| 160 | |||||
| 129 | def is_minor(self): | 161 | def is_minor(self): | ||
| 130 | for el in self.set_of_tones: | 162 | for el in self.set_of_tones: | ||
| 131 | interval = self.root - el | 163 | interval = self.root - el | ||
| 132 | if el == self.root: | 164 | if el == self.root: | ||
| 133 | continue | 165 | continue | ||
| 134 | elif interval.interval == "minor 3rd": | 166 | elif interval.interval == "minor 3rd": | ||
| 135 | return True | 167 | return True | ||
| 136 | return False | 168 | return False | ||
| n | n | 169 | |||
| 170 | |||||
| 137 | def is_major(self): | 171 | def is_major(self): | ||
| 138 | for el in self.set_of_tones: | 172 | for el in self.set_of_tones: | ||
| 139 | interval = self.root - el | 173 | interval = self.root - el | ||
| 140 | if el == self.root: | 174 | if el == self.root: | ||
| 141 | continue | 175 | continue | ||
| 142 | elif interval.interval == "major 3rd": | 176 | elif interval.interval == "major 3rd": | ||
| 143 | return True | 177 | return True | ||
| 144 | return False | 178 | return False | ||
| n | n | 179 | |||
| 180 | |||||
| 145 | def is_power_chord(self): | 181 | def is_power_chord(self): | ||
| 146 | return self.is_major() is False and self.is_minor() is False | 182 | return self.is_major() is False and self.is_minor() is False | ||
| n | n | 183 | |||
| 184 | |||||
| 147 | def __add__(self, other): | 185 | def __add__(self, other): | ||
| 148 | if isinstance(other, Tone): | 186 | if isinstance(other, Tone): | ||
| 149 | self.set_of_tones.add(other) | 187 | self.set_of_tones.add(other) | ||
| 150 | sort_tones(self.set_of_tones, self.root) | 188 | sort_tones(self.set_of_tones, self.root) | ||
| 151 | return self | 189 | return self | ||
| 152 | if isinstance(other, Chord): | 190 | if isinstance(other, Chord): | ||
| 153 | self.set_of_tones.update(other.set_of_tones) | 191 | self.set_of_tones.update(other.set_of_tones) | ||
| 154 | placeholed = self | 192 | placeholed = self | ||
| 155 | return placeholed | 193 | return placeholed | ||
| n | n | 194 | |||
| 195 | |||||
| 156 | def __sub__(self, other): | 196 | def __sub__(self, other): | ||
| 157 | if other not in self.set_of_tones: | 197 | if other not in self.set_of_tones: | ||
| 158 | raise TypeError(f"Cannot remove tone {other} from chord {self}") | 198 | raise TypeError(f"Cannot remove tone {other} from chord {self}") | ||
| 159 | elif len(self.set_of_tones) < 3: | 199 | elif len(self.set_of_tones) < 3: | ||
| 160 | raise TypeError("Cannot have a chord made of only 1 unique tone") | 200 | raise TypeError("Cannot have a chord made of only 1 unique tone") | ||
| 161 | else: | 201 | else: | ||
| 162 | self.set_of_tones.remove(other) | 202 | self.set_of_tones.remove(other) | ||
| 163 | sort_tones(self.set_of_tones, self.root) | 203 | sort_tones(self.set_of_tones, self.root) | ||
| 164 | if self.root == other: | 204 | if self.root == other: | ||
| 165 | self.root = list(self.set_of_tones)[0] | 205 | self.root = list(self.set_of_tones)[0] | ||
| 166 | return self | 206 | return self | ||
| n | n | 207 | |||
| 167 | #Не баца за отрицателен инпут и тая си е | 208 | #Не баца за отрицателен интер и тая си е | ||
| 168 | def transposed(self, inter): | 209 | def transposed(self, inter): | ||
| 169 | notes = sort_tones(self.set_of_tones,self.root) | 210 | notes = sort_tones(self.set_of_tones,self.root) | ||
| 170 | for i in range(0,3): | 211 | for i in range(0,3): | ||
| 171 | notes[i] = notes[i] + inter | 212 | notes[i] = notes[i] + inter | ||
| 172 | return Chord(notes[0], tuple(notes)) | 213 | return Chord(notes[0], tuple(notes)) | ||
| t | t | 214 | 
| Legends | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|
 
  | 
              
  |  |||||||||