Skip to content

Commit

Permalink
Continue the optional ffmpeg feature
Browse files Browse the repository at this point in the history
  • Loading branch information
Polochon-street committed May 12, 2024
1 parent e9fb401 commit eefade0
Show file tree
Hide file tree
Showing 22 changed files with 1,372 additions and 1,233 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ jobs:
run: cargo +nightly-2024-01-16 bench --verbose --features=bench --no-run
- name: Build examples
run: cargo build --examples --verbose --features=serde,library
- name: Build without ffmpeg
run: cargo build --verbose --no-default-features


build-test-lint-windows:
name: Windows - build, test and lint
Expand Down
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@
* Remove circular dependency between playlist and song by removing distances
from the `Song` struct (Thanks @SimonTeixidor!)

## bliss 0.7.0
* Decoupled bliss from ffmpeg, by making a default but optional feature.
Existing code will need to be updated by replacing `Song::from_path` by
`song::decoder::bliss_ffmpeg::FFmpeg::song_from_path`, and the other
corresponding functions.

## bliss 0.6.11
* Bump rust-ffmpeg to 6.1.1 to fix build for raspberry pis.

Expand Down
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ default = ["ffmpeg", "aubio-static"]
# 99% of cases, disable it at your own risk! It would be useful if you
# want to implement the decoding of the tracks yourself and just feed
# them to bliss, so you don't depend on ffmpeg.
# TODO make ffmpeg a test-dep
ffmpeg = ["dep:ffmpeg-next", "dep:ffmpeg-sys-next"]
aubio-static = ["bliss-audio-aubio-rs/static"]
# Build ffmpeg instead of using the host's.
Expand Down
12 changes: 8 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,13 @@ Ready to use code examples:

