mirror of
https://github.com/transistorfet/moa.git
synced 2024-12-01 09:49:39 +00:00
Modified ym2612 to use 16 bit signed number a bit sooner
This commit is contained in:
parent
71cd47466b
commit
074d29c023
@ -163,14 +163,15 @@ lazy_static! {
|
|||||||
.map(|i| {
|
.map(|i| {
|
||||||
let sine = (((i * 2 + 1) as f32 / SIN_TABLE_SIZE as f32) * f32::consts::PI / 2.0).sin();
|
let sine = (((i * 2 + 1) as f32 / SIN_TABLE_SIZE as f32) * f32::consts::PI / 2.0).sin();
|
||||||
let log_sine = -1.0 * sine.log2();
|
let log_sine = -1.0 * sine.log2();
|
||||||
|
// Convert to fixed decimal notation with 4.8 bit format
|
||||||
(log_sine * (1 << 8) as f32) as u16
|
(log_sine * (1 << 8) as f32) as u16
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
static ref POW_TABLE: Vec<u16> = (0..POW_TABLE_SIZE)
|
static ref POW_TABLE: Vec<i16> = (0..POW_TABLE_SIZE)
|
||||||
.map(|i| {
|
.map(|i| {
|
||||||
let linear = 2.0_f32.powf(-1.0 * (((i & 0xFF) + 1) as f32 / 256.0));
|
let linear = 2.0_f32.powf(-1.0 * (((i & 0xFF) + 1) as f32 / 256.0));
|
||||||
let linear_fixed = (linear * (1 << 11) as f32) as u16;
|
let linear_fixed = (linear * (1 << 11) as f32) as i16;
|
||||||
let shift = (i as i32 >> 8) - 2;
|
let shift = (i as i32 >> 8) - 2;
|
||||||
if shift < 0 {
|
if shift < 0 {
|
||||||
linear_fixed << (0 - shift)
|
linear_fixed << (0 - shift)
|
||||||
@ -226,8 +227,8 @@ impl EnvelopeGenerator {
|
|||||||
sustain_level: 0,
|
sustain_level: 0,
|
||||||
rates: [0; 4],
|
rates: [0; 4],
|
||||||
|
|
||||||
envelope_state: EnvelopeState::Attack,
|
envelope_state: EnvelopeState::Release,
|
||||||
envelope: 0,
|
envelope: MAX_ENVELOPE,
|
||||||
last_envelope_clock: 0,
|
last_envelope_clock: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -410,8 +411,8 @@ impl PhaseGenerator {
|
|||||||
self.increment = increment;
|
self.increment = increment;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_phase(&mut self, _fm_clock: FmClock) -> u16 {
|
fn update_phase(&mut self, _fm_clock: FmClock) -> i16 {
|
||||||
let phase = ((self.counter >> 10) & 0x3FF) as u16;
|
let phase = ((self.counter >> 10) & 0x3FF) as i16;
|
||||||
self.counter += self.increment;
|
self.counter += self.increment;
|
||||||
phase
|
phase
|
||||||
}
|
}
|
||||||
@ -455,7 +456,7 @@ struct Operator {
|
|||||||
debug_name: String,
|
debug_name: String,
|
||||||
phase: PhaseGenerator,
|
phase: PhaseGenerator,
|
||||||
envelope: EnvelopeGenerator,
|
envelope: EnvelopeGenerator,
|
||||||
output: u16,
|
output: i16,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Operator {
|
impl Operator {
|
||||||
@ -497,18 +498,29 @@ impl Operator {
|
|||||||
self.phase.reset();
|
self.phase.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_output(&mut self, modulator: u16, clocks: (FmClock, EnvelopeClock)) -> u16 {
|
fn get_output(&mut self, modulator: i16, clocks: (FmClock, EnvelopeClock)) -> i16 {
|
||||||
let (fm_clock, envelope_clock) = clocks;
|
let (fm_clock, envelope_clock) = clocks;
|
||||||
|
|
||||||
let envelope = self.envelope.get_envelope(envelope_clock, self.phase.get_rate_adjust());
|
let envelope = self.envelope.get_envelope(envelope_clock, self.phase.get_rate_adjust());
|
||||||
let phase = self.phase.update_phase(fm_clock);
|
let phase = self.phase.update_phase(fm_clock);
|
||||||
|
|
||||||
let mod_phase = phase + modulator;
|
let mod_phase = phase + modulator;
|
||||||
|
|
||||||
let mut output = POW_TABLE[(SIN_TABLE[(mod_phase & 0x1FF) as usize] + envelope) as usize];
|
// The sine table contains the first half of the wave as an attenuation value
|
||||||
|
// Use the phase with the sign truncated to get the attenuation, plus the
|
||||||
|
// attenuation from the envelope, to get the total attenuation at this point
|
||||||
|
let attenuation = SIN_TABLE[(mod_phase & 0x1FF) as usize] + envelope;
|
||||||
|
|
||||||
|
// The power table contains the 13-bit output (not including the sign) for a
|
||||||
|
// 12 bit attenuation value, which is then negated based on the sign of the phase
|
||||||
|
let mut output = POW_TABLE[attenuation as usize];
|
||||||
|
|
||||||
|
// If the original phase was in the negative portion, invert the output
|
||||||
|
// since the sine wave's second half is a mirror of the first half
|
||||||
if mod_phase & 0x200 != 0 {
|
if mod_phase & 0x200 != 0 {
|
||||||
output = (output as i16 * -1) as u16
|
output = output * -1;
|
||||||
}
|
}
|
||||||
|
// The output is now represented with a 16-bit signed number in the range of -0x1FFF and 0x1FFF
|
||||||
|
|
||||||
// Save the output for use as feedback later
|
// Save the output for use as feedback later
|
||||||
self.output = output;
|
self.output = output;
|
||||||
@ -530,7 +542,7 @@ struct Channel {
|
|||||||
key_state: u8,
|
key_state: u8,
|
||||||
next_key_clock: FmClock,
|
next_key_clock: FmClock,
|
||||||
next_key_state: u8,
|
next_key_state: u8,
|
||||||
op1_output: [u16; 2],
|
op1_output: [i16; 2],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Channel {
|
impl Channel {
|
||||||
@ -580,25 +592,24 @@ impl Channel {
|
|||||||
} else {
|
} else {
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
let output = self.get_algorithm_output(clocks, feedback);
|
|
||||||
|
|
||||||
let output = if output & 0x2000 == 0 {
|
let output = self.get_algorithm_output(clocks, feedback);
|
||||||
output as i16
|
|
||||||
} else {
|
|
||||||
(output | 0xC000) as i16
|
|
||||||
};
|
|
||||||
|
|
||||||
self.op1_output[0] = self.op1_output[1];
|
self.op1_output[0] = self.op1_output[1];
|
||||||
self.op1_output[1] = self.operators[0].output;
|
self.op1_output[1] = self.operators[0].output;
|
||||||
|
|
||||||
let sample = output as f32 / (1 << 14) as f32;
|
//let output = sign_extend_u16(output, 14);
|
||||||
|
|
||||||
|
//let output = output * 2 / 3;
|
||||||
|
|
||||||
|
let sample = output as f32 / (1 << 13) as f32;
|
||||||
|
|
||||||
let left = if self.enabled.0 { sample } else { 0.0 };
|
let left = if self.enabled.0 { sample } else { 0.0 };
|
||||||
let right = if self.enabled.1 { sample } else { 0.0 };
|
let right = if self.enabled.1 { sample } else { 0.0 };
|
||||||
(left, right)
|
(left, right)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_algorithm_output(&mut self, clocks: (FmClock, EnvelopeClock), feedback: u16) -> u16 {
|
fn get_algorithm_output(&mut self, clocks: (FmClock, EnvelopeClock), feedback: i16) -> i16 {
|
||||||
match self.algorithm {
|
match self.algorithm {
|
||||||
OperatorAlgorithm::A0 => {
|
OperatorAlgorithm::A0 => {
|
||||||
let modulator0 = self.operators[0].get_output(feedback, clocks);
|
let modulator0 = self.operators[0].get_output(feedback, clocks);
|
||||||
@ -650,6 +661,14 @@ impl Channel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn sign_extend_u16(value: u16, size: usize) -> i16 {
|
||||||
|
if value & (1 << (size + 1)) == 0 {
|
||||||
|
value as i16
|
||||||
|
} else {
|
||||||
|
(value | 0xFFFF << (size + 1)) as i16
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
struct Dac {
|
struct Dac {
|
||||||
enabled: bool,
|
enabled: bool,
|
||||||
|
Loading…
Reference in New Issue
Block a user