use rustfft::num_complex::Complex;
use super::fft::SpectrumError;
pub fn complex_to_polar_rfft(spectrum: &[Complex<f64>]) -> (Vec<f64>, Vec<f64>) {
let mut magnitude_spectrum = vec![0.0 as f64; spectrum.len()];
let mut phase_spectrum = vec![0.0 as f64; spectrum.len()];
for i in 0..spectrum.len() {
magnitude_spectrum[i] = f64::sqrt(spectrum[i].re.powf(2.0) + spectrum[i].im.powf(2.0));
phase_spectrum[i] = f64::atan2(spectrum[i].im, spectrum[i].re);
}
(magnitude_spectrum, phase_spectrum)
}
pub fn complex_to_polar_rstft(spectrogram: &Vec<Vec<Complex<f64>>>) -> (Vec<Vec<f64>>, Vec<Vec<f64>>) {
let mut magnitude_spectrogram: Vec<Vec<f64>> = Vec::with_capacity(spectrogram.len());
let mut phase_spectrogram: Vec<Vec<f64>> = Vec::with_capacity(spectrogram.len());
for frame_idx in 0..spectrogram.len() {
let mut frame_magnitude_spectrum = vec![0.0 as f64; spectrogram[frame_idx].len()];
let mut frame_phase_spectrum = vec![0.0 as f64; spectrogram[frame_idx].len()];
for fft_bin_idx in 0..spectrogram[frame_idx].len() {
frame_magnitude_spectrum[fft_bin_idx] = f64::sqrt(spectrogram[frame_idx][fft_bin_idx].re.powf(2.0) + spectrogram[frame_idx][fft_bin_idx].im.powf(2.0));
frame_phase_spectrum[fft_bin_idx] = f64::atan2(spectrogram[frame_idx][fft_bin_idx].im, spectrogram[frame_idx][fft_bin_idx].re);
}
magnitude_spectrogram.push(frame_magnitude_spectrum);
phase_spectrogram.push(frame_phase_spectrum);
}
(magnitude_spectrogram, phase_spectrogram)
}
pub fn overlap_add(audio_chunks: &Vec<Vec<f64>>, fft_size: usize, hop_size: usize) -> Vec<f64> {
let mut audio: Vec<f64> = Vec::new();
let mut frame_indices: Vec<(usize, usize)> = Vec::with_capacity(audio_chunks.len());
let mut current_frame_start_idx: usize = 0;
for _ in 0..audio_chunks.len() {
frame_indices.push((current_frame_start_idx, current_frame_start_idx + fft_size));
current_frame_start_idx += hop_size;
}
let mut lower_frame_idx: usize = 0; let mut upper_frame_idx: usize = 0; let mut current_sample_idx: usize = 0;
while lower_frame_idx < audio_chunks.len() {
if current_sample_idx >= frame_indices[lower_frame_idx].1 {
lower_frame_idx += 1;
}
if upper_frame_idx + 1 < audio_chunks.len() {
if current_sample_idx >= frame_indices[upper_frame_idx + 1].0 {
upper_frame_idx += 1;
}
}
if lower_frame_idx < audio_chunks.len() {
let mut sample: f64 = 0.0;
for i in lower_frame_idx..upper_frame_idx + 1 {
let local_frame_idx = current_sample_idx - frame_indices[i].0;
sample += audio_chunks[i][local_frame_idx];
}
audio.push(sample);
current_sample_idx += 1;
}
}
audio
}
pub fn polar_to_complex_rfft(magnitude_spectrum: &[f64], phase_spectrum: &[f64]) -> Result<Vec<Complex<f64>>, SpectrumError> {
if magnitude_spectrum.len() != phase_spectrum.len() {
return Err(SpectrumError{error_msg: String::from(format!("The magnitude spectrum and phase spectrum do not \
have the same length. The magnitude spectrum has len {} and the phase spectrum has len {}.",
magnitude_spectrum.len(), phase_spectrum.len()))});
}
let mut spectrum = vec![num::complex::Complex::new(0.0, 0.0); magnitude_spectrum.len()];
for i in 0..magnitude_spectrum.len() {
let real = f64::cos(phase_spectrum[i]) * magnitude_spectrum[i];
let imag = f64::sin(phase_spectrum[i]) * magnitude_spectrum[i];
let output: Complex<f64> = Complex::new(real, imag);
spectrum[i] = output;
}
Ok(spectrum)
}
pub fn polar_to_complex_rstft(magnitude_spectrogram: &Vec<Vec<f64>>, phase_spectrogram: &Vec<Vec<f64>>) -> Result<Vec<Vec<Complex<f64>>>, SpectrumError> {
if magnitude_spectrogram.len() != phase_spectrogram.len() {
return Err(SpectrumError{error_msg: String::from(format!("The magnitude spectrogram and phase spectrogram do not \
have the same length. The magnitude spectrogram has len {} and the phase spectrogram has len {}.",
magnitude_spectrogram.len(), phase_spectrogram.len()))});
}
let mut spectrogram: Vec<Vec<Complex<f64>>> = Vec::with_capacity(magnitude_spectrogram.len());
for i in 0..magnitude_spectrogram.len() {
if magnitude_spectrogram[i].len() != phase_spectrogram[i].len() {
return Err(SpectrumError{error_msg: String::from(format!("The {}th magnitude spectrum and phase spectrum do not \
have the same length. The magnitude spectrum has len {} and the phase spectrum has len {}.",
i, magnitude_spectrogram[i].len(), phase_spectrogram[i].len()))});
}
let mut frame_spectrum: Vec<Complex<f64>> = Vec::with_capacity(magnitude_spectrogram[i].len());
for j in 0..magnitude_spectrogram[i].len() {
let real = f64::cos(phase_spectrogram[i][j]) * magnitude_spectrogram[i][j];
let imag = f64::sin(phase_spectrogram[i][j]) * magnitude_spectrogram[i][j];
let output: Complex<f64> = Complex::new(real, imag);
frame_spectrum.push(output);
}
spectrogram.push(frame_spectrum);
}
Ok(spectrogram)
}
#[inline(always)]
pub fn rfftfreq(fft_size: usize, sample_rate: u32) -> Vec<f64> {
let mut freqs = vec![0.0 as f64; fft_size / 2 + 1];
let f_0 = sample_rate as f64 / fft_size as f64;
for i in 1..freqs.len() {
freqs[i] = f_0 * i as f64;
}
freqs
}