<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.3.2">Jekyll</generator><link href="https://www.brianfogg.com/feed.xml" rel="self" type="application/atom+xml" /><link href="https://www.brianfogg.com/" rel="alternate" type="text/html" /><updated>2025-08-26T04:53:48+00:00</updated><id>https://www.brianfogg.com/feed.xml</id><title type="html">brianfogg.com</title><entry><title type="html">Hiking the PCT - 2024</title><link href="https://www.brianfogg.com/blog/hiking-the-pct-2024/" rel="alternate" type="text/html" title="Hiking the PCT - 2024" /><published>2024-05-25T12:23:00+00:00</published><updated>2024-05-25T12:23:00+00:00</updated><id>https://www.brianfogg.com/blog/pct-hike</id><content type="html" xml:base="https://www.brianfogg.com/blog/hiking-the-pct-2024/"><![CDATA[<p><a target="_blank" href="https://www.pcta.org/discover-the-trail/maps/overview-maps/">
<img style="max-width: 500px; display: block; margin: auto;" src="https://www.pcta.org/wp-content/uploads/2019/12/PCT-overview-map-on-1-page-by-Magellan-v.1.2018.jpg" />
</a></p>

<hr />

<p>Update: May 31st</p>

<p>One day before leaving for this trip a client called and made me an offer I could not refuse for a month of consulting work. I’ll be postponing this trip until further notice. Funny how that happens… I would rather not spend a month hiking while money is on the table. Better to do this trip while actually unemployed.</p>

<hr />

<p>I’ll be hiking the PCT this summer. Planning to start between June 5th and June 10th and I’ll hike north until I get tired of it (or someone calls me about work).</p>

<p>If you’re interested in joining me for a section, you can follow my position and message me via the Garmin Explore portal below. I’m carrying a Garmin inRreach Mini so I’ll be able to receive and send messages/locations and I’ll try to update my position nightly.</p>

<p>(If the iframe doesn’t load correctly in your browser, you can visit the page on Garmin’s website directly.)</p>

<p><a target="_blank" href="https://share.garmin.com/brianlocation">https://share.garmin.com/brianlocation</a></p>

<iframe width="100%" height="700px" src="https://share.garmin.com/brianlocation"></iframe>

<p><a target="_blank" href="https://docs.google.com/spreadsheets/d/1Rc9P1SoY3aS2UA5cTHT1O7RZ5cPxkCcCQb-E-_XQQg8/edit?usp=sharing">Spreadsheet with everything in my backpack</a></p>

<iframe width="100%" height="700px" src="https://docs.google.com/spreadsheets/d/e/2PACX-1vSnPOFTE3VLWrXYZF--CDyUVKfK_CUsqdu6FlaUXwztle_ZQFSvOXIpiN96CUiSbWIHIVYRKk3InrTm/pubhtml?widget=true&amp;headers=false"></iframe>]]></content><author><name></name></author><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">Coltrane as code</title><link href="https://www.brianfogg.com/blog/coltrane-as-code/" rel="alternate" type="text/html" title="Coltrane as code" /><published>2023-04-06T12:23:00+00:00</published><updated>2023-04-06T12:23:00+00:00</updated><id>https://www.brianfogg.com/blog/coltrane-as-code</id><content type="html" xml:base="https://www.brianfogg.com/blog/coltrane-as-code/"><![CDATA[<div style="display: flex; justify-content: center;">
    <div style="max-width: 400px">
        <div>
    <img style="border-radius: .2rem;" src="/assets/images/blog/coltrane/coltrane-circle.png" alt="" />
    <p style="text-align: center; color: darkgrey; margin-top: 0;"></p>
</div>
    </div>
</div>

<h3 id="giant-steps">Giant Steps</h3>

<p>This post is a messy work in progress:</p>

<p><a href="https://github.com/fogg4444/coltrane-as-code">Github repo with all code used in this article</a></p>

<p>What a song. I had always heard about the geometric underpinnings of this tune, and last year I learned it on piano.</p>

<p>Much has been written about the music theory in this Coltrane’s Giant Steps. <a href="https://roelhollander.eu/en/blog-saxophone/Coltrane-Geometry/">This excellent post by Roel Hollander</a> lays things out very nicely. The song uses a multi-tonic structure, sometimes referred to as the “Coltrane Matrix”.</p>

<p>I always wondered why these relationships were chosen. And if the relationships were different, how would it sound? Changing one element of the pattern, without modifying the others is tedious to do by hand, but if this song could be translated into a parameterized function, we could iterate on the chordal relationships in a very granular way.</p>

<p>I’ve been working on a blog post profiling my friend Dan Gorelick and his live coding work. He introduced me to Tidal cycles and I started experimenting in the browser with <a href="https://strudel.tidalcycles.org/">Strudel REPL</a>.</p>

<p>The genesis of this post arrived purely by accident while randomly shuffling through the provided code samples provided in web tool.</p>

<div>
    <iframe width="100%" height="400px" src="https://strudel.tidalcycles.org/#Ly8gSm9obiBDb2x0cmFuZSAtIEdpYW50IFN0ZXBzCnNldFZvaWNpbmdSYW5nZSgnbGVmdGhhbmQnLCBbJ0UzJywgJ0c0J10pOwoKc3RhY2soCiAgLy8gbWVsb2R5CiAgc2VxKAogICAgIltGIzUgRDVdIFtCNCBHNF0gQmI0IFtCNCBBNF0iLAogICAgIltENSBCYjRdIFtHNCBFYjRdIEYjNCBbRzQgRjRdIiwKICAgICJCYjQgW0I0IEE0XSBENSBbRCM1IEMjNV0iLAogICAgIkYjNSBbRzUgRjVdIEJiNSBbRiM1IEYjNV0iLAogICkuY29sb3IoJyNGOEU3MUMnKSwKICAvLyBjaG9yZHMKICBzZXEoCiAgICAiW0JeNyBEN10gW0deNyBCYjddIEViXjcgW0FtNyBEN10iLAogICAgIltHXjcgQmI3XSBbRWJeNyBGIzddIEJeNyBbRm03IEJiN10iLAogICAgIkViXjcgW0FtNyBEN10gR143IFtDI203IEYjN10iLAogICAgIkJeNyBbRm03IEJiN10gRWJeNyBbQyNtNyBGIzddIgogICkudm9pY2luZ3MoJ2xlZnRoYW5kJykuY29sb3IoJyM3RUQzMjEnKSwKICAvLyBiYXNzCiAgc2VxKAogICAgIltCMiBEMl0gW0cyIEJiMl0gW0ViMiBCYjNdIFtBMiBEMl0iLAogICAgIltHMiBCYjJdIFtFYjIgRiMyXSBbQjIgRiMyXSBbRjIgQmIyXSIsCiAgICAiW0ViMiBCYjJdIFtBMiBEMl0gW0cyIEQyXSBbQyMyIEYjMl0iLAogICAgIltCMiBGIzJdIFtGMiBCYjJdIFtFYjIgQmIzXSBbQyMyIEYjMl0iCiAgKS5jb2xvcignIzAwQjhENCcpCikuc2xvdygyMCkubm90ZSgpCi8vLnBpYW5vcm9sbCh7Zm9sZDoxfSk%3D"></iframe>
</div>

