commit
ed2dd72c6b
53
Cargo.lock
generated
53
Cargo.lock
generated
|
@ -8,6 +8,12 @@ version = "1.0.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "adler32"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ahash"
|
name = "ahash"
|
||||||
version = "0.8.6"
|
version = "0.8.6"
|
||||||
|
@ -114,10 +120,10 @@ checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
|
||||||
name = "bliss-audio"
|
name = "bliss-audio"
|
||||||
version = "0.6.10"
|
version = "0.6.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"adler32",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bliss-audio-aubio-rs",
|
"bliss-audio-aubio-rs",
|
||||||
"clap",
|
"clap",
|
||||||
"crossbeam",
|
|
||||||
"dirs",
|
"dirs",
|
||||||
"ffmpeg-next",
|
"ffmpeg-next",
|
||||||
"ffmpeg-sys-next",
|
"ffmpeg-sys-next",
|
||||||
|
@ -129,10 +135,8 @@ dependencies = [
|
||||||
"ndarray-npy",
|
"ndarray-npy",
|
||||||
"ndarray-stats",
|
"ndarray-stats",
|
||||||
"noisy_float",
|
"noisy_float",
|
||||||
"num_cpus",
|
|
||||||
"pretty_assertions",
|
"pretty_assertions",
|
||||||
"rcue",
|
"rcue",
|
||||||
"ripemd",
|
|
||||||
"rusqlite",
|
"rusqlite",
|
||||||
"rustfft",
|
"rustfft",
|
||||||
"serde",
|
"serde",
|
||||||
|
@ -292,30 +296,6 @@ dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "crossbeam"
|
|
||||||
version = "0.8.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "6eb9105919ca8e40d437fc9cbb8f1975d916f1bd28afe795a48aae32a2cc8920"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
"crossbeam-channel",
|
|
||||||
"crossbeam-deque",
|
|
||||||
"crossbeam-epoch",
|
|
||||||
"crossbeam-queue",
|
|
||||||
"crossbeam-utils",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "crossbeam-channel"
|
|
||||||
version = "0.5.10"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "82a9b73a36529d9c47029b9fb3a6f0ea3cc916a261195352ba19e770fc1748b2"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
"crossbeam-utils",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-deque"
|
name = "crossbeam-deque"
|
||||||
version = "0.8.4"
|
version = "0.8.4"
|
||||||
|
@ -338,16 +318,6 @@ dependencies = [
|
||||||
"crossbeam-utils",
|
"crossbeam-utils",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "crossbeam-queue"
|
|
||||||
version = "0.3.10"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "adc6598521bb5a83d491e8c1fe51db7296019d2ca3cb93cc6c2a20369a4d78a2"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
"crossbeam-utils",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-utils"
|
name = "crossbeam-utils"
|
||||||
version = "0.8.18"
|
version = "0.8.18"
|
||||||
|
@ -1250,15 +1220,6 @@ version = "1.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "194d8e591e405d1eecf28819740abed6d719d1a2db87fc0bcdedee9a26d55560"
|
checksum = "194d8e591e405d1eecf28819740abed6d719d1a2db87fc0bcdedee9a26d55560"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ripemd"
|
|
||||||
version = "0.1.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f"
|
|
||||||
dependencies = [
|
|
||||||
"digest",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rusqlite"
|
name = "rusqlite"
|
||||||
version = "0.28.0"
|
version = "0.28.0"
|
||||||
|
|
|
@ -39,15 +39,15 @@ serde = ["dep:serde"]
|
||||||
# Until https://github.com/aubio/aubio/issues/336 is somehow solved
|
# Until https://github.com/aubio/aubio/issues/336 is somehow solved
|
||||||
# Hopefully we'll be able to use the official aubio-rs at some point.
|
# Hopefully we'll be able to use the official aubio-rs at some point.
|
||||||
bliss-audio-aubio-rs = "0.2.1"
|
bliss-audio-aubio-rs = "0.2.1"
|
||||||
crossbeam = "0.8.2"
|
|
||||||
ffmpeg-next = "6.1.0"
|
ffmpeg-next = "6.1.0"
|
||||||
ffmpeg-sys-next = { version = "6.1.0", default-features = false }
|
ffmpeg-sys-next = { version = "6.1.0", default-features = false }
|
||||||
log = "0.4.17"
|
log = "0.4.17"
|
||||||
|
# `rayon` is used only by `par_mapv_inplace` in chroma.rs.
|
||||||
|
# TODO: is the speed gain that substantial?
|
||||||
ndarray = { version = "0.15.6", features = ["rayon"] }
|
ndarray = { version = "0.15.6", features = ["rayon"] }
|
||||||
num_cpus = "1.15.0"
|
|
||||||
ndarray-stats = "0.5.1"
|
ndarray-stats = "0.5.1"
|
||||||
noisy_float = "0.2.0"
|
noisy_float = "0.2.0"
|
||||||
ripemd = "0.1.3"
|
adler32 = "1.0.2"
|
||||||
rustfft = "6.1.0"
|
rustfft = "6.1.0"
|
||||||
thiserror = "1.0.40"
|
thiserror = "1.0.40"
|
||||||
strum = "0.24.1"
|
strum = "0.24.1"
|
||||||
|
|
|
@ -160,8 +160,8 @@ impl BlissCueFile {
|
||||||
let mut songs = Vec::new();
|
let mut songs = Vec::new();
|
||||||
for (index, tuple) in (self.tracks[..]).windows(2).enumerate() {
|
for (index, tuple) in (self.tracks[..]).windows(2).enumerate() {
|
||||||
let (current_track, next_track) = (tuple[0].to_owned(), tuple[1].to_owned());
|
let (current_track, next_track) = (tuple[0].to_owned(), tuple[1].to_owned());
|
||||||
if let Some((_, start_current)) = current_track.indices.get(0) {
|
if let Some((_, start_current)) = current_track.indices.first() {
|
||||||
if let Some((_, end_current)) = next_track.indices.get(0) {
|
if let Some((_, end_current)) = next_track.indices.first() {
|
||||||
let start_current = (start_current.as_secs_f32() * SAMPLE_RATE as f32) as usize;
|
let start_current = (start_current.as_secs_f32() * SAMPLE_RATE as f32) as usize;
|
||||||
let end_current = (end_current.as_secs_f32() * SAMPLE_RATE as f32) as usize;
|
let end_current = (end_current.as_secs_f32() * SAMPLE_RATE as f32) as usize;
|
||||||
let duration = Duration::from_secs_f32(
|
let duration = Duration::from_secs_f32(
|
||||||
|
@ -176,7 +176,7 @@ impl BlissCueFile {
|
||||||
}
|
}
|
||||||
// Take care of the last track, since the windows iterator doesn't.
|
// Take care of the last track, since the windows iterator doesn't.
|
||||||
if let Some(last_track) = self.tracks.last() {
|
if let Some(last_track) = self.tracks.last() {
|
||||||
if let Some((_, start_current)) = last_track.indices.get(0) {
|
if let Some((_, start_current)) = last_track.indices.first() {
|
||||||
let start_current = (start_current.as_secs_f32() * SAMPLE_RATE as f32) as usize;
|
let start_current = (start_current.as_secs_f32() * SAMPLE_RATE as f32) as usize;
|
||||||
let duration = Duration::from_secs_f32(
|
let duration = Duration::from_secs_f32(
|
||||||
(self.sample_array.len() - start_current) as f32 / SAMPLE_RATE as f32,
|
(self.sample_array.len() - start_current) as f32 / SAMPLE_RATE as f32,
|
||||||
|
|
|
@ -75,8 +75,6 @@ mod temporal;
|
||||||
mod timbral;
|
mod timbral;
|
||||||
mod utils;
|
mod utils;
|
||||||
|
|
||||||
extern crate crossbeam;
|
|
||||||
extern crate num_cpus;
|
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate serde;
|
extern crate serde;
|
||||||
|
@ -155,7 +153,7 @@ pub type BlissResult<T> = Result<T, BlissError>;
|
||||||
pub fn analyze_paths<P: Into<PathBuf>, F: IntoIterator<Item = P>>(
|
pub fn analyze_paths<P: Into<PathBuf>, F: IntoIterator<Item = P>>(
|
||||||
paths: F,
|
paths: F,
|
||||||
) -> mpsc::IntoIter<(PathBuf, BlissResult<Song>)> {
|
) -> mpsc::IntoIter<(PathBuf, BlissResult<Song>)> {
|
||||||
let cores = NonZeroUsize::new(num_cpus::get()).unwrap();
|
let cores = thread::available_parallelism().unwrap_or(NonZeroUsize::new(1).unwrap());
|
||||||
analyze_paths_with_cores(paths, cores)
|
analyze_paths_with_cores(paths, cores)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -203,7 +201,7 @@ pub fn analyze_paths_with_cores<P: Into<PathBuf>, F: IntoIterator<Item = P>>(
|
||||||
paths: F,
|
paths: F,
|
||||||
number_cores: NonZeroUsize,
|
number_cores: NonZeroUsize,
|
||||||
) -> mpsc::IntoIter<(PathBuf, BlissResult<Song>)> {
|
) -> mpsc::IntoIter<(PathBuf, BlissResult<Song>)> {
|
||||||
let mut cores = NonZeroUsize::new(num_cpus::get()).unwrap();
|
let mut cores = thread::available_parallelism().unwrap_or(NonZeroUsize::new(1).unwrap());
|
||||||
if cores > number_cores {
|
if cores > number_cores {
|
||||||
cores = number_cores;
|
cores = number_cores;
|
||||||
}
|
}
|
||||||
|
|
|
@ -138,6 +138,7 @@ use std::num::NonZeroUsize;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
use std::thread;
|
||||||
|
|
||||||
use crate::Song;
|
use crate::Song;
|
||||||
use crate::FEATURES_VERSION;
|
use crate::FEATURES_VERSION;
|
||||||
|
@ -277,8 +278,9 @@ impl BaseConfig {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let number_cores =
|
let number_cores = number_cores.unwrap_or_else(|| {
|
||||||
number_cores.unwrap_or_else(|| NonZeroUsize::new(num_cpus::get()).unwrap());
|
thread::available_parallelism().unwrap_or(NonZeroUsize::new(1).unwrap())
|
||||||
|
});
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
config_path,
|
config_path,
|
||||||
|
@ -3010,7 +3012,7 @@ mod test {
|
||||||
library.config.base_config().config_path.display(),
|
library.config.base_config().config_path.display(),
|
||||||
library.config.base_config().database_path.display(),
|
library.config.base_config().database_path.display(),
|
||||||
FEATURES_VERSION,
|
FEATURES_VERSION,
|
||||||
num_cpus::get(),
|
thread::available_parallelism().unwrap_or(NonZeroUsize::new(1).unwrap()),
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -3183,7 +3185,10 @@ mod test {
|
||||||
ignore_wav_files: true,
|
ignore_wav_files: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_eq!(config.get_number_cores().get(), num_cpus::get());
|
assert_eq!(
|
||||||
|
config.get_number_cores().get(),
|
||||||
|
usize::from(thread::available_parallelism().unwrap_or(NonZeroUsize::new(1).unwrap())),
|
||||||
|
);
|
||||||
|
|
||||||
let base_config =
|
let base_config =
|
||||||
BaseConfig::new(Some(config_file), Some(database_file), Some(nzus(1))).unwrap();
|
BaseConfig::new(Some(config_file), Some(database_file), Some(nzus(1))).unwrap();
|
||||||
|
|
98
src/song.rs
98
src/song.rs
|
@ -7,7 +7,6 @@
|
||||||
//! For implementation of plug-ins for already existing audio players,
|
//! For implementation of plug-ins for already existing audio players,
|
||||||
//! a look at Library is instead recommended.
|
//! a look at Library is instead recommended.
|
||||||
|
|
||||||
extern crate crossbeam;
|
|
||||||
extern crate ffmpeg_next as ffmpeg;
|
extern crate ffmpeg_next as ffmpeg;
|
||||||
extern crate ndarray;
|
extern crate ndarray;
|
||||||
|
|
||||||
|
@ -23,7 +22,6 @@ use crate::{BlissError, BlissResult, SAMPLE_RATE};
|
||||||
use crate::{CHANNELS, FEATURES_VERSION};
|
use crate::{CHANNELS, FEATURES_VERSION};
|
||||||
use ::log::warn;
|
use ::log::warn;
|
||||||
use core::ops::Index;
|
use core::ops::Index;
|
||||||
use crossbeam::thread;
|
|
||||||
use ffmpeg_next::codec::threading::{Config, Type as ThreadingType};
|
use ffmpeg_next::codec::threading::{Config, Type as ThreadingType};
|
||||||
use ffmpeg_next::util::channel_layout::ChannelLayout;
|
use ffmpeg_next::util::channel_layout::ChannelLayout;
|
||||||
use ffmpeg_next::util::error::Error;
|
use ffmpeg_next::util::error::Error;
|
||||||
|
@ -40,7 +38,7 @@ use std::path::Path;
|
||||||
use std::path::PathBuf;
|
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;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use strum::{EnumCount, IntoEnumIterator};
|
use strum::{EnumCount, IntoEnumIterator};
|
||||||
use strum_macros::{EnumCount, EnumIter};
|
use strum_macros::{EnumCount, EnumIter};
|
||||||
|
@ -331,16 +329,16 @@ impl Song {
|
||||||
*
|
*
|
||||||
* If you *do* want to use this with a song already decoded by yourself,
|
* If you *do* want to use this with a song already decoded by yourself,
|
||||||
* the sample format of `sample_array` should be f32le, one channel, and
|
* the sample format of `sample_array` should be f32le, one channel, and
|
||||||
* the sampling rate 22050 Hz. Anything other thant that will yield aberrant
|
* the sampling rate 22050 Hz. Anything other than that will yield aberrant
|
||||||
* results.
|
* results.
|
||||||
* To double-check that your sample array has the right format, you could run
|
* 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 ripemd160 -`,
|
* `ffmpeg -i path_to_your_song.flac -ar 22050 -ac 1 -c:a pcm_f32le -f hash -hash addler32 -`,
|
||||||
* which will give you the ripemd160 hash of the sample array if the song
|
* which will give you the addler32 checksum of the sample array if the song
|
||||||
* has been decoded properly. You can then compute the ripemd160 hash of your sample
|
* 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 hashes are the same.
|
* 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
|
* (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 hashes)
|
* you the raw sample array as it should look like, if you're not into computing checksums)
|
||||||
**/
|
**/
|
||||||
pub fn analyze(sample_array: &[f32]) -> BlissResult<Analysis> {
|
pub fn analyze(sample_array: &[f32]) -> BlissResult<Analysis> {
|
||||||
let largest_window = vec![
|
let largest_window = vec![
|
||||||
|
@ -358,8 +356,8 @@ impl Song {
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
thread::scope(|s| {
|
thread::scope(|s| -> BlissResult<Analysis> {
|
||||||
let child_tempo: thread::ScopedJoinHandle<'_, BlissResult<f32>> = s.spawn(|_| {
|
let child_tempo = s.spawn(|| {
|
||||||
let mut tempo_desc = BPMDesc::new(SAMPLE_RATE)?;
|
let mut tempo_desc = BPMDesc::new(SAMPLE_RATE)?;
|
||||||
let windows = sample_array
|
let windows = sample_array
|
||||||
.windows(BPMDesc::WINDOW_SIZE)
|
.windows(BPMDesc::WINDOW_SIZE)
|
||||||
|
@ -371,17 +369,14 @@ impl Song {
|
||||||
Ok(tempo_desc.get_value())
|
Ok(tempo_desc.get_value())
|
||||||
});
|
});
|
||||||
|
|
||||||
let child_chroma: thread::ScopedJoinHandle<'_, BlissResult<Vec<f32>>> = s.spawn(|_| {
|
let child_chroma = s.spawn(|| {
|
||||||
let mut chroma_desc = ChromaDesc::new(SAMPLE_RATE, 12);
|
let mut chroma_desc = ChromaDesc::new(SAMPLE_RATE, 12);
|
||||||
chroma_desc.do_(sample_array)?;
|
chroma_desc.do_(sample_array)?;
|
||||||
Ok(chroma_desc.get_values())
|
Ok(chroma_desc.get_values())
|
||||||
});
|
});
|
||||||
|
|
||||||
#[allow(clippy::type_complexity)]
|
#[allow(clippy::type_complexity)]
|
||||||
let child_timbral: thread::ScopedJoinHandle<
|
let child_timbral = s.spawn(|| {
|
||||||
'_,
|
|
||||||
BlissResult<(Vec<f32>, Vec<f32>, Vec<f32>)>,
|
|
||||||
> = s.spawn(|_| {
|
|
||||||
let mut spectral_desc = SpectralDesc::new(SAMPLE_RATE)?;
|
let mut spectral_desc = SpectralDesc::new(SAMPLE_RATE)?;
|
||||||
let windows = sample_array
|
let windows = sample_array
|
||||||
.windows(SpectralDesc::WINDOW_SIZE)
|
.windows(SpectralDesc::WINDOW_SIZE)
|
||||||
|
@ -395,22 +390,21 @@ impl Song {
|
||||||
Ok((centroid, rolloff, flatness))
|
Ok((centroid, rolloff, flatness))
|
||||||
});
|
});
|
||||||
|
|
||||||
let child_zcr: thread::ScopedJoinHandle<'_, BlissResult<f32>> = s.spawn(|_| {
|
let child_zcr = s.spawn(|| {
|
||||||
let mut zcr_desc = ZeroCrossingRateDesc::default();
|
let mut zcr_desc = ZeroCrossingRateDesc::default();
|
||||||
zcr_desc.do_(sample_array);
|
zcr_desc.do_(sample_array);
|
||||||
Ok(zcr_desc.get_value())
|
Ok(zcr_desc.get_value())
|
||||||
});
|
});
|
||||||
|
|
||||||
let child_loudness: thread::ScopedJoinHandle<'_, BlissResult<Vec<f32>>> =
|
let child_loudness = s.spawn(|| {
|
||||||
s.spawn(|_| {
|
let mut loudness_desc = LoudnessDesc::default();
|
||||||
let mut loudness_desc = LoudnessDesc::default();
|
let windows = sample_array.chunks(LoudnessDesc::WINDOW_SIZE);
|
||||||
let windows = sample_array.chunks(LoudnessDesc::WINDOW_SIZE);
|
|
||||||
|
|
||||||
for window in windows {
|
for window in windows {
|
||||||
loudness_desc.do_(window);
|
loudness_desc.do_(window);
|
||||||
}
|
}
|
||||||
Ok(loudness_desc.get_value())
|
Ok(loudness_desc.get_value())
|
||||||
});
|
});
|
||||||
|
|
||||||
// Non-streaming approach for that one
|
// Non-streaming approach for that one
|
||||||
let tempo = child_tempo.join().unwrap()?;
|
let tempo = child_tempo.join().unwrap()?;
|
||||||
|
@ -434,7 +428,6 @@ impl Song {
|
||||||
})?;
|
})?;
|
||||||
Ok(Analysis::new(array))
|
Ok(Analysis::new(array))
|
||||||
})
|
})
|
||||||
.unwrap()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn decode(path: &Path) -> BlissResult<InternalSong> {
|
pub(crate) fn decode(path: &Path) -> BlissResult<InternalSong> {
|
||||||
|
@ -548,7 +541,7 @@ impl Song {
|
||||||
let (tx, rx) = mpsc::channel();
|
let (tx, rx) = mpsc::channel();
|
||||||
let in_codec_format = decoder.format();
|
let in_codec_format = decoder.format();
|
||||||
let in_codec_rate = decoder.rate();
|
let in_codec_rate = decoder.rate();
|
||||||
let child = std_thread::spawn(move || {
|
let child = thread::spawn(move || {
|
||||||
resample_frame(
|
resample_frame(
|
||||||
rx,
|
rx,
|
||||||
in_codec_format,
|
in_codec_format,
|
||||||
|
@ -752,8 +745,8 @@ fn push_to_sample_array(frame: &ffmpeg::frame::Audio, sample_array: &mut Vec<f32
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use adler32::RollingAdler32;
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
use ripemd::{Digest, Ripemd160};
|
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -802,14 +795,14 @@ mod tests {
|
||||||
assert_eq!(FEATURES_VERSION, song.features_version);
|
assert_eq!(FEATURES_VERSION, song.features_version);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn _test_decode(path: &Path, expected_hash: &[u8]) {
|
fn _test_decode(path: &Path, expected_hash: u32) {
|
||||||
let song = Song::decode(path).unwrap();
|
let song = Song::decode(path).unwrap();
|
||||||
let mut hasher = Ripemd160::new();
|
let mut hasher = RollingAdler32::new();
|
||||||
for sample in song.sample_array.iter() {
|
for sample in song.sample_array.iter() {
|
||||||
hasher.update(sample.to_le_bytes().to_vec());
|
hasher.update_buffer(&sample.to_le_bytes());
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_eq!(expected_hash, hasher.finalize().as_slice());
|
assert_eq!(expected_hash, hasher.hash());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -842,21 +835,15 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_resample_multi() {
|
fn test_resample_multi() {
|
||||||
let path = Path::new("data/s32_stereo_44_1_kHz.flac");
|
let path = Path::new("data/s32_stereo_44_1_kHz.flac");
|
||||||
let expected_hash = [
|
let expected_hash = 0xbbcba1cf;
|
||||||
0xc5, 0xf8, 0x23, 0xce, 0x63, 0x2c, 0xf4, 0xa0, 0x72, 0x66, 0xbb, 0x49, 0xad, 0x84,
|
_test_decode(&path, expected_hash);
|
||||||
0xb6, 0xea, 0x48, 0x48, 0x9c, 0x50,
|
|
||||||
];
|
|
||||||
_test_decode(&path, &expected_hash);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_resample_stereo() {
|
fn test_resample_stereo() {
|
||||||
let path = Path::new("data/s16_stereo_22_5kHz.flac");
|
let path = Path::new("data/s16_stereo_22_5kHz.flac");
|
||||||
let expected_hash = [
|
let expected_hash = 0x1d7b2d6d;
|
||||||
0x24, 0xed, 0x45, 0x58, 0x06, 0xbf, 0xfb, 0x05, 0x57, 0x5f, 0xdc, 0x4d, 0xb4, 0x9b,
|
_test_decode(&path, expected_hash);
|
||||||
0xa5, 0x2b, 0x05, 0x56, 0x10, 0x4f,
|
|
||||||
];
|
|
||||||
_test_decode(&path, &expected_hash);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -864,12 +851,9 @@ mod tests {
|
||||||
let path = Path::new("data/s16_mono_22_5kHz.flac");
|
let path = Path::new("data/s16_mono_22_5kHz.flac");
|
||||||
// Obtained through
|
// Obtained through
|
||||||
// ffmpeg -i data/s16_mono_22_5kHz.flac -ar 22050 -ac 1 -c:a pcm_f32le
|
// ffmpeg -i data/s16_mono_22_5kHz.flac -ar 22050 -ac 1 -c:a pcm_f32le
|
||||||
// -f hash -hash ripemd160 -
|
// -f hash -hash addler32 -
|
||||||
let expected_hash = [
|
let expected_hash = 0x5e01930b;
|
||||||
0x9d, 0x95, 0xa5, 0xf2, 0xd2, 0x9c, 0x68, 0xe8, 0x8a, 0x70, 0xcd, 0xf3, 0x54, 0x2c,
|
_test_decode(&path, expected_hash);
|
||||||
0x5b, 0x45, 0x98, 0xb4, 0xf3, 0xb4,
|
|
||||||
];
|
|
||||||
_test_decode(&path, &expected_hash);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -877,12 +861,9 @@ mod tests {
|
||||||
let path = Path::new("data/s32_stereo_44_1_kHz.mp3");
|
let path = Path::new("data/s32_stereo_44_1_kHz.mp3");
|
||||||
// Obtained through
|
// Obtained through
|
||||||
// ffmpeg -i data/s16_mono_22_5kHz.mp3 -ar 22050 -ac 1 -c:a pcm_f32le
|
// ffmpeg -i data/s16_mono_22_5kHz.mp3 -ar 22050 -ac 1 -c:a pcm_f32le
|
||||||
// -f hash -hash ripemd160 -
|
// -f hash -hash addler32 -
|
||||||
let expected_hash = [
|
let expected_hash = 0x69ca6906;
|
||||||
0x28, 0x25, 0x6b, 0x7b, 0x6e, 0x37, 0x1c, 0xcf, 0xc7, 0x06, 0xdf, 0x62, 0x8c, 0x0e,
|
_test_decode(&path, expected_hash);
|
||||||
0x91, 0xf7, 0xd6, 0x1f, 0xac, 0x5b,
|
|
||||||
];
|
|
||||||
_test_decode(&path, &expected_hash);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -969,11 +950,8 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_decode_wav() {
|
fn test_decode_wav() {
|
||||||
let expected_hash = [
|
let expected_hash = 0xde831e82;
|
||||||
0xf0, 0xe0, 0x85, 0x4e, 0xf6, 0x53, 0x76, 0xfa, 0x7a, 0xa5, 0x65, 0x76, 0xf9, 0xe1,
|
_test_decode(Path::new("data/piano.wav"), expected_hash);
|
||||||
0xe8, 0xe0, 0x81, 0xc8, 0xdc, 0x61,
|
|
||||||
];
|
|
||||||
_test_decode(Path::new("data/piano.wav"), &expected_hash);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
Loading…
Reference in New Issue
Block a user