pyScore

Copyright 2004-2005 Michael Droettboom

pyScore is a set of Python-based tools for working with symbolic music notation.

Since it is pure Python (with an optional compiled rational number library), it runs on many different platforms without modifications, including Microsoft Windows, Linux and Apple Mac OS-X.

pyScore can be run from the commandline or as a Python library. GUI support may be available in the future if there is enough demand. It should be fairly easy for an experienced Python GUI programmer to build a GUI for pyScore.

This software is released under the GNU General Public License (GPL). This work is supported in part by the National Science Foundation through an Information Technology Research grant.

Contents

Features

The current features are:

The various conversions are illustrated in the following graph. Each arrow represents a direct conversion. The dashed arrows indicate that the conversion is somehow lossy. The bluish nodes represent on-disk files. Everything else is an in-memory data structure.

pyScore_graph.png

Download

You can also browse the CVS.

Release Notes

Pertaining to latest release (0.4.0):

Notes

  • Guido is output with latin_1 encoding, because that seems to work with NoteServer [convert.py]
  • arguments to Guido beams are ignored [beam_stem.py]
  • Only the first verse of lyrics in MusicXML can be stored in Guido [musicxml_to_guido.py]
  • There is no way to represent <senza-misura> and type="single-number" for meters in Guido [musicxml_to_guido.py]
  • Tempo names are not converted from MusicXML -> Guido, only metronome markings [musicxml_to_guido.py]
  • There is a limited vocabulary of written directions that get converted from MusicXML to Guido. This conversion is not very smart or robust. [musicxml_to_guido.py]
  • Markings followed by dashes are not supported by MusicXML -> Guido [musicxml_to_guido.py]
  • MusicXML doesn't seem to have a way to support Guido \headsReverse [guido_to_musicxml.py]
  • Guido \noteFormat tag is completely unsupported [guido_to_musicxml.py]
  • Guido \splitChord tag is completely unsupported [guido_to_musicxml.py]
  • In GUIDO, barlines are "global": i.e. they affect all parts. Therefore, we merge all barlines, but warn if there are barlines in subsequent parts that do not match those in the previous parts. [guido_to_musicxml.py]
  • Guido doesn't have named parts like MusicXML, so we grab it from the \instrument tag [guido_to_musicxml.py]
  • Measures out-of-order (using arguments to the \bar tag) in Guido are treated as being in file ordering [guido_to_musicxml.py]
  • accelerandos/ritardandos are output to MusicXML as text only (i.e. no actual tempo changes) [guido_to_musicxml.py]
  • Lyric syllables from MusicXML -> MidiXML are pretty weak for obvious reasons [musicxml_to_midixml.py]
  • Only type 1 MIDI files are supported at this time [midixml_to_midi.py]
  • MidiXML <EndOfTrack> elements are ignored [midixml_to_midi.py]
  • MidiXML <MTCQuarterFrame> elements are ignored [midixml_to_midi.py]

Bugs or shortcomings in other systems

  • Note-level dynamics do not seem to work in Turandot [guido_to_musicxml.py]
  • tremolos don't seem to work in Turandot [guido_to_musicxml.py]
  • tremolos don't seem to work in Finale 2004 / Dolet 1.3.1 [guido_to_musicxml.py]
  • secondary beaming doesn't seem to work in Turandot [guido_to_musicxml.py]
  • Elisions don't work correctly in Turandot. [guido_to_musicxml.py]
  • ornaments don't seem to work in Turandot [guido_to_musicxml.py]
  • Turandot doesn't seem to handle changing clefs mid-stream [guido_to_musicxml.py]
  • System breaks don't work in Turandot. [guido_to_musicxml.py]
  • multiple repeat endings do not seem to work in Turandot [guido_to_musicxml.py]
  • repeats display but do not actually play in Turandot [guido_to_musicxml.py]
  • tempo tags don't seem to work in Turandot [guido_to_musicxml.py]
  • Octave shift does not seem to work with Turandot [guido_to_musicxml.py]

To-dos

  • deal with time-wise MusicXML scores (e.g. use Michael Good's XSLT transform first) [musicxml_to_guido.py]
  • MusicXML -> Guido ornament handling [musicxml_to_guido.py]
  • check that we have xmllint and use it [validate.py]
  • document GuidoToMusicXML.make_plan because it's really hairy [guido_to_musicxml.py]
  • support word-based (as opposed to wedge-based) cresc. and dim. [guido_to_musicxml.py]
  • add support for custom namespace resolvers/default namespaces [ElementTree.py]
  • add support for incremental parsing [ElementTree.py]
  • check that we have xmllint and use it [validate.py]

Longer-term plans

  • Finish support for conversion from MusicXML to Guido [musicxml_to_guido.py]
  • Possibly switch to another XML toolkit to support transformation and validation directly from Python [validate.py]

Test results

There are some automatically generated test results that demonstrate the abilities of the system.

It is not expected at this point that the output is entirely correct. If you see a long URL displayed beginning with http://tempo.iti.informatik.tu-darmstadt.de/, that means the Guido NoteServer choked on what was being sent to it, which is most likely the result of pyScore generating erroneous output. Internet Explorer and Mozilla will display the MusicXML files as pretty-printed XML which is a nice way to debug the output. If your browser is set up to play MIDI files, they should play directly from the link.

Installation

Building and installing from source

To build and install this package, use the regular Python distutils method:

python setup.py build
sudo python setup.py install

If you do not have a compiler available, you can use the --no-compiler build flag. pyScore will still work, but will run much slower:

python setup.py build --no-compiler
sudo python setup.py install

On Mac OS-X, you probably want to install the scripts somewhere reasonable:

sudo python setup.py install --install-scripts=/usr/local/bin

If you don't already have /usr/local/bin/ on your PATH, you may want to add it.

Binary installers

No binary installers available yet.

Acknowledgements

This package includes local copies of other third-party packages, so that it can be installed on a vanilla Python system. I'd like to thank these uber-programmers for their great work, without which writing pyScore would have been much more difficult: