def testBasic(self): # deriving a scale from a Stream # just get default, c-minor, as derive will check all tonics sc2 = scale.MinorScale() # we can get a range of pitches # noinspection PyTypeChecker self.assertEqual( self.pitchOut(sc2.getPitches('c2', 'c5')), '[C2, D2, E-2, F2, G2, A-2, B-2, C3, D3, E-3, F3, G3, A-3, B-3, ' + 'C4, D4, E-4, F4, G4, A-4, B-4, C5]') # we can transpose the Scale sc3 = sc2.transpose('-m3') self.assertEqual( self.pitchOut(sc3.getPitches('c2', 'c5')), '[C2, D2, E2, F2, G2, A2, B2, C3, D3, E3, F3, G3, A3, B3, ' + 'C4, D4, E4, F4, G4, A4, B4, C5]') # getting pitches from scale degrees self.assertEqual(str(sc3.pitchFromDegree(3)), 'C4') self.assertEqual(str(sc3.pitchFromDegree(7)), 'G4') self.assertEqual(self.pitchOut(sc3.pitchesFromScaleDegrees([1, 5, 6])), '[A3, E4, F4, A4]') self.assertEqual( self.pitchOut( sc3.pitchesFromScaleDegrees([2, 3], minPitch='c6', maxPitch='c9')), '[C6, B6, C7, B7, C8, B8, C9]') # given a pitch, get the scale degree sc4 = scale.MajorScale('A-') self.assertEqual(sc4.getScaleDegreeFromPitch('a-'), 1) # default is name matching self.assertEqual(sc4.getScaleDegreeFromPitch('g#'), None) # can set pitchClass comparison attribute self.assertEqual( sc4.getScaleDegreeFromPitch('g#', comparisonAttribute='pitchClass'), 1) self.assertEqual( sc4.getScaleDegreeFromPitch('e-', comparisonAttribute='name'), 5) # showing scales # this assumes that the tonic is not the first scale degree sc1 = scale.HypophrygianScale('c4') self.assertEqual(str(sc1.pitchFromDegree(1)), 'G3') self.assertEqual(str(sc1.pitchFromDegree(4)), 'C4') # sc1.show() sc1 = scale.MajorScale() # deriving a new scale from the pitches found in a collection s = corpus.parse('bwv66.6') sc3 = sc1.derive(s.parts['#soprano']) self.assertEqual(str(sc3), '<music21.scale.MajorScale A major>') sc3 = sc1.derive(s.parts['#tenor']) self.assertEqual(str(sc3), '<music21.scale.MajorScale A major>') sc3 = sc2.derive(s.parts['#bass']) self.assertEqual(str(sc3), '<music21.scale.MinorScale F# minor>') # composing with a scale s = stream.Stream() p = 'd#4' # sc = scale.PhrygianScale('e') sc = scale.MajorScale('E4') for d, x in [(Direction.ASCENDING, 1), (Direction.DESCENDING, 2), (Direction.ASCENDING, 3), (Direction.DESCENDING, 4), (Direction.ASCENDING, 3), (Direction.DESCENDING, 2), (Direction.ASCENDING, 1)]: # use duration type instead of quarter length for y in (1, 0.5, 0.5, 0.25, 0.25, 0.25, 0.25): p = sc.nextPitch(p, direction=d, stepSize=x) n = note.Note(p) n.quarterLength = y s.append(n) self.assertEqual( self.pitchOut(s.pitches), '[E4, F#4, G#4, A4, B4, C#5, D#5, B4, G#4, E4, C#4, A3, F#3, D#3, ' + 'G#3, C#4, F#4, B4, E5, A5, D#6, G#5, C#5, F#4, B3, E3, A2, D#2, G#2, ' + 'C#3, F#3, B3, E4, A4, D#5, B4, G#4, E4, C#4, A3, F#3, D#3, E3, F#3, ' + 'G#3, A3, B3, C#4, D#4]') # s.show() # composing with an octatonic scale. s1 = stream.Part() s2 = stream.Part() p1 = 'b4' p2 = 'b3' sc = scale.OctatonicScale('C4') for d, x in [(Direction.ASCENDING, 1), (Direction.DESCENDING, 2), (Direction.ASCENDING, 3), (Direction.DESCENDING, 2), (Direction.ASCENDING, 1)]: for y in (1, 0.5, 0.25, 0.25): p1 = sc.nextPitch(p1, direction=d, stepSize=x) n = note.Note(p1) n.quarterLength = y s1.append(n) if d == Direction.ASCENDING: d = Direction.DESCENDING elif d == Direction.DESCENDING: d = Direction.ASCENDING for y in [1, 0.5, 0.25, 0.25]: p2 = sc.nextPitch(p2, direction=d, stepSize=x) n = note.Note(p2) n.quarterLength = y s2.append(n) s = stream.Score() s.insert(0, s1) s.insert(0, s2) # s.show() # compare two different major scales sc1 = scale.MajorScale('g') sc2 = scale.MajorScale('a') sc3 = scale.MinorScale('f#') # exact comparisons self.assertNotEqual(sc1, sc2) self.assertEqual(sc1.abstract, sc2.abstract) self.assertNotEqual(sc1, sc3) self.assertNotEqual(sc1.abstract, sc3.abstract) # getting details on comparison self.assertEqual( pformat(sc1.match(sc2)), '''{'matched': [<music21.pitch.Pitch A4>, <music21.pitch.Pitch B4>, <music21.pitch.Pitch D5>, <music21.pitch.Pitch E5>, <music21.pitch.Pitch F#5>], 'notMatched': [<music21.pitch.Pitch C#5>, <music21.pitch.Pitch G#5>]}''', pformat(sc1.match(sc2)))
def testScales01(self): from music21 import pitch #==== "fig-py01" # Providing a tonic makes this concrete sc1 = scale.MajorScale('g4') sc2 = scale.MajorScale('e-3') # Comparing Concrete and Abstract Scales assert (sc1 == sc2) == False assert (sc1.abstract == sc2.abstract) == True # Without arguments, getPitches() returns a single span assert common.pitchList( sc1.getPitches()) == '[G4, A4, B4, C5, D5, E5, F#5, G5]' assert common.pitchList(sc2.getPitches( 'c2', 'c3')) == '[C2, D2, E-2, F2, G2, A-2, B-2, C3]' # As a Chord, Scale pitches gain additional functionality assert sc1.getChord().forteClass == '7-35' # Given a degree, get the pitch assert str(sc1.pitchFromDegree(5)) == 'D5' assert common.pitchList( sc2.pitchesFromScaleDegrees([7, 2], 'e-6', 'e-9')) == '[F6, D7, F7, D8, F8, D9]' # Get a scale degree from a pitch assert sc1.getScaleDegreeFromPitch('d') == 5 assert sc2.getScaleDegreeFromPitch('d') == 7 # Get the next pitch given step directions match = [pitch.Pitch('g2')] for direction in [1, 1, 1, -2, 4, -1, 1, 1, 1]: # Append the next pitch based on the last-added pitch match.append(sc1.next(match[-1], direction)) assert common.pitchList( match), '[G2, A2, B2, C3, A2, E3, D3, E3, F#3, G3]' # Derive new scales based on a provided collection or degree assert str(sc1.derive(['c4', 'g4', 'b8', 'f2'])) == '<music21.scale.MajorScale C major>' assert str(sc1.deriveByDegree( 7, 'C#')) == '<music21.scale.MajorScale D major>' # Methods unique to DiatonicScale subclasses assert str( sc2.getRelativeMinor()) == '<music21.scale.MinorScale C minor>' #==== "fig-py01" end #==== "fig-py02" sc1 = scale.PhrygianScale('g4') assert common.pitchList( sc1.getPitches()) == '[G4, A-4, B-4, C5, D5, E-5, F5, G5]' assert str( sc1.getRelativeMajor()) == '<music21.scale.MajorScale E- major>' assert str(sc1.getTonic()), str(sc1.getDominant()) == ('G4', 'D5') sc2 = scale.HypodorianScale('a6') assert common.pitchList(sc2.getPitches( 'e2', 'e3')) == '[E2, F#2, G2, A2, B2, C3, D3, E3]' assert str( sc2.getRelativeMajor()) == '<music21.scale.MajorScale G major>' assert str(sc2.getTonic()), str(sc2.getDominant()) == ('A6', 'C7') #==== "fig-py02" end #==== "fig-py06" # see below #==== "fig-py06" end #==== "fig-py03" #print('\n\nfig-py03') sc1 = scale.HarmonicMinorScale('a3') assert common.pitchList( sc1.getPitches()) == '[A3, B3, C4, D4, E4, F4, G#4, A4]' assert str(sc1.getTonic()), str(sc1.getDominant()) == ('A3', 'E4') s = stream.Stream() for d in [1, 3, 2, 1, 6, 5, 8, 7, 8]: s.append( note.Note(sc1.pitchFromDegree(d, equateTermini=False), type='eighth')) #s.show() #==== "fig-py03" end #==== "fig-py04" import random sc1 = scale.MelodicMinorScale('c4') assert common.pitchList(sc1.getPitches( direction='ascending')) == '[C4, D4, E-4, F4, G4, A4, B4, C5]' assert common.pitchList( sc1.getPitches('c3', 'c5', direction='descending')) == ( '[C5, B-4, A-4, G4, F4, E-4, D4, ' + 'C4, B-3, A-3, G3, F3, E-3, D3, C3]') assert str(sc1.getTonic()), str(sc1.getDominant()) == ('C4', 'G4') s = stream.Stream() p = None for i in range(8): # was 16, but sometimes exceeded scale length. direction = random.choice([-1, 1]) for j in range(2): p = sc1.next(p, direction) s.append(note.Note(p, quarterLength=.25)) #s.show() #==== "fig-py04" end #==== "fig-py05" sc1 = scale.OctatonicScale('e3', 'm2') assert common.pitchList( sc1.getPitches()) == '[E3, F3, G3, A-3, B-3, C-4, D-4, D4, E4]' sc2 = scale.OctatonicScale('e3', 'M2') assert common.pitchList( sc2.getPitches()) == '[E3, F#3, G3, A3, B-3, C4, D-4, E-4, F-4]' part1 = stream.Part() part2 = stream.Part() durPart1 = [1, 1, 0.5, 0.5, 1] durPart2 = [3, 1] degrees = list(range(1, 9)) for unused in range(4): random.shuffle(degrees) random.shuffle(durPart1) random.shuffle(durPart2) i = 0 for dur in durPart1: part1.append( note.Note(sc2.pitchFromDegree(degrees[i]), quarterLength=dur)) i += 1 for dur in durPart2: part2.append( note.Note(sc2.pitchFromDegree(degrees[i], minPitch='c2', maxPitch='c3'), quarterLength=dur)) i += 1 s = stream.Score() s.insert(0, part1) s.insert(0, part2) #s.show() # add notation example; perhaps create tri-chords from scale-completing selections #==== "fig-py05" end #sc = scale.SieveScale('c2', '(-3@2 & 4) | (-3@1 & 4@1) | (3@2 & 4@2) | (-3 & 4@3)') #==== "fig-py07" # add examples sc1 = scale.SieveScale('c4', '3@0|4@0') self.assertEqual(common.pitchList(sc1.getPitches()), '[C4, E-4, E4, F#4, G#4, A4, C5]') sc2 = scale.SieveScale('c4', '5@0|7@0') self.assertEqual( common.pitchList(sc2.getPitches()), '[C4, F4, G4, B-4, D5, E-5, G#5, A5, C#6, E6, F#6, B6]') s = stream.Stream() pColection = sc2.getPitches('c3', 'c7') random.shuffle(pColection) for p in pColection: s.append(note.Note(p, type='16th')) #s.show() #==== "fig-py07" end #==== "fig-py08" sc1 = scale.RagAsawari('g3') self.assertEqual( common.pitchList(sc1.getPitches(direction='ascending')), '[G3, A3, C4, D4, E-4, G4]') self.assertEqual( common.pitchList(sc1.getPitches(direction='descending')), '[G4, F4, E-4, D4, C4, B-3, A3, G3]') sc2 = scale.RagMarwa('g3') assert common.pitchList(sc2.getPitches(direction='ascending') ) == '[G3, A-3, B3, C#4, E4, F#4, E4, G4, A-4]' assert common.pitchList( sc2.getPitches(direction='descending' )) == '[A-4, G4, A-4, F#4, E4, C#4, B3, A-3, G3]' p1 = None s = stream.Stream() for direction in ([1] * 10) + ([-1] * 8) + ([1] * 4) + ([-1] * 3) + ([1] * 4): p1 = sc1.next(p1, direction) s.append(note.Note(p1, quarterLength=.25)) #s.show() p1 = None s = stream.Stream() for direction in ([1] * 10) + ([-1] * 8) + ([1] * 4) + ([-1] * 3) + ([1] * 4): p1 = sc2.next(p1, direction) s.append(note.Note(p1, quarterLength=.25)) #s.show() #==== "fig-py08" end #==== "fig-py09" #import random sc1 = scale.WeightedHexatonicBlues('c3') p = 'c3' s = stream.Stream() for n in range(32): p = sc1.next(p, random.choice([-1, 1])) n = note.Note(p, quarterLength=random.choice([.5, .25, .25])) s.append(n)
def testShowAllTypes(self): ''' show all known types to display tests fromMusic21Object() ''' from music21 import scale from music21 import chord from music21 import duration from music21 import dynamics from music21 import meter from music21 import pitch m = stream.Measure() n = note.Note("D#6") m.repeatAppend(n, 6) m.show() s = stream.Stream() s.repeatAppend(n, 6) s.show() s = stream.Score() s.repeatAppend(n, 6) s.show() s = stream.Score() p = stream.Part() p.repeatAppend(n, 6) p2 = stream.Part() p2.repeatAppend(n, 6) s.insert(0, p) s.insert(0, p2) s.show() #emptyStream s = stream.Stream() s.show() p2.show() n.show() c = chord.Chord(['C3', 'D4', 'E5']) c.show() r = note.Rest() r.show() p = pitch.Pitch() p.show() d = duration.Duration(2.0) d.show() #empty duration! shows blank 4/4 measure, maybe with default rest. d = duration.Duration() d.show() mf = dynamics.Dynamic('mf') mf.show() cm = scale.MajorScale('C') cm.show() o = scale.OctatonicScale("C#4") o.show() ts = meter.TimeSignature('3/4') ts.show()