MoonBit 原生 WAV 音频解码库 | A native MoonBit WAV audio decoding library
moon add bw448/moon-wavfn main {
// Generate a 440Hz sine wave
let audio = generate_sine_wav(440.0, 16000.0, 44100, 1.0, 16)
// Encode to WAV format
let wav_bytes = encode(audio)
println("Generated " + wav_bytes.length().to_string() + " bytes")
// Decode and analyze
match decode(wav_bytes) {
Ok(decoded) => {
let analysis = analyze(decoded, 100)
println("Peak: " + analysis.peak.to_string())
println("RMS: " + analysis.rms.to_string())
}
Err(_) => println("Decode failed")
}
}pub struct WavInfo {
audio_format : Int // 1 = PCM, 3 = IEEE float
num_channels : Int // 1 = mono, 2 = stereo
sample_rate : Int // Sample rate in Hz (e.g., 44100)
byte_rate : Int // Byte rate
block_align : Int // Block align
bits_per_sample : Int // 8, 16, 24, or 32
data_size : Int // Data size in bytes
}pub struct AudioData {
samples : Array[Int] // Decoded samples (32-bit signed integers)
info : WavInfo // Format information
}pub enum WavError {
InvalidHeader
UnsupportedFormat
CorruptedData
InvalidChunk
}pub struct ValidationResult {
is_valid : Bool
warnings : Array[String]
error : String?
}pub struct AudioAnalysis {
duration_sec : Double
samples_per_channel : Int
peak : Int
rms : Double
dc_offset : Double
zero_crossings : Int
has_clipping : Bool
clipped_samples : Int
is_silent : Bool
silence_ratio : Double
}| Function | Description |
|---|---|
| decode(data : Bytes) -> Result[AudioData, WavError] | Decode a WAV file (PCM & IEEE float) |
| get_info(data : Bytes) -> Result[WavInfo, WavError] | Get WAV info without decoding |
| Function | Description |
|---|---|
| encode(audio : AudioData) -> Bytes | Encode audio data to WAV format |
| encode_with_format(samples, num_channels, sample_rate, bits_per_sample) -> Bytes | Encode with specified format |
| Function | Description |
|---|---|
| validate(data : Bytes) -> ValidationResult | Validate WAV file structure |
| Function | Description |
|---|---|
| convert_bit_depth(samples, from_bits, to_bits) -> Result[Array[Int], WavError] | Convert bit depth |
| convert_channels(samples, from_channels, to_channels) -> Result[Array[Int], WavError] | Convert channels |
| resample(samples, from_rate, to_rate, num_channels) -> Array[Int] | Resample audio |
| Function | Description |
|---|---|
| trim(samples, start, end) -> Array[Int] | Trim audio |
| concat(a, b) -> Array[Int] | Concatenate audio |
| adjust_volume(samples, factor) -> Array[Int] | Adjust volume |
| mix(a, b) -> Array[Int] | Mix two streams |
| fade_in(samples, fade_samples) -> Array[Int] | Fade in |
| fade_out(samples, fade_samples) -> Array[Int] | Fade out |
| reverse(samples) -> Array[Int] | Reverse audio |
| get_peak_amplitude(samples) -> Int | Get peak amplitude |
| get_rms_level(samples) -> Double | Get RMS level |
| Function | Description |
|---|---|
| echo(samples, delay_samples, decay) -> Array[Int] | Echo effect |
| delay(samples, delay_samples, mix) -> Array[Int] | Delay effect |
| normalize(samples, target_peak) -> Array[Int] | Normalize to target peak |
| soft_clip(samples, threshold) -> Array[Int] | Soft clipping |
| remove_dc_offset(samples) -> Array[Int] | Remove DC offset |
| low_pass_filter(samples, window_size) -> Array[Int] | Low-pass filter |
| high_pass_filter(samples, window_size) -> Array[Int] | High-pass filter |
| reverse_reverb(samples, fade_samples) -> Array[Int] | Reverse reverb |
| Function | Description |
|---|---|
| generate_sine(freq, amp, rate, duration) -> Array[Int] | Sine wave |
| generate_square(freq, amp, rate, duration) -> Array[Int] | Square wave |
| generate_sawtooth(freq, amp, rate, duration) -> Array[Int] | Sawtooth wave |
| generate_triangle(freq, amp, rate, duration) -> Array[Int] | Triangle wave |
| generate_noise(amp, rate, duration, seed) -> Array[Int] | White noise |
| generate_chirp(start_freq, end_freq, amp, rate, duration) -> Array[Int] | Frequency sweep |
| generate_silence(rate, duration) -> Array[Int] | Silence |
| generate_sine_wav(freq, amp, rate, duration, bits) -> AudioData | Sine as AudioData |
| Function | Description |
|---|---|
| analyze(audio, silence_threshold) -> AudioAnalysis | Full analysis |
| calculate_dc_offset(samples) -> Double | DC offset |
| count_zero_crossings(samples) -> Int | Zero crossings |
| count_clipped_samples(samples, min, max) -> Int | Clipped samples |
| count_silent_samples(samples, threshold) -> Int | Silent samples |
| format_analysis(analysis) -> String | Format analysis as string |
| Function | Description |
|---|---|
| format_wav_info(info) -> String | Format WAV info as string |
| split_stereo(samples) -> (Array[Int], Array[Int]) | Split stereo to L/R |
| combine_stereo(left, right) -> Array[Int] | Combine L/R to stereo |
| get_duration(audio) -> Double | Get duration in seconds |
| get_frame_count(audio) -> Int | Get frame count |
| extract_channel(samples, num_channels, channel) -> Array[Int] | Extract one channel |
| mix_multiple(streams) -> Array[Int] | Mix multiple streams |
| repeat(samples, times) -> Array[Int] | Repeat audio |
| pad_to_length(samples, target_length) -> Array[Int] | Pad with silence |
| cross_correlation_zero_lag(a, b) -> Double | Cross-correlation |
| Format | Decode | Encode |
|---|---|---|
| PCM 8-bit unsigned | ✅ | ✅ |
| PCM 16-bit signed LE | ✅ | ✅ |
| PCM 24-bit signed LE | ✅ | ✅ |
| PCM 32-bit signed LE | ✅ | ✅ |
| IEEE 754 32-bit float | ✅ | ❌ |
| ADPCM, A-law, μ-law | ❌ | ❌ |
| Compressed formats | ❌ | ❌ |
| Channels | Support |
|---|---|
| Mono (1ch) | ✅ Full |
| Stereo (2ch) | ✅ Full |
| Multi-channel (3+) | ⚠️ Partial (decode only) |
let audio = generate_sine_wav(440.0, 16000.0, 44100, 1.0, 16)
let wav_bytes = encode(audio)
println("WAV file: " + wav_bytes.length().to_string() + " bytes")let result = validate(wav_data)
if result.is_valid {
println("Valid WAV file")
} else {
println("Invalid: " + result.error.to_string())
}match decode(wav_data) {
Ok(audio) => {
let analysis = analyze(audio, 100)
println("Duration: " + analysis.duration_sec.to_string() + "s")
println("Peak: " + analysis.peak.to_string())
println("Clipping: " + analysis.has_clipping.to_string())
}
Err(_) => ()
}let audio = generate_sine_wav(440.0, 16000.0, 44100, 1.0, 16)
let processed = fade_in(audio.samples, 4410) // 100ms fade in
let processed = fade_out(processed, 4410) // 100ms fade out
let processed = normalize(processed, 32000) // Normalize
let encoded = encode({ samples: processed, info: audio.info })# Build the library
moon build
# Run tests
moon test
# Run the example
moon run cmd/mainpub struct AudioAnalysis {
duration_sec : Double
samples_per_channel : Int
peak : Int
rms : Double
dc_offset : Double
zero_crossings : Int
has_clipping : Bool
clipped_samples : Int
is_silent : Bool
silence_ratio : Double
} derive(Debug)pub struct WavInfo {
audio_format : Int
num_channels : Int
sample_rate : Int
byte_rate : Int
block_align : Int
bits_per_sample : Int
data_size : Int
} derive(Debug)fn encode_with_format(samples : Array[Int], num_channels : Int, sample_rate : Int, bits_per_sample : Int) -> Bytesfn generate_chirp(start_freq : Double, end_freq : Double, amplitude : Double, sample_rate : Int, duration_sec : Double) -> Array[Int]fn generate_noise(amplitude : Double, sample_rate : Int, duration_sec : Double, seed : Int) -> Array[Int]fn generate_sawtooth(frequency : Double, amplitude : Double, sample_rate : Int, duration_sec : Double) -> Array[Int]fn generate_sine(frequency : Double, amplitude : Double, sample_rate : Int, duration_sec : Double) -> Array[Int]fn generate_sine_wav(frequency : Double, amplitude : Double, sample_rate : Int, duration_sec : Double, bits_per_sample : Int) -> AudioDatafn generate_square(frequency : Double, amplitude : Double, sample_rate : Int, duration_sec : Double) -> Array[Int]fn generate_triangle(frequency : Double, amplitude : Double, sample_rate : Int, duration_sec : Double) -> Array[Int]fn make_wav_info(audio_format : Int, num_channels : Int, sample_rate : Int, byte_rate : Int, block_align : Int, bits_per_sample : Int, data_size : Int) -> WavInfoInstall
Download zipMoonBit 原生 WAV 音频解码库 | A native MoonBit WAV audio decoding library