Exemplo n.º 1
0
    def testAbc21DirectiveCarryPitch(self):
        from music21 import abcFormat
        from music21 import note
        from music21.abcFormat import translate

        af = abcFormat.ABCFile()
        ah = af.readstr(directiveCarryPitch)
        s = translate.abcToStreamScore(ah)
        notes = s.flatten().getElementsByClass(note.Note)
        gSharp = notes[1]
        g8va = notes[3]
        self.assertEqual(gSharp.pitch.midi % 12, g8va.pitch.midi % 12,
                         'Sharp does not carry through measure')
        aFlat = notes[2]
        a = notes[4]
        self.assertEqual(aFlat.pitch.midi, a.pitch.midi,
                         'Flat does not carry through measure')
        fNat = notes[5]
        f = notes[6]
        f8ba = notes[7]
        self.assertEqual(fNat.pitch.midi, f.pitch.midi,
                         'Natural does not carry through measure')
        self.assertEqual(fNat.pitch.midi % 12, f8ba.pitch.midi % 12,
                         'Natural does not carry through measure')
        self.assertEqual(notes[8].pitch.midi, 65, 'Natural is ignored')
        self.assertEqual(notes[12].pitch.midi, 72, 'Natural is ignored')
Exemplo n.º 2
0
    def testAbc21(self):
        from music21 import abcFormat, note
        from music21.abcFormat import translate

        af = abcFormat.ABCFile(abcVersion=(2,1,0))
        ah = af.readstr(carryThrough)
        title = ah.getTitle()
        environLocal.printDebug([title])
        s = translate.abcToStreamScore(ah)
        notes = s.flat.getElementsByClass(note.Note)
        cSharp = notes[3]
        cThrough = notes[5]
        self.assertEqual(cSharp.pitch.midi, cThrough.pitch.midi, 'Sharp does not carry through measure')
        bFlat = notes[4]
        bLast = notes[7]
        self.assertEqual(bFlat.pitch.midi, bLast.pitch.midi, 'Flat does not carry through measure')
        bNat = notes[10]
        bNatNext = notes[11]
        self.assertEqual(bNat.pitch.midi, bNatNext.pitch.midi, 'Natural does not carry through measure')
        self.assertEqual(notes[12].pitch.midi, 73, 'Sharp does not carry through measure')
        self.assertEqual(notes[13].pitch.midi, 72, 'Natural is ignored')
        self.assertEqual(notes[14].pitch.midi, 72, 'Natural does not carry through measure')
        self.assertEqual(notes[16].pitch.midi, 72, 'Sharp carries over measure incorrectly')
        self.assertEqual(notes[17].pitch.midi, 74, 'Sharp (D5) carries over measure incorrectly')
        self.assertEqual(notes[18].pitch.midi, 78, 'Natural (F5) carries over measure incorrectly')
Exemplo n.º 3
0
    def testBasic(self):
        from music21 import abcFormat
        from music21.abcFormat import translate
        from music21.musicxml import m21ToXml

        af = abcFormat.ABCFile()

        GEX = m21ToXml.GeneralObjectExporter()

        for i, tf in enumerate(ALL):
            ah = af.readstr(tf)
            title = ah.getTitle()
            environLocal.printDebug([title])
            s = translate.abcToStreamScore(ah)
            # run musicxml processing to look for internal errors
            #print(repr(s.metadata._workIds['localeOfComposition']._data))
            #print(s.metadata.all())
            try:
                unused_out = GEX.parse(s)
            except UnicodeDecodeError as ude:
                environLocal.warn('About to fail on ABC file #{}'.format(i))
                raise ude

            if title == 'D Fragment':
                sharps = s.parts[0].keySignature.sharps
                self.assertEqual(
                    sharps, 7, 'C# key signature should be parsed as 7 sharps')
Exemplo n.º 4
0
    def testAbc21DirectiveCarryNot(self):
        from music21 import abcFormat, note
        from music21.abcFormat import translate

        af = abcFormat.ABCFile()
        ah = af.readstr(directiveCarryNot)
        s = translate.abcToStreamScore(ah)
        notes = s.flat.getElementsByClass(note.Note)
        gSharp = notes[1]
        g8va = notes[3]
        self.assertGreater(gSharp.pitch.midi % 12, g8va.pitch.midi % 12,
                           'Sharp carries beyond its octave')
        aFlat = notes[2]
        a = notes[4]
        self.assertLess(aFlat.pitch.midi, a.pitch.midi,
                        'Flat carries through measure')
        fNat = notes[5]
        f = notes[6]
        f8ba = notes[7]
        self.assertLess(fNat.pitch.midi, f.pitch.midi,
                        'Natural carries through measure')
        self.assertLess(fNat.pitch.midi % 12, f8ba.pitch.midi % 12,
                        'Natural carries beyond its octave')
        self.assertEqual(notes[8].pitch.midi, 65, 'Natural is ignored')
        self.assertEqual(notes[12].pitch.midi, 72, 'Natural is ignored')
