summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices
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 /src/devices
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.
Diffstat (limited to 'src/devices')
-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)