Pure MoonBit audio toolkit: WAV/AIFF/AU/FLAC decoding, PCM conversion, resampling, FFT and spectrograms, with zero platform bindings.
let bytes = read_your_file() // 由宿主提供 Bytes(见「关于文件 IO」)
let audio = @moonaudio.decode(bytes) // 自动识别 WAV / AIFF / AU / FLAC
println(audio.sample_rate) // 44100
println(audio.frames()) // 采样帧数
println(audio.peak_dbfs()) // 峰值电平| 能力 | 说明 |
|---|---|
| 四个容器解码 | WAV、AIFF/AIFC、Sun .au、FLAC |
| 三个容器编码 | WAV、AIFF/AIFC、.au(FLAC 目前仅解码) |
| 采样格式 | u8 / s16 / s24 / s32 / f32 / f64 |
| DSP | 窗函数、基-2 FFT 与实 FFT、幅度谱、频谱图、biquad 滤波、统计、淡入淡出、混音、测试音、确定性白噪声 |
| 重采样 | 线性、Catmull-Rom 三次、窗函数 sinc(带抗混叠截止) |
| 依赖 | 仅 moonbitlang/core,无外部包 |
| 测试 | 138 个单元测试,覆盖正常路径与错误路径 |
| CI | Linux / macOS / Windows 三平台 check、test、fmt、接口一致性检查,另有真实 FLAC 文件的一致性任务 |
| 现有包 | 它们的定位 | moonaudio 的不同之处 |
|---|---|---|
| mizchi/audio、Milky2018/moon_rodio、moon_cpal | 浏览器 / C 音频库的绑定,负责播放与设备 IO | 纯 MoonBit、零绑定,只做「字节 ↔ 采样 ↔ 分析」的纯函数处理,可离线、可在 wasm-gc 里跑 |
| bw448/moon-wav、Ridge-Lab/moonwavkit、Xcsa-ee/moonflac 等 | 单一格式的最小解析器 | 四个容器 + 统一 AudioBuffer + 编码 + 重采样 + DSP + CLI,格式之间可以互相喂给同一条分析流水线 |
| 各家的 DSP / FFT 小包 | 单点算法 | 与容器解码共用同一套归一化采样与错误模型,analyse/spectrogram/Biquad 直接吃解码结果 |
# 安装 MoonBit 工具链(已安装可跳过)
curl -fsSL https://cli.moonbitlang.com/install/unix.sh | bash # macOS / Linux
# Windows: irm https://cli.moonbitlang.com/install/powershell.ps1 | iexmoon add Sakuraqwq1/moonaudiogit clone https://github.com/Sakuraqwq1/moonaudio
cd moonaudio
moon check
moon testlet audio = @moonaudio.decode(bytes)
println("\{audio.sample_rate} Hz, \{audio.channels} ch, \{audio.frames()} frames")
println("peak: \{audio.peak_dbfs()} dBFS, rms: \{audio.rms_dbfs()} dBFS")// 16-bit PCM WAV
let wav = @wav.encode(audio)
// 24-bit AIFF
let aiff = @aiff.encode(audio, format=@audio.I24)
// 32-bit float .au
let au = @au.encode(audio, format=@audio.F32)let loud = audio.copy()
loud.normalize(target=0.9) // 峰值归一到 0.9
let mono = loud.remix(1) // 立体声下混
let resampled = @resample.resample(mono, 48000)
let filtered = @dsp.Biquad::new(
@dsp.LowPass, 48000, 4000.0,
).apply_buffer(resampled)let stats = @dsp.analyse(audio)
println(stats.to_lines()) // key=value 列表,顺序稳定
let spec = @dsp.spectrogram(audio, fft_size=1024, hop=256)
println(spec.to_csv())
println(spec.to_svg()) // 直接可放进网页的灰度频谱图match @moonaudio.sniff(bytes) {
Some(container) => println(container.to_name()) // "wav" | "aiff" | "au" | "flac"
None => println("unrecognised")
}# 端到端自检:生成 → 编码 → 解码 → 分析 → 重采样,输出 Markdown 报告
moon run cmd/main -- demo
# 生成 440 Hz 正弦波 WAV(base64)
moon run cmd/main -- tone --freq 440 --ms 500 > tone.b64
# 小文件可以直接当参数传
moon run cmd/main -- info "$(cat tone.b64)"
moon run cmd/main -- stats "$(cat tone.b64)"
# 大一点的用环境变量,绕开命令行长度限制
export AUDIO_B64="$(cat tone.b64)"
moon run cmd/main -- convert @AUDIO_B64 --rate 48000 --format s24 --container aiff# moonaudio demo
- module version: `0.3.2`
- generated: 1.000 s of 440 Hz at 44.1 kHz, peak 0.800
- encoded: 88244 byte WAV, sniffed as wav
- header: 44100 Hz, 1 ch, 16 bit (s16), pcm, 44100 frames
- roundtrip: 44100 frames, peak -1.938 dBFS, rms -4.949 dBFS, crest 1.414
- AIFF 24-bit: 132354 bytes, decoded peak 0.800
- AU float64: 352824 bytes, decoded peak 0.800
- resampled 44.1 kHz -> 48 kHz: 48000 frames, peak 0.800
- FFT peak: 441.431 Hz for the 440 Hz tone (10.767 Hz per bin)
- spectrogram: 170 frames x 513 bins, bin width 43.066 Hz, frame 0 peak 430.664 Hz
- high pass 200 Hz: peak 0.824, rms 0.554moon run examples/basic # 20 行:生成正弦 → WAV 编码 → 门面解码 → 打印电平
moon run examples/tour # 分节导览:合成、分析、滤波、重采样、容器往返== synthesis ==
tone 440 Hz : 22050 frames, peak 0.4
mixed : peak 0.666, rms 0.354
deterministic: true
== analysis ==
fft peak at bin 128: 1000 Hz (input 1000 Hz)
spectrogram: 31 frames x 257 bins, 15.625 Hz per bin
frame 0 peak: 1000 Hz
== resampling ==
ratio 44100:48000 reduces to 147:160
expected frames: 4800
actual frames : 4800
== containers ==
wav: 4454 bytes — 22050 Hz, 1 ch, 16 bit (s16), pcm, 2205 frames
aiff: 6670 bytes — 22050 Hz, 1 ch, 24 bit (s24), AIFF NONE, 2205 frames| 包 | 职责 |
|---|---|
| Sakuraqwq1/moonaudio | 门面:sniff / decode / decode_detected / describe / version |
| src/audio | AudioBuffer、采样格式、量化、dBFS、G.711、字节读取器 |
| src/wav | RIFF/WAVE 解码与编码 |
| src/aiff | AIFF/AIFC 解码与编码 |
| src/au | Sun .au 解码与编码 |
| src/flac | FLAC 解码(位流、帧、子帧、Rice、CRC) |
| src/dsp | 窗函数、FFT、频谱、滤波器、统计 |
| src/resample | 采样率转换 |
moon check --deny-warn
moon test --deny-warn
moon fmt --check
moon info # 接口若有变化会更新 pkg.generated.mbti说明:仓库内的测试向量由合成器生成,不依赖外部数据,因此在离线 CI 中也能跑。 另外用官方 ietf-wg-cellar/flac-test-files 的真实文件做过交叉验证:解码后把采样重新编码成 16-bit PCM,重算 MD5 与 FLAC STREAMINFO 里记录的原 PCM 摘要比对,逐采样比特级一致。覆盖的文件有
官方文件 覆盖点 结果 60 - mono audio 单声道基准 一致 38 - 3 channels (3.0) 3 声道独立编码 一致 61 - predictor overflow check, 16-bit 故意让 32 位预测器溢出的极端信号 一致 64 - rice partitions with escape code zero Rice 分区与 escape 码 0 一致 14 - wasted bits wasted bits 与立体声去相关 一致 复现方式:git clone 上述测试集,取其中任一 16-bit 文件,用 @moonaudio.decode 解码后以 @wav.encode(..., format=@audio.I16) 写回 WAV,比对 data 块的 MD5 与 STREAMINFO 的 MD5。
pub(all) enum Container {
Wav
Aiff
Au
Flac
}fn version() -> StringInstall
Download zipPure MoonBit audio toolkit: WAV/AIFF/AU/FLAC decoding, PCM conversion, resampling, FFT and spectrograms, with zero platform bindings.