pubPhotos
LATEST NEWS from my Prolatio and music21 blogs:
[September 8, 2021 20:11 pm] « » [music21]
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.

Big improvements:

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)

New Core Developer: Jacob!

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).

Other substantial improvements

  • I hope you're editing your own files in a modern IDE like PyCharm or VSCode.  We've added tons of typing information to help you find bugs before you run.
  • Significant improvement in MIDI Quantization.  We still recommend converting MIDI to MusicXML (or Humdrum/MEI/etc.) in a dedicated MIDI processor, but many more MIDI files will work "out of the box" in music21 v7.
  • Go ahead and parse a large piano score from musicxml.  But don't go get your customary cup of coffee.  Jacob made it very fast now!  Lots of speedups!
  • PercussionChords or chords containing a mixture of Note and Unpitched objects are now supported!  We're getting much closer to equal support for percussion as for pitched music!
  • Multiple instruments can be in a part now and manipulated and exported to musicxml.  This works simultaneously in voices, successively (broken before in musicxml), or overridden on a single note basis with n.storedInstrument.
  • Full support for Python 3.9.  Python 3.10 also seems to work with m21v7, but is not officially supported.  Official support will come during the v.7 lifecycle unless it requires backward incompatible changes (unlikely).  In keeping with music21 policy to support the last three versions of Python, version 7 will be the last version of music21 to support Python 3.7. 
  • The representation of many music21 objects has changed and become standardized to give a lot more information (what type of rest is it?  What octave is the note in?)  This should help with debugging and shouldn't affect anyone unless you are parsing repr() for information.  (Don't do that).  If you are creating your own Music21Object subclasses define _reprInternal() to return just internal information beyond the class name to get it right.
  • Braille output respects lineLength configurations. Slurs work better too in braille.
  • MIDI import comes with measures already made for you!
  • roman.romanNumeralFromChord() recognizes a bunch more chords including all augmented sixth chords in all inversions (except German7 which I can't figure out).  And RomanNumeral now takes "It" alone to mean It+6, and same for the others -- it puts them in their most common inversions.  To get root-position Aug6 chords, spell out their figures explicitly:  It53, Ger7, Fr7, etc.
  • Ornaments now realize with their key contexts.  Trills are great.
  • MIDI input now preserves channel and program numbers for MIDI output.
  • Chris Reyes has contributed a formal grammar for TinyNotation which helped us find lots of bugs.  Thanks!
  • Write compressed musicxml directly by passing in a filename ending in .mxl.
  • getContextByClass has configuration options that when called on a Stream let them look inside themselves for their own context.
  • Beaming improvements in pickups and incomplete final measures.
  • MusicXML and MIDI files that give a part name like "flute" but no instrument or program code will get a Flute object in music21.  It's the least we can do.  And if a score sets a MIDI-0 instrument but no part name and only a single staff, it's probably a default value and not a piano, so we just give a generic Instrument object.

Incompatible Changes that might affect casual users:

  • Python 3.6 is no longer supported.  Stay with 6.7.1 if you need that.
  • The default extension for musicxml is now .musicxml and not .xml
  • MIDI import comes with measures already made
  • Stream.iter is now Stream.iter() -- the old format will work for one more version.  (Most people just do "for el in s" anyhow, so not a big deal.
  • findGaps() now returns Rest objects at the same place as the old Music21Objects.  Makes it easier to add them back to the Stream to fill gaps.
  • See above about if you're parsing repr() that representations have changed.
  • n.pitch.accidental = 'sharp' is no longer allowed.  Do n.pitch.accidental = pitch.Accidental('sharp') -- this is so that querying n.pitch.accidental afterwards returns the same object.
  • Stream.sorted has become Stream.sorted(), but you probably should never call this anyhow, since all streams are always sorted unless you set .autoSort to False.
  • stripTies() removes retainContainers parameter.  They're always retained.  Just call .flatten() after stripTies to remove them.  MatchByPitch is also True by default now.
  • Before running WindowedAnalysis on a Score, flatten it.  (This came from the makeMeasures change)
  • See the changes to instantiating a Stream with a list of elements above.
  • note.SpacerRest() is gone.  Use a normalRest with .style.hideObjectOnPrint set to True.
  • ComposerPopularityFeature is gone.  It was a fun routine that added the popularity of the composer by googling her or him and returning the log10 of the number of search results.  But Google changed their API so it was no longer working.  Too bad.   (It's not working in v6 either)
  • Dynamics, etc. now use "placement" instead of "positionPlacement"
  • Now that Percussion chords are being used and unpitched objects will appear more often, do not assume that the only things in ".notes" are Notes and Chords.  So if you want to call ".pitch" on the object, check that it is a Note, instead of checking that it is not a Chord.

Other improvements and fixes

  • Add TempoChangeSpanner with subclasses RitardandoSpanner and AccelerandoSpanner.  How these were missed is beyond me!
  • ABC supports more chord formats including better durations (thanks Marian Schultz)
  • Stream.splitAtDurations() now works and can efficiently remove all "complex" durations.
  • A number of places where "coreElementsChanged()" weren't being called now are.
  • NotRest objects all get .pitches attribute, which might be empty.  Version 8 will add this to Rest objects as well, which will of course always be empty.
  • Lots of docs typos fixed (thanks Meekohi)
  • Plaintext (non-Regexp) lyric searching had bugs that are fixed
  • Piano Scores can now have independent key signatures in each hand imported and exported to musicxml properly.  Go play "The Alcotts" now.  :-)
  • Cross-staff spanners in piano scores import much better.
  • Lots of special strings and ints have become Enums.  Expect more in the future.
  • MakeMeasures can be run on a score without losing its part information.
  • Running Score.measures(24, 26) etc. will only get spanners relevant to that measure range, not every darn slur in the score!
  • Speedups now that the minimum Python version 3.7 has dictionaries that preserve insertion order.
  • Bold + Italic text exports to musicxml properly.
  • Added common.misc.unique which gets a unique list from an iterator while preserving order (unlike set)
  • Meter has been split into four modules to make it easier for someone to figure out how TimeSignatures work without needing to read about AccentSequences first.  TimeSignatures are much faster to generate.
  • Lots more docs in the duration module.
  • Decent beams in output of a score w/o explicit time signatures
  • When you mistype a path into converter, now you'll get a FileNotFoundError rather than music21 trying to parse the path name as a type of notation.
  • simplifyEnharmonics on a Chord can now be given a keyContext to figure out a better way of reducing accidentals (thanks gulnazaki!)
  • ChordSymbol objects transpose properly to a new ChordSymbol that reflects its current bass/root etc.
  • Chord.isTranspositionallySymmetrical -- can the chord be transposed up some number of semitones between 1 and 11 and get the same pitch classes?  Also has a requireIntervallicEvenness which checks if it is a tritone-dyad, augmented triad, diminished-seventh chord, wholetone scale, etc. for which inversion cannot be determined by ear.
  • hyphen-to-camelCase is now way faster, so is elementOffset() -- this would be a "so-what" except that together with an improvement to duration creation they speed up MusicXML parsing by almost 40%.
  • Spanner.getSpannedElementIds is sped up.  Again a so what?  Well, it's 75% faster MusicXML output for scores with spanners such as slurs, etc.
  • Duration.expressionIsInferred attribute.  Think that a QL of 0.5 is always an eighth note?  Well, if it's between 0.333 and 0.16666 it might be a dotted-eighth triplet.  When a note is set with a quarter length, expressionIsInferred is True, and music21 is allowed to renotate it to fit the context.  A note with duration 2.5 might be quarter + dotted quarter in 5/8 as 2+3 but might be the opposite in 3+2 5/8.  Not fully implemented, but something for the future.
  • Lots of little speedups all around.
  • Full measure rests now work in 9/8 and some other meters where there is no way of expressing a note of that length, but we can for rests with a Whole Note.
  • Improvements to NeoRiemannian operations on MIDI-generated notes.  Thanks ax-le.
  • Dynamics, wedges, coda, segno, and tempo markings retain their positions on musicxml import/export.  And thanks to Gesellkammer metronome marks also know if they're above or below the staff.
  • makeTies() works better when a note inside a voice is tied to a note outside of a voice.  No unnecessary voices made.
  • TAB staves always have notes that are stem down.  (Thanks Louis Bigo)
  • DataSet.write() now tells you the filepath that was written.  (Duh!)
  • Add Chord.hasAnyEnharmonicSpelledPitches()  -- C4 E4 G4 B#4 returns True
  • isItalianAugmentedSixth etc. gains a permitAnyInversion=False keyword which can be set to True to find unusual inversions of augmented 6th chords.  Oh, and they're much simpler and faster (if it matters)
  • Mordents etc. return GenericIntervals when realized so that they can take into account key signatures.
  • Finding the root of a chord is much, much faster.  That's something that's needed for lots of analytical methods.
  • i7 and iv7 are now minor seventh chords when in a Major key.  So C-Eb-G-Bb.  To get a minor-major chord, spell it as i[add7].  Tonic minor-major chords in third inversion in major currently have no representation.  I think that that's a very rare case that this is an improvement for everyone.
  • FrontAlteration symbols are fixed for Neapolitan and AugmentedSixth roman numerals.
  • Add common.classTools.tempAttribute and saveAttributes context-managers for temporarily setting an attribute to something else and restoring it afterwards.  (just a helper)
  • Stream.duration is much better about detecting non-standard ways of altering containing note durations.  Thanks Greg Chapman for finding the bug.
  • MusicXML can import measures containing only ChordSymbols (empty leadsheets)
  • converter.parse() with a URL can now also take forceSource=True to redownload a file from the net.
  • Scores generated by .template() now export repeats properly.
  • makeTies() takes a classFilterList now.
  • makeRests puts rests properly in measures.  So you can do.  s = stream.Stream(); s.append(meter.TimeSignature('4/4')); s.insert(9, note.Note()); call makeRests() and get two full bars of rests, a quarter rest, and then your note and rests afterwards!
  • MusicXML input now handles notes that have different durations than the typical modern length implied by their shape (handy for contemporary music and the baroque).
  • TimeSignatures of 3.0/4.0 are now identified as an error before they're parsed into something weird. (Thanks Luke Poeppel)
  • Gracenote and appogiature display improvements.
  • Crashes in feature extraction should be less rare as more common edge cases are handled.
  • GraceNotes no longer interfere with beaming.
  • .melodicIntervals() works with Chords now too.
  • Lilypond output fixes and improvements.  With Lilypond now having a native Mac-64bit app, it is no longer under threat of being removed from music21.
  • Various write/show routines now work in multi-user Unix environments where users do not have write access to the normal temp folder.  (Thanks tanchihpin0517)
  • Improvements to TwelveToneRow.areCombinatorial()  (Thanks Mark Gotham)
  • KeySignature objects can now run asKey(tonic='A') and will try to find what mode has this key signature with that tonic.
  • Substantial improvements in Stream.findConsecutiveNotes() including with and without voices.
  • advanced users who need a very fast output of a Score which has already been asserted to be well-formed can call .write(makeNotation=False), which will not create any beams, tuplets, etc.  Unless you are a power user who needs the extra speed for processing thousands of files, and who can run a debugger to see what is wrong, don't use this.  It's going to crash on you.  But for those who do need it, the speedup is tremendous.
  • Transposing instruments set to .atWrittenPitch now display at written not sounding pitch in musicxml output.
  • Add Electric Piano and Choir instruments.
  • Music21 via pip will always be installed with the correct requirements (thanks James Owers)
  • Very long notes can now be shown via .show() and will be broken up into multiple measures.
  • Add Chord.inversionText to easily get "First inversion" "Root position" etc.  For unusual augmented sixth chord inversions, we add this text to the common name.
  • Smarter decisions on when to rearticulate an accidental after a key change.
  • Successful writing to MuseScore PNG/PDF will not fill your console with junk.

Deprecated methods/etc. that you were warned about that have been removed: 

  • Chord.findRoot() [dep. since 2018] is gone. Just use Chord.root()
  • Editorial.misc['anyKey'] is gone.  Just use Editorial.anyKey instead.
  • humdrum.parseFile() and humdrum.parseData() are gone. [Dep. since v6] Just call converter.parse('myFile.krn') instead.  These functions stuck around for way too long since they appear in the original music21 publications, but time changes.
  • interval.convertSpecifier() is gone. [dep v6]  use interval.parseSpecifier() instead, which returns a interval.Specifier enum instead. 
  • Roman.scaleOffset is removed.  Use the identical .frontAlterationTransposeInterval instead.

Incompatible changes that will only bite real music21 fanatics:

  • setElementOffset has addElement and setActiveSite removed as options
  • Environment.launch() no longer raises CalledProcessError
  • Duration.updateQuarterLength() is gone/private.  QuarterLengths should always automatically match the type/dots/tuplet, etc. unless "unlinked".
  • Harmony.addChordStepModification() sets default for updatePitches to True. 
  • Roman.followsKeyChange is now Roman.editorial.followsKeyChange
  • makeAccidentals inPlace defaults to False.
  • Stream.__init__ is mostly in Stream.base now.
  • We've taken advantage of Python 3.7's module level __dir__ to remove things you don't want to see from dir(module)
  • A number of string/int returns have become StrEnums or IntEnums which can compare to their old values (i.e., OffsetSpecial.AT_END == 'highestTime'), but if you're doing isinstance checking then it's not going to work.  Relatedly getOffsetBySite(returnString=True) becomes getOffsetBySite(returnSpecial=True)
  • Stream.quantize() has recurse=False by default, matching other music21 methods.
  • StripTies() inPlace=True now returns None like other inPlace=True methods.
  • Meter split into 4 modules.
  • test/stream.py is now stream/tests.py
  • duration.durationTupleFromQuarterLength and durationTupleFromTypeDots are gone -- just create a Duration object with a given quarterLength or type and dots instead.  (made private on Duration)
  • setDefaultBeatPartitions moves forceCompound to a keyword only attribute.
  • default for key.KeySignature() is now no-sharps or flats rather than None (non-standard key signature).
  • Style objects are ProtoM21Objects.
  • Spanner.replaceSpannedElement() only takes Elements not memory locations.
  • hasAnyRepeatedDiatonicNote removes the useless testRoot keyword.
  • Realizing a mordent or trill or turn will give a different (now correct) result in a key context.  
  • See the change to "It" to mean "It6" etc.
  • See changes to i7 and iv7 in Major.
  • makeRests puts rests properly in measures.
  • Many music21 specific exceptions have been replaced by very similar general Python exceptions.  Grabbing an element that doesn't exist from a stream, like s[123999] raises an IndexError not a StreamException, for instance.
  • Ambitus.getPitchRanges() is removed.  Just do stream.analyze('ambitus')
  • .mx is no longer an abbreviation for musicxml.
  • Now that isinstance() is very fast on Python, we use that a lot internally.  This will only bite people who are loading modules from two different installations of music21 somehow (like using a package that includes its own version of music21).  Otherwise just enjoy the speed.
  • Chord now inherits from ChordBase to support having the same features on PercussionChord
  • Stream.extendDurationsAndGetBoundaries is gone -- did too many things at once.

New Deprecations

  • Stream.variants.  Call Stream[variant.Variant] or Stream.getElementsByClass(variant.Variant) instead.
  • Score.flattenParts().  Basically unused.  Iterate over sc.parts and call .flatten() on each of them.
  • common.Iterator. You haven't been using Python 2.6 for years, so you don't need it.
  • Duration.fill().  Was just a test function and we don't put them on objects any more.
  • TimeSignature.loadRatio().  Create a new TimeSignature or set .ratioString = '4/4' or .load()
  • TimeSignature.beatDuration returns NaN rather than raising an exception if beats are unequal.
  • common.almostEquals.  Since Python 3.4, Math.isclose() is better.
  • Spanner.getSpannedElementById().  Of course you never used this.
  • Stream.makeChords().  Use chordify() instead.
  • Stream.getKeySignatures().  Use getElementsByClass(key.KeySignature)
  • Stream.getClefs().  use getElementsByClass(clef.Clef) or getContextByClass(clef.Clef) or bestClef() depending on what you want.
  • VoiceleadingQuartet.color.  Use .style.color instead.
  • Note that isClassOrSubclass was slated to be deprecated in v7, but it was found to be too useful to remove completely.  Nonetheless, we prefer isinstance(n, note.Note) instead.


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:

6.7 -- Composite lyrics: multiple syllables on one note
6.5 -- PartStaff round-tripping to musicxml, RomanText output, better lyric searching
6.3 -- Compatibility with macOS Big Sur and Python 3.8
6 -- Type-hinting, no external modules bundled, interval fixes
5.7 -- big bug squashing.  Chorale metadata.  Chord.notes tools
5.5 -- Chord.commonName improvements. Volpiano.  Cad64
5.3 -- ABC parsing improvements. containerInHierarchy. Py 3.7 support
5 -- Chordify massive speedups. MusicXML style preservation.  Multiprocessing AI/ML
4 -- Graphing rewrite.  Local Corpora.  Style objects.  TinyNotation subclassing. Direct PDF generation
...and the list goes on.

Thanks always to the Seaver Institute, MIT, and the National Endowment for the Humanities for supporting music21.

[February 3, 2021 19:49 pm] « » [music21]

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:

  • Important bug fix: if you’ve had trouble loading music21 with an “importlib” error, this is fixed.
  • Composite lyrics changes to the implementation in 6.5: multiple syllables on one note in a single verse (like in Italian, “Il bianco edolce cigno”) now are imported to MusicXML property, stored in a Lyric.components object, and export to MusicXML properly.
  • Lyrics searching finds all lyrics in all verses (and composite lyrics too)
  • More major improvements to piano staff imports (thanks to Jacob Tyler Walls = JTW)
  • RomanNumeral.isMixture() shows whether a chord is borrowed from the other mode (Mark Gotham)
  • Several improvements in chord symbols (JTW + Alexandre Papadopoulos)
  • More improvements to finding instrument names from MIDI (JTW)
  • Duration marks in chords in ABC import properly (Marian Schultz)
  • Documentation improvements.
  • MusicXML parse failures now more often give the part and measure context (JTW)
  • Substantial bug fixes in Stream.setElementOffset. Adds a new Stream.coreSetElementOffset for the dangerous but super fast version, and makes the original version safer. (JTW)
  • Bug fixes in MEI articulations (heinzer) and accidentals (JTW)
  • Bug fixes in external tools in windows including spaces (JTW)
  • Channels handle better in MIDI (bearpelican)
  • Humdrum files with positioned rests no longer crash (Phil Kirlin)
  • OctaveRepeatingScale and CyclicalScale now usable as abstract classes (JTW)
  • Articulations and expressions musicxml does not support are exported as (JTW)
  • Better support for .musicxml as a file name within compressed .mxl files.
  • Beaming in pickup measures is fixed.
  • Stem directions can now be set automatically to coincide with beam groups. This is very useful if you are creating your own notation from scratch (as in VexFlow output; m21j gets the same routines)
  • Spanner endHeight and startHeight are processed correctly (JTW)
  • NoChord objects (in Chord Symbols) now retain their text (like “N.C.”) in more situations (JTW)
  • All NotRest objects get a .pitches function – a small thing, but will be helpful in the future.

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.

  • Version 7 will require Python 3.7 as a minimum version. Python 3.6 will be end-of-life by November, and v.7 will last for at least into 2022. music21 will continue to support all Python versions that are actively maintained during the expected life of the version. v3.7-3.9 will be supported, and when 3.10 comes out, the next minor version of music21 will support it.

But dropping Py3.6 means some great changes:

  • Many things that are NamedTuples will become dataclasses. (all but sortTuple). This will make working with a lot of data much better.
  • Many many string options (such as notehead and beam types) will become Enums. This will help with avoiding making coding mistakes that are hard to detect. Where this has already happened (like in VoiceLeadingQuartet.MotionType) life has already become better. They will be StringEnums, and have a transition period, so code that checks for Beam.type == “start” or Lyric.syllabic == “begin” will still work (but I can never remember which is start and which is begin. Hence the point!)
  • Substantial changes to Unpitched to make percussion support work.
  • Some OrderedDicts (yuk!) will become normal dictionaries, now that insertion order is guaranteed to be preserved.
  • Whatever else has been annoying me but I haven't been able to fix by committing to keep major versions backwards compatible.
  • For simplifying the life of beginner users, __getattr__ and __dir__ will be defined for certain key modules (like Note) so that all the typing and internal information isn't exposed.
  • I'm hoping that getElementsByClass will be able to specify its return type, at least when called with a class. For people using Typing in Python, this will be a major improvement.

Deprecated functions gone ASAP:

  • Chord.findRoot() -- just use chord.root() instead
  • interval.convertSpecifier – use parseSpecifier instead
  • formats.findFormat (and many others in the formats module etc.)
  • humdrum.parseData, humdrum.parseFile (just use converter.parse)
  • Editorial.misc (just stick it on editorial)
  • Duration.updateQuarterLength (not needed)

New deprecations

  • SpacerRest will become deprecated – just use a normal Rest with hideObjectOnPrint = True
  • Setting a pitch.accidental to a number or string will be deprecated – create an Accidental object first
  • setElementOffset deprecates two keywords: addElement and setActiveSite
  • isClassOrSubclass to be deprecated, use Class in .classSet – WAY faster
  • getClefs to be deprecated – use recurse().getElementsByClass(‘Clef’)
  • getKeySignatures to be deprecated -- use recurse().getElementsByClass(‘KeySignature’)
  • Stream.makeChords() to be deprecated – Chordify is the way to go.
  • Stream.extendDurationsAndGetBoundaries – was meant to be deprecated in 6 and gone in 7. It gets a one version reprieve.
  • stripTies.retainContainers to be deprecated – will always be True. Just call .flat afterwards to not get this.
  • Stream.iter.variants to be deprecated. Just use .getElementsByClass(‘Variant’)
  • tree.toStream.chordified() to be deprecated. It’s the internal guts of Chordify now
  • VoiceLeading.color to be deprecated – set .style.color on notes like any other object

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
  • (This might not happen, but...) Stream.flat() encouraged for Stream.flat -- similarly for .semiFlat
  • Other properties where it is possible to encourage method calling will also get this change.

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. The main 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.

[December 31, 2020 22:19 pm] « » [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!
  • RomanText is now a valid output format in addition to input! Save your analyses for later! Thanks Mark Gotham!
  • search/lyrics now finds second and subsequent lyrics (thanks to Paula ML and DIDONE project)
  • Improvements to VI and VII roman numerals in minor (JTW)
  • MIDI tries to import part names from instruments (JTW)
  • MIDI properly reads and writes conductor tracks (JTW)
  • Doc improvements for many places including RomanNumerals, insertIntoNoteOrChord, chordify with GraceNote (MSC)
  • Major speedups for many chord actions including getLeadingTone, isTriad, isMajorTriad, etc. (NNL + MSC w/ JTW)
  • music21 loads or starts up in 1/3 the time as before. (MSC)
  • Opus.write() improvements -- now all filenames of an Opus write call have similar names and only the last filename is returned (JTW)
  • All properties in music21 are readable without raising an exception. This will help inspection/debugging software. (MSC)
  • Staff-type is imported and exported properly to/from musicxml as the .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)
  • roman.RomanNumeral.isNeapolitan() (MG)

Smaller features and bug fixes:

  • midi.realtime.StreamPlayer now allows for non-blocking playing and for stopping at various points. (antran22)
  • If scratch/temp directory is not writable or does not exist, use backup directories (JTW + Tanchihpin0517 )
  • Use subprocess.run() for launching external tools (JTW)
  • Deprecated method Environment.launch() is removed. (JTW)
  • MusicXML reader selection improved, especially on Windows (MSC)
  • Refactor of the musicxml subpackage for smaller files and more expandability (MSC)
  • Default readers set for Unix (Thomas Wilson).
  • RomanNumeral parsing improvements, esp. for chords like V7b5. (MSC)
  • testing is moved to Github Actions for faster responses. Thanks to Travis-CI for years of support (MSC)
  • works on Python 3.9 -- v6 is likely the last version to support py 3.6. (MSC)
  • Instruments outside of voices are retained when making measures (JTW)
  • all tests pass on Windows for windows developers. (JTW)
  • better installation on conda-forge w/ a webcolors change (JTW)
  • unmeasured scores export to MusicXML better (JTW)
  • MIDI instruments no longer get incorrect durations (JTW)
  • MIDI pitch bends are easier to understand (JTW)
  • Improved tuplet brackets when number is not shown (JTW)
  • Coverage improved (MSC + JTW)
  • Better commonName for 0, 1, 2 note chords, and microtonal chords (MSC)
  • .show('scala') works on more scales. (JTW)
  • More XML Chord symbols import (JTW)
  • Fixes for aadd6 and other chord symbols where the name of the note ("A") is also present in the modifier ("Add") (JTW)
  • Chord.quality returns "other" for C C# E G (MG)
  • An empty degree-alter now matches MusicXML spec (JTW)
  • ABC and MIDI parsing cleanups to make it easier for developers to extend (MSC)
  • Very old musicxml files with empty "tie" elements parse better. (JTW)
  • Improved handling of omitted pitches in RomanNumerals (JTW)
  • instrument.deduplicate() removes duplicate instruments at the same offset in a stream (JTW)
  • Repeat endings with no number displayed now export to musicxml properly (JTW)
  • Several routines such as findGaps were leaving Streams in corrupt states -- fixed (MSC)
  • partitionByInstrument() no longer leaves instruments with non-zero durations (MSC)
  • MuseData reading works properly on zip files created on an OS with different line breaks (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

[November 18, 2020 01:34 am] « » [music21]

 Music21 version 6.3 has been released. Biggest new feature is compatibility with macOS 11.0 Big Sur, whose numbering system change broke music21. Major bug of corpus.search() on Windows not working should be fixed also. Chordify users get a nice upgrade also.

Update with

pip install --upgrade music21

This is primarily a bug fix release, so let's list the major bugs squashed first:

Bug fixes

  • Music21 gets the proper mac version and runs in Big Sur (thanks Daniel Fürst)
  • corpus.search() should work on PC now. Sharing music21 scores that have been frozen and thawed should also work across Mac and PC.
  • ChordSymbols preserve root and bass (thanks to Jacob Tayler Walls = JTW for this and so much else in this release!)
  • Instrument names that cannot be decoded from MIDI do not crash MIDI parsing (JTW)
  • Audio searches and other searches on empty streams are improved. (JTW)
  • Non existent user scratch directory does not raise major bugs any more (David Garfinkle and JTW)
  • New location for System/Preview on macOS since Catalina and musescore on Windows (MSC + JTW)
  • remove() now searches endElements as well.
  • Corrected octaves on pitches derived in IntervalNetwork.nextPitch() (JTW) -- should fix some weird scale pitch octaves.
  • TextExpressions now have correct offsets when derived from a tempo indication or coda (JTW)
  • MIDI files parsed multiple times with different quantization settings work properly (JTW)
  • MIDI files with zero-length notes now create zero-length GraceNotes and not 1.0 length notes in music21 (JTW)
  • All tests pass in Python 3.8 (now on to 3.9!)
  • Beethoven Opus 59 no 3 mvmt 4 contained all 4 movements in it. Now it only contains movement 4.
  • MIDI's matchedNoteOff was not working properly. Works now (Thanks SunWoong KIM)
  • If two keys had the same likelihood in probe-tone analysis then only one appeared in .alterateInterpretations. Now there will always be a 23-element list. (ZM-J + JTW)
  • C-version of Python Levenshtein was sometimes not being called even if installed. This will greatly speed up similarity searching.
  • Harmony.addChordStepModification gets an updatePitches=True attribute that will immediately apply the chordStepModification to the computed pitches. The default of False remains for now, but will become True in music21 v.7.

Improvements:

  • Chordify and Verticality.makeChords gets a new keyword attribute "copyPitches=False" which makes it so that the original pitches (and not deepcopies) from the score appear in the chordified score. This can make it MUCH easier to see which pitches in a chordified score relate to the pitches in the original. However, they are identical objects, so changing one later will change the other. Default behavior is unchanged.
  • Repeats play back properly in MIDI (JTW)
  • Improved Docs (configuration instructions, typos, examples) (many people but especially JTW)
  • Much better typing all around for developers
  • math.log2 used instead of math.log(x, 2) for no more floating point confusion in many quarterLengths (JTW)
  • Braille keeps its debugging information in Note.editorial instead of custom attributes (backwards incompatible change, but okay)
  • Braille/runAllBrailleTests improved for non-sighted developers.
  • Incomplete 7th/9th/11th chords find roots better (JTW)
  • Legacy code for Python 3.5 removed (JTW)
  • Augmented sixth RomanNumerals work w/o needing a key. Also work with secondary numerals (JTW)
  • Bach chorales sort by BWV as a number rather than a string (JTW)
  • Beethoven quartets from Project Gutenberg had hidden voices w/ incorrect durations to show playback of trills, etc. Those voices have been removed. Speeds up the parsing of those pieces greatly, and gives better feature extractions. Affected pieces are opus 59.1.3, 59.1.4, 59.2.1, 59.2.2, 59.3.2, 59.3.3, 59.3.4, and opus 133.
  • Improvements to instrument name lookups (Thanks Mark Gotham)
  • Unnecessary list comprehensions are removed.
  • For running tests, missing optional modules and Lilypond. will cause import errors.
  • ABC module has been partially cleaned up, and made easier for developers to hack new ABC extensions to.

Changes:

as this is a 6.X release, we have tried to keep backwards incompatible changes to a bare minimum, but a few obscure cases are changed:

  • .seconds.beat.beatStrength on notes without a TimeSignature or MetronomeMark context now return nan instead of raising an exception.  .beatStr returns the string "nan". Python 3.8's mock methods iterate through all properties before setting up the mocked object and properties that might raise exceptions cause problems. This seems like a good direction to go in, so please expect that all property getters will switch to never raising an exception but giving nan or another failure indicator in the future.
  • KrumhanslSchmucker and KrumhanslKessler probe tone analysis are now identical. The difference before was probably a typo. They are now synonyms for each other.

Thanks always to the Seaver Institute, the National Endowment for the Humanities, and the School of Humanities, Arts, and Social Sciences and the Music and Theater Arts Section of MIT for their support in making music21 possible. And can we all give applause to Jacob Tayler Walls for all the great work done on this release!

[September 1, 2020 00:45 am] « » [music21]

Music21 v6 is OUT as v6.1.0! This represents over 500 commits over the past 14 months since v5.7 was released.

Many thanks to Jacob Tyler Walls (JTW below) who made so many contributions to the v6 branch, both big and small. Mad props and round of applause!

v6 fully supports Python 3.8 and removes support for Python 3.5. v6 will be the last major release to support Python 3.6 and we will work on Python 3.9 support immediately.

As with all new v.X releases of music21 there are improvements and some backwards incompatible changes (not too many)

In no particular order, here are the things to look for in the new music21 v6:

  • Type hints throughout music21 -- when you program with a sophisticated IDE you will be able to see what is returned and required as attributes in much of music21.

  • music21 is no longer packaged with external modules; these will be installed when installing music21 via pip (otherwise run pip install -r requirements.txt). Speed and security improvements come with this.

  • converter.parse('file.mid', quantizePost=False) will let you load in a MIDI file without any quantizing. (Thanks JTW)

  • Lots more values cached = faster music21; RomanNumerals in particular are over an order of magnitude faster, and Chords are faster too. If you ever have a problem, all Music21Objects have a .clearCache() function. Just add @cacheMethod as a decorator to a method and it will use the caching routine.

  • Intervals have been rewritten to use properties entirely. So whatever happens to an Interval, its semiSimpleNiceName (to take one of dozens of examples) will always be up to date. Intervals use Specifiers that are enums like interval. Specifier.PERFECTinstead of inscrutable numbers. (those inscrutable numbers still work though) Specifiers are more than just standard enums -- they can invert themselves, do semitonesAboveMajor() etc. Interval geeks rejoice.

  • Intervals given a noteStart and a name will generate noteEnd automagically. They also get transposePitch() improvements along the way.

  • KeySignature gets transposePitchFromC() which takes a pitch in C major and returns the pitch in the same scale degree in this key..

  • Voices with gaps in them work way better in MusicXML. Repeat endings with multiple numbers like 1,2 r/t with musicxml (JTW)

  • TSV files which encode harmonic analysis can now be parsed (Thanks Mark Gotham)

  • Humdrum harm spines parse now, giving another way of encoding harmonic analysis. (Thanks Néstor Nápoles López)

  • MIDI refactor: easier to subclass and extend and with many docs -- keeps a clear distinction between strings and bytes. MIDI values are all Enum classes (but IntEnums so they compare well with pure numbers)

  • StripTies works much better thanks to JTW -- and does not filter out non-Notes anymore (technically an incompatibility, but really a bug fix). Voices, etc. don't faze .stripTies() any more. Stream.voicesToParts() also preserves more elements. Chords with some notes tied and some don't no longer get merged. Note that stripTies retainContainers defaults to True now, because getting the opposite behavior is as easy as a .flat

  • Internal but important: lots of parts of music21 code that used abbreviations now spell out the whole word. This is important for our friends using screen readers. While music21 will (for historical/compatibility reasons) still use camelCase for all method names, attribute names, etc., internal variables may now use underscore_case which helps with screen readers.

  • Stream().write('mxl') will write compressed musicxml (JTW). Or write('...', format='musicxml', compress=True)

  • Improvements to VoiceLeadingQuartets (thanks Ryaan Ahmed), including finding parallel intervals with octave displacement. voiceCrossing and voiceOverlap detection.

  • Substantial improvements to RomanText: see https://dmitri.mycpanel.princeton.edu/romantext.pdf

  • RomanNumerals can specify how they represent ^6 and ^7 in minor with sixthMinor and seventhMinor keywords)

  • OMR fixers can recognize Turns and other ornaments. More merging here to come. Thanks Janelle Sands!

  • Substantial improvements to beaming routines and tests (thanks Almog Cohen!)

  • Keys now have .deriveByDegree() like Scales, so "What minor key has scale degree 3 as B-flat?" can easily be answered.

  • Improvements to dotted tuplets (Almog Cohen)

  • Chord.name/fullName now gives better names for common chords like Major/Minor triads -- no longer relies entirely on chord.tables. But even there many improvements and spelling corrections.

  • Chords expose .notes to get at the notes that make up a chord, in a different way than Chord[0] or for n in Chord -- I'm still an old Perl guy, sometimes There's More Than One Way to Do It, and this way makes some things conceptually much easier and faster.

  • More Bach Chorale fixes from Doctor Schmidt (thanks!)

  • Stream.replace(recurse=True) finally works!

  • StringIndication, FretIndication work in musicxml (thanks Peter Mitrano)

  • For those who are adventurous -- intervalNetworks are now exposed on scales.

  • prebase.ProtoM21Object -- an idea ported back from music21j: nearly every object in music21, including all Music21Objects, inherits from this super-lightweight base class which allows for querying classes and giving consistent representations. It makes working in music21 a lot more fun.

Incompatible Changes

  • Stream filters now return a new StreamIterator. So old code like:
s = stream.Stream()
sIter = s.iter
sIter.getElementsByClass('Chord')
list(sIter)

should now be written as:

s = stream.Stream()
sIter = s.iter
sIter2 = sIter.getElementsByClass('Chord')
list(sIter2)

For most people using filters within a for-loop, nothing will appear to have changed.

  • if element in stream now only returns True if the element is actually in the Stream, not if element is equal to something in the Stream. This is not normal Python behavior for __contains__ but it is something music21 users have counted on for a decade, and now it is assured.

  • MIDI has been completely refactored, so if you are mucking with MIDI internals, it's going to be completely different. If you're just using converter.parse and .write('midi') it won't have changed much.

Also

  • Setting a pitch's accidental to a number is deprecated and to be removed soon. use b = pitch.Pitch('B4'); b.accidental = pitch.Accidental(-1).
  • some long deprecated functions removed, such as Stream.restoreActiveSites, Stream. _yieldReverseUpwardsSearch, common.standardDeviation (use statistics.stdev instead).
  • Chord sort methods no longer return the chord itself if inPlace=True
  • interval.convertSemitoneToSpecifierGenericMicrotone, convertSemitoneToSpecifierGeneric now return a Specifier Enum as their first value
  • Spelling corrections that are technically incompatible: Interval.perfectable replaces typo Interval.prefectable. Appoggiatura is spelled correctly with two-gs everywhere it's used (JTW)
  • stripTies(retainContainers=True) is now the default.
  • Half-diminished chords have ø7 etc. as their default representation.
  • MIDI.intsToHexString has become MIDI.intsToHexBytes which does what is says it does.

Small Changes/Bugs squashed:

  • A malformed spanner in musicxml will no longer crash parsing.
  • Tuplets are equal if their durations are equal. Better docs for duration equality.
  • contextSitesnextprevious, and getContextByClass have a priorityTargetOnly or activeSiteOnly keyword for searching activeSite only. Speed!
  • From music21.X import * works much more reliably.
  • Bugs fixed in feature extraction of keys.
  • serial allows "P" or "T" to be used for transpositions
  • Tone-Rows give their row in the repr.
  • Historical tone-rows no longer have Row in their name. For instance: serial.getHistoricalRowByName('SchoenbergOp37').matrix() -- the old form still works though.
  • Feature extraction on empty streams (or ones that don't have instruments or something else) works properly (JTW)
  • Feature output formats can set .ext directly, in case you need a different extension.
  • viio7 can be specified as vii07
  • Interval: reverse=True works properly
  • subprocess.run is used instead of os.system for PNG generation. Thanks Uğur Güney. Fixes using musescore with music21 in Jupyter when spaces appear in filenames. (also thanks to Frank Zalkow)
  • Better representation for many objects
  • Error handling for incorrect chord abbreviation is improved. Thanks Vikram Natarajan
  • Librettists and lyricists can be searched in metadata.  .age() works properly for living composers.
  • MIDI plays back properly in Jupyter again BUT also does not add a delay when writing out a file.
  • Voice numbers in generated musicxml are now low numbers
  • pitch.Accidental gets . setAttributeIndependently() in case you want something to look like a flat but only alter 0.8 semitones. (This appeared in v.5 at some point but was never announced)
  • Note gets a pitchChanged() method which is called by its attached pitch anytime it changes so that caches can be used. Pitch gets an informClient() method which is called anytime the pitch itself changes. There is something similar in Chords too. This squashes a lot of bugs where pitches were changing but notes/chords/scales/etc. did not act like they had changed.
  • makeAccidentals works properly in Voices (JTW)
  • MIDI parsing gets more instrument objects from more places (JTW)
  • zero-length objects at the end of streams were being ignored by makeNotation (JTW)
  • Show formats: MuseScore 3.5 compatibility. (JTW). Preview is found by default on macOS Catalina/Big Sur -- still works for older OSes. No more 'is your doc > 999 pages?' bugs!
  • Some Neo-Riemannian docs weren't showing (thanks Adam Spiers)
  • Tone profiles for key analysis have been corrected. (thanks Micah Walter)
  • scaleDegreeWithAlteration on Augmented 6th chords works.
  • .musicxml is fully recognized as a suffix.
  • Improvements to analysis.windowed (thanks Sandro Luck)
  • RepeatExpander now does nothing on a score with no repeats. Before, it crashed.
  • Sousa example couldn't show before (thanks David H. Gutteridge)
  • Verticality.removeVerticalDissonances now works (also thanks to Gutteridge)
  • Z-relation for 5Z37 (5Z17) was incorrect (thanks Rodrigo Balthar Furman for spotting this)
  • Power-users who subclass Stream to be standard storage variants: Stream().coreSelfActiveSite(el) allows for subclassing what happens when an element should normally have its activeSite set to the stream.
  • Lilypond output with UTF-8 works. Grace notes no longer crash Lilypond. Now that there is a 64-bit binary Mac version of Lilypond, it will not be removed from music21.
  • RomanNumerals compare with each other. __eq__ logically defined.
  • Modest performance improvements in sorting (Thanks Alexander Morgan)
  • Documentation and test improvements and a few bugs squashed in ABC parsing.
  • f-strings used throughout music21 allowing for more detailed error messages and many bugs to be detected and removed.

Deprecations

  • interval.Interval.convertSpecifier() deprecated. use parseSpecifier instead.
  • Humdrum parseData() and parseFile() are deprecated. use the general converter.parse() instead.
  • .editorial.misc is deprecated, just stick whatever you want on the .editorial object itself.

Gratitude

As always, I want to thank MIT, the NEH, and the Seaver Institute for supporting music21 over the years along with the community of developers who use and give back to music21.

[December 28, 2019 10:53 am] « » [music21]
Music21 v5.7.2 has been released.

This release adds basic support for running music21 v5 on Python 3.8 — the full test suite does not pass on py 3.8 but the differences there appear to be cosmetic.

If you are using Python 3.8 run:

pip install --upgrade music21

For older stories visit the Prolatio (general items) or music21 (computational musicology) blogs.

Michael Scott Asato Cuthbert (cuthbert [at] mit.edu) is Associate Professor of Music at M.I.T.

Cuthbert received his A.B. summa cum laude, A.M. and Ph.D. degrees from Harvard University. He spent 2004-05 at the American Academy as a Rome Prize winner in Medieval Studies, 2009-10 as Fellow at Harvard's Villa I Tatti Center for Italian Renaissance Studies in Florence, and in 2012–13 was a Fellow at the Radcliffe Institute in 2012-13. Prior to coming to MIT, Cuthbert was Visiting Assistant Professor on the faculties of Smith and Mount Holyoke Colleges. His teaching includes early music, music since 1900, computational musicology, and music theory.

Cuthbert has worked extensively on computer-aided musical analysis, fourteenth-century music, and the music of the past forty years. He is creator and principal investigator of the music21 project. He has lectured and published on fragments and palimpsests of the late Middle Ages, set analysis of Sub-Saharan African Rhythm, Minimalism, and the music of John Zorn.

Cuthbert is writing a book on Italian sacred music from the arrival of the Black Death to the end of the Great Schism.

Download what is almost certainly an out-of-date C.V. here (last modified June 2012)

2010
Changing Musical Time in the Renaissance (and Today), for Festschrift Joseph Connors (forthcoming)

Bologna Q15: the making and remaking of a musical manuscript, review for Notes 66.3 (March), pp. 656-60.

2009
Ars Nova: French and Italian Music in the Fourteenth Century, edited volume with John L. Nádas (Music in the Medieval World Reference Series vol. 6). London: Ashgate. Reviewed by Gary Towne, The Medieval Review, February 2010.

"Palimpsests, Sketches, and Extracts: The Organization and Compositions of Seville 5-2-25," L’Ars Nova Italiana del Trecento 7, pp. 57–78.

Der Mensural Codex St. Emmeram: Faksimile der Handschift Clm 14274 der Bayerischen Staatsbibliothek München, review for Notes 65.4 (June), pp. 252–4.

2008
"A New Trecento Source of a French Ballade (Je voy mon cuer)," in Golden Muse: The Loeb Music Library at 50. Harvard Library Bulletin, new series 18, pp. 77–81.

2007
"Esperance and the French Song in Foreign Sources," Studi Musicali 36.1, pp. 1–19.

2006
"Trecento Fragments and Polyphony Beyond the Codex", Ph.D. Dissertation, Harvard University (unpublished).

"Generalized Set Analysis and Sub-Saharan African Rhythm? Evaluating and Expanding the Theories of Willie Anku," Journal of New Music Research (formerly Interface) 35.3, pp. 211–19. [.pdf]

2005
"Zacara’s D’amor Languire and Strategies for Borrowing in the Early Fifteenth-Century Italian Mass," in Antonio Zacara da Teramo e il suo tempo, edited by Francesco Zimei. Lucca: LIM, pp. 337–57 and plates 10–13.

2001
"Free Improvisation: John Zorn and the Construction of Jewish Identity through Music," in Studies in Jewish Musical Traditions, edited by Kay Kaufman Shelemay (Cambridge, Mass.: Harvard College Library). pp. 1-31. [.pdf]

Creative Commons License Unless otherwise mentioned, the writings, compositions and recordings on this site are licensed under a Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 United States License.

Copyright 2010-11, Michael Scott Asato Cuthbert. Web design by M.S.A.C.