Skip to content

Conversation

@adhooge
Copy link
Contributor

@adhooge adhooge commented May 23, 2023

Fixes #1471

Hi! First PR so I expect a few things to be added/modified but here's a first draft.
I've updated the FretBend articulation so that it includes the musicXML properties bendAlter, preBend and release.

It goes round from musicXML to m21 back to mXML.

I've not written any tests yet because I'm not sure what to add. Let me know of what could be good to add!

as a PR newbie, I also have some irrelevant commits that I manually reverted. If that's a problem I'll try to clean that up.

Copy link
Member

@mscuthbert mscuthbert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well on its way! Ask around if you need help in writing tests, and for help on why music21's system of intervals is more complex than musicxml's.

(the changes to note.Note are rejected, so please remove them, thanks!)

release: t.Optional[float]
withBar: t.Optional[bool]

def __init__(self, number=0, preBend=False, release=None, withBar=None, **keywords):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

number is too generic a term -- and we usually reserve the term for identifying which of multiple simultaneous items (like slur number=1 vs slur number=2). Are fret-bends always chromatic intervals? it seems like you can also have a diatonic interval of a fretbend. hence why bendAlter was typed as IntervalBase not ChromaticInterval. It seems better to have bendAlter as described above interval.IntervalBase | None = None where None indicates unspecified. Having a default of 0, becoming ChromaticInterval(0) indicates that this fretBend does not alter the pitch at all, which would be a very strange fret bend. This would also make it so that interval.py does not need to be imported here.

The other keywords should be typed in the __init__ declaration in addition to the class.

We no longer use t.Optional[X] in the code base. Use X | None instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed with d63c78a

Comment on lines 593 to 600
bend indication for fretted instruments
bend in musicxml
number is the interval of the bend in number of semitones, bend-alter in musicxml
preBend indicates wether the note is prebended or not
release is the offset value for releasing the bend, if Any
withBar indicates if the bend is done using a whammy bar movement
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Capitalization and use asterisks and line breaks for documentation -- run documentation/build.py and look at the difference between the docs produced here and elsewhere in the system.

preBend indicates wether the note is prebended or not -- I don't know what prebended means.

what is release measured in? Is it an offset (which is relative to the start of the Measure/stream)? That doesn't sound right. Is it a quarterLength measured from the start of the note? or from the end of the note.

withBar doc is fine.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've tried to improve it in 03e6117
Let me know if that seems good to you

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tests are on their way

Comment on lines 5526 to 5527
bendAlterSubElement = SubElement(mxTechnicalMark, 'bend-alter')
bendAlterSubElement.text = str(articulationMark.bendAlter.semitones)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this has enough ifs that it should be brought out as its own small method that allows for easier documentation and testing. articulationMark will probably need to be cast as a FretBend.

We can solve the case of GenericInterval later, which doesn't have .semitones. Perhaps it always needs to be a full Interval object or None.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New submethod added in 85cc6a8
Now I indeed have the problem that I need to retrieve the number of semitones. I could probably do something with GenericInterval.value but I don't know how to do the conversion properly

Comment on lines 5531 to 5532
releaseSubElement = SubElement(mxTechnicalMark, 'release')
releaseSubElement.set('offset', str(articulationMark.release))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

musicxml's definition of offset is very different from music21's and (despite me now being editor of the musicxml spec) we shouldn't use musicxml offsets anywhere in music21 -- these need to be converted according to the current divisionsPerQuarter setting.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should work with d93af6d though I need to write the tests

if mxObj.get('substitution') is not None:
tech.substitution = xmlObjects.yesNoToBoolean(mxObj.get('substitution'))
if tag == 'bend':
tech.bendAlter = interval.Interval(int(mxObj.find('bend-alter').text))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this has too many potentials for crashing the processing. What if there is no bend-alter or no bend-alter.text? check that before typing to assign.