<p>I tried asking GPT-4 to modify this in several ways but it had a hard time with the format. GPT wanted to use functions to generate the chords but the Strudel language didn’t seem to have a great functional interface. I haven’t read all the docs but it seems to operate more like a declarative config style language. I switched gears towards code generation and began building a generator function in Javascript.</p>

<p>So the goal would be to take a string like this:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    "[B^7 D7] [G^7 Bb7] Eb^7 [Am7 D7]",
    "[G^7 Bb7] [Eb^7 F#7] B^7 [Fm7 Bb7]",
    "Eb^7 [Am7 D7] G^7 [C#m7 F#7]",
    "B^7 [Fm7 Bb7] Eb^7 [C#m7 F#7]"
</code></pre></div></div>

<p>and turn it into a series of functions which could be called according to their tonal center, and degree of scale from that center. We’re assuming a few things here, namely that the tonal center is an important idea, and that in this song there is a clear tonal center for each note and chord. According to Roel and other’s analysis, that seems to be the case. I’m pondering how this code would work (or not work) for music with more abstract tonal definition.</p>

<p>B^7 in the Strudel string notation would have to be written something like this:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    <span class="nf">generateChord</span><span class="p">({</span>
        <span class="na">tonalCenter</span><span class="p">:</span> <span class="dl">"</span><span class="s2">B</span><span class="dl">"</span><span class="p">,</span>
        <span class="na">romanNumeral</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
        <span class="na">chordType</span><span class="p">:</span> <span class="dl">"</span><span class="s2">major</span><span class="dl">"</span>
    <span class="p">})</span>
</code></pre></div></div>

<p>I re-arranged the Giant Steps Strudel format string into an array based data structure:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    <span class="kd">const</span> <span class="nx">giantStepsChordArray</span> <span class="o">=</span> <span class="p">[</span>
        <span class="p">[</span><span class="dl">'</span><span class="s1">B^7</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">D7</span><span class="dl">'</span><span class="p">],</span>
        <span class="p">[</span><span class="dl">'</span><span class="s1">G^7</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">Bb7</span><span class="dl">'</span><span class="p">],</span>
        <span class="dl">'</span><span class="s1">Eb^7</span><span class="dl">'</span><span class="p">,</span>
        <span class="p">[</span><span class="dl">'</span><span class="s1">Am7</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">D7</span><span class="dl">'</span><span class="p">],</span>
        <span class="p">[</span><span class="dl">'</span><span class="s1">G^7</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">Bb7</span><span class="dl">'</span><span class="p">],</span>
        <span class="p">[</span><span class="dl">'</span><span class="s1">Eb^7</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">F#7</span><span class="dl">'</span><span class="p">],</span>
        <span class="dl">'</span><span class="s1">B^7</span><span class="dl">'</span><span class="p">,</span>
        <span class="p">[</span><span class="dl">'</span><span class="s1">Fm7</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">Bb7</span><span class="dl">'</span><span class="p">],</span>
        <span class="dl">'</span><span class="s1">Eb^7</span><span class="dl">'</span><span class="p">,</span>
        <span class="p">[</span><span class="dl">'</span><span class="s1">Am7</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">D7</span><span class="dl">'</span><span class="p">],</span>
        <span class="dl">'</span><span class="s1">G^7</span><span class="dl">'</span><span class="p">,</span>
        <span class="p">[</span><span class="dl">'</span><span class="s1">C#m7</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">F#7</span><span class="dl">'</span><span class="p">],</span>
        <span class="dl">'</span><span class="s1">B^7</span><span class="dl">'</span><span class="p">,</span>
        <span class="p">[</span><span class="dl">'</span><span class="s1">Fm7</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">Bb7</span><span class="dl">'</span><span class="p">],</span>
        <span class="dl">'</span><span class="s1">Eb^7</span><span class="dl">'</span><span class="p">,</span>
        <span class="p">[</span><span class="dl">'</span><span class="s1">C#m7</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">F#7</span><span class="dl">'</span><span class="p">]</span>
    <span class="p">];</span>
</code></pre></div></div>

