Make audx marketable: zero-config synth kit, PortAudio-optional install, 4x tests, full docs - #4
Merged
Merged
Conversation
…l offline use - Add audx/synth.py: pure-numpy procedural drum/perc voices (kick, snare, hh, oh, clap, rim, tom, cowbell, perc, ride, crash, shaker, sub) with aliases, tuning, and deterministic rendering. No samples required. - Renderer falls back to the synth kit when a sample is not found, so 'audx render "kick 4/4"' makes sound with zero setup; --sample is optional. - New commands: 'audx demo' (renders a full multi-track beat) and 'audx synths' (lists built-in voices). - Engine: import sounddevice lazily so the CLI and all offline features work without the PortAudio system library; add SynthVoice + synth fallback to the live callback; tidy types. - Types: mypy now checks the whole package cleanly (was 4 files); fix real errors in midi/web/calibration/voice/groove; add types-requests.
- Add test_synth, test_render_synth, test_cli, test_more_coverage covering the synth kit, synth-fallback rendering, MIDI export, project round-trips, DSL operators, and the offline CLI surface. Coverage 27%→43%. - Fix 'audx mix set <ch> gain -3': allow dash-leading values (ignore_unknown_options) so documented negative-dB usage works. - Autouse fixtures reset the process-global pattern engine between CLI tests. - Raise CI coverage gate 25→40.
…page - Rewrite README around the 10-second zero-config demo and the built-in synth kit; add badges, DSL reference table, grouped command overview, honest 'what it isn't yet' section. - Add LICENSE (MIT), CHANGELOG.md (Keep a Changelog), CONTRIBUTING.md. - Add docs/getting-started.md, docs/synth-kit.md and a docs index. - Add site/ static landing page (dark terminal aesthetic, no build step).
CI was pip-installing an unpinned mypy (2.1.0) and using flake8, so it diverged from the project's locked tools and failed on stricter var-annotated/unused-ignore inference that 'uv run mypy' (1.20.2) doesn't report. Run ruff, mypy and pytest through uv with --all-extras so CI matches local exactly; drop flake8. fail-fast: false to see all matrix results.
…ideo + PyPI release Product (team): - synth: 6 melodic voices (bass, pluck, stab, keys/ep, saw, sine) — band-limited saws, pitched via tune; bass is now its own voice. Kit is 20 voices total. - arrangement: Song/Section model + render_song; new 'audx song render|info' build multi-section tracks (intro/verse/drop/outro) from a JSON spec. - ui: live finger-drum pads (w e r a s d f z x c u i o) trigger synth voices on dedicated channels while a project is open. Marketing: - Animated terminal demo GIF in README (scripts/make-demo-gif.py, Pillow-only). - Runnable Remotion promo project (marketing/remotion/) + rendered 1080p MP4 and poster (marketing/promo/). Packaging: - Automated PyPI release via trusted publishing on v* tags (.github/workflows/release.yml); PUBLISHING.md updated for the uv build flow. Tests 123→172, coverage 43%→46%; ruff + mypy clean across the package.
The old promo was static terminal text with hard cuts. Rebuilt it around what audx actually is — a live instrument: - build-beat.py renders a real audx beat (synth kit) and emits a frame-accurate data track (per-track 16-step grids + hit frames, master RMS envelope, waveform peaks) so the motion graphics are driven by the actual audio. - AudxPromo.tsx: a live step-sequencer grid that fires on the beat with a moving playhead, per-track VU meters, and a waveform scope that sweeps in time — with the rendered beat as the MP4 soundtrack. Smooth eased crossfades, no hard cuts. - Electric-neon palette on pure black (cyan/magenta/lime/amber/violet). - README hero is now the neon sequencer poster linking to the 20s promo. Rendered artifacts: marketing/promo/audx-promo.mp4 (1080p, with audio) + poster.
… + gradients Neon + gradients read as cheap/generic. Researched premium audio-brand and motion direction (Teenage Engineering's muted-palette + single-accent restraint; the 2025 monochrome counter-trend to gradients/glow) and rebuilt accordingly: - Near-monochrome: warm off-white on true black, a SINGLE amber accent used only for the play position. No gradients, no glows, flat fills. - Sequencer is now a Monome/TE-style monochrome LED matrix: hairline-outlined cells, off-white hits, amber only under the thin playhead rule. Flat waveform. - Swiss layout: passe-partout frame, lowercase monospace labels, generous space. - Calmer motion: one bezier easing, restrained fades, discrete caret blink. - Flat monochrome also compresses far better — MP4 2.7MB (was ~10MB). Refreshed marketing/promo/*.mp4 + poster and docs/assets/promo-poster.png.
- audx jam: real-time play from a MIDI controller or Push 2. Drums mode maps
GM notes to drum voices and never leaves a pad silent; --chromatic plays a
melodic voice across the keys. New audx/live.py (pure, tested mapping) wired to
engine.play_synth (now supports tune_semitones).
- docs/playing-live.md: kid-friendly controller/Push 2 walkthrough; linked from
README ('Play it live') and the docs index.
- Bump to 0.3.0 (pyproject, package.json, __init__, CHANGELOG cut).
- Push2Lights drives Push 2 pad LEDs over MIDI: SysEx colour-palette entries (8-bit RGB split to 7-bit LSB/MSB) + note-on (channel 0) lighting, per the official Push 2 MIDI spec. Byte-exact unit tests against the spec example. - push2_pad_layout: a 13-voice drum kit on the bottom two rows, one colour each. - audx jam auto-detects a Push 2, paints the kit and flashes each pad on hit (--no-lights to disable; lights are drums-mode only). New 'audx push2 lights' lights the kit on its own for a quick check. - Bundle python-rtmidi so mido has a backend — midi/jam/Push 2 work out of the box. - Port discovery degrades gracefully with no backend/device; guide + README + CHANGELOG updated.
chrisschouk
pushed a commit
that referenced
this pull request
Jun 21, 2026
main advanced via PR #4 ("Make audx marketable"), which added the same foundational files this branch already carries (synth.py, push2.py, arrangement.py, site/, …) in a parallel version — producing add/add conflicts. This branch is a strict superset of those files (it also rewrote the serve dashboard and added the whole web/ studio), so the 5 conflicts (README.md, docs/README.md, docs/playing-live.md, site/index.html, synth.py) were resolved to this branch's versions, which contain main's content plus the web additions (browser callout, open --serve, percussion alias, second-screen doc). Verified after merge: ruff + mypy clean, full Python suite green, 108 web tests pass, tsc clean.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
audx was a well-architected terminal DAW that couldn't make a sound out of the box (every render needed your own sample files) and hard-crashed on
importon any machine without the PortAudio C library — sopip install audx→ first run failed. This PR fixes both and rounds the project into a state you could put in front of people.The headline: it makes music in 10 seconds, zero config
pip install audx audx demo loop.wav # full multi-track beat, no samples, no audio device1. Built-in synth kit (
audx/synth.py)14 pure-numpy procedurally-synthesised drum/perc voices —
kick,sub/808,snare,clap,snap,hh,oh,rim,tom,cowbell,perc,ride,crash,shaker— with aliases, per-voicetune, velocity scaling and deterministic (seeded) output. The renderer falls back to the synth kit whenever a sample of that name isn't found, so:Your own audio always wins when present;
--sampleis now optional. Newaudx demoandaudx synthscommands.2. Install actually works on a clean machine
sounddeviceis now imported lazily, so the CLI and all offline features (render, export, demo, diff, project ops) need no system libraries. Only live real-time playback requires PortAudio, with a friendly install hint when missing. Verified: importing the whole CLI no longer loadssounddevice.3. Quality
pytest), coverage ~28% → ~43%; CI gate raised to 40%. synth.py at 96%.midi,web,calibration,voice,groove; addedtypes-requests.audx mix set <ch> gain -3(documented negative dB) was rejected as an unknown option.4. Marketable docs
Rewritten README (10-second demo hero, DSL table, grouped command overview, honest "what it isn't yet"),
LICENSE(MIT),CHANGELOG.md,CONTRIBUTING.md,docs/getting-started.md,docs/synth-kit.md, and a staticsite/landing page (dark terminal aesthetic, no build step).Verification
Notes
warn_return_anyis intentionally disabled in mypy config (numpy stubs returnAny); every other strict flag stays on. Rationale documented inline inpyproject.toml.🤖 Generated with Claude Code
Generated by Claude Code