Audio Decoding (Symphonia)
Relevant source files
The following files were used as context for generating this wiki page:
The Audio Decoding system provides the core infrastructure for transforming raw audio files into normalized PCM data. It utilizes the Symphonia library to support multiple formats, including MP3, WAV, FLAC, AIFF, and M4A. This system serves as the foundation for subsequent analysis tasks such as BPM detection, key estimation, and phrase segmentation.
Sources: crates/analysis/src/decoder.rs:1-6, README.md:280-285
Architecture and Data Flow
The decoding pipeline follows a structured path from file discovery to normalized output. The dj-assistant-analysis crate manages this process, separating the high-level decoding logic from low-level container-specific duration parsers found in dj-assistant-core.
The diagram shows the sequential steps taken to transform a file on disk into a normalized DecodedAudio structure.
Sources: crates/analysis/src/decoder.rs:64-155
Key Components
| Component | Responsibility |
|---|---|
DecodedAudio | Stores interleaved f32 samples, sample rate, channel count, and duration. |
decode_audio_file | Primary entry point for decoding a file from a path. |
symphonia | External library providing codec backends and format probing. |
| Container Parsers | High-speed, non-decoding parsers for MP3, RIFF, and AIFF durations. |
Sources: crates/analysis/src/decoder.rs:19-30, crates/analysis/Cargo.toml:10-10
Supported Formats
The system implements broad format support through a combination of Symphonia features and custom fallback parsers for metadata consistency.
- MP3: Uses
symphoniawith anisomp4feature. Custom duration parsing handles Xing, VBRI, or CBR estimates. - WAV/RIFF: Parsed for duration via
fmtanddatachunks. - FLAC: Supported natively via the
flacfeature. - AIFF: Supported via the
aifffeature; duration is read fromnumSampleFramesin theCOMMchunk. - M4A/AAC: Handled via
isomp4andaacfeatures.
Sources: crates/analysis/Cargo.toml:10-10, crates/core/src/mp3.rs:1-10, crates/core/src/riff.rs:1-15
Decoded Data Management
Decoding results in a DecodedAudio structure that holds 32-bit floating point PCM audio. Samples are interleaved and normalized to the range [-1.0, 1.0].
Normalization and Layouts
The DecodedAudio struct provides methods to manipulate the audio layout for different analysis requirements:
- Interleaved: Standard format where samples from different channels alternate.
- Mono Conversion: The
to_mono()method averages multiple channels into a single buffer. - Planar Layout: The
channel_planar()method separates interleaved samples into individual vectors per channel.
// crates/analysis/src/decoder.rs:38-51
pub fn to_mono(&self) -> Vec<f32> {
if self.channels <= 1 {
return self.samples.clone();
}
let num_frames = self.total_frames();
let mut mono = Vec::with_capacity(num_frames);
let ch_f32 = self.channels as f32;
for frame in self.samples.chunks_exact(self.channels) {
let sum: f32 = frame.iter().sum();
mono.push(sum / ch_f32);
}
mono
}
Sources: crates/analysis/src/decoder.rs:19-58
Robust Error Handling
The decoder is designed to be forgiving of malformed files to prevent a single corrupt track from failing a library-wide scan.
- Probe Failure: If Symphonia cannot recognize the format, it returns an
UnrecognizedFormaterror. - Corrupt Packets: The decoding loop gracefully skips individual corrupt packets within a valid stream.
- Metadata Fallback: If tags are unparseable, the system uses the filename stem as the title and "Unknown Artist" for the artist.
- Duration Fallbacks: When containers (like WAV) do not report duration via
audiotags, the system falls back to container-specific header parsing.
Sources: crates/analysis/src/decoder.rs:125-148, crates/core/src/metadata.rs:8-13, crates/core/src/metadata.rs:145-155
Duration Parsing Implementation
For efficiency, the system includes dedicated parsers that calculate duration without decoding the full audio stream.
WAV (RIFF) Duration
Duration is calculated by dividing the data chunk size by the byte_rate found in the fmt chunk.
Sources: crates/core/src/riff.rs:1-15
MP3 Duration
The system attempts to find the Xing or Info header for an exact frame count. If absent, it checks for a VBRI header. If both are missing, it estimates duration based on the file size and a CBR bitrate derived from the first MPEG frame.
Sources: crates/core/src/mp3.rs:55-80
AIFF Duration
The parser reads the COMM chunk to extract numSampleFrames and the 80-bit extended sampleRate.
Sources: crates/core/src/aiff.rs:1-10
Conclusion
The Audio Decoding system serves as a resilient gateway for the DJ Assistant's analysis pipeline. By combining the Symphonia library with custom, high-speed header parsers, it ensures that diverse audio formats are reliably converted into standardized PCM data while maintaining metadata integrity even in the presence of malformed files.