Skip to content

Commit 4f5dd27

Browse files
committed
refactor: address review comments
1 parent 4187282 commit 4f5dd27

File tree

8 files changed

+32
-265
lines changed

8 files changed

+32
-265
lines changed

src/decoder/builder.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
//! let file = File::open("audio.flac")?;
6363
//! let len = file.metadata()?.len();
6464
//!
65+
//! // High-quality decoder with precise seeking
6566
//! let decoder = Decoder::builder()
6667
//! .with_data(file)
6768
//! .with_byte_len(len)
@@ -73,8 +74,7 @@
7374
//! .with_gapless(false)
7475
//! .build()?;
7576
//!
76-
//! // High-quality decoder with precise seeking
77-
//! Ok(())
77+
//! Ok(())
7878
//! }
7979
//! ```
8080
//!

src/decoder/flac.rs

Lines changed: 0 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -107,11 +107,6 @@ const READER_OPTIONS: FlacReaderOptions = FlacReaderOptions {
107107
/// to minimize allocations during playback. Buffers are reused across blocks for
108108
/// optimal performance.
109109
///
110-
/// # Thread Safety
111-
///
112-
/// This decoder is not thread-safe. Create separate instances for concurrent access
113-
/// or use appropriate synchronization primitives.
114-
///
115110
/// # Generic Parameters
116111
///
117112
/// * `R` - The underlying data source type, must implement `Read + Seek`
@@ -526,20 +521,6 @@ where
526521
/// buffer of the current FLAC block. It returns samples one at a time while
527522
/// automatically decoding new blocks as needed.
528523
///
529-
/// # Sample Format Conversion
530-
///
531-
/// Raw FLAC samples are converted to Rodio's sample format based on bit depth:
532-
/// - 8-bit: Direct conversion from `i8`
533-
/// - 16-bit: Direct conversion from `i16`
534-
/// - 24-bit: Conversion using `I24` type
535-
/// - 32-bit: Direct conversion from `i32`
536-
/// - Other (12, 20-bit): Bit-shifted to 32-bit then converted
537-
///
538-
/// # Performance
539-
///
540-
/// - **Hot path**: Returning samples from current block (very fast)
541-
/// - **Cold path**: Decoding new blocks when buffer is exhausted (slower)
542-
///
543524
/// # Returns
544525
///
545526
/// - `Some(sample)` - Next audio sample
@@ -610,12 +591,6 @@ where
610591
/// This information can be used by consumers for buffer pre-allocation
611592
/// and progress indication.
612593
///
613-
/// # Returns
614-
///
615-
/// A tuple `(lower_bound, upper_bound)` where:
616-
/// - `lower_bound`: Minimum number of samples guaranteed to be available
617-
/// - `upper_bound`: Maximum number of samples that might be available (None if unknown)
618-
///
619594
/// # Accuracy
620595
///
621596
/// - **With metadata**: Exact remaining sample count (lower == upper)
@@ -646,54 +621,13 @@ where
646621
}
647622

648623
/// Probes input data to detect FLAC format.
649-
///
650-
/// This function attempts to parse the FLAC magic bytes and stream info header to determine if the
651-
/// data contains a valid FLAC stream. The stream position is restored regardless of the result.
652-
///
653-
/// # Arguments
654-
///
655-
/// * `data` - Mutable reference to the input stream to probe
656-
///
657-
/// # Returns
658-
///
659-
/// - `true` if the data appears to contain a valid FLAC stream
660-
/// - `false` if the data is not FLAC or is corrupted
661-
///
662-
/// # Implementation
663-
///
664-
/// Uses the common `utils::probe_format` helper which:
665-
/// 1. Saves the current stream position
666-
/// 2. Attempts FLAC detection using `claxon::FlacReader`
667-
/// 3. Restores the original stream position
668-
/// 4. Returns the detection result
669-
///
670-
/// # Performance
671-
///
672-
/// This function only reads the minimum amount of data needed to identify
673-
/// the FLAC format (magic bytes and basic header), making it efficient for
674-
/// format detection in multi-format scenarios.
675624
fn is_flac<R>(data: &mut R) -> bool
676625
where
677626
R: Read + Seek,
678627
{
679628
utils::probe_format(data, |reader| FlacReader::new(reader).is_ok())
680629
}
681630

