Sampled sound on the sn76489 -- tests

discuss bbc micro and electron emulators (including mame) here!
User avatar
scarybeasts
Posts: 559
Joined: Tue Feb 06, 2018 7:44 am
Contact:

Sampled sound on the sn76489 -- tests

Post by scarybeasts » Wed Jul 24, 2019 11:11 am

Hi,

As is well documented, the sn76489 in the BBC is capable of sampled sound playback. See e.g. Spy Hunter loading screen or game start of sideways RAM version Exile.

This is achieved by rapidly modulating the 4-bit volume of one or more of the three tone channels, where said channel is programmed with a period value of 1. Programming a tone channel with period 1 causes it to stop oscillating and emit a constant voltage, which is the basis for the volume modulation trick.

I have a couple of tests to see whether the noise channel has a similar capability. On the attached SSD:

- TONE1
Synthesizes a 30.5Hz square wave (lower than the sound chip can naturally produce) on a tone channel, to give an idea of what a successful test sounds like.

- NOISE1
Synthesizes a 30.5Hz square wave on a noise channel, using "method 1", which is to keep the output constant by repeatedly rewriting the noise control register.
This method works in b-em and jsbeeb, and matches my reading of the data sheet. Will be interesting to see if the real hardware behaves as expected.

- NOISE2
Synthesizes a 30.5Hz square wave on a noise channel, using "method 2". "Method 2" sets the noise channel to period 1 by using the noise channel mode where the period is pegged to the period of one of tone channels. I haven't seen it documented anywhere whether this will trigger the "stop oscillation" trick on the noise channel or not.
The emulators don't seem to like this trick, they emit a 30.5Hz scratching of noise instead of a 30.5Hz square wave. But this doesn't guarantee the real hardware is the same.


Anyway, if anyone is inclined, this is a fun little "listen" test: do NOISE1 and NOISE2 sound like TONE1 or are they different?


Cheers
Chris
Attachments
noise.ssd
(200 KiB) Downloaded 65 times

User avatar
sweh
Posts: 2262
Joined: Sat Mar 10, 2012 12:05 pm
Location: New York, New York
Contact:

Re: Sampled sound on the sn76489 -- tests

Post by sweh » Wed Jul 24, 2019 11:50 am

You might be interested in this disk, from BITD
Attachments
231.Digital_Music.ssd
(200 KiB) Downloaded 64 times
Rgds
Stephen

User avatar
tricky
Posts: 4676
Joined: Tue Jun 21, 2011 9:25 am
Contact:

Re: Sampled sound on the sn76489 -- tests

Post by tricky » Wed Jul 24, 2019 1:17 pm

My AstroBlaster also plays sampled speech at startup, I also write the 4 bit value to the high bits of the parallel port incase anyone has a resistor ladder attached as a D2A.

User avatar
scarybeasts
Posts: 559
Joined: Tue Feb 06, 2018 7:44 am
Contact:

Re: Sampled sound on the sn76489 -- tests

Post by scarybeasts » Sat Jul 27, 2019 9:46 am

Ping on this thread -- anyone able to run the test cases on a real beeb to see what they sound like?

I can paste the file content here as text if that would help.

User avatar
tricky
Posts: 4676
Joined: Tue Jun 21, 2011 9:25 am
Contact:

Re: Sampled sound on the sn76489 -- tests

Post by tricky » Sat Jul 27, 2019 10:40 am

Here is a recording of them on a ModelB, recorded via the TV on a mobile phone with a CTRL-G at the start for comparison.
https://www.dropbox.com/s/pvrpnroueedxg ... .3gpp?dl=0 no login or password should be required.
The first one seemed to make the odd occasional very quiet click.
I would say that b-em is close on noise 2, but beebem is off by much, neither make noise1 silent like on my model B.
Last edited by tricky on Sat Jul 27, 2019 10:48 am, edited 1 time in total.

User avatar
simonm
Posts: 316
Joined: Mon May 09, 2016 3:40 pm
Contact:

Re: Sampled sound on the sn76489 -- tests

Post by simonm » Sat Jul 27, 2019 1:03 pm

This is a very interesting topic.
I'm unsure how it might work though, because as I understand it, the noise LFSR is reset such that the top bit (bit 15) is set and the low bit (bit 0) is clear (0x8000), and it is the low bit 0 that is output to the mixer, so that means the output is low on reset - not the constant level that we want.

It's not clear which direction the LFSR shifts when the noise frequency counter reaches 0, but most emulations seem to assume it shifts left to right. So if that's correct:

In periodic noise mode, it will take 16 duty cycles for the top bit to be shifted down to bit 0 and the output to go high. That set bit is then fed back into bit 14 (on the BBC's version of the SN76489 anyway) and the process repeats. So there will only be a high output every 1/15 duty cycles.

In white noise mode, output bit 0 is still going to be 0 on reset, and remain 0 until 16 duty cycles have occurred before high bit 15 reaches the output bit, however all following bits are going to be pseudo random rather than constant level, even in tuned mode with channel 2 set to a period of 1, so again, not the constant level we want.

I keep meaning to do an oscilloscope look at the output because the "stop oscillation" trick still seems like unfinished business. Setting a frequency counter to 1 is a valid setting; it creates the highest valid frequency - 125Khz on a 4Mhz BBC - an "almost constant" waveform - however the thing I'd like to really know is exactly what the chip does when you set the frequency counter to 0, because essentially that is a divide by zero, and perhaps the only way that a constant level output could be achieved (on tone channels anyway). If it does stop oscillation then in principle, with an assumed ability to achieve almost quantum precision timing, it might be possible to begin a noise sound and then set the frequency to 0 at precisely the right time when there happens to be a 1 in bit 0 on the LFSR, in order to "hold" that output level and then modulate the volume levels for sample playback on the noise channel too.

Food for thought.
Last edited by simonm on Sat Jul 27, 2019 1:07 pm, edited 4 times in total.

User avatar
simonm
Posts: 316
Joined: Mon May 09, 2016 3:40 pm
Contact:

Re: Sampled sound on the sn76489 -- tests

Post by simonm » Sat Jul 27, 2019 1:54 pm

Just a note that I have read conflicting opinion on whether or not setting the tone register to 1 generates a square wave or a constant level. If the chip logic is:
decrement counter
if 0, flip output bit, reload counter

Then we'd expect a 125Khz square wave if the tone register is set to 1.

However other sources say the chip outputs a constant level in this scenario. Would be good to determine this via oscilloscope.

User avatar
Rich Talbot-Watkins
Posts: 1662
Joined: Thu Jan 13, 2005 5:20 pm
Location: Palma, Mallorca
Contact:

Re: Sampled sound on the sn76489 -- tests

Post by Rich Talbot-Watkins » Sat Jul 27, 2019 5:48 pm

Fairly sure the sound chip will be generating a 125kHz square wave. In practice, the speaker will certainly not be able to physically reproduce that, so you get what seems to be a constant level. It wouldn't make sense for the SN chip to treat frequency 1 differently and output a constant level in this case.

User avatar
tricky
Posts: 4676
Joined: Tue Jun 21, 2011 9:25 am
Contact:

Re: Sampled sound on the sn76489 -- tests

Post by tricky » Sat Jul 27, 2019 5:58 pm

It certainly seemed half volume to me.
0 might have made sense, but I seem to remember that that was the lowest frequency - but my memory is very poor!

User avatar
scarybeasts
Posts: 559
Joined: Tue Feb 06, 2018 7:44 am
Contact:

Re: Sampled sound on the sn76489 -- tests

Post by scarybeasts » Sun Jul 28, 2019 7:28 am

tricky wrote:
Sat Jul 27, 2019 10:40 am
Here is a recording of them on a ModelB, recorded via the TV on a mobile phone with a CTRL-G at the start for comparison.
https://www.dropbox.com/s/pvrpnroueedxg ... .3gpp?dl=0 no login or password should be required.
The first one seemed to make the odd occasional very quiet click.
I would say that b-em is close on noise 2, but beebem is off by much, neither make noise1 silent like on my model B.
Thanks tricky! Love the formal announcement of each sub-test name :)

This is very useful. I sent a patch to jsbeeb and the latest live version at https://bbc.godbolt.org/ is faithful to your results. From a technical perspective, this confirms that the noise channel is oscillating between 0 and +ve. The incorrectness in the emulators causing NOISE1 to make noise was oscillation between -ve and +ve.


Cheers
Chris

User avatar
tricky
Posts: 4676
Joined: Tue Jun 21, 2011 9:25 am
Contact:

Re: Sampled sound on the sn76489 -- tests

Post by tricky » Sun Jul 28, 2019 7:36 am

I couldn't work out how to make my phone record multiple files and name them :lol: (have now!).

User avatar
scarybeasts
Posts: 559
Joined: Tue Feb 06, 2018 7:44 am
Contact:

Re: Sampled sound on the sn76489 -- tests

Post by scarybeasts » Sun Jul 28, 2019 9:32 am

simonm wrote:
Sat Jul 27, 2019 1:54 pm
Just a note that I have read conflicting opinion on whether or not setting the tone register to 1 generates a square wave or a constant level. If the chip logic is:
decrement counter
if 0, flip output bit, reload counter

Then we'd expect a 125Khz square wave if the tone register is set to 1.

