import music21 from itertools import islice from music21 import note, harmony, expressions # constants SLUR_SYMBOL = '__' START_SYMBOL = 'START' END_SYMBOL = 'END' REST_SYMBOL = 'rest' OUT_OF_RANGE = 'OOR' PAD_SYMBOL = 'XX' def standard_name(note_or_rest, voice_range=None): """ Convert music21 objects to str :param note_or_rest: :return: """ if isinstance(note_or_rest, note.Note): if voice_range is not None: min_pitch, max_pitch = voice_range pitch = note_or_rest.pitch.midi if pitch < min_pitch or pitch > max_pitch: return OUT_OF_RANGE return note_or_rest.nameWithOctave if isinstance(note_or_rest, note.Rest): return note_or_rest.name # == 'rest' := REST_SYMBOL if isinstance(note_or_rest, str): return note_or_rest if isinstance(note_or_rest, harmony.ChordSymbol): return note_or_rest.figure if isinstance(note_or_rest, expressions.TextExpression): return note_or_rest.content def standard_note(note_or_rest_string): """ Convert str representing a music21 object to this object :param note_or_rest_string: :return: """ if note_or_rest_string == 'rest': return note.Rest() # treat other additional symbols as rests elif (note_or_rest_string == END_SYMBOL or note_or_rest_string == START_SYMBOL or note_or_rest_string == PAD_SYMBOL): # print('Warning: Special symbol is used in standard_note') return note.Rest() elif note_or_rest_string == SLUR_SYMBOL: # print('Warning: SLUR_SYMBOL used in standard_note') return note.Rest() elif note_or_rest_string == OUT_OF_RANGE: # print('Warning: OUT_OF_RANGE used in standard_note') return note.Rest() else: return note.Note(note_or_rest_string) class ShortChoraleIteratorGen: """ Class used for debugging when called, it returns an iterator over 3 Bach chorales, similar to music21.corpus.chorales.Iterator() """ def __init__(self): pass def __call__(self): it = ( chorale for chorale in islice(music21.corpus.chorales.Iterator(), 3) ) return it.__iter__()