aaronsgiles / ymfm

BSD-licensed Yamaha FM sound cores (OPM, OPN, OPL, and others)
BSD 3-Clause "New" or "Revised" License
260 stars 40 forks source link

Attack glitch issue #7

Closed LeonardoDemartino closed 2 years ago

LeonardoDemartino commented 3 years ago

I'm using on my tracker the approach @aaronsgiles proposed some weeks ago on #1 (about writing only 1 register per clock() as a conservative approach to avoid spam the chips). So far so good for YM2612 and YM2610, however, on YM2151, first notes of certain instruments have some missing registers writes, after that first note subsequent notes are sounding just fine (so the first note is being triggered before the preset data was processed internally). This is an issue that #1 fixed on the other chips, but not for YM2151.

Does the YM2151 have a specific quirk I must know about? Maybe this is related with it having a slower internal clock (3,5mhz vs ~8mhz)? Maybe is there a recommended order to write instrument data?

I double checked and my tracker is indeed sending 1 register write per clock. Here is an example .vgm: https://deflemask.com/waits_bug.vgm

This is how it sounds on my tracker: https://deflemask.com/waits_bug.wav

And this is how it should sound: https://deflemask.com/waits_ok.wav

aaronsgiles commented 3 years ago

It shouldn't matter which chip, as long as you wait one sample period between writes. I'll take a listen.

One other possibility is that maybe my YM2151 isn't being initialized to the expected state.

LeonardoDemartino commented 3 years ago

I did some more investigation. This have to do with operator 1 not starting the envelope in some particular cases. Only seems to happen if the attack of the first operator is >=0x17 && <=0x1E on this particular instrument.

aaronsgiles commented 3 years ago

Ok, fixed this. There was a documented glitch in the YM2612 where changing the attack rate after key on would cause attacks not to happen for certain values. This was tripping for this case. Apparently this glitch is specific to the OPNA, so I've narrowed its effect.

LeonardoDemartino commented 3 years ago

Thanks, that fixed the problem!

nukeykt commented 3 years ago

Attack glitch is not exclusive to OPN family. It happens on OPM, OPL(including OPLL) families as well.

aaronsgiles commented 3 years ago

@nukeykt Thanks for that info. Seems I need to find another way to address this then.

The VGM in question issues a key on before setting any frequency, so it starts at freq=0. The first 2 ops have fast attack rates of 0x19 and 0x1C and a large keyscale rate of 3. Since the freq=0, the keycode value is also 0 so the effective attack rate of these two ops is 0x32 and 0x38.

It then changes the frequency to 0x1100, giving a keycode of 0x11. With the large keyscale rate, this redlines the attack rate after the key on to 0x3F for both operators, preventing them from ever incrementing due to the glitch.

Random thoughts:

  1. If the frequency had been set before the key on, the key on would have seen the attack rate at max and done an immediate attack. Since this is the first note being played in the VGM, we have the unusual previous frequency of 0.
  2. Due to pipelining I've noticed nuked tends to start the key on behavior a cycle or two later than I do. I've been debating whether to introduce a similar delay. If the key on were processed one FM clock later, the first half of the frequency would have been written, and perhaps the initial attack computation would go to 0x3F when we started.

I'll need to think on this a bit more. I'm reopening and undoing the previous fix based on @nukeykt's comment, and we'll try to dig deeper on this.

LeonardoDemartino commented 3 years ago

Your message @aaronsgiles gave me the information I needed to address the issue on the tracker side. On all new notes I was writing the "note on" event first and the frequency afterwards. Inverting those fixed the issue, at least on my end. Thanks for that insight.

aaronsgiles commented 3 years ago

Ah, glad you worked around it, though apparently ymfm should behave better here so let's leave the issue open and I will try to get the attached VGM to work as expected. :)

aaronsgiles commented 2 years ago

After examining this issue in more detail today, I've concluded that it's not really fixable without emulating (or faking) the inner details of the pipelining of the chip. Since this goes beyond the scope of where I want to go with ymfm, and since your workaround seems sufficient, I'm marking it won't fix.