Skip to content
f1nel-egyPublic

About

Use Math to create music

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

10 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Math2Wav

Create music with math. Math2Wav renders a mathematical formula into an audio waveform and writes it to a WAV file. Formulas are written in SSF (Sound Source File), a tiny interpreted math language that supports constants, user-defined functions, imports, and a full set of audio-oriented builtins (oscillators, envelopes, filters, FX).

Both a command-line renderer (math2wav) and an interactive GUI (math2wav-gui) are provided. The GUI is a live-coding environment: edit the formula and the sound updates in real time.

Features

  • Formula to WAV: evaluate f(x) for every sample and write 8/16/32/64-bit PCM (or 32/64-bit IEEE-754 float) WAV files.
  • SSF language: const variables, fn functions, multi-file import, comments, and a library of builtins.
  • Band-unlimited oscillators: saw, tri, sqr, deterministic noise, plus standard math functions.
  • Live GUI: Nuklear-based editor with real-time audio via miniaudio, hot-reload on every edit, syntax diagnostics with squiggly-line support, play/pause, gain, and one-click WAV export.
  • Structured diagnostics: parse/compile errors are reported with line/column info, usable both on the CLI and in the editor.
  • Extensible audio backend: a generator-based audio API (formats/audio.h) currently ships a WAV backend and is designed for more formats.

Requirements

  • CMake >= 3.16
  • A C23 compiler (GCC 13+, Clang 16+, or similar)
  • SDL2 (fetched as a Git submodule)
  • The SDL2, GLAD, tinyexpr, Nuklear, and miniaudio sources are vendored under src/thirdparty.

Building

# 1. clone with submodules (or run these after cloning)
git clone --recurse-submodules https://github.com/f1nel-egy/Math2Wav.git
cd Math2Wav
git submodule update --init --recursive

# 2. configure and build
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j

This produces two executables in build/:

Executable Purpose
math2wav Command-line renderer: .ssf file to .wav
math2wav-gui Interactive live-coding editor (SDL2/OpenGL)

Command-Line Usage

Usage: math2wav [OPTION]... [FILE.ssf]

Render a sound from a formula and write it to a WAV file. The formula can come from a Sound Source File (.ssf), the -m option, or, if neither is given, a built-in default tone.

Option Description
-h, --help Show help
-v, --version Show version
-o, --output FILE Output WAV file (default output.wav)
-i, --input FILE Read settings and formula from an .ssf file
-m, --math FORMULA Use FORMULA directly (overrides the .ssf formula)
-f, --frequency FREQ Sample rate in Hz
-d, --duration DURATION Duration in ms
-w, --width WIDTH PCM bit width in bits (8, 16, 32 or 64)

Examples:

math2wav examples/sine.ssf -o sine.wav
math2wav examples/testsong.ssf -o testsong.wav
math2wav -m "0.25 * sin(2 * pi() * 440 * x)" -d 2000 -o beep.wav

GUI

Run math2wav-gui to open the live-coding editor:

  • Edit SSF source in the editor pane; the sound recompiles and updates while you type (250 ms debounce).
  • Play/Pause toggles real-time playback, Gain controls output level.
  • File field + Load opens an .ssf file (imports resolve relative to it).
  • Export .wav renders the current source to a WAV file.
  • The diagnostics pane lists errors/warnings with line numbers; clicking one jumps to the line.
  • When compilation fails, the audio engine keeps playing the last good version.

The SSF Language

SSF (Sound Source File) is a tiny math language interpreted at runtime. It is built on tinyexpr and adds user-defined symbols, imports, and audio helpers. The variable x is always time in seconds; the result should stay in [-1, 1] (anything outside is clamped).

Settings

Top-level key = value lines configure the render:

samplerate = 48000
duration   = 2000
width      = 32
format     = wav

Accepted aliases: samplerate/sample_rate/rate/hz, duration/ms, width/bits/bit_width, format/container. width supports 8, 16, 32 or 64 bits.

Constants and functions

const TAU = 2 * pi()
const BPM = 128

fn eq(a, b) = 1 - sign(abs(a - b))
fn kick(t)  = sin(TAU * 50 * t) * exp(-t * 8)

Imports

import "lib/notes.ssf"
import "lib/env.ssf"

Imports are resolved relative to the importing file and are de-duplicated. A standard library lives in examples/lib:

File Contents
lib/notes.ssf Note frequency constants C0…B8, midi(), semis()
lib/time.ssf BPM / beat / bar / step / gate helpers
lib/env.ssf Envelopes (decay, ar/ad, adsr, lfo, …)
lib/fx.ssf Distortion, clipping, filtering, tilt, mixing helpers

Builtins

Arithmetic: + - * / ^ % (% is fmod, ^ is power)

Math: sin cos tan asin acos atan atan2 sinh cosh tanh exp ln log log10 pow sqrt abs floor ceil fac

Audio:

Function Description
fmod(a, b) Floating-point modulo
min(a, b) Minimum
max(a, b) Maximum
clamp(v, lo, hi) Clamp between lo and hi
sign(a) Sign (-1/0/1)
saw(p) Band-unlimited sawtooth, one cycle per unit of phase
tri(p) Band-unlimited triangle, one cycle per unit of phase
sqr(p) Band-unlimited square, one cycle per unit of phase
noise(seed) Deterministic white noise in [-1, 1]
pi(), e() Constants

Comments

# this is a comment
// so is this

Examples

Every example is a complete .ssf file in examples/:

File What it demonstrates
sine.ssf A simple 440 Hz sine tone
beat.ssf A kick-drum-style beat in a one-line formula
gabber.ssf 200 BPM gabber kick + hoover bass
house_drums.ssf Full house drum machine (kick, clap, snare, hats, rim)
testsong.ssf A complete 136-second track with arrangement + sidechain
rcs_helmet_vibration.ssf RCS thruster / helmet vibration sound design

Render one with:

math2wav examples/testsong.ssf -o testsong.wav

Project Structure

Math2Wav
├── CMakeLists.txt            # CMake build (C23)
├── examples/                 # .ssf files + lib/ standard library
└── src/
    ├── main.c                # CLI renderer
    ├── maingui.c             # GUI entry point (SDL2 + OpenGL + Nuklear)
    ├── libs/
    │   ├── math2wav.*        # shared math/audio helpers
    │   ├── ssf.*             # SSF language: parser, compiler, evaluator
    │   ├── m2waudio.*        # real-time playback via miniaudio
    │   └── m2wui.*           # Nuklear-based editor UI state + drawing
    ├── formats/
    │   ├── audio.*           # pluggable audio file generator API
    │   └── wav/*             # WAV backend implementation
    └── thirdparty/           # SDL2 (submodule), glad, tinyexpr,
                              # nuklear, miniaudio

Third-Party Libraries

  • SDL2 (submodule, branch = SDL2) - windowing/input
  • glad - OpenGL loader
  • tinyexpr - expression parsing/evaluation
  • Nuklear - immediate-mode GUI
  • miniaudio - audio playback

License

This project is licensed under the GPL 3.0 - see LICENSE.

This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law.

About

Use Math to create music

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages