use fundsp::hacker::Shared;
use super::harmony::{golden_pentatonic, rand_f32, rand_u32};
pub struct Genome<'a> {
pub freq: &'a Shared,
pub cutoff: &'a Shared,
pub resonance: &'a Shared,
pub reverb_mix: &'a Shared,
pub pulse_depth: &'a Shared,
pub pattern_hits: &'a Shared,
pub pattern_rotation: &'a Shared,
pub character: &'a Shared,
}
pub fn mutate(g: &Genome, seed: &mut u64, strength: f32) {
let s = strength.clamp(0.0, 1.0);
let cur = g.freq.value();
let scale = golden_pentatonic(cur);
let idx = rand_u32(seed, scale.len() as u32) as usize;
g.freq.set_value(scale[idx]);
let cut_factor = (1.0 + s * 0.8 * rand_f32(seed)).clamp(0.25, 4.0);
g.cutoff
.set_value((g.cutoff.value() * cut_factor).clamp(40.0, 12000.0));
let res = (g.resonance.value() + s * 0.15 * rand_f32(seed)).clamp(0.0, 0.55);
g.resonance.set_value(res);
let rev = (g.reverb_mix.value() + s * 0.25 * rand_f32(seed)).clamp(0.0, 1.0);
g.reverb_mix.set_value(rev);
let pulse = (g.pulse_depth.value() + s * 0.2 * rand_f32(seed)).clamp(0.0, 1.0);
g.pulse_depth.set_value(pulse);
let hits = (g.pattern_hits.value() + s * 3.0 * rand_f32(seed)).clamp(1.0, 11.0);
g.pattern_hits.set_value(hits);
let rot = (g.pattern_rotation.value() + s * 4.0 * rand_f32(seed)).rem_euclid(16.0);
g.pattern_rotation.set_value(rot);
let ch = (g.character.value() + s * 0.35 * rand_f32(seed)).clamp(0.0, 1.0);
g.character.set_value(ch);
}
pub fn crossover(a: &Genome, b: &Genome, seed: &mut u64) {
if rand_u32(seed, 2) == 0 {
a.freq.set_value(b.freq.value());
}
if rand_u32(seed, 2) == 0 {
a.cutoff.set_value(b.cutoff.value());
}
if rand_u32(seed, 2) == 0 {
a.resonance.set_value(b.resonance.value());
}
if rand_u32(seed, 2) == 0 {
a.reverb_mix.set_value(b.reverb_mix.value());
}
if rand_u32(seed, 2) == 0 {
a.pulse_depth.set_value(b.pulse_depth.value());
}
if rand_u32(seed, 2) == 0 {
a.pattern_hits.set_value(b.pattern_hits.value());
}
if rand_u32(seed, 2) == 0 {
a.pattern_rotation.set_value(b.pattern_rotation.value());
}
if rand_u32(seed, 2) == 0 {
a.character.set_value(b.character.value());
}
let cur = a.freq.value();
let scale = golden_pentatonic(cur);
let idx = rand_u32(seed, scale.len() as u32) as usize;
a.freq.set_value(scale[idx]);
}