The gray keys in between: a makam practice tool built on open data

I have been playing Turkish / Ottoman music for a while, and practising it is annoying. You want to loop four bars, slow them down, and have a metronome that actually clicks the rhythm you are playing. Normal notation software gets the notes wrong before you even start, because the notes are not on the piano.
So I built a small practice tool: sinan.pl/makam-deste. Pick a piece, click a passage, loop it, pick a tempo, play along. It runs entirely in the browser, and it exists mostly because someone else did the hard part and published 2,200 scores as open data.
Here is what is in it, and what got in the way.
First: why microtonal music is different
Easiest with a piano. White keys, black keys, twelve per octave, all evenly spaced. Makam music needs the gray keys in between.
- Western tuning splits the octave into 12 equal steps. Makam theory splits it into 53, called komas. One koma is
1200/53 ≈ 22.6cents, so roughly a ninth of a whole tone. - These are not “quarter tones”. The system in use (Arel-Ezgi-Uzdilek, or AEU) has four accidental sizes: 1, 4, 5 and 8 komas. A bakiye flat (4) and a küçük mücennep flat (5) are different notes, written with different symbols.
- A famous example: the second degree of makam Uşşak sits one koma below B natural. Not B, not B flat. Something in between that a piano simply cannot produce.
- A makam is also more than a scale. It carries a seyir, a typical direction of travel, so two makams can share the same notes and still be different makams.
- Rhythm works the same way. A usul is a cycle of named strokes (düm, tek, teke), and cycles run from 2 counts up to 120. Not every count gets a stroke, which is exactly why a flat click track is useless.
There is also ahenk: scores are written in one fixed transposition, and what actually sounds depends on which ney size the ensemble tuned to. The page never moves, the whole group does.
Here is some Uşşak in the app. That key signature is not a normal flat.

The open data
The whole thing rests on SymbTr, a symbolic collection of Turkish makam music from the CompMusic project at UPF. It is genuinely impressive:
- 2,200 pieces, 155 makams, 88 usuls, 56 forms
- around 865,000 notes, about 80 hours of nominal playback
- released under CC BY-NC-SA 4.0, with a paper to cite
It ships in five formats: txt, MusicXML, MIDI, mu2 and PDF. Here is the first trap, and it took me a while to notice.
Only the txt format keeps the microtones. The MusicXML flattens everything down to normal and quarter-tone accidentals:
<alter>-1</alter> <accidental>flat</accidental>
<alter>-0.5</alter> <accidental>quarter-flat</accidental>That is lossy in the one dimension the music is about. The txt columns give exact pitch in komas, so a 4-koma flat stays distinct from a 5-koma flat instead of both becoming “flat”. If you build on the convenient format, you build the wrong thing.
Other open pieces I leaned on:
- Verovio for engraving. It renders MEI to SVG in the browser, is LGPL, and ships the Bravura font (SIL OFL) which happens to include the AEU accidental glyphs at
U+E440–U+E447. That range existing in a standard font is the only reason the notation looks correct. - Dunya fixtures, also from CompMusic, to turn ASCII slugs back into proper Turkish names for all 155 makams, 88 usuls and 56 forms.
- Netlify for hosting, since the whole app is static.
How it fits together

A Python package parses the txt and writes two things per score: an MEI file for the notation, and a JSON file for playback. The browser loads both. There is no backend, no database and no audio files.
koma.pyis the pitch model.freq = 440 · 2^((koma − 305) / 53)is basically the whole thing.symbtr.pyparses the txt into notes, measures, usul changes and section names.mei.pywrites the notation: tuplets, ties across barlines, beaming, one explicit glyph per accidental.player.jsis a Web Audio scheduler,selection.jshandles clicking passages on the score, andusul-patterns.jsholds the metronome patterns.
Roughly 5,800 lines, and the Python half has no dependencies at all.
The interesting problems
Which pitch do you trust? The txt gives pitch twice: a raw 53-tone reading and an AEU reading. They disagree on about 8% of notes, by one koma. I started from the raw one, which is impossible to notate honestly, because there is no AEU symbol for a 2-koma alteration. 65,568 notes quietly fell back to a natural and stated the wrong pitch on the page. Now both the notation and the sound come from the AEU columns, so what you hear is what you see.
Repeats. A saz semâîsi has four hanes and repeats the same teslim after each one. A linear rendering prints that teslim four times, which no printed edition ever does. So the app folds it: printed once, marked with a segno, and every block that returns ends with D.S. al Teslim. That removed 10,157 printed bars across 364 scores.

Folding breaks a nice assumption though. A printed bar no longer means one stretch of time. Selecting the teslim now drills all four occurrences, and the label says so.

The metronome is where the data runs out. SymbTr gives you the usul name and its meter, but not the strokes. And the strokes are the whole point:
Sengin semâî 6/8: Dü-üm Tek Tek Düm Tek
2 1 1 1 1
Six counts, five attacks, and nothing at all on count 1. Clicking a flat six teaches the wrong thing. So I hand-authored patterns for twelve usuls from the theory literature, each citing its source, which covers 77% of the usul changes in the corpus. The remaining 22% fall back to an even grid. I deliberately did not guess the tail: a wrong stroke pattern removes attacks rather than shifting an accent, so it is both more audible and more misleading than no pattern.
Long cycles. A peşrev in Muhammes is 32 counts to the bar, and Zencîr is 120. Looping one bar there is a performance, not practice. So bars over ten counts get cut into four-count cells you can select on their own, drawn as a light dashed grid anchored to real note positions (Verovio spaces music non-linearly, so a fraction of the bar width would land in the wrong place).
No recordings. CompMusic cannot redistribute the audio for copyright reasons, so playback is synthesised. For practice that is arguably better, since you get exact microtones and any tempo without time-stretching artefacts. There are two voices: a kanûn built as a Karplus-Strong string in an AudioWorklet, and a ney built from held oscillators plus band-passed breath noise.
Titles. 199 scores have an empty title field and came out as a bare dash. The sibling mu2 file carries a header with the properly spelled Turkish title, composer and form, so that became the primary source.
Open data comes with obligations
Easy to skip, so worth saying out loud. SymbTr is CC BY-NC-SA 4.0, and publishing counts as sharing. The converted scores are adaptations rather than copies (different pitch selection, new engraving, folded repeats), which is what pulls in ShareAlike.
- BY: an About dialog credits the collection and its authors, links the licence, and lists what changed.
- SA: the derived scores go out under the same licence, stated in a
LICENSE.txt, in every score’s JSON header, and in every MEI file. - NC: the site is free, has no ads and no sponsorship. Adding any of that would break it.
One Python module owns that wording and stamps all three places, so the notice cannot drift out of sync.
What is still missing
Being honest about the gaps is part of the point:
- 22% of usul changes still get a flat grid instead of real strokes.
- The four-count grid on long bars is a reading aid, not a claim about the usul’s real internal structure.
- Grace notes (about 12,500 of them) are parsed but not played.
- Only four of the twelve named ahenks are wired up.
Wrapping up
The takeaway for me was less about music and more about data. The interesting work was not writing a player. It was deciding which column of an open dataset to believe, and noticing that the friendlier export format had quietly thrown away the only thing that mattered.
Go have a play. Search for “hicaz sazsemaisi”, click a few bars, slow it right down.
References & further reading
M. K. Karaosmanoğlu, “A Turkish makam music symbolic database for music information retrieval”, ISMIR 2012
https://github.com/MTG/SymbTr
https://compmusic.upf.edu/
https://dunya.compmusic.upf.edu/
https://www.verovio.org/
https://music-encoding.org/
https://www.smufl.org/