<p>and then set about modifying each chord in this array to form a comprehensive configuration object I could later pass to a function:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    <span class="kd">const</span> <span class="nx">giantStepsDataStructure</span> <span class="o">=</span> <span class="p">[</span>
        <span class="c1">// ['B^7', 'D7'],</span>
        <span class="p">[{</span>
            <span class="c1">// tonalCenter: "?",</span>
            <span class="c1">// romanNumeral: ?,</span>
            <span class="na">chordType</span><span class="p">:</span> <span class="dl">'</span><span class="s1">^</span><span class="dl">'</span>
        <span class="p">},</span> <span class="p">{</span>
            <span class="c1">// tonalCenter: "?",</span>
            <span class="c1">// romanNumeral: ?,</span>
            <span class="na">chordType</span><span class="p">:</span> <span class="dl">'</span><span class="s1">7</span><span class="dl">'</span>
        <span class="p">}],</span>
        <span class="nx">etc</span><span class="p">...</span>
</code></pre></div></div>

<p>Well, this is tedious. Now we need to actually figure out what the tonal center of each of these chords is, so we can set the relative roman numeral position correctly. a little more reading at the various blogs…</p>

<p><a href="https://j.eu/en/blog-saxophone/Coltrane-Geometry/">https://j.eu/en/blog-saxophone/Coltrane-Geometry/</a>
<a href="https://www.learnjazzstandards.com/blog/understanding-coltrane-changes-part-1/">https://www.learnjazzstandards.com/blog/understanding-coltrane-changes-part-1/</a></p>

<p>I hope I’m not losing you all by sucking all the soul out of this timeless jazz standard and reducing it to code… This does feel like some sort of perverse fetish to compulsively parameterize and automate all things… Once this is finished I’ll be able to tweak a parameter or two and everything will probably sound like trash, (in a perfectly systematic and repeatable way!). So definitely a gamble here, but once this code is all set up we’ll be able to quickly iterate on weird and radical reharmonizations of Giant Steps.</p>

<p>Ok, so for the first three chords BMajor7 -&gt; D7 -&gt; GMajor7 we’re starting on the tonic of one key (B), moving up a minor third to D7 (the fifth degree of our next scale), then resolving down the perfect fifth to G (the new root), which from the perspective of our original tonic B is a downwards movement of a Major Third. This pattern repeats twice landing on a long Eb^7 before shifting keys again across a 2-&gt;5 progression.</p>

<p>This can be reflected in our javascript config object as such:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    <span class="kd">const</span> <span class="nx">giantStepsDataStructure</span> <span class="o">=</span> <span class="p">[</span>
        <span class="c1">// ['B^7', 'D7'],</span>
        <span class="p">[{</span>
            <span class="na">tonalCenter</span><span class="p">:</span>  <span class="nx">note</span><span class="p">.</span><span class="nx">B</span><span class="p">,</span>
            <span class="na">romanNumeral</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
            <span class="na">chordType</span><span class="p">:</span>    <span class="nx">chordType</span><span class="p">.</span><span class="nx">majorSeventh</span>
        <span class="p">},</span> <span class="p">{</span>
            <span class="na">tonalCenter</span><span class="p">:</span>  <span class="nx">note</span><span class="p">.</span><span class="nx">G</span><span class="p">,</span>
            <span class="na">romanNumeral</span><span class="p">:</span> <span class="mi">5</span><span class="p">,</span>
            <span class="na">chordType</span><span class="p">:</span>    <span class="nx">chordType</span><span class="p">.</span><span class="nx">dominantSeventh</span>
        <span class="p">}],</span>

        <span class="c1">// ['G^7', 'Bb7'],</span>
        <span class="p">[{</span>
            <span class="na">tonalCenter</span><span class="p">:</span>  <span class="nx">note</span><span class="p">.</span><span class="nx">G</span><span class="p">,</span>
            <span class="na">romanNumeral</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
            <span class="na">chordType</span><span class="p">:</span>    <span class="nx">chordType</span><span class="p">.</span><span class="nx">majorSeventh</span>
        <span class="p">},</span> <span class="p">{</span>
            <span class="na">tonalCenter</span><span class="p">:</span>  <span class="nx">note</span><span class="p">.</span><span class="nx">Eb</span><span class="p">,</span>
            <span class="na">romanNumeral</span><span class="p">:</span> <span class="mi">5</span><span class="p">,</span>
            <span class="na">chordType</span><span class="p">:</span>    <span class="nx">chordType</span><span class="p">.</span><span class="nx">dominantSeventh</span>
        <span class="p">}],</span>

        <span class="c1">// 'Eb^7',</span>
        <span class="p">{</span>
            <span class="na">tonalCenter</span><span class="p">:</span>  <span class="nx">note</span><span class="p">.</span><span class="nx">Eb</span><span class="p">,</span>
            <span class="na">romanNumeral</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
            <span class="na">chordType</span><span class="p">:</span>    <span class="nx">chordType</span><span class="p">.</span><span class="nx">majorSeventh</span>
        <span class="p">},</span>

        <span class="c1">// ['Am7', 'D7'],</span>
        <span class="p">[{</span>
            <span class="na">tonalCenter</span><span class="p">:</span>  <span class="nx">note</span><span class="p">.</span><span class="nx">G</span><span class="p">,</span>
            <span class="na">romanNumeral</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span>
            <span class="na">chordType</span><span class="p">:</span>    <span class="nx">chordType</span><span class="p">.</span><span class="nx">minorSeventh</span>
        <span class="p">},</span> <span class="p">{</span>
            <span class="na">tonalCenter</span><span class="p">:</span>  <span class="nx">note</span><span class="p">.</span><span class="nx">G</span><span class="p">,</span>
            <span class="na">romanNumeral</span><span class="p">:</span> <span class="mi">5</span><span class="p">,</span>
            <span class="na">chordType</span><span class="p">:</span>    <span class="nx">chordType</span><span class="p">.</span><span class="nx">dominantSeventh</span>
        <span class="p">}],</span>
        <span class="nx">etc</span><span class="p">...</span>
</code></pre></div></div>

<p>So I think it’s time to build a formatter to process this data set and render strings friendly to Strudel</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    <span class="kd">const</span> <span class="nx">note</span> <span class="o">=</span> <span class="p">{</span>
        <span class="na">C</span>  <span class="p">:</span> <span class="dl">"</span><span class="s2">C</span><span class="dl">"</span><span class="p">,</span>
        <span class="nx">C</span><span class="na">$</span> <span class="p">:</span> <span class="dl">"</span><span class="s2">C#</span><span class="dl">"</span><span class="p">,</span>
        <span class="na">Db</span> <span class="p">:</span> <span class="dl">"</span><span class="s2">Db</span><span class="dl">"</span><span class="p">,</span>
        <span class="na">D</span>  <span class="p">:</span> <span class="dl">"</span><span class="s2">D</span><span class="dl">"</span><span class="p">,</span>
        <span class="nx">D</span><span class="na">$</span> <span class="p">:</span> <span class="dl">"</span><span class="s2">D#</span><span class="dl">"</span><span class="p">,</span>
        <span class="na">Eb</span> <span class="p">:</span> <span class="dl">"</span><span class="s2">Eb</span><span class="dl">"</span><span class="p">,</span>
        <span class="na">E</span>  <span class="p">:</span> <span class="dl">"</span><span class="s2">E</span><span class="dl">"</span><span class="p">,</span>
        <span class="nx">E</span><span class="na">$</span> <span class="p">:</span> <span class="dl">"</span><span class="s2">E#</span><span class="dl">"</span><span class="p">,</span>
        <span class="na">F</span>  <span class="p">:</span> <span class="dl">"</span><span class="s2">F</span><span class="dl">"</span><span class="p">,</span>
        <span class="nx">F</span><span class="na">$</span> <span class="p">:</span> <span class="dl">"</span><span class="s2">F#</span><span class="dl">"</span><span class="p">,</span>
        <span class="na">G</span>  <span class="p">:</span> <span class="dl">"</span><span class="s2">G</span><span class="dl">"</span><span class="p">,</span>
        <span class="nx">G</span><span class="na">$</span> <span class="p">:</span> <span class="dl">"</span><span class="s2">G#</span><span class="dl">"</span><span class="p">,</span>
        <span class="na">A</span>  <span class="p">:</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span><span class="p">,</span>
        <span class="nx">A</span><span class="na">$</span> <span class="p">:</span> <span class="dl">"</span><span class="s2">A#</span><span class="dl">"</span><span class="p">,</span>
        <span class="na">B</span>  <span class="p">:</span> <span class="dl">"</span><span class="s2">B</span><span class="dl">"</span><span class="p">,</span>
        <span class="nx">B</span><span class="na">$</span> <span class="p">:</span> <span class="dl">"</span><span class="s2">B#</span><span class="dl">"</span>
    <span class="p">}</span>

    <span class="kd">const</span> <span class="nx">noteToMidiNumber</span> <span class="o">=</span> <span class="p">{</span>
        <span class="p">[</span><span class="nx">note</span><span class="p">.</span><span class="nx">C</span><span class="p">]</span>  <span class="p">:</span> <span class="mi">0</span><span class="p">,</span>
        <span class="p">[</span><span class="nx">note</span><span class="p">.</span><span class="nx">C$</span><span class="p">]</span> <span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
        <span class="p">[</span><span class="nx">note</span><span class="p">.</span><span class="nx">Db</span><span class="p">]</span> <span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
        <span class="p">[</span><span class="nx">note</span><span class="p">.</span><span class="nx">D</span><span class="p">]</span>  <span class="p">:</span> <span class="mi">2</span><span class="p">,</span>
        <span class="p">[</span><span class="nx">note</span><span class="p">.</span><span class="nx">D$</span><span class="p">]</span> <span class="p">:</span> <span class="mi">3</span><span class="p">,</span>
        <span class="p">[</span><span class="nx">note</span><span class="p">.</span><span class="nx">Eb</span><span class="p">]</span> <span class="p">:</span> <span class="mi">3</span><span class="p">,</span>
        <span class="p">[</span><span class="nx">note</span><span class="p">.</span><span class="nx">E</span><span class="p">]</span>  <span class="p">:</span> <span class="mi">4</span><span class="p">,</span>
        <span class="p">[</span><span class="nx">note</span><span class="p">.</span><span class="nx">E$</span><span class="p">]</span> <span class="p">:</span> <span class="mi">5</span><span class="p">,</span>
        <span class="p">[</span><span class="nx">note</span><span class="p">.</span><span class="nx">Fb</span><span class="p">]</span> <span class="p">:</span> <span class="mi">4</span><span class="p">,</span>
        <span class="p">[</span><span class="nx">note</span><span class="p">.</span><span class="nx">F</span><span class="p">]</span>  <span class="p">:</span> <span class="mi">5</span><span class="p">,</span>
        <span class="p">[</span><span class="nx">note</span><span class="p">.</span><span class="nx">F$</span><span class="p">]</span> <span class="p">:</span> <span class="mi">6</span><span class="p">,</span>
        <span class="p">[</span><span class="nx">note</span><span class="p">.</span><span class="nx">Gb</span><span class="p">]</span> <span class="p">:</span> <span class="mi">6</span><span class="p">,</span>
        <span class="p">[</span><span class="nx">note</span><span class="p">.</span><span class="nx">G</span><span class="p">]</span>  <span class="p">:</span> <span class="mi">7</span><span class="p">,</span>
        <span class="p">[</span><span class="nx">note</span><span class="p">.</span><span class="nx">G$</span><span class="p">]</span> <span class="p">:</span> <span class="mi">8</span><span class="p">,</span>
        <span class="p">[</span><span class="nx">note</span><span class="p">.</span><span class="nx">Ab</span><span class="p">]</span> <span class="p">:</span> <span class="mi">8</span><span class="p">,</span>
        <span class="p">[</span><span class="nx">note</span><span class="p">.</span><span class="nx">A</span><span class="p">]</span>  <span class="p">:</span> <span class="mi">9</span><span class="p">,</span>
        <span class="p">[</span><span class="nx">note</span><span class="p">.</span><span class="nx">A$</span><span class="p">]</span> <span class="p">:</span> <span class="mi">10</span><span class="p">,</span>
        <span class="p">[</span><span class="nx">note</span><span class="p">.</span><span class="nx">Bb</span><span class="p">]</span> <span class="p">:</span> <span class="mi">10</span><span class="p">,</span>
        <span class="p">[</span><span class="nx">note</span><span class="p">.</span><span class="nx">B</span><span class="p">]</span>  <span class="p">:</span> <span class="mi">11</span><span class="p">,</span>
        <span class="p">[</span><span class="nx">note</span><span class="p">.</span><span class="nx">B$</span><span class="p">]</span> <span class="p">:</span> <span class="mi">12</span><span class="p">,</span>
    <span class="p">};</span>

    <span class="kd">function</span> <span class="nf">noteToMidi</span><span class="p">(</span><span class="nx">noteName</span><span class="p">)</span> <span class="p">{</span>
        <span class="c1">// hardcoding all octaves to 1 for now</span>
        <span class="c1">// not yet ready to deal with this complexity</span>
        <span class="kd">const</span> <span class="nx">octave</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
        <span class="k">return</span> <span class="nx">noteToMidiNumber</span><span class="p">[</span><span class="nx">noteName</span><span class="p">]</span> <span class="o">+</span> <span class="mi">12</span> <span class="o">*</span> <span class="p">(</span><span class="nx">octave</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span>
    <span class="p">}</span>
    
    <span class="kd">function</span> <span class="nf">midiToNote</span><span class="p">(</span><span class="nx">midiNoteNumber</span><span class="p">)</span> <span class="p">{</span>
        <span class="kd">const</span> <span class="nx">numberToNote</span> <span class="o">=</span> <span class="p">[</span>
            <span class="nx">note</span><span class="p">.</span><span class="nx">C</span><span class="p">,</span> <span class="nx">note</span><span class="p">.</span><span class="nx">C$</span><span class="p">,</span> <span class="nx">note</span><span class="p">.</span><span class="nx">D</span><span class="p">,</span> <span class="nx">note</span><span class="p">.</span><span class="nx">D$</span><span class="p">,</span> <span class="nx">note</span><span class="p">.</span><span class="nx">E</span><span class="p">,</span> <span class="nx">note</span><span class="p">.</span><span class="nx">F</span><span class="p">,</span> <span class="nx">note</span><span class="p">.</span><span class="nx">F$</span><span class="p">,</span> <span class="nx">note</span><span class="p">.</span><span class="nx">G</span><span class="p">,</span> <span class="nx">note</span><span class="p">.</span><span class="nx">G$</span><span class="p">,</span> <span class="nx">note</span><span class="p">.</span><span class="nx">A</span><span class="p">,</span> <span class="nx">note</span><span class="p">.</span><span class="nx">A$</span><span class="p">,</span> <span class="nx">note</span><span class="p">.</span><span class="nx">B</span>
        <span class="p">];</span>

        <span class="c1">// const octave = Math.floor(midiNoteNumber / 12) - 1;</span>
        <span class="kd">const</span> <span class="nx">noteName</span> <span class="o">=</span> <span class="nx">numberToNote</span><span class="p">[</span><span class="nx">midiNoteNumber</span> <span class="o">%</span> <span class="mi">12</span><span class="p">];</span>

        <span class="c1">// return noteName + octave;</span>
        <span class="k">return</span> <span class="nx">noteName</span><span class="p">;</span>
    <span class="p">}</span>
    
    <span class="kd">const</span> <span class="nx">romanNumeralToInterval</span> <span class="o">=</span> <span class="p">{</span>
        <span class="mi">1</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span>
        <span class="mi">2</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span>
        <span class="mi">3</span><span class="p">:</span> <span class="mi">4</span><span class="p">,</span>
        <span class="mi">4</span><span class="p">:</span> <span class="mi">5</span><span class="p">,</span>
        <span class="mi">5</span><span class="p">:</span> <span class="mi">7</span><span class="p">,</span>
        <span class="mi">6</span><span class="p">:</span> <span class="mi">9</span><span class="p">,</span>
        <span class="mi">7</span><span class="p">:</span> <span class="mi">11</span>
    <span class="p">};</span>

    <span class="kd">const</span> <span class="nx">chordType</span> <span class="o">=</span> <span class="p">{</span>
        <span class="na">minorSeventh</span>    <span class="p">:</span> <span class="dl">'</span><span class="s1">-</span><span class="dl">'</span><span class="p">,</span>
        <span class="na">majorSeventh</span>    <span class="p">:</span> <span class="dl">'</span><span class="s1">^</span><span class="dl">'</span><span class="p">,</span>
        <span class="na">dominantSeventh</span> <span class="p">:</span> <span class="dl">'</span><span class="s1">7</span><span class="dl">'</span><span class="p">,</span>
        <span class="na">minSevenFlat5</span>   <span class="p">:</span> <span class="dl">"</span><span class="s2">ø</span><span class="dl">"</span>
    <span class="p">}</span>

    <span class="kd">const</span> <span class="nx">chordQualityMapping</span> <span class="o">=</span> <span class="p">{</span>
        <span class="p">[</span><span class="nx">chordType</span><span class="p">.</span><span class="nx">majorSeventh</span><span class="p">]</span>    <span class="p">:</span> <span class="dl">"</span><span class="s2">^7</span><span class="dl">"</span><span class="p">,</span>
        <span class="p">[</span><span class="nx">chordType</span><span class="p">.</span><span class="nx">minorSeventh</span><span class="p">]</span>    <span class="p">:</span> <span class="dl">"</span><span class="s2">m7</span><span class="dl">"</span><span class="p">,</span>
        <span class="p">[</span><span class="nx">chordType</span><span class="p">.</span><span class="nx">minSevenFlat5</span><span class="p">]</span>   <span class="p">:</span> <span class="dl">"</span><span class="s2">m7b5</span><span class="dl">"</span><span class="p">,</span>
        <span class="p">[</span><span class="nx">chordType</span><span class="p">.</span><span class="nx">dominantSeventh</span><span class="p">]</span> <span class="p">:</span> <span class="dl">"</span><span class="s2">7</span><span class="dl">"</span>
    <span class="p">};</span>

    <span class="kd">const</span> <span class="nx">generateChord</span> <span class="o">=</span> <span class="p">({</span> <span class="nx">tonalCenter</span><span class="p">,</span> <span class="nx">romanNumeral</span><span class="p">,</span> <span class="nx">chordType</span> <span class="p">})</span> <span class="o">=&gt;</span> <span class="p">{</span>

        <span class="c1">// extract midi note from note string</span>
        <span class="kd">const</span> <span class="nx">rootMidiNote</span> <span class="o">=</span> <span class="nf">noteToMidi</span><span class="p">(</span><span class="nx">tonalCenter</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>
        
        <span class="c1">// modify root midi note by it's roman numeral interval offset</span>
        <span class="kd">const</span> <span class="nx">newRootMidiNumber</span> <span class="o">=</span> <span class="nx">rootMidiNote</span> <span class="o">+</span> <span class="nx">romanNumeralToInterval</span><span class="p">[</span><span class="nx">romanNumeral</span><span class="p">];</span>

        <span class="kd">const</span> <span class="nx">newRootNoteName</span> <span class="o">=</span> <span class="nf">midiToNote</span><span class="p">(</span><span class="nx">newRootMidiNumber</span><span class="p">)</span>

        <span class="c1">// now append the chord type information to this string</span>
        <span class="kd">const</span> <span class="nx">fullChordDefinition</span> <span class="o">=</span> <span class="nx">newRootNoteName</span> <span class="o">+</span> <span class="nx">chordQualityMapping</span><span class="p">[</span><span class="nx">chordType</span><span class="p">]</span>

        <span class="c1">// return fullChordDefinition;</span>
        <span class="k">return</span> <span class="nx">fullChordDefinition</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="kd">const</span> <span class="nx">recursiveGiantStepsParser</span> <span class="o">=</span> <span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
        <span class="nf">if</span><span class="p">(</span><span class="nb">Array</span><span class="p">.</span><span class="nf">isArray</span><span class="p">(</span><span class="nx">data</span><span class="p">))</span> <span class="p">{</span>
            <span class="kd">const</span> <span class="nx">result</span> <span class="o">=</span> <span class="p">[];</span>

            <span class="c1">// add opening bracket</span>
            <span class="nx">result</span><span class="p">.</span><span class="nf">push</span><span class="p">(</span><span class="dl">'</span><span class="s1">[</span><span class="dl">'</span><span class="p">)</span>
            
            <span class="c1">// loop over each item and recurse if it's not a string</span>
            <span class="nx">data</span><span class="p">.</span><span class="nf">forEach</span><span class="p">((</span><span class="nx">eachElem</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
                <span class="nx">result</span><span class="p">.</span><span class="nf">push</span><span class="p">(</span><span class="nf">recursiveGiantStepsParser</span><span class="p">(</span><span class="nx">eachElem</span><span class="p">));</span>
            <span class="p">})</span>

            <span class="c1">// add closing bracket</span>
            <span class="nx">result</span><span class="p">.</span><span class="nf">push</span><span class="p">(</span><span class="dl">'</span><span class="s1">]</span><span class="dl">'</span><span class="p">)</span>
            
            <span class="c1">// join with a space so it's readable</span>
            <span class="k">return</span> <span class="nx">result</span><span class="p">.</span><span class="nf">join</span><span class="p">(</span><span class="dl">'</span><span class="s1"> </span><span class="dl">'</span><span class="p">);</span>
        <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
            <span class="c1">// Assuming we don't have anything but arrays and chord param objects here</span>
            <span class="k">return</span> <span class="nf">generateChord</span><span class="p">({</span>
                <span class="na">tonalCenter</span><span class="p">:</span> <span class="nx">data</span><span class="p">.</span><span class="nx">tonalCenter</span><span class="p">,</span>
                <span class="na">romanNumeral</span><span class="p">:</span> <span class="nx">data</span><span class="p">.</span><span class="nx">romanNumeral</span><span class="p">,</span>
                <span class="na">chordType</span><span class="p">:</span> <span class="nx">data</span><span class="p">.</span><span class="nx">chordType</span>
            <span class="p">});</span>
        <span class="p">}</span>
    <span class="p">}</span>
</code></pre></div></div>

<p>And after all that code, we get this:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    [ [ B^7 D7 ] [ G^7 A#7 ] D#^7 [ Am7 D7 ] [ G^7 A#7 ] [ D#^7 F#7 ] B^7 [ Fm7 A#7 ] D#^7 [ Am7 D7 ] G^7 [ C#m7 F#7 ] B^7 [ Fm7 A#7 ] D#7 [ C#m7 F#7 ] ]
</code></pre></div></div>

<p>Let’s compare to our original source string:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    "[B^7 D7] [G^7 Bb7] Eb^7 [Am7 D7]",
    "[G^7 Bb7] [Eb^7 F#7] B^7 [Fm7 Bb7]",
    "Eb^7 [Am7 D7] G^7 [C#m7 F#7]",
    "B^7 [Fm7 Bb7] Eb^7 [C#m7 F#7]"
</code></pre></div></div>

<p>Ok, so it’s a one liner, but not too bad</p>

<p>The chords are rendering slightly differently but they are technically the same. Bb7 equates to A#7 for example. I should really fix the code to operate in flats since the original track is in flats. This output is going to be so modulated once we start experimenting that it hardly matters. I’ll have a few friends try to solo over this when it’s done. I hope they don’t mind that it’s all sharps. Maybe we can modify the code later.</p>

<p>So, the first modulation I want to attempt is changing the roman numerals across the song. In this case, my code is still not sufficiently parameterized, so we’ll add this romanNumeralMap object:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    <span class="kd">const</span> <span class="nx">romanNumeralMap</span> <span class="o">=</span> <span class="p">{</span>
        <span class="mi">1</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
        <span class="mi">2</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span>
        <span class="mi">3</span><span class="p">:</span> <span class="mi">3</span><span class="p">,</span>
        <span class="mi">4</span><span class="p">:</span> <span class="mi">4</span><span class="p">,</span>
        <span class="mi">5</span><span class="p">:</span> <span class="mi">5</span><span class="p">,</span>
        <span class="mi">6</span><span class="p">:</span> <span class="mi">6</span><span class="p">,</span>
        <span class="mi">7</span><span class="p">:</span> <span class="mi">7</span>
    <span class="p">}</span>
    <span class="kd">const</span> <span class="nx">giantStepsDataStructure</span> <span class="o">=</span> <span class="p">[</span>
    <span class="c1">// ['B^7', 'D7'],</span>
    <span class="p">[{</span>
        <span class="na">tonalCenter</span><span class="p">:</span>  <span class="nx">note</span><span class="p">.</span><span class="nx">B</span><span class="p">,</span>
        <span class="na">romanNumeral</span><span class="p">:</span> <span class="nx">romanNumeralMap</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span>
        <span class="na">chordType</span><span class="p">:</span>    <span class="nx">chordType</span><span class="p">.</span><span class="nx">majorSeventh</span>
    <span class="p">},</span> <span class="p">{</span>
        <span class="na">tonalCenter</span><span class="p">:</span>  <span class="nx">note</span><span class="p">.</span><span class="nx">G</span><span class="p">,</span>
        <span class="na">romanNumeral</span><span class="p">:</span> <span class="nx">romanNumeralMap</span><span class="p">[</span><span class="mi">5</span><span class="p">],</span>
        <span class="na">chordType</span><span class="p">:</span>    <span class="nx">chordType</span><span class="p">.</span><span class="nx">dominantSeventh</span>
    <span class="p">}],</span>
</code></pre></div></div>

<p>This allows a single line re-configuration of the song. For example:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    <span class="kd">const</span> <span class="nx">romanNumeralMap</span> <span class="o">=</span> <span class="p">{</span>
        <span class="mi">1</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
        <span class="mi">2</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span>
        <span class="mi">3</span><span class="p">:</span> <span class="mi">3</span><span class="p">,</span>
        <span class="mi">4</span><span class="p">:</span> <span class="mi">4</span><span class="p">,</span>
        <span class="mi">5</span><span class="p">:</span> <span class="mi">5</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span>
        <span class="mi">6</span><span class="p">:</span> <span class="mi">6</span><span class="p">,</span>
        <span class="mi">7</span><span class="p">:</span> <span class="mi">7</span>
    <span class="p">}</span>
</code></pre></div></div>

<p>For example switching all 5th degree chords to sixths! Output rendered looks like this:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    [ [ B^7 E7 ] [ G^7 C7 ] D#^7 [ Am7 E7 ] [ G^7 C7 ] [ D#^7 G#7 ] B^7 [ Fm7 C7 ] D#^7 [ Am7 E7 ] G^7 [ C#m7 G#7 ] B^7 [ Fm7 C7 ] D#7 [ C#m7 G#7 ] ]
</code></pre></div></div>

<p>I should really get this working with flats… fixed that and regenerated the chords:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    [ [ B^7 E7 ] [ G^7 C7 ] Eb^7 [ Am7 E7 ] [ G^7 C7 ] [ Eb^7 undefined7 ] B^7 [ Fm7 C7 ] Eb^7 [ Am7 E7 ] G^7 [ Dbm7 undefined7 ] B^7 [ Fm7 C7 ] Eb7 [ Dbm7 undefined7 ] ]
</code></pre></div></div>

<p>Oops… good luck with undefined7. Fixed it again, and now we have the correctly augmented 5th scale degrees rendered back into the original chord progression. Cool.</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    [ [ B^7 E7 ] [ G^7 C7 ] Eb^7 [ Am7 E7 ] [ G^7 C7 ] [ Eb^7 Ab7 ] B^7 [ Fm7 C7 ] Eb^7 [ Am7 E7 ] G^7 [ Dbm7 Ab7 ] B^7 [ Fm7 C7 ] Eb7 [ Dbm7 Ab7 ] ]
</code></pre></div></div>

<p>Ok, so now it’s time to plug some of this into Strudel and see what it sounds like. This time let’s try lowering all the 5th degree chords by three positions! (completely random choice)</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    <span class="kd">const</span> <span class="nx">romanNumeralMap</span> <span class="o">=</span> <span class="p">{</span>
        <span class="mi">1</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
        <span class="mi">2</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span>
        <span class="mi">3</span><span class="p">:</span> <span class="mi">3</span><span class="p">,</span>
        <span class="mi">4</span><span class="p">:</span> <span class="mi">4</span><span class="p">,</span>
        <span class="mi">5</span><span class="p">:</span> <span class="mi">5</span> <span class="o">-</span> <span class="mi">3</span><span class="p">,</span>
        <span class="mi">6</span><span class="p">:</span> <span class="mi">6</span><span class="p">,</span>
        <span class="mi">7</span><span class="p">:</span> <span class="mi">7</span>
    <span class="p">}</span>
</code></pre></div></div>

<p>So, lowering the fifth degree of the scale everywhere it’s used sounds like this. And remember that’s the fifth based on the tonic center which is defined in our config object and constantly shifting throughout the song:</p>

<div>
    <iframe width="100%" height="400px" src="https://strudel.tidalcycles.org/#Ly8gSm9obiBDb2x0cmFuZSAtIEJyaWFuIEZvZ2cgLSBWYXJpYXRlZCBTdGVwcwpzZXRWb2ljaW5nUmFuZ2UoJ2xlZnRoYW5kJywgWydFMycsICdHNCddKTsKCnN0YWNrKAogICAgLy8gbWVsb2R5CiAgICBzZXEoCiAgICAiW0YjNSBENV0gW0I0IEc0XSBCYjQgW0I0IEE0XSIsCiAgICAiW0Q1IEJiNF0gW0c0IEViNF0gRiM0IFtHNCBGNF0iLAogICAgIkJiNCBbQjQgQTRdIEQ1IFtEIzUgQyM1XSIsCiAgICAiRiM1IFtHNSBGNV0gQmI1IFtGIzUgRiM1XSIsCiAgICApLmNvbG9yKCcjRjhFNzFDJyksCiAgICAvLyBjaG9yZHMKICAgIHNlcSgiWyBbIEJeNyBBNyBdIFsgR143IEY3IF0gRWJeNyBbIEFtNyBBNyBdIFsgR143IEY3IF0gWyBFYl43IERiNyBdIEJeNyBbIEZtNyBGNyBdIEViXjcgWyBBbTcgQTcgXSBHXjcgWyBEYm03IERiNyBdIEJeNyBbIEZtNyBGNyBdIEViNyBbIERibTcgRGI3IF0gXSIpCiAgICAudm9pY2luZ3MoJ2xlZnRoYW5kJykKICAgIC5jb2xvcignIzdFRDMyMScpLAogICAgLy8gYmFzcwogICAgc2VxKAogICAgIltCMiBEMl0gW0cyIEJiMl0gW0ViMiBCYjNdIFtBMiBEMl0iLAogICAgIltHMiBCYjJdIFtFYjIgRiMyXSBbQjIgRiMyXSBbRjIgQmIyXSIsCiAgICAiW0ViMiBCYjJdIFtBMiBEMl0gW0cyIEQyXSBbQyMyIEYjMl0iLAogICAgIltCMiBGIzJdIFtGMiBCYjJdIFtFYjIgQmIzXSBbQyMyIEYjMl0iCiAgICApLmNvbG9yKCcjMDBCOEQ0JykKKS5zbG93KDIwKS5ub3RlKCkKLy8gLnBpYW5vcm9sbCh7Zm9sZDoxfSk%3D"></iframe>
</div>
<p>Pretty weird</p>

<p>the original again for reference:</p>

<div>
    <iframe width="100%" height="400px" src="https://strudel.tidalcycles.org/#Ly8gSm9obiBDb2x0cmFuZSAtIEJyaWFuIEZvZ2cgLSBWYXJpYXRlZCBTdGVwcwpzZXRWb2ljaW5nUmFuZ2UoJ2xlZnRoYW5kJywgWydFMycsICdHNCddKTsKCnN0YWNrKAogICAgLy8gbWVsb2R5CiAgICBzZXEoCiAgICAiW0YjNSBENV0gW0I0IEc0XSBCYjQgW0I0IEE0XSIsCiAgICAiW0Q1IEJiNF0gW0c0IEViNF0gRiM0IFtHNCBGNF0iLAogICAgIkJiNCBbQjQgQTRdIEQ1IFtEIzUgQyM1XSIsCiAgICAiRiM1IFtHNSBGNV0gQmI1IFtGIzUgRiM1XSIsCiAgICApLmNvbG9yKCcjRjhFNzFDJyksCiAgICAvLyBjaG9yZHMKICAgIHNlcSgiWyBbIEJeNyBENyBdIFsgR143IEJiNyBdIEViXjcgWyBBbTcgRDcgXSBbIEdeNyBCYjcgXSBbIEViXjcgR2I3IF0gQl43IFsgRm03IEJiNyBdIEViXjcgWyBBbTcgRDcgXSBHXjcgWyBEYm03IEdiNyBdIEJeNyBbIEZtNyBCYjcgXSBFYjcgWyBEYm03IEdiNyBdIF0iKQogICAgLnZvaWNpbmdzKCdsZWZ0aGFuZCcpCiAgICAuY29sb3IoJyM3RUQzMjEnKSwKICAgIC8vIGJhc3MKICAgIHNlcSgKICAgICJbQjIgRDJdIFtHMiBCYjJdIFtFYjIgQmIzXSBbQTIgRDJdIiwKICAgICJbRzIgQmIyXSBbRWIyIEYjMl0gW0IyIEYjMl0gW0YyIEJiMl0iLAogICAgIltFYjIgQmIyXSBbQTIgRDJdIFtHMiBEMl0gW0MjMiBGIzJdIiwKICAgICJbQjIgRiMyXSBbRjIgQmIyXSBbRWIyIEJiM10gW0MjMiBGIzJdIgogICAgKS5jb2xvcignIzAwQjhENCcpCikuc2xvdygyMCkubm90ZSgpCi8vIC5waWFub3JvbGwoe2ZvbGQ6MX0p"></iframe>
</div>

<p>Well, this is fun, but the changes are not so obvious here.. I should probably start generating the bass line and the melody in a similar way. Back to the drawing board…</p>

<p>This is the melody in strudel format:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    "[F#5 D5] [B4 G4] Bb4 [B4 A4]",
    "[D5 Bb4] [G4 Eb4] F#4 [G4 F4]",
    "Bb4 [B4 A4] D5 [D#5 C#5]",
    "F#5 [G5 F5] Bb5 [F#5 F#5]",
</code></pre></div></div>

<p>I’ll re-factor my code to handle this. Will need to define the tonal center for each note in a similar way it was done with the chords. In fact, I need to copy this tonal center and re-use it everywhere. The tonal center should not change for melody and bass. This is a little annoying to write in my code notation because the amount of notes per measure varies in the bassline. I’m doing a lot of manual transposition to set all this up.</p>

<p>Ok, a few minutes later and we’ve completed the process of manually transposing the original notes into tonal-center-aware javascript config format:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    <span class="kd">const</span> <span class="nx">bassConfig</span> <span class="o">=</span> <span class="p">[</span>
    <span class="c1">// B2 D2</span>
    <span class="p">[</span>
        <span class="p">{</span>
            <span class="na">tonalCenter</span><span class="p">:</span> <span class="nx">note</span><span class="p">.</span><span class="nx">B</span><span class="p">,</span>
            <span class="na">scaleDegree</span><span class="p">:</span> <span class="nx">bassScaleDegreeMap</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span>
            <span class="na">octave</span><span class="p">:</span> <span class="mi">2</span>
        <span class="p">},</span>
        <span class="p">{</span>
            <span class="na">tonalCenter</span><span class="p">:</span> <span class="nx">note</span><span class="p">.</span><span class="nx">G</span><span class="p">,</span>
            <span class="na">scaleDegree</span><span class="p">:</span> <span class="nx">bassScaleDegreeMap</span><span class="p">[</span><span class="mi">5</span><span class="p">],</span>
            <span class="na">octave</span><span class="p">:</span> <span class="mi">2</span>
        <span class="p">}</span>
    <span class="p">],</span>
    <span class="nx">etc</span><span class="p">...</span>

    <span class="kd">const</span> <span class="nx">melodyConfig</span> <span class="o">=</span> <span class="p">[</span>
    <span class="c1">// [F#5 D5],</span>
    <span class="p">[{</span>
        <span class="na">tonalCenter</span><span class="p">:</span> <span class="nx">note</span><span class="p">.</span><span class="nx">B</span><span class="p">,</span>
        <span class="na">scaleDegree</span><span class="p">:</span> <span class="nx">melodyScaleDegreeMap</span><span class="p">[</span><span class="mi">5</span><span class="p">],</span>
        <span class="na">octave</span><span class="p">:</span> <span class="mi">5</span>
    <span class="p">},</span> <span class="p">{</span>
        <span class="na">tonalCenter</span><span class="p">:</span> <span class="nx">note</span><span class="p">.</span><span class="nx">G</span><span class="p">,</span>
        <span class="na">scaleDegree</span><span class="p">:</span> <span class="nx">melodyScaleDegreeMap</span><span class="p">[</span><span class="mi">5</span><span class="p">],</span>
        <span class="na">octave</span><span class="p">:</span> <span class="mi">5</span>
    <span class="p">}],</span>
    <span class="nx">etc</span><span class="p">...</span>

    <span class="kd">const</span> <span class="nx">melodyScaleDegreeMap</span> <span class="o">=</span> <span class="p">{</span>
        <span class="mi">1</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
        <span class="mi">2</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span>
        <span class="mi">3</span><span class="p">:</span> <span class="mi">3</span><span class="p">,</span>
        <span class="mi">4</span><span class="p">:</span> <span class="mi">4</span><span class="p">,</span>
        <span class="mi">5</span><span class="p">:</span> <span class="mi">5</span><span class="p">,</span>
        <span class="mi">6</span><span class="p">:</span> <span class="mi">6</span><span class="p">,</span>
        <span class="mi">7</span><span class="p">:</span> <span class="mi">7</span>
    <span class="p">}</span>

    <span class="kd">const</span> <span class="nx">bassScaleDegreeMap</span> <span class="o">=</span> <span class="p">{</span>
        <span class="mi">1</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
        <span class="mi">2</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span>
        <span class="mi">3</span><span class="p">:</span> <span class="mi">3</span><span class="p">,</span>
        <span class="mi">4</span><span class="p">:</span> <span class="mi">4</span><span class="p">,</span>
        <span class="mi">5</span><span class="p">:</span> <span class="mi">5</span><span class="p">,</span>
        <span class="mi">6</span><span class="p">:</span> <span class="mi">6</span><span class="p">,</span>
        <span class="mi">7</span><span class="p">:</span> <span class="mi">7</span>
    <span class="p">}</span>
</code></pre></div></div>

<p>I’ve added separate scale config objects for each section of the song so we can modulate melody without effecting bass, etc.</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    // John Coltrane - Brian Fogg - Variated Steps
    setVoicingRange('lefthand', ['E3', 'G4']);

    stack(
        // melody
        seq("[ [ E6 C6 ] [ A4 E4 ] Ab4 [ Bb4 A4 ] [ C6 Ab4 ] [ Gb4 C5 ] E5 [ Gb4 F4 ] Ab4 [ Bb4 A4 ] C6 [ D6 Db6 ] E6 [ Gb5 F5 ] Ab5 [ E6 E6 ] ]")
        // chords
        seq("[ [ B1^7 D27 ] [ G1^7 Bb17 ] Eb1^7 [ A1m7 D27 ] [ G1^7 Bb17 ] [ Eb1^7 Gb27 ] B1^7 [ F1m7 Bb17 ] Eb1^7 [ A1m7 D27 ] G1^7 [ Db2m7 Gb27 ] B1^7 [ F1m7 Bb17 ] Eb17 [ Db2m7 Gb27 ] ]")
        .voicings('lefthand')
        // bass
        seq("[ [ C3 C3 ] [ Ab2 Ab2 ] [ E2 Ab3 ] [ A2 C3 ] [ Ab2 Ab2 ] [ E2 Eb3 ] [ C3 Eb3 ] [ F2 Ab2 ] [ E2 ] [ A2 C3 ] [ Ab2 C3 ] [ Db3 E3 ] [ C3 E3 ] [ F2 Ab2 ] [ E2 Ab3 ] [ Db3 E3 ] ]")
    )
    .slow(20)
    .note()
</code></pre></div></div>

<p>I’m certain I’ve introduced errors during this transposition process. I’ll need to manually compare the rendered outputs to the original source. Maybe the sharp eared among you will simply hear the errors.</p>

<p>TODO: add the above code to Strudel interactive player</p>

<p>Ok, now it’s time to start modulating things… Let’s try something very easy, a move of a perfect fifth in the melody without touching anything else. That should be easy to hear and ideally not too musically obtuse.</p>

<p>We’ll take the second degree of the melody scale range and boost it by a perfect fifth. This means that any note which should be the 2nd degree of a scale will now be played as a sixth. It’s a musically reasonable move and not too “outside”. This one line change will effect several notes in the melody, and with the constantly shifting tonal centers, I don’t know how many notes will be modifie, so it’s very hard to predict exactly how this will sound.</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    <span class="kd">const</span> <span class="nx">melodyScaleDegreeMap</span> <span class="o">=</span> <span class="p">{</span>
        <span class="mi">1</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
        <span class="mi">2</span><span class="p">:</span> <span class="mi">2</span> <span class="o">+</span> <span class="mi">5</span><span class="p">,</span>
        <span class="mi">3</span><span class="p">:</span> <span class="mi">3</span><span class="p">,</span>
        <span class="mi">4</span><span class="p">:</span> <span class="mi">4</span><span class="p">,</span>
        <span class="mi">5</span><span class="p">:</span> <span class="mi">5</span><span class="p">,</span>
        <span class="mi">6</span><span class="p">:</span> <span class="mi">6</span><span class="p">,</span>
        <span class="mi">7</span><span class="p">:</span> <span class="mi">7</span>
    <span class="p">}</span>
</code></pre></div></div>

<p>That’s the change!</p>

<p>TODO: generate output</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    // John Coltrane - Brian Fogg - Variated Steps
    setVoicingRange('lefthand', ['E3', 'G4']);

    stack(
        // melody
        seq("[ [ E6 C6 ] [ A4 E4 ] Ab4 [ Bb4 A4 ] [ C6 Ab4 ] [ Gb4 C5 ] E5 [ Gb4 F4 ] Ab4 [ Bb4 A4 ] C6 [ D6 Db6 ] E6 [ Gb5 F5 ] Ab5 [ E6 E6 ] ]")
        // chords
        seq("[ [ B1^7 D27 ] [ G1^7 Bb17 ] Eb1^7 [ A1m7 D27 ] [ G1^7 Bb17 ] [ Eb1^7 Gb27 ] B1^7 [ F1m7 Bb17 ] Eb1^7 [ A1m7 D27 ] G1^7 [ Db2m7 Gb27 ] B1^7 [ F1m7 Bb17 ] Eb17 [ Db2m7 Gb27 ] ]")
        .voicings('lefthand')
        // bass
        seq("[ [ C3 C3 ] [ Ab2 Ab2 ] [ E2 Ab3 ] [ A2 C3 ] [ Ab2 Ab2 ] [ E2 Eb3 ] [ C3 Eb3 ] [ F2 Ab2 ] [ E2 ] [ A2 C3 ] [ Ab2 C3 ] [ Db3 E3 ] [ C3 E3 ] [ F2 Ab2 ] [ E2 Ab3 ] [ Db3 E3 ] ]")
    )
    .slow(20)
    .note()
</code></pre></div></div>

<p>Ok, I realize this is not very impressive yet, but this is as far as I’ve gotten as of last night. I’ll update later…</p>

<p>-Brian</p>]]></content><author><name></name></author><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">Sun Dome / The Long Rain</title><link href="https://www.brianfogg.com/blog/bradbury-sun-dome-long-rain-art-installation/" rel="alternate" type="text/html" title="Sun Dome / The Long Rain" /><published>2023-03-21T12:44:30+00:00</published><updated>2023-03-21T12:44:30+00:00</updated><id>https://www.brianfogg.com/blog/ray-bradbury-sun-dome</id><content type="html" xml:base="https://www.brianfogg.com/blog/bradbury-sun-dome-long-rain-art-installation/"><![CDATA[<div>
    <img style="border-radius: .2rem;" src="/assets/images/blog/bradbury/sun_dome.jpg" alt="Sun Dome art installation rendering" />
    <p style="text-align: center; color: darkgrey; margin-top: 0;"></p>
</div>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>The rain continued. It was a hard rain, a perpetual rain, a sweating and steaming rain; it was a mizzle, a downpour, a fountain, a whipping at the eyes, an undertow at the ankles; it was a rain to drown all rains and the memory of rains. It came by the pound and the ton, it hacked at the jungle and cut the trees like scissors and shaved the grass and tunneled the soil and molted the bushes. It shrank men’s hands into the hands of wrinkled apes; it rained a solid glassy rain, and it never stopped.

“How much farther, Lieutenant?”

“I don’t know. A mile, ten miles, a thousand.”

“Aren’t you sure?”

“How can I be sure?”

“I don’t like this rain. If we only knew how far it is to the Sun Dome, I’d feel better.”

-- excerpt from: The Long Rain by Ray Bradbury
</code></pre></div></div>

<p>Several years ago I enjoyed reading <a href="https://en.wikipedia.org/wiki/Ray_Bradbury">Ray Bradbury’s</a> short story <a href="https://en.wikipedia.org/wiki/The_Long_Rain">The Long Rain</a>. (<a href="http://mrdamodeo.weebly.com/uploads/3/9/1/9/39191519/the-long-rain.pdf">find it here</a>)</p>

<p>It’s a story of a small expedition crew lost on a rainy planet in search of the Sun Dome, an outpost of warmth and comfort.</p>

<p>Around the same time I was experimenting with <a href="https://www.blender.org/">Blender</a> 3D rendering software and attending music and art festivals regularly.</p>

<p>The above image is a piece of concept art I created depicting Ray Bradbury’s Sun Dome as I imagined it for an art festival installation.</p>

<p>The sun hanging from the center of the dome would be built to emit enough radiant heat via internal heating to keep the dome at a comfortable temperature during cold nights.</p>

<p>Around the perimeter of the dome, amber spotlights would be installed pointing towards the sun, similar to the arrangement of a disco ball installation. The sun’s surface would be need to be coated with heat resistant white paint to reflect light and withstand powerful radiant heat.</p>

<p>The structure would be based on a standard geodesic steel frame, and if cost were no object, it would be fitted with triangular glass panels.</p>

<p>Not pictured in this rendering is a collection of furniture and period decor matching the vintage space age theme that recurs throughout Bradbury’s literary universe. Perhaps a coffee/hot chocolate station (as described in the story) and small library stocked with science fiction literature, featuring the works of Mr Bradbury.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[]]></summary></entry></feed>