682-
/// Converts claxon decoder errors to rodio seek errors.
683-
///
684-
/// This implementation provides error context preservation when FLAC decoding operations fail
685-
/// during seeking. The original `claxon` error is wrapped in an `Arc` for thread safety and
686-
/// converted to the appropriate Rodio error type.
687-
///
688-
/// # Error Mapping
689-
///
690-
/// All `claxon::Error` variants are mapped to `SeekError::ClaxonDecoder` with the
691-
/// original error preserved for debugging and error analysis.
692-
///
693-
/// # Thread Safety
694-
///
695-
/// The error is wrapped in `Arc` to allow sharing across thread boundaries if needed,
696-
/// following Rodio's error handling patterns.
697631
impl From<claxon::Error> for SeekError {
698632
/// Converts a claxon error into a Rodio seek error.
699633
///

src/decoder/mod.rs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -111,14 +111,10 @@ pub struct LoopedDecoder<R: Read + Seek> {
111111
inner: Option<DecoderImpl<R>>,
112112
/// Configuration settings for the decoder.
113113
settings: Settings,
114-
/// Cached metadata from the first successful decoder creation.
115114
/// Used to avoid expensive file scanning on subsequent loops.
116115
cached_duration: Option<Duration>,
117116
}
118117

119-
// Cannot really reduce the size of the VorbisDecoder. There are not any
120-
/// Internal enum representing different decoder implementations.
121-
///
122118
/// This enum dispatches to the appropriate decoder based on detected format
123119
/// and available features. Large enum variant size is acceptable here since
124120
/// these are infrequently created and moved.
@@ -145,7 +141,6 @@ enum DecoderImpl<R: Read + Seek> {
145141
None(Unreachable, PhantomData<R>),
146142
}
147143

148-
/// Placeholder type for the None variant that can never be instantiated.
149144
enum Unreachable {}
150145

151146
impl<R: Read + Seek> DecoderImpl<R> {

src/decoder/mp3.rs

Lines changed: 3 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -98,22 +98,15 @@ use crate::{
9898
/// MP3 frames can theoretically change channel configuration, though this is
9999
/// rare in practice. The decoder handles such changes dynamically.
100100
///
101-
/// # Thread Safety
102-
///
103-
/// This decoder is not thread-safe. Create separate instances for concurrent access
104-
/// or use appropriate synchronization primitives.
105-
///
106101
/// # Generic Parameters
107102
///
108103
/// * `R` - The underlying data source type, must implement `Read + Seek`
109104
pub struct Mp3Decoder<R>
110105
where
111106
R: Read + Seek,
112107
{
113-
/// The underlying minimp3 decoder, wrapped in Option for seeking operations.
114-
///
115-
/// Temporarily set to `None` during stream reset operations for seeking.
116-
/// Always `Some` during normal operation and iteration.
108+
/// The underlying minimp3 decoder, wrapped in Option to allow owning the
109+
/// Decoder instance during seeking.
117110
decoder: Option<Decoder<R>>,
118111

119112
/// Byte position where audio data begins (after headers/metadata).
@@ -142,8 +135,7 @@ where
142135

143136
/// Sample rate in Hz.
144137
///
145-
/// Fixed for the entire MP3 stream. Common rates include 44.1kHz (CD quality),
146-
/// 48kHz (professional), and various rates for different MPEG versions.
138+
/// Does not change after decoder initialization.
147139
sample_rate: SampleRate,
148140

149141
/// Number of samples read so far (for seeking calculations).
@@ -740,12 +732,6 @@ where
740732
/// Provides size estimates based on MP3 metadata and current playback position.
741733
/// The accuracy depends on the availability and reliability of duration information.
742734
///
743-
/// # Returns
744-
///
745-
/// A tuple `(lower_bound, upper_bound)` where:
746-
/// - `lower_bound`: Minimum number of samples guaranteed to be available
747-
/// - `upper_bound`: Maximum number of samples that might be available (None if unknown)
748-
///
749735
/// # Accuracy Levels
750736
///
751737
/// - **High accuracy**: When total samples calculated from scanned duration
@@ -841,39 +827,6 @@ fn get_mp3_duration<R: Read + Seek>(data: &mut R) -> Option<Duration> {
841827
}
842828

843829
/// Probes input data to detect MP3 format.
844-
///
845-
/// This function attempts to decode the first MP3 frame to determine if the
846-
/// data contains a valid MP3 stream. The stream position is restored regardless
847-
/// of the result, making it safe to use for format detection.
848-
///
849-
/// # Arguments
850-
///
851-
/// * `data` - Mutable reference to the input stream to probe
852-
///
853-
/// # Returns
854-
///
855-
/// - `true` if the data appears to contain a valid MP3 stream
856-
/// - `false` if the data is not MP3 or is corrupted
857-
///
858-
/// # Implementation
859-
///
860-
/// Uses the common `utils::probe_format` helper which:
861-
/// 1. Saves the current stream position
862-
/// 2. Attempts MP3 detection using `minimp3::Decoder`
863-
/// 3. Restores the original stream position
864-
/// 4. Returns the detection result
865-
///
866-
/// # Performance
867-
///
868-
/// This function only reads the minimum amount of data needed to identify
869-
/// and decode the first MP3 frame, making it efficient for format detection
870-
/// in multi-format scenarios.
871-
///
872-
/// # Robustness
873-
///
874-
/// The detection uses actual frame decoding rather than just header checking,
875-
/// providing more reliable format identification at the cost of slightly
876-
/// higher computational overhead.
877830
fn is_mp3<R>(data: &mut R) -> bool
878831
where
879832
R: Read + Seek,

src/decoder/read_seek_source.rs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,6 @@ use crate::decoder::builder::Settings;
5252
/// - **Byte length**: Total stream size for seeking and progress calculations
5353
/// - **Configuration**: Stream properties from decoder builder settings
5454
///
55-
/// # Thread Safety
56-
///
57-
/// This wrapper requires `Send + Sync` bounds on the wrapped type to ensure
58-
/// thread safety for Symphonia's internal operations. Most standard I/O types
59-
/// satisfy these requirements.
60-
///
6155
/// # Generic Parameters
6256
///
6357
/// * `T` - The wrapped I/O type, must implement `Read + Seek + Send + Sync`

src/decoder/symphonia.rs

Lines changed: 27 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -135,11 +135,6 @@ use crate::{decoder::builder::Settings, BitDepth};
135135
/// - **Reset required**: Recreate decoder and continue with next track
136136
/// - **I/O errors**: Attempt to continue when possible
137137
/// - **Terminal errors**: Clean shutdown when recovery is impossible
138-
///
139-
/// # Thread Safety
140-
///
141-
/// This decoder is not thread-safe. Create separate instances for concurrent access
142-
/// or use appropriate synchronization primitives.
143138
pub struct SymphoniaDecoder {
144139
/// The underlying Symphonia audio decoder.
145140
///
@@ -1054,12 +1049,6 @@ impl Iterator for SymphoniaDecoder {
10541049
///
10551050
/// For multi-track files, estimates represent the currently selected audio
10561051
/// track, not the entire file duration or all tracks combined.
1057-
///
1058-
/// # Returns
1059-
///
1060-
/// A tuple `(lower_bound, upper_bound)` where:
1061-
/// - `lower_bound`: Minimum number of samples guaranteed to be available
1062-
/// - `upper_bound`: Maximum number of samples that might be available (None if unknown)
10631052
fn size_hint(&self) -> (usize, Option<usize>) {
10641053
// Samples already decoded and buffered (guaranteed available)
10651054
let buffered_samples = self
@@ -1189,36 +1178,34 @@ fn should_continue_on_decode_error(
11891178
}
11901179
}
11911180

1181+
/// Converts Rodio's SeekMode to Symphonia's SeekMode.
1182+
///
1183+
/// This conversion maps Rodio's seeking preferences to Symphonia's
1184+
/// internal seeking modes, enabling consistent seeking behavior
1185+
/// across different audio processing layers.
1186+
///
1187+
/// # Mapping
1188+
///
1189+
/// - `SeekMode::Fastest` → `SymphoniaSeekMode::Coarse`
1190+
/// - Prioritizes speed over precision
1191+
/// - Uses keyframe-based seeking when available
1192+
/// - Suitable for user scrubbing and fast navigation
1193+
/// - `SeekMode::Nearest` → `SymphoniaSeekMode::Accurate`
1194+
/// - Prioritizes precision over speed
1195+
/// - Attempts sample-accurate positioning
1196+
/// - Suitable for gapless playback and precise positioning
1197+
///
1198+
/// # Performance Implications
1199+
///
1200+
/// The choice between modes affects performance significantly:
1201+
/// - **Coarse**: Fast seeks but may require fine-tuning
1202+
/// - **Accurate**: Slower seeks but precise positioning
1203+
///
1204+
/// # Format Compatibility
1205+
///
1206+
/// Not all formats support both modes equally. Automatic
1207+
/// fallbacks may occur when preferred mode unavailable.
11921208
impl From<SeekMode> for SymphoniaSeekMode {
1193-
/// Converts Rodio's SeekMode to Symphonia's SeekMode.
1194-
///
1195-
/// This conversion maps Rodio's seeking preferences to Symphonia's
1196-
/// internal seeking modes, enabling consistent seeking behavior
1197-
/// across different audio processing layers.
1198-
///
1199-
/// # Mapping
1200-
///
1201-
/// - `SeekMode::Fastest` → `SymphoniaSeekMode::Coarse`
1202-
/// - Prioritizes speed over precision
1203-
/// - Uses keyframe-based seeking when available
1204-
/// - Suitable for user scrubbing and fast navigation
1205-
/// - `SeekMode::Nearest` → `SymphoniaSeekMode::Accurate`
1206-
/// - Prioritizes precision over speed
1207-
/// - Attempts sample-accurate positioning
1208-
/// - Suitable for gapless playback and precise positioning
1209-
///
1210-
/// # Performance Implications
1211-
///
1212-
/// The choice between modes affects performance significantly:
1213-
/// - **Coarse**: Fast seeks but may require fine-tuning
1214-
/// - **Accurate**: Slower seeks but precise positioning
1215-
///
1216-
/// # Format Compatibility
1217-
///
1218-
/// Not all formats support both modes equally:
1219-
/// - Some formats only implement one mode effectively
1220-
/// - Automatic fallbacks may occur when preferred mode unavailable
1221-
/// - Mode availability may depend on stream characteristics
12221209
fn from(mode: SeekMode) -> Self {
12231210
match mode {
12241211
SeekMode::Fastest => SymphoniaSeekMode::Coarse,

src/decoder/vorbis.rs

Lines changed: 0 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -105,11 +105,6 @@ use crate::{
105105
/// Ogg supports chained streams where multiple Vorbis streams are concatenated.
106106
/// The decoder adapts to parameter changes (sample rate, channels) between streams.
107107
///
108-
/// # Thread Safety
109-
///
110-
/// This decoder is not thread-safe. Create separate instances for concurrent access
111-
/// or use appropriate synchronization primitives.
112-
///
113108
/// # Generic Parameters
114109
///
115110
/// * `R` - The underlying data source type, must implement `Read + Seek`
@@ -725,12 +720,6 @@ where
725720
/// playback position. The accuracy depends on the availability of duration information
726721
/// from granule position scanning or explicit duration settings.
727722
///
728-
/// # Returns
729-
///
730-
/// A tuple `(lower_bound, upper_bound)` where:
731-
/// - `lower_bound`: Minimum number of samples guaranteed to be available
732-
/// - `upper_bound`: Maximum number of samples that might be available (None if unknown)
733-
///
734723
/// # Accuracy Levels
735724
///
736725
/// - **High accuracy**: When total samples calculated from granule scanning
@@ -995,39 +984,6 @@ fn granules_to_duration(granules: u64, sample_rate: SampleRate) -> Duration {
995984
}
996985

997986
/// Probes input data to detect Ogg Vorbis format.
998-
///
999-
/// This function attempts to initialize a lewton OggStreamReader to determine if the
1000-
/// data contains a valid Ogg Vorbis stream. The stream position is restored regardless
1001-
/// of the result, making it safe to use for format detection.
1002-
///
1003-
/// # Arguments
1004-
///
1005-
/// * `data` - Mutable reference to the input stream to probe
1006-
///
1007-
/// # Returns
1008-
///
1009-
/// - `true` if the data appears to contain a valid Ogg Vorbis stream
1010-
/// - `false` if the data is not Ogg Vorbis or is corrupted
1011-
///
1012-
/// # Implementation
1013-
///
1014-
/// Uses the common `utils::probe_format` helper which:
1015-
/// 1. Saves the current stream position
1016-
/// 2. Attempts Ogg Vorbis detection using `lewton::OggStreamReader`
1017-
/// 3. Restores the original stream position
1018-
/// 4. Returns the detection result
1019-
///
1020-
/// # Performance
1021-
///
1022-
/// This function reads the minimum amount of data needed to identify the Ogg
1023-
/// container format and Vorbis codec headers, making it efficient for format
1024-
/// detection in multi-format scenarios.
1025-
///
1026-
/// # Robustness
1027-
///
1028-
/// The detection uses actual stream reader initialization rather than just header
1029-
/// checking, providing reliable format identification with proper Ogg/Vorbis
1030-
/// validation at the cost of slightly higher computational overhead.
1031987
fn is_vorbis<R>(data: &mut R) -> bool
1032988
where
1033989
R: Read + Seek,

0 commit comments

Comments
 (0)