Implementing harmonic analysis

• Mar 19, 2017 - 03:23

I would like to start looking into implementing harmonic (roman numeral) analysis in MuseScore.
I propose the user interaction be similar to entering figured bass or chords, but with a special syntax to allow for maximum customization and to address the problem of various standards. The syntax would be something like the following:


where A, B, C, and D represent arbitrary text that stacks vertically to the right of the number. This syntax allows for unlimited stacking, but I am content with a maximum of three. Each text section would use the regular ASCII-to-music substitutions MuseScore uses in other modes (b/h/# turn into a flat/natural/sharp signs, 0 turns into a half-diminished sign, etc.)

For example, the syntax ii0[6][5] would turn into the following:
If desired, a field may be left blank, so bVII[][2] would result in this:
Additional text may follow the brackets to allow for secondary chords, like V[7]/V:
Additional style settings should be added to control the size and spacing of the stacked text, just as figured bass does. The initial implementation will probably not include pivot chord symbols, though this would be a logical next step. Until then, a line with positive and negative hook settings will suffice and reflow properly.


I think that's possible.
I even guess that it can be done using the ".xml" files that are used for the current chord symbols.
I just see a few points that can cause problems with formatting.
The code in the first example "ii0 [6] [5]" could be: "ii0 [6,5]". We can understand that they are superimposed.
The other example "bVII [] [2]" should be: "bVII [0,2]" or "bVII [,2]
The last example "V[7]/V" is probably better if it is "V7/V"

Class		Type		Sample and Expl.
Accidental:	b #	 	(bII) // accidental first (if exist)
Quality:	Romen Numeral	(V, ii) Uppercase for Major, lovercase for minor)
Modifier:	text|acci.|num.	(7,sus4,b5, add9) // text | accidental | number 
Voicing:	[,]		([5] for top, [6,4] for top&bottom, [,2] for bottom) // position
Relevance:	/ 		(V7/V, V7/ii)

In reply to by Jester Musician

Are there other things that can be used?
Is there something missing or wrong, according to the list below?
What is the most complex and extreme example that can be written?

