RFC: working on making chord naming/chordList more consistent

Hi all,
Referencing this discussion on chord naming, I thought it would be worth having a bit of a discussion about what people want/are expecting:

Here's the source code

My first idea is to take the standard capitalised M (major) and lower case m (minor) nomenclature and apply it - I assume this has been considered though...

My proposal - taking:

elevenSharp :: Num a => [a]
m11sharp :: Num a => [a]

and changing to:

M11sharp :: Num a => [a]
m11sharp :: Num a => [a]

@yaxu does haskell allow/handle case sensitive naming in this context?

Second idea, there's often multiple ways to define a chord quality/extensions - ideally we could create the verbose version of the chord as the actual pattern, then have the common shorthand variations defined as pointers to the verbose named pattern - is this possible?

example in pseudo code (I'm making a fudged pointer thing here):

dominant7 :: Num a => [a]
dominant7 = [0,4,7,10]
dom7 ==pointer>> dominant7
seven ==pointer>> dominant7
2 Likes

I'll chip in here:

I think the idea of having a number of aliases for chord qualities is good. So, for instance, c'major7, c'maj7, c'ma7

I'm not convinced that distinguising major and minor chord qualities by case is a particularly good idea. Certainly in handwritten music, I've always found it risky to write CM7 and Cm7, as they can look too similar. But it is done, is if it can be supported, then fine.

At the risk of taking the discussion in a different direction: using 's' for notes that are sharps and 'f' for flats is… unusual, counterintuitive at least to me. I would have expected '#' for sharp and 'b' for flat.

Looking at some of the existing chord names: can we avoid lower camel case, like 'sevenFlat10'? Also… that chord doesn't really exist! The more I look at this, there is quite a bit of work to do here.

What I would be looking for is a naming system that corresponds as closely as is practicable to the naming conventions used by jazz musicians.

Now I feel bad for saying anything! I'd like to contribute properly to this piece of work but I'm not sure if I have time :frowning:

4 Likes

Somewhat orthogonal to this naming question - what about semantics? Tidal's current model is "chord = set of notes". It is convenient because you can mix notes and chords in mini notation. But it makes it hard (to impossible) to transform chords - you'd first have to reconstruct the chord (name) from the notes, and that's not always possible. A while ago, a student of mine wrote a thesis on chords in Tidal represented by a separate data type that keeps all the information. Of course this requires a separate interpretation step (from chord to notes) which may be inconvenient. I will ask the student about publishing the code.

4 Likes

I don't know very much about chords so while I'm supportive of improving this, I will mostly keep quiet on this one! Just some thoughts

4 Likes

My two cents re: naming of chords. I think having several different names for the same chord is a good thing, as it saves the effort of remembering the one and only correct name by allowing to settle for a "good enough" one when using them, but I also think it would be good to have at least one set of names that follow rigorous and predictable rules, to be able to work them out without looking them up.

I also second the idea of transitioning to a more semantic concept of chords as a long term goal, but as Alex said, it has to be thoroughly thought-out first.

2 Likes

Thanks everyone for the replies!

Yes, this is my primary concern - hence opening up to discussion. This will need significant
a) agreement between different users as to what they expect/require
b) planning before a line of code gets touched (including what the limitations are in the language, which is where you are best placed to guide us)

