| f | class Tone: | f | class Tone: | 
             |     CHROMATIC_SCALE = ("C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B") |  |     CHROMATIC_SCALE = ("C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B") | 
             |  |  |  | 
             |     def __init__(self, name): |  |     def __init__(self, name): | 
             |         self.name = name |  |         self.name = name | 
             |         self.index = self.CHROMATIC_SCALE.index(name) |  |         self.index = self.CHROMATIC_SCALE.index(name) | 
             |  |  |  | 
             |     def __str__(self): |  |     def __str__(self): | 
             |         return self.name |  |         return self.name | 
             |      |  |      | 
             |     def __eq__(self, other): |  |     def __eq__(self, other): | 
             |         return self.name == other.name |  |         return self.name == other.name | 
             |      |  |      | 
             |     def __hash__(self): |  |     def __hash__(self): | 
             |         return hash(self.name) |  |         return hash(self.name) | 
             |      |  |      | 
             |     def __add__(self, other): |  |     def __add__(self, other): | 
            | n |  | n |         """Add Tone and Tone or Tone and Interval""" | 
             |         if isinstance(other, Tone): |  |         if isinstance(other, Tone): | 
             |             return Chord(self, other) |  |             return Chord(self, other) | 
             |         if isinstance(other, Interval): |  |         if isinstance(other, Interval): | 
             |             return Tone(self.CHROMATIC_SCALE[(self.index + other.semitones) % 12]) |  |             return Tone(self.CHROMATIC_SCALE[(self.index + other.semitones) % 12]) | 
             |      |  |      | 
             |     def __sub__(self, other): |  |     def __sub__(self, other): | 
            | n |  | n |         """Substract Tone from Tone or Tone from Interval""" | 
             |         if isinstance(other, Tone): |  |         if isinstance(other, Tone): | 
             |             return Interval((self.index - other.index) % 12) |  |             return Interval((self.index - other.index) % 12) | 
             |         if isinstance(other, Interval): |  |         if isinstance(other, Interval): | 
             |             return Tone(self.CHROMATIC_SCALE[(self.index - other.semitones) % 12]) |  |             return Tone(self.CHROMATIC_SCALE[(self.index - other.semitones) % 12]) | 
             |  |  |  | 
             |      |  |      | 
             |  |  |  | 
             | class Interval: |  | class Interval: | 
             |     INTERVAL_NAMES = ( |  |     INTERVAL_NAMES = ( | 
             |         "unison", |  |         "unison", | 
             |         "minor 2nd", |  |         "minor 2nd", | 
             |         "major 2nd",     |  |         "major 2nd",     | 
             |         "minor 3rd", |  |         "minor 3rd", | 
             |         "major 3rd", |  |         "major 3rd", | 
             |         "perfect 4th", |  |         "perfect 4th", | 
             |         "diminished 5th", |  |         "diminished 5th", | 
             |         "perfect 5th", |  |         "perfect 5th", | 
             |         "minor 6th", |  |         "minor 6th", | 
             |         "major 6th", |  |         "major 6th", | 
             |         "minor 7th", |  |         "minor 7th", | 
             |         "major 7th" |  |         "major 7th" | 
             |     ) |  |     ) | 
             |  |  |  | 
             |     def __init__(self, semitones): |  |     def __init__(self, semitones): | 
             |         self.semitones = semitones % 12 |  |         self.semitones = semitones % 12 | 
             |  |  |  | 
             |     def __str__(self): |  |     def __str__(self): | 
             |         return self.INTERVAL_NAMES[self.semitones % 12] |  |         return self.INTERVAL_NAMES[self.semitones % 12] | 
             |      |  |      | 
             |     def __add__(self, other): |  |     def __add__(self, other): | 
            | n |  | n |         """Throw err when adding Interval and Tone; Add Interval and Interval""" | 
             |         if isinstance(other, Tone): |  |         if isinstance(other, Tone): | 
             |             raise TypeError("Invalid operation") |  |             raise TypeError("Invalid operation") | 
             |         if isinstance(other, Interval): |  |         if isinstance(other, Interval): | 
             |             return Interval((self.semitones + other.semitones) % 12) |  |             return Interval((self.semitones + other.semitones) % 12) | 
             |          |  |          | 
             |     def __sub__(self, other): |  |     def __sub__(self, other): | 
            | n |  | n |         """Throw err when substracting Tone from Interval""" | 
             |         if isinstance(other, Tone): |  |         if isinstance(other, Tone): | 
             |             raise TypeError("Invalid operation") |  |             raise TypeError("Invalid operation") | 
             |          |  |          | 
             |     def __neg__(self): |  |     def __neg__(self): | 
             |         return Interval(-self.semitones) |  |         return Interval(-self.semitones) | 
             |      |  |      | 
             |  |  |  | 
             | class Chord: |  | class Chord: | 
             |     def __init__(self, root, *tones): |  |     def __init__(self, root, *tones): | 
             |         unique_tones = {root, *tones} |  |         unique_tones = {root, *tones} | 
             |         if len(unique_tones) < 2: |  |         if len(unique_tones) < 2: | 
             |             raise TypeError("Cannot have a chord made of only 1 unique tone") |  |             raise TypeError("Cannot have a chord made of only 1 unique tone") | 
             |         self.root = root |  |         self.root = root | 
             |         self.tones = sorted(unique_tones, key=lambda tone: (tone.index - root.index) % 12) |  |         self.tones = sorted(unique_tones, key=lambda tone: (tone.index - root.index) % 12) | 
             |  |  |  | 
             |     def __str__(self): |  |     def __str__(self): | 
             |         return "-".join(str(t) for t in self.tones) |  |         return "-".join(str(t) for t in self.tones) | 
             |      |  |      | 
             |     def is_minor(self): |  |     def is_minor(self): | 
            | n |  | n |         """Has minor 3rd""" | 
             |         return any((t.index - self.root.index) % 12 == 3 for t in self.tones) |  |         return any((t.index - self.root.index) % 12 == 3 for t in self.tones) | 
             |      |  |      | 
             |     def is_major(self): |  |     def is_major(self): | 
            | n |  | n |         """Has major 3rd""" | 
             |         return any((t.index - self.root.index) % 12 == 4 for t in self.tones) |  |         return any((t.index - self.root.index) % 12 == 4 for t in self.tones) | 
             |      |  |      | 
             |     def is_power_chord(self): |  |     def is_power_chord(self): | 
            | n |  | n |         """Is not minor and major""" | 
             |         return not (self.is_minor() or self.is_major()) |  |         return not (self.is_minor() or self.is_major()) | 
             |      |  |      | 
             |     def __sub__(self, other): |  |     def __sub__(self, other): | 
            | n |  | n |         """Substract Tone from Chord""" | 
             |         if isinstance(other, Tone): |  |         if isinstance(other, Tone): | 
             |             if other not in self.tones: |  |             if other not in self.tones: | 
             |                 raise TypeError(f"Cannot remove tone {other} from chord {self}") |  |                 raise TypeError(f"Cannot remove tone {other} from chord {self}") | 
             |             new_tones = [tone for tone in self.tones if tone != other] |  |             new_tones = [tone for tone in self.tones if tone != other] | 
             |             if len(new_tones) < 2: |  |             if len(new_tones) < 2: | 
             |                 raise TypeError("Cannot have a chord made of only 1 unique tone") |  |                 raise TypeError("Cannot have a chord made of only 1 unique tone") | 
             |             if other == self.root: |  |             if other == self.root: | 
             |                 new_root = new_tones[0] |  |                 new_root = new_tones[0] | 
             |                 return Chord(new_root, *new_tones) |  |                 return Chord(new_root, *new_tones) | 
             |             return Chord(self.root, *new_tones) |  |             return Chord(self.root, *new_tones) | 
             |          |  |          | 
             |     def __add__(self, other): |  |     def __add__(self, other): | 
            | n |  | n |         """Add Chord and Tone or Chord and Chord""" | 
             |  |  |         if isinstance(other, Tone): | 
             |  |  |             self.tones.append(other) | 
             |  |  |             unique_tones = {self.root, *self.tones} | 
             |  |  |             self.tones = sorted(unique_tones, key=lambda tone: (tone.index - self.root.index) % 12) | 
             |  |  |             return Chord(self.root, *self.tones) | 
             |         if isinstance(other, Chord): |  |         if isinstance(other, Chord): | 
             |             tones_sum = {self.root, *self.tones, *other.tones} |  |             tones_sum = {self.root, *self.tones, *other.tones} | 
             |             return Chord(self.root, *tones_sum) |  |             return Chord(self.root, *tones_sum) | 
             |          |  |          | 
             |     def transposed(self, interval): |  |     def transposed(self, interval): | 
            | n |  | n |         """Move with interval positions each tone in the chord""" | 
             |         transposed_tones = [tone + interval for tone in self.tones] |  |         transposed_tones = [tone + interval for tone in self.tones] | 
             |         return Chord(transposed_tones[0], *transposed_tones) |  |         return Chord(transposed_tones[0], *transposed_tones) | 
            | t |   | t |  | 
        
     
07.11.2024 09:20
07.11.2024 09:21
07.11.2024 09:22