#[doc(hidden)]
#[cxx::bridge]
pub mod ffi {
unsafe extern "C++" {
include!("libkeyfinder-sys/src/bridge.h");
#[namespace = "keyfinder_bridge"]
type KeyFinderWrapper;
#[namespace = "keyfinder_bridge"]
type AudioDataWrapper;
#[namespace = "keyfinder_bridge"]
fn new_keyfinder() -> UniquePtr<KeyFinderWrapper>;
#[namespace = "keyfinder_bridge"]
fn new_audiodata() -> UniquePtr<AudioDataWrapper>;
#[namespace = "keyfinder_bridge"]
fn key_of_audio(kf: Pin<&mut KeyFinderWrapper>, audio: &AudioDataWrapper) -> u32;
#[namespace = "keyfinder_bridge"]
fn set_frame_rate(audio: Pin<&mut AudioDataWrapper>, frame_rate: u32);
#[namespace = "keyfinder_bridge"]
fn set_channels(audio: Pin<&mut AudioDataWrapper>, channels: u32);
#[namespace = "keyfinder_bridge"]
fn get_channels(audio: &AudioDataWrapper) -> u32;
#[namespace = "keyfinder_bridge"]
fn get_frame_rate(audio: &AudioDataWrapper) -> u32;
#[namespace = "keyfinder_bridge"]
fn get_sample_count(audio: &AudioDataWrapper) -> u32;
#[namespace = "keyfinder_bridge"]
fn get_frame_count(audio: &AudioDataWrapper) -> u32;
#[namespace = "keyfinder_bridge"]
fn add_to_sample_count(audio: Pin<&mut AudioDataWrapper>, samples: u32);
#[namespace = "keyfinder_bridge"]
fn reset_iterators(audio: Pin<&mut AudioDataWrapper>);
#[namespace = "keyfinder_bridge"]
fn advance_write_iterator(audio: Pin<&mut AudioDataWrapper>, by: u32);
#[namespace = "keyfinder_bridge"]
fn set_sample_at_write_iterator(audio: Pin<&mut AudioDataWrapper>, sample: f32);
#[namespace = "keyfinder_bridge"]
fn reduce_to_mono(audio: Pin<&mut AudioDataWrapper>);
#[namespace = "keyfinder_bridge"]
fn downsample(audio: Pin<&mut AudioDataWrapper>, factor: u32);
}
}
#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum KeyFinderKey {
AMajor = 0,
AMinor = 1,
BFlatMajor = 2,
BFlatMinor = 3,
BMajor = 4,
BMinor = 5,
CMajor = 6,
CMinor = 7,
DFlatMajor = 8,
DFlatMinor = 9,
DMajor = 10,
DMinor = 11,
EFlatMajor = 12,
EFlatMinor = 13,
EMajor = 14,
EMinor = 15,
FMajor = 16,
FMinor = 17,
GFlatMajor = 18,
GFlatMinor = 19,
GMajor = 20,
GMinor = 21,
AFlatMajor = 22,
AFlatMinor = 23,
Silence = 24,
}
impl KeyFinderKey {
fn from_u32(value: u32) -> Self {
if value <= 24 {
unsafe { std::mem::transmute(value) }
} else {
KeyFinderKey::Silence
}
}
}
pub struct KeyFinder {
inner: cxx::UniquePtr<ffi::KeyFinderWrapper>,
}
impl KeyFinder {
pub fn new() -> Self {
Self {
inner: ffi::new_keyfinder(),
}
}
pub fn key_of_audio(&mut self, audio: &AudioData) -> KeyFinderKey {
let value = ffi::key_of_audio(self.inner.pin_mut(), &audio.inner);
KeyFinderKey::from_u32(value)
}
}
impl Default for KeyFinder {
fn default() -> Self {
Self::new()
}
}
pub struct AudioData {
inner: cxx::UniquePtr<ffi::AudioDataWrapper>,
}
impl AudioData {
pub fn new() -> Self {
Self {
inner: ffi::new_audiodata(),
}
}
pub fn set_frame_rate(&mut self, frame_rate: u32) {
ffi::set_frame_rate(self.inner.pin_mut(), frame_rate);
}
pub fn frame_rate(&self) -> u32 {
ffi::get_frame_rate(&self.inner)
}
pub fn set_channels(&mut self, channels: u32) {
ffi::set_channels(self.inner.pin_mut(), channels);
}
pub fn channels(&self) -> u32 {
ffi::get_channels(&self.inner)
}
pub fn sample_count(&self) -> u32 {
ffi::get_sample_count(&self.inner)
}
pub fn frame_count(&self) -> u32 {
ffi::get_frame_count(&self.inner)
}
pub fn reduce_to_mono(&mut self) {
ffi::reduce_to_mono(self.inner.pin_mut());
}
pub fn downsample(&mut self, factor: u32) {
ffi::downsample(self.inner.pin_mut(), factor);
}
}
impl Default for AudioData {
fn default() -> Self {
Self::new()
}
}
impl Extend<f32> for AudioData {
fn extend<T: IntoIterator<Item = f32>>(&mut self, iter: T) {
let samples: Vec<f32> = iter.into_iter().collect();
if samples.is_empty() {
return;
}
let old_count = self.sample_count();
ffi::add_to_sample_count(self.inner.pin_mut(), samples.len() as u32);
ffi::reset_iterators(self.inner.pin_mut());
ffi::advance_write_iterator(self.inner.pin_mut(), old_count);
for &sample in &samples {
ffi::set_sample_at_write_iterator(self.inner.pin_mut(), sample);
ffi::advance_write_iterator(self.inner.pin_mut(), 1);
}
}
}
impl FromIterator<f32> for AudioData {
fn from_iter<T: IntoIterator<Item = f32>>(iter: T) -> Self {
let mut audio = AudioData::new();
audio.extend(iter);
audio
}
}