summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
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
commit76f7ddca50ada66a4681cac8f2e68569465dda6a (patch)
treefe2ec1a2a9fd59fbe101eaede03bc5fe3adde0f7
parent0633a88c198755c0024a3cfcee5f98de7f39f6f0 (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.
-rw-r--r--src/devices/sound/ymfm.cpp97
-rw-r--r--src/devices/sound/ymfm.h2
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)