Exemplo n.º 5
0
    def parseFile(self, fp, number=None):
        '''
        Get ABC data from a file path. If more than one work is defined in the ABC 
        data, a  :class:`~music21.stream.Opus` object will be returned; 
        otherwise, a :class:`~music21.stream.Score` is returned.

        If `number` is provided, and this ABC file defines multiple works 
        with a X: tag, just the specified work will be returned.
        '''
        #environLocal.printDebug(['ConverterABC.parseFile: got number', number])
        from music21 import abcFormat

        af = abcFormat.ABCFile()
        af.open(fp)
        # returns a handler instance of parse tokens
        abcHandler = af.read(number=number)
        af.close()

        # only create opus if multiple ref numbers
        # are defined; if a number is given an opus will no be created
        if abcHandler.definesReferenceNumbers():
            # this creates a Score or Opus object, depending on if a number
            # is given
            self.stream = abcFormat.translate.abcToStreamOpus(abcHandler,
                                                              number=number)
        # just get a single work
        else:
            abcFormat.translate.abcToStreamScore(abcHandler, self.stream)
Exemplo n.º 6
0
    def testAbc21DirectiveCarryOctave(self):
        from music21 import abcFormat, note
        from music21.abcFormat import translate

        af = abcFormat.ABCFile()
        ah = af.readstr(directiveCarryOctave)
        s = translate.abcToStreamScore(ah)
        notes = s.flat.getElementsByClass(note.Note)
        gSharp = notes[1]
        g8va = notes[3]
        self.assertTrue(gSharp.pitch.midi % 12 > g8va.pitch.midi % 12,
                        "Sharp carries beyond its octave")
        aFlat = notes[2]
        a = notes[4]
        self.assertEqual(aFlat.pitch.midi, a.pitch.midi,
                         "Flat does not carry through measure")
        fNat = notes[5]
        f = notes[6]
        f8ba = notes[7]
        self.assertEqual(fNat.pitch.midi, f.pitch.midi,
                         "Natural does not carry through measure")
        self.assertTrue(fNat.pitch.midi % 12 < f8ba.pitch.midi % 12,
                        "Natural carries beyond its octave")
        self.assertEqual(notes[8].pitch.midi, 65, "Natural is ignored")
        self.assertEqual(notes[12].pitch.midi, 72, "Natural is ignored")
Exemplo n.º 7
0
    def testGetMetaData(self):
        '''
        NB -- only title is checked. not meter or key
        '''

        from music21 import abcFormat
        from music21.abcFormat import testFiles

        for (tf, titleEncoded, unused_meterEncoded, unused_keyEncoded) in [
            (testFiles.fyrareprisarn, 'Fyrareprisarn', '3/4', 'F'),
            (testFiles.mysteryReel, 'Mystery Reel', 'C|', 'G'),
            (
                testFiles.aleIsDear,
                'The Ale is Dear',
                '4/4',
                'D',
            ),
            (testFiles.kitchGirl, 'Kitchen Girl', '4/4', 'D'),
            (testFiles.williamAndNancy, 'William and Nancy', '6/8', 'G'),
        ]:

            af = abcFormat.ABCFile()
            ah = af.readstr(tf)  # returns an ABCHandler object
            s = abcToStreamScore(ah)

            self.assertEqual(s.metadata.title, titleEncoded)
Exemplo n.º 8
0
    def testChords(self):

        from music21 import abcFormat
        from music21.abcFormat import testFiles

        tf = testFiles.aleIsDear
        af = abcFormat.ABCFile()
        s = abcToStreamScore(af.readstr(tf))
        #s.show()
        self.assertEqual(len(s.parts), 2)
        self.assertEqual(len(s.parts[0].flat.notesAndRests), 111)
        self.assertEqual(len(s.parts[1].flat.notesAndRests), 127)

        # chords are defined in second part here
        self.assertEqual(len(s.parts[1].flat.getElementsByClass('Chord')), 32)

        # check pitches in chords; sharps are applied due to key signature
        match = [
            p.nameWithOctave
            for p in s.parts[1].flat.getElementsByClass('Chord')[4].pitches
        ]
        self.assertEqual(match, ['F#4', 'D4', 'B3'])

        match = [
            p.nameWithOctave
            for p in s.parts[1].flat.getElementsByClass('Chord')[3].pitches
        ]
        self.assertEqual(match, ['E4', 'C#4', 'A3'])
