-
Notifications
You must be signed in to change notification settings - Fork 407
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Romantext writer handle repeat bars and measure suffixes like m1a #1435
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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 | ||
|
@@ -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) | ||
|
@@ -332,11 +360,14 @@ def rnString(measureNumber: int, | |
''' | ||
|
||
if inString: | ||
inStringMeasureNumber = int(inString.split(' ')[0][1:]) | ||
if inStringMeasureNumber != measureNumber: | ||
inStringMeasureNumber = inString.split(' ')[0][1:] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Do you mean on this line? The only thing I changed was removing the cast to int. It doesn't split the suffix, it splits the inString on space and then slices the "m" from the beginning. As far as I can tell the suffix stays put once it is added. I agree this function is clearly inefficient. It seems the obvious thing to do would be accumulate each "word" to a list and then do |
||
# 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}' | ||
|
@@ -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): | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In definition of rnString, change type to t.Union[int, str]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But it looks like you're concating int(measure.number) + measure.suffix only to separate them later. why not pass in the suffix separately?
I didn't look carefully enough at
rnString()
when this went in. It's quite inefficient. It seems to me that it really should be an object whose str gives the correct result so you don't need to keep passing in a the same string to concat to and read from over and over. But that's a later/larger refactor.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks all.
+1 for sorting out
rnString
.Mea culpa for how it looks as it stands though I suspect it ended up that way as one of those solutions that seeks to please everyone ... but ends up half way between different solutions and ends up pleasing no one ;)
See #1393 for an alternative that removes it completely.
I'm happy to advance this sometime.