audio
Audio processing and synthesis - sample generation, effects (reverb, echo, filter), oscillator-based synthesis, spectrum analysis, and streaming.
Load with: use audio
What this module does
audio works with audio data as plain ilusm lists of floating-point samples.
You create a sample object describing the format (sample rate, bit depth, channels),
generate or load audio data into it, apply effects, feed it through a synthesiser,
analyse its frequency content, and read/write it via a stream.
All processing is pure ilusm using mth for trigonometry - there are no native
bindings for audio I/O. The module handles the maths; you connect the output to your
platform's audio pipeline.
Quick example
use audio
# Generate a 440 Hz sine wave, 1 second, full amplitude
sample = adsne(440.0, 1.0, 1.0, 44100)
# Apply reverb
sample = adffc(sample, 0.3, 0.5)
# Check the peak amplitude
prn(adnpk(sample))
# Build a two-oscillator synth
synth = adsba()
synth = adsfa(synth, "osc1", "sine", 440.0, 0.7)
synth = adsfa(synth, "osc2", "square", 880.0, 0.3)
out = adsyn(synth, 2.0, 44100)
Functions
Sample creation
adsqa()
Creates a default empty sample: 44100 Hz, 16-bit, stereo, no data, duration 0.0.
adsma(sample_rate, bit_depth, channels) / adsna(sample_rate, bit_depth, channels)
Creates a sample with explicit format settings. Any nil argument falls back to the default (44100 / 16 / 2). Returns an empty sample object ready to receive data.
adsmp(sample, frequency, duration, amplitude)
Fills a sample's data with a pure sine wave at frequency Hz, lasting duration seconds, scaled by amplitude (0.0–1.0). Uses mth.sin. Returns the updated sample.
adsne(frequency, duration, amplitude, sample_rate)
Convenience shorthand: creates a new sample and fills it with a sine wave in one call.
adska(sample1, sample2, weight)
Mixes two samples together. Both must have the same data length. Each output sample is sample1[i] * weight + sample2[i] * (1 - weight). Returns a new sample with the mixed data.
Effects
adfxr(sample, room_size, damping) / adffc(sample, room_size, damping)
Simple reverb. Adds a delayed copy of each sample (delayed by room_size * sample_rate samples) scaled by damping to the original. Returns a new sample.
adfxc(sample, delay_time, decay) / adffa(sample, delay_time, decay)
Echo effect. Adds a delayed copy (delayed by delay_time * sample_rate samples) scaled by decay. Returns a new sample.
adfxf(sample, filter_type, cutoff) / adfha(sample, filter_type, cutoff)
First-order IIR filter. filter_type is "lowpass" or "highpass".
cutoff is the cutoff frequency in Hz.
Alpha is computed as 2π × cutoff / sample_rate.
For any other filter type, returns the original data unchanged.
Returns a new sample.
adfga(type, parameters) / audfx(type, parameters)
Creates a generic effect descriptor object with type and parameters. The effect is not applied - this is a data object for passing effect configs around.
Synthesis
adsla() / adsba()
Creates a new synthesiser with empty oscillator, envelope, and filter maps.
adsja(synth, id, waveform, frequency, amplitude) / adsfa(synth, id, waveform, frequency, amplitude)
Adds an oscillator to the synth. waveform can be "sine", "square", "sawtooth", or "triangle".
Returns the updated synth.
adsia(synth, duration, sample_rate) / adsyn(synth, duration, sample_rate)
Renders audio from all oscillators in the synth by summing their outputs sample-by-sample. Returns a mono sample object (channels: 1) with the mixed result.
adsga(oscillator, duration, sample_rate)
Internal: generates the raw sample list for a single oscillator over duration seconds.
Waveform generation per sample:
"sine"-mth.sin(phase)"square"- 1.0 if sine ≥ 0, else −1.0"sawtooth"-2 × (phase/2π − floor(phase/2π + 0.5))"triangle"- absolute value of sawtooth, scaled to −1/+1- Unknown waveform - 0.0
Analysis
adncr(fft_size, window_function) / adnlz(fft_size, window_function)
Creates an analyser with a given FFT size (default 1024) and window function (default "hanning").
adnaa(analyzer, sample) / adnfr(sample, fft_size)
Simplified frequency spectrum. Takes the first fft_size samples and computes a magnitude for each frequency bin up to Nyquist. Note: this is a simplified magnitude readout (abs of sample value), not a proper FFT. Returns {frequencies, magnitudes}.
adnrm(analyzer, sample) / adnrm(sample)
RMS (Root Mean Square) amplitude of the sample - square root of the mean of squared sample values. Returns 0.0 for empty data.
adnpk(analyzer, sample) / adnpk(sample)
Peak amplitude - the maximum absolute sample value. Returns 0.0 for empty data.
Format descriptors
adfca()
Returns a WAV format descriptor: {name: "WAV", extensions: [".wav"]}.
adfaa()
Returns an MP3 format descriptor: {name: "MP3", extensions: [".mp3"]}.
adfrm()
Returns a FLAC format descriptor: {name: "FLAC", extensions: [".flac"]}.
adfba()
Returns an OGG format descriptor: {name: "OGG", extensions: [".ogg"]}.
Streaming
adsha(buffer_size, sample_rate) / adsoa(buffer_size, sample_rate)
Creates a stream with a given buffer size (default 1024) and sample rate (default 44100). The stream starts paused (playing: fls).
adsaa(stream, data)
Appends sample data to the stream's buffer.
adsda(stream, num_samples)
Reads up to num_samples from the stream, advancing the read position. Returns however many are available up to the request.
adsca(stream)
Sets the stream to playing (playing: tru).
adstr(stream)
Sets the stream to stopped (playing: fls).
adsea(stream, position)
Seeks the stream's read position to the given sample index.
Notes
- All audio data is stored as lists of floats. There is no native I/O - connect the output to your platform's audio API yourself.
adnaa/adnfris a simplified approximation, not a real FFT. Magnitudes are absolute sample values for the firstfft_size/2samples.adska(mix) requires both samples to have the same data length - it errors otherwise.- Some function names are overloaded (
adnrm,adnpk,adsoa) and have convenience single-argument shorthands that create a default analyser internally. - Requires
mth,trl,txt,jsn,cry, andtim.