# Catsharp Sonification

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

- Skill: `plurigrid/catsharp-sonification` (Agent Skill, multi-file: 9 files)
- Install (CLI): `npx skillmds@latest add plurigrid/catsharp-sonification`
- Raw SKILL.md: https://api.skillmd.com/api/skills/plurigrid/catsharp-sonification/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: plurigrid (https://skillmd.com/u/plurigrid)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/plurigrid/catsharp-sonification

---


# 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 Range | Trit | Role | Temperature |
|-----------|------|------|-------------|
| 0-60°, 300-360° | +1 | PLUS | warm |
| 60-180° | 0 | ERGODIC | neutral |
| 180-300° | -1 | MINUS | cold |

### Trit → Waveform

| Trit | Waveform | Character |
|------|----------|-----------|
| +1 | sine | smooth, harmonic |
| 0 | triangle | balanced, neutral |
| -1 | square | harsh, 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 Classes | Trit | Structure |
|---------------|------|-----------|
| {0, 4, 8} (C, E, G#) | +1 | Augmented triad |
| {3, 6, 9} (Eb, F#, A) | 0 | Diminished subset |
| Circle of fifths | -1 | Fifths stack |

## Usage

### Python (sox required)

```python
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

```clojure
(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)

```julia
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

