summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty
diff options
context:
space:
mode:
author Aaron Giles <aaron@aarongiles.com>2021-05-23 16:02:28 -0700
committer Aaron Giles <aaron@aarongiles.com>2021-05-23 16:02:28 -0700
commit48bde2d64798311d6581cf7102fd1631803dca87 (patch)
tree839835eecc8ab4e55c8482e2c3f4d4aa65f1d338 /3rdparty
parentac96627377b2eb960d02557dc956401ae157f280 (diff)
ymfm: Fix OPZ fine tuning and envelope shift. Now pretty much all the TX81Z built-in instruments sound reasonable.
Diffstat (limited to '3rdparty')
-rw-r--r--3rdparty/ymfm/src/ymfm_fm.ipp4
-rw-r--r--3rdparty/ymfm/src/ymfm_opz.cpp25
2 files changed, 16 insertions, 13 deletions
diff --git a/3rdparty/ymfm/src/ymfm_fm.ipp b/3rdparty/ymfm/src/ymfm_fm.ipp
index 3f85a241283..0c51a1528cf 100644
--- a/3rdparty/ymfm/src/ymfm_fm.ipp
+++ b/3rdparty/ymfm/src/ymfm_fm.ipp
@@ -768,7 +768,7 @@ void fm_operator<RegisterType>::clock_phase(int32_t lfo_raw_pm)
template<class RegisterType>
uint32_t fm_operator<RegisterType>::envelope_attenuation(uint32_t am_offset) const
{
- uint32_t result = m_env_attenuation;
+ uint32_t result = m_env_attenuation >> m_cache.eg_shift;
// invert if necessary due to SSG-EG
if (RegisterType::EG_HAS_SSG && m_ssg_inverted)
@@ -782,7 +782,7 @@ uint32_t fm_operator<RegisterType>::envelope_attenuation(uint32_t am_offset) con
result += m_cache.total_level;
// clamp to max, apply shift, and return
- return std::min<uint32_t>(result, 0x3ff) >> m_cache.eg_shift;
+ return std::min<uint32_t>(result, 0x3ff);
}
diff --git a/3rdparty/ymfm/src/ymfm_opz.cpp b/3rdparty/ymfm/src/ymfm_opz.cpp
index fc6a3ab44c4..8ee0cd9ab66 100644
--- a/3rdparty/ymfm/src/ymfm_opz.cpp
+++ b/3rdparty/ymfm/src/ymfm_opz.cpp
@@ -423,10 +423,12 @@ void opz_registers::cache_operator_data(uint32_t choffs, uint32_t opoffs, opdata
// detune adjustment
cache.detune = detune_adjustment(op_detune(opoffs), keycode);
- // multiple value, as an x.1 value (0 means 0.5)
- cache.multiple = op_multiple(opoffs) * 2;
+ // multiple value, as an x.4 value (0 means 0.5)
+ // the "fine" control provides the fractional bits
+ cache.multiple = op_multiple(opoffs) << 4;
if (cache.multiple == 0)
- cache.multiple = 1;
+ cache.multiple = 0x08;
+ cache.multiple |= op_fine(opoffs);
// phase step, or PHASE_STEP_DYNAMIC if PM is active; this depends on
// block_freq, detune, and multiple, so compute it after we've done those;
@@ -490,6 +492,10 @@ uint32_t opz_registers::compute_phase_step(uint32_t choffs, uint32_t opoffs, opd
substep += 75 * freq;
phase_step = substep >> 12;
m_phase_substep[opoffs] = substep & 0xfff;
+
+ // detune/multiple occupy the same space as fix_range/fix_frequency so
+ // don't apply them in addition
+ return phase_step;
}
else
{
@@ -498,9 +504,6 @@ uint32_t opz_registers::compute_phase_step(uint32_t choffs, uint32_t opoffs, opd
static const int16_t s_detune2_delta[4] = { 0, (600*64+50)/100, (781*64+50)/100, (950*64+50)/100 };
int32_t delta = s_detune2_delta[op_detune2(opoffs)];
- // the fine parameter seems to add 1/16th of an octave per unit
- delta += op_fine(opoffs) * (12*64)/16;
-
// add in the PM deltas
uint32_t pm_sensitivity = ch_lfo_pm_sens(choffs);
if (pm_sensitivity != 0)
@@ -532,13 +535,13 @@ uint32_t opz_registers::compute_phase_step(uint32_t choffs, uint32_t opoffs, opd
// apply delta and convert to a frequency number; this translation is
// the same as OPM so just re-use that helper
phase_step = opm_key_code_to_phase_step(cache.block_freq, delta);
- }
- // apply detune based on the keycode
- phase_step += cache.detune;
+ // apply detune based on the keycode
+ phase_step += cache.detune;
- // apply frequency multiplier (which is cached as an x.1 value)
- return (phase_step * cache.multiple) >> 1;
+ // apply frequency multiplier (which is cached as an x.4 value)
+ return (phase_step * cache.multiple) >> 4;
+ }
}