lookas 1.10.0

Perception aligned terminal-based audio spectrum visualizer
Documentation
use lookas::audio::AudioMode;

use super::Runtime;

pub struct FrameSamples {
    mic_tail: Vec<f32>,
    sys_tail: Vec<f32>,
    mix: Vec<f32>,
}

struct AudioReady {
    mic: bool,
    system: bool,
}

impl FrameSamples {
    pub fn new(fft_size: usize) -> Self {
        Self {
            mic_tail: Vec::with_capacity(fft_size),
            sys_tail: Vec::with_capacity(fft_size),
            mix: vec![0.0f32; fft_size],
        }
    }

    pub fn len(&self) -> usize {
        self.mix.len()
    }

    pub fn mix(&self) -> &[f32] {
        &self.mix
    }

    pub fn resize(&mut self, fft_size: usize) {
        self.mic_tail = Vec::with_capacity(fft_size);
        self.sys_tail = Vec::with_capacity(fft_size);
        self.mix = vec![0.0; fft_size];
    }

    pub fn prepare(&mut self, runtime: &Runtime) -> bool {
        let ready = self.copy_tails(runtime);

        match runtime.mode() {
            AudioMode::Mic => self.copy_mic(ready.mic),
            AudioMode::System => self.copy_system(ready.system),
            AudioMode::Both => {
                self.mix_samples(runtime.fft_size(), &ready)
            }
        }
    }

    fn copy_tails(&mut self, runtime: &Runtime) -> AudioReady {
        AudioReady {
            mic: runtime.copy_mic_tail(&mut self.mic_tail),
            system: runtime.copy_system_tail(&mut self.sys_tail),
        }
    }

    fn copy_mic(&mut self, ready: bool) -> bool {
        if ready {
            self.mix.copy_from_slice(&self.mic_tail);
        }
        ready
    }

    fn copy_system(&mut self, ready: bool) -> bool {
        if ready {
            self.mix.copy_from_slice(&self.sys_tail);
        }
        ready
    }

    fn mix_samples(
        &mut self,
        fft_size: usize,
        ready: &AudioReady,
    ) -> bool {
        if !ready.mic || !ready.system {
            return false;
        }

        #[allow(clippy::indexing_slicing)]
        for i in 0..fft_size {
            self.mix[i] = (self.mic_tail[i] + self.sys_tail[i]) * 0.5;
        }

        true
    }
}