Exemplo n.º 9
0
    def testTuplets(self):

        from music21 import abcFormat
        from music21.abcFormat import testFiles

        tf = testFiles.testPrimitiveTuplet
        af = abcFormat.ABCFile()
        s = abcToStreamScore(af.readstr(tf))
        match = []
        # match strings for better comparison
        for n in s.flat.notesAndRests:
            match.append(str(n.quarterLength))
        self.assertEqual(match, [
            '0.333333333333',
            '0.333333333333', '0.333333333333', '0.2', '0.2', '0.2', '0.2',
            '0.2', '0.166666666667', '0.166666666667', '0.166666666667',
            '0.166666666667', '0.166666666667', '0.166666666667',
            '0.142857142857', '0.142857142857', '0.142857142857',
            '0.142857142857', '0.142857142857', '0.142857142857',
            '0.142857142857', '0.666666666667', '0.666666666667',
            '0.666666666667', '0.666666666667', '0.666666666667',
            '0.666666666667', '0.0833333333333', '0.0833333333333',
            '0.0833333333333', '0.0833333333333', '0.0833333333333',
            '0.0833333333333', '0.0833333333333', '0.0833333333333',
            '0.0833333333333', '0.0833333333333', '0.0833333333333',
            '0.0833333333333', '2.0',
            ])
Exemplo n.º 10
0
    def testBasic(self):
        from music21 import abcFormat
        #from music21.abcFormat import testFiles

        for tf in [
                #             testFiles.fyrareprisarn,
                #             testFiles.mysteryReel,
                #             testFiles.aleIsDear,
                #             testFiles.testPrimitive,
                #            testFiles.fullRiggedShip,
                #            testFiles.kitchGirl,
                #testFiles.morrisonsJig,
                #            testFiles.hectorTheHero,
                #             testFiles.williamAndNancy,
                #            testFiles.theAleWifesDaughter,
                #            testFiles.theBeggerBoy,
                #            testFiles.theAleWifesDaughter,
                #            testFiles.draughtOfAle,

                #            testFiles.testPrimitiveTuplet,
                #            testFiles.testPrimitivePolyphonic,
        ]:
            af = abcFormat.ABCFile()
            ah = af.readstr(tf)  # return handler, processes tokens
            s = abcToStreamScore(ah)
            s.show()
Exemplo n.º 11
0
 def testKeySignatures(self):
     from music21 import abcFormat
     from music21.abcFormat import translate
     af = abcFormat.ABCFile()
     ah = af.readstr(czernyCsharp)
     s = translate.abcToStreamScore(ah)
     sharps = s.parts[0].keySignature.sharps
     self.assertEqual(sharps, 7, 'C# key signature should be parsed as 7 sharps')
Exemplo n.º 12
0
    def testAbc21BrokenRhythm(self):
        # Test the chord symbol for note and chord
        from music21 import abcFormat
        from music21 import note
        from music21.abcFormat import translate

        # default length of this test
        abc_dl = 'L:1/4\n'

        # test abc strings of broken rhythm between 2 notes and/or chords and their
        # quarter lengths at the default length of 1/4
        # list[tuple(abc: str, value1: int, value2: int)]
        data = [
            ('[ceg]<f', 0.5, 1.5),
            ('f<[ceg]', 0.5, 1.5),
            ('c>g', 1.5, 0.5),
            ('c<g', 0.5, 1.5),
            ('c>>=g', 1.75, 0.25),
            ('c<<g', 0.25, 1.75),
            ('c>>>g', 1.875, 0.125),
            ('c<<<_g', 0.125, 1.875),
            ("[ceg]>^f", 1.5, 0.5),
            ('[ce^g]>>f', 1.75, 0.25),
            ("[ceg]<<f", 0.25, 1.75),
            ('[ceg]>>>f', 1.875, 0.125),
            ("[ceg]<<<f", 0.125, 1.875),
            ('f>[ceg]', 1.5, 0.5),
            ('f>>[_ceg]', 1.75, 0.25),
            ("f'<<[ceg]", 0.25, 1.75),
            ('f,>>>[ceg]', 1.875, 0.125),
            ('f<<<[ce_g]', 0.125, 1.875),
            ('f<<<[ceg]', 0.125, 1.875),
            ('f2>[ceg]', 3, 0.5),
            ('[ceg]>f2', 1.5, 1),
            ('f>[c_eg]2', 1.5, 1),
            ('[c^eg]2>f', 3, 0.5),
            ('f2<[ceg]', 1.0, 1.5),
            ('[ceg]<f2', 0.5, 3),
            ('f<[ceg]2', 0.5, 3),
            ('[ceg]2<f', 1.0, 1.5),
        ]

        af = abcFormat.ABCFile()
        for abc, soll_left, soll_right in data:
            ah = af.readstr(abc_dl + abc)
            part = translate.abcToStreamScore(ah).parts[0]
            general_notes = part.getElementsByClass(note.GeneralNote)
            self.assertEqual(len(general_notes), 2,
                             f'Wrong numbers of Notes found in abc: {abc}!')
            ist_left, ist_right = general_notes
            self.assertEqual(
                ist_left.duration.quarterLength, soll_left,
                f'Invalid left note/chord length of abc broken rhythm: {abc}')
            self.assertEqual(
                ist_right.duration.quarterLength, soll_right,
                f'Invalid right note/chord length of abc broken rhythm: {abc}')
