audio

audio encoder for wav/ogg

moonbit
audio
mixer
wav
ogg
moon add mizchi/audio@0.1.1
Download zip
Author
Version
0.1.1
License
Apache-2.0
Last updated
3 months ago
Downloads
1K
README

#mizchi/audio-mpt

WIP audio library for MoonBit.

#Goal

  • Provide mixer/decoder/playback primitives for games
  • Keep API backend-agnostic for js/native/wasm

#Package

  • mizchi/audio-mpt

#Status

  • Boilerplate only
  • See TODO.md for the implementation plan

#
AudioError

pub suberror AudioError {
InvalidFormat(String)
DecodeFailed(String)
}

Audio subsystem errors.
impl Show for AudioError

#
AssetCache

pub(all) struct AssetCache {
entries : Map[String, CacheEntry]
total_bytes : Int
max_bytes : Int
max_entries : Int
access_counter : Int
}

LRU asset cache for audio buffers.
impl Show for AssetCache

#
AudioBackendHooks

pub(all) struct AudioBackendHooks {
initialize : (Int, Int) -> Unit
write : (FixedArray[Float], Int) -> Unit
suspend : () -> Unit
resume_playback : () -> Unit
close : () -> Unit
report_consumed : () -> Int
}

Backend hooks for platform-specific audio output.

#
AudioBuffer

pub(all) struct AudioBuffer {
channels : Int
sample_rate : Int
data : FixedArray[Float]
}

PCM audio buffer with interleaved sample data.
impl Eq for AudioBuffer
impl Show for AudioBuffer

#
AudioCommand

pub(all) enum AudioCommand {
PlaySource(AudioSource, Float, Float, Bool)
PauseVoice(VoiceId)
ResumeVoice(VoiceId)
StopVoice(VoiceId)
SeekVoice(VoiceId, Int)
SetVoiceGain(VoiceId, Float)
SetVoicePan(VoiceId, Float)
SetMasterGain(Float)
}

Commands for controlling the audio mixer from any thread.

#
AudioRuntime

pub(all) struct AudioRuntime {
mixer : Mixer
output_buffer : FixedArray[Float]
frames_per_tick : Int
tick_count : Int
initialized : Bool
command_queue : CommandQueue
latency_monitor : LatencyMonitor
}

High-level audio runtime that integrates the mixer with backend hooks.

#
AudioSource

pub(all) enum AudioSource {
Buffer(AudioBuffer)
Stream(StreamingSource)
}

Audio source: either a complete buffer or a streaming source.
impl Show for AudioSource

#
BiquadState

pub(all) struct BiquadState {
b0 : Float
b1 : Float
b2 : Float
a1 : Float
a2 : Float
z1 : Float
z2 : Float
}

Biquad filter state (Direct Form II Transposed).
impl Show for BiquadState

#
BitReader

type BitReader

LSB-first bit reader for Vorbis bitstream parsing.
impl Show for BitReader

#
CacheEntry

pub(all) struct CacheEntry {
buffer : AudioBuffer
policy : CachePolicy
byte_size : Int
last_access : Int
}

Single entry in the asset cache.
impl Show for CacheEntry

#
CachePolicy

pub(all) enum CachePolicy {
AlwaysCache
Normal
StreamPrefer
}

Cache eviction policy for audio assets.
impl Eq for CachePolicy
impl Show for CachePolicy

#
CommandQueue

pub(all) struct CommandQueue {
commands : Array[AudioCommand]
pending_ids : Array[VoiceId]
}

Queue of audio commands to be flushed on the mixer thread.

#
DelayState

pub(all) struct DelayState {
buffer : FixedArray[Float]
write_pos : Int
delay_samples : Int
feedback : Float
mix : Float
}

Delay effect state.
impl Show for DelayState

#
EffectNode

pub(all) enum EffectNode {
Lowpass(BiquadState)
Highpass(BiquadState)
Delay(DelayState)
}

Effect node in the processing chain.
impl Show for EffectNode

#
Envelope

pub(all) struct Envelope {
config : EnvelopeConfig
sample_rate : Int
phase : EnvelopePhase
level : Float
phase_position : Int
release_start_level : Float
}

ADSR envelope state machine.
impl Show for Envelope

#
EnvelopeConfig

pub(all) struct EnvelopeConfig {
attack : Float
decay : Float
sustain : Float
release_time : Float
}

ADSR envelope configuration.

#
EnvelopePhase

pub(all) enum EnvelopePhase {
Attack
Decay
Sustain
Release
Done
}

Envelope phase in ADSR state machine.
impl Eq for EnvelopePhase

#
LatencyMonitor

