def get_notes_from_root(cls, root, note_list_type=None, octave=None, alt=Note.SHARP): """ :param root: root note :param note_list_type: a list of notes distance from root note :param octave: octave of notes in chord :param alt: note alteration 'sharp' or 'flat' :type root: Note :type note_list_type: list :type octave: Union[int, string, callable] :type alt: string :return: Scale """ if note_list_type is None: raise NoteListException('Invalid note list type') if octave is None: octave = cls.OCTAVE_TYPE_ROOT root_idx = root.get_note_index() def get_octave(i, distance): if callable(octave): return octave(root.octave, i, distance) elif isinstance(octave, int): return octave elif octave == cls.OCTAVE_TYPE_ROOT: return root.octave elif octave == cls.OCTAVE_TYPE_FROM_ROOT: return root.octave + int(distance / len(Note.NOTES)) else: return Note.A_DEFAULT_OCTAVE notes = [ Note(name=Note.get_note_name_by_index(root_idx + distance, alt=alt), octave=get_octave(i, root_idx + distance), alt=alt) for i, distance in enumerate(note_list_type) ] notes.insert(0, root) return notes
def test_get_note_name_by_index(): assert Note.get_note_name_by_index(0) == 'C' assert Note.get_note_name_by_index(1) == 'C#' assert Note.get_note_name_by_index(1, alt=Note.FLAT) == 'Db' assert Note.get_note_name_by_index(12) == 'C' assert Note.get_note_name_by_index(26) == 'D'