ptcow 0.6.0

Library for editing and playback of PxTone (.ptcop) music
Documentation
const OCTAVE_NUM: u8 = 16;
const KEY_PER_OCTAVE: u8 = 12;
const FREQUENCY_PER_KEY: u8 = 0x10;
const TABLE_SIZE: usize =
    OCTAVE_NUM as usize * KEY_PER_OCTAVE as usize * FREQUENCY_PER_KEY as usize;

pub struct PulseFrequency {
    table: [f32; TABLE_SIZE],
}

pub static PULSE_FREQ: PulseFrequency = PulseFrequency::generate();

impl PulseFrequency {
    const fn generate() -> Self {
        #[expect(clippy::unreadable_literal)]
        let oct_table: [f64; OCTAVE_NUM as usize] = [
            0.00390625, 0.0078125, 0.015625, 0.03125, 0.0625, 0.125, 0.25, 0.5, 1., 2., 4., 8.,
            16., 32., 64., 128.,
        ];

        let mut table = [0.0; _];

        let oct_x24: f64 = divide_octave_rate(KEY_PER_OCTAVE * FREQUENCY_PER_KEY);

        let mut i = 0;
        while i < table.len() {
            let freq = &mut table[i];
            let mut oct = oct_table[i / (KEY_PER_OCTAVE as usize * FREQUENCY_PER_KEY as usize)];
            let mut j = 0;
            while j < i % (KEY_PER_OCTAVE as usize * FREQUENCY_PER_KEY as usize) {
                oct *= oct_x24;
                j += 1;
            }
            #[expect(clippy::cast_possible_truncation)]
            (*freq = oct as f32);
            i += 1;
        }
        Self { table }
    }
    #[expect(
        clippy::cast_possible_truncation,
        clippy::cast_possible_wrap,
        clippy::cast_sign_loss
    )]
    pub const fn get(&self, key: i32) -> f32 {
        let mut i = (key.wrapping_add(0x6000)).wrapping_mul(FREQUENCY_PER_KEY as i32) / 0x100;
        if i < 0 {
            i = 0;
        } else if i >= TABLE_SIZE as i32 {
            i = TABLE_SIZE as i32 - 1;
        }
        self.table[i as usize]
    }
    pub const fn get2(&self, key: usize) -> f32 {
        let mut i = key >> 4;
        if i >= TABLE_SIZE {
            i = TABLE_SIZE - 1;
        }
        self.table[i]
    }
}

const fn divide_octave_rate(divi: u8) -> f64 {
    let mut parameter: f64 = 1.0;

    let mut i = 0;
    while i < 17 {
        let mut add = 1.0;
        let mut j = 0;
        while j < i {
            add *= 0.1;
            j += 1;
        }

        j = 0;

        while j < 10 {
            let work = (add * j as f64) + parameter;

            let mut result = 1.0;
            let mut k = 0;
            while k < divi {
                result *= work;
                if result >= 2.0 {
                    break;
                }
                k += 1;
            }

            if k != divi {
                break;
            }
            j += 1;
        }
        parameter += add * (j as f64 - 1.0);
        i += 1;
    }

    parameter
}