Exemplo n.º 13
0
    def testLyrics(self):
        # TODO

        from music21 import abcFormat
        from music21.abcFormat import testFiles

        tf = testFiles.sicutRosa
        af = abcFormat.ABCFile()
        s = abcToStreamScore(af.readstr(tf))
        assert s is not None
Exemplo n.º 14
0
    def testBasic(self):
        from music21 import abcFormat
        from music21.abcFormat import translate
        from music21.musicxml import m21ToString

        af = abcFormat.ABCFile()

        for tf in ALL:
            ah = af.readstr(tf)
            environLocal.printDebug([ah.getTitle()])
            s = translate.abcToStreamScore(ah)
            # run musicxml processing to look for internal errors
            unused_out = m21ToString.fromMusic21Object(s)
Exemplo n.º 15
0
    def testAbc21Chords(self):
        '''
        Translation of ABC Chord variations
        '''
        from music21 import abcFormat
        from music21 import chord
        from music21.abcFormat import translate

        af = abcFormat.ABCFile()
        # default length of this test
        abc_dl = 'L:1/8\n'

        # Empty Chords should be skipped at all
        for abc_chord in ['[]', '[z]']:
            ah = af.readstr(abc_dl + '[]')
            s = translate.abcToStreamScore(ah)
            part = s.parts[0]
            self.assertFalse(part.getElementsByClass(chord.Chord),
                             f'Empty chord "{abc_chord}" in Score')

        # list of test abc chords and their quarter lengths at the default length of 1/8
        # list[tuple(str, int)] = of abc chords and= [( abc_chord: str)]
        abc_chords = [
            ('[c_eg]', 0.5, ['C', 'E-', 'G']),
            ('[ceg]', 0.5, 'CEG'),
            ('[ceg]2', 1.0, 'CEG'),
            ('[c2e2^g2]', 1.0, ['C', 'E', 'G#']),
            ("[c'e2g]", 0.5, 'CEG'),
            ('[ce^g2]', 0.5, ['C', 'E', 'G#']),
            ('[c,2e2g2]/2', 0.5, 'CEG'),
            ("[c/2e'/2=g/2]", 0.25, 'CEG'),
            ('[c2_e,,/2g/2]/2', 0.5, ['C', 'E-', 'G']),
            ('[c/2e/2g/2]2', 0.5, 'CEG'),
            ('[^c/2e/2g/2]/2', 0.125, ['C#', 'E', 'G']),
            ('[ceg]', 0.5, 'CEG'),
        ]

        for abc_chord, quarter_length, chord_pitches in abc_chords:
            ah = af.readstr(abc_dl + abc_chord)
            s = translate.abcToStreamScore(ah)
            self.assertEqual(s.duration.quarterLength, quarter_length,
                             f'invalid duration of chord "{abc_chord}"')

            notes = s.parts[0].notes
            chord0 = notes[0]
            self.assertEqual(len(notes), 1, 'Wrong number of chords found,')
            self.assertIsInstance(chord0, chord.Chord, 'Not a Chord!')
            for pitch_name in chord_pitches:
                self.assertIn(pitch_name, chord0.pitchNames,
                              f'Pitch not in Chord "{abc_chord}"')