### Compute the distance between two songs
```
use bliss_audio::{BlissError, Song};
use bliss_audio::decoder::bliss_ffmpeg::FFmpeg as Decoder;
use bliss_audio::decoder::Decoder as DecoderTrait;
use bliss_audio::BlissError;
fn main() -> Result<(), BlissError> {
let song1 = Song::from_path("/path/to/song1")?;
let song2 = Song::from_path("/path/to/song2")?;
let song1 = Decoder::from_path("/path/to/song1")?;
let song2 = Decoder::from_path("/path/to/song2")?;
println!("Distance between song1 and song2 is {}", song1.distance(&song2));
Ok(())
Expand All @@ -61,14 +63,16 @@ fn main() -> Result<(), BlissError> {

### Make a playlist from a song
```
use bliss_audio::decoder::bliss_ffmpeg::FFmpeg as Decoder;
use bliss_audio::decoder::Decoder as DecoderTrait;
use bliss_audio::{BlissError, Song};
use noisy_float::prelude::n32;
fn main() -> Result<(), BlissError> {
let paths = vec!["/path/to/song1", "/path/to/song2", "/path/to/song3"];
let mut songs: Vec<Song> = paths
.iter()
.map(|path| Song::from_path(path))
.map(|path| Decoder::song_from_path(path))
.collect::<Result<Vec<Song>, BlissError>>()?;
// Assuming there is a first song
Expand Down
1 change: 1 addition & 0 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ ask questions if you want to tackle an item.

- Split out ffmpeg (see https://github.com/Polochon-street/bliss-rs/issues/63 and https://users.rust-lang.org/t/proper-way-to-abstract-a-third-party-provider/107076/8)
- Make ffmpeg an optional (but default) feature
- The library trait must be Decoder-agnostic, and not depend on FFmpeg
- Make the tests that don't need it not dependent of ffmpeg
- Make the Song::from_path a trait that is by default implemented with the
ffmpeg feature (so you can theoretically implement the library trait without ffmpeg)
Expand Down
2 changes: 1 addition & 1 deletion ci_check.sh
Original file line number Diff line number Diff line change
@@ -1 +1 @@
cargo fmt -- --check && cargo clippy --examples --features=serde -- -D warnings && cargo build --verbose && cargo test --verbose && cargo test --verbose --examples && cargo +nightly-2023-02-16 bench --verbose --features=bench --no-run && cargo build --examples --verbose --features=serde
cargo fmt -- --check && cargo clippy --examples --features=serde -- -D warnings && cargo build --verbose && cargo test --verbose && cargo test --verbose --examples && cargo +nightly-2024-01-16 bench --verbose --features=bench --no-run && cargo build --examples --verbose --features=serde && cargo build --no-default-features
5 changes: 3 additions & 2 deletions examples/analyze.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use bliss_audio::Song;
use bliss_audio::decoder::ffmpeg::FFmpeg as Decoder;
use bliss_audio::decoder::Decoder as DecoderTrait;
use std::env;

/**
Expand All @@ -9,7 +10,7 @@ use std::env;
fn main() {
let args: Vec<String> = env::args().skip(1).collect();
for path in &args {
match Song::from_path(path) {
match Decoder::song_from_path(path) {
Ok(song) => println!("{}: {:?}", path, song.analysis),
Err(e) => println!("{path}: {e}"),
}
Expand Down
8 changes: 5 additions & 3 deletions examples/distance.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use bliss_audio::{playlist::euclidean_distance, Song};
use bliss_audio::decoder::ffmpeg::FFmpeg as Decoder;
use bliss_audio::decoder::Decoder as DecoderTrait;
use bliss_audio::playlist::euclidean_distance;
use std::env;

/**
Expand All @@ -13,8 +15,8 @@ fn main() -> Result<(), String> {
let first_path = paths.next().ok_or("Help: ./distance <song1> <song2>")?;
let second_path = paths.next().ok_or("Help: ./distance <song1> <song2>")?;

let song1 = Song::from_path(first_path).map_err(|x| x.to_string())?;
let song2 = Song::from_path(second_path).map_err(|x| x.to_string())?;
let song1 = Decoder::song_from_path(first_path).map_err(|x| x.to_string())?;
let song2 = Decoder::song_from_path(second_path).map_err(|x| x.to_string())?;

println!(
"d({:?}, {:?}) = {}",
Expand Down
7 changes: 4 additions & 3 deletions examples/library.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
/// For simplicity's sake, this example recursively gets songs from a folder
/// to emulate an audio player library, without handling CUE files.
use anyhow::Result;
use bliss_audio::decoder::ffmpeg::FFmpeg as Decoder;
use bliss_audio::library::{AppConfigTrait, BaseConfig, Library};
use clap::{App, Arg, SubCommand};
use glob::glob;
Expand Down Expand Up @@ -68,7 +69,7 @@ trait CustomLibrary {
fn song_paths(&self) -> Result<Vec<String>>;
}

impl CustomLibrary for Library<Config> {
impl CustomLibrary for Library<Config, Decoder> {
/// Get all songs in the player library
fn song_paths(&self) -> Result<Vec<String>> {
let music_path = &self.config.music_library_path;
Expand Down Expand Up @@ -180,7 +181,7 @@ fn main() -> Result<()> {
library.analyze_paths(library.song_paths()?, true)?;
} else if let Some(sub_m) = matches.subcommand_matches("update") {
let config_path = sub_m.value_of("config-path").map(PathBuf::from);
let mut library: Library<Config> = Library::from_config_path(config_path)?;
let mut library: Library<Config, Decoder> = Library::from_config_path(config_path)?;
library.update_library(library.song_paths()?, true, true)?;
} else if let Some(sub_m) = matches.subcommand_matches("playlist") {
let song_path = sub_m.value_of("SONG_PATH").unwrap();
Expand All @@ -189,7 +190,7 @@ fn main() -> Result<()> {
.value_of("playlist-length")
.unwrap_or("20")
.parse::<usize>()?;
let library: Library<Config> = Library::from_config_path(config_path)?;
let library: Library<Config, Decoder> = Library::from_config_path(config_path)?;
let songs = library.playlist_from::<()>(&[song_path], playlist_length)?;
let song_paths = songs
.into_iter()
Expand Down
7 changes: 4 additions & 3 deletions examples/library_extra_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
/// For simplicity's sake, this example recursively gets songs from a folder
/// to emulate an audio player library, without handling CUE files.
use anyhow::Result;
use bliss_audio::decoder::ffmpeg::FFmpeg as Decoder;
use bliss_audio::library::{AppConfigTrait, BaseConfig, Library};
use clap::{App, Arg, SubCommand};
use glob::glob;
Expand Down Expand Up @@ -69,7 +70,7 @@ trait CustomLibrary {
fn song_paths_info(&self) -> Result<Vec<(String, ExtraInfo)>>;
}

impl CustomLibrary for Library<Config> {
impl CustomLibrary for Library<Config, Decoder> {
/// Get all songs in the player library, along with the extra info
/// one would want to store along with each song.
fn song_paths_info(&self) -> Result<Vec<(String, ExtraInfo)>> {
Expand Down Expand Up @@ -198,7 +199,7 @@ fn main() -> Result<()> {
library.analyze_paths_extra_info(library.song_paths_info()?, true)?;
} else if let Some(sub_m) = matches.subcommand_matches("update") {
let config_path = sub_m.value_of("config-path").map(PathBuf::from);
let mut library: Library<Config> = Library::from_config_path(config_path)?;
let mut library: Library<Config, Decoder> = Library::from_config_path(config_path)?;
library.update_library_extra_info(library.song_paths_info()?, true, true)?;
} else if let Some(sub_m) = matches.subcommand_matches("playlist") {
let song_path = sub_m.value_of("SONG_PATH").unwrap();
Expand All @@ -207,7 +208,7 @@ fn main() -> Result<()> {
.value_of("playlist-length")
.unwrap_or("20")
.parse::<usize>()?;
let library: Library<Config> = Library::from_config_path(config_path)?;
let library: Library<Config, Decoder> = Library::from_config_path(config_path)?;
let songs = library.playlist_from::<ExtraInfo>(&[song_path], playlist_length)?;
let playlist = songs
.into_iter()
Expand Down
8 changes: 5 additions & 3 deletions examples/playlist.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use anyhow::Result;
use bliss_audio::decoder::ffmpeg::FFmpeg as Decoder;
use bliss_audio::decoder::Decoder as DecoderTrait;
use bliss_audio::playlist::{closest_to_songs, dedup_playlist, euclidean_distance};
use bliss_audio::{analyze_paths, Song};
use bliss_audio::Song;
use clap::{App, Arg};
use glob::glob;
use std::env;
Expand Down Expand Up @@ -56,14 +58,14 @@ fn main() -> Result<()> {
.map(|x| x.to_string_lossy().to_string())
.collect::<Vec<String>>();

let song_iterator = analyze_paths(
let song_iterator = Decoder::analyze_paths(
paths
.iter()
.filter(|p| !analyzed_paths.contains(&PathBuf::from(p)))
.map(|p| p.to_owned())
.collect::<Vec<String>>(),
);
let first_song = Song::from_path(file)?;
let first_song = Decoder::song_from_path(file)?;
let mut analyzed_songs = vec![first_song.to_owned()];
for (path, result) in song_iterator {
match result {
Expand Down
22 changes: 14 additions & 8 deletions src/chroma.rs
Original file line number Diff line number Diff line change
Expand Up @@ -365,9 +365,13 @@ fn chroma_stft(
mod test {
use super::*;
#[cfg(feature = "ffmpeg")]
use crate::song::decoder::ffmpeg::FFmpeg as Decoder;
#[cfg(feature = "ffmpeg")]
use crate::song::decoder::Decoder as DecoderTrait;
#[cfg(feature = "ffmpeg")]
use crate::utils::stft;
#[cfg(feature = "ffmpeg")]
use crate::{Song, SAMPLE_RATE};
use crate::SAMPLE_RATE;
use ndarray::{arr1, arr2, Array2};
use ndarray_npy::ReadNpyExt;
use std::fs::File;
Expand Down Expand Up @@ -439,7 +443,7 @@ mod test {
#[test]
#[cfg(feature = "ffmpeg")]
fn test_chroma_desc() {
let song = Song::decode(Path::new("data/s16_mono_22_5kHz.flac")).unwrap();
let song = Decoder::decode(Path::new("data/s16_mono_22_5kHz.flac")).unwrap();
let mut chroma_desc = ChromaDesc::new(SAMPLE_RATE, 12);
chroma_desc.do_(&song.sample_array).unwrap();
let expected_values = vec![
Expand All @@ -462,7 +466,7 @@ mod test {
#[test]
#[cfg(feature = "ffmpeg")]
fn test_chroma_stft_decode() {
let signal = Song::decode(Path::new("data/s16_mono_22_5kHz.flac"))
let signal = Decoder::decode(Path::new("data/s16_mono_22_5kHz.flac"))
.unwrap()
.sample_array;
let mut stft = stft(&signal, 8192, 2205);
Expand Down Expand Up @@ -496,7 +500,7 @@ mod test {
#[test]
#[cfg(feature = "ffmpeg")]
fn test_estimate_tuning_decode() {
let signal = Song::decode(Path::new("data/s16_mono_22_5kHz.flac"))
let signal = Decoder::decode(Path::new("data/s16_mono_22_5kHz.flac"))
.unwrap()
.sample_array;
let stft = stft(&signal, 8192, 2205);
Expand Down Expand Up @@ -559,8 +563,10 @@ mod test {
mod bench {
extern crate test;
use super::*;
use crate::song::decoder::ffmpeg::FFmpeg as Decoder;
use crate::song::decoder::Decoder as DecoderTrait;
use crate::utils::stft;
use crate::{Song, SAMPLE_RATE};
use crate::SAMPLE_RATE;
use ndarray::{arr2, Array1, Array2};
use ndarray_npy::ReadNpyExt;
use std::fs::File;
Expand Down Expand Up @@ -614,7 +620,7 @@ mod bench {
#[bench]
#[cfg(feature = "ffmpeg")]
fn bench_chroma_desc(b: &mut Bencher) {
let song = Song::decode(Path::new("data/s16_mono_22_5kHz.flac")).unwrap();
let song = Decoder::decode(Path::new("data/s16_mono_22_5kHz.flac")).unwrap();
let mut chroma_desc = ChromaDesc::new(SAMPLE_RATE, 12);
let signal = song.sample_array;
b.iter(|| {
Expand All @@ -626,7 +632,7 @@ mod bench {
#[bench]
#[cfg(feature = "ffmpeg")]
fn bench_chroma_stft(b: &mut Bencher) {
let song = Song::decode(Path::new("data/s16_mono_22_5kHz.flac")).unwrap();
let song = Decoder::decode(Path::new("data/s16_mono_22_5kHz.flac")).unwrap();
let mut chroma_desc = ChromaDesc::new(SAMPLE_RATE, 12);
let signal = song.sample_array;
b.iter(|| {
Expand All @@ -638,7 +644,7 @@ mod bench {
#[bench]
#[cfg(feature = "ffmpeg")]
fn bench_chroma_stft_decode(b: &mut Bencher) {
let signal = Song::decode(Path::new("data/s16_mono_22_5kHz.flac"))
let signal = Decoder::decode(Path::new("data/s16_mono_22_5kHz.flac"))
.unwrap()
.sample_array;
let mut stft = stft(&signal, 8192, 2205);
Expand Down
Loading

0 comments on commit eefade0

Please sign in to comment.