Skip to content

Repository files navigation

ChordID474plus

English | Deutsch | Español | Italiano

A plugin for MuseScore Studio 4 that reads the notes of a score and writes the chords it finds as real chord symbols (Harmony elements, not staff text) above the staff you choose. They stay transposable and playable.

The plugin dialog

Listed on musescore.org: https://musescore.org/en/project/chordid474plus

Tested with MuseScore Studio 4.7.4 (Qt 6.10, plugin API MuseScore 3.0). Unversioned QML imports and startCmd with a name exist from 4.4 on, so the file should load there as well, but only 4.7.4 has actually been tried.

Install

Download the archive from Releases and unzip it so that this file exists:

  • macOS and Linux: ~/Documents/MuseScore4/Plugins/ChordID474plus/ChordID474plus.qml
  • Windows: C:\Users\<name>\Documents\MuseScore4\Plugins\ChordID474plus\ChordID474plus.qml

Then enable ChordID474plus under Home > Plugins and call it from the Plugins menu.

What it does

Detected chords in the score

Without a selection the whole score is analysed, with a selection only the marked range. Every marked staff is listened to, the symbols go to one staff.

Setting Meaning
Grid one symbol per measure, per half measure, per beat or per eighth note
Scope triads only, with sixths and sevenths, or with extensions (9, 11, 13)
Minimum length shorter chords count as passing and are left out
Target staff where the symbols are written
Language German, English, Spanish, Italian, or follow the system
Slash chord append the bass note (C/E)
Sounding notes notes from earlier beats count while they still sound
Skip repeats the same chord is not written again
Remove existing clear old chord symbols before writing
Jazz symbols -7, Δ7, ø7, °7 instead of m7, maj7, m7b5, dim7
Dry run detect and log without touching the score

Remove symbols takes chord symbols out again, without detecting anything, in the selected range and across all staves. That is the way back when symbols ended up on the wrong staff. A run, and a removal, is one undo step each.

How it decides

For every window the plugin collects which pitch classes sound and for how long, weighting the start of the window a little higher. For all twelve possible roots it works out what role each note would play (third, fifth, seventh, extension) and how much of the sounding material that reading explains. A missing root, a missing third and a foreign bass cost points, a bass equal to the root gains them. Below an explanation rate of 0.5 nothing is written, which keeps passing passages empty.

The bass comes from the note carrying the beat, not from the lowest note in the window. Without that rule a passing note below the bass turns Abmaj7 into Abmaj7/G. Notes struck before the window count half, so a chord that is still ringing does not cover the next one.

Equal chords are then merged into blocks. A block shorter than the minimum length is dropped and its neighbours close the gap. This also carries an anticipation along: a chord played just before the beat forms one block with the chord it ties into, so its symbol sits at the anticipated position instead of on the beat after it.

The spelling of the root comes from the note as written in the score, so Eb stays Eb, otherwise from the key signature.

Languages

German, English, Spanish and Italian, all in the same file. Without an explicit choice the plugin follows the system language. No Qt translation files (.ts or .qm) are needed, which keeps the plugin a single file with no build step.

The table lives in the LANGUAGES section as strings. A new text goes in there and is fetched with tr(lang, "key").

Layout of the file

ChordID474plus/ChordID474plus.qml is the only source and has five sections:

  1. Properties and defaults
  2. ENGINE: plain music theory, no MuseScore objects
  3. LANGUAGES: the text table
  4. BRIDGE: read notes, build the grid, write symbols
  5. UI: the dialog

Traps in MuseScore Studio 4.7.4

All of these were measured with the probe in ChordID474plusProbe/, not guessed. They cost a day, so they are written down here:

  1. Set harmony.text only after attaching. Setting the text on a Harmony element that is not in the score yet quits MuseScore instantly, without a crash report. The order is cursor.add(h) and then h.text = ....
  2. Never rewind the cursor to the end of the score. cursor.rewindToTick() onto the tick behind the last measure quits MuseScore as well. Walk the measure chain curScore.firstMeasure and measure.nextMeasure instead.
  3. measure.tick is a Fraction object, not a number. The tick of the measure start is measure.firstSegment.tick, its length measure.ticks.ticks.
  4. console.log does not reach the log, console.warn and console.error do. Use warn for diagnostics.
  5. Plugin files are read once per session. After every change MuseScore has to be restarted, otherwise the old version keeps running.
  6. New plugins are inactive until an entry with a filled actions array appears in extensions/config.json in MuseScore's application support folder.

Tests

node test/run_tests.js     # 53 cases against the engine inside the QML file
node test/check_qml.js     # bracket balance and parsing of every function
node test/check_i18n.js    # completeness of the four languages

test/engine.js cuts the ENGINE section out of the QML file, so there is no second copy of the logic. The BRIDGE can only be checked inside MuseScore, since MuseScore 4 has no command line call for plugins.

test/make_runner.py builds a dialog-free variant from the same source that runs straight away, which is how the whole chain gets checked without clicking inside the dialog.

License

GNU General Public License v3, see LICENSE.

About

MuseScore Studio 4 plugin that detects the chords of a score from its notes and writes them as chord symbols

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages