Add album_artist and duration to song.

This commit is contained in:
Polochon-street 2022-04-12 22:06:49 +02:00
parent c08fd3d703
commit b61c0e0b62
4 changed files with 27 additions and 1 deletions

View file

@ -1,9 +1,10 @@
#Changelog #Changelog
## bliss 0.5.0 ## bliss 0.5.0
* Add `album_artist` and `duration` to `Song`.
* Fix a bug in `estimate_tuning` that led to empty chroma errors. * Fix a bug in `estimate_tuning` that led to empty chroma errors.
* Remove the unusued Library trait, and extract a few useful functions from * Remove the unusued Library trait, and extract a few useful functions from
there (`analyze_paths`, `closest_to_album_group`. there (`analyze_paths`, `closest_to_album_group`).
* Rename `distance` module to `playlist`. * Rename `distance` module to `playlist`.
* Remove all traces of the "analyse" word vs "analyze" to make the codebase * Remove all traces of the "analyse" word vs "analyze" to make the codebase
more coherent. more coherent.

Binary file not shown.

Binary file not shown.

View file

@ -41,6 +41,7 @@ use std::path::PathBuf;
use std::sync::mpsc; use std::sync::mpsc;
use std::sync::mpsc::Receiver; use std::sync::mpsc::Receiver;
use std::thread as std_thread; use std::thread as std_thread;
use std::time::Duration;
use strum::{EnumCount, IntoEnumIterator}; use strum::{EnumCount, IntoEnumIterator};
use strum_macros::{EnumCount, EnumIter}; use strum_macros::{EnumCount, EnumIter};
@ -57,12 +58,16 @@ pub struct Song {
pub title: Option<String>, pub title: Option<String>,
/// Song's album name, read from the metadata /// Song's album name, read from the metadata
pub album: Option<String>, pub album: Option<String>,
/// Song's album's artist name, read from the metadata
pub album_artist: Option<String>,
/// Song's tracked number, read from the metadata /// Song's tracked number, read from the metadata
pub track_number: Option<String>, pub track_number: Option<String>,
/// Song's genre, read from the metadata (`""` if empty) /// Song's genre, read from the metadata (`""` if empty)
pub genre: Option<String>, pub genre: Option<String>,
/// bliss analysis results /// bliss analysis results
pub analysis: Analysis, pub analysis: Analysis,
/// The song's duration
pub duration: Duration,
/// Version of the features the song was analyzed with. /// Version of the features the song was analyzed with.
/// A simple integer that is bumped every time a breaking change /// A simple integer that is bumped every time a breaking change
/// is introduced in the features. /// is introduced in the features.
@ -290,10 +295,12 @@ impl Song {
Ok(Song { Ok(Song {
path: raw_song.path, path: raw_song.path,
artist: raw_song.artist, artist: raw_song.artist,
album_artist: raw_song.album_artist,
title: raw_song.title, title: raw_song.title,
album: raw_song.album, album: raw_song.album,
track_number: raw_song.track_number, track_number: raw_song.track_number,
genre: raw_song.genre, genre: raw_song.genre,
duration: raw_song.duration,
analysis: Song::analyze(raw_song.sample_array)?, analysis: Song::analyze(raw_song.sample_array)?,
features_version: FEATURES_VERSION, features_version: FEATURES_VERSION,
}) })
@ -477,6 +484,13 @@ impl Song {
t => Some(t.to_string()), t => Some(t.to_string()),
}; };
}; };
if let Some(album_artist) = format.metadata().get("album_artist") {
song.album_artist = match album_artist {
"" => None,
t => Some(t.to_string()),
};
};
let in_channel_layout = { let in_channel_layout = {
if codec.channel_layout() == ChannelLayout::empty() { if codec.channel_layout() == ChannelLayout::empty() {
ChannelLayout::default(codec.channels().into()) ChannelLayout::default(codec.channels().into())
@ -569,6 +583,8 @@ impl Song {
drop(tx); drop(tx);
song.sample_array = child.join().unwrap()?; song.sample_array = child.join().unwrap()?;
let duration_seconds = song.sample_array.len() as f32 / SAMPLE_RATE as f32;
song.duration = Duration::from_nanos((duration_seconds * 1e9_f32).round() as u64);
Ok(song) Ok(song)
} }
} }
@ -577,10 +593,12 @@ impl Song {
pub(crate) struct InternalSong { pub(crate) struct InternalSong {
pub path: PathBuf, pub path: PathBuf,
pub artist: Option<String>, pub artist: Option<String>,
pub album_artist: Option<String>,
pub title: Option<String>, pub title: Option<String>,
pub album: Option<String>, pub album: Option<String>,
pub track_number: Option<String>, pub track_number: Option<String>,
pub genre: Option<String>, pub genre: Option<String>,
pub duration: Duration,
pub sample_array: Vec<f32>, pub sample_array: Vec<f32>,
} }
@ -723,10 +741,17 @@ mod tests {
fn test_tags() { fn test_tags() {
let song = Song::decode(Path::new("data/s16_mono_22_5kHz.flac")).unwrap(); let song = Song::decode(Path::new("data/s16_mono_22_5kHz.flac")).unwrap();
assert_eq!(song.artist, Some(String::from("David TMX"))); assert_eq!(song.artist, Some(String::from("David TMX")));
assert_eq!(
song.album_artist,
Some(String::from("David TMX - Album Artist"))
);
assert_eq!(song.title, Some(String::from("Renaissance"))); assert_eq!(song.title, Some(String::from("Renaissance")));
assert_eq!(song.album, Some(String::from("Renaissance"))); assert_eq!(song.album, Some(String::from("Renaissance")));
assert_eq!(song.track_number, Some(String::from("02"))); assert_eq!(song.track_number, Some(String::from("02")));
assert_eq!(song.genre, Some(String::from("Pop"))); assert_eq!(song.genre, Some(String::from("Pop")));
// Test that there is less than 10ms of difference between what
// the song advertises and what we compute.
assert!((song.duration.as_millis() as f32 - 11070.).abs() < 10.);
} }
#[test] #[test]