sim-lib-music-transform 0.1.4

Pitch, time, pattern, and diagnostic transforms over canonical SIM music objects.
Documentation
#[derive(Clone, Debug)]
pub(super) struct PatternRng {
    state: u64,
}

impl PatternRng {
    pub(super) fn new(seed: u64) -> Self {
        Self {
            state: seed ^ 0x9e37_79b9_7f4a_7c15,
        }
    }

    fn next_u64(&mut self) -> u64 {
        self.state = self.state.wrapping_add(0x9e37_79b9_7f4a_7c15);
        let mut value = self.state;
        value = (value ^ (value >> 30)).wrapping_mul(0xbf58_476d_1ce4_e5b9);
        value = (value ^ (value >> 27)).wrapping_mul(0x94d0_49bb_1331_11eb);
        value ^ (value >> 31)
    }

    pub(super) fn next_bool(&mut self) -> bool {
        self.next_u64() & 1 == 1
    }

    pub(super) fn range(&mut self, upper: usize) -> usize {
        if upper == 0 {
            0
        } else {
            (self.next_u64() as usize) % upper
        }
    }

    pub(super) fn chance(&mut self, percent: u8) -> bool {
        percent >= 100 || (percent > 0 && self.range(100) < usize::from(percent))
    }

    pub(super) fn shuffle<T>(&mut self, values: &mut [T]) {
        for index in (1..values.len()).rev() {
            let swap_with = self.range(index + 1);
            values.swap(index, swap_with);
        }
    }
}