use alloc::collections::VecDeque;
use alloc::rc::Rc;
use alloc::vec::Vec;
use crate::{
constants::{HAT_PATTERNS, KICK_PATTERNS, SAMPLE_RATE, SNARE_PATTERNS},
plugin::{Plugin, Random, SampleStepConfig},
SongMetadata,
};
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
pub struct DrumStep {
pub kick: bool,
pub snare: bool,
pub hat: bool,
pub open_hat: bool,
pub offset: usize,
}
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
pub struct DrumPattern {
pub steps: [DrumStep; 16],
}
impl DrumPattern {
pub fn from_seed(seed: &[u8; 8]) -> DrumPattern {
let mut kick = KICK_PATTERNS[(seed[0] % 3) as usize];
let snare = SNARE_PATTERNS[(seed[1] % 3) as usize];
let hat = HAT_PATTERNS[(seed[2] % 3) as usize];
if seed[3] & 0x03 == 0 {
let slots = [6usize, 11, 14];
kick[slots[(seed[4] % 3) as usize]] = 1;
}
let mut steps = [DrumStep::default(); 16];
for offset in 0..16 {
steps[offset] = DrumStep {
kick: kick[offset] == 1,
snare: snare[offset] == 1,
hat: hat[offset] == 1,
open_hat: false,
offset,
};
}
if seed[5] & 0x01 != 0 {
steps[8].open_hat = true;
}
DrumPattern { steps }
}
pub fn steps(self) -> Steps {
Steps::new(self)
}
pub fn step(&self, n: u64) -> DrumStep {
self.steps[(n % 16) as usize].clone()
}
}
pub struct Steps {
pattern: DrumPattern,
step: u64,
}
impl Steps {
pub fn new(pattern: DrumPattern) -> Self {
Self { pattern, step: 0 }
}
}
impl Iterator for Steps {
type Item = DrumStep;
fn next(&mut self) -> Option<Self::Item> {
let i = self.step;
self.step = (self.step + 1) % 16;
Some(self.pattern.step(i))
}
}
pub type DrumSample = f32;
pub struct DrumSampleGenerator {
metadata: SongMetadata,
plugin: Rc<dyn Plugin>,
sample_rate: f64,
random: Rc<dyn Random>,
}
impl DrumSampleGenerator {
pub fn new(metadata: SongMetadata, plugin: Rc<dyn Plugin>, random: Rc<dyn Random>) -> Self {
Self {
metadata,
plugin,
sample_rate: SAMPLE_RATE as f64,
random,
}
}
pub fn with_sample_rate(self, sample_rate: u32) -> Self {
Self {
sample_rate: sample_rate as f64,
..self
}
}
pub fn samples(self) -> SampleDrumSteps {
SampleDrumSteps {
drum_pattern: self.metadata.drum_pattern.clone(),
sample_generator: self,
step: 0,
samples: Default::default(),
}
}
pub fn sample_step(&mut self, step: DrumStep) -> Vec<DrumSample> {
let pattern = (step.offset % 16) as usize;
let step_duration = self.metadata.timing.sixteenth;
let color = self.metadata.seed[pattern % 8];
let total_samples = (self.sample_rate * self.metadata.timing.sixteenth).floor() as usize;
let mut samples = Vec::with_capacity(total_samples);
samples.resize_with(total_samples, Default::default);
self.plugin.sample_step(
step,
SampleStepConfig {
sample_rate: self.sample_rate,
step_duration,
pattern,
color,
random: &self.random,
},
&mut samples,
);
samples
}
}
pub struct SampleDrumSteps {
sample_generator: DrumSampleGenerator,
drum_pattern: DrumPattern,
step: u64,
samples: VecDeque<DrumSample>,
}
impl SampleDrumSteps {
pub fn new(metadata: SongMetadata, plugin: Rc<dyn Plugin>, random: Rc<dyn Random>) -> Self {
Self::from_generator(
metadata.clone(),
DrumSampleGenerator::new(metadata, plugin, random),
)
}
pub fn from_generator(metadata: SongMetadata, sample_generator: DrumSampleGenerator) -> Self {
Self {
drum_pattern: metadata.drum_pattern.clone(),
sample_generator,
step: 0,
samples: Default::default(),
}
}
pub fn with_sample_rate(self, sample_rate: u32) -> Self {
Self {
sample_generator: self.sample_generator.with_sample_rate(sample_rate),
..self
}
}
}
impl Iterator for SampleDrumSteps {
type Item = DrumSample;
fn next(&mut self) -> Option<Self::Item> {
loop {
if let Some(sample) = self.samples.pop_front() {
return Some(sample);
}
self.samples.extend(
self.sample_generator
.sample_step(self.drum_pattern.step(self.step)),
);
self.step += 1;
}
}
}