Exemplo n.º 16
0
    def testMultiVoice(self):

        from music21 import abcFormat
        from music21.abcFormat import testFiles

        tf = testFiles.testPrimitivePolyphonic

        af = abcFormat.ABCFile()
        s = abcToStreamScore(af.readstr(tf))

        self.assertEqual(len(s.parts), 3)
        # must flatten b/c  there are measures
        self.assertEqual(len(s.parts[0].flat.notesAndRests), 6)
        self.assertEqual(len(s.parts[1].flat.notesAndRests), 17)
        self.assertEqual(len(s.parts[2].flat.notesAndRests), 6)
Exemplo n.º 17
0
    def testOpusImport(self):
        from music21 import corpus
        from music21 import abcFormat

        # replace w/ ballad80, smaller or erk5
        fp = corpus.getWork('essenFolksong/teste')
        self.assertTrue(fp.endswith('essenFolksong/teste.abc') or fp.endswith(r'essenFolksong\teste.abc'))

        af = abcFormat.ABCFile()
        af.open(fp) # return handler, processes tokens
        ah = af.read()
        af.close()

        op = abcToStreamOpus(ah)
        #op.scores[3].show()
        self.assertEqual(len(op), 8)
Exemplo n.º 18
0
 def parseData(self, strData, number=None):
     '''
     Get ABC data, as token list, from a string representation.
     If more than one work is defined in the ABC data, a
     :class:`~music21.stream.Opus` object will be returned;
     otherwise, a :class:`~music21.stream.Score` is returned.
     '''
     from music21 import abcFormat
     af = abcFormat.ABCFile()
     # do not need to call open or close
     abcHandler = af.readstr(strData, number=number)
     # set to stream
     if abcHandler.definesReferenceNumbers():
         # this creates an Opus object, not a Score object
         self.stream = abcFormat.translate.abcToStreamOpus(abcHandler,
                                                           number=number)
     else:  # just one work
         abcFormat.translate.abcToStreamScore(abcHandler, self.stream)
Exemplo n.º 19
0
    def testAbc21ChordSymbol(self):
        # Test the chord symbol for note and chord
        from music21 import abcFormat, harmony
        from music21.abcFormat import translate

        # default length of this test
        abc_dl = 'L:1/8\n'

        af = abcFormat.ABCFile()
        for abc_text in ('"C"C', '"C"[ceg]'):
            ah = af.readstr(abc_dl + abc_text)
            part = translate.abcToStreamScore(ah).parts[0]
            chord_symbol = part.getElementsByClass(harmony.ChordSymbol)
            self.assertTrue(chord_symbol,
                            'No ChordSymbol found in abc: "%s"' % abc_text)
            for pitch_name in 'CEG':
                self.assertIn(
                    pitch_name, chord_symbol[0].pitchNames,
                    'Pitch not in ChordSymbol of abc: "%s"' % abc_text)
    def testTuplets(self):

        from music21 import abcFormat
        from music21.abcFormat import testFiles

        tf = testFiles.testPrimitiveTuplet
        af = abcFormat.ABCFile()
        s = abcToStreamScore(af.readstr(tf))
        match = []
        # match strings for better comparison
        for n in s.flat.notesAndRests:
            match.append(n.quarterLength)
        shouldFind = [
            1 / 3, 1 / 3, 1 / 3, 1 / 5, 1 / 5, 1 / 5, 1 / 5, 1 / 5, 1 / 6,
            1 / 6, 1 / 6, 1 / 6, 1 / 6, 1 / 6, 1 / 7, 1 / 7, 1 / 7, 1 / 7,
            1 / 7, 1 / 7, 1 / 7, 2 / 3, 2 / 3, 2 / 3, 2 / 3, 2 / 3, 2 / 3,
            1 / 12, 1 / 12, 1 / 12, 1 / 12, 1 / 12, 1 / 12, 1 / 12, 1 / 12,
            1 / 12, 1 / 12, 1 / 12, 1 / 12, 2
        ]
        self.assertEqual(match, [common.opFrac(x) for x in shouldFind])
Exemplo n.º 21
0
    def testBasic(self):
        from music21 import abcFormat
        from music21.abcFormat import translate
        from music21.musicxml import m21ToXml

        af = abcFormat.ABCFile()

        GEX = m21ToXml.GeneralObjectExporter()
        
        for i, tf in enumerate(ALL):
            ah = af.readstr(tf)
            environLocal.printDebug([ah.getTitle()])
            s = translate.abcToStreamScore(ah)
            # run musicxml processing to look for internal errors
            #print(repr(s.metadata._workIds['localeOfComposition']._data))
            #print(s.metadata.all())
            try:
                unused_out = GEX.parse(s)
            except UnicodeDecodeError as ude:
                environLocal.warn("About to fail on ABC file #{}".format(i))
                raise ude
