Skip to content
Merged
Show file tree
Hide file tree
Changes from 56 commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
aae9de0
Ottava transposition fixes.
gregchapman-dev Nov 25, 2022
53ee607
Fix test failures by returning 'unknown' from _treatAtSoundingPitch i…
gregchapman-dev Nov 26, 2022
c4c0c02
Initial implementation of Spanner.fillIntermediateElements. Doesn't …
gregchapman-dev Nov 27, 2022
085cf29
Make sure you append the last element afterward, not during the loop.
gregchapman-dev Nov 27, 2022
a2522a0
Default fill type to Music21Object, Ottava overrides to NotRest. Som…
gregchapman-dev Nov 27, 2022
8fd6ad8
Take a first (crude) shot at filling in Ottavas during MusicXML parse.
gregchapman-dev Nov 27, 2022
d609478
Fix failing test by being careful not to fill too far into the future.
gregchapman-dev Nov 27, 2022
0d4b916
Implement fill appropriately for all spanners.
gregchapman-dev Nov 29, 2022
f2b5c5f
Don't crash if searchStream is the wrong stream, just don't fill the …
gregchapman-dev Nov 29, 2022
1ff1328
Make pylint happy (bare-exception).
gregchapman-dev Nov 29, 2022
45d4d71
Never fill a TremoloSpanner. A few fixes in fillIntermediateSpannedE…
gregchapman-dev Nov 30, 2022
5f40922
Less lint. Also, forgot to mention in previous checkin: stop hiding/…
gregchapman-dev Nov 30, 2022
31c42f0
Only fill Ottavas during MusicXML parse. All other spanners are left…
gregchapman-dev Dec 1, 2022
58ad46a
When transposing, there is now an option to inheritAccidentalDisplay.…
gregchapman-dev Dec 1, 2022
0550262
Oops, missed a couple transpose functions.
gregchapman-dev Dec 1, 2022
34c6d57
More inheritance interface tweaks.
gregchapman-dev Dec 1, 2022
2efa95d
Did mypy just get pickier? Add a couple type hints.
gregchapman-dev Dec 1, 2022
3b4248f
Fix inheritsAccidentalDisplay crash.
gregchapman-dev Dec 1, 2022
4eea546
Missed a few Interval transposePitch routines that needed inheritAcci…
gregchapman-dev Dec 2, 2022
c16dd7d
Fix a place where 'natural' could turn to None, losing all accidental…
gregchapman-dev Dec 2, 2022
bb53483
Merge remote-tracking branch 'origin/master' into gregc/ottavaTranspo…
gregchapman-dev Dec 22, 2022
25f859e
Fix testSpannerAnchor expected results to include 'implicit="no"'.
gregchapman-dev Dec 22, 2022
b94e6eb
mypy fixes.
gregchapman-dev Dec 22, 2022
6ea5ad4
Merge branch 'gregc/spannerAnchor' into gregc/ottavaTransposeFix
gregchapman-dev Dec 31, 2022
c619df1
Make mypy happy again.
gregchapman-dev Dec 31, 2022
55a53c8
Some comment cleanup.
gregchapman-dev Jan 2, 2023
2168e21
Merge branch 'master' into gregc/ottavaTransposeFix
gregchapman-dev Jan 20, 2023
beb9a33
Merge branch 'master' into gregc/ottavaTransposeFix
gregchapman-dev Jan 20, 2023
d0c0d53
Get rid of inheritAccidentalDisplay options, and just fix the bug whe…
gregchapman-dev Jan 20, 2023
ad52399
Clean up accidental display inheritance in Interval._diatonicTranspos…
gregchapman-dev Jan 27, 2023
5b024e8
Make displayStatus inheritance an option in Interval._diatonicTranspo…
gregchapman-dev Jan 27, 2023
c38dedd
Set treatAsKeySignature (which means it's safe to inherit accidental …
gregchapman-dev Jan 27, 2023
d64a7be
Rename fillIntermediateSpannerElements -> fill. Default behavior for…
gregchapman-dev Jan 27, 2023
6ede867
Rework Ottava handling in XmlToM21.py for speed and readability.
gregchapman-dev Jan 27, 2023
0bf2263
Allow Spanner.fill to be called with searchStream=None; use startElem…
gregchapman-dev Jan 27, 2023
9495eb1
Improve Spanner fill algorithm (spanner.py) as well as SpannerAnchor …
gregchapman-dev Jan 28, 2023
7f63e7a
Move stripInnerSpaces to top of test_m21ToXml.py module.
gregchapman-dev Jan 29, 2023
49d3e56
SpannerAnchor fixes: allow duration != 0, implement _reprInternal, im…
gregchapman-dev Jan 29, 2023
e464afa
Add v9 comment (and bump version twice to get past my failed attempt …
gregchapman-dev Jan 29, 2023
6aea4d7
Make toSoundingPitch test a bit more meaningful when s.atSoundingPitc…
gregchapman-dev Jan 29, 2023
908159d
Don't import stream within Stream class. More doc/test tweaks.
gregchapman-dev Jan 29, 2023
75cf322
If necessary jump to end of measure after emitting spanners in a seco…
gregchapman-dev Jan 29, 2023
58cd39d
Add tests for moveForward and moveBackward in m21ToXml.py.
gregchapman-dev Jan 29, 2023
ffc97c3
Added a few tests for Spanner.fill (more to come) and found a bug.
gregchapman-dev Jan 30, 2023
6c95326
Spanner.fill doctest tweaks.
gregchapman-dev Jan 30, 2023
4141a06
Merge branch 'master' into pr/1486
mscuthbert Jan 30, 2023
ed21c88
Merge branch 'master' into gregc/ottavaTransposeFix
mscuthbert Jan 30, 2023
937aec9
More SpannerAnchor tests.
gregchapman-dev Jan 30, 2023
1e9f099
pylint/flake8
gregchapman-dev Jan 30, 2023
4f9d0d2
Get rid of treatAsKeyChange, and instead, in _transposeByInstrument s…
gregchapman-dev Jan 30, 2023
d072f0b
Be pickier in Interval._diatonicTransposeFix when deciding if an Inte…
gregchapman-dev Jan 31, 2023
012a728
pylint
gregchapman-dev Jan 31, 2023
cfa4987
A better fix for unison/octave detection.
gregchapman-dev Jan 31, 2023
6854ce8
Test more code paths in Spanner.fill().
gregchapman-dev Jan 31, 2023
a52bc13
Actually test that accid.displayStatus is maintained across _transpos…
gregchapman-dev Jan 31, 2023
9468436
Some testing of MusicXML import and then tranposition of <octave-shif…
gregchapman-dev Jan 31, 2023
61166b1
More review responses.
gregchapman-dev Feb 3, 2023
986bdda
Don't name the check I need to do; just do the check.
gregchapman-dev Feb 7, 2023
498a2a9
Merge branch 'master' into gregc/ottavaTransposeFix
gregchapman-dev Feb 24, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion music21/_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
'''
from __future__ import annotations

__version__ = '9.0.0a6'
__version__ = '9.0.0a8'


def get_version_tuple(vv):
Expand Down
2 changes: 1 addition & 1 deletion music21/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
<class 'music21.base.Music21Object'>

>>> music21.VERSION_STR
'9.0.0a6'
'9.0.0a8'

Alternatively, after doing a complete import, these classes are available
under the module "base":
Expand Down
3 changes: 3 additions & 0 deletions music21/dynamics.py
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,9 @@ class DynamicWedge(spanner.Spanner):
def __init__(self, *spannedElements, **keywords):
super().__init__(*spannedElements, **keywords)

# from music21 import note
# self.fillElementTypes = [note.GeneralNote]

self.type = None # crescendo or diminuendo
self.placement = 'below' # can above or below, after musicxml
self.spread = 15 # this unit is in tenths
Expand Down
6 changes: 6 additions & 0 deletions music21/expressions.py
Original file line number Diff line number Diff line change
Expand Up @@ -1437,6 +1437,10 @@ class TrillExtension(spanner.Spanner):
# N.B. this extension always includes a trill symbol
def __init__(self, *spannedElements, **keywords):
super().__init__(*spannedElements, **keywords)

# from music21 import note
# self.fillElementTypes = [note.NotRest]

self._placement = None # can above or below or None, after musicxml

def _getPlacement(self):
Expand Down Expand Up @@ -1484,6 +1488,7 @@ class TremoloSpanner(spanner.Spanner):

def __init__(self, *spannedElements, **keywords):
super().__init__(*spannedElements, **keywords)

self.placement = None
self.measured = True
self._numberOfMarks = 3
Expand Down Expand Up @@ -1565,6 +1570,7 @@ def __init__(self,
arpeggioType: str = 'normal',
**keywords):
super().__init__(*spannedElements, **keywords)

if arpeggioType not in ('normal', 'up', 'down', 'non-arpeggio'):
raise ValueError(
'Arpeggio type must be "normal", "up", "down", or "non-arpeggio", '
Expand Down
54 changes: 49 additions & 5 deletions music21/interval.py
Original file line number Diff line number Diff line change
Expand Up @@ -2832,6 +2832,11 @@ class Interval(IntervalBase):
>>> aInterval.semiSimpleName
'P8'

Check if transposition would change pitch class:

>>> aInterval.transpositionChangesPitchClass
False

An interval can also be specified directly:

>>> aInterval = interval.Interval('m3')
Expand All @@ -2850,6 +2855,8 @@ class Interval(IntervalBase):
False
>>> aInterval.isStep
False
>>> aInterval.transpositionChangesPitchClass
True

Some ways of creating half-steps.

Expand Down Expand Up @@ -2956,6 +2963,8 @@ class Interval(IntervalBase):
>>> iInterval = interval.Interval(gPitch, hPitch)
>>> iInterval
<music21.interval.Interval AAAA1>
>>> iInterval.transpositionChangesPitchClass
True

>>> interval.Interval(pitch.Pitch('e##4'), pitch.Pitch('f--5'))
<music21.interval.Interval dddd9>
Expand Down Expand Up @@ -3232,6 +3241,12 @@ def isStep(self) -> bool:
def isSkip(self) -> bool:
return self.diatonic.isSkip

@property
def transpositionChangesPitchClass(self) -> bool:
if self.simpleName == 'P1' and float(self.semitones) == float(int(self.semitones)):
return False
return True

# -------------------------------------
# methods
def isConsonant(self) -> bool:
Expand Down Expand Up @@ -3443,6 +3458,12 @@ def _diatonicTransposePitch(self,
PRIVATE METHOD: Return p even if inPlace is True
'''
# NOTE: this is a performance critical method

inheritAccidentalDisplayStatus: bool = False
if not self.transpositionChangesPitchClass:
# unison and any multiple of octave
inheritAccidentalDisplayStatus = True

if p.octave is None:
useImplicitOctave = True
else:
Expand All @@ -3459,6 +3480,7 @@ def _diatonicTransposePitch(self,
newStep, newOctave = convertDiatonicNumberToStep(newDiatonicNumber)
pitch2.step = newStep
pitch2.octave = newOctave
oldPitch2Accidental = pitch2.accidental
pitch2.accidental = None
# if this is not set to None then terrible things happen
pitch2.microtone = None # type: ignore
Expand Down Expand Up @@ -3487,13 +3509,35 @@ def _diatonicTransposePitch(self,
# pitch2 = pitchAlt
pitch2.ps = pitch2.ps + halfStepsToFix
else:
# cannot import Accidental here.
pitch2.accidental = halfStepsToFix # type:ignore

# inherit accidental display type etc. but not current status
if pitch2.accidental is not None and pitch1.accidental is not None:
pitch2.accidental.inheritDisplay(pitch1.accidental)
pitch2.accidental.displayStatus = None # set accidental display to None
if not inheritAccidentalDisplayStatus:
# inherit accidental display type etc. but not current status
if pitch2.accidental is not None and pitch1.accidental is not None:
pitch2.accidental.inheritDisplay(pitch1.accidental)
pitch2.accidental.displayStatus = None # set accidental display to None
else:
# inherit all accidental display options (including status)
if pitch2.accidental is None:
if pitch1.accidental is not None:
pitch2.accidental = 0 # type:ignore
if t.TYPE_CHECKING:
assert pitch2.accidental is not None
pitch2.accidental.inheritDisplay(pitch1.accidental)
else:
if pitch1.accidental is not None:
pitch2.accidental.inheritDisplay(pitch1.accidental)
else:
pitch2.accidental.displayStatus = False

else:
# no halfStepsToFix, so pitch2 is fine as is, but...
if inheritAccidentalDisplayStatus:
# We have set pitch2.accidental to None, so we might have lost some
# display options. So we restore oldPitch2Accidental if that makes sense.
if (oldPitch2Accidental is not None
and oldPitch2Accidental.name == 'natural'):
pitch2.accidental = oldPitch2Accidental

if useImplicitOctave is True:
pitch2.octave = None
Expand Down
8 changes: 3 additions & 5 deletions music21/musicxml/m21ToXml.py
Original file line number Diff line number Diff line change
Expand Up @@ -1517,9 +1517,8 @@ def parse(self):
if not s:
return self.emptyObject()

if s.atSoundingPitch is True:
# A copy was already made or elected NOT to be made.
s.toWrittenPitch(inPlace=True)
# A copy was already made or elected NOT to be made.
s.toWrittenPitch(inPlace=True, ottavasToSounding=True)

self.scorePreliminaries()

Expand Down Expand Up @@ -2730,8 +2729,7 @@ def parse(self):
# unless makeNotation=False, but the user
# should have called toWrittenPitch() first
# and is explicitly asking for no further copies to be made
if self.stream.atSoundingPitch is True:
self.stream.toWrittenPitch(inPlace=True)
self.stream.toWrittenPitch(inPlace=True, ottavasToSounding=True)

# Suppose that everything below this is a measure
if self.makeNotation:
Expand Down
Loading