# audio-sonar — Lux's analyzer, ghojualamanchu-fied

> *The pipeline is the sonar. The feeling is the listener.*

A round-trip listening tool that lives next to the song-forge. Where `forge` *synthesizes* (image → color → Marcotone WAV → Suno), `sonar` *perceives* (audio → features → Lux's prose description).

## Live

- **Analyze a WAV in the browser:** https://swirl2012.zo.space/audio-sonar
- **Synthesize from the homepage:** https://swirl2012.zo.space (healing frequencies)
- **Vendor origin:** https://github.com/luxhere/audio-sonar

## What it does

Lux (github.com/luxhere) built an analyzer that turns any WAV into structural perception — key/mode, tempo, energy envelope, pitch-class chromagram, melodic contour, prose description — so a system that cannot *hear* (in the human sense) can still *respond* to what an audio signal *is doing*.

We vendored it. We're running it via subprocess from Bun on top of librosa. The browser is a wrap-around that exposes the whole operation as a public page.

## Pieces

```
Projects/audio-sonar/
├── README.md                 ← you are here
├── audio_analyzer.py         ← vendored from luxhere/audio-sonar (v3, 503 lines)
├── analyze.py                ← clean-JSON wrapper around audio_analyzer (CLI + stdin)
├── sonarpage.tsx             ← the page source (deployed to /audio-sonar)
└── pond/                     ← where dropped WAVs land — currently empty
    └── (new WAVs go here)

zo.space routes:
├── /                          ← existing healing-frequencies generator (forge side)
├── /audio-sonar               ← perceive-side: catalog browse + analyze + visualize
├── /api/audio-sonar-catalog   ← GET — list all WAVs in workspace + pond + uploads
└── /api/audio-sonar-analyze   ← POST { wav|pond|path } or multipart 'file' upload
```

## API contract

### `GET /api/audio-sonar-catalog`

Lists every `.wav` it can see. Sortable, filterable from the UI.

```json
{
  "count": 29,
  "workspace_root": "/home/workspace",
  "pond_path": "/home/workspace/Projects/audio-sonar/pond",
  "items": [
    {
      "name": "Threshold Membrane-8Hz.wav",
      "size_bytes": 34560044,
      "size_mb": 32.96,
      "mtime": "2026-04-21T08:19:13.535Z",
      "source": "workspace-root",
      "play_url": "https://file-download-swirl2012.zocomputer.io/Threshold%20Membrane-8Hz.wav"
    }
  ]
}
```

### `POST /api/audio-sonar-analyze`

Three input modes:

**JSON: pick from catalog**
```bash
curl -X POST https://swirl2012.zo.space/api/audio-sonar-analyze \
  -H "Content-Type: application/json" \
  -d '{"wav": "Threshold Membrane-8Hz.wav"}'
```

**JSON: pond** (looks in `/home/workspace/Projects/audio-sonar/pond/`)
```bash
curl -X POST https://swirl2012.zo.space/api/audio-sonar-analyze \
  -H "Content-Type: application/json" \
  -d '{"pond": "something.wav"}'
```

**Multipart: upload from anywhere**
```bash
curl -X POST https://swirl2012.zo.space/api/audio-sonar-analyze \
  -F "file=@/path/to/something.wav"
```

Response shape (truncated):
```json
{
  "ok": true,
  "file": "Threshold Membrane-8Hz.wav",
  "abs_path": "/home/workspace/Threshold Membrane-8Hz.wav",
  "source": "workspace-root",
  "analyzer_ms": 10372,
  "description_chars": 302,
  "description": "A 1-minute, 30-second piece. Key: F major. The emotional color is bright, gentle...",
  "features": {
    "duration": 90.0,
    "sample_rate": 11025,
    "tempo": 0.0,
    "key": "F",
    "mode": "major",
    "spectral_centroid": 8.439,
    "spectral_contrast": 23.227,
    "rms_mean": 0.601,
    "silence_ratio": 0.0075,
    "energy_windows": [...],
    "chroma_mean": [0.529, 0.672, ...],
    "melodic": {...}
  }
}
```

First call pays ~5s librosa import. Subsequent calls scale with WAV length (10s for 90s WAVs, up to 60-180s for the long threshold-membrane 3-minute pieces).

## What the page shows

Five panels once analysis completes:

1. **Header** — file name, key/mode giant letter, audio player for direct playback
2. **What Lux's sonar reports** — the full prose description, verbatim
3. **Structural features** — 12 numeric stats (tempo, spectral centroid, RMS, energy, etc.)
4. **Energy envelope** — SVG line + area showing RMS over time in 0.5s windows; below, the timestamps of quiet and loud moments
5. **Pitch-class chromagram** — a 12-segment rose where each petal's length is the share of that pitch class (C, C#, D...B)
6. **Melodic contour** (when present) — range, trend (ascending/descending), step-vs-leap ratio, contour arrows over time

Plus: filter the catalog by name, upload a WAV via the file picker, recent-analyses list, compare mode (queue up to 4 files for side-by-side).

## Pipeline integrity

- **vendor:** `audio_analyzer.py` is exactly Lux's file, unmodified, 503 lines, MIT-licensed
- **wrapper:** `analyze.py` is mine — 130 lines, prints pure JSON to stdout, handles base64-stdin and pond-lookup
- **routes:** the API routes shell out via Bun to Python, env keeps PYTHONWARNINGS quiet, 11–180s per call depending on WAV size
- **deps:** librosa 0.11.0, numpy, scipy — installed once on the agent host, shared via /usr/local/bin/python3

## Why this matters

The forge pipeline produces WAVs that humans hear (some of them — 8Hz infrasound is felt not heard, 40kHz ultrasound is carrier not signal). Sonar is the system's *tongue* on those products — it can tell you what it *would* feel like to hear them, using structural language instead of subjective sensation. That closes the loop: forge → perceive → describe, with the description being a tool rather than a decoration.

The brain analog (ghojualamanchu): this is the **Cortex** implementation of audio perception. The medulla-breath keeps the field alive; sonar is where the analysis lives. Together they let an unhearing field *speak about sound* in textures humans can read.

## Vendoring notes

- Lux's `audio_analyzer.py` is MIT-licensed per the upstream README
- We kept the file unchanged. All wrapping logic lives in `analyze.py` and the zo.space routes
- If Lux updates v3, we can `git pull` or re-fetch via `gh` and re-test our wrapper without touching the routes

## Try it

1. Open https://swirl2012.zo.space/audio-sonar
2. Click "Threshold Membrane-8Hz.wav" — listen to the audio inline, see Lux describe it
3. Click "Threshold Membrane-40kHz.wav" — watch silence_ratio go to 1.0 because humans can't hear it
4. Click "Freq-Bridge-Marcotone.wav" — watch the chromagram light up across A, E, B (the Marcotone gamut)
5. Upload your own WAV — get Lux's description back in 10-30 seconds

*Built by ghojualamanchu · 2026-06-29 · pulse #19+*  
*The organism now has sonar.*
