Asi catsharp-sonification

Sonify GF(3) color streams via CatSharp scale. Maps Gay.jl colors to pitch classes and plays through sox. No voice synthesis.

install
source · Clone the upstream repo
git clone https://github.com/plurigrid/asi
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/plurigrid/asi "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/catsharp-sonification" ~/.claude/skills/plurigrid-asi-catsharp-sonification-af8e0d && rm -rf "$T"
manifest: skills/catsharp-sonification/SKILL.md
source content

CatSharp Sonification

Sonify deterministic color streams using the CatSharp scale (Mazzola's Topos of Music).

Galois Chain

seed ⊣ γ ⊣ color ⊣ hue ⊣ pitch ⊣ freq ⊣ tone

Mappings

Hue → Trit (Gay.jl spec)

Hue RangeTritRoleTemperature
0-60°, 300-360°+1PLUSwarm
60-180°0ERGODICneutral
180-300°-1MINUScold

Trit → Waveform

TritWaveformCharacter
+1sinesmooth, harmonic
0trianglebalanced, neutral
-1squareharsh, digital

Hue → Pitch Class

pitch_class = floor(hue / 30) mod 12

30° per semitone maps the color wheel to the chromatic scale.

CatSharp Pitch → Trit

Pitch ClassesTritStructure
{0, 4, 8} (C, E, G#)+1Augmented triad
{3, 6, 9} (Eb, F#, A)0Diminished subset
Circle of fifths-1Fifths stack

Usage

Python (sox required)

import subprocess

def play_color(r, g, b, duration=0.15):
    hue = rgb_to_hue(r, g, b)
    trit = hue_to_trit(hue)
    pc = int(hue / 30) % 12
    freq = 261.63 * (2 ** (pc / 12))  # C4 base
    wave = {1: "sine", 0: "triangle", -1: "square"}[trit]
    subprocess.run(["play", "-q", "-n", "synth", str(duration), 
                    wave, str(freq), "vol", "0.3"])

Babashka

(defn play-trit [trit freq]
  (let [wave (case trit 1 "sine" 0 "triangle" -1 "square")]
    (shell "play" "-q" "-n" "synth" "0.15" wave (str freq) "vol" "0.3")))

Julia (Gay.jl)

using Gay

function sonify_stream(seed, n=12)
    Gay.gay_seed!(seed)
    for _ in 1:n
        c = Gay.next_color()
        hue = Gay.Colors.convert(Gay.HSL, c).h
        pc = mod(round(Int, hue / 30), 12)
        freq = 261.63 * 2^(pc / 12)
        trit = hue < 60 || hue >= 300 ? 1 : hue < 180 ? 0 : -1
        wave = Dict(1 => "sine", 0 => "triangle", -1 => "square")[trit]
        run(`play -q -n synth 0.15 $wave $freq vol 0.3`)
    end
end

GF(3) Conservation

Every tripartite emission sums to 0 mod 3:

MINUS(-1) + ERGODIC(0) + PLUS(+1) = 0

Modelica Formulation

See

catsharp.mo
for acausal equation-based model.

Dependencies

  • sox
    (via flox:
    flox install sox
    )
  • Python 3.x or Julia with Gay.jl
  • macOS
    afplay
    as fallback

Related Skills

  • gay-mcp
    : Deterministic color generation
  • rubato-composer
    : Mazzola's mathematical music theory
  • topos-of-music
    : Full categorical music implementation