From 8573d30d0234082cc6b66f54f64509e9ec4425cf Mon Sep 17 00:00:00 2001 From: Kai Vogelgesang Date: Wed, 15 Sep 2021 21:03:13 +0200 Subject: [PATCH] Add beat detection Rust POC --- libpulse_aubio/.gitignore | 1 + libpulse_aubio/Cargo.lock | 204 +++++++++++++++++++++++++++++++++++++ libpulse_aubio/Cargo.toml | 12 +++ libpulse_aubio/src/main.rs | 56 ++++++++++ 4 files changed, 273 insertions(+) create mode 100644 libpulse_aubio/.gitignore create mode 100644 libpulse_aubio/Cargo.lock create mode 100644 libpulse_aubio/Cargo.toml create mode 100644 libpulse_aubio/src/main.rs diff --git a/libpulse_aubio/.gitignore b/libpulse_aubio/.gitignore new file mode 100644 index 0000000..eb5a316 --- /dev/null +++ b/libpulse_aubio/.gitignore @@ -0,0 +1 @@ +target diff --git a/libpulse_aubio/Cargo.lock b/libpulse_aubio/Cargo.lock new file mode 100644 index 0000000..5d7abd5 --- /dev/null +++ b/libpulse_aubio/Cargo.lock @@ -0,0 +1,204 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "anyhow" +version = "1.0.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61604a8f862e1d5c3229fdd78f8b02c68dcf73a4c4b05fd636d12240aaa242c1" + +[[package]] +name = "aubio" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "577cfca08ecb60eb4ad21f19507bc614229130112ac606cd493c0e5bb5318f54" +dependencies = [ + "aubio-sys", +] + +[[package]] +name = "aubio-sys" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99ef2dfeaceccd0b8a6d72203409acc927d9eebc8180c5756099549c9f8f20a8" +dependencies = [ + "cc", +] + +[[package]] +name = "autocfg" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "cc" +version = "1.0.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26a6ce4b6a484fa3edb70f7efa6fc430fd2b87285fe8b84304fd0936faa0dc0" +dependencies = [ + "jobserver", +] + +[[package]] +name = "jobserver" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa" +dependencies = [ + "libc", +] + +[[package]] +name = "libc" +version = "0.2.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2a5ac8f984bfcf3a823267e5fde638acc3325f6496633a5da6bb6eb2171e103" + +[[package]] +name = "libpulse-binding" +version = "2.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86835d7763ded6bc16b6c0061ec60214da7550dfcd4ef93745f6f0096129676a" +dependencies = [ + "bitflags", + "libc", + "libpulse-sys", + "num-derive", + "num-traits", + "winapi", +] + +[[package]] +name = "libpulse-simple-binding" +version = "2.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6a22538257c4d522bea6089d6478507f5d2589ea32150e20740aaaaaba44590" +dependencies = [ + "libpulse-binding", + "libpulse-simple-sys", + "libpulse-sys", +] + +[[package]] +name = "libpulse-simple-sys" +version = "1.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b8b0fcb9665401cc7c156c337c8edc7eb4e797b9d3ae1667e1e9e17b29e0c7c" +dependencies = [ + "libpulse-sys", + "pkg-config", +] + +[[package]] +name = "libpulse-sys" +version = "1.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f12950b69c1b66233a900414befde36c8d4ea49deec1e1f34e4cd2f586e00c7d" +dependencies = [ + "libc", + "num-derive", + "num-traits", + "pkg-config", + "winapi", +] + +[[package]] +name = "libpulse_aubio" +version = "0.1.0" +dependencies = [ + "anyhow", + "aubio", + "libpulse-binding", + "libpulse-simple-binding", +] + +[[package]] +name = "num-derive" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "num-traits" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +dependencies = [ + "autocfg", +] + +[[package]] +name = "pkg-config" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" + +[[package]] +name = "proc-macro2" +version = "1.0.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9f5105d4fdaab20335ca9565e106a5d9b82b6219b5ba735731124ac6711d23d" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "syn" +version = "1.0.76" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6f107db402c2c2055242dbf4d2af0e69197202e9faacbef9571bbe47f5a1b84" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "unicode-xid" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/libpulse_aubio/Cargo.toml b/libpulse_aubio/Cargo.toml new file mode 100644 index 0000000..573f3b8 --- /dev/null +++ b/libpulse_aubio/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "libpulse_aubio" +version = "0.1.0" +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +aubio = "0.2.1" +pulse = { version = "2.23.1", package = "libpulse-binding" } +psimple = { version = "2.23.0", package = "libpulse-simple-binding" } +anyhow = "1.0.44" diff --git a/libpulse_aubio/src/main.rs b/libpulse_aubio/src/main.rs new file mode 100644 index 0000000..58057cb --- /dev/null +++ b/libpulse_aubio/src/main.rs @@ -0,0 +1,56 @@ +use anyhow::Result; +use psimple::Simple; +use pulse::sample::{Format, Spec}; +use pulse::stream::Direction; + +const BUF_SIZE: usize = 1024; +const HOP_SIZE: usize = 512; +const SAMPLE_RATE: u32 = 44100; + +fn main() -> Result<()> { + let spec = Spec { + format: Format::F32le, + channels: 2, + rate: 44100, + }; + assert!(spec.is_valid()); + + let s = Simple::new( + None, + "AAAAAAAA", + Direction::Record, + None, + "BBBBBBBB", + &spec, + None, + None, + )?; + + let mut tempo = aubio::Tempo::new(aubio::OnsetMode::SpecFlux, BUF_SIZE, HOP_SIZE, SAMPLE_RATE)?; + + let mut data = [0u8; 4 * BUF_SIZE]; + let mut float_data = [0f32; BUF_SIZE]; + + loop { + s.read(&mut data)?; + + for (i, f) in float_data.iter_mut().enumerate() { + let mut float_bytes = [0u8; 4]; + float_bytes.copy_from_slice(&data[4 * i..4 * i + 4]); + *f = f32::from_le_bytes(float_bytes); + } + + let r = tempo.do_result(&float_data)?; + + if r > 0f32 { + println!( + "{}ms, {}s, frame {}, {} bpm, confidence {}", + tempo.get_last_ms(), + tempo.get_last_s(), + tempo.get_last(), + tempo.get_bpm(), + tempo.get_confidence() + ); + } + } +}