However other sources say the chip outputs a constant level in this scenario. Would be good to determine this via oscilloscope.
Yes, I think this conflicting opinion is a source of a lot of propagation of incorrect information (and emulation!)
There's a good source here where someone actually tested some hardware variants and found that period 1 gives max frequency and NOT a constant output:
https://forums.nesdev.com/viewtopic.php ... 62#p190216
It also notes a difference in handling of period 0. On the BBC SN chip, this gives min frequency as we know (low tone).

Also this thread states that a root source of information is wrong and emulators all copied it(!):
http://gendev.spritesmind.net/forum/vie ... php?t=1132

I think what happened here in the BBC emulators is this:
- Everyone generally chooses to model the square waves as a transition between +ve and -ve.
- With this output mode, sampled sound will NOT work unless you add the hack where period 1 == constant output, because the average of +ve and -ve is 0 -- try amplitude modulating that and getting any noise.
- Furthermore, the hack expanded in BeebEm and b-em to cover periods 1-4 inclusive, otherwise various demos that use period==4 for sampled sound do not work.
- jsbeeb based off of b-em but only applied the hack for period==1 so a lot of sampled sound software fails.

I sent a PR for jsbeeb that is now live on https://bbc.godbolt.org/ that does the following:
- Remove special case period. There are now no periods that give a constant output.
- Model square waves as a transition between 0 and +ve.

And everything seems to work fine, with a simpler model and code. I personally consider the mystery solved!


Cheers
Chris

User avatar
scarybeasts
Posts: 559
Joined: Tue Feb 06, 2018 7:44 am
Contact:

Re: Sampled sound on the sn76489 -- tests

Post by scarybeasts » Sun Jul 28, 2019 9:37 am

simonm wrote:
Sat Jul 27, 2019 1:03 pm
This is a very interesting topic.
I'm unsure how it might work though, because as I understand it, the noise LFSR is reset such that the top bit (bit 15) is set and the low bit (bit 0) is clear (0x8000), and it is the low bit 0 that is output to the mixer, so that means the output is low on reset - not the constant level that we want.
I agree, it won't work.
The trick was working in the emulators because, as per my other reply, they were modeling output as +ve or -ve. This results in sound. But the correct model is +ve or 0. This results in no sound, and tricky just confirmed no sound on a real beeb.

It's a bit of a shame because this technique would have given louder output for sampled sound, and carried less risk of distortions carrying through from an underlying 125kHz square wave.


Cheers
Chris

User avatar
simonm
Posts: 316
Joined: Mon May 09, 2016 3:40 pm
Contact:

Re: Sampled sound on the sn76489 -- tests

Post by simonm » Sun Jul 28, 2019 3:01 pm

It's great that even after all these years the level of understanding about these simple components continues to be expanded.
scarybeasts wrote:
Sun Jul 28, 2019 9:32 am
Yes, I think this conflicting opinion is a source of a lot of propagation of incorrect information (and emulation!)
There's a good source here where someone actually tested some hardware variants and found that period 1 gives max frequency and NOT a constant output:
https://forums.nesdev.com/viewtopic.php ... 62#p190216
It also notes a difference in handling of period 0. On the BBC SN chip, this gives min frequency as we know (low tone).
That explanation makes more sense logically; ie. setting 0 will take 2^10 cycles to reach 0 again, so you get the lowest possible frequency. As Rich mentioned, it seems unlikely the chip contains special case logic. However, I'm sure I've written code on a real beeb before that used 0 in sample playback, but I'd need to double check that.

scarybeasts wrote:
Sun Jul 28, 2019 9:32 am
Also this thread states that a root source of information is wrong and emulators all copied it(!):
http://gendev.spritesmind.net/forum/vie ... php?t=1132

I think what happened here in the BBC emulators is this:
- Everyone generally chooses to model the square waves as a transition between +ve and -ve.
- With this output mode, sampled sound will NOT work unless you add the hack where period 1 == constant output, because the average of +ve and -ve is 0 -- try amplitude modulating that and getting any noise.
- Furthermore, the hack expanded in BeebEm and b-em to cover periods 1-4 inclusive, otherwise various demos that use period==4 for sampled sound do not work.
- jsbeeb based off of b-em but only applied the hack for period==1 so a lot of sampled sound software fails.

I sent a PR for jsbeeb that is now live on https://bbc.godbolt.org/ that does the following:
- Remove special case period. There are now no periods that give a constant output.
- Model square waves as a transition between 0 and +ve.

And everything seems to work fine, with a simpler model and code. I personally consider the mystery solved!
This is excellent work Chris, thanks. Your fix makes sampled sounds in JSBeeb just like the originals, it's surprising how few emulators reproduce these audio effects accurately.
scarybeasts wrote:
Sun Jul 28, 2019 9:37 am
simonm wrote:
Sat Jul 27, 2019 1:03 pm
This is a very interesting topic.
I'm unsure how it might work though, because as I understand it, the noise LFSR is reset such that the top bit (bit 15) is set and the low bit (bit 0) is clear (0x8000), and it is the low bit 0 that is output to the mixer, so that means the output is low on reset - not the constant level that we want.
I agree, it won't work.
The trick was working in the emulators because, as per my other reply, they were modeling output as +ve or -ve. This results in sound. But the correct model is +ve or 0. This results in no sound, and tricky just confirmed no sound on a real beeb.

