pub trait Decoder {
// Required method
fn decode(path: &Path) -> BlissResult<PreAnalyzedSong>;
// Provided methods
fn song_from_path<P: AsRef<Path>>(path: P) -> BlissResult<Song> { ... }
fn song_from_path_with_options<P: AsRef<Path>>(
path: P,
analysis_options: AnalysisOptions,
) -> BlissResult<Song> { ... }
fn analyze_paths<P: Into<PathBuf>, F: IntoIterator<Item = P>>(
paths: F,
) -> IntoIter<(PathBuf, BlissResult<Song>)> { ... }
fn analyze_paths_with_options<P: Into<PathBuf>, F: IntoIterator<Item = P>>(
paths: F,
analysis_options: AnalysisOptions,
) -> IntoIter<(PathBuf, BlissResult<Song>)> { ... }
}Expand description
Trait used to implement your own decoder.
The decode function should be implemented so that it
decodes and resample a song to one channel with a sampling rate of 22050 Hz
and a f32le layout.
Once it is implemented, several functions
to perform analysis from path(s) are available, such as
song_from_path and
analyze_paths.
For a reference on how to implement that trait, look at the FFmpeg decoder
Required Methods§
Sourcefn decode(path: &Path) -> BlissResult<PreAnalyzedSong>
fn decode(path: &Path) -> BlissResult<PreAnalyzedSong>
A function that should decode and resample a song, optionally extracting the song’s metadata such as the artist, the album, etc.
The output sample array should be resampled to f32le, one channel, with a sampling rate
of 22050 Hz. Anything other than that will yield wrong results.
To double-check that your sample array has the right format, you could run
ffmpeg -i path_to_your_song.flac -ar 22050 -ac 1 -c:a pcm_f32le -f hash -hash addler32 -,
which will give you the addler32 checksum of the sample array if the song
has been decoded properly. You can then compute the addler32 checksum of your sample
array (see _test_decode in the tests) and make sure both are the same.
(Running ffmpeg -i path_to_your_song.flac -ar 22050 -ac 1 -c:a pcm_f32le will simply give
you the raw sample array as it should look like, if you’re not into computing checksums)
Provided Methods§
Sourcefn song_from_path<P: AsRef<Path>>(path: P) -> BlissResult<Song>
fn song_from_path<P: AsRef<Path>>(path: P) -> BlissResult<Song>
Returns a decoded Song given a file path, or an error if the song could not be analyzed for some reason.
§Arguments
path- A Path holding a valid file path to a valid audio file.
§Errors
This function will return an error if the file path is invalid, if the file path points to a file containing no or corrupted audio stream, or if the analysis could not be conducted to the end for some reason.
The error type returned should give a hint as to whether it was a decoding (DecodingError) or an analysis (AnalysisError) error.
Sourcefn song_from_path_with_options<P: AsRef<Path>>(
path: P,
analysis_options: AnalysisOptions,
) -> BlissResult<Song>
fn song_from_path_with_options<P: AsRef<Path>>( path: P, analysis_options: AnalysisOptions, ) -> BlissResult<Song>
Returns a decoded Song given a file path, processed with the options
analysis_options or an error if the song could not be analyzed for some
reason. Use this if you want to analyze a song with older features version.
§Arguments
path- A Path holding a valid file path to a valid audio file.analysis_options: An AnalysisOptions struct holding various analysis options, such as the feature version. Thenumber_coresparameter is not used here, since only a single song is processed.
§Errors
This function will return an error if the file path is invalid, if the file path points to a file containing no or corrupted audio stream, or if the analysis could not be conducted to the end for some reason.
The error type returned should give a hint as to whether it was a decoding (DecodingError) or an analysis (AnalysisError) error.
Sourcefn analyze_paths<P: Into<PathBuf>, F: IntoIterator<Item = P>>(
paths: F,
) -> IntoIter<(PathBuf, BlissResult<Song>)>
fn analyze_paths<P: Into<PathBuf>, F: IntoIterator<Item = P>>( paths: F, ) -> IntoIter<(PathBuf, BlissResult<Song>)>
Analyze songs in paths using multiple threads, and return the
analyzed Song objects through an mpsc::IntoIter.
Returns an iterator, whose items are a tuple made of
the song path (to display to the user in case the analysis failed),
and a Result<Song>.
§Note
This function also works with CUE files - it finds the audio files mentionned in the CUE sheet, and then runs the analysis on each song defined by it, returning a proper Song object for each one of them.
Make sure that you don’t submit both the audio file along with the CUE
sheet if your library uses them, otherwise the audio file will be
analyzed as one, single, long song. For instance, with a CUE sheet named
cue-file.cue with the corresponding audio files album-1.wav and
album-2.wav defined in the CUE sheet, you would just pass cue-file.cue
to analyze_paths, and it will return Songs from both files, with
more information about which file it is extracted from in the
cue info field.
This example uses FFmpeg to decode songs by default, but it is possible to
implement another decoder and replace use bliss_audio::decoder::ffmpeg::FFmpegDecoder as Decoder;
by a custom decoder.
§Example
use bliss_audio::{BlissResult};
use bliss_audio::decoder::Decoder as DecoderTrait;
use bliss_audio::decoder::ffmpeg::FFmpegDecoder as Decoder;
fn main() -> BlissResult<()> {
let paths = vec![String::from("/path/to/song1"), String::from("/path/to/song2")];
for (path, result) in Decoder::analyze_paths(&paths) {
match result {
Ok(song) => println!("Do something with analyzed song {} with title {:?}", song.path.display(), song.title),
Err(e) => println!("Song at {} could not be analyzed. Failed with: {}", path.display(), e),
}
}
Ok(())
}Sourcefn analyze_paths_with_options<P: Into<PathBuf>, F: IntoIterator<Item = P>>(
paths: F,
analysis_options: AnalysisOptions,
) -> IntoIter<(PathBuf, BlissResult<Song>)>
fn analyze_paths_with_options<P: Into<PathBuf>, F: IntoIterator<Item = P>>( paths: F, analysis_options: AnalysisOptions, ) -> IntoIter<(PathBuf, BlissResult<Song>)>
Analyze songs in paths, and return the analyzed Song objects through an
mpsc::IntoIter. number_cores sets the number of cores the analysis
will use, capped by your system’s capacity. Most of the time, you want to
use the simpler analyze_paths functions, which autodetects the number
of cores in your system.
Return an iterator, whose items are a tuple made of
the song path (to display to the user in case the analysis failed),
and a Result<Song>.
§Note
This function also works with CUE files - it finds the audio files mentionned in the CUE sheet, and then runs the analysis on each song defined by it, returning a proper Song object for each one of them.
Make sure that you don’t submit both the audio file along with the CUE
sheet if your library uses them, otherwise the audio file will be
analyzed as one, single, long song. For instance, with a CUE sheet named
cue-file.cue with the corresponding audio files album-1.wav and
album-2.wav defined in the CUE sheet, you would just pass cue-file.cue
to analyze_paths, and it will return Songs from both files, with
more information about which file it is extracted from in the
cue info field.
§Example
use bliss_audio::BlissResult;
use bliss_audio::decoder::Decoder as DecoderTrait;
use bliss_audio::decoder::ffmpeg::FFmpegDecoder as Decoder;
fn main() -> BlissResult<()> {
let paths = vec![String::from("/path/to/song1"), String::from("/path/to/song2")];
for (path, result) in Decoder::analyze_paths(&paths) {
match result {
Ok(song) => println!("Do something with analyzed song {} with title {:?}", song.path.display(), song.title),
Err(e) => println!("Song at {} could not be analyzed. Failed with: {}", path.display(), e),
}
}
Ok(())
}Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.