Add album_artist and duration to song.
This commit is contained in:
parent
c08fd3d703
commit
b61c0e0b62
4 changed files with 27 additions and 1 deletions
|
@ -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.
25
src/song.rs
25
src/song.rs
|
@ -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]
|
||||||
|
|
Loading…
Reference in a new issue