pub(all) struct LatencyMonitor {
frames_written : Int
ticks_elapsed : Int
drift_frames_val : Int
underrun_count : Int
max_drift : Int
}

Monitors audio latency and drift between producer and consumer.

#
Mixer

pub(all) struct Mixer {
voices : Array[Voice]
master_gain : Float
channels : Int
sample_rate : Int
resample_quality : ResampleQuality
next_voice_id : Int
}

Multi-voice mixer with master gain.

#
OggDemuxer

type OggDemuxer

OGG container demuxer.
impl Show for OggDemuxer

#
OggPage

type OggPage

OGG page header.
impl Show for OggPage

#
PullCallback

pub(all) type PullCallback (FixedArray[Float], Int) -> Int

Callback that pulls audio data into a buffer. Returns frames actually written.

#
PullCallback::inner

#deprecated("Use `struct T(A)` to declare a newtype and use `.0` access the underlying type instead.")
fn PullCallback::inner(self : PullCallback) -> ((FixedArray[Float], Int) -> Int)
Convert newtype to its underlying type, automatically derived.

#
ResampleQuality

pub(all) enum ResampleQuality {
Nearest
Linear
Cubic
}

Resampling quality presets.

#
RingBuffer

pub(all) struct RingBuffer {
data : FixedArray[Float]
capacity : Int
channels : Int
write_pos : Int
read_pos : Int
frames_available : Int
}

Ring buffer for streaming audio data.
impl Show for RingBuffer

#
StreamingSource

pub(all) struct StreamingSource {
ring : RingBuffer
pull : PullCallback
channels : Int
sample_rate : Int
ended : Bool
total_pulled : Int
}

Streaming audio source backed by a ring buffer.

#
Voice

pub(all) struct Voice {
id : VoiceId
source : AudioSource
position : Float
gain : Float
pan : Float
state : VoiceState
looping : Bool
sample_rate : Int
loop_start : Int
loop_end : Int
envelope : Envelope?
effects : Array[EffectNode]
}

A single voice playing an audio source.
impl Show for Voice

#
VoiceId

pub(all) type VoiceId Int

Stable voice identifier.
impl Compare for VoiceId
impl Eq for VoiceId
impl Hash for VoiceId
impl Show for VoiceId

#
VoiceId::inner

#deprecated("Use `struct T(A)` to declare a newtype and use `.0` access the underlying type instead.")
fn VoiceId::inner(self : VoiceId) -> Int
Convert newtype to its underlying type, automatically derived.

#
VoiceState

pub(all) enum VoiceState {
Playing
Paused
Stopped
}

Voice playback state.
impl Eq for VoiceState
impl Show for VoiceState

#
VorbisCodebook

type VorbisCodebook

A Vorbis codebook for Huffman decoding and VQ lookup.

#
VorbisFloorConfig

type VorbisFloorConfig

Vorbis floor type 1 configuration.

#
VorbisInfo

type VorbisInfo

Vorbis stream configuration parsed from headers.
impl Show for VorbisInfo

#
VorbisMapping

type VorbisMapping

Vorbis channel mapping.

#
VorbisMode

type VorbisMode

Vorbis mode configuration.
impl Show for VorbisMode

#
VorbisResidueConfig

type VorbisResidueConfig

Vorbis residue configuration.

#
add_voice

fn add_voice(mixer : Mixer, voice : Voice) -> VoiceId

Add a voice to the mixer. Returns the voice ID.

#
audio_tick

fn audio_tick(rt : AudioRuntime) -> Unit

Run one game tick: flush commands, mix audio, write to backend, track latency.

#
biquad_process

fn biquad_process(state : BiquadState, input : Float) -> Float

Process one sample through a biquad filter (Direct Form II Transposed).

#
cache_clear

fn cache_clear(cache : AssetCache) -> Unit

Clear all entries from the cache.

#
cache_evict

fn cache_evict(cache : AssetCache, key : String) -> Bool

Evict a specific key from the cache. Returns true if found and removed.

#
cache_get

fn cache_get(cache : AssetCache, key : String) -> AudioBuffer?

Get a cached audio buffer by key. Returns None if not found.

#
cache_put

fn cache_put(cache : AssetCache, key : String, buffer : AudioBuffer, policy? : CachePolicy) -> Unit

Put an audio buffer into the cache. Evicts entries if needed.

#
collect_stopped

fn collect_stopped(mixer : Mixer) -> Unit

Remove stopped voices from the mixer.

#
decode_ogg

fn decode_ogg(raw : Bytes) -> AudioBuffer raise AudioError

Top-level OGG/Vorbis decode function. Decodes an OGG/Vorbis file from raw bytes into an AudioBuffer.

#
decode_wav

