moon_sfx

    Industrial-grade procedural audio synthesizer, 8-bit retro sound FX generator and RIFF WAV encoder in pure MoonBit.

    audio
    synthesizer
    sound-effects
    sfx
    sfxr
    chiptune
    wav
    dsp
    game-audio
    retro
    8-bit
    procedural-audio
    Download zip
    Author
    Version
    0.1.2
    License
    Apache-2.0
    Last updated
    19 hours ago
    Downloads
    12

    No dependencies

    #moon_sfx

    CI MoonBit License Tests Dependencies

    moon_sfx is an industrial-grade, zero-dependency procedural audio synthesizer, 8-bit retro game sound FX generator, and Microsoft RIFF WAVE binary encoder implemented in 100% pure MoonBit.

    Targeted at WebAssembly browser games, indie cross-platform engines, UI interaction audio, and asset-less game development, moon_sfx delivers a complete, modular audio generation pipeline from pure mathematical wave oscillation to standard binary .wav output and self-contained interactive HTML5 audio studios.


    #Architecture & Features

    #1. Mathematical Waveform Oscillators (oscillator.mbt)

    • Sine: Pure, clean fundamental frequency for whistles, UI chimes, and smooth tones.
    • Square (PWM): Classic 8-bit / NES sound chip timbre with configurable duty cycle (1% to 99%) and dynamic duty sweep.
    • Sawtooth: Rich harmonics with all integer multiples for bright, aggressive leads and synth brass.
    • Triangle: Rapidly decaying odd harmonics for soft basslines and warm tones.
    • Noise Generator: Fast deterministic 32-bit PRNG (Xorshift32) white/pink noise for explosions, wind, snare hits, and impacts.
    • Continuous Tone Generator (render_tone): Renders arbitrary duration, frequency, volume, and sample rate with sub-sample phase accuracy.

    #2. High-Precision ADSR Envelope Generator (envelope.mbt)

    • 4-Stage Modeling: Attack, Decay, Sustain, and Release with non-negative constraints.
    • Transition Curves: Both perceptual Exponential curves (natural volume decay) and Linear curves.
    • Built-in Presets:
      • ADSR::percussive(decay): Snap attack with rapid exponential drop for drums and explosions.
      • ADSR::pad(attack, release): Ambient swell with smooth in-and-out fades.
      • ADSR::organ(): Crisp keyboard articulation with rapid attack and firm sustain.
    • Click-Free Transitions: Graceful release ramping prevents waveform discontinuity pops and clicks.

    #3. Procedural SFXR Retro Sound Generator (sfxr.mbt)

    Ported, refactored, and type-safety enhanced with 100% mathematical algorithm coverage of Tomas Pettersson's legendary sfxr:
    • Core SFXR Algorithmic Pillars Fully Supported:
      • 频率滑动 (Frequency Slide & Delta Slide): Exponential frequency sweep with acceleration drift (freq_slide, freq_delta_slide).
      • 颤音 (Vibrato LFO): Sinusoidal low-frequency pitch modulation with configurable depth and rate (vibrato_depth, vibrato_speed).
      • 音高突变 (Pitch Jump / Arpeggio): Instantaneous pitch interval shift at programmable timeline offsets (change_amount, change_time).
      • 周期重复 (Cycle Repeat): Periodic envelope and frequency reset loop creating rapid stutter, laser bursts, and machine-gun tremolo effects (repeat_speed).
      • Phaser (Comb Filtering & Phase Sweep): 1024-sample circular delay line with dynamic phase offset sweep creating sweeping jet-engine comb notch filters (phaser_offset, phaser_sweep).
      • 滤波扫描 (Dynamic Low-Pass & High-Pass Filter Sweeping): Dynamic cutoff modulation per sample frame for both low-pass and high-pass filters (lpf_cutoff, lpf_sweep, hpf_cutoff, hpf_sweep).
    • 8 Classic Game Sound FX Presets:
      • laser(seed): Rapid downward frequency sweep with square/sawtooth timbre.
      • jump(seed): Upward pitch jump with snappy decay.
      • explosion(seed): Resonant low-pass filtered noise with heavy sustain punch.
      • coin(seed): Two-tone ascending arpeggio step simulating retro coin pickups.
      • hit(seed): Crunchy noise/square impact with steep pitch plunge.
      • powerup(seed): Ascending multi-harmonic saw slide with vibrato modulation.
      • blip(seed): Ultra-short high-frequency click for UI menus.
      • burst(seed): Rapid cyclic repeating multi-stage burst demonstrating cycle repetition and phaser sweep.
    • Deterministic Mutator (mutate): Perturbs existing parameters within specified intensity [0.0, 1.0] using reproducible PRNG seeds.
    • Wild Randomizer (randomize): Generates completely unexpected sound parameters for creative sound design.

    #4. Digital Signal Processing (DSP) Effects Pipeline (dsp.mbt)

    • Biquad IIR Filter:
      • Implements Robert Bristow-Johnson Audio EQ Cookbook algorithms.
      • Supports LowPass, HighPass, and BandPass with configurable cutoff frequency and resonance ( factor).
    • Cubic Overdrive Distortion (apply_overdrive):
      • Warm analog-style saturation via soft polynomial clipping:
    • Feedback Echo / Delay (apply_echo):
      • Configurable delay time in seconds, feedback regeneration ratio, and wet/dry mix.
    • Lo-Fi Bitcrusher (apply_bitcrush):
      • Emulates vintage 8-bit / 12-bit DAC quantization and downsampling artifacts.

    #5. Melodic Score Sequencer (sequencer.mbt)

    • 12-Tone Equal Temperament (12-TET):
      • Exact note pitch to frequency conversion from to using standard:
    • Rhythmic Timing & BPM:
      • Quarter, Half, Whole, Eighth, Sixteenth notes and rests calculated precisely according to tempo BPM.
    • Melody Rendering (render_score):
      • Seamlessly concatenates multiple notes with individual ADSR shaping and polyphonic mixing.
      • Built-in victory_fanfare() and arpeggio_c_major() melodies.

    #6. Binary RIFF WAVE Packaging & Web Output (wav.mbt, export.mbt)

    • Microsoft RIFF WAVE 16-Bit / 8-Bit Encoder:
      • Encodes raw audio buffers directly into standard uncompressed binary .wav byte streams.
      • Includes proper 44-byte RIFF, fmt , and data chunk headers with little-endian byte ordering.
    • RFC 4648 Base64 Data URI (to_data_uri):
      • Converts audio into inline data:audio/wav;base64,... strings ready for immediate browser playback:
        new Audio(dataUri).play();
    • Interactive HTML5 Studio (generate_html_playground):
      • Exports a self-contained, responsive dark-mode HTML page containing embedded audio clips, waveform descriptions, and instant audio playback controls.

    #7. FM (Frequency Modulation) Synthesis Engine (fm.mbt)

    Emulates classic Yamaha OPL2/OPL3 and Sega Genesis YM2612 sound chips via 2-operator Chowning FM algorithms:
    • Dynamic Carrier/Modulator Shaping: Exponential decay of modulation index captures real physical acoustic resonance.
    • Built-in Presets:
      • fm_electric_piano(freq, dur, sr): DX7-style 1:1 harmonic bell chime.
      • fm_bell(freq, dur, sr): Inharmonic metallic church bell.
      • fm_brass(freq, dur, sr): Polyphonic synth brass swell.
      • fm_slap_bass(freq, dur, sr): Sega Genesis 1:2 ratio punchy funk slap bass.

    #8. Music Macro Language (MML) Compiler (mml.mbt)

    Full retro MML parser compiling single-line score strings directly into playable PCM audio:
    • Syntax: T<bpm>, O<octave>, >, <, L<length>, V<volume>, notes C-B (with #, +, -), and rests R/P.
    • One-Liner Melody Rendering:
      ///|
      let audio = @sfx.render_mml(
      "T140 O4 C8 E8 G8 > C4",
      Square(0.5),
      ADSR::organ(),
      44100,
      )

    #9. Spatial Stereo & Multi-Track Game Mixer (types.mbt, mixer.mbt)

    • StereoBuffer & Constant-Power Panning Law:
    • Multi-Track Mixer: Polyphonic multi-track scheduler with start time offsets, per-track volume, pan, and mute controls.
    • Master Soft Limiter: Smooth algebraic saturation prevents harsh digital clipping when multiple sounds overlap.
    • Stereo WAV Encoder: Encodes 2-channel 16-bit interleaved PCM WAV files.

    #10. Native RIFF WAVE Binary Decoder (wav.mbt)

    • Header Inspection (inspect_wav): Extracts sample rate, channels, bit depth, duration, and sample count without full decoding.
    • Dual Decoder (decode_wav, decode_wav_stereo): Decodes standard 16-bit signed and 8-bit unsigned PCM WAV files back into AudioBuffer or StereoBuffer with zero external dependencies.


    #Quick Start

    #Installation

    Add zmjknn/moon_sfx to your moon.mod:

    moon add zmjknn/moon_sfx

    Or declare it in your moon.mod.json:

    { "deps": { "zmjknn/moon_sfx": "0.1.1" } }

    #Usage Examples

    #1. Generate and Play a Laser Sound

    ///|
    /// In moon.pkg:
    import {
    "zmjknn/moon_sfx" @sfx,
    }

    ///|
    /// In main.mbt:
    fn main {
    // Generate a retro laser sound using seed 42
    let wav_bytes = @sfx.play_laser_wav(42U)
    println("Generated laser WAV: \{wav_bytes.length()} bytes")
    }

    #2. Synthesize Custom Audio with Oscillator & ADSR

    ///|
    fn make_synth_note() -> @sfx.AudioBuffer {
    // Render a 440Hz Square wave for 0.5 seconds at 44.1kHz
    let tone = @sfx.render_tone(
    @sfx.Waveform::Square(0.5),
    440.0,
    0.5,
    44100,
    0.8,
    )

    // Apply percussive envelope
    let adsr = @sfx.ADSR::percussive(0.4)
    tone.apply_adsr(adsr, @sfx.Curve::Exponential)

    // Add low-pass warmth and slight echo
    tone.apply_filter(@sfx.FilterType::LowPass, 1200.0, 1.0)
    tone.apply_echo(0.05, 0.4, 0.5)

    tone
    }

    #3. Compose a Melody and Export Base64 Data URI

    ///|
    fn create_fanfare() -> String {
    let score = @sfx.Score::victory_fanfare()
    let audio = @sfx.render_score(
    score,
    140,
    @sfx.Waveform::Square(0.5),
    @sfx.ADSR::organ(),
    44100,
    )
    audio.to_data_uri()
    }


    #Running the CLI Demonstration

    The repository includes a comprehensive CLI showcase application demonstrating all presets, filter pipelines, sequencer playback, and HTML report generation:

    moon run cmd/main

    Output preview:
    ================================================================== moon_sfx: Procedural Retro Audio Synthesizer & Sound FX Engine ================================================================== 1. Generating Retro SFXR Sound FX Presets (44.1 kHz, 16-bit PCM): ------------------------------------------------------------------ - Laser Shoot: 25496 bytes (12726 samples, 288 ms) - Jump Up: 26734 bytes (13345 samples, 302 ms) - Coin Pickup: 25676 bytes (12816 samples, 290 ms) - Explosion: 75184 bytes (37570 samples, 851 ms) - Hit / Damage: 23414 bytes (11685 samples, 264 ms) - Powerup: 53430 bytes (26693 samples, 605 ms) - UI Blip Click: 8792 bytes (4374 samples, 99 ms) - Repeating Burst: 35500 bytes (17728 samples, 401 ms) 2. Demonstrating Core Waveform Oscillators: - Sine (440Hz): 8864 bytes - Square PWM 50% (440Hz): 8864 bytes - Sawtooth (440Hz): 8864 bytes - Triangle (440Hz): 8864 bytes - White Noise: 8864 bytes 3. Demonstrating DSP Digital Filters & Effects Pipeline: - Base Sawtooth Tone: 8820 samples - Applied Biquad Low-Pass Filter (800Hz, Q=1.4): OK - Applied Cubic Overdrive Distortion (drive=3.0): OK - Applied Retro Lo-Fi Bitcrusher (4-bit, 4x downsample): OK - Applied Feedback Delay / Echo (delay=40ms, feedback=0.5): OK 4. Demonstrating Musical Score Sequencer: - Victory Fanfare (BPM 140, Square Lead): * Duration: 2464 ms * Samples: 108675 * WAV Size: 217394 bytes 5. Interactive HTML5 Audio Playground Generation: - Generated Single-File HTML5 Audio Studio: 1202294 characters - Status: Ready for WebAssembly browser playback & zero-asset game audio!


    #Verification & Testing

    The package includes 53 deterministic unit, invariant, and round-trip tests covering:
    • Tomas Pettersson SFXR complete algorithm parity:
      • 频率滑动 (Frequency slide & delta acceleration slide)
      • 颤音 (Vibrato LFO depth & speed pitch modulation)
      • 音高突变 (Pitch jump arpeggio step & timing)
      • 周期重复 (Cycle repeat periodic envelope & frequency loop reset)
      • Phaser (1024-sample circular comb filter phase sweep)
      • 滤波扫描 (Dynamic Low-Pass & High-Pass cutoff sweep modulation)
    • Extreme parameter resilience and defensive guards (zero division, infinite loop, negative envelope/frequency/phaser sweeps)
    • Word-aligned odd-length RIFF chunk padding support
    • Strict stereo pan isolation invariants (pure left/right channel silence)
    • Mathematical waveform phase boundary accuracy
    • Robert Bristow-Johnson biquad filter stability
    • ADSR envelope phase transitions (Attack, Decay, Sustain, Release)
    • RIFF WAVE binary header compliance and 16-bit/8-bit byte layout
    • Bi-directional WAV encoding and decoding round-trip integrity
    • Stereo constant-power panning law and multi-track mixing
    • FM 2-operator frequency modulation and dynamic index decay
    • Music Macro Language (MML) syntax parsing and compilation
    • RFC 4648 Base64 official test vectors
    • 12-Tone equal temperament pitch calculation accuracy ()
    • High-throughput multi-voice audio mixing and memory safety

    Run all tests:

    moon test

    Result:
    Total tests: 46, passed: 46, failed: 0.


    #References & Attribution

    • Tomas Pettersson, original creator of sfxr (Public Domain)
    • Chris McCormick, jsfxr (Apache-2.0)
    • Robert Bristow-Johnson, Cookbook formulae for audio equalizer biquad filter coefficients
    • Microsoft Corporation & IBM, Multimedia Programming Interface and Data Specifications 1.0 (RIFF WAVE)


    #License

    Licensed under the Apache License, Version 2.0.

    ADSR

    pub struct ADSR {
    attack : Double
    decay : Double
    sustain : Double
    release : Double
    } derive(Eq,
    Debug
    )

    Standard 4-stage Attack-Decay-Sustain-Release audio envelope generator.

    ADSR::gain_at

    fn ADSR::gain_at(self : ADSR, time : Double, total_duration : Double, curve : Curve) -> Double

    Computes the envelope gain factor [0.0, 1.0] at a given timestamp within total duration.

    ADSR::new

    fn ADSR::new(attack : Double, decay : Double, sustain : Double, release : Double) -> ADSR

    Constructs a new ADSR configuration ensuring non-negative values.

    ADSR::organ

    fn ADSR::organ() -> ADSR

    Punchy organ/synth-lead envelope with minimal attack and quick release.

    ADSR::pad

    fn ADSR::pad(attack_sec : Double, release_sec : Double) -> ADSR

    Sustained pad envelope with smooth fading in and out.

    ADSR::percussive

    fn ADSR::percussive(decay_sec : Double) -> ADSR

    Fast percussive envelope ideal for drums, explosions, and impact hits.

    AudioBuffer

    pub struct AudioBuffer {
    sample_rate : Int
    samples : Array[Double]
    } derive(Eq)

    A mono linear floating-point audio buffer holding raw PCM samples normalized between -1.0 and 1.0.

    AudioBuffer::amplify

    fn AudioBuffer::amplify(self : AudioBuffer, gain : Double) -> Unit

    Multiplies all samples by a gain factor.

    AudioBuffer::apply_adsr

    fn AudioBuffer::apply_adsr(self : AudioBuffer, adsr : ADSR, curve : Curve) -> Unit

    Applies this ADSR envelope in-place across an entire AudioBuffer.

    AudioBuffer::apply_bitcrush

    fn AudioBuffer::apply_bitcrush(self : AudioBuffer, bits : Int, downsample_factor : Int) -> Unit

    Bitcrushes and downsamples the audio buffer to emulate classic 8-bit / 12-bit lo-fi retro sound chips.

    AudioBuffer::apply_echo

    fn AudioBuffer::apply_echo(self : AudioBuffer, delay_seconds : Double, feedback : Double, wet_mix : Double) -> Unit

    Applies a feedback echo / delay effect to the audio buffer.

    AudioBuffer::apply_filter

    fn AudioBuffer::apply_filter(self : AudioBuffer, filter_type : FilterType, cutoff_freq : Double, resonance_q : Double) -> Unit

    Applies a biquad filter across all samples in the AudioBuffer.

    AudioBuffer::apply_overdrive

    fn AudioBuffer::apply_overdrive(self : AudioBuffer, drive : Double) -> Unit

    Applies warm cubic overdrive distortion to the buffer. drive parameter controls intensity (1.0 = gentle saturation, 5.0+ = heavy fuzz).

    AudioBuffer::clamp

    fn AudioBuffer::clamp(self : AudioBuffer, min : Double, max : Double) -> Unit

    Hard clamps all samples to the range [min, max].

    AudioBuffer::clone

    fn AudioBuffer::clone(self : AudioBuffer) -> AudioBuffer

    Creates a deep copy of this AudioBuffer.

    AudioBuffer::duration

    fn AudioBuffer::duration(self : AudioBuffer) -> Double

    Returns total duration of the buffer in seconds.

    AudioBuffer::get

    fn AudioBuffer::get(self : AudioBuffer, index : Int) -> Double

    Gets sample at index with bounds checking, returning 0.0 if out of bounds.

    AudioBuffer::length

    fn AudioBuffer::length(self : AudioBuffer) -> Int

    Returns the number of samples in the buffer.

    AudioBuffer::mix

    fn AudioBuffer::mix(self : AudioBuffer, other : AudioBuffer, offset_samples : Int, volume : Double) -> Unit

    Mixes another audio buffer into this buffer starting at offset_samples with volume scaling.

    AudioBuffer::new

    fn AudioBuffer::new(sample_rate : Int, _capacity : Int) -> AudioBuffer

    Creates a new empty AudioBuffer with specified sample rate and reserved capacity.

    AudioBuffer::normalize

    fn AudioBuffer::normalize(self : AudioBuffer, target_peak : Double) -> Unit

    Normalizes peak amplitude to target_peak (usually 0.95 or 1.0) to prevent clipping.

    AudioBuffer::push

    fn AudioBuffer::push(self : AudioBuffer, sample : Double) -> Unit

    Appends a sample to the end of the buffer.

    AudioBuffer::sample_rate

    fn AudioBuffer::sample_rate(self : AudioBuffer) -> Int

    Returns the sample rate of the audio buffer in Hz.

    AudioBuffer::samples

    fn AudioBuffer::samples(self : AudioBuffer) -> Array[Double]

    Returns the raw samples array.

    AudioBuffer::set

    fn AudioBuffer::set(self : AudioBuffer, index : Int, value : Double) -> Unit

    Sets sample at index if within bounds.

    AudioBuffer::soft_limit

    fn AudioBuffer::soft_limit(self : AudioBuffer, threshold : Double) -> Unit

    Smoothly soft-limits samples exceeding threshold using an algebraic saturation curve. Prevents harsh digital clipping when multiple sounds or loud gains are summed together.

    AudioBuffer::to_16bit_pcm

    fn AudioBuffer::to_16bit_pcm(self : AudioBuffer) -> Array[Int]

    Converts float samples in [-1.0, 1.0] to signed 16-bit integers [-32768, 32767].

    AudioBuffer::to_8bit_pcm

    fn AudioBuffer::to_8bit_pcm(self : AudioBuffer) -> Array[Byte]

    Converts float samples in [-1.0, 1.0] to unsigned 8-bit bytes [0, 255] with center at 128.

    AudioBuffer::to_data_uri

    fn AudioBuffer::to_data_uri(self : AudioBuffer) -> String

    Encodes an AudioBuffer as a self-contained Base64 Data URI string ("data:audio/wav;base64,...").

    AudioBuffer::to_stereo

    fn AudioBuffer::to_stereo(self : AudioBuffer, pan : Double) -> StereoBuffer

    Converts a mono AudioBuffer into a StereoBuffer using the Constant-Power Panning Law. pan parameter: -1.0 = 100% Left, 0.0 = Center (balanced), 1.0 = 100% Right.

    AudioBuffer::with_silence

    fn AudioBuffer::with_silence(sample_rate : Int, count : Int) -> AudioBuffer

    Creates an AudioBuffer prefilled with silent samples (0.0).

    BiquadFilter

    pub struct BiquadFilter {
    b0 : Double
    b1 : Double
    b2 : Double
    a1 : Double
    a2 : Double
    x1 : Double
    x2 : Double
    y1 : Double
    y2 : Double
    }

    Digital biquad IIR filter implementing Robert Bristow-Johnson Audio EQ Cookbook algorithms.

    BiquadFilter::new

    fn BiquadFilter::new(filter_type : FilterType, cutoff_freq : Double, resonance_q : Double, sample_rate : Int) -> BiquadFilter

    Creates a new BiquadFilter with given filter type, cutoff frequency, and resonance Q factor.

    BiquadFilter::process

    fn BiquadFilter::process(self : BiquadFilter, x : Double) -> Double

    Processes a single input sample through the biquad filter.

    BiquadFilter::update_cutoff

    fn BiquadFilter::update_cutoff(self : BiquadFilter, filter_type : FilterType, cutoff_freq : Double, resonance_q : Double, sample_rate : Int) -> Unit

    Dynamically updates the cutoff frequency and recalculates filter coefficients. Enables continuous dynamic filter sweeping during audio rendering without allocating new objects.

    Curve

    pub(all) enum Curve {
    Linear
    Exponential
    } derive(Eq,
    Debug
    )

    Transition curve style for ADSR envelope phases.

    Duration

    pub(all) enum Duration {
    Whole
    Half
    Quarter
    Eighth
    Sixteenth
    } derive(Eq,
    Debug
    )

    Musical note duration relative to measure meter.

    FilterType

    pub(all) enum FilterType {
    LowPass
    HighPass
    BandPass
    } derive(Eq,
    Debug
    )

    Filter type for digital biquad filtering.

    Mixer

    pub struct Mixer {
    sample_rate : Int
    tracks : Array[Track]
    master_volume : Double
    } derive(Eq)

    Multi-track game audio mixer supporting polyphonic track scheduling, stereo panning per track, and anti-clipping master soft limiting.

    Mixer::add_track

    fn Mixer::add_track(self : Mixer, buffer : AudioBuffer, offset_seconds : Double, volume : Double, pan : Double) -> Unit

    Adds an audio buffer to the mixer scheduled to start at offset_seconds with individual volume and stereo pan (-1.0 to 1.0).

    Mixer::duration

    fn Mixer::duration(self : Mixer) -> Double

    Returns total duration of the mixed master output in seconds.

    Mixer::new

    fn Mixer::new(sample_rate : Int) -> Mixer

    Creates an empty Mixer with the specified sample rate.

    Mixer::render_mono

    fn Mixer::render_mono(self : Mixer) -> AudioBuffer

    Renders all scheduled tracks into a mono AudioBuffer with master soft-limiting.

    Mixer::render_stereo

    fn Mixer::render_stereo(self : Mixer) -> StereoBuffer

    Renders all scheduled tracks into a 2-channel StereoBuffer. Implements Constant-Power Panning per track and master soft-limiting.

    Mixer::set_master_volume

    fn Mixer::set_master_volume(self : Mixer, vol : Double) -> Unit

    Sets the overall master volume of the mixer.

    Note

    pub(all) enum Note {
    C
    Cs
    D
    Ds
    E
    F
    Fs
    G
    Gs
    A
    As
    B
    Rest
    } derive(Eq,
    Debug
    )

    Semitone musical pitch class in standard 12-tone equal temperament.

    Rng

    pub struct Rng {
    state : UInt
    }

    Fast deterministic pseudo-random number generator (Xorshift32) for reproducible audio noise and parameter mutation.

    Rng::new

    fn Rng::new(seed : UInt) -> Rng

    Creates a new Rng with the given 32-bit unsigned seed.

    Rng::next_bipolar

    fn Rng::next_bipolar(self : Rng) -> Double

    Generates a uniform bipolar float in the range [-1.0, 1.0).

    Rng::next_double

    fn Rng::next_double(self : Rng) -> Double

    Generates a uniform float in the range [0.0, 1.0).

    Rng::next_u32

    fn Rng::next_u32(self : Rng) -> UInt

    Generates the next pseudorandom 32-bit unsigned integer.

    Score

    pub struct Score {
    items : Array[ScoreItem]
    } derive(Eq,
    Debug
    )

    A musical sequence of notes played sequentially.

    Score::add

    fn Score::add(self : Score, note : Note, octave : Int, duration : Duration, volume : Double) -> Unit

    Appends a note to the musical score.

    Score::arpeggio_c_major

    fn Score::arpeggio_c_major() -> Score

    Creates a classic retro C Major ascending/descending arpeggio.

    Score::length

    fn Score::length(self : Score) -> Int

    Returns the number of notes in this score.

    Score::new

    fn Score::new() -> Score

    Creates an empty musical score.

    Score::victory_fanfare

    fn Score::victory_fanfare() -> Score

    Creates a triumphant retro game victory fanfare jingle.

    ScoreItem

    pub struct ScoreItem {
    note : Note
    octave : Int
    duration : Duration
    volume : Double
    } derive(Eq,
    Debug
    )

    A single scored note event with pitch, octave, duration, and velocity volume.

    ScoreItem::new

    fn ScoreItem::new(note : Note, octave : Int, duration : Duration, volume : Double) -> ScoreItem

    Creates a new ScoreItem.

    SfxParams

    pub(all) struct SfxParams {
    wave_type : Waveform
    start_freq : Double
    min_freq : Double
    freq_slide : Double
    freq_delta_slide : Double
    square_duty : Double
    duty_sweep : Double
    vibrato_depth : Double
    vibrato_speed : Double
    attack_time : Double
    sustain_time : Double
    sustain_punch : Double
    decay_time : Double
    lpf_cutoff : Double
    lpf_resonance : Double
    lpf_sweep : Double
    hpf_cutoff : Double
    hpf_sweep : Double
    phaser_offset : Double
    phaser_sweep : Double
    repeat_speed : Double
    change_amount : Double
    change_time : Double
    master_volume : Double
    } derive(Eq,
    Debug
    )

    Comprehensive configuration parameters for procedural retro sound synthesis (sfxr engine). Implements 100% full feature parity with Tomas Pettersson's legendary sfxr algorithm, covering frequency slides, vibrato, pitch jumps (arpeggios), cycle repeats, phaser sweeps, and dynamic Low-Pass / High-Pass filter cutoff sweeps.

    SfxParams::blip

    fn SfxParams::blip(seed : UInt) -> SfxParams

    Generates a crisp, snappy retro UI "Blip / Select" click sound effect.

    SfxParams::burst

    fn SfxParams::burst(seed : UInt) -> SfxParams

    Generates a periodic stuttering burst sound effect, showcasing cycle repeat and phaser.

    SfxParams::coin

    fn SfxParams::coin(seed : UInt) -> SfxParams

    Generates a bright, ascending two-tone retro "Coin / Pickup" sound effect. Employs pitch change arpeggio jumping upward by approx 5 semitones.

    SfxParams::default

    fn SfxParams::default() -> SfxParams

    Creates a default baseline SfxParams structure.

    SfxParams::explosion

    fn SfxParams::explosion(seed : UInt) -> SfxParams

    Generates a thunderous retro "Explosion" sound effect parameters. Leverages dynamic low-pass filter cutoff sweep to dive into deep rumble.

    SfxParams::hit

    fn SfxParams::hit(seed : UInt) -> SfxParams

    Generates a heavy crunchy retro "Hit / Hurt" sound effect. Uses high-pass filter sweep and steep frequency slide.

    SfxParams::jump

    fn SfxParams::jump(seed : UInt) -> SfxParams

    Generates a classic retro "Jump" sound effect parameters. Features a prominent upward frequency slide and snappy decay.

    SfxParams::laser

    fn SfxParams::laser(seed : UInt) -> SfxParams

    Generates a classic retro "Laser / Shoot" sound effect parameters. Incorporates rapid downward frequency slide and classic sci-fi phaser sweep.

    SfxParams::mutate

    fn SfxParams::mutate(self : SfxParams, amount : Double, seed : UInt) -> SfxParams

    Mutates existing parameters by a perturbation factor [0.0, 1.0] to create subtle variations.

    SfxParams::powerup

    fn SfxParams::powerup(seed : UInt) -> SfxParams

    Generates an ascending, triumphant retro "Powerup" sound effect. Features frequency slide, vibrato modulation, and expanding filter sweep.

    SfxParams::randomize

    fn SfxParams::randomize(seed : UInt) -> SfxParams

    Generates a completely randomized retro sound effect covering all parameter dimensions.

    SfxParams::set_duty_sweep

    fn SfxParams::set_duty_sweep(self : SfxParams, sweep : Double) -> Unit

    SfxParams::set_freq_delta_slide

    fn SfxParams::set_freq_delta_slide(self : SfxParams, delta : Double) -> Unit

    SfxParams::set_hpf_cutoff

    fn SfxParams::set_hpf_cutoff(self : SfxParams, cutoff : Double) -> Unit

    SfxParams::set_hpf_sweep

    fn SfxParams::set_hpf_sweep(self : SfxParams, sweep : Double) -> Unit

    SfxParams::set_lpf_sweep

    fn SfxParams::set_lpf_sweep(self : SfxParams, sweep : Double) -> Unit

    SfxParams::set_master_volume

    fn SfxParams::set_master_volume(self : SfxParams, volume : Double) -> Unit

    SfxParams::set_phaser

    fn SfxParams::set_phaser(self : SfxParams, offset : Double, sweep : Double) -> Unit

    SfxParams::set_repeat_speed

    fn SfxParams::set_repeat_speed(self : SfxParams, speed : Double) -> Unit

    SfxParams::synthesize

    fn SfxParams::synthesize(self : SfxParams, sample_rate : Int) -> AudioBuffer

    Synthesizes raw audio samples into an AudioBuffer according to SfxParams. Full coverage of all 6 core sfxr algorithmic pillars:
    1. Frequency Slide & Acceleration (freq_slide, freq_delta_slide)
    2. LFO Vibrato (vibrato_speed, vibrato_depth)
    3. Pitch Change Arpeggio (change_amount, change_time)
    4. Cycle Repeat (repeat_speed)
    5. Phaser delay comb filtering (phaser_offset, phaser_sweep)
    6. Dynamic Filter Cutoff Sweeping (lpf_cutoff, lpf_sweep, hpf_cutoff, hpf_sweep)

    StereoBuffer

    pub struct StereoBuffer {
    sample_rate : Int
    left : AudioBuffer
    right : AudioBuffer
    } derive(Eq)

    A stereo audio buffer containing separate left and right PCM audio channels.

    StereoBuffer::amplify

    fn StereoBuffer::amplify(self : StereoBuffer, gain : Double) -> Unit

    Amplifies both channels by a gain multiplier.

    StereoBuffer::clone

    Deep copies a StereoBuffer.

    StereoBuffer::duration

    fn StereoBuffer::duration(self : StereoBuffer) -> Double

    Returns the duration of the stereo buffer in seconds.

    StereoBuffer::from_channels

    fn StereoBuffer::from_channels(left : AudioBuffer, right : AudioBuffer) -> StereoBuffer

    Creates a StereoBuffer from two individual mono channels.

    StereoBuffer::from_mono

    fn StereoBuffer::from_mono(mono : AudioBuffer, pan : Double) -> StereoBuffer

    Convenience helper to create a StereoBuffer from a mono buffer and pan value.

    StereoBuffer::left

    Returns the left channel AudioBuffer.

    StereoBuffer::length

    fn StereoBuffer::length(self : StereoBuffer) -> Int

    Returns the number of sample frames in the stereo buffer.

    StereoBuffer::new

    fn StereoBuffer::new(sample_rate : Int, capacity : Int) -> StereoBuffer

    Creates a new StereoBuffer with specified sample rate and capacity.

    StereoBuffer::normalize

    fn StereoBuffer::normalize(self : StereoBuffer, target_peak : Double) -> Unit

    Normalizes both channels of the stereo buffer relative to the highest peak.

    StereoBuffer::right

    Returns the right channel AudioBuffer.

    StereoBuffer::sample_rate

    fn StereoBuffer::sample_rate(self : StereoBuffer) -> Int

    Returns the sample rate of the stereo buffer.

    StereoBuffer::to_data_uri

    fn StereoBuffer::to_data_uri(self : StereoBuffer) -> String

    Encodes a StereoBuffer as a self-contained Base64 Data URI string.

    Track

    pub struct Track {
    buffer : AudioBuffer
    offset_seconds : Double
    volume : Double
    pan : Double
    mute : Bool
    } derive(Eq)

    A single audio track within the multi-track Mixer.

    Track::new

    fn Track::new(buffer : AudioBuffer, offset_seconds : Double, volume : Double, pan : Double) -> Track

    Creates a new Track.

    Track::set_mute

    fn Track::set_mute(self : Track, mute : Bool) -> Unit

    Mutes or unmutes this track.

    WavInfo

    pub struct WavInfo {
    sample_rate : Int
    num_channels : Int
    bits_per_sample : Int
    num_samples : Int
    duration : Double
    } derive(Eq,
    Debug
    )

    Metadata information parsed from a standard RIFF WAVE file header.

    Waveform

    pub(all) enum Waveform {
    Sine
    Square(Double)
    Sawtooth
    Triangle
    Noise
    } derive(Eq,
    Debug
    )

    Represents the fundamental wave shapes used for sound synthesis.

    decode_wav

    fn decode_wav(bytes : Bytes) -> Result[AudioBuffer, String]

    Decodes a RIFF WAVE byte stream into a mono AudioBuffer. If the file is stereo, both channels are averaged into mono.

    decode_wav_stereo

    fn decode_wav_stereo(bytes : Bytes) -> Result[StereoBuffer, String]

    Decodes a 2-channel RIFF WAVE byte stream into a StereoBuffer.

    duration_to_seconds

    fn duration_to_seconds(duration : Duration, bpm : Int) -> Double

    Converts Duration enum to duration in seconds based on Tempo BPM.

    encode_wav_16bit

    fn encode_wav_16bit(buffer : AudioBuffer) -> Bytes

    Encodes an AudioBuffer into standard 16-bit signed PCM Microsoft RIFF WAVE binary bytes.

    encode_wav_8bit

    fn encode_wav_8bit(buffer : AudioBuffer) -> Bytes

    Encodes an AudioBuffer into standard 8-bit unsigned PCM Microsoft RIFF WAVE binary bytes.

    encode_wav_stereo_16bit

    fn encode_wav_stereo_16bit(stereo : StereoBuffer) -> Bytes

    Encodes a StereoBuffer into standard 2-channel 16-bit signed PCM Microsoft RIFF WAVE binary bytes.

    fm_bell

    fn fm_bell(freq : Double, duration : Double, sample_rate : Int) -> AudioBuffer

    FM Preset 2: Crystal Chime / Metallic Church Bell. Uses inharmonic ratio (1 : sqrt(2) ≈ 1 : 1.4142) to produce authentic metallic overtones.

    fm_brass

    fn fm_brass(freq : Double, duration : Double, sample_rate : Int) -> AudioBuffer

    FM Preset 3: 80s Synth Brass / Synth Horn. Features a dynamic filter swell characteristic of vintage polyphonic brass synthesizers.

    fm_electric_piano

    fn fm_electric_piano(freq : Double, duration : Double, sample_rate : Int) -> AudioBuffer

    FM Preset 1: Yamaha DX7 style retro Electric Piano (E-Piano). Uses 1:1 harmonic ratio with snappy attack and warm metallic bell transient.

    fm_slap_bass

    fn fm_slap_bass(freq : Double, duration : Double, sample_rate : Int) -> AudioBuffer

    FM Preset 4: Sega Genesis 16-bit Funk Slap Bass. Uses 1:2 harmonic ratio for punching second harmonic transient.

    generate_html_playground

    fn generate_html_playground() -> String

    Generates a complete, self-contained interactive HTML5 audio playground page with embedded base64 sounds.

    inspect_wav

    fn inspect_wav(bytes : Bytes) -> Result[WavInfo, String]

    Inspects metadata from a RIFF WAVE byte stream without fully decoding all audio samples.

    note_to_frequency

    fn note_to_frequency(note : Note, octave : Int) -> Double

    Calculates exact fundamental frequency in Hertz based on A4 = 440 Hz standard.

    parse_mml

    fn parse_mml(mml : String) -> (Score, Int)

    Parses an MML string into a Score and tempo BPM.

    Supported MML Syntax:
    • T<bpm>: Sets playback tempo (e.g. T140). Default: 120.
    • O<octave>: Sets octave 1..7 (e.g. O4). Default: 4.
    • >: Octave up by 1.
    • <: Octave down by 1.
    • L<length>: Sets default note duration: 1 (Whole), 2 (Half), 4 (Quarter), 8 (Eighth), 16 (Sixteenth). Default: 4.
    • V<volume>: Sets volume 0..100 (e.g. V80 -> 0.8). Default: 80.
    • Notes C, D, E, F, G, A, B:
      • Optional accidentals: # or + (sharp), - (flat)
      • Optional explicit duration: e.g. C8, F#16, D-2, A1
    • Rests: R or P with optional duration (e.g. R4, R8).
    • Whitespace and bar dividers |, ,, ; are ignored.
    let pi : Double

    play_blip_wav

    fn play_blip_wav(seed : UInt) -> Bytes

    Quick one-liner helper to generate a Blip click sound effect WAV byte array.

    play_burst_wav

    fn play_burst_wav(seed : UInt) -> Bytes

    Quick one-liner helper to generate a Periodic Repeating Burst sound effect WAV byte array.

    play_coin_wav

    fn play_coin_wav(seed : UInt) -> Bytes

    Quick one-liner helper to generate a Coin pickup sound effect WAV byte array.

    play_explosion_wav

    fn play_explosion_wav(seed : UInt) -> Bytes

    Quick one-liner helper to generate an Explosion sound effect WAV byte array.

    play_hit_wav

    fn play_hit_wav(seed : UInt) -> Bytes

    Quick one-liner helper to generate a Hit / Hurt sound effect WAV byte array.

    play_jump_wav

    fn play_jump_wav(seed : UInt) -> Bytes

    Quick one-liner helper to generate a Jump sound effect WAV byte array.

    play_laser_wav

    fn play_laser_wav(seed : UInt) -> Bytes

    Quick one-liner helper to generate a Laser sound effect WAV byte array.

    play_powerup_wav

    fn play_powerup_wav(seed : UInt) -> Bytes

    Quick one-liner helper to generate a Powerup sound effect WAV byte array.

    render_fm_dynamic

    fn render_fm_dynamic(carrier_freq : Double, mod_freq : Double, mod_index_start : Double, mod_index_end : Double, duration : Double, sample_rate : Int, adsr : ADSR, volume : Double) -> AudioBuffer

    Renders an expressive 2-operator dynamic FM tone with time-varying modulation index and ADSR envelope. The modulation index dynamically transitions from mod_index_start to mod_index_end, mimicking physical acoustic instruments where harmonic brightness decays faster than base loudness.

    render_fm_tone

    fn render_fm_tone(carrier_freq : Double, mod_freq : Double, mod_index : Double, duration : Double, sample_rate : Int, volume : Double) -> AudioBuffer

    Renders a basic static 2-operator FM tone where the carrier oscillator is frequency-modulated by a sinusoidal modulator oscillator.
    • carrier_freq: Base pitch frequency in Hz (fc)
    • mod_freq: Modulator oscillator frequency in Hz (fm)
    • mod_index: Modulation index I = Delta f / fm (higher index adds more bright sideband harmonics)

    render_mml

    fn render_mml(mml : String, waveform : Waveform, adsr : ADSR, sample_rate : Int) -> AudioBuffer

    Compiles an MML string directly into a rendered AudioBuffer.

    render_score

    fn render_score(score : Score, bpm : Int, waveform : Waveform, adsr : ADSR, sample_rate : Int) -> AudioBuffer

    Renders an entire Score into an AudioBuffer using the specified waveform and ADSR articulation.

    render_tone

    fn render_tone(waveform : Waveform, frequency : Double, duration_sec : Double, sample_rate : Int, volume : Double) -> AudioBuffer

    Generates a continuous audio buffer playing a constant pitch tone for a given duration.

    sample_waveform

    fn sample_waveform(waveform : Waveform, phase : Double, rng : Rng) -> Double

    Evaluates a single waveform sample at a given normalized phase in [0.0, 1.0).

    to_base64

    fn to_base64(bytes : Bytes) -> String

    Encodes raw binary bytes into a standard RFC 4648 Base64 string.

    two_pi

    let two_pi : Double

    write_u16_le

    fn write_u16_le(b : FixedArray[Byte], offset : Int, val : Int) -> Unit

    Writes a 16-bit unsigned integer into FixedArray[Byte] in Little-Endian order.

    write_u32_le

    fn write_u32_le(b : FixedArray[Byte], offset : Int, val : Int) -> Unit

    Writes a 32-bit integer into FixedArray[Byte] in Little-Endian order.