diff options
author | Aaron Giles <aaron@aarongiles.com> | 2021-03-03 01:06:11 -0800 |
---|---|---|
committer | Aaron Giles <aaron@aarongiles.com> | 2021-03-03 01:06:11 -0800 |
commit | 76f7ddca50ada66a4681cac8f2e68569465dda6a (patch) | |
tree | fe2ec1a2a9fd59fbe101eaede03bc5fe3adde0f7 /src/devices | |
parent | 0633a88c198755c0024a3cfcee5f98de7f39f6f0 (diff) |
ymfm: Improve LFO noise behavior. Add logging (under verbose) when LFO noise sounds are played to help ID cases for further study. This will be removed prior to release.
Diffstat (limited to 'src/devices')
-rw-r--r-- | src/devices/sound/ymfm.cpp | 97 | ||||
-rw-r--r-- | src/devices/sound/ymfm.h | 2 |
2 files changed, 57 insertions, 42 deletions
diff --git a/src/devices/sound/ymfm.cpp b/src/devices/sound/ymfm.cpp index 35fff69c3a0..2931b62ebbe 100644 --- a/src/devices/sound/ymfm.cpp +++ b/src/devices/sound/ymfm.cpp @@ -4,7 +4,7 @@ #include "emu.h" #include "ymfm.h" -//#define VERBOSE 1 +#define VERBOSE 1 #define LOG_OUTPUT_FUNC osd_printf_verbose #include "logmacro.h" @@ -640,31 +640,34 @@ void ymfm_operator<RegisterType>::start_attack(u8 keycode) if (effective_rate(m_regs.attack_rate(), keycode) >= 62) m_env_attenuation = 0; - // log keys - LOG("KeyOn %d.%d: freq=%04X dt2=%d fb=%d alg=%d dt=%d mul=%X tl=%02X ksr=%d adsr=%02X/%02X/%02X/%X sl=%X pan=%c%c", - m_regs.chnum(), m_regs.opnum(), - m_regs.block_freq(), - m_regs.detune2(), - m_regs.feedback(), - m_regs.algorithm(), - m_regs.detune(), - m_regs.multiple(), - m_regs.total_level(), - m_regs.ksr(), - m_regs.attack_rate(), - m_regs.decay_rate(), - m_regs.sustain_rate(), - m_regs.release_rate(), - m_regs.sustain_level(), - m_regs.pan_left() ? 'L' : '-', - m_regs.pan_right() ? 'R' : '-'); - if (m_regs.ssg_eg_enabled()) - LOG(" ssg=%X", m_regs.ssg_eg_mode()); - if (m_regs.lfo_enabled() && ((m_regs.lfo_am_enabled() && m_regs.lfo_am_sensitivity() != 0) || m_regs.lfo_pm_sensitivity() != 0)) - LOG(" am=%d pm=%d w=%d", m_regs.lfo_am_enabled() ? m_regs.lfo_am_sensitivity() : 0, m_regs.lfo_pm_sensitivity(), m_regs.lfo_waveform()); - if (m_regs.noise_enabled() && m_regs.opnum() == 3 && m_regs.chnum() == 7) - LOG(" noise=1"); - LOG("\n"); + // log key on events under certain conditions + if (m_regs.lfo_waveform() == 3 && m_regs.lfo_enabled() && ((m_regs.lfo_am_enabled() && m_regs.lfo_am_sensitivity() != 0) || m_regs.lfo_pm_sensitivity() != 0)) + { + LOG("KeyOn %d.%d: freq=%04X dt2=%d fb=%d alg=%d dt=%d mul=%X tl=%02X ksr=%d adsr=%02X/%02X/%02X/%X sl=%X pan=%c%c", + m_regs.chnum(), m_regs.opnum(), + m_regs.block_freq(), + m_regs.detune2(), + m_regs.feedback(), + m_regs.algorithm(), + m_regs.detune(), + m_regs.multiple(), + m_regs.total_level(), + m_regs.ksr(), + m_regs.attack_rate(), + m_regs.decay_rate(), + m_regs.sustain_rate(), + m_regs.release_rate(), + m_regs.sustain_level(), + m_regs.pan_left() ? 'L' : '-', + m_regs.pan_right() ? 'R' : '-'); + if (m_regs.ssg_eg_enabled()) + LOG(" ssg=%X", m_regs.ssg_eg_mode()); + if (m_regs.lfo_enabled() && ((m_regs.lfo_am_enabled() && m_regs.lfo_am_sensitivity() != 0) || m_regs.lfo_pm_sensitivity() != 0)) + LOG(" am=%d pm=%d w=%d", m_regs.lfo_am_enabled() ? m_regs.lfo_am_sensitivity() : 0, m_regs.lfo_pm_sensitivity(), m_regs.lfo_waveform()); + if (m_regs.noise_enabled() && m_regs.opnum() == 3 && m_regs.chnum() == 7) + LOG(" noise=1"); + LOG("\n"); + } } @@ -1255,6 +1258,8 @@ ymfm_engine_base<RegisterType>::ymfm_engine_base(device_t &device) : m_lfo_counter(0), m_noise_lfsr(0), m_noise_counter(0), + m_noise_state(0), + m_noise_lfo(0), m_lfo_am(0), m_status(0), m_clock_prescale(RegisterType::DEFAULT_PRESCALE), @@ -1291,6 +1296,8 @@ void ymfm_engine_base<RegisterType>::save(device_t &device) device.save_item(YMFM_NAME(m_lfo_counter)); device.save_item(YMFM_NAME(m_noise_lfsr)); device.save_item(YMFM_NAME(m_noise_counter)); + device.save_item(YMFM_NAME(m_noise_state)); + device.save_item(YMFM_NAME(m_noise_lfo)); device.save_item(YMFM_NAME(m_lfo_am)); device.save_item(YMFM_NAME(m_status)); device.save_item(YMFM_NAME(m_clock_prescale)); @@ -1375,7 +1382,7 @@ void ymfm_engine_base<RegisterType>::output(s32 &lsum, s32 &rsum, u8 rshift, s16 { // noise must be non-zero to use noise on OP4, so if it is enabled, // OR with 2 (since only the LSB is actually checked for the noise state) - u8 noise = (chnum == 7 && m_regs.noise_enabled()) ? (m_noise_lfsr | 2) : 0; + u8 noise = (chnum == 7 && m_regs.noise_enabled()) ? (m_noise_state | 2) : 0; m_channel[chnum]->output(m_lfo_am, noise, lsum, rsum, rshift, clipmax); } } @@ -1439,6 +1446,7 @@ s8 ymfm_engine_base<ymopm_registers>::clock_lfo() // leading 1; this matches exactly the frequencies in the application // manual, though it might not be implemented exactly this way on chip u8 rate = m_regs.lfo_rate(); + u32 prev_counter = m_lfo_counter; m_lfo_counter += (0x10 | BIT(rate, 0, 4)) << BIT(rate, 4, 4); u8 lfo = BIT(m_lfo_counter, 22, 8); @@ -1470,11 +1478,12 @@ s8 ymfm_engine_base<ymopm_registers>::clock_lfo() // noise: case 3: - // QUESTION: totally random guess here; does the LFO counter - // play into this? Is there a separate LFSR for the LFO noise? - // Do we sample & hold the noise at a certain point based on - // the LFO counter? - am = BIT(m_noise_lfsr, 0) ? 0xff : 0; + // QUESTION: this behavior is surmised but not yet verified: + // LFO noise value is accumulated over 8 bits of LFSR and + // clocked as the LFO value transitions + if (BIT(m_lfo_counter ^ prev_counter, 22, 8) != 0) + m_noise_lfo = m_noise_lfsr & 0xff; + am = m_noise_lfo; pm = am ^ 0x80; break; } @@ -1537,18 +1546,22 @@ void ymfm_engine_base<ymopm_registers>::clock_noise() { // base noise frequency is measured at 2x 1/2 FM frequency; this means // each tick counts as two steps against the noise counter - m_noise_counter += 2; - - // compare against the frequency - u8 freq = m_regs.noise_frequency() + 1; - while (m_noise_counter >= freq) + u8 freq = m_regs.noise_frequency(); + for (int rep = 0; rep < 2; rep++) { - m_noise_counter -= freq; - - // note that the LFSR here contains the output bit in bit 0, with - // the current LFSR state in bits 1-17 + // evidence seems to suggest the LFSR is clocked continually and just + // sampled at the noise frequency for output purposes; clock it here + // twice; note that the low 8 bits are the most recent 8 bits of history + // while bits 8-24 contain the 17 bit LFSR state m_noise_lfsr >>= 1; - m_noise_lfsr |= (BIT(m_noise_lfsr, 0) ^ BIT(m_noise_lfsr, 3) ^ 1) << 17; + m_noise_lfsr |= (BIT(m_noise_lfsr, 7) ^ BIT(m_noise_lfsr, 10) ^ 1) << 24; + + // compare against the frequency and latch when we exceed it + if (m_noise_counter++ >= freq) + { + m_noise_counter = 0; + m_noise_state = BIT(m_noise_lfsr, 7); + } } } diff --git a/src/devices/sound/ymfm.h b/src/devices/sound/ymfm.h index 9d5c4197dad..33e307ed16f 100644 --- a/src/devices/sound/ymfm.h +++ b/src/devices/sound/ymfm.h @@ -799,6 +799,8 @@ private: u32 m_lfo_counter; // LFO counter u32 m_noise_lfsr; // noise LFSR state u8 m_noise_counter; // noise counter + u8 m_noise_state; // latched noise state + u8 m_noise_lfo; // latched LFO noise value u8 m_lfo_am; // current LFO AM value u8 m_status; // current status register u8 m_clock_prescale; // prescale factor (2/3/6) |