PSG tone period update

Page 1/2
| 2

By GhostwriterP

Paladin (683)

GhostwriterP's picture

27-11-2021, 16:24

Maybe it is already well known issue (just not yet for me Wink ) or maybe it is and PSG emulation bug... Or maybe there is a secret to writing the tone period registers that avoids this unwanted byproduct when updating both low and high at the same time ... which is not 100% possible and this is the problem I think.

Anyway the following basic program demonstrates the issue. The program plays an A-4 note on the PSG with some modulation:

10 SOUND 7,128+62
20 SOUND 8,13
30 SOUND 0,254:SOUND 1,0
40 FORI=0TO200:NEXT
50 SOUND 0,0:SOUND 1,1
60 FORI=0TO200:NEXT
70 GOTO 30

In emulators (openMSX, blueMSX) this sounds pretty bad. Does it also sound bad on real MSX? Can anyone confirm?
It improves a bit when changing the order of sound commands in line 50, thus:
50 SOUND 1,1:SOUND 0,0
But it is still not perfect solution, at least not in emulator (or in basic) it seems.

So is there a better way to update the tone period registers?
Or should we just live with this?

Login or register to post comments

By Grauw

Ascended (10771)

Grauw's picture

27-11-2021, 19:12

In Basic this is an issue due to the slowness of the execution. It would’ve been nice if the SOUND command could write both LSB and MSB in one go, but alas. In assembly there shouldn’t be issues with this because you can update registers quick enough.

Despite the speed of assembly there is still the possibility that between register changes the tone period is temporarily set to (near) zero. E.g. when going from frequency 100H to 0FFH and writing the MSB before the LSB, the period will briefly be 0. This can result in an extremely short oscillation momentarily. However this is of a frequency much higher than what the low pass filter circuitry in the machine will allow to pass (or what our ears can hear), so it should be filtered out and inaudible.

If one absolutely wants to avoid this, then write the LSB before the MSB if the period decreases, and write the MSB before the LSB if the period increases. This relies on the program being able to change both registers before the tone generation cycle completes, so this only works in assembly. But for most intents and purposes this seems overkill, I doubt any software bothers with it.

By GhostwriterP

Paladin (683)

GhostwriterP's picture

27-11-2021, 19:30

The issue persist also in assembler otherwise I would not have noticed Wink. You can try in Realfun 3 or Trilo Tracker yourselves. Just play an A-4 note with modulation up to +3, and you will hear it.

So that brings me back that it could still be emulator thingy, like I have said did not test this in real.

Changing the order or LSB and MSB depending the situation, maybe it does work better in assembly than it would in basic... but I do not want to go that route... although in VGM format (if not encoded sequential anyway) you could without extra cost!?

Other options I had in mind are:

  • avoid using notes A-0 to A-4 entirely (just transpose the song Wink)
  • change tuning to increase distance of the A notes to the boundary (for example use 444hz i.s.o. 440hz) which gives room for +3 emulation without crossing (should be enough)
  • use single sided (or carefully selected) modulation near A notes to avoid boundary crossing

By Grauw

Ascended (10771)

Grauw's picture

27-11-2021, 19:56

Hmm well I’ve never taken any special measures for it, but I guess it would be easy to miss since it would only really occur in quite specific situations as you describe like pitch modulating A-4 (close to the 256 threshold). I guess indeed for VGMPlay it does not matter, it updates registers in the order of the original song so it plays back in an authentic way.

I’m not sure if for a test on real hardware the BASIC program is a reliable test, due to the much longer time between register writes. Whether the transition is filtered out by the LPF filter very much depends on that this period is short.

Why don’t you want to go the route of the changing MSB / LSB? If it fixes an actual issue that you’re having… It’s a bit of a hassle, but there’s only three channels so processing overhead should be fairly negligible. But it’s true that simply avoiding the issue in the song itself is the easiest solution.

By Grauw

Ascended (10771)

Grauw's picture

27-11-2021, 20:02

p.s. On the SCC the register writes have similar issues, however it works a bit differently.

On the PSG the period counter counts up until it becomes greater than or equal to the set period, then it toggles the output and resets the counter to 0. Writing to the tone period registers does not affect the period counter.

On the SCC the period counter counts down until it becomes 0, then it advances to the next sample and resets the counter to the set period. Writing to the tone period registers resets the period counter to the set period.

By GhostwriterP

Paladin (683)

GhostwriterP's picture

28-11-2021, 13:05

Following up on this I made a video (in openMSX) that demonstrates the difference between "conventional" low-high period update order and "conditional" chosen low-high or high-low period update order in assembly.
First heard is conventional method and secondly the conditional method, alternating for 3 different patterns.
PSG_tp_update_test
The conditional method seems to work quite well and provides cleaner playback indeed. For the last pattern the difference is not that apparent anymore but still it feels cleaner the second time.
Question still outstanding is what happens on real PSG...

By Grauw

Ascended (10771)

Grauw's picture

28-11-2021, 13:24

Thanks for the video, and for testing out the suggestion! Interesting to hear the effect, I didn’t think it would be so pronounced.

I think the momentary high frequency output is not the cause of the distortion by itself, the LPF theory still makes sense to me. But what I didn’t consider is that as a side effect it also resets the period counter prematurely where it would normally complete the full cycle. I think that is what causes the audible distortion.

It sounds quite similar to what the SCC does on vibratos & pitch bends, because as we know the SCC resets the period counter on every write.

By hit9918

Prophet (2932)

hit9918's picture

28-11-2021, 16:32

It is a phase reset click. And it also sometimes happens when switching between 511 and 512 etc!
There is a fix to this. "the frequency register must never be below the intended value".
Because when the frequency register is lower than the oscilator counter register, this makes a phase reset.
While a too high frequency register value for a couple of microseconds has no effect.

By hit9918

Prophet (2932)

hit9918's picture

28-11-2021, 16:57

GhostwriterP wrote:

Question still outstanding is what happens on real PSG...

The question is whether the phase reset feature works at the speed of the 1.78Mhz, or at the speed of the counter register increment, which is 1/16?
Because then the cpu could sometimes get away without a phase reset when writing the registers in below 32 cpu cycles.

By GhostwriterP

Paladin (683)

GhostwriterP's picture

28-11-2021, 18:06

Quote:

the frequency register must never be below the intended value

so always write 255 to low part then update high part and then update low part?
Did not work in basic, but I could try it in assembly.

By Grauw

Ascended (10771)

Grauw's picture

28-11-2021, 19:26

GhostwriterP wrote:

so always write 255 to low part then update high part and then update low part?
Did not work in basic, but I could try it in assembly.

That seems to me like it should work as well, yeah!

hit9918 wrote:

The question is whether the phase reset feature works at the speed of the 1.78Mhz, or at the speed of the counter register increment, which is 1/16?

I would expect the latter.

Page 1/2
| 2