use std::{
cell::RefCell,
marker::PhantomData,
rc::Rc,
sync::{Arc, RwLock},
};
use fxhash::{FxHashMap, FxHashSet};
use num_traits::Float;
use rustfft::{FftPlanner, num_complex::Complex};
use crate::{
audio_buffer::{AudioBuffer, AudioBufferInterleaved, AudioChannelLayout},
audio_math::AudioFilter,
backend::{AudioHost, Device, RawAudioStream},
float_type::FloatType,
resampler::{Resampler, ResamplerQuality},
};
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum AudioEffectState {
ProcessOk,
ProcessError,
ParamNoEntry,
ParamStrInvalid(String),
EffectOk,
EffectResetFailed,
EffectAlreadyExists,
EffectNoEntry,
}
#[derive(Debug, Clone)]
pub enum EffectParamValue<'a> {
U8(u8),
U16(u16),
U32(u32),
U64(u64),
I8(i8),
I16(i16),
I32(i32),
I64(i64),
F32(f32),
F64(f64),
Str(&'a str),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum EffectParamType {
U8,
U16,
U32,
U64,
I8,
I16,
I32,
I64,
F32,
F64,
Str,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum AudioStreamState {
Ok,
Err,
Silence,
Other(String),
}
#[derive(Debug, Clone)]
pub struct AudioAnalysis {
pub name: String,
pub avg_volume_db: f32,
pub clippings: usize,
pub clipping_ratio: f32,
pub analysis: Vec<f32>,
}
pub type ParamPropDesk<'a, const N: usize> = [(&'a str, EffectParamType); N];
pub trait AudioEffectTrait<T: FloatType> {
fn process(&mut self, input: &mut AudioBuffer<T>) -> AudioEffectState;
fn get_param(&mut self, name: &str) -> Result<EffectParamValue, AudioEffectState>;
fn set_param(&mut self, name: &str, value: EffectParamValue) -> AudioEffectState;
fn reset(&mut self) -> AudioEffectState;
fn set_sample_rate(&mut self, sample_rate: f32);
}
#[derive(Debug, Clone)]
pub struct AudioStreamContext {
pub timestamp: f64,
pub sample_rate: u32,
}
pub trait AudioStreamFeederTrait<T: FloatType + Float> {
fn process(
&mut self,
context: &AudioStreamContext,
input: &mut AudioBuffer<T>,
) -> AudioStreamState;
}
pub trait AudioEffectImpl<T: FloatType + Float>: Sized {
fn new<const N: usize>(
name: &str,
param_props: ParamPropDesk<N>,
proc: Box<dyn AudioEffectTrait<T>>,
) -> AudioEffect<T>;
fn get_name(&self) -> &str;
fn get_params(&self) -> &FxHashMap<String, EffectParamType>;
fn set_param(&mut self, name: &str, value: EffectParamValue) -> AudioEffectState;
fn get_param(&self, name: &str) -> Result<EffectParamValue, AudioEffectState>;
fn use_filter_in(&mut self, use_filter: bool);
fn use_filter_out(&mut self, use_filter: bool);
fn is_using_filter_in(&self) -> bool;
fn is_using_filter_out(&self) -> bool;
fn set_mix(&mut self, new_mix: f32);
fn get_mix(&self) -> f32;
fn set_low_cut_in(&mut self, cut: f32);
fn get_low_cut_in(&self) -> f32;
fn set_high_cut_in(&mut self, cut: f32);
fn get_high_cut_in(&self) -> f32;
fn set_low_cut_out(&mut self, cut: f32);
fn get_low_cut_out(&self) -> f32;
fn set_high_cut_out(&mut self, cut: f32);
fn get_high_cut_out(&self) -> f32;
}
pub trait AudioProcessorImpl<T: FloatType + Float>: Sized {
fn new(sample_rate: f32, buffer_size: usize) -> AudioProcessor<T>;
fn set_mix(&mut self, mix: f32);
fn get_mix(&self) -> f32;
fn use_filter(&mut self, use_filter: bool);
fn is_using_filter(&self) -> bool;
fn set_low_cut(&mut self, low_cut: f32);
fn get_low_cut(&self) -> f32;
fn set_high_cut(&mut self, high_cut: f32);
fn get_high_cut(&self) -> f32;
fn set_sample_rate(&mut self, sample_rate: f32);
fn get_sample_rate(&self) -> f32;
fn add_effect(&mut self, effect: AudioEffect<T>) -> AudioEffectState;
fn remove_effect(&mut self, name: &str) -> Result<AudioEffect<T>, AudioEffectState>;
fn move_effect(&mut self, from: usize, to: usize);
fn get_effect(&self, name: &str) -> Result<AudioEffect<T>, AudioEffectState>;
fn connect_analyser(&mut self, anal: Rc<RefCell<AudioAnalyser<T>>>);
fn disconnect_analyser(&mut self) -> Option<Rc<RefCell<AudioAnalyser<T>>>>;
}
#[derive(Debug, Clone)]
pub struct AudioStreamSettings {
pub sample_rate: u32,
pub channel_layout: AudioChannelLayout,
}
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub enum AudioMasterError {
NoDeviceAvailable,
StreamNotInitialized,
Internal(String),
}
pub trait AudioMasterImpl {
fn new() -> AudioMaster;
fn new_with_buffer_size(buffer_size: usize) -> AudioMaster;
fn new_with_fps(fps: usize) -> AudioMaster;
fn stop_sys_stream(&mut self) -> Result<(), AudioMasterError>;
fn start_sys_stream(&mut self) -> Result<(), AudioMasterError>;
fn try_to_initialize_stream(&mut self) -> Result<(), AudioMasterError>;
fn devices(&self) -> Vec<Device>;
fn get_current_device(&self) -> Option<Device>;
fn change_device(&self, device_id: usize) -> Result<(), AudioMasterError>;
fn create_stream_f32(
&mut self,
settings: &AudioStreamSettings,
feeder: Box<dyn AudioStreamFeederTrait<f32>>,
) -> AudioStream<f32>;
fn create_stream_f64(
&mut self,
settings: &AudioStreamSettings,
feeder: Box<dyn AudioStreamFeederTrait<f64>>,
) -> AudioStream<f64>;
}
pub trait AudioStreamImpl<T: FloatType + Float> {
fn use_normalization(&mut self, norm: bool);
fn is_using_normalization(&self) -> bool;
fn get_timestamp(&self) -> f64;
fn get_resample_quality(&self) -> ResamplerQuality;
fn set_resample_quality(&mut self, quality: ResamplerQuality);
fn get_speed(&self) -> f32;
fn set_speed(&mut self, speed: f32);
fn get_volume(&self) -> f32;
fn set_volume(&self, volume: f32);
fn use_filter(&mut self, filter: bool);
fn is_using_filter(&self) -> bool;
fn get_low_cut(&self) -> f32;
fn set_low_cut(&mut self, low_cut: f32);
fn get_high_cut(&self) -> f32;
fn set_high_cut(&mut self, high_cut: f32);
fn get_sample_rate(&self) -> f32;
fn set_sample_rate(&mut self, sample_rate: f32);
fn get_channel_layout(&self) -> AudioChannelLayout;
fn set_channel_layout(&mut self, layout: AudioChannelLayout);
fn get_processor(&self) -> AudioProcessor<T>;
fn resume(&mut self);
fn pause(&mut self);
}
#[derive(Clone)]
pub struct AudioEffect<T: FloatType + Float> {
pub(super) inner: Arc<RwLock<AudioEffectInner<T>>>,
}
#[derive(Clone)]
pub struct AudioMaster {
pub(super) inner: Arc<RwLock<AudioMasterInner>>,
}
#[derive(Clone)]
pub struct AudioStream<T: FloatType + Float> {
pub(super) inner: Arc<RwLock<AudioStreamInner<T>>>,
}
#[derive(Clone)]
pub struct AudioProcessor<T: FloatType + Float> {
pub(super) inner: Arc<RwLock<AudioProcessorInner<T>>>,
}
pub trait AudioProcessorPrivateImpl<T: FloatType + Float>: Sized {
fn process(&mut self, input: &mut AudioBuffer<T>) -> AudioEffectState;
fn set_effects_sample_rate(&mut self, sample_rate: f32);
fn anal_start_sequence(anal: &Option<Rc<RefCell<AudioAnalyser<T>>>>, size: usize);
fn anal_end_sequence(anal: &Option<Rc<RefCell<AudioAnalyser<T>>>>);
fn analyze_next_node(
anal: &Option<Rc<RefCell<AudioAnalyser<T>>>>,
name: &str,
input: &AudioBuffer<T>,
);
fn set_buffer_size(&mut self, new_len: usize);
}
pub trait AudioStreamPrivateImpl<T: FloatType + Float>: Sized {
fn factory(
feeder: Box<dyn AudioStreamFeederTrait<T>>,
sample_rate: u32,
channel_layout: AudioChannelLayout,
) -> Self;
fn process(&mut self, input: &mut AudioBuffer<T>);
fn pre_process(&mut self);
fn post_process(&mut self, input: &mut AudioBuffer<T>);
fn clear_buffers(&mut self);
fn set_buffer_size(&mut self, new_buff_size: usize);
}
pub trait AudioEffectPrivateImpl<T: FloatType + Float>: Sized {
fn process(&mut self, input: &mut AudioBuffer<T>) -> AudioEffectState;
fn set_sample_rate(&mut self, sample_rate: f32);
fn resize(&mut self, new_len: usize);
}
pub trait AudioAnalyserPrivateImpl<T: FloatType>: Sized {
fn resize(&mut self, new_len: usize);
fn calc_volume_and_clippings(&mut self);
fn analyze(&mut self);
fn start_sequence(&mut self, size: usize);
fn end_sequence(&mut self);
fn process_next_node(&mut self, name: &str, input: &AudioBuffer<T>);
}
pub trait AudioAnalysisPrivateImpl: Sized {
fn new(len: usize) -> AudioAnalysis;
}
#[derive(Clone)]
pub struct MainStreamFeeder<T> {
pub(super) master: Arc<RwLock<AudioMasterInner>>,
pub(super) _phantom: PhantomData<T>,
}
#[derive(Debug, Clone)]
pub struct ParamProp {
pub(super) name: String,
pub(super) _type: EffectParamType,
}
pub trait AudioMasterPrivateImpl: Sized {
fn factory(
host: AudioHost,
device: Device,
buffer_size: Option<usize>,
frame_rate: Option<usize>,
) -> Arc<RwLock<Self>>;
fn try_to_create_default(
buffer_size: Option<usize>,
frame_rate: Option<usize>,
) -> Option<Arc<RwLock<Self>>>;
}
pub struct AudioMasterInner {
pub(super) host: AudioHost,
pub(super) current_device: Option<Device>,
pub(super) streams_f32: Vec<(AudioBuffer<f32>, Arc<RwLock<AudioStreamInner<f32>>>)>,
pub(super) streams_f64: Vec<(AudioBuffer<f64>, Arc<RwLock<AudioStreamInner<f64>>>)>,
pub(super) main_stream: Option<RawAudioStream<f32>>,
}
pub struct AudioStreamInner<T: FloatType + Float> {
pub(super) feeder: Box<dyn AudioStreamFeederTrait<T>>,
pub(super) sample_rate: f32,
pub(super) speed: f32,
pub(super) volume: f32,
pub(super) resample_factor: f64,
pub(super) channel_layout: AudioChannelLayout,
pub(super) buffer_resampled: AudioBufferInterleaved<T>,
pub(super) buffer: AudioBufferInterleaved<T>,
pub(super) cb_buffer: AudioBuffer<T>,
pub(super) resampled_buffer_pos: usize,
pub(super) resampled_buffer_len: usize,
pub(super) use_filter: bool,
pub(super) use_normalization: bool,
pub(super) use_processor: bool,
pub(super) processor: AudioProcessor<T>,
pub(super) filter: AudioFilter<T>,
pub(super) resampler: Resampler<T>,
pub(super) timestamp: f64,
pub(super) is_paused: bool,
}
pub struct AudioEffectInner<T: FloatType + Float> {
pub(super) name: String,
pub(super) params: FxHashMap<String, EffectParamType>,
pub(super) processor: Box<dyn AudioEffectTrait<T>>,
pub(super) buffer: AudioBuffer<T>,
pub(super) mix: f32,
pub(super) sample_rate: f32,
pub(super) filter_in: AudioFilter<T>,
pub(super) filter_out: AudioFilter<T>,
pub(super) use_filter_in: bool,
pub(super) use_filter_out: bool,
pub(super) is_muffled: bool,
}
pub struct AudioProcessorInner<T: FloatType + Float> {
pub(super) effects: FxHashSet<String>,
pub(super) effects_seq: Vec<AudioEffect<T>>,
pub(super) buffer: AudioBuffer<T>,
pub(super) analyser: Option<Rc<RefCell<AudioAnalyser<T>>>>,
pub(super) filter: AudioFilter<T>,
pub(super) use_filter: bool,
pub(super) sample_rate: f32,
pub(super) mix: f32,
}
pub struct AudioAnalyser<T: FloatType> {
pub(super) planner: FftPlanner<f32>,
pub(super) signal: Vec<Complex<f32>>,
pub(super) mixed: Vec<T>,
pub(super) anals: Vec<AudioAnalysis>,
pub(super) user_cb: Box<dyn FnMut(&[AudioAnalysis]) + 'static>,
pub(super) seq_size: usize,
pub(super) seq_index: usize,
pub(super) seq_started: bool,
}