Skip to content

Commit 5b6a4dc

Browse files
authored
Merge pull request #4 from gregchapman-dev/gregc/barlines
Add Barline to the extras for each Measure.
2 parents 5acd04e + db8ff6b commit 5b6a4dc

File tree

2 files changed

+43
-9
lines changed

2 files changed

+43
-9
lines changed

musicdiff/annotation.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,7 @@ def get_note_ids(self):
323323

324324

325325
class AnnMeasure:
326-
def __init__(self, measure, score):
326+
def __init__(self, measure, score, spannerBundle):
327327
"""
328328
Extend music21 Measure with some precomputed, easily compared information about it.
329329
@@ -346,7 +346,7 @@ def __init__(self, measure, score):
346346
self.n_of_voices = len(self.voices_list)
347347

348348
self.extras_list = []
349-
for extra in M21Utils.get_extras(measure, score.spannerBundle):
349+
for extra in M21Utils.get_extras(measure, spannerBundle):
350350
self.extras_list.append(AnnExtra(extra, measure, score))
351351

352352
# For correct comparison, sort the extras_list, so that any list slices
@@ -400,7 +400,7 @@ def get_note_ids(self):
400400

401401

402402
class AnnPart:
403-
def __init__(self, part, score):
403+
def __init__(self, part, score, spannerBundle):
404404
"""
405405
Extend music21 Part/PartStaff with some precomputed, easily compared information about it.
406406
@@ -410,7 +410,7 @@ def __init__(self, part, score):
410410
self.part = part.id
411411
self.bar_list = []
412412
for measure in part.getElementsByClass("Measure"):
413-
ann_bar = AnnMeasure(measure, score) # create the bar objects
413+
ann_bar = AnnMeasure(measure, score, spannerBundle) # create the bar objects
414414
if ann_bar.n_of_voices > 0:
415415
self.bar_list.append(ann_bar)
416416
self.n_of_bars = len(self.bar_list)
@@ -465,9 +465,10 @@ def __init__(self, score):
465465
"""
466466
self.score = score.id
467467
self.part_list = []
468+
spannerBundle = score.spannerBundle
468469
for part in score.parts.stream():
469470
# create and add the AnnPart object to part_list
470-
ann_part = AnnPart(part, score)
471+
ann_part = AnnPart(part, score, spannerBundle)
471472
if ann_part.n_of_bars > 0:
472473
self.part_list.append(ann_part)
473474
self.n_of_parts = len(self.part_list)

musicdiff/m21utils.py

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -394,10 +394,19 @@ def get_extras(measure: m21.stream.Measure, spannerBundle: m21.spanner.SpannerBu
394394
# substreams/Voices), skipping any Streams, GeneralNotes (which are returned from
395395
# get_notes/get_notes_and_gracenotes), and Barlines. We're looking for things
396396
# like Clefs, TextExpressions, and Dynamics...
397-
output: List[m21.base.Music21Object] = list(measure.recurse().getElementsNotOfClass((m21.note.GeneralNote,
398-
m21.stream.Stream,
399-
m21.bar.Barline,
400-
m21.layout.LayoutBase )))
397+
output: List[m21.base.Music21Object] = []
398+
399+
initialList: List[m21.base.Music21Object] = list(
400+
measure.recurse().getElementsNotOfClass(
401+
(m21.note.GeneralNote,
402+
m21.stream.Stream,
403+
m21.layout.LayoutBase) ) )
404+
405+
# loop over the initialList, filtering out (and complaining about) things we
406+
# don't recognize.
407+
for el in initialList:
408+
if M21Utils.extra_to_string(el) != '':
409+
output.append(el)
401410

402411
# we must add any Crescendo/Diminuendo spanners that start on GeneralNotes in this measure
403412
for gn in measure.recurse().getElementsByClass(m21.note.GeneralNote):
@@ -476,6 +485,28 @@ def tempo_to_string(mm: m21.tempo.TempoIndication) -> str:
476485
return f'{M21Utils.tempo_to_string(mm._tempoText)} {mm.referent.fullName}={float(mm.number)}'
477486
# pylint: enable=protected-access
478487

488+
@staticmethod
489+
def barline_to_string(barline: m21.bar.Barline) -> str:
490+
# for all Barlines: type, pause
491+
# for Repeat Barlines: direction, times
492+
pauseStr: str = ''
493+
if barline.pause is not None:
494+
if isinstance(barline.pause, m21.expressions.Fermata):
495+
pauseStr = ' with fermata'
496+
else:
497+
pauseStr = ' with pause (non-fermata)'
498+
499+
output: str = f'{barline.type}{pauseStr}'
500+
if not isinstance(barline, m21.bar.Repeat):
501+
return f'BL:{output}'
502+
503+
# add the Repeat fields (direction, times)
504+
if barline.direction is not None:
505+
output += f' direction={barline.direction}'
506+
if barline.times is not None:
507+
output += f' times={barline.times}'
508+
return f'RPT:{output}'
509+
479510
@staticmethod
480511
def extra_to_string(extra: m21.base.Music21Object) -> str:
481512
# object classes that have text content in a single field
@@ -499,6 +530,8 @@ def extra_to_string(extra: m21.base.Music21Object) -> str:
499530
return M21Utils.timesig_to_string(extra)
500531
if isinstance(extra, m21.tempo.TempoIndication):
501532
return M21Utils.tempo_to_string(extra)
533+
if isinstance(extra, m21.bar.Barline):
534+
return M21Utils.barline_to_string(extra)
502535

503536
print(f'Unexpected extra: {extra.classes[0]}', file=sys.stderr)
504537
return ''

0 commit comments

Comments
 (0)