diff --git a/music21/scale/__init__.py b/music21/scale/__init__.py index ebb66478e..9dc898f0f 100644 --- a/music21/scale/__init__.py +++ b/music21/scale/__init__.py @@ -6,7 +6,7 @@ # Michael Scott Asato Cuthbert # Jose Cabal-Ugaz # -# Copyright: Copyright © 2009-2011 Michael Scott Asato Cuthbert +# Copyright: Copyright © 2009-2026 Michael Scott Asato Cuthbert # License: BSD, see license.txt # ------------------------------------------------------------------------------ ''' @@ -1005,10 +1005,6 @@ def __init__(self, mode: t.Any = None, **keywords) -> None: mode = ['P8'] self.buildNetwork(mode=mode) - # by definition, these are forced to be octave duplicating - # though, do to some intervals, duplication may not happen every oct - self.octaveDuplicating = True - def buildNetwork(self, mode: t.Any = None) -> None: ''' Here, mode is the list of intervals. @@ -1022,6 +1018,11 @@ def buildNetwork(self, mode: t.Any = None) -> None: if iComplement is not None: mode.append(iComplement) + # steps wider than an octave complete a pattern spanning several + # octaves, which does not repeat every octave + span = intervalSum.semitones + (iComplement.semitones if iComplement else 0) + self.octaveDuplicating = span == 12 + self.tonicDegree = 1 self._net = intervalNetwork.IntervalNetwork(mode, octaveDuplicating=self.octaveDuplicating) diff --git a/music21/scale/test_scale_main.py b/music21/scale/test_scale_main.py index ded1bd6d9..1ccf36487 100644 --- a/music21/scale/test_scale_main.py +++ b/music21/scale/test_scale_main.py @@ -5,7 +5,7 @@ # Authors: Christopher Ariza # Michael Scott Asato Cuthbert # -# Copyright: Copyright © 2010-2024 Michael Scott Asato Cuthbert +# Copyright: Copyright © 2010-2026 Michael Scott Asato Cuthbert # License: BSD, see license.txt # ------------------------------------------------------------------------------ from __future__ import annotations @@ -233,6 +233,11 @@ def testBasic(self): ], 'notMatched': [, ]}''', pformat(sc1.match(sc2))) + def testOctaveRepeatingScaleWiderThanAnOctave(self): + sc = scale.OctaveRepeatingScale('c4', ['P5', 'P5']) + self.assertEqual(self.pitchOut(sc.pitches), '[C4, G4, D5, C6]') + self.assertEqual(self.pitchOut(sc.getPitches('c3', 'c6')), '[D3, C4, G4, D5, C6]') + def testCyclicalScales(self): sc = scale.CyclicalScale('c4', ['m2', 'm2'])