fn decode_wav(raw : Bytes) -> AudioBuffer raise AudioError

Decode a WAV file from raw bytes into an AudioBuffer. Supports PCM format (format=1), 8-bit and 16-bit.

#
delay_process

fn delay_process(state : DelayState, input : Float) -> Float

Process one sample through the delay effect. Ring buffer: write_pos always points to the oldest sample (delay_samples ago).

#
drift_frames

fn drift_frames(monitor : LatencyMonitor) -> Int

Get current drift in frames.

#
drift_secs

fn drift_secs(monitor : LatencyMonitor, sample_rate : Int) -> Float

Get current drift in seconds.

#
duration_secs

fn duration_secs(buf : AudioBuffer) -> Float

Duration of the buffer in seconds.

#
effect_process

fn effect_process(node : EffectNode, sample : Float) -> Float

Process one sample through an effect node.

#
effects_chain_process

fn effects_chain_process(effects : Array[EffectNode], sample : Float) -> Float

Process one sample through an entire effects chain.

#
enqueue

fn enqueue(queue : CommandQueue, cmd : AudioCommand, mixer : Mixer) -> VoiceId?

Enqueue a command. For PlaySource, returns the pre-allocated VoiceId.

#
envelope_release

fn envelope_release(env : Envelope) -> Unit

Trigger the release phase of the envelope.

#
envelope_reset

fn envelope_reset(env : Envelope) -> Unit

Reset the envelope to the beginning of the attack phase.

#
envelope_tick

fn envelope_tick(env : Envelope) -> Float

Advance envelope by one sample and return the current gain level.

#
find_voice

fn find_voice(mixer : Mixer, id : VoiceId) -> Voice?

Find a voice by its ID. Returns None if not found.

#
flush_commands

fn flush_commands(queue : CommandQueue, mixer : Mixer) -> Unit

Flush all commands to the mixer. Processes in FIFO order.

#
frame_count

fn frame_count(buf : AudioBuffer) -> Int

Number of frames in the buffer.

#
get_audio_backend_hooks

fn get_audio_backend_hooks() -> AudioBackendHooks

Get a reference to the current backend hooks.

#
get_sample

fn get_sample(buf : AudioBuffer, frame : Int, channel : Int) -> Float

Get sample value at (frame, channel). Interleaved layout.

#
highpass_coefficients

fn highpass_coefficients(cutoff_hz : Float, sample_rate : Int, q? : Float) -> BiquadState

Compute highpass biquad filter coefficients (RBJ Audio EQ Cookbook).

#
lowpass_coefficients

fn lowpass_coefficients(cutoff_hz : Float, sample_rate : Int, q? : Float) -> BiquadState

Compute lowpass biquad filter coefficients (RBJ Audio EQ Cookbook).

#
new_asset_cache

fn new_asset_cache(max_bytes : Int, max_entries : Int) -> AssetCache

Create a new asset cache with given limits.

#
new_audio_buffer

fn new_audio_buffer(channels : Int, sample_rate : Int, frames : Int) -> AudioBuffer

Create a new AudioBuffer with zeroed samples.

#
new_audio_runtime

fn new_audio_runtime(sample_rate : Int, tps : Int) -> AudioRuntime

Create a new audio runtime. sample_rate: output sample rate (e.g. 44100) tps: ticks per second (e.g. 60 for 60fps game loop)

#
new_command_queue

fn new_command_queue() -> CommandQueue

Create a new empty command queue.

#
new_delay

fn new_delay(delay_ms : Float, sample_rate : Int, feedback? : Float, mix? : Float) -> DelayState

Create a new delay effect.

#
new_envelope

fn new_envelope(config : EnvelopeConfig, sample_rate : Int) -> Envelope

Create a new ADSR envelope.

#
new_latency_monitor

fn new_latency_monitor() -> LatencyMonitor

Create a new latency monitor.

#
new_mixer

fn new_mixer(sample_rate : Int, resample_quality? : ResampleQuality) -> Mixer

Create a new stereo mixer at the given sample rate.

#
new_ring_buffer

fn new_ring_buffer(capacity : Int, channels : Int) -> RingBuffer

Create a new ring buffer with the given capacity in frames.

#
new_streaming_source

fn new_streaming_source(pull : PullCallback, channels : Int, sample_rate : Int, buffer_frames? : Int) -> StreamingSource

Create a new streaming audio source.

#
new_voice

fn new_voice(mixer : Mixer, source : AudioSource, gain? : Float, pan? : Float, looping? : Bool, envelope? : Envelope?) -> Voice

Create a new voice from an audio source.

#
new_voice_from_buffer

fn new_voice_from_buffer(mixer : Mixer, buffer : AudioBuffer, gain? : Float, pan? : Float, looping? : Bool, envelope? : Envelope?) -> Voice