Exemplo n.º 22
0
    def append(self, corpus_path=None, corpus_str=None, d_score=None, header_path=None,
               header_str=None, as_xml=True, title=None):
        corpus_type = None

        if corpus_path:
            corpus_type = DCorpus.corpus_type(corpus_path=corpus_path)
            if corpus_type in [Constant.CORPUS_ABC, Constant.CORPUS_ABCD]:
                corpus_str = DCorpus.file_to_string(corpus_path)

        if header_path:
            header_str = DCorpus.file_to_string(header_path)

        abcd_header = None
        abc_body = ''

        if corpus_type == Constant.CORPUS_MIDI:
            score = converter.parseFile(corpus_path)
            score_title = title
            if score_title is None:
                score_title = os.path.basename(corpus_path)
                score_title = score_title.split(sep='.')[0]
            da_score = DScore(music21_stream=score, segmenter=self.segmenter(),
                              abcd_header=abcd_header, title=score_title)
            self._d_scores.append(da_score)

        if d_score:
            self._d_scores.append(d_score)

        abc_handle = None
        staff_assignments = []

        if corpus_str:
            corpus_type = DCorpus.corpus_type(corpus_str=corpus_str)
            if corpus_type == Constant.CORPUS_ABCD and not header_str:
                header_str = corpus_str
            if header_str:
                abcd_header = DCorpus.abcd_header(string=header_str)

            if corpus_type in [Constant.CORPUS_ABC, Constant.CORPUS_ABCD]:
                abc_body = DCorpus.abc_body_str(string=corpus_str)

            if as_xml:
                corpus_str = DCorpus.abc2xml(abc_content=corpus_str)
                corpus_type = DCorpus.corpus_type(corpus_str=corpus_str)

            if corpus_type in [Constant.CORPUS_ABC, Constant.CORPUS_ABCD]:
                # NOTE: We only do this if we are not using the XML transform.
                # THIS IS NOT RECOMMENDED.
                # The abc conversion does not manage the grouping of voices into
                # the appropriate part (staff), so we hack around this shortcoming.
                self._abc_strings.append(corpus_str)
                abc_file = abcFormat.ABCFile(abcVersion=(2, 1, 0))
                staff_assignments = DCorpus._score_staff_assignments(abc_content=corpus_str)
                abc_handle = abc_file.readstr(corpus_str)
            else:
                # THIS IS WHERE WE SHOULD BE.
                corp = converter.parse(corpus_str)
                if isinstance(corp, stream.Opus):
                    for score in corp:
                        da_score = DScore(music21_stream=score, segmenter=self.segmenter())
                        self._d_scores.append(da_score)
                else:
                    score = corp
                    da_score = DScore(music21_stream=score, segmenter=self.segmenter(),
                                      abcd_header=abcd_header, abc_body=abc_body)
                    self._d_scores.append(da_score)
        else:
            return False

        if corpus_type in [Constant.CORPUS_ABC, Constant.CORPUS_ABCD]:
            # WARNING: abc parsing is NOT recommended
            ah_for_id = abc_handle.splitByReferenceNumber()
            if len(staff_assignments) > 0 and len(staff_assignments) != len(ah_for_id):
                # We must know how to map all voices to a staff. Either all scores (tunes)
                # in corpus must have two or fewer voices, or we need a map. For simplicity,
                # we make this an all-or-nothing proposition. If any score in the corpus
                # needs a map, they all must provide one. For two voices, this would
                # look like this:
                #
                #    %%score { ( 1 ) | ( 2 ) }
                raise Exception("All abc scores in corpus must have %%score staff assignments or none should.")

            score_index = 0
            for score_id in ah_for_id:
                if len(staff_assignments) > 0:
                    da_score = DScore(abc_handle=ah_for_id[score_id], abcd_header=abcd_header, abc_body=abc_body,
                                      voice_map=staff_assignments[score_index], segmenter=self.segmenter())
                else:
                    da_score = DScore(abc_handle=ah_for_id[score_id], abcd_header=abcd_header, abc_body=abc_body,
                                      segmenter=self.segmenter())
                self._d_scores.append(da_score)
                score_index += 1