...and this is the sort of guidance I need! That looks super promising and already implements some standards (eg on sharps and flats s b, slash/inverted chords \C_g.asNotes // C/g -> [ 7, 12, 16 ] etc.
I'll dig into it a bit further later, but I think this may be an ideal starting point.

I did think about this, and didn't have a good shorthand alternative in mind, but...

I think this works. ma and mi are clear, no capitalisation required - having said that, M and m notation on traditional charts is exceedingly common, so both should be considered imo

agree - there is also an existing standard in tidal for indicating sharp and flat which imo should be applied to chord names as well (and looks like it is also used by the supercollider module @yaxu linked).

I'm not sure what sort of transformations you mean - can you elaborate?

Chords can certainly be inverted and have extra numbers of notes included/excluded as per the docs, but if you mean changing discrete notes within the chord itself then that should be doable by changing the chord (which would require some deeper musicianship/knowledge of chord makeup). If you want to transform chords to something which can't be provided by a standard chord name then yes, you'll need to write it as discrete notes for now

I'd be keen to read it

agree

This could be quickly doable as a short term goal, simply updating/adding chords so there is one consistent set - it'll be non-breaking, definitions can be duplicated for now rather than worrying about aliases etc
I'll draft a couple of possible naming variations and come back to this thread (or a separate one) for a vote

Thanks again for all the feedback folks, this gives me a couple of things to look into short term and medium.
I'm also not trying to "own/be opinionated about" this either, I think it just needs some direction/management/resourcing which I'm hoping I can provide/pull the threads on that will make the most useable/least breaking outcome(s)

3 Likes

A warning, my entire exposure to programming in haskell is by writing some tidal code, so my very early initial foray into this is just working out some of the haskell dev processes (I'm having a read of Learn You a Haskell for Great Good).

I've managed to load Chords.hs into ghc interactively, I can call the chord names and get lists returned.

Question for @yaxu - is the chordList something I can effectively use for the aliases as previously mentioned?

It looks like this is exactly what's happening here with major and maj:

chordTable = [("major", major),
              ("maj", major),
...

Where both major and maj reference the major function (?) which is defined in Chords.hs at line 25

major :: Num a => [a]
major = [0,4,7]

Can you confirm my logic is correct?

If that's the case, once the naming convention is defined/confirmed:

  • I will update the list of chord functions according to our rules(? lines 25-112),
  • add any aliases/shorthand references into the chordList, potentially including any previous naming conventions to minimise breakage

Am I heading in the right direction?

@tedthetrumpet @th4 @jwaldmann (and anyone else who wishes to contribute/comment), here's some brainstorming:

Let's begin with a set of basic major chords in C:
major, major 7, 7 (dominant 7))
In current nomencalature, this is inconsistent because we have c'major7 (the 7th defined with an integer), but the dominant cannot be written as c'7 - instead it's c'dom7 ... which is also inconsistent because it's using a shortening of the word "dominant", but we're not shortening "major".

Can I get some thoughts on the following initial proposal:

Proposal: Use full, unambiguous, strings for the "master function/reference list" ie the list of chord names that all aliases will refer to

Using the above example, this will look like:

major :: Num a => [a]
major = [0,4,7]
majorseven :: Num a => [a]
majorseven = [0,4,7,11]
dominantseven :: Num a => [a]
dominantseven = [0,4,7,10]

Here are some additional thoughts that crossed my mind while reading this topic:

Chord symbols in Tidal are shorthands for things that are hard to type fast (e.g. lists of numeric values). Polyphony is expressed with commas and brackets, which are great because they work for any atomic thing (be it a number, a name, or even other things). Chords could be represented by some kind of special notation, akin to how euclidian patterns have their own special representation.

Chords are really weird objects because they do not really represent a finite set of notes. When we do represent them as simple objects, that’s mostly for pedagogical reasons: writing one by one all the necessary notes for a chord to be labelled as "dominant", "m11" or so. However, chords are almost never used as monolithic blocks of notes, each block containing all the notes that "make" a chord the perfect exemple of itself.

There can be repetitions of notes (e.g. c4 e4 g4 c5), omission of notes (e.g. c4 e4 b4), variable span (e.g. c2 c3 e3 g4 c5 e6 c5 f6 g6 b6 c7), inversions (e.g. e3 g3 c4), etc... I don’t think that one can come up with a shorthand notation that will be able to express every shape a chord can take. More importantly, weird chord shapes are seen out there in the wild all the time, for melodic reasons or because people do all sorts of crazy stuff with voice-leading.

Some computer langages do intriguing stuff in order to represent chords. It’s most of the time really hard to represent a chord textually, without the spatio-temporal twist that traditional notation is offering to the reader. I recently played a bit with Opusmodus, which is targetting a different audience than Tidal (compose first, edit the score, give it to the musicians). Opusmodus is sitting on Common Lisp and does cool things when it comes to manipulating its own syntax. For instance, you can "glue" together notes and that will make a chord: (c4e4g4c5). This way, chords can be seen as blocks of notes, and do not require any kind of cognitive thinking to determine what goes inside a chord. People will be encouraged to play with arbitrary shapes, and some things that could be difficult to write in other languages are rather easy to express : '((c4e4) (d4f4) (e4g4)).

I wonder how well Tidal could handle this kind of notation (without the mandatory LISP parenthesis). This would be rather strange because it would add a new type of polyphonic notation that wont work well for every pattern (just picture the ugliness and non-sense of something like bdsnhhsn). However, it would be really cool to quickly input list of notes, as long as notes are not represented by numbers or individual letters.

7 Likes

some thoughts/requests:

I'm not so picky about what the chords are called as long as i can remember them and that they are applied consistently. i don't mind camel case, i don't mind M or m, ma/mi, whatever, it all works for me, really. what i dislike currently is that i have to write min7 and m9 but i can't write min9, which bothers me only because it seems inconsistent. it seems to me that the more options exist, the better off we'll be, especially if the variations are always consistent and dare i say predictable.

the chord list in it's current state is not exhaustive. just one example, a major seventh chord is not the same as a dominant seventh chord and therefore it's not always clear what base chord i'm dealing with in the chord reference documentation, specifically when looking at the syntax for chords that contain upper extensions. i think there's room for a more thorough audit of this and i would love to see a wider range of common (and uncommon) chord types represented in the Tidal chord list. for example, i don't think there's a lot of support for "add9" chord types currently. also, i think there should be a really easy, straightforward way to add custom chords to your chord list locally so you can have custom chords like you have custom functions or whatever.

obviously (or maybe not so obviously, actually) there are many ways to name a given chord, especially when you start to talk about certain voicings of chords containing upper extensions. a lot of this has to do with the actual physical limitations of playing chords on standard instruments like guitar or piano. we only have so many fingers so often times musicians will miss off the root or the third or whatever so they can reach a sixth, seventh, ninth, eleventh, or thirteenth. the missing notes are, in these cases, "implied". in Tidal, this is not an issue -- we explicitly define each note of a chord as if all the notes can be played, which they can. something to maybe think about as chord lists start to be mapped. a lookup table returning multiple results might be an interesting way to deal with the flexibility in how we want to call up a given chord.

one request i'd like to make (and happy to think through this and contribute somehow with a collaborator, as i'm not currently equipped technically to help code it myself), is finding some room for things like simple intervals, coming up with nice ways to pattern them, and maybe thinking of useful ways of building slash chords with them...defining an certain interval to become the bass note in a given chord. simple intervals, sometimes called double stops, are super super duper important to a lot of players and i don't know of a way currently (please correct me if i'm wrong!!!) to easily move intervals around (root + sixth, root + third, etc.).

