music21 is a Toolkit for Computational Musicology
Music21 v9 (June 2023) is the latest release of music21
, a toolkit for computational music research.
Version 9 contains about 600 new commits and features from the version 8 release from September 2022. It is the latest and best release in the industry standard toolkit for doing music research and composition ("traditional" computation and AI/ML) with musical scores.
As a new Version X release, music21
gains a lot of its power with a few non-backwards compatible changes that make the system easier to use, faster, and more up to date. People using music21 in existing environments should read the change logs to make sure their systems work with it before upgrading.
A big change in music21 is that v9 is compatible with Python 3.10 and 3.11 only. The version 9 release will be updated to be compatible with at least Python 3.12 when it is released. Users on Python 3.8 and 3.9 should stick with v8 and those on older versions should look at the README to see what version will be installed for their systems.
Two weeks from the release of version 9 (July 1, 2023), Michael Asato Cuthbert, the lead developer of music21 will take a 6-12-month sabbatical from monitoring the mailing list, answering questions/issues, and merging PRs in order to focus on what he does best and what is best for the community: developing core parts of the system and documenting what already exists. Working with the user community has been amazing, but given that he only has about 10-15 hours per week to devote to the project, it often means deviating from efforts that help a large number of people to instead work through PRs and issues that are important to a smaller community. This news will probably not be welcomed by some, but the results should be better for the larger community.
music21
in a modern IDE to see it. Uses Python 3.10 TypeGuards. Add common.classTools.holdsType([‘a’, ‘b’], str) which asserts that everything in a collection has the same type. (@mscuthbert in https://github.com/cuthbertLab/music21/pull/1447). converter and corpus are fully typed.music21
that are too late to fix, but the next generation of software should not emulate. (3) add docs about abcFormat support (@mscuthbert in https://github.com/cuthbertLab/music21/pull/1484). (4) coreInsert (@mscuthbert in https://github.com/cuthbertLab/music21/pull/1549). (5) layout (@mscuthbert in https://github.com/cuthbertLab/music21/pull/1554). (6) clercqTemperley (RS100 dataset) format (#1558)PercussionChord.pitches
property (@jacobtylerwalls in https://github.com/cuthbertLab/music21/pull/1547), (2) Ignore Unpitched objects in key analysis (@jacobtylerwalls in https://github.com/cuthbertLab/music21/pull/1543, (3) Search support (@mscuthbert in https://github.com/cuthbertLab/music21/pull/1597)requests
should have been in the minimum requirements (@jacobtylerwalls in https://github.com/cuthbertLab/music21/pull/1568)__eq__
comparison on many objects has changed. – it is now based on a class hierarchy where the object needs to be equal in all of its super-classes (@mscuthbert in https://github.com/cuthbertLab/music21/pull/1466 and https://github.com/cuthbertLab/music21/pull/1459).
For time signatures: (@MarkGotham in https://github.com/cuthbertLab/music21/pull/1457). For ChordStepModification (@jacobtylerwalls in https://github.com/cuthbertLab/music21/pull/1482). An exception is made for RomanNumerals which do not need to have pitches in the same octave (like their chord.Chord superclass requires)Full Changelog: https://github.com/cuthbertLab/music21/compare/v8.3.0...v9.1.0
Music21 v8.3 is a maintenance release that fixes a few bugs in romanText/translate (thanks @malcolmsailor) already in v9alpha, but also fixes a change in the Github.io version of music21j that broke .show('midi') inside Jupyter notebooks.
Full Changelog: https://github.com/cuthbertLab/music21/compare/v8.1.0...v8.3.0
I'm proud to release v8 of music21, the toolkit for computer-aided music analysis, score manipulation, computational musicology, etc. This release (technically 8.1) builds on 12.5 months of work from v7, and like all new big number releases has a few backwards incompatible changes from before, in exchange for cool new features.
Version 8 supports Python 3.8+, if you need Python 3.7 (such as on Google Colab which is now 3+ Python versions behind) stick to music21 v7. V8 is the first to fully support Python 3.10 and will receive patches to support Python 3.11 in the future. As Python 3.11 is due to be released any day now, keeping with the m21 policy of supporting three versions of Python, music21 v9 (work starts tomorrow!) will support Python 3.9 and above only.
<forward>
tags from expressions out of measure bounds by @jacobtylerwalls in https://github.com/cuthbertLab/music21/pull/1261
<movement-title />
and <creator />
tags when title and author have no defaults by @jacobtylerwalls in https://github.com/cuthbertLab/music21/pull/1248
getPitches(direction=DESCENDING)
returning ascending scales by @jacobtylerwalls in https://github.com/cuthbertLab/music21/pull/1311
Key
instances compare equal regardless of tonic octave by @jacobtylerwalls in https://github.com/cuthbertLab/music21/pull/1316
splitElementsToCompleteTuplets
doctest by @jacobtylerwalls in https://github.com/cuthbertLab/music21/pull/1362
RomanNumeral()
by @jacobtylerwalls in https://github.com/cuthbertLab/music21/pull/1340
Stream.__getitem__
searches by @jacobtylerwalls in https://github.com/cuthbertLab/music21/pull/1359
makeNotation
argument to test utility by @jacobtylerwalls in https://github.com/cuthbertLab/music21/pull/1376
<backup>
values in PartStaffExporter by @jacobtylerwalls in https://github.com/cuthbertLab/music21/pull/1375
stripTies()
crash in certain scenario with matchByPitch=False by @jacobtylerwallsfiguredBassFromStream()
by @jacobtylerwallsfiguredBassFromStream()
by @jacobtylerwalls<forward>
tags by @jacobtylerwalls__eq__()
and __getitem__()
in doc builds by @jacobtylerwallsAs always, thanks to the Seaver Institute and the National Endowment for the Humanities for supporting music21. And MIT, SHASS/Music and Theater Arts.
Full Changelog: https://github.com/cuthbertLab/music21/compare/v7.1.0...v8.1.0
Music21 v8 Release Candidate
testing a new deploy system.
Music21 7.3.3 adds support for showing MIDI inside a Google Colaboratory (colab) notebook, via music21j. Since m21 v8 will be Python 3.8+ only, and Google Colab is still on Python 3.7, a back-port to v7 was needed.
7.3.2 was internal development only and not released
7.3.1 fixed a bug that made some installations of v7.3.0 fail, and fully replaced the 7.3.0 branch, which, as Apple would say, is now "unsigned".
Music21 version 7.3 is released. This is the second and probably final release on the v7 line. I begin work on version 8 today.
Version 7.3 is a bug-fix, improvement, and maintenance release of music21. Aside from a few obscure corners of the code, it is designed to be fully backwards compatible with the previous v7 releases (7.1). It represents half a year's work since the original v7.1 release.
Thanks go especially to Jacob Tyler Walls who really steered the contributions to this release.
Among the major improvements in this branch are:
vi/VI/vio
and vii/VII/viio
Smaller improvements and features include:
Deprecations:
Goals for the upcoming v.8 include support for MusicXML 4.0 and SMuFL and better round-tripping between various formats, cleaner typing, improved docs and faster operations. Improved support for IDEs including Jupyter notebook and Colab will also be prioritized.
There are other new features, such as improving OMR post-processing, restoring the web/VexFlow 4.0 connection, etc., but (as people who have proposed major new features on GitHub will be aware), I'm planning on considering the core music21 largely "feature complete" and encouraging people to make external libraries (now that pip + GitHub makes this so much easier) rather than stuffing more into music21. I'd rather focus music21 on being the core system for so much else than putting more into it. I don't plan on removing anything currently in music21 in the next version, but you may find that they're being imported from other libraries instead. This will let the community move at the pace some people there want while letting me guide the core project as 15 years of development on it has taught me.
As ever, music21 would not have been possible without support from the Seaver Institute, the National Endowment for the Humanities and the multinational Digging into Data challenge, and the support of MIT/SHASS/Music & Theater Arts.
(7.3.0 had an installation bug -- replacing with 7.3.1)
Version 7 (technically 7.1.0) of music21, a toolkit for computational musicology, music theory, composition, etc. is released! A substantial revision and set of improvements for music21 that will make it easier to analyze, explore, and compose music. As with all new major version releases, there are some incompatibilities with earlier versions that should make developers test their own software before upgrading.
Why type:
myScore.recurse().getElementsByClass(note.Note)
When you can now type:
myScore[note.Note]
Or if you want to find the first Key object in the piece, don't type:
walkure.flat.getElementsByClass(key.Key)[0]
...which will walk through the entire score, even though you just want something at the beginning. You can instead do:
walkure[key.Key].first()
in a millionth of the time. Streams and StreamIterators get the .first() and .last() methods, though only .first() is currently a major speedup. When we figure out how to walk an iterator quickly backwards, though, one day, .last() will also magically become faster.
Making a stream from notes could take a lot of space:
c = note.Note('C')
d = note.Note('D')
m = stream.Measure()
m.append(c)
m.append(d)
p = stream.Part()
p.append(m)
So why not:
c = note.Note('C')
d = note.Note('D')
p = stream.Part(stream.Measure([c, d]))
now if a list of elements are passed into the stream constructor, they are appended one after another, not all inserted at position 0.
If a stream is passed to another Stream's constructor it is put into the Stream itself, not its elements. This was a common mistake in v6 and earlier:
c = note.Note('C')
m = stream.Measure(c)
p = stream.Part(m)
sc = stream.Score(p)
Before, since Streams are list-like, the only thing in the Score would have been the single note C with no parts or measures at all!
In v7, the code above will create a perfectly well-formed score (well, except the lack of TimeSignature, etc., but music21 can figure that out for you.
Oh, and if you put multiple Measures into a Part constructor, they're all appended as they should be. Put put multiple Parts into a Score constructor or multiple Voices into a Measure constructor and they're all at offset 0, like they should be. Smart is better than inflexible.
Because of this change, there's now much more incentive to create proper Part, Measure, etc. objects than just making everything a general Stream.
Streams can now retrieve a single element with recursive search by id:
sc['#myId']
or easily iterate over all elements recursively by group:
for n in sc['.myGroup']: ...
If it looks like CSS querySelectors, it's for a reason. And we're just getting started with showing the power of these elements.
Stream.flat has become Stream.flatten() -- why? (a) it's a verb, and should be a verb. (b) it takes a long time to generate and alters the .sites on the contained notes, so it shouldn't be a property, which implies that it's fast and has no side-effects. (c) it is now no longer shorter and faster to type than Stream.recurse() which is what you want to do 90% of the time anyhow. Stream.flat will stick around for at least 2 more versions, becoming deprecated in v8 or 9 and removed in v9 or 10. I know it's our version of "print(a)" replacing "print a" and it'll take some time to get used to. But it was a mistaken choice in 2008 and it's just as much of a mistake in 2021.
(For .semiFlat, just use Stream.flatten(retainContainers=True) which is much clearer)
Jacob Tyler Walls has joined the commit/core development group of music21 and can now review your pull requests etc. He has made MAJOR contributions to v7 and it would not be out without him! Please send him your thanks when you use music21. Because he's on the core team now, I won't single out his contributions separately from my own (for the most part. When it's big, I'll say so).
*Add TempoChangeSpanner with subclasses RitardandoSpanner and AccelerandoSpanner. How these were missed is beyond me!
Stream.__init__
is mostly in Stream.base now. __dir__
to remove things you don't want to see from dir(module)This was a HUGE amount of work since v6.7 released in February. Super proud of the community for making it possible. If you're on a version older than 6.7, here are the biggest things you're missing:
Thanks always to the Seaver Institute, MIT, and the National Endowment for the Humanities for supporting music21.
Maintenance release for v6.7 --
fixes bugs in lyric.search for working with "composite" lyrics, in the export of piano scores with key signatures, and a bug in piano scores and other part staffs that (a) prevented them from being flattened properly and (b) did not allow flattened piano scores to call `.show()
Other changes and improvements are going into the v7 / main branch.
music21
v6.7 is released. This will likely be the last release on the v6 line (more later), which has seen remarkable speed and stability improvements. Here’s what’s new in the past month since 6.5 came out:
music21
with an “importlib” error, this is fixed.6.7 is likely the last release in version 6. We begin work on version 7 today! This means that most deprecated functions will be removed, to speed up the system and help build new things.
music21
will support it.But dropping Py3.6 means some great changes:
__getattr__
and __dir__
will be defined for certain key modules (like Note) so that all the typing and internal information isn't exposed.Deprecated functions gone ASAP:
New deprecations
Weird changes of properties to methods:
Stream.iter()
will be the encouraged new form instead of Stream.iter
Stream.sorted()
will be encouraged new form instead of Stream.sorted
Stream.flat()
encouraged for Stream.flat
-- similarly for .semiFlat
These methods were disguised as properties early on in music21
and it was a bad mistake, leading to lots of problems with introspection. Migration will go like this: v7 -- new forms are allowed and documentation is updated to encourage it. v8 -- all mention of old forms will be removed from the system and where possible using the old form will send a DeprecationWarning. v9 -- old forms are removed.
Version 7 might take until the summer or beyond. (Hence there may be bug-fix versions of v6.7 along the way). So for now, enjoy what’s out there and look forward to the future. Master branch will move to v7 but will remain as stable as possible.
Thanks to the community for great support and as always to the Seaver Institute, National Endowment for the Humanities, and MIT for support of music21
.
Happy New Year! I am pleased to announce that the newest Version of music21
, version 6.5 has been released. It is nearly completely backwards compatible with other v6 releases and runs on Python 3.6–3.8. Music21
is an open-source toolkit for computational music theory and musicology, and also used in composition and music production. Download it via pip
with:
pip install --upgrade music21
Version 6.5 adds several important new features since the bug-fix version 6.3 (from mid-November 2020) while squashing many bugs and speeding up a number of parts of the system. Many of the contributions were made by members of the open source community, including major contributions by Jacob Tyler Walls (JTW), Mark Gotham (MG), Néstor Nápoles López (NNL), and Paula Muñoz Lago.
Highlights include:
PartStaff
objects such as a staff of a piano part now export properly back to MusicXML as one part with <staff>
tags. Huge work by JTW!music21
loads or starts up in 1/3 the time as before. (MSC).staffType
attribute on layout.StaffLayout
objects. .staffLines
is now settable on all Stream types (not just Parts) as a shortcut to manipulating layout.StaffLayout().staffLines
at the start of the Stream. (MSC)Smaller features and bug fixes:
.show('scala')
works on more scales. (JTW)instrument.deduplicate()
removes duplicate instruments at the same offset in a stream (JTW)partitionByInstrument()
no longer leaves instruments with non-zero durations (MSC)Thanks always to the Seaver Institute, the NEH, and MIT for support on creating music21
.
I'm not sure if the next release will be v7 (with some backwards incompatible changes) or another v6 release (6.7). I do know that better piano support and percussion support are high on my lists. However, I'll be taking a bit of a break from music21 over January at least in order to get other publications out and work with my other projects. Happily, the community engagement with music21 has never been stronger and I'll still be here reviewing Pull Requests and thinking about the next steps!
-- Myke Cuthbert