pub(crate) struct Rng(u64);
impl Rng {
pub(crate) fn new(seed: u64) -> Self {
Self(seed.wrapping_mul(0x9E37_79B9_7F4A_7C15) | 1)
}
pub(crate) fn next_u64(&mut self) -> u64 {
self.0 ^= self.0 >> 12;
self.0 ^= self.0 << 25;
self.0 ^= self.0 >> 27;
self.0.wrapping_mul(0x2545_F491_4F6C_DD1D)
}
pub(crate) fn range(&mut self, lo: usize, hi: usize) -> usize {
lo + (self.next_u64() % (hi - lo + 1) as u64) as usize
}
pub(crate) fn unit(&mut self) -> f64 {
(self.next_u64() >> 11) as f64 / (1_u64 << 53) as f64
}
pub(crate) fn chance(&mut self, probability: f64) -> bool {
self.unit() < probability
}
pub(crate) fn signal(&mut self, len: usize) -> Vec<f32> {
let mut samples = Vec::with_capacity(len);
while samples.len() < len {
let segment = self.range(1, 400).min(len - samples.len());
let kind = self.range(0, 6);
let amplitude = [1e-4, 0.01, 0.5, 1.0, 1e3][self.range(0, 4)];
let freq = self.unit() * 0.5;
let phase = self.unit() * std::f64::consts::TAU;
for idx in 0..segment {
let value = match kind {
0 => 0.0,
1 => amplitude * (phase + std::f64::consts::TAU * freq * idx as f64).sin(),
2 => amplitude * (self.unit() * 2.0 - 1.0),
3 if idx == 0 => amplitude,
3 => 0.0,
4 => amplitude,
5 => (self.unit() * 2.0 - 1.0) * 1e-40,
_ => amplitude * (self.unit() * 2.0 - 1.0) * (idx % 7) as f64,
};
samples.push(value as f32);
}
}
samples
}
}
pub(crate) fn fuzz_cases(default: usize) -> usize {
let scale = std::env::var("MEL_SPEC_FUZZ_SCALE")
.ok()
.and_then(|value| value.parse::<usize>().ok())
.unwrap_or(1);
default * scale.max(1)
}
pub(crate) fn same_f32(a: f32, b: f32) -> bool {
a == b || (a.is_nan() && b.is_nan())
}
pub(crate) fn same_f64(a: f64, b: f64) -> bool {
a == b || (a.is_nan() && b.is_nan())
}