i will say that i'm generally very happy with the various results i'm able to come up with currently, finding cool workarounds to create friction with intervals, hacking slash chords, but just in my own naive way. when i started experimenting with harmony in Tidal, i realized i had A LOT to learn about music theory so it's been a work in progress for me over the last few years. the more i'm learning about theory, the more i'm looking for insane ways to exploit this in Tidal that isn't just cobbled together.

3 Likes

Thanks @Raph , all of that is really good food for thought, and you've got me thinking about how to "tidal-ise" the chord representations by allowing us to pattern within the syntax as well -

When I get past the easy part (just making some consistent naming) checking out other ascii/code based chord representations should be the first thing we do to see what other possibilities others have come up with and whether that's workable here.

This is where my journey to writing this thread began :stuck_out_tongue:

I've missed these as well

This is something else I'm interested in - particularly open piano voicings

Once again, I'll review this in more detail once I've gotten over the simple(r) short term resolution of consistent naming :slight_smile:

I think this is a really interesting question. I think, like many others have pointed out, that this kind of chord name language comes out of a tradition of naming used and invented by jazz musicians to quickly communicate the flavor of chord that they would like at that moment in the song.

This naming has the effect of outlining which notes are allowed but, as others on this thread have noted, it does not tell you in which octave to play those notes, or even if you should play all of them. For example, it is quite common when voicing a 13th chord (a chord where all notes from the scale are allowed [root, 3rd, 5th, 7th, 9th, 11th, 13th]) to omit notes to reduce the tension in the harmony or to make space for other musicians to fill. It is quite common to omit the 5th, 11th, or 9th. But really even the root could be left out and the flavor of the chord could remain.

When artists are using tidal, what I think they are after is the ability of use this very human notation to tell the computer which harmony they would like. But the symbol alone doesn't quite give tidal enough info.

I am intrigued by @tedthetrumpet suggestion about multiple name aliases as there is a lot of variation in this naming tradition.

I am also intrigued by @jwaldmann suggestion about mini-notation to specify chord inversion. The flavor of a chord in root position vs. first inversion (3rd in the bass) is very different. Also, changing inversions is a cool way to keep harmonic interest without changing chords. Maybe something like c7(1) to specify 1st inversion and c7([0 1 1 3]) to specify the inversion changing over time. One zany though I'm having is that this could also be extended to allow the user to specify the top voices of the chord. Example, c7(1,2) could put the 3rd (E natural) in the bass and then take the remaining notes (G Bb C) and invert them 2 times (C G Bb). This could be extended for however big the chord is minus 1. c7(1,2,1). Depending on how this was implemented this also might let the user specify open voicing as the inversion function would displace notes up octaves as it goes.

