#[cfg(feature = "envelopes")]
use crate::{NdResult, operations::dynamic_range::EnvelopeFollower};
#[cfg(feature = "envelopes")]
use crate::operations::types::DynamicRangeMethod;
#[cfg(feature = "editing")]
use crate::operations::types::{FadeCurve, PadSide};
#[cfg(feature = "iir-filtering")]
use crate::AudioSample;
#[cfg(all(
feature = "editing",
feature = "random-generation",
feature = "iir-filtering"
))]
use crate::operations::types::PerturbationConfig;
#[cfg(feature = "channels")]
use crate::operations::types::{MonoConversionMethod, StereoConversionMethod};
#[cfg(feature = "processing")]
use crate::operations::types::NormalizationConfig;
#[cfg(all(feature = "processing", feature = "resampling"))]
use crate::{operations::types::ResamplingQuality, repr::SampleRate};
#[cfg(feature = "decomposition")]
use crate::operations::hpss::HpssConfig;
#[cfg(feature = "onset-detection")]
use crate::operations::onset::{
ComplexOnsetConfig, OnsetDetectionConfig, SpectralFluxConfig, SpectralFluxMethod,
};
#[cfg(feature = "parametric-eq")]
use crate::operations::types::{EqBand, ParametricEq};
#[cfg(feature = "beat-tracking")]
use crate::operations::beat::{BeatTrackingConfig, BeatTrackingData};
#[cfg(feature = "vad")]
use crate::operations::types::VadConfig;
#[cfg(feature = "dynamic-range")]
use crate::operations::types::{CompressorConfig, LimiterConfig};
#[cfg(feature = "pitch-analysis")]
use crate::operations::types::PitchDetectionMethod;
#[cfg(feature = "iir-filtering")]
use crate::operations::types::{FilterResponse, IirFilterDesign};
#[cfg(feature = "transforms")]
use spectrograms::{
AmpScaleSpec, ChromaParams, Chromagram, CqtDbSpectrogram, CqtMagnitudeSpectrogram, CqtParams,
CqtPowerSpectrogram, CqtResult, CqtSpectrogram, Decibels, Gammatone, GammatoneDbSpectrogram,
GammatoneMagnitudeSpectrogram, GammatoneParams, GammatonePowerSpectrogram, LinearDbSpectrogram,
LinearHz, LinearMagnitudeSpectrogram, LinearPowerSpectrogram, LogHz, LogHzDbSpectrogram,
LogHzMagnitudeSpectrogram, LogHzParams, LogHzPowerSpectrogram, LogMelSpectrogram, LogParams,
Magnitude, MelMagnitudeSpectrogram, MelParams, MelPowerSpectrogram, MelSpectrogram, Mfcc,
MfccParams, Power, Spectrogram, SpectrogramParams, StftParams, StftResult,
};
#[cfg(any(feature = "transforms", feature = "onset-detection"))]
use ndarray::{Array2, Zip};
#[cfg(feature = "pitch-analysis")]
use spectrograms::WindowType;
#[cfg(feature = "plotting")]
use crate::operations::{
WaveformPlot, WaveformPlotParams,
plotting::spectrograms::{SpectrogramPlot, SpectrogramPlotParams},
plotting::spectrum::{MagnitudeSpectrumParams, MagnitudeSpectrumPlot},
};
#[cfg(any(feature = "transforms", feature = "onset-detection"))]
use num_complex::Complex;
#[allow(unused_imports)]
use crate::{AudioSampleResult, AudioSamples, AudioTypeConversion, StandardSample};
#[allow(unused_imports)]
use non_empty_slice::{NonEmptySlice, NonEmptyVec};
#[allow(unused_imports)]
use std::num::NonZeroUsize;
#[cfg(feature = "statistics")]
pub trait AudioStatistics: AudioTypeConversion
where
Self::Sample: StandardSample,
{
fn peak(&self) -> Self::Sample;
#[inline]
fn amplitude(&self) -> Self::Sample {
self.peak()
}
fn min_sample(&self) -> Self::Sample;
fn max_sample(&self) -> Self::Sample;
fn mean(&self) -> f64;
fn median(&self) -> Option<f64>;
fn rms(&self) -> f64;
fn rms_and_peak(&self) -> (f64, Self::Sample) {
(self.rms(), self.peak())
}
fn variance(&self) -> f64;
fn std_dev(&self) -> f64;
fn zero_crossings(&self) -> usize;
fn zero_crossing_rate(&self) -> f64;
fn cross_correlation(
&self,
other: &Self,
max_lag: NonZeroUsize,
) -> AudioSampleResult<NonEmptyVec<f64>>;
#[cfg(feature = "transforms")]
fn spectral_centroid(&self) -> AudioSampleResult<f64>;
#[cfg(feature = "transforms")]
fn autocorrelation(&self, max_lag: NonZeroUsize) -> Option<NonEmptyVec<f64>>;
#[cfg(feature = "transforms")]
fn spectral_rolloff(&self, rolloff_percent: f64) -> AudioSampleResult<f64>;
}
#[cfg(feature = "vad")]
pub trait AudioVoiceActivityDetection: AudioTypeConversion
where
Self::Sample: StandardSample,
{
fn voice_activity_mask(&self, config: &VadConfig) -> AudioSampleResult<NonEmptyVec<bool>>;
fn speech_regions(&self, config: &VadConfig) -> AudioSampleResult<Vec<(usize, usize)>>;
}
#[cfg(feature = "processing")]
pub trait AudioProcessing: AudioTypeConversion
where
Self::Sample: StandardSample,
{
fn normalize(self, config: NormalizationConfig<Self::Sample>) -> AudioSampleResult<Self>;
#[must_use]
fn scale(self, factor: f64) -> Self;
fn apply_window(self, window: &NonEmptySlice<Self::Sample>) -> AudioSampleResult<Self>;
fn apply_filter(self, filter_coeffs: &NonEmptySlice<Self::Sample>) -> AudioSampleResult<Self>;
fn mu_compress(self, mu: Self::Sample) -> AudioSampleResult<Self>;
fn mu_expand(self, mu: Self::Sample) -> AudioSampleResult<Self>;
fn low_pass_filter(self, cutoff_hz: f64) -> AudioSampleResult<Self>;
fn high_pass_filter(self, cutoff_hz: f64) -> AudioSampleResult<Self>;
fn band_pass_filter(self, low_cutoff_hz: f64, high_cutoff_hz: f64) -> AudioSampleResult<Self>;
fn remove_dc_offset(self) -> AudioSampleResult<Self>;
fn clip(self, min_val: Self::Sample, max_val: Self::Sample) -> AudioSampleResult<Self>;
fn clip_in_place(
&mut self,
min_val: Self::Sample,
max_val: Self::Sample,
) -> AudioSampleResult<()>;
#[cfg(feature = "resampling")]
fn resample(
&self,
target_sample_rate: SampleRate,
quality: ResamplingQuality,
) -> AudioSampleResult<AudioSamples<'static, Self::Sample>>;
#[cfg(feature = "resampling")]
fn resample_by_ratio(
&self,
ratio: f64,
quality: ResamplingQuality,
) -> AudioSampleResult<AudioSamples<'static, Self::Sample>>;
}
#[cfg(feature = "transforms")]
pub trait AudioTransforms: AudioTypeConversion
where
Self::Sample: StandardSample,
{
fn fft(&self, n_fft: NonZeroUsize) -> AudioSampleResult<Array2<Complex<f64>>>;
#[inline]
fn rfft(&self, n_fft: NonZeroUsize) -> AudioSampleResult<Array2<f64>> {
let fft_complex = self.fft(n_fft)?;
Ok(fft_complex.mapv(Complex::norm))
}
fn stft(&self, params: &StftParams) -> AudioSampleResult<StftResult>;
fn istft(stft: StftResult) -> AudioSampleResult<AudioSamples<'static, Self::Sample>>;
fn linear_spectrogram<AmpScale>(
&self,
params: &SpectrogramParams,
db: Option<&LogParams>,
) -> AudioSampleResult<Spectrogram<LinearHz, AmpScale>>
where
AmpScale: AmpScaleSpec;
#[inline]
fn linear_magnitude_spectrogram(
&self,
params: &SpectrogramParams,
) -> AudioSampleResult<LinearMagnitudeSpectrogram> {
self.linear_spectrogram::<Magnitude>(params, None)
}
#[inline]
fn linear_power_spectrogram(
&self,
params: &SpectrogramParams,
) -> AudioSampleResult<LinearPowerSpectrogram> {
self.linear_spectrogram::<Power>(params, None)
}
#[inline]
fn linear_db_spectrogram(
&self,
params: &SpectrogramParams,
db: &LogParams,
) -> AudioSampleResult<LinearDbSpectrogram> {
self.linear_spectrogram::<Decibels>(params, Some(db))
}
fn log_frequency_spectrogram<AmpScale>(
&self,
params: &SpectrogramParams,
loghz: &LogHzParams,
db: Option<&LogParams>,
) -> AudioSampleResult<Spectrogram<LogHz, AmpScale>>
where
AmpScale: AmpScaleSpec;
#[inline]
fn loghz_power_spectrogram(
&self,
params: &SpectrogramParams,
loghz: &LogHzParams,
) -> AudioSampleResult<LogHzPowerSpectrogram> {
self.log_frequency_spectrogram::<Power>(params, loghz, None)
}
#[inline]
fn loghz_magnitude_spectrogram(
&self,
params: &SpectrogramParams,
loghz: &LogHzParams,
) -> AudioSampleResult<LogHzMagnitudeSpectrogram> {
self.log_frequency_spectrogram::<Magnitude>(params, loghz, None)
}
#[inline]
fn loghz_db_spectrogram(
&self,
params: &SpectrogramParams,
loghz: &LogHzParams,
db: &LogParams,
) -> AudioSampleResult<LogHzDbSpectrogram> {
self.log_frequency_spectrogram::<Decibels>(params, loghz, Some(db))
}
fn mel_spectrogram<AmpScale>(
&self,
params: &SpectrogramParams,
mel: &MelParams,
db: Option<&LogParams>, ) -> AudioSampleResult<MelSpectrogram<AmpScale>>
where
AmpScale: AmpScaleSpec;
#[inline]
fn mel_mag_spectrogram(
&self,
params: &SpectrogramParams,
mel: &MelParams,
) -> AudioSampleResult<MelMagnitudeSpectrogram> {
self.mel_spectrogram(params, mel, None)
}
#[inline]
fn mel_db_spectrogram(
&self,
params: &SpectrogramParams,
mel: &MelParams,
db: &LogParams,
) -> AudioSampleResult<LogMelSpectrogram> {
self.mel_spectrogram(params, mel, Some(db))
}
#[inline]
fn mel_power_spectrogram(
&self,
params: &SpectrogramParams,
mel: &MelParams,
) -> AudioSampleResult<MelPowerSpectrogram> {
self.mel_spectrogram(params, mel, None)
}
fn mfcc(
&self,
stft_params: &StftParams,
n_mels: NonZeroUsize,
mfcc_params: &MfccParams,
) -> AudioSampleResult<Mfcc>;
fn chromagram(
&self,
stft_params: &StftParams,
cfg: &ChromaParams,
) -> AudioSampleResult<Chromagram>;
fn power_spectral_density(
&self,
window_size: NonZeroUsize,
overlap: f64,
) -> AudioSampleResult<(Vec<f64>, Vec<f64>)>;
fn gammatone_spectrogram<AmpScale>(
&self,
params: &SpectrogramParams,
gammatone_params: &GammatoneParams,
db: Option<&LogParams>,
) -> AudioSampleResult<Spectrogram<Gammatone, AmpScale>>
where
AmpScale: AmpScaleSpec;
#[inline]
fn gammatone_magnitude_spectrogram(
&self,
params: &SpectrogramParams,
gammatone_params: &GammatoneParams,
) -> AudioSampleResult<GammatoneMagnitudeSpectrogram> {
self.gammatone_spectrogram::<Magnitude>(params, gammatone_params, None)
}
#[inline]
fn gammatone_power_spectrogram(
&self,
params: &SpectrogramParams,
gammatone_params: &GammatoneParams,
) -> AudioSampleResult<GammatonePowerSpectrogram> {
self.gammatone_spectrogram::<Power>(params, gammatone_params, None)
}
#[inline]
fn gammatone_db_spectrogram(
&self,
params: &SpectrogramParams,
gammatone_params: &GammatoneParams,
db: &LogParams,
) -> AudioSampleResult<GammatoneDbSpectrogram> {
self.gammatone_spectrogram::<Decibels>(params, gammatone_params, Some(db))
}
fn constant_q_transform(
&self,
params: &CqtParams,
hop_size: NonZeroUsize,
) -> AudioSampleResult<CqtResult>;
fn cqt_spectrogram<AmpScale>(
&self,
params: &SpectrogramParams,
cqt: &CqtParams,
db: Option<&LogParams>,
) -> AudioSampleResult<CqtSpectrogram<AmpScale>>
where
AmpScale: AmpScaleSpec;
#[inline]
fn cqt_magnitude_spectrogram(
&self,
params: &SpectrogramParams,
cqt: &CqtParams,
) -> AudioSampleResult<CqtMagnitudeSpectrogram> {
self.cqt_spectrogram::<Magnitude>(params, cqt, None)
}
#[inline]
fn cqt_power_spectrogram(
&self,
params: &SpectrogramParams,
cqt: &CqtParams,
) -> AudioSampleResult<CqtPowerSpectrogram> {
self.cqt_spectrogram::<Power>(params, cqt, None)
}
#[inline]
fn cqt_db_spectrogram(
&self,
params: &SpectrogramParams,
cqt: &CqtParams,
db: &LogParams,
) -> AudioSampleResult<CqtDbSpectrogram> {
self.cqt_spectrogram::<Decibels>(params, cqt, Some(db))
}
#[inline]
#[must_use]
fn magphase(
complex_spect: &Array2<Complex<f64>>,
power: Option<NonZeroUsize>,
) -> (Array2<f64>, Array2<Complex<f64>>) {
let mut mag = complex_spect.mapv(num_complex::Complex::norm);
let zeros_to_ones = mag.mapv(|x| if x == 0.0 { 1.0 } else { 0.0 });
let mag_nonzero = &mag + &zeros_to_ones;
let mut phase = complex_spect.clone();
let power = power.map_or(1.0, |p| p.get() as f64);
Zip::from(&mut phase)
.and(&mag_nonzero)
.and(&zeros_to_ones)
.for_each(|p, &m_nz, &z| {
let div = Complex {
re: p.re / m_nz + z, im: p.im / m_nz,
};
*p = div;
});
mag.mapv_inplace(|x| x.powf(power));
(mag, phase)
}
}
#[cfg(feature = "pitch-analysis")]
pub trait AudioPitchAnalysis: AudioTypeConversion
where
Self::Sample: StandardSample,
{
fn detect_pitch_yin(
&self,
threshold: f64,
min_frequency: f64,
max_frequency: f64,
) -> AudioSampleResult<Option<f64>>;
fn detect_pitch_autocorr(
&self,
min_frequency: f64,
max_frequency: f64,
) -> AudioSampleResult<Option<f64>>;
fn track_pitch(
&self,
window_size: NonZeroUsize,
hop_size: NonZeroUsize,
method: PitchDetectionMethod,
threshold: f64,
min_frequency: f64,
max_frequency: f64,
) -> AudioSampleResult<Vec<(f64, Option<f64>)>>;
fn harmonic_to_noise_ratio(
&self,
fundamental_freq: f64,
num_harmonics: NonZeroUsize,
n_fft: Option<NonZeroUsize>,
window_type: Option<WindowType>,
) -> AudioSampleResult<f64>;
fn harmonic_analysis(
&self,
fundamental_freq: f64,
num_harmonics: NonZeroUsize,
tolerance: f64,
n_fft: Option<NonZeroUsize>,
window_type: Option<WindowType>,
) -> AudioSampleResult<Vec<f64>>;
fn estimate_key(&self, stft_params: &StftParams) -> AudioSampleResult<(usize, f64)>;
}
#[cfg(feature = "iir-filtering")]
pub trait AudioIirFiltering: AudioTypeConversion
where
Self::Sample: AudioSample,
{
fn apply_iir_filter(&mut self, design: &IirFilterDesign) -> AudioSampleResult<()>;
fn butterworth_lowpass(
&mut self,
order: NonZeroUsize,
cutoff_frequency: f64,
) -> AudioSampleResult<()>;
fn butterworth_highpass(
&mut self,
order: NonZeroUsize,
cutoff_frequency: f64,
) -> AudioSampleResult<()>;
fn butterworth_bandpass(
&mut self,
order: NonZeroUsize,
low_frequency: f64,
high_frequency: f64,
) -> AudioSampleResult<()>;
fn chebyshev_i(
&mut self,
order: NonZeroUsize,
cutoff_frequency: f64,
passband_ripple: f64,
response: FilterResponse,
) -> AudioSampleResult<()>;
fn frequency_response(&self, frequencies: &[f64]) -> AudioSampleResult<(Vec<f64>, Vec<f64>)>;
}
#[cfg(feature = "parametric-eq")]
pub trait AudioParametricEq: AudioChannelOps
where
Self::Sample: StandardSample,
{
fn apply_parametric_eq(&mut self, eq: &ParametricEq) -> AudioSampleResult<()>;
fn apply_eq_band(&mut self, band: &EqBand) -> AudioSampleResult<()>;
fn apply_peak_filter(
&mut self,
frequency: f64,
gain_db: f64,
q_factor: f64,
) -> AudioSampleResult<()>;
fn apply_low_shelf(
&mut self,
frequency: f64,
gain_db: f64,
q_factor: f64,
) -> AudioSampleResult<()>;
fn apply_high_shelf(
&mut self,
frequency: f64,
gain_db: f64,
q_factor: f64,
) -> AudioSampleResult<()>;
fn apply_three_band_eq(
&mut self,
low_freq: f64,
low_gain: f64,
mid_freq: f64,
mid_gain: f64,
mid_q: f64,
high_freq: f64,
high_gain: f64,
) -> AudioSampleResult<()>;
fn eq_frequency_response(
&self,
eq: &ParametricEq,
frequencies: &[f64],
) -> AudioSampleResult<(Vec<f64>, Vec<f64>)>;
}
#[cfg(feature = "dynamic-range")]
pub trait AudioDynamicRange: AudioTypeConversion
where
Self::Sample: StandardSample,
{
fn apply_compressor(&mut self, config: &CompressorConfig) -> AudioSampleResult<()>;
fn apply_limiter(&mut self, config: &LimiterConfig) -> AudioSampleResult<()>;
fn apply_compressor_sidechain(
&mut self,
config: &CompressorConfig,
sidechain_signal: &Self,
) -> AudioSampleResult<()>;
fn apply_limiter_sidechain(
&mut self,
config: &LimiterConfig,
sidechain_signal: &Self,
) -> AudioSampleResult<()>;
fn get_compression_curve(
&self,
config: &CompressorConfig,
input_levels_db: &NonEmptySlice<f64>,
) -> AudioSampleResult<Vec<f64>>;
fn get_gain_reduction(&self, config: &CompressorConfig) -> AudioSampleResult<Vec<f64>>;
fn apply_gate(
&mut self,
threshold_db: f64,
ratio: f64,
attack_ms: f64,
release_ms: f64,
) -> AudioSampleResult<()>;
fn apply_expander(
&mut self,
threshold_db: f64,
ratio: f64,
attack_ms: f64,
release_ms: f64,
) -> AudioSampleResult<()>;
}
#[cfg(feature = "editing")]
pub trait AudioEditing: AudioTypeConversion
where
Self::Sample: StandardSample,
{
fn reverse<'b>(&self) -> AudioSamples<'b, Self::Sample>
where
Self: Sized;
fn reverse_in_place(&mut self) -> AudioSampleResult<()>
where
Self: Sized;
fn trim<'b>(
&self,
start_seconds: f64,
end_seconds: f64,
) -> AudioSampleResult<AudioSamples<'b, Self::Sample>>;
fn pad<'b>(
&self,
pad_start_seconds: f64,
pad_end_seconds: f64,
pad_value: Self::Sample,
) -> AudioSampleResult<AudioSamples<'b, Self::Sample>>;
fn pad_samples_right<'b>(
&self,
target_num_samples: usize,
pad_value: Self::Sample,
) -> AudioSampleResult<AudioSamples<'b, Self::Sample>>;
fn pad_to_duration<'b>(
&self,
target_duration_seconds: f64,
pad_value: Self::Sample,
pad_side: PadSide,
) -> AudioSampleResult<AudioSamples<'b, Self::Sample>>;
fn split(
&self,
segment_duration_seconds: f64,
) -> AudioSampleResult<Vec<AudioSamples<'static, Self::Sample>>>;
fn concatenate<'b>(
segments: &'b NonEmptySlice<AudioSamples<'b, Self::Sample>>,
) -> AudioSampleResult<AudioSamples<'b, Self::Sample>>;
fn concatenate_owned<'b>(
segments: NonEmptyVec<AudioSamples<'_, Self::Sample>>,
) -> AudioSampleResult<AudioSamples<'b, Self::Sample>>;
fn mix(
sources: &NonEmptySlice<Self>,
weights: Option<&NonEmptySlice<f64>>,
) -> AudioSampleResult<AudioSamples<'static, Self::Sample>>;
fn fade_in(&mut self, duration_seconds: f64, curve: FadeCurve) -> AudioSampleResult<()>;
fn fade_out(&mut self, duration_seconds: f64, curve: FadeCurve) -> AudioSampleResult<()>;
fn repeat(&self, count: usize) -> AudioSampleResult<AudioSamples<'static, Self::Sample>>;
fn trim_silence(
&self,
threshold_db: f64,
) -> AudioSampleResult<AudioSamples<'static, Self::Sample>>;
#[cfg(all(feature = "random-generation", feature = "iir-filtering"))]
fn perturb<'b>(
&self,
config: &PerturbationConfig,
) -> AudioSampleResult<AudioSamples<'b, Self::Sample>>;
#[cfg(all(feature = "random-generation", feature = "iir-filtering"))]
fn perturb_in_place(&mut self, config: &PerturbationConfig) -> AudioSampleResult<()>;
fn stack(
sources: &NonEmptySlice<Self>,
) -> AudioSampleResult<AudioSamples<'static, Self::Sample>>;
fn trim_all_silence(
&self,
threshold_db: f64,
min_silence_duration_seconds: f64,
) -> AudioSampleResult<AudioSamples<'static, Self::Sample>>;
}
#[cfg(feature = "channels")]
pub trait AudioChannelOps: AudioTypeConversion
where
Self::Sample: StandardSample,
{
fn to_mono(
&self,
method: MonoConversionMethod,
) -> AudioSampleResult<AudioSamples<'static, Self::Sample>>;
fn to_stereo(
&self,
method: StereoConversionMethod,
) -> AudioSampleResult<AudioSamples<'static, Self::Sample>>;
fn duplicate_to_channels(
&self,
n_channels: usize,
) -> AudioSampleResult<AudioSamples<'static, Self::Sample>>;
fn extract_channel(
&self,
channel_index: u32,
) -> AudioSampleResult<AudioSamples<'static, Self::Sample>>;
fn borrow_channel(
&self,
channel_index: u32,
) -> AudioSampleResult<AudioSamples<'_, Self::Sample>>;
fn swap_channels(&mut self, channel1: u32, channel2: u32) -> AudioSampleResult<()>;
fn pan(&mut self, pan_value: f64) -> AudioSampleResult<()>;
fn balance(&mut self, balance: f64) -> AudioSampleResult<()>;
fn apply_to_channel<F>(&mut self, channel_index: u32, func: F) -> AudioSampleResult<()>
where
F: FnMut(Self::Sample) -> Self::Sample;
fn interleave_channels(
channels: &NonEmptySlice<AudioSamples<'_, Self::Sample>>,
) -> AudioSampleResult<AudioSamples<'static, Self::Sample>>;
fn deinterleave_channels(&self) -> AudioSampleResult<Vec<AudioSamples<'static, Self::Sample>>>;
}
#[cfg(feature = "decomposition")]
pub trait AudioDecomposition: AudioTransforms
where
Self::Sample: StandardSample,
{
#[allow(clippy::type_complexity)]
fn hpss(
&self,
config: &HpssConfig,
) -> AudioSampleResult<(
AudioSamples<'static, Self::Sample>,
AudioSamples<'static, Self::Sample>,
)>;
}
#[cfg(feature = "onset-detection")]
pub trait AudioOnsetDetection: AudioTransforms
where
Self::Sample: StandardSample,
{
fn detect_onsets(&self, config: &OnsetDetectionConfig) -> AudioSampleResult<Vec<f64>>;
fn onset_detection_function(
&self,
config: &OnsetDetectionConfig,
) -> AudioSampleResult<(NonEmptyVec<f64>, NonEmptyVec<f64>)>;
fn detect_onsets_spectral_flux(
&self,
config: &SpectralFluxConfig,
) -> AudioSampleResult<Vec<f64>>;
fn spectral_flux(
&self,
config: &CqtParams,
window_size: NonZeroUsize,
hop_size: NonZeroUsize,
method: SpectralFluxMethod,
) -> AudioSampleResult<(NonEmptyVec<f64>, NonEmptyVec<f64>)>;
fn complex_onset_detection(
&self,
onset_config: &ComplexOnsetConfig,
) -> AudioSampleResult<Vec<f64>>;
fn onset_detection_function_complex(
&self,
onset_config: &ComplexOnsetConfig,
) -> AudioSampleResult<NonEmptyVec<f64>>;
fn magnitude_difference_matrix(
&self,
config: &ComplexOnsetConfig,
) -> AudioSampleResult<Array2<f64>>;
fn phase_deviation_matrix(&self, config: &ComplexOnsetConfig)
-> AudioSampleResult<Array2<f64>>;
}
#[cfg(feature = "beat-tracking")]
pub trait AudioBeatTracking: AudioTransforms
where
Self::Sample: StandardSample,
{
fn detect_beats(&self, config: &BeatTrackingConfig) -> AudioSampleResult<BeatTrackingData>;
}
#[cfg(feature = "plotting")]
pub trait AudioPlotting: AudioTransforms
where
Self::Sample: StandardSample,
{
fn plot_waveform(&self, params: &WaveformPlotParams) -> AudioSampleResult<WaveformPlot>;
fn plot_spectrogram(
&self,
params: &SpectrogramPlotParams,
) -> AudioSampleResult<SpectrogramPlot>;
fn plot_magnitude_spectrum(
&self,
params: &MagnitudeSpectrumParams,
) -> AudioSampleResult<MagnitudeSpectrumPlot>;
}
#[cfg(feature = "envelopes")]
pub trait AudioEnvelopes: AudioStatistics
where
Self::Sample: StandardSample,
{
fn amplitude_envelope(&self) -> NdResult<Self::Sample>;
fn rms_envelope(
&self,
window_size: NonZeroUsize,
hop_size: NonZeroUsize,
) -> NdResult<Self::Sample>;
#[allow(clippy::type_complexity)]
fn attack_decay_envelope(
&self,
follower: &EnvelopeFollower,
method: DynamicRangeMethod,
) -> (NdResult<Self::Sample>, NdResult<Self::Sample>);
fn analytic_envelope(&self) -> NdResult<Self::Sample>;
fn moving_average_envelope(
&self,
window_size: NonZeroUsize,
hop_size: NonZeroUsize,
) -> NdResult<Self::Sample>;
}