<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Music on s20n blog</title><link>https://blog.s20n.dev/tags/music/</link><description>Recent content in Music on s20n blog</description><generator>Hugo 0.150.0</generator><language>en-us</language><lastBuildDate>Sat, 06 Apr 2024 10:55:09 +0530</lastBuildDate><atom:link href="https://blog.s20n.dev/tags/music/index.xml" rel="self" type="application/rss+xml"/><item><title>How Chordcat Works, A Chord Naming Algorithm</title><link>https://blog.s20n.dev/posts/how-chordcat-works/</link><pubDate>Sat, 06 Apr 2024 10:55:09 +0530</pubDate><guid>https://blog.s20n.dev/posts/how-chordcat-works/</guid><description>
&lt;p&gt;
&lt;img src="https://blog.s20n.dev/images/chordcat-banner.png" alt="/images/chordcat-banner.png" title="/images/chordcat-banner.png" /&gt;&lt;/p&gt;
&lt;p&gt;
&lt;a href="https://github.com/shriramters/chordcat/"&gt;chordcat&lt;/a&gt; is a chord-naming application and a pet project of mine. It is written
in C++ and SFML.&lt;/p&gt;
&lt;p&gt;
At the heart of chordcat is the chord naming algorithm. I and my dear friend &lt;a href="https://theakash.dev"&gt;Akash&lt;/a&gt;
came up with this one afternoon and found it rather elegant. The algorithm
itself is not very complicated but the explanation might be a tad bit
lengthy. In this blog, I&amp;#39;ll try my best to explain how this algorithm works.&lt;/p&gt;
&lt;p&gt;
All the code presented in this blog is licensed under &lt;a href="https://www.gnu.org/licenses/gpl-3.0.en.html"&gt;GPL-3.0&lt;/a&gt;&lt;/p&gt;
&lt;div id="outline-container-headline-1" class="outline-2"&gt;
&lt;h2 id="headline-1"&gt;
Basic Theory
&lt;/h2&gt;
&lt;div id="outline-text-headline-1" class="outline-text-2"&gt;
&lt;p&gt;
A chord can have many names. In fact we could pick any of the notes as the root
note and come up with a name for the chord. For example, the notes &lt;code&gt;C&lt;/code&gt;, &lt;code&gt;E&lt;/code&gt; and
&lt;code&gt;G&lt;/code&gt; (The C major chord) can have any of the following names, based on what is
considered to be the root note.&lt;/p&gt;
&lt;table&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;root note&lt;/td&gt;
&lt;td&gt;chord name&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C&lt;/td&gt;
&lt;td&gt;C Major&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;E&lt;/td&gt;
&lt;td&gt;E Minor #5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;G&lt;/td&gt;
&lt;td&gt;G sus4 (13)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;
(To the best of my knowledge, I&amp;#39;m no music theorist)&lt;/p&gt;
&lt;p&gt;
Also, it does not really matter what octave these notes are played in or whether
these notes are repeated. For all intents and purposes, we can simply take the
index of the key pressed on the keyboard (0-88 starting from A) and take the
modulo of that index with 12 to get our note.&lt;/p&gt;
&lt;p&gt;
It is also important to know that chords are built on thirds. If we were to go
up the major scale from the root note in diatonic thirds (alternating notes),
we&amp;#39;d form chords like 1, 3, 5, 7, 9, 11, 13 (Maj13)&lt;/p&gt;
&lt;p&gt;
For example, in the C Major scale (&lt;code&gt;CDEFGABC&lt;/code&gt;), we could pick the alternate
notes and form this chord (&lt;code&gt;CEGBDFA&lt;/code&gt;) which is the &lt;code&gt;CMaj13&lt;/code&gt; chord.&lt;/p&gt;
&lt;p&gt;
And that&amp;#39;s about the biggest chord you&amp;#39;ll find using this technique because the
next number after 13, i.e &amp;#34;15&amp;#34;, is the root note &lt;code&gt;C&lt;/code&gt; again.&lt;/p&gt;
&lt;p&gt;
While we were coming up with chordcat, Jake from &lt;a href="https://signalsmusicstudio.com/"&gt;signals music studio&lt;/a&gt; posted
&lt;a href="https://www.youtube.com/watch?v=2SeN9W1CIrI"&gt;this excellent video&lt;/a&gt; on how to name every chord ever. This video came
extremely in clutch when we were writing this software.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-headline-2" class="outline-2"&gt;
&lt;h2 id="headline-2"&gt;
The Algorithm
&lt;/h2&gt;
&lt;div id="outline-text-headline-2" class="outline-text-2"&gt;
&lt;p&gt;
First, we get &lt;code&gt;indices&lt;/code&gt;, which is the list of indices of all the keys pressed on
the keyboard (0-88). As discussed in the previous section, we can simply take
the modulo of these indices with 12 and store them in a set to name our chord
(no duplicates). We&amp;#39;ll call this set &amp;#34;&lt;code&gt;notes&lt;/code&gt;&amp;#34;.&lt;/p&gt;
&lt;p&gt;
Since we now know that basically any of the played notes could be the root note
of our chord, we&amp;#39;ll need to iterate through all the notes that were played and
run the chord-naming algorithm once for each note.&lt;/p&gt;
&lt;p&gt;
This is what is done in the piece of code below. In our chord naming function,
we&amp;#39;ve got the second &lt;code&gt;for&lt;/code&gt; loop iterating through each of the notes considering
each of them the root, one at a time.&lt;/p&gt;
&lt;div class="src src-c++"&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-c++" data-lang="c++"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;multiset&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;Chord&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; name_that_chord(&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;vector&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;size_t&lt;span style="color:#f92672"&gt;&amp;gt;&amp;amp;&lt;/span&gt; indices) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;set&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;unsigned&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;short&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; notes &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {};
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;auto&lt;/span&gt; index : indices) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; notes.insert(index &lt;span style="color:#f92672"&gt;%&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;12&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;multiset&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;Chord&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; result &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {};
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;auto&lt;/span&gt; root : notes) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;set&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;unsigned&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;short&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; intervals &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {};
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;auto&lt;/span&gt; other : notes) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	 &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (other &lt;span style="color:#f92672"&gt;==&lt;/span&gt; root)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	 &lt;span style="color:#66d9ef"&gt;continue&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	 intervals.insert(get_note_distance(root, other));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; insert_chords(root, intervals, result);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; result;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Once we consider one of the notes as the root, we can then go ahead and get the
structure of the chord by calculating the distance of each of the notes in
relation with the root note. By distance, I mean the number of semitones between
the two notes. This is stored in a set named &amp;#34;&lt;code&gt;intervals&lt;/code&gt;&amp;#34;.&lt;/p&gt;
&lt;p&gt;
Once we have the set of intervals, we can then simply lookup this set in our
database of chord names. &lt;a href="https://github.com/shriramters/chordcat/blob/main/src/chord_db.hpp"&gt;This is a rudimentary &amp;#34;database&amp;#34; of chord names I came
up with&lt;/a&gt;. These names will be our &amp;#34;base names&amp;#34;. We will have to check our
intervals set against each of these chords in our database. The missing or
additional notes will be the accidental notes in the chord (b13, #11 etc..).&lt;/p&gt;
&lt;p&gt;
Here &lt;code&gt;Chord&lt;/code&gt; is a struct representing the actual chord. We store:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;root note,&lt;/li&gt;
&lt;li&gt;extra tones (The notes present in our intervals set but not in the chord&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;database entry)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;omitted tones (The notes present in the database entry but not in our
intervals set)&lt;/li&gt;
&lt;li&gt;num_accidentals (the sum of extra and omitted tones, this is used for sorting)&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="src src-c++"&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-c++" data-lang="c++"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;struct&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Chord&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;unsigned&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;short&lt;/span&gt; root;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; sf&lt;span style="color:#f92672"&gt;::&lt;/span&gt;String base_name;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;vector&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;unsigned&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;short&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; extra_tones;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;vector&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;unsigned&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;short&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; omitted_tones;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;unsigned&lt;/span&gt; num_accidentals;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// support sorting
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;friend&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;auto&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;operator&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;=&amp;gt;&lt;/span&gt;(Chord &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt; a, Chord &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt; b) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; a.num_accidentals &lt;span style="color:#f92672"&gt;&amp;lt;=&amp;gt;&lt;/span&gt; b.num_accidentals;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-headline-3" class="outline-3"&gt;
&lt;h3 id="headline-3"&gt;
Sorting?
&lt;/h3&gt;
&lt;div id="outline-text-headline-3" class="outline-text-3"&gt;
&lt;p&gt;
Here is another postulate of this algorithm, the chord name that has fewer
accidentals can be considered a more proper name for the chord.&lt;/p&gt;
&lt;p&gt;
It is for this reason that we are making our chords sortable by
&lt;code&gt;num_accidentals&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;
For instance, consider the chord &lt;code&gt;CEG&lt;/code&gt;. If we consider &lt;code&gt;C&lt;/code&gt; to be the root note,
we can calculate the interval set to be &lt;code&gt;(4, 7)&lt;/code&gt; (because &lt;code&gt;E&lt;/code&gt; is 4 semitones above
&lt;code&gt;C&lt;/code&gt; and &lt;code&gt;G&lt;/code&gt; is 7 semitones above &lt;code&gt;C&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;
Running this &lt;code&gt;(4,7)&lt;/code&gt; against our database, we come up with these candidates for names:&lt;/p&gt;
&lt;table&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;intervals&lt;/td&gt;
&lt;td&gt;base name&lt;/td&gt;
&lt;td&gt;omitted tones&lt;/td&gt;
&lt;td&gt;extra tones&lt;/td&gt;
&lt;td&gt;final name&lt;/td&gt;
&lt;td class="align-right"&gt;num_accidentals&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;(3,7)&lt;/td&gt;
&lt;td&gt;minor&lt;/td&gt;
&lt;td&gt;(3)&lt;/td&gt;
&lt;td&gt;(4)&lt;/td&gt;
&lt;td&gt;C minor (no b3, add 3)&lt;/td&gt;
&lt;td class="align-right"&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;(4,7)&lt;/td&gt;
&lt;td&gt;major&lt;/td&gt;
&lt;td&gt;nil&lt;/td&gt;
&lt;td&gt;nil&lt;/td&gt;
&lt;td&gt;C major&lt;/td&gt;
&lt;td class="align-right"&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;(4,7,10)&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;(10)&lt;/td&gt;
&lt;td&gt;nil&lt;/td&gt;
&lt;td&gt;C7 (no b7)&lt;/td&gt;
&lt;td class="align-right"&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;(4,7,11)&lt;/td&gt;
&lt;td&gt;maj7&lt;/td&gt;
&lt;td&gt;(11)&lt;/td&gt;
&lt;td&gt;nil&lt;/td&gt;
&lt;td&gt;Cmaj7 (no 7)&lt;/td&gt;
&lt;td class="align-right"&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;(3,7,10)&lt;/td&gt;
&lt;td&gt;min7&lt;/td&gt;
&lt;td&gt;(3, 11)&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;Cmin7(no b3, no b7, add 3)&lt;/td&gt;
&lt;td class="align-right"&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;
Clearly, we can see that the names with fewer accidentals are more fitting (in
our case &lt;code&gt;C major&lt;/code&gt; would be the best name for our set of notes).&lt;/p&gt;
&lt;p&gt;
These accidentals (difference between our interval set and the chord_db entry)
are calculated in our &lt;code&gt;insert_chords&lt;/code&gt; function:&lt;/p&gt;
&lt;div class="src src-c++"&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-c++" data-lang="c++"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;insert_chords&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;unsigned&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;short&lt;/span&gt; root, &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;set&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;unsigned&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;short&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&amp;amp;&lt;/span&gt; intervals,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;multiset&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;Chord&lt;span style="color:#f92672"&gt;&amp;gt;&amp;amp;&lt;/span&gt; res) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;set&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;Chord&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; temp;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;auto&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt; [name, notes] &lt;span style="color:#f92672"&gt;:&lt;/span&gt; chord_db) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Chord chord &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {};
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; chord.root &lt;span style="color:#f92672"&gt;=&lt;/span&gt; root;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; chord.base_name &lt;span style="color:#f92672"&gt;=&lt;/span&gt; name;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Can be written better using std::ranges::set_difference
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;&lt;/span&gt; std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;set_difference(notes.begin(), notes.end(), intervals.begin(), intervals.end(),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;back_inserter(chord.omitted_tones));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;set_difference(intervals.begin(), intervals.end(), notes.begin(), notes.end(),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; std&lt;span style="color:#f92672"&gt;::&lt;/span&gt;back_inserter(chord.extra_tones));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; chord.num_accidentals &lt;span style="color:#f92672"&gt;=&lt;/span&gt; chord.extra_tones.size() &lt;span style="color:#f92672"&gt;+&lt;/span&gt; chord.omitted_tones.size();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; temp.insert(chord);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#f92672"&gt;!&lt;/span&gt;temp.empty())
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; res.insert(&lt;span style="color:#f92672"&gt;*&lt;/span&gt;temp.begin());
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-headline-4" class="outline-3"&gt;
&lt;h3 id="headline-4"&gt;
Why multiset?
&lt;/h3&gt;
&lt;div id="outline-text-headline-4" class="outline-text-3"&gt;
&lt;p&gt;
Going back to our &lt;code&gt;name_that_chord&lt;/code&gt; function, we see that I have used a
&lt;code&gt;multiset&lt;/code&gt; to store all the candidate names instead of a regular &lt;code&gt;set&lt;/code&gt;. The
reason for this is the comparison operator &lt;code&gt;&amp;lt;=&amp;gt;&lt;/code&gt; that we defined in our &lt;code&gt;Chord&lt;/code&gt;
struct.&lt;/p&gt;
&lt;p&gt;
Since it is entirely possible that two chords can have the same number of
accidentals, it is not possible to store both of these chords in a set (if we
define the operator like that). For this reason, we have to use a &lt;code&gt;multiset&lt;/code&gt;
which allows for two or more entries to be on the same level (or in our case,
have the same number of accidentals).&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="outline-container-headline-5" class="outline-2"&gt;
&lt;h2 id="headline-5"&gt;
Conclusion
&lt;/h2&gt;
&lt;div id="outline-text-headline-5" class="outline-text-2"&gt;
&lt;p&gt;In this blog we&amp;#39;ve taken a look at the chord naming algorithm powering
chordcat. The algorithm has these following steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Get all the pressed notes (No duplicates, each note an integer between
[0,11]).&lt;/li&gt;
&lt;li&gt;Iterate through the set of notes making each of them the root, one at a time.&lt;/li&gt;
&lt;li&gt;Get the set of intervals (distances of other notes of the set from the
current root)&lt;/li&gt;
&lt;li&gt;Take the two-way set difference of this interval set against our database of
chord names to get the number of accidentals.&lt;/li&gt;
&lt;li&gt;Sort these candidate chord names from the database by the number of
accidentals and take the top result(s).&lt;/li&gt;
&lt;li&gt;Store the top results for each root note in a &lt;code&gt;multiset&lt;/code&gt; to get our final
list of chord names.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Thank you for reading till the end. I hope that you found this interesting and I
encourage you to use this code (GPL-3.0) in your projects as well. I&amp;#39;m also sure
that I might have gotten some things wrong from a music theory
standpoint. Suggestions are always welcome. Please email them to me at s20n AT
ters.dev.&lt;/p&gt;
&lt;p&gt;
Until next time!&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;</description></item></channel></rss>