On the topic of distinguishing major and minor chords: I would offer the observation that when writing charts for bands it can be quite common to assume that Major chords are "normal" and dominant 7ths are also "normal". So, c7means c dominant 7. (C E G Bb). If minor valence or a major 7 is intended it is specified explicitly (cm or cmaj7). I'm sure there are places where this breaks down but it is something I have observed playing in funk and rock bands. This extends to the other tensions as well, major 9ths are more "normal" than flat 9s which are specified with c7b9 ect...

One last thought I'm having on this topic is that there are a LOT of possible chord names that someone would want to use (without considering aliases). Here is the link to an personal project where I built a little chord naming utility. Notice the size of the CHORD_NAMES variable. I'm pretty sure I didn't get them all either but gave up as I had the flavors that I wanted for my writing.

Anyway, that was longer than I expected. Thanks for reading my brain dump! :sweat_smile:

1 Like

Hey thanks for joining the discussion!

This is a pretty accurate representation of my experience :slight_smile:

I'm not sure from your post whether you're aware that chord inversion is currently quite simple to use - from the docs :

This is doable as:
c'seven'ii
I read/remember this as "put the second tone of the chord in the bass"

Limiting your upper notes (ie excluding the root altogether in this case) can be done using: c'seven`ii`3
which can be read as "put the second tone of the chord in the bass, and only play 3 notes in the chord"

Now, i think the decision to go with ii for the first inversion was a bit counter-intuitive, and this should also be part of the discussion :slight_smile:

This is a huge effort! I did have a look through it - I noticed that a lot of your extended chords place the extensions within the same octave as the root note rather than an octave above, example:

{{0,3,7,1,8},"maddb9addb13"}

I'm curious why you didn't spread this out across two octaves as per:

{{0,3,7,13,20},"maddb9addb13"}

was there a reason?

Thanks for taking the time to join the discussion :slight_smile:

About concrete syntax: how about copying what lilypond does? https://lilypond.org/doc/v2.20/Documentation/notation/chord-mode
(perhaps with some conflicting characters re-mapped)
Their primary goal is type-setting but they still can generate sets-of-notes for MIDI.

1 Like

About semantics: my student basically did

data Chord = Chord   
  {root :: PitchClass
  ,      components :: [Degree]
  ,      bass :: PitchClass
  ,      chordRange :: (Int,Int)} 
data PitchClass = Cf | C | Cs ...
type Degree = Int
instance Parseable Chord where ...
chdN :: Pattern Chord -> Pattern Double

so, chords as a separate type. There are functions :: Chord -> Chord that cannot be realized via set-of-notes alone. Sure you might argue that set-of-notes is what you ultimately hear. But, as has been said in this thread, chord symbols are used for writing, as a basis for improvisation/transformation.

2 Likes

Thanks @cleary. I wasn't aware you could do that! I think I need to update my Tidal install. :smiley:

The purpose of the program was to rip through a bunch of combinatorial and spit out names rather than to make music so I just dealt in pitch classes and ignored octaves.

1 Like

Yes it feels like this should be a solved problem. I expected the Music Informational Retrieval (MIR/ISMIR) research community would have a standard but I couldn't find one although didn't look super hard. I tweeted asking about it but got no responses (although a fair number of likes and retweets)

Anway I'm really enjoying this discussion of nuance I wasn't aware of!

Yes. But also xkcd: Standards

Jokes aside, I am using https://de.schott-music.com/shop/neue-jazz-harmonielehre-no91932.html (I am sure there are many English-language equivalents) as a reference for "real book" chord notation. But it does not discuss computerisation.

Musicologists can be very fussy about chords and their proper naming. Some of them spent a large part of the XXth century discussing just one of them. I don't expect an unified theory anytime soon. The naming of chords is as much a matter of classification as it is a matter of interpreting the role of certain chords in particular contexts.

IMHO Tidal should just take a direction and follow it as accurately as possible. Users will likely adapt and form their own abstractions if they need them. I'm afraid that speaking about proper chord naming is an endless field that will not give any answers for practitioners, improvisers and Tidalists.

PS: it is also a matter of culture and social/academical environment. I already got slapped as a student at univ for suggesting that some chords in a Chopin piece could be seen as X and Y in a jazz context.

3 Likes

That's the plan :slight_smile:

I agree that we should consider a standardised cross platform syntax, but we definitely need to think beyond this because we (I :stuck_out_tongue: ), should be able to make use of the patterning possibilities offered by tidal/haskell which is where the strengths of this tool lie...

I don't have any proposals yet, but this discussion is giving a lot of the perspective and context required to choose a sensible direction - thanks again everyone :slight_smile:

1 Like