use crate::audio::pitch_table::{midi_inc, MidiNote};
pub const VOICE_BASE: usize = 0x3041;
pub const VOICE_SIZE: usize = 7;
pub const VOICE_COUNT: usize = 8;
pub const WAVETABLE_BASE: usize = 0x3300;
pub const WAVETABLE_SIZE: usize = 256;
pub const WAVETABLE_COUNT: usize = 11;
pub const WAVETABLE: [u16; WAVETABLE_COUNT] = [
0x0300, 0x0400, 0x0500, 0x0600, 0x0700,
0x0800, 0x0900, 0x0A00, 0x0B00, 0x0C00,
0x0D00,
];
#[repr(C, packed)]
pub struct Voice {
phase: u16,
frequency: u16,
wavetable: u16,
volume: u8,
}
impl Voice {
#[inline]
pub fn set_note(&mut self, note: MidiNote) {
self.frequency = midi_inc(note);
}
#[inline]
pub fn set_frequency(&mut self, freq_inc: u16) {
self.frequency = freq_inc;
}
#[inline]
pub fn set_volume(&mut self, volume: u8) {
self.volume = volume;
}
#[inline]
pub fn set_wavetable(&mut self, wavetable_addr: u16) {
self.wavetable = wavetable_addr;
}
#[inline]
pub fn mute(&mut self) {
self.volume = 0;
}
#[inline]
pub fn reset_phase(&mut self) {
self.phase = 0;
}
#[inline]
pub fn get_volume(&self) -> u8 {
self.volume
}
}
#[inline]
pub fn voices() -> &'static mut [Voice; VOICE_COUNT] {
unsafe { &mut *(VOICE_BASE as *mut [Voice; VOICE_COUNT]) }
}
#[inline]
pub fn voice(index: usize) -> &'static mut Voice {
assert!(index < VOICE_COUNT, "voice index out of range");
unsafe { &mut *((VOICE_BASE + index * VOICE_SIZE) as *mut Voice) }
}
#[inline]
pub fn mute_all() {
let v = voices();
for voice in v.iter_mut() {
voice.mute();
}
}