It's a bit of a shame because this technique would have given louder output for sampled sound, and carried less risk of distortions carrying through from an underlying 125kHz square wave.
Yes, there'd be some really interesting possibilities if samples could be achieved on the noise channel. I'm curious now what a sample might sound like if modulated with high frequency 125Khz noise. probably awful!

For future reference, here's a link to some related discussion on this.

User avatar
simonm
Posts: 316
Joined: Mon May 09, 2016 3:40 pm
Contact:

Re: Sampled sound on the sn76489 -- tests

Post by simonm » Sun Jul 28, 2019 3:43 pm

scarybeasts wrote:
Sun Jul 28, 2019 9:32 am
I personally consider the mystery solved!
Those links you shared were very interesting Chris, and I think I've finally reached the same conclusion.
There is no scenario in the TI or Sega VDP variants of the SN76489 where oscillations can be stopped or generate a constant output level, they just have different implementations of how tone register value of 0 is handled.

In TI chips, 0 delivers a low frequency (counter = 0x400), in Sega chips 0 delivers a high frequency (counter = 0x0001).

Setting the tone register to 1 will have the same effect on both chip.

Which for sampled sounds is "using highest possible frequency which then averages into something along the lines of DC level due to lowpass filters on the chip output path".

User avatar
1024MAK
Posts: 10294
Joined: Mon Apr 18, 2011 5:46 pm
Location: Looking forward to summer in Somerset, UK...
Contact:

Re: Sampled sound on the sn76489 -- tests

Post by 1024MAK » Sun Jul 28, 2019 5:19 pm

Um, you do know that the average AC component of an AC signal (regardless of offset) is zero volts, yes?
And if the DC offset is zero volts, then the overall average of the AC signal will also be zero volts DC.

In a BBC B, the output of a SN76489 is NOT really AC, but rather switched DC pulses. The audio circuitry then processes these pulses, and puts the results through a 8kHz low pass filter. Then the resulting signal is coupled via a capacitor (which only lets AC signals through) to the power amplifier. The output of the power amplifier is then coupled via another capacitor to the loud speaker.

A 8kHz low pass filter will block frequencies significantly above 8kHz from passing. In other words, any component in the audio signal with a frequency significantly above 8kHz will not get through to the power amplifier.

So rather than thinking of DC, you should be thinking more along the lines of a low frequency (your wanted audio sample) being mixed with a higher frequency (the unwanted high frequency ‘sound’ from the sound chips frequency divider). Then the 8kHz low pass filter will be acting as a demodulator (removing the unwanted high frequency ‘sound’ from the sound chips frequency divider) to leave the lower frequency audio sample. This is a similar principle to that used for the modulation of audio (radio and TV) and video (TV) for transmission over long distances. And the resulting demodulation in the radio or TV...

Of course, the actual effect very much depends on the circuitry after the 76489, so may well sound different for different hardware...

Mark

tom_seddon
Posts: 426
Joined: Tue Aug 30, 2005 12:42 am
Contact:

Re: Sampled sound on the sn76489 -- tests

Post by tom_seddon » Sun Jul 28, 2019 7:32 pm

Thanks for this! - currently fixing b2.

[EDIT: removed something that I figured out after posting]

Regarding sound chip write enable: b2 does run the speech demo, as it has a fudge for this: allow writes to the sound chip at any time, if write is enabled. There's an internal counter that corresponds to the 16 µsec delay you're supposed to have from the 6502 end, but judging by the commit comment this didn't make any obvious difference.

This was put in there to fix an annoying buzz at the start of Repton 2's intro speech (jsbeeb link), as after trawling through the code it was looking as if some sound writes were getting lost. And I figured that maybe the chip polls ~WE, rather than watching for transitions, and that if you're careful/careless enough then you can just set ~WE=0 once and do as many writes as required.

Doing this seemed to be rather unreliable on my Master, in that some writes would get lost - but at least some would get through, suggesting my theory might be sort of on the right track. So the fudge stayed in, but I'm not exactly convinced it's the right thing...