(Better to call out into a separate sub-method. This method was designed just for one-to-two lines per technical

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sub-method and bend-alter check in 2e1ea43

if mxObj.find('pre-bend') is not None:
tech.preBend = True
if mxObj.find('release') is not None:
tech.release = int(mxObj.find('release').get('offset'))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as above -- offset needs to be converted to music21 quarterLengths.

except clause without Try.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both fixed with 58eeb04

tech.release = int(mxObj.find('release').get('offset'))
except TypeError:
# offset is not mandatory
tech.release = 0
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

release is a float. needs to be 0.0

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also fixed with 58eeb04

music21/note.py Outdated
Comment on lines 40 to 43
from music21 import articulations

if t.TYPE_CHECKING:
from music21 import articulations
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as above -- alphabetical and remove from type-checking if imported at top. (but won't be necessary).

music21/note.py Outdated
Comment on lines 1788 to 1789
@property
def string(self):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this new property and all properties below are rejected. Note is the most common object in music21 and users who are not working with guitar music will never use these routines but will need to figure out what they mean in the docs. (we don't have "accent" or "staccato" etc. either) -- and parallel routines would need to be added to Chord, etc.

In general for any mature open-source project, don't make additions or substantive changes to core parts of the system without a prior discussion.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oops sorry about that, they were just for my personal convenience. Removed with 0b2074f

@mscuthbert
Copy link
Member

Hello -- just as a note (from the music21list Google Group) I'm taking a sabbatical from reviewing music21 issues and PRs until at least Jan 1, 2024, so this PR will be deferred until then.

@adhooge
Copy link
Contributor Author

adhooge commented Jul 10, 2023

Hello Michael, sorry for not being able to finish this PR sooner. Enjoy your sabbatical! Hopefully my PR will be ready for approval when you come back 🤞

@adhooge
Copy link
Contributor Author

adhooge commented May 5, 2025

Hello @mscuthbert !
Apologies for the very long delay, I had difficulties finding time for finishing this PR, but I'm hopeful it can be done by the end of the month :)

I think I have addressed all your comments, let me know if there is anything I should improve further!

Best,

@adhooge adhooge marked this pull request as ready for review May 7, 2025 08:32
@adhooge adhooge requested a review from mscuthbert May 12, 2025 07:06
Copy link
Member

@mscuthbert mscuthbert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi adhooge I'm realizing that for some reason you don't have permissions to run the Github Actions here automatically (I think you get them the first time you open a PR that passes)

Make sure that you're running python music21/test/multiprocessTest.py before pushing here -- you have tests that aren't passing -- as soon as I noticed that I stopped reviewing for now.

If you want to open up a dummy PR that changes one letter (like add a period somewhere it's missing) point to this comment and I'll merge it so you have full actions rights. (Or point me to some web resource that tells me how to exempt you from the hold back until you have it).

@adhooge
Copy link
Contributor Author

adhooge commented May 13, 2025

Hi mscuthbert apologies for the missed test, I updated them and also made a dummy PR so that I can run github actions to check linting etc.:
#1776

@coveralls
Copy link

coveralls commented May 13, 2025

Coverage Status

coverage: 93.01% (+0.004%) from 93.006%
when pulling 7e8a800 on adhooge:pr-bend
into 9e84df1 on cuthbertLab:master.

@adhooge
Copy link
Contributor Author

adhooge commented May 14, 2025

It seems I got all the coveted green ticks! There might still be a few changes required. I'm thinking in particular about the fact that I had to import interval and OffsetQL to get the typing tests to pass. They should probably only be imported for type checking? I'll wait for your feedback on that before changing it

Thank you very much for your reactivity and detailed answers mscuthbert, it was very helpful!

Copy link
Member

@mscuthbert mscuthbert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Congrats! Looks great!

@mscuthbert mscuthbert changed the title FretBend update FretBend supports alter (interval), prebend, and release May 14, 2025
@mscuthbert mscuthbert merged commit ed245aa into cuthbertLab:master May 14, 2025
8 checks passed
@mscuthbert
Copy link
Member

This is a really significant contribution for a first PR. Congrats! Hope it was a good enough experience that there will be many more.

I'm planning on doing a release by July 1 or when we get the Piano Pedal PRs in whichever comes first.

@adhooge
Copy link
Contributor Author

adhooge commented May 15, 2025

Thank you very much for your kind help throughout the process (that spanned over several years!!)
It was a great experience and I'm very happy and proud to contribute to this great library :)

I won't hesitate to contribute more in the future!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Improve management of bends

3 participants