mirror of
https://github.com/storytold/craft-libs.git
synced 2026-11-08 19:42:12 +00:00
FilmCraft's FLAC encoder behind `flac-encode`, kept over SoundCraft's: linear prediction, stereo decorrelation and the STREAMINFO MD5 give 0.1-37% smaller files on 12 test signals, and the output is bit-exact through `flac` and ffmpeg. It is 3-5x slower than SoundCraft's, still about 56x real time. `lossless-encode` is now `pcm-encode` plus `flac-encode`, and `EncodeFormat::Flac` writes it through `encode` and `FileEncoder`. With only one of the two features, the other's formats are refused as `Unsupported`. The tests that use FLAC files as decode fixtures (truncation, corruption, metadata bounds, zero-frame files, container preflight) come with it, as do the FLAC oracle tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
32 lines
1.5 KiB
Rust
32 lines
1.5 KiB
Rust
//! Write a tone as WAV and FLAC, whole and streamed.
|
|
//!
|
|
//! `cargo run -p craft-audio --example encode --features lossless-encode -- out`
|
|
|
|
use craft_audio::{AudioBuffer, BitDepth, ChannelLayout, EncodeFormat, EncodeOptions, FileEncoder, encode};
|
|
|
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
let dir = std::path::PathBuf::from(std::env::args().nth(1).unwrap_or_else(|| ".".into()));
|
|
std::fs::create_dir_all(&dir)?;
|
|
let rate = 48_000;
|
|
let tone: Vec<f32> = (0..rate).map(|i| (i as f32 * 440.0 * std::f32::consts::TAU / rate as f32).sin() * 0.5).collect();
|
|
let stereo = AudioBuffer { sample_rate: rate as u32, channels: vec![tone.clone(), tone.clone()] };
|
|
|
|
// A whole buffer at once.
|
|
let wav = encode(&stereo, &EncodeOptions::new(EncodeFormat::Wav).with_bit_depth(BitDepth::Int24).with_dither(true))?;
|
|
std::fs::write(dir.join("tone.wav"), wav)?;
|
|
|
|
// A 5.1 file whose layout a channel count alone cannot name (side surrounds).
|
|
let surround = AudioBuffer { sample_rate: rate as u32, channels: vec![tone.clone(); 6] };
|
|
let wav = encode(&surround, &EncodeOptions::default().with_layout(ChannelLayout::SURROUND_5_1_SIDE))?;
|
|
std::fs::write(dir.join("tone-5.1.wav"), wav)?;
|
|
|
|
// Streamed: the same bytes, block by block into a file.
|
|
let opts = EncodeOptions::new(EncodeFormat::Flac);
|
|
let mut enc = FileEncoder::new(std::fs::File::create(dir.join("tone.flac"))?, &opts, rate as u32, 2)?;
|
|
for chunk in tone.chunks(4096) {
|
|
enc.write(&[chunk, chunk], chunk.len())?;
|
|
}
|
|
enc.finish()?;
|
|
Ok(())
|
|
}
|