class Chord(BaseChord, metaclass=SequencerChordSingletonMeta): def __init__(self, root, name, inversion, base_note, extensions): self._load_attributes(root, name, inversion, base_note, extensions) def _load_attributes(self, root_note, chord_name, inversion, base_note, extensions): if not isinstance(root_note, Note): root_note = Note(root_note) if not (data := self._DIRECTORY.get(chord_name)): raise ValueError("Chord name does not exists") self.root = root_note self.inversion = inversion or 0 self.base_note = None if base_note and base_note != root_note: self.base_note = Note.cast_from_theory( base_note, octave=(self.root.octave if (base_note < self.root or self.root.octave == 0) else self.root.octave - 1)) self.name, intervals = data self.intervals = copy(intervals) if inversion and (inversion < 0 or inversion >= len(self.intervals)): raise ValueError("Chord inversion out of range") notes = [] if self.base_note: notes.append(self.base_note) base_chord_notes = [self.root] + [ self.root + interval for interval in self.intervals[1:] ] notes += base_chord_notes[ self.inversion:] + base_chord_notes[:self.inversion] self.notes = [notes[0]] last_note = notes[0] for note in notes[1:]: # AU CAS OU IL Y AURAIT DES INTERVALES ETENDUS while note < last_note: note += OCTAVE self.notes.append(note) last_note = note self.extensions = [] for extension in sorted(extensions): if extension in self.intervals: continue self.notes.append(self.root + extension) self.intervals.append(extension) self.extensions.append(extension) self.notes = list(sorted(self.notes)) self.intervals = list(sorted(self.intervals))
def adapt_chord_to_sequencer(chord, range): low_range, high_range = range chord_data = chord.to_dict() root_note = chord_data.pop("root_note") if isinstance(chord, TheoryChord): root_note = Note.cast_from_theory(root_note) if root_note < low_range: while root_note < low_range: root_note += OCTAVE chord = Chord(root_note=root_note, **chord_data) return [note for note in chord.notes if note <= high_range]