staff 0.11.0

Music theory library with midi, notes, chords, scales, and more
Documentation
use super::Frequencies;
use crate::synth::GuitarSource;
use rand::{thread_rng, Rng};
use std::slice;

#[derive(Clone, Debug)]
struct Index {
    pub pos: usize,
    pub len: usize,
}

#[derive(Clone, Debug, Default)]
pub struct GuitarChord {
    frequencies: Vec<f32>,
    strings: Vec<Index>,
}

impl GuitarChord {
    pub fn set_frequencies(&mut self, sample_rate: u32, freqs: impl IntoIterator<Item = f32>) {
        self.strings.clear();

        for freq in freqs {
            let period = (sample_rate as f32 / freq).round() as usize;
            self.strings.push(Index {
                pos: 0,
                len: period,
            });

            let mut rng = thread_rng();
            for _ in 0..period {
                let noise = rng.gen_range(-1.0..1.0);
                self.frequencies.push(noise);
            }
        }
    }
}

pub struct GuitarChordFrequencies<'a> {
    frequencies: &'a mut [f32],
    indices: slice::IterMut<'a, Index>,
    start: usize,
}

impl Iterator for GuitarChordFrequencies<'_> {
    type Item = f32;

    fn next(&mut self) -> Option<Self::Item> {
        if let Some(index) = self.indices.next() {
            let frequencies = &mut self.frequencies[self.start..self.start + index.len];
            self.start += index.len;

            let mut guitar_string = GuitarSource::new(frequencies, index.pos);
            let output = guitar_string.next().unwrap();
            index.pos = guitar_string.pos;
            Some(output)
        } else {
            None
        }
    }
}

impl Frequencies for GuitarChord {
    type Frequencies<'a> = GuitarChordFrequencies<'a>;

    fn frequencies<'a>(&'a mut self) -> Self::Frequencies<'a> {
        GuitarChordFrequencies {
            frequencies: &mut self.frequencies,
            indices: self.strings.iter_mut(),
            start: 0,
        }
    }
}