Also on the subject of the Repton 2 speech buzz: viewtopic.php?f=4&t=10247 (haven't looked at this thread in any great detail yet though)

--Tom
Last edited by tom_seddon on Sun Jul 28, 2019 7:36 pm, edited 2 times in total.

tom_seddon
Posts: 426
Joined: Tue Aug 30, 2005 12:42 am
Contact:

Re: Sampled sound on the sn76489 -- tests

Post by tom_seddon » Sun Jul 28, 2019 8:49 pm

Regarding noise output bit 0: b2 uses the inverse of bit 0 when reading the next value for the noise output, because John K's SN76489 page mentioned this.

And the forum post linked to above also mentions this, too.

But this can't be right, surely, because the initial output would then be 1. And then NOISE1 would be alternating between outputting +1 and +0, i.e., producing sound...

--Tom

P.S. the nesdev forum post says the LFSR register rotates left, but John K's page and Maxim's page say it rotates right...

User avatar
scarybeasts
Posts: 559
Joined: Tue Feb 06, 2018 7:44 am
Contact:

Re: Sampled sound on the sn76489 -- tests

Post by scarybeasts » Sun Jul 28, 2019 9:46 pm

tom_seddon wrote:
Sun Jul 28, 2019 8:49 pm
Regarding noise output bit 0: b2 uses the inverse of bit 0 when reading the next value for the noise output, because John K's SN76489 page mentioned this.

And the forum post linked to above also mentions this, too.

But this can't be right, surely, because the initial output would then be 1. And then NOISE1 would be alternating between outputting +1 and +0, i.e., producing sound...

--Tom

P.S. the nesdev forum post says the LFSR register rotates left, but John K's page and Maxim's page say it rotates right...
Yeah, there's a lot of conflicting information and it's making me want to buy a beeb and an oscilloscope but I don't have the space at this time :)

In terms of actual evidence, though, I do think NOISE1 is pretty decisive. Although, checks of my coding are welcome so we can check it is testing what we think it is!

One more source of info I refer to (that has been assembled with a lot of testing) is the MAME code:
https://github.com/mamedev/mame/blob/ma ... n76496.cpp

It's probably the most concise source of behavior difference descriptions between the SN variants.
It agrees that LFSR always shifts right.
Output of LFSR is never inverted but one of the non-beeb SN variants does use XNOR instead of XOR in the shift function.


Cheers
Chris

User avatar
scarybeasts
Posts: 559
Joined: Tue Feb 06, 2018 7:44 am
Contact:

Re: Sampled sound on the sn76489 -- tests

Post by scarybeasts » Sun Jul 28, 2019 10:11 pm

tom_seddon wrote:
Sun Jul 28, 2019 7:32 pm
Regarding sound chip write enable: b2 does run the speech demo, as it has a fudge for this: allow writes to the sound chip at any time, if write is enabled. There's an internal counter that corresponds to the 16 µsec delay you're supposed to have from the 6502 end, but judging by the commit comment this didn't make any obvious difference.

This was put in there to fix an annoying buzz at the start of Repton 2's intro speech (jsbeeb link), as after trawling through the code it was looking as if some sound writes were getting lost. And I figured that maybe the chip polls ~WE, rather than watching for transitions, and that if you're careful/careless enough then you can just set ~WE=0 once and do as many writes as required.

Doing this seemed to be rather unreliable on my Master, in that some writes would get lost - but at least some would get through, suggesting my theory might be sort of on the right track. So the fudge stayed in, but I'm not exactly convinced it's the right thing...

Also on the subject of the Repton 2 speech buzz: viewtopic.php?f=4&t=10247 (haven't looked at this thread in any great detail yet though)

--Tom
This is next on my list to look at as Speech.dsd is the most unusually coded sampled sound playback I've seen and I want to make it work in jsbeeb to be thorough. It's great that it already worked in b2!

IMHO, the evidence we already have from Speech.dsd is interesting: it suggests that the SN chip doesn't need to see a transition on its WE pin in order to consume new bytes on the data pins. This, of course, assumes that that there are no digital or even analog WE pulse effects caused when the beeb pulls WE low when it is already low.

This makes me think the same thing as you: the SN chip is probably just grabbing the data bits whenever it can, if WE is low. You mention this was unreliable on your Master. Were you throwing data at the chip very fast, or still waiting a reasonable number of cycles to give the SN chip a chance to grab the data? After all, the poor SN is only a 250kHz device internally. I suspect super accurate emulation would need to know when in its cycle it consumes the data pins and how long the pins need to have been stable, i.e. in reality, something like the minCyclesWELow constant in jsbeeb would be variable depending on where the SN chip is in its cycle when the data gets put on the bus.

I'll cook up another test that writes output samples without ever changing WE and post it in a new thread, hopefully we'll get some great tricky narration again!


Cheers
Chris

User avatar
Richard Russell
Posts: 1668
Joined: Sun Feb 27, 2011 10:35 am
Location: Downham Market, Norfolk
Contact:

Re: Sampled sound on the sn76489 -- tests

Post by Richard Russell » Sun Jul 28, 2019 10:34 pm

tom_seddon wrote:
Sun Jul 28, 2019 8:49 pm
P.S. the nesdev forum post says the LFSR register rotates left, but John K's page and Maxim's page say it rotates right...
It depends on how you visualise the LFSR; you can think of it as shifting in either direction (you could even draw it vertically and then you'd be debating whether it shifts up or down!). What matters is that it has a maximal-length sequence, which for a 15-bit LFSR implies repeating every 32767 clocks; that happens if the feedback term is derived as an XNOR function of the last bit and the next-to-last bit. You can demonstrate that in BASIC V or later as follows:

Code: Select all

      lfsr% = 1
      N% = 0
      REPEAT
        bit14% = (lfsr% >> 14) AND 1
        bit13% = (lfsr% >> 13) AND 1
        xnor% = bit14% EOR bit13% EOR 1
        lfsr% = ((lfsr% << 1) AND &7FFF) OR xnor%
        N% += 1
      UNTIL lfsr% = 1
      PRINT "Sequence length = "; N%
BBC BASIC's PRNG also uses a maximal-length LFSR, this time with 33-bits and a sequence length of 2^33-1.

User avatar
simonm
Posts: 316
Joined: Mon May 09, 2016 3:40 pm
Contact:

Re: Sampled sound on the sn76489 -- tests

Post by simonm » Sun Jul 28, 2019 10:39 pm

tom_seddon wrote:
Sun Jul 28, 2019 8:49 pm
P.S. the nesdev forum post says the LFSR register rotates left, but John K's page and Maxim's page say it rotates right...
Strong possibility that the nesdev poster meant to type "left [to right]" I wonder? The captures of the white noise sequence that are on SMS page all show an initial sequence of 0's that correlates with the left-to-right shift so that's pretty compelling evidence.

Another example of just how just tiny differences of interpretations can really matter in this emulation lark!

[EDIT: Plus what Richard said above]

tom_seddon
Posts: 426
Joined: Tue Aug 30, 2005 12:42 am
Contact:

Re: Sampled sound on the sn76489 -- tests

Post by tom_seddon » Mon Jul 29, 2019 12:02 am

scarybeasts wrote:
Sun Jul 28, 2019 9:46 pm
One more source of info I refer to (that has been assembled with a lot of testing) is the MAME code:
https://github.com/mamedev/mame/blob/ma ... n76496.cpp

It's probably the most concise source of behavior difference descriptions between the SN variants.
It agrees that LFSR always shifts right.
Output of LFSR is never inverted but one of the non-beeb SN variants does use XNOR instead of XOR in the shift function.
My model B has a SN76489AN, and my Master has a SN76496AN.

I was wondering whether any earlier beebs would use the non-A version (since the A wasn't introduced until 1983, according to Wikipedia) - but if the MAME code is right, then I don't think it actually matters, at least not if you're just listening with your ears. Going by the code, the entire output from the chip is inverted, not just the output from the noise shift register. (Min volume = + output, and max volume = 0 output.) So NOISE1 should be silent in both cases.

--Tom

tom_seddon
Posts: 426
Joined: Tue Aug 30, 2005 12:42 am
Contact:

Re: Sampled sound on the sn76489 -- tests

Post by tom_seddon » Mon Jul 29, 2019 12:38 am

scarybeasts wrote:
Sun Jul 28, 2019 10:11 pm
This makes me think the same thing as you: the SN chip is probably just grabbing the data bits whenever it can, if WE is low. You mention this was unreliable on your Master. Were you throwing data at the chip very fast, or still waiting a reasonable number of cycles to give the SN chip a chance to grab the data? After all, the poor SN is only a 250kHz device internally. I suspect super accurate emulation would need to know when in its cycle it consumes the data pins and how long the pins need to have been stable, i.e. in reality, something like the minCyclesWELow constant in jsbeeb would be variable depending on where the SN chip is in its cycle when the data gets put on the bus.
Sending data too fast, I think! - looks like there were too few NOPs in my "normal" write routine that I was using to set up the volume registers initially. I suspect one or more of the volume commands would sometimes get lost, and it would end up playing tones on a silent channel.

Fixed code is below. It just plays two alternating tones on channel 1 with ~WE=0 the whole time.

I assume it'll just re-execute the command on every cycle if you leave it in this state? - safe enough for tone/volume, but you could I suppose end up with it resetting the noise shift register on every cycle.

--Tom

Code: Select all

10REM>WE0
20IFPAGE<&E00:PRINT"I/O PROCESSOR ONLY":STOP
30?&70=8
40MODE7
50HIMEM=&7000
60FORPASS%=0TO3STEP3:P%=&7000:[OPTPASS%
70.start
80sei
90lda#255
100sta&FE43\ddra
110sta&FE42\ddrb
120
130lda#FNvol(0,0):jsrwrite
140lda#FNvol(1,15):jsrwrite
150lda#FNvol(2,0):jsrwrite
160lda#FNvol(3,0):jsrwrite
170lda#FNfreq(1,0):jsrwrite
180lda#0:sta&FE40\~WE=0
190.loop
200lda#50:jsrwrite2
210jsrdelay
220lda#40:jsrwrite2
230jsrdelay
240jmploop
250rts
260:
270.delay:ldy#100:.delay0:ldx#0:.delay1:inx:bnedelay1:dey:bnedelay0:rts
280:
290.write
300sta&FE4F
310lda#0:sta&FE40\~WE=0
320nop:nop:nop:nop
330nop:nop:nop:nop
340lda#8:sta&FE40\~WE=1
350rts
360:
370.write2
380sta&FE4F
390rts
400]
410NEXT
420CALLstart
430END
440:
450DEFFNvol(C%,V%):=&80OR(C%*32)OR&10OR(V%EOR15)
460DEFFNfreq(C%,V%):=&80OR(C%*32)ORV%
470

User avatar
scarybeasts
Posts: 559
Joined: Tue Feb 06, 2018 7:44 am
Contact:

Re: Sampled sound on the sn76489 -- tests

Post by scarybeasts » Mon Jul 29, 2019 2:25 am

tom_seddon wrote:
Mon Jul 29, 2019 12:38 am
Fixed code is below. It just plays two alternating tones on channel 1 with ~WE=0 the whole time.

I assume it'll just re-execute the command on every cycle if you leave it in this state? - safe enough for tone/volume, but you could I suppose end up with it resetting the noise shift register on every cycle.

--Tom
Pardon my confusion, but are you describing how it behaves on real hardware or are you asking for testing? (I have no idea if you have a real beeb or not :)


Cheers
Chris

tom_seddon
Posts: 426
Joined: Tue Aug 30, 2005 12:42 am
Contact:

Re: Sampled sound on the sn76489 -- tests

Post by tom_seddon » Mon Jul 29, 2019 10:34 am

scarybeasts wrote:
Mon Jul 29, 2019 2:25 am
are you describing how it behaves on real hardware or are you asking for testing? (I have no idea if you have a real beeb or not
I've run the test on real hardware (Master, SN76494AN), and it does produce the expected sound.

I haven't done (not even really thought very hard about how to do...) any more careful testing with a noise data command to see whether a WE transition plays any part in resetting the noise shift register.

--Tom

User avatar
scarybeasts
Posts: 559
Joined: Tue Feb 06, 2018 7:44 am
Contact:

Re: Sampled sound on the sn76489 -- tests

Post by scarybeasts » Mon Jul 29, 2019 10:42 am

tom_seddon wrote:
Mon Jul 29, 2019 10:34 am
scarybeasts wrote:
Mon Jul 29, 2019 2:25 am
are you describing how it behaves on real hardware or are you asking for testing? (I have no idea if you have a real beeb or not
I've run the test on real hardware (Master, SN76494AN), and it does produce the expected sound.

I haven't done (not even really thought very hard about how to do...) any more careful testing with a noise data command to see whether a WE transition plays any part in resetting the noise shift register.

--Tom
Fantastic, thanks Tom! I'll look at fixing jsbeeb.

User avatar
Rich Talbot-Watkins
Posts: 1662
Joined: Thu Jan 13, 2005 5:20 pm
Location: Palma, Mallorca
Contact:

Re: Sampled sound on the sn76489 -- tests

Post by Rich Talbot-Watkins » Mon Jul 29, 2019 1:08 pm

I don't think I'm adding anything that hasn't already been said, but maybe it's worth tying all this stuff up in one place. My best understanding of how all this works (with reference to the datasheet and the Beeb circuit diagram) is as follows:
  • The SN76489 is clocked at 4MHz, but internally the clock is divided by 16 to give 250kHz, so this is the basic operating frequency. Notice that the pitch dividers (÷N in the diagram) divide the divided clock.
  • Following the ÷N, there's a ÷2, so this gives us our maximum frequency of 125kHz (when N=1). N=0 is the the case where it takes 1024 cycles before the 'borrow' occurs, and is therefore equivalent to N=1024.
    SN.PNG
  • The SN has /CE (chip enable) and /WE (write enable) lines - both must be low in order for the chip to load a register from the data bus. In the Beeb circuit diagram, /CE is always tied low, and /WE comes directly from the addressable latch. Therefore it follows that the SN chip doesn't require any kind of transition; just having /WE low in this case is enough to have it send data to the registers. In the Beeb's case, if /WE is held low, the SN chip will just continually load the contents of the System VIA PA0-7.
  • The SN provides a READY output which the host can use to determine when data transfer is completed, but the Beeb doesn't use any of this, and just relies on timing alone (the idea is that you can stall the CPU while write is taking place).
  • The SN76489 datasheet specifies that it requires 32 clock cycles to load data into the control register (at 4MHz), so this agrees with the AUG's 8µs, or 16 clock cycles. We can see that the registers are effectively clocked at 250kHz, which would imply that you'd only technically need 4µs in order to catch an active clock edge, so there must be some other reason why it requires two clocks to load data. We don't know what's going on in the 'decoder' block, but according to the diagram, this logic isn't clocked. Any ideas?
  • Attenuation happens as a final stage, clocked at the final pitch frequency, so I would assume that volume changes only take place at the start of a new tone cycle rather than immediately.

User avatar
simonm
Posts: 316
Joined: Mon May 09, 2016 3:40 pm
Contact:

Re: Sampled sound on the sn76489 -- tests

Post by simonm » Mon Jul 29, 2019 3:06 pm

Is it the case that all 8-bits of data are presented by the VIA to the SN chip instantaneously - Ie. within one cycle? This would be necessary to ensure the SN never reads partially set data bits/bytes.

As an exaggerated example, there were situations from home brew projects using SN76489 with an Arduino who were writing the digital pins individually bit-by-bit, but the Arduino latency was such that the SN would read incomplete bytes and generate incorrect audio. The solution there was to use 8-bit DDR writes rather than per-pin output writes. (and also handle /WE correctly, which some projects weren't).

Keeping /WE low is definitely an interesting observation, as it suggests slightly higher sample playback rates might be possible, since fewer CPU instructions will be needed between writing to the port. Especially if using the 12-bit stepped approach that puppeh mentioned a while back, where you want to minimise time delays between attenuation updates across the 3 tone channels.
Last edited by simonm on Tue Jul 30, 2019 12:17 am, edited 3 times in total.

tom_seddon
Posts: 426
Joined: Tue Aug 30, 2005 12:42 am
Contact:

Re: Sampled sound on the sn76489 -- tests

Post by tom_seddon » Mon Jul 29, 2019 10:57 pm

tom_seddon wrote:
Mon Jul 29, 2019 10:34 am
I haven't done (not even really thought very hard about how to do...) any more careful testing with a noise data command to see whether a WE transition plays any part in resetting the noise shift register.
Done, I think - see attached. It's the same as the previous test, but this time It repeatedly sets the sound chip to output low frequency white noise, with a delay between each write.

As supplied, it does things properly, by setting ~WE=0 then ~WE=1 each time. The result is white noise, with the shift register resets audible.

Change line 210 to "jsrwrite2" - now it will just leave ~WE=0 the whole time and write to the chip that way, with the same delays. Result: silence. The shift register is presumably constantly getting reset. The chip can't distinguish between the command being written once, and the CPU constantly spamming it with the same command. (I don't think this is particularly unexpected, at least not after this thread, but it's nice to know that the chip doesn't do something non-obvious...)

(Tone frequency or attenuation changes can be repeatedly submitted without any other side-effects - I think? So if you were going to program the chip this way, you could work around this issue by ensuring that a noise control write is always followed up by some other command. With 210 reading jsrwrite2, you can add, say, 211nop:nop:nop:nop:nop:nop:nop:nop:lda#FNvol(3,15):jsrwrite2 to try this out, and, sure enough, it seems to work.)

--Tom

Code: Select all

10REM>WE0-NOISE
20IFPAGE<&E00:PRINT"I/O PROCESSOR ONLY":STOP
30?&70=8
40MODE7
50*KEY10OLD|M
60HIMEM=&7000
70FORPASS%=0TO3STEP3:P%=&7000:[OPTPASS%
80.start
90sei
100lda#255
110sta&FE43\ddra
120sta&FE42\ddrb
130
140lda#FNvol(0,0):jsrwrite
150lda#FNvol(1,0):jsrwrite
160lda#FNvol(2,0):jsrwrite
170lda#FNvol(3,15):jsrwrite
180lda#0:sta&FE40\~WE=0
190.loop
200lda#FNfreq(3,4)
210jsrwrite
220jsrdelay
230jmploop
240rts
250:
260.delay:ldy#200:.delay0:ldx#0:.delay1:inx:bnedelay1:dey:bnedelay0:rts
270:
280.write
290sta&FE4F
300lda#0:sta&FE40\~WE=0
310nop:nop:nop:nop
320nop:nop:nop:nop
330lda#8:sta&FE40\~WE=1
340rts
350:
360.write2
370sta&FE4F
380rts
390]
400NEXT
410CALLstart
420END
430:
440DEFFNvol(C%,V%):=&80OR(C%*32)OR&10OR(V%EOR15)
450DEFFNfreq(C%,V%):=&80OR(C%*32)ORV%
460
Last edited by tom_seddon on Mon Jul 29, 2019 11:11 pm, edited 4 times in total.

Post Reply

Return to “8-bit acorn emulators”