Create a new voice from an AudioBuffer (convenience wrapper).

#
new_voice_with_loop

fn new_voice_with_loop(mixer : Mixer, source : AudioSource, loop_start : Int, loop_end : Int, gain? : Float, pan? : Float, looping? : Bool) -> Voice

Create a new voice with loop points from an audio source.

#
pan_gains

fn pan_gains(pan : Float) -> (Float, Float)

Compute constant-power pan gains for left and right channels. pan: -1.0 (full left) to 1.0 (full right), 0.0 = center.

#
pause_voice

fn pause_voice(mixer : Mixer, id : VoiceId) -> Bool

Pause a playing voice. Returns true if state changed.

#
play_sound

fn play_sound(rt : AudioRuntime, buffer : AudioBuffer, gain? : Float, pan? : Float, looping? : Bool) -> VoiceId

Play a sound buffer through the runtime. Returns voice ID.

#
queue_length

fn queue_length(queue : CommandQueue) -> Int

Number of pending commands.

#
read_source_sample

fn read_source_sample(source : AudioSource, frame : Int, channel : Int) -> Float

Read a sample from an audio source at the given frame and channel.

#
reset_audio_backend_hooks

fn reset_audio_backend_hooks() -> Unit

Reset hooks to no-op defaults.

#
reset_latency_monitor

fn reset_latency_monitor(monitor : LatencyMonitor) -> Unit

Reset all counters.

#
resume_voice

fn resume_voice(mixer : Mixer, id : VoiceId) -> Bool

Resume a paused voice. Returns true if state changed.

#
ring_available

fn ring_available(rb : RingBuffer) -> Int

Number of frames available for reading.

#
ring_consume

fn ring_consume(rb : RingBuffer, frames : Int) -> Unit

Consume (advance read_pos) the given number of frames.

#
ring_free

fn ring_free(rb : RingBuffer) -> Int

Number of frames of free space for writing.

#
ring_peek

fn ring_peek(rb : RingBuffer, frame_offset : Int, channel : Int) -> Float

Peek at a sample at the given frame offset from read_pos.

#
ring_reset

fn ring_reset(rb : RingBuffer) -> Unit

Reset the ring buffer to empty state.

#
ring_write

fn ring_write(rb : RingBuffer, src : FixedArray[Float], frames : Int) -> Int

Write frames into the ring buffer. Returns number of frames actually written.

#
seek_voice

fn seek_voice(mixer : Mixer, id : VoiceId, frame : Int) -> Bool

Seek a voice to a given frame position. Returns true if voice was found.

#
set_audio_backend_hooks

fn set_audio_backend_hooks(hooks : AudioBackendHooks) -> Unit

Set the audio backend hooks.

#
set_sample

fn set_sample(buf : AudioBuffer, frame : Int, channel : Int, value : Float) -> Unit

Set sample value at (frame, channel). Interleaved layout.

#
source_channels

fn source_channels(source : AudioSource) -> Int

Get the channel count of an audio source.

#
source_frame_count

fn source_frame_count(source : AudioSource) -> Int

Get the frame count of an audio source.

#
source_sample_rate

fn source_sample_rate(source : AudioSource) -> Int

Get the sample rate of an audio source.

#
stop_voice

fn stop_voice(mixer : Mixer, id : VoiceId) -> Bool

Stop a voice. Returns true if voice was found.

#
streaming_available

fn streaming_available(source : StreamingSource) -> Int

Number of frames available in the streaming source.

#
streaming_fill

fn streaming_fill(source : StreamingSource, min_frames : Int) -> Unit

Fill the streaming source's ring buffer until at least min_frames are available.

#
tick

fn tick(mixer : Mixer, frames : Int, output : FixedArray[Float]) -> Unit

Mix all playing voices into the output buffer for the given number of frames. Output is interleaved stereo (2 channels). Buffer must have length >= frames * 2.

#
underrun_count

fn underrun_count(monitor : LatencyMonitor) -> Int

Get underrun count.

#
update_latency

fn update_latency(monitor : LatencyMonitor, frames_this_tick : Int, consumed : Int) -> Unit

Update latency tracking after a tick. frames_this_tick: frames produced this tick. consumed: frames consumed by backend since last update.

#
voice_position

fn voice_position(mixer : Mixer, id : VoiceId) -> Float?

Get the current position of a voice in frames.

#
voice_state

fn voice_state(mixer : Mixer, id : VoiceId) -> VoiceState?

Get the current state of a voice.

Powered by MoonBit

Site sourceReport issuePackagesBuild queueSkillsStatistics

© 2026 mooncakes.io