Class		Type		Sample and Expl.
Accidental:	b #	 	(bII) // accidental first (if exist)
Quality:	Romen Numeral	(V, ii) Uppercase for Major, lovercase for minor)
Modifier:	text|acci.|num.	(7,sus4,b5, add9) // text | accidental | number 
Voicing:	[acci|num|,]	([5] top; [6,4] top-bottom; [,2] bottom; [#6,4,3] top to bottom) // should include accidentals.
Relevance:	/ 		(V7/V, V7/ii)

Because if we want it to work properly, it's best to discuss ideas here.

I think this is a great idea...I would think the jazz chords framework can be modified to accept and parse numeral notation. But note I don't think all the [] are necessary. For instance when we type C69, musescore knows to put the 6 over the 9 because it adheres to a certain pattern. I haven't thought this through thoroughly enough to, though.

In reply to by Ziya Mete Demircan

In writing this out, it should not always be necessary to include brackets. For example, I you were to write


it is obvious what is meant, so the brackets are unnecessary in that instance. The same is true for


There is no ambiguity involved with a parser. Your example where you wrote

bVII [,2]

should be parsed the same as if a user decided to write

bVII [0,2]
bVII [] [2]

This would be a matter of personal taste in entering the chords and both should be parsed the same way. I suggest that

bVII02 or bVII 0 2

would cause ambiguity because it could mean bVII 1/2 augmented or bVII with a 2 subscripted but no superscript. This rule would need to be spelled out for the parser so the user would know what to expect.

The pseudocode you wrote explains the general idea of parsing these strings. The parse would look first for an accidental, if none is found it would then look for a chord identifier by looking for a valid roman numeral including i and v or I and V. Once it ran out of these it would have to determine if the next item is an accidental, modifier or a voicing. Once it runs into a / it knows it is looking for a relevant chord. If after all of this parsing, it is unclear what to do with a character, it should leave the original text as it currently does with a bad chord.

In reply to by mike320

"it should not always be necessary to include brackets"

Right. So maybe it would be nice to design it such that it is able to parse most any chords without brackets, but then use brackets to handle cases that are ambiguous.

i.e. optimize for the common case.

In reply to by mike320

if the "space-character" does not create a problem, it may not be necessary to use a bracket.
Entering a space after them solves this problem.

chord  : V6 
voicing: V 6

voicing : V6 6

If the space character is going to the next note (as in chords, lyrics), we lose this option..
I always think of "space character is not allowed".

In reply to by ericfontainejazz

If we do not use square brackets (or something similar * 1): * 2
How will this script know that the digit entered is modifier or voicing?
Any idea?

* 1: Covering, enclosing.
* 2: The parentheses have other meanings, "/" character is used in another job, "- / + / _" characters are misunderstood. Space is already in use. "&" is problematic. "#" has alternate meaning.

The chord script doesn't understand "69". **1
XML contains a special entry for its alternatives.

    render: m:1:-2 s6 m:-2.5:0 s/ m:-2:7 s9 m:0:-5

    render: s6 m:0:-&mod; s, m:0:&mod; s9

**1 In fact, 6/9 is a completely unnecessary chord for Jazz. If the pianist sees a bare 'C' chord, he thinks it is "e, a, d, g" (3,6,9,5), or similar.
But, It has to be specified especially in pop chords.

Isn't this expression approach wrong for MuseScore? It sounds like you guys are homing in on a perfectly fine language, with brackets and commas, etc., for defining these chords. But this seems more like the LilyPond style.

MuseScore has a gui, wysiwyg, interface, and it seems to me that you could and should use that approach. I'm not knowledgeable enough to take a shot at it. But I think that the user who knows what she wants to build, could choose superscript, figured base, etc., and instantiate them as needed. What do you think?

In reply to by MikeN

I agree. Just like chord symbols and figured bass intelligently parse the closest thing to "natural language," so should roman numerals. I'd go so far as to suggest that simple line breaks should be used to stack numbers. So, if the user enters


then upon exiting text edit mode it should be rendered as


In reply to by Ziya Mete Demircan

I personally would prefer if "Enter" was reserved for creating a chord underneath the current chord, such that they layout automatically nicely on different vertical positions but same horizontal position with out having to manually move them...which is used for instance when writing optional alternative chords:


But maybe there is a better way to handle such cases.

Aside: there is still a feature request that I've been making to implement for a while which is to allow for stacked poly chords: ...I intended to use underscore '_' to delineate the horizontal line between the upper and lower chord. Of course that won't conflict with what you guys are suggesting with using "Enter" here.

In reply to by ericfontainejazz

I was just thinking, currently chord entry will wait until the entire string is entered before rendering. I'm imagining now if someone is typing in voices and pressing return between each voice, then it would be great if musescore renders it at every step of the way, instead of seeing a confusing multi-line text box.

And I'm also realizing that the parser would know that the user is inputting a Roman numeral by the time that the first Roman numeral is typed, so I guess my concern about reserving enter for stacking jazz chords is less of a problem, since Enter could only be interpreted as adding additional voicings only if currently inputting a Roman numeral chord.

In reply to by MikeN

On the contrary, I think this is a very good idea.
Teachers can use MuseScore for harmonic analysis.
This increases the number of users. Because the teachers have students :)
for difficulty of writing:
Yes, users can format what they want.
But they can not do it as shown here. For example: three figures on top of each other. a superscript, a small number in the middle and a subscript are in the same place.

Besides, if you do not need it, OK. So it does not force you to use it.
But it is a blessing to, those who need it.

If you also want to do this with the GUI, then you need to open an interface for each analysis code:

The minus of this interface is: Whenever you want to change a code, you have to right click and select "edit" option. (Such as guitar chord diagrams)

Attachment Size
HA-Interface-01m.png 27.35 KB

I cleaned my mind and I went another way.
What if the user enters the chord shape and position as a shortcut alongside the Roman Numeral?
(Additional symbols can be entered after this. V7b/ii)
V7 == root position:

V7b == V7 first inversion.

V7c == V7 second inversion.

V7d == V7 fourth inversion.
V73rdinvA.png or V73rdinvB.png

A wider example:
V7d/ii :

Non case sensitive....
for minors: iimc same as IImc == minor 3rd inversion.
v7b9/v7 same as V7b9/V7
ii0/v7 same as IIm7b5/V7

Just like chords. Only the position (inversion shortcut = b, c, d, e) is added.

When we press the space key to move to the next note, our previous input is being processed.
And it's written like we talked before:


Later, the user can double-click on it and make changes. (As in figured bass)

I'd love to see RNA as well! A few points:

- I'd especially love the option for a font that includes the horizontal bars above and below capital V. These are not technically needed in typeset scores with serif fonts, but they are standard in handwritten analysis, and that's important for education use since students will be writing in their own analyses a lot and I'd like to model good practice in my examples.

- I prefer not to force people to learn a complicated language but rather try to parse a plain simple text representation. I expect to type V65/ii and have it rendered pretty without my needing to do anything special. Just like chord symbols and figured bass.

- Chord symbols currently wait until the end to render because that's the way it was done back when chord symbols had be matched using exact strings and we couldn't render anything without an exact match. Now that we actually parse the chord, it's probably feasible to render chords symbols on the fly. I don't remember if I actually tried this while implementing the parser, but I suspect it might be a really simple change. Could well be the same for RNA.

In reply to by ericfontainejazz

Feel free to try implementing this. We are already parsing the chord on each keystroke in Harmony::edit(). In principle, we just need to also do a "render()" operation (which is what does the fancy formatting - turning "b" into flat signs, possibly superscripting things, etc), perhaps a "layout()" too, then modify the draw() function to go ahead and use the rendered chord rather than the plain text even when in edit mode (currently, we fall back on plain text while editing, or if the "render list" is empty). We'd probably have to implement our own drawing for the cursor, I guess that could be the trickiest part.

I'd love to see RNA implemented in Musescore! (I'm actually learning Lilypond right now since Musescore can't.) For those of you planning it out don't forget to allow a superscript diminished/half-diminished/augmented symbol before the stacked arabic numerals

In reply to by liph

As a result of discussions with lasconic and others, I've come to believe the "right" solution is to convince the SMuFL folks to add RNA symbols to the standard, then hopefully the next version of BravuraText will include the necessary symbols right out of the box. Really, theres no reaosn we should have have to reinvent this wheel ourselves - it's just text.

That said, if someone wanted to take the initiative and just create a font with the necessary characters and share it and then maybe propose it to Daniel & co with SMuFL, that would be awesome.

In reply to by Marc Sabatella

FWIW, I did check with Daniel at Steinberg and he said there are no current plans to introduce such symbols, but he welcomes proposals. So, I guess we do get to invent this wheel if we want it to happen, but at least once it is part of the standard then potentially other fonts will also adopt it. Anyone want to take a crack at designin what such a font would look like? I still think a simple text font that uses positioning cleverly is a better choice than actually implementing some complex RNA rendering algorithms.

In reply to by ffulvio1

Yes, double flats and double sharps are entered just by typing "b" or "#" twice ("x" is used for other purposes, but the "##" does convert to the double sharp symbol).

Looks like Piston is doing things backwards from the more common way, though, putting accidentals after the number instead of before. The Campania font isn't designed to do things that way but sort of can. As you see, it doesn't handle multiple accidentals. Really, that's more like figured bass notation than how Roman numeral notation is normally used. So you might consider entering those symbols that way. Or just entering each of the individual numbers / accidental pairs separately and positioning them manually.

Do you still have an unanswered question? Please log in first to post your question.