Search code examples
pythonmidimusic21

Getting parts from a kern score with music21 (python) - why doesn't it find the parts?


I have parsed a collection of krn files with music21 and they all consist of a number of parts. I want to remix the parts and save them as a different file.

However, for a few of the kern files music21 says that is has 0 parts:

>>> s = converter.parse('./data/Benedictus_23.krn')
>>> print len(s.parts)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Opus' object has no attribute 'parts'   -> this really strange
>>> print len(s.voices)
0

The file does have different bars/instruments. How could I seperate/identify them? It doesn't seem to have voices either.

Here is an example header (full file)

!!!COM: Palestrina, Giovanni Perluigi da
!!!OPR: Fratres Ego Enim Accepi
!!!OTL: Benedictus
**kern    **kern    **kern    **kern
*Itenor    *Icalto    *Icalto    *Icant
!Tenor    !Altus 2    !Altus 1    !Cantus
*clefGv2    *clefG2    *clefG2    *clefG2
*k[b-]    *k[b-]    *k[b-]    *k[b-]
*G:dor    *G:dor    *G:dor    *G:dor
*M4/2    *M4/2    *M4/2    *M4/2
=1    =1    =1    =1
0r    0a    0r    0r
=2    =2    =2    =2

Other krn files with for instance this header do work:

!!!COM: Palestrina, Giovanni Perluigi da
!!!OPR: Dum esset summus pontifex
!!!OTL: Gloria
**kern    **kern    **kern    **kern
*Ibass    *Itenor    *Icalto    *Icant
!Bassus    !Tenor    !Altus    !Cantus
*clefF4    *clefGv2    *clefG2    *clefG2
*k[]    *k[]    *k[]    *k[]
*A:aeo    *A:aeo    *A:aeo    *A:aeo
*M4/2    *M4/2    *M4/2    *M4/2
=1    =1    =1    =1
1.A    1.c#    1.e    1.a

Any idea on how to seperate the instruments? Or properly read in the parts?


Solution

  • Apparantly the pieces consists of multiple opusses.

    You can get the different streams t like this:

    s = converter.parse('./data/Benedictus_23.krn')
     try:
        numscores = len(s.scores)
     except:
        numscores = 0
        #for each opus
        if numscores > 0:
          for score in range(0,numscores):
        sys.stdout.write('\n -> opus ' + str(score))
            t = s.scores[score]
            print len(t.parts)