[HN Gopher] Xenharmlib: A music theory library that supports non...
___________________________________________________________________
Xenharmlib: A music theory library that supports non-western
harmonic systems
Author : retooth
Score : 194 points
Date : 2025-07-08 22:37 UTC (2 days ago)
(HTM) web link (xenharmlib.readthedocs.io)
(TXT) w3m dump (xenharmlib.readthedocs.io)
| ksr wrote:
| Fascinating. I'm working on many adjacent pieces myself - my name
| for this whole initiative is music-i18n because I see it as the
| equivalent of adding software layers to support world languages
| and locales - in this case musical ones.
|
| I am especially interested to hear your plans / thoughts about
| the following:
|
| - Supporting non-ET tunings
|
| - Supporting tetrachords and other scale building blocks (like
| Arabic ajnas)
|
| - Importing/exporting MusicXML
|
| - Exporting to MIDI
|
| Thanks!
| retooth wrote:
| Hi! I'll try to answer in order:
|
| 1. Just Intonation and non-linear temperaments are on the
| roadmap, but there are a couple of design problems I still have
| to figure out, mainly how to have a consistent definition of
| interval objects in regards to transposition if the distances
| between notes are uneven. It works nicely, if one uses multi-
| dimensional tunings, e.g. in a 5-Limit tuning with 3 dimensions
| every interval obtained from two notes can be applied to any
| other note as a measure of transposition distance, but once you
| reduce it to one dimension you can have two notes which form an
| interval that can not be applied to every note without reaching
| a note that is outside the temperament.
|
| 2. Tetrachords are already supported and can be easily defined
| using the scale object. There is no quartertone notation yet,
| but if you are happy with Up/Down Notation you can analyze
| arabic ajnas by using EDOTuning(24) as the base. Currently
| there is no pitch/note sequence object, so downward scale
| movement in maqams can not be properly defined, but if you are
| interested only in the harmonic qualities, scales should do.
|
| 3. MusicXML sadly does not have good support for non-12-EDO
| tunings. You can define quartertone accidentals by providing
| floats (like 0.5) as accidental values, but this gets
| increasingly difficult if you want to do anything other than
| 24-EDO. I looked into the MEI format as it supports at least
| turkish makam accidentals, but a more generalized semantic
| definition for arbitrary EDOs seems to be out of reach for the
| foreseeable future. One could however think of supporting MEI
| for a couple of tunings (like 24- or 53-EDO)
|
| 4. MIDI is also somewhat difficult. There is the MPE
| specification which allows individual note bending, however it
| is not supported by any python library as far as I can tell.
| One could try to hack something with channel pitch bends, but
| it would be limited to playing 16 notes at the same time.
|
| I am still looking for contributors, so if you are interested
| in these things, feel free to contact me ;)
| ksr wrote:
| Thanks for your answer. To me, the thrill of modeling the
| rich and vast domain of music practices across the world is a
| never-ending source of joy and discovery. To answer your
| specific points:
|
| 1. In my own similar library
| (https://github.com/infojunkie/scalextric) I decided to
| pragmatically throw an exception if the transpose method is
| called on an untransposable scale... At the moment I'm not
| trying very hard to handle all the cases of transposability -
| I'm sure there's a mathematical object like a group or ring
| to describe such cases.
|
| 2. I'll read your code to understand better how you handle
| sub-scale sequences. I would like to revisit my own approach
| to start at the dyads (sequence of 2 tones plucked from a
| given tuning) and build up longer sequences from those. I
| think this would allow to distinguish between ascending and
| descending sequences in a natural way.
|
| 3. I've spent quite a bit of time with MusicXML, and some
| time with MEI as well.. Yes, neither format has a model for
| arbitrary tunings which is a glaring gap. MusicXML does
| represent the full set of visual accidentals (including
| custom SMuFL glyphs) as well as per-note decimal pitch
| alterations that can accommodate any cent value. MEI also
| represents a reasonably complete set of accidentals although
| it's a closed set, as opposed to MusicXML's open set of
| accidentals. MEI supports a few pre-defined tunings which
| also falls short of generality. In addition, MEI does not
| support per-note pitch alterations, which makes it even
| harder to represent anything outside the tunings that it pre-
| defines.
|
| There's unfortunately little activity to update these formats
| to include general tunings. I'm having discussions in both
| communities, maybe you'd like to add your voice:
| https://github.com/music-encoding/music-encoding/issues/1167,
| https://github.com/w3c/musicxml/discussions/586.
|
| 4. I've also spent quite a bit of time on MIDI
| microtonality... There are 3 main approaches that I'm aware
| of:
|
| a. MIDI Tuning System which maps the 128 MIDI notes to
| arbitrary frequencies.
|
| b. Pitch bending which has the limitation that you mentioned
| above. MPE is essentially an organized methodology for
| reusing empty MIDI channels in a round-robin fashion for
| pitch bends and other controller effects.
|
| c. MIDI 2 supports per-note controller settings out of the
| box, thereby superseding MPE.
|
| My current focus is to create a MusicXML => MIDI conversion
| pipeline that supports arbitrary tunings, using Verovio as
| the MIDI conversion engine. I am of course "inventing" new
| MusicXML elements to represent these tunings and their
| mappings (and MEI elements too, because Verovio represents
| its own internal state based on MEI). My aim is to produce a
| MIDI version of the canonical Sagittal Example
| (https://www.sagittal.org/exmp/index.htm) from a MusicXML
| file.
| retooth wrote:
| 1. Thanks for the link. I am reading a bit of your code
| right now :) Also nice to see that it is GPL licensed too.
| In regards to intervals: What still confuses me in the
| design process is that in certain uneven tunings, (e.g.
| Pythagorean) there seems to be two approaches to naming
| intervals. One would be an "absolute" approach, where
| intervals that do not form a 5/4 ratio would not be
| considered a major third, and one "functional" approach,
| where the exact frequency ratio does not matter and the
| interval name is simply deduced from the note names (D to
| F# is a major third even tough the ratio is 81/64)
|
| 2. I'm not sure what you exactly mean by sub-scales. Imho
| the best approach in xenharmlib to define maqams from ajnas
| would be to define ajnas as interval sequences in 24-EDO
| and then concatenate them with + to a maqam interval
| sequences. Then you can use the result to define maqams on
| any note.
|
| 3. Thanks for the links. I will add something soon ;) I
| also tried my luck on the MEI Slack channel but did not
| receive any response. I think MusicXML might be a good
| format for exporting xenharmonic data, but importing from
| it is tricky. In certain temperaments the cent values have
| so many digits after the point that importing would be
| forced to apply heuristics for rounding errors :/
|
| 4. Option a) is currently the one I use, but I am somewhat
| unhappy about it, because it requires a "tacit"
| understanding between two programs of how exactly the 128
| notes are redefined (also 128 is not plenty, just think of
| turkish makam that has 53 notes per octave. That is barely
| 2 octaves in this system). My hopes are currently on MIDI
| 2.
| ksr wrote:
| 1. Regarding naming of intervals, this has confused me
| for months, until I understood (or convinced myself) that
| there are in fact 2 different things that are called
| "intervals": intervals between tuning pitches (which is
| your first example) and intervals between scale notes
| (your second example). Thinking of them as different
| things (and calling them differently) has helped me a lot
| with modeling musical objects in scalextric. For example,
| tuning intervals in different tunings (12-TET vs.
| Pythagorean) can end up having the same logical interval
| name because they are approximating the same logical
| relationship between notes even though the physical
| frequencies are different.
|
| 2. sub-scales = what you call interval sequence.
|
| If you don't mind, we can continue this conversation by
| email. Mine is in my profile on HN.
| elihu wrote:
| > There is the MPE specification which allows individual note
| bending, however it is not supported by any python library as
| far as I can tell. One could try to hack something with
| channel pitch bends, but it would be limited to playing 16
| notes at the same time.
|
| In practice, that's not usually a problem. That's a lot of
| polyphony. Technically if you're following the MPE spec, you
| only get 15 channels because one channel is reserved for
| sending commands that affect all voices at once. (Like you
| can send one pitch bend on the reserved channel and have it
| affect all 15 other channels at once. Likewise for program
| change and CC messages.)
|
| MPE is kind of a weird way to do things but it actually works
| pretty well. And one of the nice things about it is that if
| you go to the trouble to support MPE, it's a pretty easy step
| to support pre-MPE multitimbral synths -- though each one
| tends to have its own quirks that have to be worked around.
|
| I've been working on a just intonation MPE controller, and
| have gotten it to work with a bunch of old 80s-90s-2000's
| hardware synths. I've considered that it might be worthwhile
| to eventually split that code out into a separate library so
| other projects that want to use old
| Yamahas/Rolands/Korgs/E-mus etc.. in a microtonal way they
| don't have to reinvent the wheel.
| bntr wrote:
| A bit tangential, but I recently made a xenharmonic-related
| library too - focused more on the visual/harmonic space side:
|
| https://github.com/bntre/cs-rationals/blob/master/RationalsE...
|
| Demo piece: https://www.youtube.com/watch?v=y_x4vtS_I7w
| retooth wrote:
| Oh, neat :) This looks really cool. In one of the upcoming
| versions of xenharmlib I am planning to add hooks for
| visualization plugins, so structures can be rendered in
| JupyterLab. Maybe you would be interested in contributing,
| however it will take some time before JI is supported.
| bntr wrote:
| My actual question: do you use xenharmlib for composing?
|
| I assume this is your album:
| https://fabianvallon.bandcamp.com/album/a-different-path-for...
|
| Was xenharmlib used in it, or some other software?
| retooth wrote:
| Yes, I do. For the actual score composition I used Ableton, but
| xenharmlib can export SCL files to define microtonal scales,
| which then can be imported in Ableton (a lot of other DAWs and
| VSTs support this format too).
|
| For the most part however I use xenharmlib for theoretical
| aspects of music. I got interested in the "31 Equal Divisions
| per Octave" tuning a couple years ago, because of its
| psychoaccustic potentials, but thinking about chords, modes,
| notation in 31-EDO made my head hurt, so I built the library to
| help me think and answer my questions.
| max_ wrote:
| Is there a good resource to learn basic music theory?
|
| Like learn what the meaning of A B C and other letters mean?
|
| And how the come together to make actual music?
| retooth wrote:
| I often used this for reference:
| https://musictheory.pugetsound.edu/mt21c/MusicTheory.html
| max_ wrote:
| Thank you so much. This is brilliant.
| sim7c00 wrote:
| is there somethin similar in C++. this is really useful, but most
| VST etc. afaik get built in c++, i know for example JUCE
| framework to build em uses c++ so to me that seems a practical
| language for such a tool
|
| (focussing on the last bit of the article mentioning it can be
| used in digital instruments / dsp. totally agree!)
| retooth wrote:
| Since xenharmlib is written in python it is not suitable for
| real-time audio because of the latency that an interpreted
| language introduces.
|
| I think if someone was willing they could port the library to C
| or Rust rather easily, because apart from Exceptions the coding
| style is functional and stateless. AFAIK Rust has some
| libraries that provide a VST interface.
| mkesper wrote:
| Fantastic, my suggestion would be to rename to Xenharmoniclib,
| though. harmlib sounds...harmful? to me
| userbinator wrote:
| It would be a suitable name of a library for exploiting the Xen
| hypervisor.
| bhalahi wrote:
| Does this include the socialist, communist, and banana republic
| dictatorial harmonic systems?
___________________________________________________________________
(page generated 2025-07-10 23:01 UTC)