FMP AudioLabs
C1

Symbolic Format: Rendering


In this notebook, we discuss some software tools for rendering sheet music. Furthermore, we explain some functionality of the Python library music21.

Important Note: To keep the notebook executable without additional software dependencies, we provide all code cells as comments. To indicate the code cells' output (given a proper installation of the dependencies), we include static images.

Extra Software

The process of sheet music rendering refers to the computerized rendition of a symbolic music format into graphical musical symbols, e.g. modern staff notation. There exist several software tools for sheet music rendering, including text-based programs like LilyPond and Verovio, as well as WYSIWYG sheet music editors like MuseScore and Sibelius.

For rendering sheet music from Python, we recommend to use the package music21. For a full introduction, we refer to the documentation of music21. It offers various options to feed its internal data structure to a renderer. One option is to internally convert music21's data structure to the MusicXML format (for more details, see the MusicXML notebook) and use MuseScore to graphically render the sheet music. With a working Python environment where music21 is installed, three more steps are needed to get it to work.

  • First, one needs to install MuseScore, which can be downloaded freely on its website. Second, one needs to tell music21 the path to the MuseScore binary.
  • Second, we have to set up a music21 user environment file.
  • Third, we have to register the path to MuseScore for music21.

Those three steps only need to be executed one time.

The following code cell sets up a music21 user environment file:

In [1]:
import os
import music21 as m21

us = m21.environment.UserSettings()
us_path = us.getSettingsPath()
if not os.path.exists(us_path):
    us.create()
print('Path to music21 environment', us_path)
print(us)
Path to music21 environment /Users/zal/.music21rc
{'directoryScratch': None, 'lilypondPath': '/Applications/Lilypond.app/Contents/Resources/bin/lilypond', 'lilypondVersion': None, 'lilypondFormat': 'pdf', 'lilypondBackend': 'ps', 'musicxmlPath': '/Applications/MuseScore 3.app/Contents/MacOS/mscore', 'midiPath': '/Applications/Utilities/QuickTime Player 7.app', 'graphicsPath': '/Applications/Preview.app', 'vectorPath': '/Applications/Preview.app', 'pdfPath': '/Applications/Preview.app', 'braillePath': None, 'musescoreDirectPNGPath': '/Applications/MuseScore 3.app/Contents/MacOS/mscore', 'showFormat': 'musicxml', 'writeFormat': 'musicxml', 'ipythonShowFormat': 'ipython.musicxml.png', 'autoDownload': 'ask', 'debug': '0', 'warnings': '1', 'localCorpusSettings': LocalCorpusSettings([]), 'localCorporaSettings': {}, 'manualCoreCorpusPath': None}

Next, we give the path to the MuseScore binary. The following code cell gives two typical locations for Linux and Windows environments. Note that this could be different on your system and has to be changed, possibly. Both, setting up the user environment file and the specification of the MuseScore path has to be executed only once.

Note: The following example may not work on Windows yet. The reason for this is a bug in music21. This was fixed and will be solved in the next version of music21. However, currently the fix is not included the the latest version.

In [2]:
# for linux
# us['musescoreDirectPNGPath'] = '/usr/bin/mscore'
# us['musicxmlPath'] = '/usr/bin/mscore'

# for windows
# us['musescoreDirectPNGPath'] = r'C:\Program Files (x86)\MuseScore 2\bin\MuseScore.exe' 
# us['musicxmlPath'] = r'C:\Program Files (x86)\MuseScore 2\bin\MuseScore.exe'

If the setup is correct, the following code cell should create a music21 Note object and show its graphical rendition via MuseScore:

In [3]:
# n = m21.note.Note('c')
# n.show('ipython.musicxml.png')

Output of previous code cell

Another possibility is to use LilyPond for rendering. Again, we need three steps to get it to work.

  • First we need to install LilyPond.
  • Second, we have to set up the music21 user environment file (we already did that above).
  • Third, we have to register the path to Lilypond for music21. The following code cell again gives typical locations for Linux and Windows.
In [4]:
# for linux
# us['lilypondPath'] = '/usr/local/bin/lilypond'

# for windows
# us['lilypondPath'] = r'C:\Program Files (x86)\LilyPond\usr\bin\lilypond.exe'

Finally, we are able to render our simple note via Lilypond:

In [5]:
# n.show('ipython.lily.png')

Output of previous code cell

For creating a staff line with multiple notes, we add multiple music21 objects to a music21 Stream.

In [6]:
# s = m21.stream.Stream()
# s.append(m21.key.Key('E-'))
# s.append(m21.meter.TimeSignature('2/4'))
# s.append(m21.note.Rest(quarterLength=0.5))
# s.append(m21.note.Note('g', quarterLength=0.5))
# s.append(m21.note.Note('g', quarterLength=0.5))
# s.append(m21.note.Note('g', quarterLength=0.5))
# s.append(m21.note.Note('e-', quarterLength=2))

# s.show('ipython.musicxml.png')

Output of previous code cell

Instead of writing Python code to create a music21 score, we can also read and display a MusicXML file.

In [7]:
# fn_xml = os.path.join('..', 'data', 'C1', 'FMP_C1_F01_Beethoven_FateMotive_Sibelius.xml')
# s = m21.converter.parse(fn_xml)
# s.show('ipython.musicxml.png')

Output of previous code cell

We can also read in a full orchestral score. Since such a score cannot be rendered on a single page, we can specify the measures that we want to show:

In [8]:
# fn_xml = os.path.join('..', 'data', 'C1', 'FMP_C1_F10_Beethoven_Fifth-MM1-21_Sibelius-Orchestra.xml')
# s = m21.converter.parse(fn_xml)
# s.measures(1, 5).show('ipython.musicxml.png')

Output of previous code cell

Acknowledgment: This notebook was created by Frank Zalkow and Meinard Müller.
C0 C1 C2 C3 C4 C5 C6 C7 C8