diff --git a/musicdiff/__init__.py b/musicdiff/__init__.py index e6c714f..3c3e792 100644 --- a/musicdiff/__init__.py +++ b/musicdiff/__init__.py @@ -97,7 +97,7 @@ def diff( AllObjects), or any combination (with | or &~) of those or NotesAndRests, Beams, Tremolos, Ornaments, Articulations, Ties, Slurs, Signatures, Directions, Barlines, StaffDetails, ChordSymbols, Ottavas, Arpeggios, Lyrics, - Style, Metadata, Voicing, or NoteStaffPosition. + LyricIdentifiers, Style, Metadata, Voicing, or NoteStaffPosition. Returns: int | None: The total OMR Edit Distance, i.e. the number of individual symbols @@ -355,7 +355,7 @@ def diff_ml_training( AllObjects), or any combination (with | or &~) of those or NotesAndRests, Beams, Tremolos, Ornaments, Articulations, Ties, Slurs, Signatures, Directions, Barlines, StaffDetails, ChordSymbols, Ottavas, Arpeggios, Lyrics, - Style, Metadata, Voicing, or NoteStaffPosition. + LyricIdentifiers, Style, Metadata, Voicing, or NoteStaffPosition. Returns: tuple[float, str]: Overall OMR-NED score for the batch, and the full path to the diff --git a/musicdiff/__main__.py b/musicdiff/__main__.py index 801f12d..6a30d0a 100644 --- a/musicdiff/__main__.py +++ b/musicdiff/__main__.py @@ -25,8 +25,8 @@ ''' if __name__ == '__main__': usage: str = '''python3 -m musicdiff [-h] - [-i [{decoratednotesandrests,otherobjects,allobjects,style,metadata,voicing,notestaffposition,notesandrests,beams,tremolos,ornaments,articulations,ties,slurs,signatures,directions,barlines,staffdetails,chordsymbols,ottavas,arpeggios,lyrics} ...]] - [-x [{decoratednotesandrests,otherobjects,allobjects,style,metadata,voicing,notestaffposition,notesandrests,beams,tremolos,ornaments,articulations,ties,slurs,signatures,directions,barlines,staffdetails,chordsymbols,ottavas,arpeggios,lyrics} ...]] + [-i [{decoratednotesandrests,otherobjects,allobjects,style,metadata,voicing,notestaffposition,lyricidentifiers,notesandrests,beams,tremolos,ornaments,articulations,ties,slurs,signatures,directions,barlines,staffdetails,chordsymbols,ottavas,arpeggios,lyrics} ...]] + [-x [{decoratednotesandrests,otherobjects,allobjects,style,metadata,voicing,notestaffposition,lyricidentifiers,notesandrests,beams,tremolos,ornaments,articulations,ties,slurs,signatures,directions,barlines,staffdetails,chordsymbols,ottavas,arpeggios,lyrics} ...]] [-o [{visual,v,text,t,omrned,o} ...]] [--fix_first_file_syntax] file1 file2 @@ -37,8 +37,8 @@ --ground_truth_folder gtfolderpath --predicted_folder predfolderpath --output_folder outputfolderpath - [-i [{decoratednotesandrests,otherobjects,allobjects,style,metadata,voicing,notestaffposition,notesandrests,beams,tremolos,ornaments,articulations,ties,slurs,signatures,directions,barlines,staffdetails,chordsymbols,ottavas,arpeggios,lyrics} ...]] - [-x [{decoratednotesandrests,otherobjects,allobjects,style,metadata,voicing,notestaffposition,notesandrests,beams,tremolos,ornaments,articulations,ties,slurs,signatures,directions,barlines,staffdetails,chordsymbols,ottavas,arpeggios,lyrics} ...]] + [-i [{decoratednotesandrests,otherobjects,allobjects,style,metadata,voicing,notestaffposition,lyricidentifiers,notesandrests,beams,tremolos,ornaments,articulations,ties,slurs,signatures,directions,barlines,staffdetails,chordsymbols,ottavas,arpeggios,lyrics} ...]] + [-x [{decoratednotesandrests,otherobjects,allobjects,style,metadata,voicing,notestaffposition,lyricidentifiers,notesandrests,beams,tremolos,ornaments,articulations,ties,slurs,signatures,directions,barlines,staffdetails,chordsymbols,ottavas,arpeggios,lyrics} ...]] ''' epilog: str = '''\ @@ -102,6 +102,7 @@ 'metadata', 'voicing', 'notestaffposition', + 'lyricidentifiers', 'notesandrests', 'beams', @@ -135,6 +136,7 @@ 'metadata', 'voicing', 'notestaffposition', + 'lyricidentifiers', 'notesandrests', 'beams', @@ -246,6 +248,8 @@ detail |= DetailLevel.Metadata elif det == 'notestaffposition': detail |= DetailLevel.NoteStaffPosition + elif det == 'lyricidentifiers': + detail |= DetailLevel.LyricIdentifiers # bits in the DecoratedNotesAndRests combo elif det == 'notesandrests': @@ -300,6 +304,8 @@ detail &= ~DetailLevel.Metadata elif det == 'notestaffposition': detail &= ~DetailLevel.NoteStaffPosition + elif det == 'lyricidentifiers': + detail &= ~DetailLevel.LyricIdentifiers # bits in the DecoratedNotesAndRests combo elif det == 'notesandrests': diff --git a/musicdiff/annotation.py b/musicdiff/annotation.py index cbe3f5f..392606a 100755 --- a/musicdiff/annotation.py +++ b/musicdiff/annotation.py @@ -85,7 +85,7 @@ def __init__( AllObjects), or any combination (with | or &~) of those or NotesAndRests, Beams, Tremolos, Ornaments, Articulations, Ties, Slurs, Signatures, Directions, Barlines, StaffDetails, ChordSymbols, Ottavas, Arpeggios, Lyrics, - Style, Metadata, Voicing, or NoteStaffPosition. + LyricIdentifiers, Style, Metadata, Voicing, or NoteStaffPosition. ''' super().__init__(general_note) self.is_in_chord: bool = False @@ -672,7 +672,7 @@ def __init__( AllObjects), or any combination (with | or &~) of those or NotesAndRests, Beams, Tremolos, Ornaments, Articulations, Ties, Slurs, Signatures, Directions, Barlines, StaffDetails, ChordSymbols, Ottavas, Arpeggios, Lyrics, - Style, Metadata, Voicing, or NoteStaffPosition. + LyricIdentifiers, Style, Metadata, Voicing, or NoteStaffPosition. ''' super().__init__(extra) self.kind: str = M21Utils.extra_to_kind(extra) @@ -894,7 +894,7 @@ def __init__( AllObjects), or any combination (with | or &~) of those or NotesAndRests, Beams, Tremolos, Ornaments, Articulations, Ties, Slurs, Signatures, Directions, Barlines, StaffDetails, ChordSymbols, Ottavas, Arpeggios, Lyrics, - Style, Metadata, Voicing, or NoteStaffPosition. + LyricIdentifiers, Style, Metadata, Voicing, or NoteStaffPosition. ''' super().__init__(lyric_holder) @@ -911,7 +911,8 @@ def __init__( if lyric.number is not None: self.number = lyric.number - if (lyric._identifier is not None + if (DetailLevel.includesLyricIdentifiers(detail) + and lyric._identifier is not None and lyric._identifier != lyric.number and lyric._identifier != str(lyric.number)): self.identifier = lyric._identifier @@ -1027,7 +1028,7 @@ def __init__( AllObjects), or any combination (with | or &~) of those or NotesAndRests, Beams, Tremolos, Ornaments, Articulations, Ties, Slurs, Signatures, Directions, Barlines, StaffDetails, ChordSymbols, Ottavas, Arpeggios, Lyrics, - Style, Metadata, Voicing, or NoteStaffPosition. + LyricIdentifiers, Style, Metadata, Voicing, or NoteStaffPosition. ''' super().__init__(voice) note_list: list[m21.note.GeneralNote] = [] @@ -1176,7 +1177,7 @@ def __init__( AllObjects), or any combination (with | or &~) of those or NotesAndRests, Beams, Tremolos, Ornaments, Articulations, Ties, Slurs, Signatures, Directions, Barlines, StaffDetails, ChordSymbols, Ottavas, Arpeggios, Lyrics, - Style, Metadata, Voicing, or NoteStaffPosition. + LyricIdentifiers, Style, Metadata, Voicing, or NoteStaffPosition. ''' super().__init__(measure) self.includes_voicing: bool = DetailLevel.includesVoicing(detail) @@ -1411,7 +1412,7 @@ def __init__( AllObjects), or any combination (with | or &~) of those or NotesAndRests, Beams, Tremolos, Ornaments, Articulations, Ties, Slurs, Signatures, Directions, Barlines, StaffDetails, ChordSymbols, Ottavas, Arpeggios, Lyrics, - Style, Metadata, Voicing, or NoteStaffPosition. + LyricIdentifiers, Style, Metadata, Voicing, or NoteStaffPosition. ''' super().__init__(part) self.part_idx: int = part_idx @@ -1720,7 +1721,7 @@ def __init__( AllObjects), or any combination (with | or &~) of those or NotesAndRests, Beams, Tremolos, Ornaments, Articulations, Ties, Slurs, Signatures, Directions, Barlines, StaffDetails, ChordSymbols, Ottavas, Arpeggios, Lyrics, - Style, Metadata, Voicing, or NoteStaffPosition. + LyricIdentifiers, Style, Metadata, Voicing, or NoteStaffPosition. ''' super().__init__(score) self.part_list: list[AnnPart] = [] diff --git a/musicdiff/detaillevel.py b/musicdiff/detaillevel.py index 1233317..35ed9be 100644 --- a/musicdiff/detaillevel.py +++ b/musicdiff/detaillevel.py @@ -108,6 +108,13 @@ class DetailLevel(IntEnum): # into every affected note. If this is set, NotesAndRests will also be considered set. NoteStaffPosition = 1 << 18 + # The names the encoding gives to the lyric verses ('verse', 'part1verse1', etc). + # They print nothing in the score, so they are off by default; turn them on to + # compare them. + # Note that if Lyrics is not also requested, no lyric identifier differences + # will be found. + LyricIdentifiers = 1 << 19 + # default detail level is all objects: Default = AllObjects @@ -193,6 +200,10 @@ def includesVoicing(cls, val: int) -> bool: def includesNoteStaffPosition(cls, val: int) -> bool: return val & cls.NoteStaffPosition != 0 + @classmethod + def includesLyricIdentifiers(cls, val: int) -> bool: + return val & cls.LyricIdentifiers != 0 + @classmethod def _included_m21_types(cls, val: int) -> tuple[t.Type, ...]: # Not all types go in here, just the ones where we will have pulled