The decode loop is the heart of audio decoding. It continuously fetches packets and decodes them.
1
Set up the decoder
First, create a decoder for your selected track:
use symphonia::core::codecs::{CODEC_TYPE_NULL, DecoderOptions};// Find the first audio tracklet track = format.tracks() .iter() .find(|t| t.codec_params.codec != CODEC_TYPE_NULL) .expect("no supported audio tracks");// Create a decoder for the tracklet dec_opts: DecoderOptions = Default::default();let mut decoder = symphonia::default::get_codecs() .make(&track.codec_params, &dec_opts) .expect("unsupported codec");let track_id = track.id;
2
Implement the decode loop
Loop through packets and decode them:
use symphonia::core::errors::Error;loop { // Get the next packet from the format reader let packet = match format.next_packet() { Ok(packet) => packet, Err(Error::ResetRequired) => { // Track list changed - recreate decoders unimplemented!(); } Err(err) => { // Handle or propagate error break; } }; // Filter packets by track ID if packet.track_id() != track_id { continue; } // Decode the packet match decoder.decode(&packet) { Ok(decoded) => { // Process decoded audio } Err(Error::IoError(_)) => { // Skip packet with IO error continue; } Err(Error::DecodeError(_)) => { // Skip packet with decode error continue; } Err(err) => { // Unrecoverable error panic!("{}" err); } }}
3
Process metadata updates
Check for metadata updates during decoding:
// Consume any new metadatawhile !format.metadata().is_latest() { format.metadata().pop(); // Access new metadata if needed if let Some(rev) = format.metadata().current() { // Process metadata revision }}
use symphonia::core::audio::{AudioBufferRef, Signal};let decoded = decoder.decode(&packet)?;match decoded { AudioBufferRef::F32(buf) => { // Iterate over samples in the first channel for &sample in buf.chan(0) { // Process sample } } AudioBufferRef::S16(buf) => { // Handle 16-bit integer samples for &sample in buf.chan(0) { // Process sample } } _ => { // Handle other sample formats }}
use symphonia::core::audio::{AudioBufferRef, Signal};match decoded { AudioBufferRef::F32(buf) => { let planes = buf.planes(); // Iterate over each channel for plane in planes.planes() { for &sample in plane.iter() { // Process sample from this channel } } } _ => { /* Handle other formats */ }}
use symphonia::core::audio::RawSampleBuffer;let mut byte_buf = None;loop { let packet = format.next_packet()?; if packet.track_id() != track_id { continue; } match decoder.decode(&packet) { Ok(decoded) => { if byte_buf.is_none() { let spec = *decoded.spec(); let duration = decoded.capacity() as u64; byte_buf = Some(RawSampleBuffer::<f32>::new(duration, spec)); } if let Some(buf) = &mut byte_buf { buf.copy_interleaved_ref(decoded); // Get raw bytes let bytes: &[u8] = buf.as_bytes(); // Write to file, send to audio device, etc. } } Err(Error::DecodeError(_)) => continue, Err(_) => break, }}