Files
craft-libs/crates/audio/examples/encode.rs
T
alehel eee76c3fc2 craft-audio: AAC, ALAC, MP3, AC-3 and E-AC-3 as formats of encode and FileEncoder
EncodeFormat gains Aac and Alac (M4A through craft-media's MP4 muxer) and
Mp3, Ac3 and Eac3 (raw streams), so one call writes any of them from
WAV-order f32 audio and EncodeOptions.

- EncodeOptions::rate_control (with_bitrate, with_quality): a bit rate is
  moved to the nearest one the stream can carry; quality is AAC's VBR.
- Channels are mapped onto the codec's order by speaker, from
  EncodeOptions::layout. A layout the format has not is Unsupported
  instead of reaching the wrong speakers.
- M4A: the edit list skips the AAC priming, and the last sample's duration
  is cut so the track ends at the last frame written.
- encode_format_for, ENCODE_EXTENSIONS and EncodeFormat::ALL list the new
  formats; aac-encode and alac-encode now turn on craft-media's isobmff.

Refs #1230
2026-11-14 03:16:51 +01:00

42 lines
2.2 KiB
Rust

//! Write a tone as WAV, FLAC and AAC in M4A, whole and streamed, and as AAC packets.
//!
//! `cargo run -p craft-audio --example encode --features lossless-encode,aac-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 bytes `encode` would give, 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()?;
// AAC in M4A at 160 kbit/s: the same call, with a bit rate in place of a bit depth.
let m4a = encode(&stereo, &EncodeOptions::new(EncodeFormat::Aac).with_bitrate(160_000))?;
std::fs::write(dir.join("tone.m4a"), m4a)?;
// AAC packets for a muxer of your own, with the configuration its sample entry needs.
let mut aac = craft_audio::aac::Encoder::new(craft_audio::aac::EncoderConfig::cbr(rate as u32, 2, 128_000))?;
let mut units = aac.encode(&[&tone, &tone]);
units.extend(aac.flush());
println!("{} AAC access units, AudioSpecificConfig {:02x?}, priming {}", units.len(), aac.audio_specific_config(), aac.priming_samples());
Ok(())
}