#+TITLE: Mujic: Learning Music Theory With Clojure #+AUTHOR: Bo Jeanes #+EMAIL: me@bjeanes.com #+STARTUP: showeverything #+OPTIONS: toc:nil ^:{} creator:nil email:nil date:nil num:nil #+PROPERTY: header-args:clojure :session *clj* :cache yes :results value silent :tangle "src/mujic.cljc" #+HTML_HEAD_EXTRA: #+HTML_HEAD_EXTRA: #+OPTIONS: html-link-use-abs-url:nil html-postamble:nil html-preamble:t #+OPTIONS: html-scripts:nil html-style:nil html5-fancy:nil tex:nil #+HTML_DOCTYPE: html5 #+HTML_CONTAINER: div #+BEGIN_SRC clojure :exports none (ns mujic (:require [clojure.set :as set] [clojure.string :as str] #?(:cljs [reagent.core :as r :refer [render]])) #?@(:cljs [(:require-macros [mujic :refer [defintervals]]) (:refer-clojure :exclude [atom])])) #?(:cljs (do (enable-console-print!) (def ratom r/atom)) :clj (do (defmacro render [& args]) (def ratom atom))) (declare note-series) ;; Some global state to keep all the interactive components using the same key ;; or tonic (def tonic (ratom :C)) (def key tonic) (defn- get-selected-key [event] (-> event .-target .-selectedOptions (aget 0) .-value keyword)) (defn- key-selector-on-change [event] (reset! key (get-selected-key event))) (defn key-selector-component "Render a re-usable widget that selects the key or tonic for the interactive example. Adjusts the key for the entire page (i.e. global state)." [] (letfn [(option-fn [note] [:option {:value note} (name note)])] (let [notes (take 12 (note-series :C)) notes (map first notes) ; TODO handle C#/Db distinctions better options (map option-fn notes)] [:div {:style {:text-align "center"}} (into [:select {:value @key :style {:padding "auto"} :on-change key-selector-on-change}] options)]))) #+END_SRC * Preamble I've played guitar since I was about 7 years old. Like many casual musicians, my interest and focus has waxed and waned over those years and, consequently, my skill level plateaued sometime before I was 18. Every time that I've been inspired to play a lot more, it lasts only as long as it takes for me to hit that same plateau threshold; that is, my frustration understanding how music really worked diminishes ([[https://en.wikipedia.org/wiki/Diminished_triad][rimshot]]) my interest. The feeling of really grokking music theory has always eluded me. Every time that I have tried to learn some music theory, it just felt like a house of cards built on memorising labels and rules, each with an abundance of special cases and exceptions. Every bit of theory I managed to learn in the past would slip away just as quickly because the foundation wasn't sturdy. Since I've been really missing working with Clojure, I decided to try to learn music theory by using Clojure to explore the relationships between different concepts (notes, intervals, scales, modes, chords). Approaching music theory as if it were any other unknown domain that I had to model in code should help me really understand and formalise how things work and hopefully let it stick in my head. This post serves as my logbook and worksheet for the experiment. As such, it preserves any understandings which are incorrect or incomplete and subsequent re-understandings of concepts are appended. I will retroactively edit earlier sections to make them clearer or easier to refer to later, though. * Logbook It seems obvious that I need some concept of the usable (Western music) notes and their order, so I'll start there: #+BEGIN_SRC clojure (def ordered-notes ;; I'm using actual flat (♭) and sharp (♯) symbols because this ;; project is for fun and I have working auto-complete. ;; Practicality be damned! [#{:C} #{:C♯ :D♭} #{:D} #{:D♯ :E♭} #{:E} #{:F} #{:F♯ :G♭} #{:G} #{:G♯ :A♭} #{:A} #{:A♯ :B♭} #{:B}]) #+END_SRC I've modelled the notes as a vector of sets. Each set spells out the valid identifiers for that note. At this point, I'm not sure that this model of the keys will be ideal---in particular, I may need to treat flats (♭) and sharps (♯) distinctly based on context---but it suffices for the time being. My exploration with music theory in the past left me with the impression that scales acted as a kind of sieve to highlight specific notes from all notes and that chords acted as sieves over specific scales to further highlight specific notes. With that vague semblance, I pursue modelling this understanding. Scales are usually defined in terms of number of semitone steps: #+BEGIN_SRC clojure (def h 1) ; half step (def W 2) ; whole step (def Wh 3) ; whole-and-half step ;; just a few common scales will do for now (def scales {:major [W W h W W W h] :minor|natural [W h W W h W W] :minor|harmonic [W h W W h Wh h]}) #+END_SRC #+BEGIN_SRC clojure :exports none (declare take-nths) (let [note-width 70 lbls {1 "H" 2 "W" 3 "W+H"} height 40] (letfn [(g ([attrs grouped] (into [:g attrs] grouped)) ([grouped] (g {} grouped))) (scale-step-svg-component [rel abs] (let [lbl (get lbls rel rel) rel (* note-width rel) abs (* note-width abs) lbl-x (/ rel 2) gap (* 0.1 note-width)] [:g {:transform (str "translate(" abs " 0)")} [:text {:text-anchor "middle" :x lbl-x} lbl] [:line {:stroke "black" :x1 gap :x2 (- rel gap) :y1 0 :y2 0}]])) (scale-steps-svg-component [scale] (let [relative (scales @scale) ; (2 2 1 2 2 2 1) absolute (take-nths relative (range))] ; (0 2 4 5 ...) (g (map (fn [rel abs] [scale-step-svg-component rel abs]) relative absolute)))) (scale-notes-svg-component [] (let [notes (take 13 (note-series @tonic)) ;; TODO handle C#/Db distinctions better notes (map first notes)] (g (map-indexed #(vector :text {:x (* note-width %1)} (name %2)) notes)))) (scales-sieve-svg-component [scale] [:svg {:width "100%" :height height :viewBox [0 0 (* 13 note-width) height]} [scale-notes-svg-component] [scale-steps-svg-component scale]]) (scale-selector-component [scale] (let [name (name @scale) ; doesn't include namespace, so: ns (namespace @scale) val (if ns (str ns "/" name) name)] [:div {:style {:text-align "center"}} [:select {:value val :on-change #(reset! scale (get-selected-key %)) } [:option {:value "major"} "Major"] [:option {:value "minor|natural"} "Natural Minor"] [:option {:value "minor|harmonic"} "Harmonic Minor"]]])) ] (defn scales-sieve-component [] (let [scale (ratom :major)] (fn [] [:div [key-selector-component] [scale-selector-component scale] [scales-sieve-svg-component scale]]))))) #+END_SRC #+BEGIN_HTML
#+END_HTML Now, I need a way to pick items from a list based on these steps, which I think of as relative indices. I have a sense that this might be a generically applicable operation so I'll write it generically (this type of operation may very well already exist, but I can explore that later): #+BEGIN_SRC clojure (defn take-nths "Takes a collection and returns the values of each interval from the previous value (or start). Always includes the first item. Named due to similarity with take-nth, with stable n: (take-nth 2 (range)) ;=> (0 2 4 6 8 10 ...) (take-nths (repeat 2) (range)) ;=> (0 2 4 6 8 10 ...) " [ns coll] (let [indices (reductions + 0 ns)] (map (partial nth coll) indices))) #+END_SRC Here's how that behaves: #+BEGIN_SRC clojure (take-nths [3 1 1 4] [1 2 3 4 5 6 7 8 9 10]) ;;=> (1 4 5 6 10) #+END_SRC Because the scale definition includes the interval to reach the octave, I'll use =cycle= to give it an infinite number of notes for the scale to select: #+BEGIN_SRC clojure (count (take 20 ordered-notes)) ;=> 12 (take-nths (scales :major) ordered-notes) ;!! java.jang.IndexOutOfBoundsException (count (take 20 (cycle ordered-notes))) ;=> 20 (take-nths (scales :major) (cycle ordered-notes)) ;=> (#{:C} #{:D} #{:E} #{:F} #{:G} #{:A} #{:B} #{:C}) #+END_SRC Since this needs a cycling notion of the available notes and I'll surely need it later for chords with super-octave notes (9th, 11th, 13th, etc), I'll create a function to return an infinite list of notes, starting with a specific note (*C* if not specified): #+BEGIN_SRC clojure ;; convenience list of all valid note names (def note-names (apply set/union ordered-notes)) (defn note-series "Returns an infinite sequence of chromatic notes starting with :C or the provided `start` note" ([] (note-series :C)) ([root] (when-let [root (note-names root)] (drop-while (complement root) (cycle ordered-notes))))) #+END_SRC (side-note: super valuable to put ={:user :global-vars {*print-length* 103 *print-level* 15}}= in your =~/.lein/profiles= file so that you don't accidentally print an infinite list in the REPL and have it hang!) Likely, the "infinite sequence of notes" model is a stopgap until I can tie in the octave of the note into the representation (e.g. with [[https://en.wikipedia.org/wiki/Scientific_pitch_notation][scientific pitch notation]]). OK, so now I can come back to building scales by sieving all possible notes from a root: #+BEGIN_SRC clojure :results output (take-nths (scales :minor|natural) (note-series :A)) ;;=> (#{:A} #{:B} #{:C} #{:D} #{:E} #{:F} #{:G} #{:A}) #+END_SRC I can anticipate that repeating scales (using =cycle=, as with the note series) which means that the root note, which is in both first and 8th position, will appear twice in a row: #+BEGIN_SRC clojure (cycle '(#{:A} #{:B} #{:C} #{:D} #{:E} #{:F} #{:G} #{:A})) ;;=> (#{:A} #{:B} #{:C} #{:D} #{:E} #{:F} #{:G} #{:A} #{:A} #{:B} #{:C} ...) ;; ^ 2x ^ #+END_SRC I'll tackle that later when it comes up, though. Here is my new =scale= function: #+BEGIN_SRC clojure (defn scale "Return the sequence of notes for the specified scale and tonic" [scale tonic] (take-nths (scales scale) (note-series tonic))) ;; arguments are in that order so its amenable to currying: (def major-scale (partial scale :major)) (major-scale :C) ;=> (#{:C} #{:D} #{:E} #{:F} #{:G} #{:A} #{:B} #{:C}) #+END_SRC As I mentioned above, I've always thought of chords as a "sieve" over their scale. In some contexts, this is obvious. The major triad is [[http://www.smithfowler.org/music/Chord_Formulas.htm][defined as *1 3 5*]] of the major scale, for example. Interestingly, a minor triad is typically in terms of the major scale too. It is [[http://www.smithfowler.org/music/Chord_Formulas.htm][represented as *1 ♭3 5*]]. This is one of those things that seemed like an exception and special case in my past---just more memorisation. However, playing around in code let me discover that it's also *1 3 5* of a minor scale. This property allows me to use these intervals as 1-based indexes of the scale and feels like a beautiful musical property---one I'll likely remember: #+BEGIN_SRC clojure ;; Just a few chords for now will do. We'll map a chord ;; name to a scale and the notes from the scale to use. (def chords {:M [:major [1 3 5]] :M7 [:major [1 3 5 7]] :m [:minor|natural [1 3 5]] :m7 [:minor|natural [1 3 5 7]]}) #+END_SRC This exploration helped throw some light on the relationship between scales and chords, which is exactly the point. To get the notes in a chord, I'll define a new function which takes a chord identifier and a root note: #+BEGIN_SRC clojure (defn chord [chord root] (let [[scale-name idxs] (chords chord) scale (scale scale-name root)] (map (comp (partial nth scale) dec) ; dec so 0-indexed idxs))) ;; arguments are in that order so its amenable to currying: (def minor-7th (partial chord :m7)) (minor-7th :C) ;=> (#{:C} #{:D♯ :E♭} #{:G} #{:A♯ :B♭}) #+END_SRC I defined a few dozen chords like this in terms of the scales whose structures I had defined earlier. Eventually, the process of converting typical notation (*1 ♭3 5*) into my notation (*1 3 5* in natural minor) to be quite difficult for some chords. I kept having to mentally convert the typical notation into notes for a *C* chord then pattern match a *C* scale that had all those notes. This is mentally taxing, because I haven't defined my scales in those terms yet. I'll explore two such chords which drove the need to introduce a new scale and to explore [[https://en.wikibooks.org/wiki/Music_Theory/Modes][modes]]. Later, I'll go back and re-model chords to avoid this mental taxation. The *m6* (minor sixth) chord is typically defined in terms of the major scale as *1 ♭3 5 6*. If I compare the major scale intervals with the two minors that I have defined, I can see that both of the defined minors flatten the *6th*. The *6* in terms of either minor scale would be incorrect, and I'd have a different chord: #+BEGIN_SRC clojure (defn scale-degrees [tonic scale-name] (map-indexed #(list (inc %1) (last %2)) (scale scale-name tonic))) (scale-degrees :C :major) ;;=> ((1 :C) (2 :D) (3 :E) (4 :F) (5 :G) (6 :A) (7 :B) (8 :C)) (scale-degrees :C :minor|natural) ;;=> ((1 :C) (2 :D) (3 :E♭) (4 :F) (5 :G) (6 :A♭) (7 :B♭) (8 :C)) (scale-degrees :C :minor|harmonic) ;;=> ((1 :C) (2 :D) (3 :E♭) (4 :F) (5 :G) (6 :A♭) (7 :B) (8 :C)) #+END_SRC *1 ♭3 5 6* from the major scale would be *C E♭ G A* but both minor scales have an *A♭* instead. Luckily, there is a minor scale, the [[https://en.wikipedia.org/wiki/Minor_scale#Melodic_minor_scale][melodic minor]], which has an *A*, so I'll add that to my defined scales: #+BEGIN_SRC clojure (def scales {:major [W W h W W W h] :minor|natural [W h W W h W W] :minor|harmonic [W h W W h Wh h] :minor|melodic [W h W W W W h]}) #+END_SRC The melodic minor is a bit special because, in melodies, it's only played in ascending order. When descending, the natural minor is used instead, though it can be referred to as the descending melodic minor scale. For our purposes of chord construction, this doesn't seem relevant, so I'll conveniently just treat it as a normal scale. Here it is, compared to the major: #+BEGIN_SRC clojure (scale-degrees :C :major) ;;=> ((1 :C) (2 :D) (3 :E) (4 :F) (5 :G) (6 :A) (7 :B) (8 :C)) (scale-degrees :C :minor|melodic) ;;=> ((1 :C) (2 :D) (3 :E♭) (4 :F) (5 :G) (6 :A) (7 :B) (8 :C)) #+END_SRC Note the 6th note is natural (♮ not ♭ or ♯). After all that work, I can finally add the *m6* chord to the chord definitions: #+BEGIN_SRC clojure (def chords {:M [:major [1 3 5]] :M7 [:major [1 3 5 7]] :m [:minor|natural [1 3 5]] :m7 [:minor|natural [1 3 5 7]] ;; ... :m6 [:minor|melodic [1 3 5 6]]}) #+END_SRC The next chord that I struggled with is the *M7♯11*. The 11th degree of a [[https://en.wikipedia.org/wiki/Diatonic_scale][diatonic scale]] (7-note scales) is the same note as the 4th, just an octave higher. So to tackle a *M7♯11* chord, I need a scale which has a *♯4* in it. I sat down at the piano and played a major scale with a sharpened 4th to see how it sounded. It was nice! A combination of my foggy memory of [[https://en.wikibooks.org/wiki/Music_Theory/Modes][modes]] and some Wikipedia spelunking led me to the [[https://en.wikipedia.org/wiki/Lydian_mode][lydian mode]], which is a major scale with a *♯4*. Perfect. It turns out that modes can be thought of as "rotations" of an existing scale. That is, rotating the C major scale (*C D E F G A B*) a degree gives a new scale with the same notes (*D E F G A B C*). Typically, when modes are mentioned, the modes based on the 7 degrees of a major scale are implied, though they can be based on other scales, [[https://en.wikipedia.org/wiki/Jazz_scale#Modes_of_the_melodic_minor_scale][such as the melodic minor scale]] or [[http://docs.solfege.org/3.22/C/scales/har.html][harmonic minor scale]]. Since this definition seems important and interesting, instead of writing out all the modes as I have done for other scales, it seems relevant and important to encode this relationship between modes and scales in code. After a few iterations, I came up with some generic functions (prior implementations likely exist): #+BEGIN_SRC clojure (defn rotate "Moves n elements in s from the front to the back." [n s] (let [shift (mod n (count s))] (concat (drop shift s) (take shift s)))) (defn rotations "Returns a sequence generated by rotating finite sequence s repeatedly until the original order is encountered." [s] (take (count s) (iterate (partial rotate 1) s))) #+END_SRC They work like so: #+BEGIN_SRC clojure (rotate 1 [:a :b :c :d]) ;=> (:b :c :d :a) (rotations [:a :b :c :d]) ;=> ([:a :b :c :d] (:b :c :d :a) (:c :d :a :b) (:d :a :b :c)) (scales :major) ;=> [2 2 1 2 2 2 1] (rotations (scales :major)) ;;=> ([2 2 1 2 2 2 1] (2 1 2 2 2 1 2) (1 2 2 2 1 2 2) (2 2 2 1 2 2 1) (2 2 1 2 2 1 2) (2 1 2 2 1 2 2) (1 2 2 1 2 2 2)) #+END_SRC I'm going to add these modes to the =scales= list in a way that reflects this relationship: #+BEGIN_SRC clojure (def scales (let [scales {:major [W W h W W W h] :minor|natural [W h W W h W W] :minor|harmonic [W h W W h Wh h] :minor|melodic [W h W W W W h]} modes (zipmap [:mode|ionian :mode|dorian :mode|phrygian :mode|lydian :mode|mixolydian :mode|aeolian :mode|locrian] (rotations (scales :major)))] (merge scales modes))) #+END_SRC Astute readers might realise that the =:minor|natural= and =:mode|aeolian= actually have the same associated definition now. The natural minor is the 6th degree mode of the major scale. It's rewarding to have read about that and then see it accidentally fall out of the model I've created. That relationship might actually stick in my head now. All of that work was so that I could encode the *M7♯11* chord, so I'll do that finally: #+BEGIN_SRC clojure (def chords {:M [:major [1 3 5]] :M7 [:major [1 3 5 7]] :m [:minor|natural [1 3 5]] :m7 [:minor|natural [1 3 5 7]] ;; ... :m6 [:minor|melodic [1 3 5 6]] :M7♯11 [:mode|lydian [1 3 5 7 11]]}) #+END_SRC At this point, it has become apparent to me that, while defining chords in terms of their scales taught me a lot about the relationship between them, it doesn't help me compare chords mentally because I have to think too hard about the scales (which I only know on paper). If I can factor out the indirection so that all chords are defined in the same absolute space, it would be an improvement. I could define everything in terms of the major scale, as is often done, but I really like thinking about the intervals as indexes in a space of notes. Defining them in terms of one specific scale means a lot of complexity around dealing with sharps and flats and other accidentals. Instead, I can define both chords and scales in terms of absolute distances from a starting note. I've found the representation used up until now to be extremely helpful so as I move on, I'll be thinking about how I can later /generate/ those previous representations when needed. Writing the chords out as pitch intervals (i.e. number of half steps) instead of as scale degrees will allow easy comparison of chords based on different scales. Intervals describe the distance between two pitches (in terms of physics, they are ratios between the frequencies of each pitch). This means we could use it to describe all scales in terms of the intervals between each note and its tonic note or the previous note. We can also describe all chords in the same fashion. This seems like a useful internal representation of these concepts, from which the prior representations can be derived anyway. In fact, my scales are already defined in this way, though I am representing them relatively instead of absolutely and indirectly converting them /to/ an absolute representation (inside =take-nths=): #+BEGIN_SRC clojure (reductions + 0 [W W h W W W h]) ;=> (0 2 4 5 7 9 11 12) #+END_SRC I then pluck those absolute half step counts from a chromatic series of notes to get the final scale: #+BEGIN_SRC clojure (map (partial nth (note-series :C)) '(0 2 4 5 7 9 11 12)) ;;=> (#{:C} #{:D} #{:E} #{:F} #{:G} #{:A} #{:B} #{:C}) #+END_SRC This strategy can work for chords too! #+BEGIN_SRC clojure ;; Am chord (map (partial nth (note-series :A)) [0 3 7]) ;=> (#{:A} #{:C} #{:E}) ;; G♯M7 (map (partial nth (note-series :G♯)) [0 4 7 11]) ;=> (#{:G♯ :A♭} #{:C} #{:D♯ :E♭} #{:G}) #+END_SRC Next, I want to write out a chord definition list in this fashion and adjust my =chord= function appropriately. However, these magic numbers aren't very meaningful by themselves and they don't reveal much about the nature of music. I'd rather reference them by name so that the significance of the difference between chords is shown most effectively. There are 12 half steps between a note and its octave note (13 if you count the 1:1 interval between a note and itself). These intervals are named by their *degree* (first/unison, second, ..., eighth/octave) and their *quality* (major, minor, and perfect). Some degrees are perfect, while some degrees have both a major and a minor quality. This doesn't make immediate sense and seems arbitrary. Here are the two octaves worth of intervals (note that the second octave just repeats the pattern of qualities) for us to think about. /Simple/ intervals are those within a single octave: | ½ Steps | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | |-----------+-----+-----+---+-----+---+-----+----+-----+-----+---+-----+----+-----| | *Degree* | 1st | 2nd | | 3rd | | 4th | - | 5th | 6th | | 7th | | 8th | | *Quality* | P | m | M | m | M | P | TT | P | m | M | m | M | P | /(I'll come to the *TT* interval at 6 half steps, later...)/ /Compound/ intervals are those that span more than one octave: | ½ Steps | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | |-----------+-----+-----+----+------+----+------+----+------+------+----+------+----+------| | *Degree* | 8th | 9th | | 10th | | 11th | - | 12th | 13th | | 14th | | 15th | | *Quality* | P | m | M | m | M | P | - | P | m | M | m | M | P | I'm going to define symbols for these interval names with the half step count as the value. I'm going to use a macro so that I can organize the symbols visually in a way that currently makes sense to me: #+BEGIN_SRC clojure #?(:clj (defmacro defintervals [& names] `(do (def ~'interval-names '[~@names]) ~@(map-indexed #(when-not (= '_ %2) (list 'def %2 %1)) names)))) (defintervals ;; simple P1 m2 M2 m3 M3 P4 TT ; tritone P5 m6 M6 m7 M7 P8 ;; compound m9 M9 m10 M10 P11 _ ; nameless? P12 m13 M13 m14 M14 P15) M2 ;=> 2 #+END_SRC If you don't understand macros, don't worry. See below to see how the macro is /expanded/ by the compiler, so you can understand what I could have written instead: #+BEGIN_SRC clojure :results output replace code :exports results :tangle no (let [form '(defintervals a b _ c) expanded (macroexpand form)] (print ";; ") (prn form) (list 'comment expanded)) #+END_SRC #+RESULTS[abea0fa4e5e21c5761923a6f25e261dbb2a17cc0]: #+BEGIN_SRC clojure ;; (defintervals a b _ c) (comment (do (def interval-names '[a b _ c]) (def a 0) (def b 1) nil (def c 3))) #+END_SRC Between the prior text and the following text, I spent about a day trying to really grok intervals. The idea of the number of halfsteps between two notes is obvious to understand, but the significance of the names applied to them is not. It seemed to me like more learn-by-rote and memorising special cases than I am comfortable with. Most explanations for the names were tautological without prior knowledge---"a major interval becomes a minor interval when inverted" doesn't actually reveal what it means to be major or minor in the first place! I tried to think about these intervals in terms of the scales I had already represented in code, and came up with what seemed like a rule of thumb and a use mnemonic: #+BEGIN_QUOTE Minor intervals are those which only appear in some minor scale. Of the remaining, the major intervals are those which appear in the major scale but only in some or no minor scale. Perfect intervals are those of the remaining which always appear in both. #+END_QUOTE Unfortunately, after thinking about it some more, this didn't fit. The *minor second* interval is not in any common minor scale. There isn't even a scale I can find which has just *♭2 ♭3 ♭6 ♭7* (though one might still exist). Furthermore, the interval between *perfect fourth* and *perfect fifth* isn't in either the major scale or a minor scale. It doesn't even have a *degree* or *quality*! What is going on‽ Luckily, I finally stumbled on [[http://music.stackexchange.com/a/30413/21702][an explanation]] that provided insight instead of yielding even more questions. The intervals from the root in an /ascending/ major scale form the major and perfect intervals. The intervals from the octave in a /descending/ major scale form the minor and perfect intervals. Perfect intervals are in both and the majors/minors are in the ascending/descending, respectively. At the heart of this is the concept of [[https://en.wikipedia.org/wiki/Interval_(music)#Inversion][inversions]]. In this context, it's raising the lowest or lowering the highest notes in an interval (e.g. *C→F* to *F→C*). An inverted *M7* interval (*C→B*) is a *m2* (*B→C*). The perfect intervals remain perfect (a *P5* becomes a *P4* and vice versa while the *P1* becomes *P8* and vice versa). That middle tone (6 half steps) which has no degree in the table above is called the [[https://en.wikipedia.org/wiki/Tritone][Tritone]]. It's special because it is directly in the middle of the chromatic 12 steps, which means its inversion is the same interval (*C→F♯* is the same number of half steps as *F♯→C*). It also doesn't appear (relative to the tonic or octave) in either the ascending or descending major scale, like the rest. Here's an example in terms of the *C Major* scale: | Interval | C1 | D | E | F | /(F♯)/ | G | A | B | C2 | |-----------+----+----+----+----+--------+----+----+----+----| | *from C1* | P1 | M2 | M3 | P4 | /(TT)/ | P5 | M6 | M7 | P8 | | *to C2* | P8 | m7 | m6 | P5 | /(TT)/ | P4 | m3 | m2 | P1 | #+BEGIN_SRC clojure :exports none (defn intervals-in-major-scale-component [] (let [major (partial scale :major) fmt (fn [t] (str/join "/" (map name t)))] (fn [] (let [scale (major @tonic) tri-tone (nth (note-series @tonic) 6) [front back] (split-at 4 scale)] [:div [key-selector-component] [:table [:thead [:tr [:th "Interval"] [:th (fmt (nth scale 0)) [:sub 1]] [:th (fmt (nth scale 1))] [:th (fmt (nth scale 2))] [:th (fmt (nth scale 3))] [:th [:i (str "(" (fmt tri-tone) ")")]] [:th (fmt (nth scale 4))] [:th (fmt (nth scale 5))] [:th (fmt (nth scale 6))] [:th (fmt (nth scale 7)) [:sub 2]]] #_(vec (concat [:tr [:th "Interval"]] (map fmt front) [(fmt tri-tone)] (map fmt back)))]]])))) #+END_SRC #+BEGIN_HTML