Skip to content

Commit

Permalink
Merge pull request #1435 from malcolmsailor/rntxt-write-repeats
Browse files Browse the repository at this point in the history
Romantext writer handle repeat bars and measure suffixes like m1a
  • Loading branch information
mscuthbert authored Sep 23, 2022
2 parents dbc1af7 + 8de236e commit 0228d71
Showing 1 changed file with 52 additions and 5 deletions.
57 changes: 52 additions & 5 deletions music21/romanText/writeRoman.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@
'''

import fractions
import textwrap
import unittest

import typing as t

from music21 import bar
from music21 import base
from music21 import metadata
from music21 import meter
Expand Down Expand Up @@ -255,19 +257,45 @@ def prepSequentialListOfLines(self):
msg = f'further time signature change(s) unprocessed: {unprocessedTSs}'
self.combinedList.append(f'Note: {msg}')

measureNumberString = str(thisMeasure.measureNumber)
if thisMeasure.numberSuffix is not None:
measureNumberString += thisMeasure.numberSuffix

# RomanNumerals
measureString = '' # Clear for each measure

rnsThisMeasure = thisMeasure.getElementsByClass(roman.RomanNumeral)
if (isinstance(thisMeasure.leftBarline, bar.Repeat)
and thisMeasure.leftBarline.direction == 'start'):
measureString = rnString(measureNumber=measureNumberString,
beat=1.0,
chordString='||:',
inString=measureString,
)

for rn in rnsThisMeasure:
if rn.tie is None or rn.tie.type == 'start': # Ignore tied to Roman numerals
chordString = self.getChordString(rn)
measureString = rnString(measureNumber=thisMeasure.measureNumber, # Suffix?
measureString = rnString(measureNumber=measureNumberString,
beat=rn.beat,
chordString=chordString,
inString=measureString, # Creating update
)
if (isinstance(thisMeasure.rightBarline, bar.Repeat)
and thisMeasure.rightBarline.direction == 'end'):
# we want to put the repeat at the beat of the last roman
# numeral to avoid printing an unnecessary indication like
# 'b3' prior to the repeat
last_rn = thisMeasure[roman.RomanNumeral].last()
if last_rn is None:
beat = 1.0
else:
beat = last_rn.beat
measureString = rnString(measureNumber=measureNumberString,
beat=beat,
chordString=':||',
inString=measureString,
)

if measureString:
self.combinedList.append(measureString)
Expand Down Expand Up @@ -303,7 +331,7 @@ def getChordString(self,

# ------------------------------------------------------------------------------

def rnString(measureNumber: int,
def rnString(measureNumber: t.Union[int, str],
beat: t.Union[str, int, float, fractions.Fraction],
chordString: str,
inString: t.Optional[str] = ''):
Expand Down Expand Up @@ -332,11 +360,14 @@ def rnString(measureNumber: int,
'''

if inString:
inStringMeasureNumber = int(inString.split(' ')[0][1:])
if inStringMeasureNumber != measureNumber:
inStringMeasureNumber = inString.split(' ')[0][1:]
# inStringMeasureNumber was previously cast to int, but this fails on
# measures with suffixes ("m1a"). However, now we need to cast
# measureNumber to string in the following comparison.
if inStringMeasureNumber != str(measureNumber):
msg = f'The current measureNumber is given as {measureNumber}, but '
msg += f'the contextual inString ({inString}) refers to '
msg += 'measure number {measureNumber}. They should match.'
msg += f'measure number {measureNumber}. They should match.'
raise ValueError(msg)
else: # inString and therefore start new line
inString = f'm{measureNumber}'
Expand Down Expand Up @@ -542,6 +573,22 @@ def testTypeParses(self):
rn = roman.RomanNumeral('viio6', 'G')
RnWriter(rn) # and even (perhaps dubiously) directly on other music21 objects

def testRepeats(self):
from music21 import converter
rntxt = textwrap.dedent('''
Time Signature: 2/4
m1 ||: C: I
m2 V :||
m3 ||: I :||
m4 ||: I
m5a V :||
m5b I
''')
s = converter.parse(rntxt, format='romanText')
writer = RnWriter(s)
assert '\n'.join(writer.combinedList).strip().endswith(rntxt.strip())


# ------------------------------------------------------------------------------

def testRnString(self):
Expand Down

0 comments on commit 0228d71

Please sign in to comment.