Weird PSG timing

By Meits

Scribe (6338)

Meits's picture

10-04-2016, 02:17

I ran into something really odd while doing some PSG testing for a nice future product...
To get some PSG going on in basic I dug deep in my memory and came up with some simple MML:

10 DEFINT A-Z
20 A$(1)="l16 o4CEGo5C o4EGo5CE o4Go5CEG CEGo6C"
30 A$(2)="l16 o4EGo5CE o4Go5CEG CEGo6C   o5Eo6CEG"
40 B$(1)="l8  o2Co3C   o2Co3C   o2Co3C   o2Co3C"
50 C$(1)="l4  o6g      f        e        d"
60 C$(2)="l4  o6c      o5b      a        g"
70 '
80 PLAY B$(1)
90 PLAY B$(1)
100 PLAY B$(1),A$(1)
110 PLAY B$(1),A$(2)
120 PLAY B$(1),A$(1),C$(1)
130 PLAY B$(1),A$(2),C$(2)
140 GOTO 80

As you can see, at the end I play all three channels at the same time. And if you check the "l" in the start of the strings in lines 20-60 and count the capital letters which are the actual notes, you see that this "l" stands for the length of the note to be played. l16 contains twice as many notes as l8 which contains twice as many notes as l4.
So, everything should be perfectly in sync... Well... Try for yourself...

Now the funny thing...
For this next step you need an MSX-Music connected...

_music
play #2,"c"

This plays a C on your MSX-Music.

If you run the MML listing again now, which still plays on your PSG, it'll all be perfectly in harmony.

I've tested this on a turbo R in z80 and r800 mode as well as on a Philips NMS8250 on 3.5MHz and 7MHz. openMSX emulates this issue as well...

I've been out of MML business since FAC soundtracker 1.0 1991 was released (was it 1991?), so my knowledge about this curious thing is not clear to me. But yet it bothers me not knowing why this occurs.

Login or register to post comments

By flyguille

Prophet (3028)

flyguille's picture

10-04-2016, 03:01

maybe basic is slow, for when it process the data per the third channel, a new vblank happens and channel 1 & 2 desync regard channel 3.... and so...

Also you are adding new streams, without testing if the previous one is done IIRC if play(1) for channel 1, etc.

concatenating in buffer, well buffer will get out of space, and blocking the basic listing from being executed, waiting to release enough buffer for copying all the new stream, then release to the next instruction.

next instruction, or item in the list, so the next can be the stream for the channel2, delayed regard channel 1, and so.

By Meits

Scribe (6338)

Meits's picture

10-04-2016, 03:23

That sounds logical, though I can't recall I ever needed it in the 80s. But once the MSX-Music played just one note the listing plays perfectly well on PSG. That's what puzzles me...

By NYYRIKKI

Enlighted (5735)

NYYRIKKI's picture

10-04-2016, 03:50

The problem is that PLAY-command pushes the data to the buffer immediately when there is enough space and then the BASIC program continues. Now what happens is that you push channel A buffer full while channel C buffer is empty. When BASIC program comes to line where it should play on channel C it fills the buffer because it is empty, but channel A buffer is not empty so that needs to wait before more data can be put it. If you really don't want to fill the buffer with rests ("R") then I suggest that you use PLAY()-function to wait before you continue. On MSX-MUSIC I think this can be controlled more easily with CALL BGM-command.

I guess the CALL MUSIC command patches the PLAY-command so that this feature gets removed, but funny side effect indeed.

Edit: Ah, I forgot that MSX-MUSIC keeps copy of the FM-registers in RAM... because it does not have better place to put these it uses the space that is normally use by PLAY-command queues. I bet here is the main reason for this effect: There is simply no space to queue anything anymore.

By Pencioner

Scribe (1351)

Pencioner's picture

10-04-2016, 09:17

Meits wrote:

That sounds logical, though I can't recall I ever needed it in the 80s. But once the MSX-Music played just one note the listing plays perfectly well on PSG. That's what puzzles me...

I've ran into this issue with PSG back at 1991 (coded the Mozart Rondo via PLAY in Basic, used 3 channels simultaneously) - so that i've split the lines in the weird way being not equal pieces for every channel - all by try-and-see experimenting, i remember i spent few days until i made it play flawlessly (the source is lost, though, i've lost all my floppies with MSX stuff from that times...).

I think some (dispatch?) routine used by Basic is replaced by the one from MSX-Music that's why it then plays perfectly even in PSG.

By umaiboux

Resident (43)

umaiboux's picture

10-04-2016, 10:02

I tried on openMSX(FS-A1ST R800 mode).

100 DEFINT A-Z
110 PLAY"T120","T120","T120"
120 FORH=1TO2
130 A$="L4 ":B$="C   C   C   C   C   C   C   C   C   C   C   C   C   C   C   C   ":GOSUB1000
140 A$="L8 ":B$="C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C ":GOSUB1000
150 A$="L16":B$="CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC":GOSUB1000
160 NEXT
170 END
1000 '
1010 PLAY A$
1020 FORI=0TO1:I=PLAY(1)+1:NEXT
1030 TIME=0
1040 FORI=1TO10:PLAYB$:NEXT
1050 FORI=0TO1:I=PLAY(1)+1:NEXT
1060 PRINT TIME:RETURN

Before CALL MUSIC, the length of "T120C16C16" seems not equal to "T120C8".
"T120C8" : 15/60 seconds
"T120C16" : should be 7.5/60 seconds, but in fact 7/60 seconds

- even before CALL MUSIC, the length of "T128C16C16" seems equal to "T128C8".
- after CALL MUSIC, the length of "T120C16C16" seems equal to "T120C8".

By st1mpy

Paladin (709)

st1mpy's picture

10-04-2016, 11:15

is this about this link?

it says it was fixed in turboR basic 4.1.
the timing issue at the end of play statement having extra space.

By Meits

Scribe (6338)

Meits's picture

06-03-2021, 10:45

I just read the interview with the former ASCII employee and it made me think of this particular issue (miracle I could find it again :) ).
It doesn't sound any better on an MSX turbo R GT, so I guess it was something else.