use rand::RngExt;
use crate::analyse::{db_to_linear, rms_db};
pub fn generate_room_tone(n_samples: usize, target_db: f32) -> Vec<i16> {
if n_samples == 0 {
return Vec::new();
}
let mut rng = rand::rng();
let n_stages = 16usize;
let mut stages = vec![0.0f32; n_stages];
let mut stage_counters = vec![0u64; n_stages];
let mut raw: Vec<f32> = Vec::with_capacity(n_samples);
for i in 0..n_samples {
for (stage_idx, (counter, stage_val)) in
stage_counters.iter_mut().zip(stages.iter_mut()).enumerate()
{
let period = 1u64 << stage_idx;
if i as u64 % period == 0 {
*counter = counter.wrapping_add(1);
*stage_val = rng.random::<f32>() * 2.0 - 1.0;
}
}
let sum: f32 = stages.iter().sum();
raw.push(sum / n_stages as f32);
}
let raw_as_i16: Vec<i16> = raw
.iter()
.map(|&s| (s * i16::MAX as f32).clamp(i16::MIN as f32, i16::MAX as f32) as i16)
.collect();
let measured = rms_db(&raw_as_i16);
let gain = if measured <= -144.0 {
1.0
} else {
db_to_linear(target_db - measured)
};
raw_as_i16
.into_iter()
.map(|s| {
(s as f32 * gain)
.round()
.clamp(i16::MIN as f32, i16::MAX as f32) as i16
})
.collect()
}