AY3 PSG duty cycle & digidrum effects

Page 1/2
| 2

By Grauw

Enlighted (7960)

Grauw's picture

11-02-2015, 00:52

I like to listen to this song and then imagine we had MSX PSG trackers like that :).

Atari trackers like this use its fast 16-bit CPU and high resolution timer interrupts to get pulse waves and digidrums. Hard to achieve on MSX, but it could get pretty far I bet! Using the hblank 15 kHz timer and some smart tables for digidrums and pulse waves… Obviously little time left to do anything else.

Here’s a PSG pulse wave test (source) I made a little while ago which plays back a pulse wave on the MSX. Just plainly timed with Z80 wait loops, nothing fancy with hsync and LUTs. Use recent openMSX builds to get a straight pulse wave, use older openMSX builds to get a nice pulse width modulation :).

Login or register to post comments

By Grauw

Enlighted (7960)

Grauw's picture

11-02-2015, 00:53

(I moved the above post from another thread, here was hit9918’s reply…)

hit9918 wrote:

The ST doesn't have a different chip, it has timer interrupt + fast cpu. I am yet to see an AY clone with real different feature.

@grauw, does the demo go with reloading the frequency register?

One doesnt need the usual interrupt rate to make digi, one just needs to reload frequency register to make different length arms.
The cpu load is much less than digi.
The nice thing is that the cpu can even be a bit late on this and jitter and it doesn't matter. The tone is perfect.
Because the bitflip is decided by AY counter / comparator (the frequency register).
The AY started counting from 0 and when you tell the new comparator value a bit later, it doesn't matter.

When timer granularity is too little, the wait time should be rather rounded up than down.
Poking to early means before AY has gotten to the flip, messes the result.

Still in the long run the timer interrupt must be exactly same hz.
When timer granularity is little, every soandso time there is some hiccup.
When starting a tone, make phase reset. When tone is short enough, no hiccup.

Well I again wonder whether 9938 sends interrupts with opened borders.
Then MSX2 could sound like the ST.

Another idea: the game for every of its loop makes a cycle estimation. With that simulate a timer interrupt.
Again, this method can stand cpu jitter and still sound clean.

Wait... it should take no more cpu to not use two arms, but say 4 different arms.
Then AY becomes synthesizer Smile

By Grauw

Enlighted (7960)

Grauw's picture

11-02-2015, 00:53

hit9918 wrote:

@grauw, does the demo go with reloading the frequency register?

The demo flips the volume register at the same frequency as the note played. As far as I was able to determine this is the method commonly used on the Atari ST. I think this is so that the PSG stays in control of the pitch while the CPU controls the pulse width. While it is ok for the pulse width to vary due to jitter and drift, the frequency must stay stable.

By Grauw

Enlighted (7960)

Grauw's picture

11-02-2015, 01:39

Some clarifications about these effects…

Pulse waves with variable duty cycle refers to taking the square wave output of the PSG and altering it to make one side of the waveform narrower. This changes the timbre of the sound.

On Atari ST, pulse waves with variable duty cycle are commonly called “SID voices”. It refers to the C64 SID chip’s ability to produce such pulse waves, though it is a common effect on synthesizers.

Youtube reference: http://youtu.be/hlXyyW7W9VI

The term “digidrums” refers to high frequency updates to the PSG’s noise output which results in very punchy drum sounds, up to the point of even playing rudimentary samples. (Maybe I’m generalising here but this is my understanding of the term.) On MSX, PSG drum effects are usually only modulated at a 60 Hz frequency at most, which makes them relatively boring.

Youtube reference: http://youtu.be/ELH1mhSemTw, http://youtu.be/ZOTjyZlOlBY

By Grauw

Enlighted (7960)

Grauw's picture

11-02-2015, 02:35

Here’s some suggested to approach to produce usable PSG pulse waves.

Step 1: Produce a stable square wave tone using the hblank bit as a timer.

This is relatively easy, e.g. given the 15.7 kHz frequency, toggle between outputting a low and a high value every 18 scanlines to produce a tone a few cents below 440 Hz (middle A). Toggle the PSG volume while the period is set to 1 (I think that should produce an audible tone), or toggle the key click bit.

Step 2: Produce this same tone using line interrupts.

You will need to experiment whether line interrupts can continue to be generated in the vertical blanking period by forcing the VDP into overscan mode. Fortunately because we’re generating audio, the stability of this will be quite easy to confirm because our ears are really sensitive to these frequencies.

Note that the line interrupt register has only 256 possible values, while the VDP displays 262 or 313 lines. I don’t know how the VDP will behave, if it’s possible to generate interrupts for all those lines. Maybe with some help with the vertical offset register.

Either way if this works reliably then it is possible to make an interrupt-driven replayer, suitable for a game. Otherwise the CPU will probably need to play music synchronously, you could interleave it with some (scanline Smile) demo effects but not much more. Maybe there would be a possibility for a mixed mode where you use line interrupts during display and synchonous timing during vertical blanking, but things’d get really tricky then.

Step 3: Match hsync to variable PSG tone frequency.

Now you can play a tone using the VDP timing, which can be used to mask a PSG-generated tone of the same pitch. Add a little offset and you’ve got a variable duty cycle. The next challenge is to deal with any number of PSG pitches.

First you need to convert a pitch period to scanlines period. The PSG counter runs at a frequency of 223.722 Hz (16 cycles / tick). The scanline timer runs at 15.700 Hz (228 cycles / tick). So: hsync_period = psg_period / 14,25. For example, a 440 Hz pitch means a PSG period of 254 per half-cycle, and 17,82456 scanlines per half-cycle.

Here we hit a problem: How do we do sub-scanline timing? We don’t, in stead we just use the PSG period counter and subtract 14,25 (<< 2) each scanline until it carries. Most of the time the period will be 18 scanlines, sometimes 17. There will be some jitter in the pulse width, but this is probably acceptable.

In stead of subtracting 14,25 it may be handier to use fixed point math, however this will introduce rounding errors which causes a slight drift in the pulse width, which will be perceived as a slow pulse width modulation effect over time. Probably acceptable as well.

By syn

Paragon (1908)

syn's picture

11-02-2015, 11:40

You mean the digidrums samples are played using the noise generator? Interesting to know.. I always thought they were played on the dma channel of the STe and on "normal" channels on ST models (using the normal sound generator to produce the samples instead of the noise generator). So they basically added a 4th channel to the psg with this Wink

Anyway interesting topic!

By hit9918

Prophet (2844)

hit9918's picture

11-02-2015, 16:40

@grauw, you could have interrupt in display area and hblank polling + interrupt simulation in the border.
The code to calculate next interrupt line, it needs to be cycle counted to know how many hblank actualy passed.
Maybe best is when it takes n + 0.5 hblanks to be safe in the middle for next resync.

a brainstorming about a datastructure.
.dw AY frequencyregister value
.dw AY frequencyregister value
.dw AY frequencyregister value
.dw 0xC000

If the value is > 0xfff, then it is end of list and at same time the address where to restart the... sample? Smile "duty-cycle-sample" Smile
Who knows what can be done with it. The list is like a run-length-encoded 1bit sample.

By dioniso

Champion (473)

dioniso's picture

11-02-2015, 19:00

This is what GUZUTA (Madonna MKII from MATRA) already did in Seleniak and Retaliot. I think he also came from the Atari scene.

By Grauw

Enlighted (7960)

Grauw's picture

11-02-2015, 20:47

Sounds good! Also the snare drum is real nice.

Since those games are for MSX1, it can’t be synced to hblank so it must’ve been implemented using Z80 cycle accurate timing (the manual suggests as much), like in my test. I notice that the sound has a dirty edge to it, it sounds better on the fast higher notes. Jitter? I wonder how much…

Recorded the channels in openMSX and looking at the wave output now… Smile

It looks like the first channel’s duty cycle isn’t stable so I wonder if the pulse mask follows the tone or uses a fixed frequency. Actually, I also see duty cycles both < and > 50% so it doesn’t use the same volume toggle-masking technique I described above, I wonder what it does precisely.

The second channel is also interesting to look at. The laser sound looks like an audio-rate envelope modulation at first sight except it doesn’t go all the way to 0 and I don’t see the YM2149’s higher envelope resolution. So it looks like it’s actually doing high frequency modulation (a digidrum). Similar for the great-sounding snare drum on the same channel, it doesn’t seem to use the noise at all, just volume modulation.

As for the third channel, the bass is made of an interrupted saw wave. I see that it has the higher resolution volume stepping so it’s an audio-rate envelope, combined with volume toggling by the CPU. The volume toggling speed matches the tone frequency.

By Grauw

Enlighted (7960)

Grauw's picture

11-02-2015, 21:03

syn wrote:

You mean the digidrums samples are played using the noise generator? Interesting to know..

Actually mentioning the word “noise” there in such a matter-of-fact way was a mistake, honestly I don’t know, it’s just my speculation Smile. I looked around and there isn’t really a wiki page or concise description about it, mostly forum threads. To me trying to using the noise channel for drums seems a logical choice, fast volume and pitch modulation wouldn’t need as high a data rate as a sample would.

But it’s hard to find a precise description of the term. I’ve also got the impression that the same term is used for various different techniques.

syn wrote:

I always thought they were played on the dma channel of the STe and on "normal" channels on ST models (using the normal sound generator to produce the samples instead of the noise generator). So they basically added a 4th channel to the psg with this Wink

At least Madonna Mk II’s song just seems to indeed use a regular channel for it and plays low-fi samples using the volume.

By syn

Paragon (1908)

syn's picture

11-02-2015, 21:32

If I'm correct, maxYMiser (one of the more popular atari trackers atm) plays digidrums through the DMA channel of the STe, and when used on a normal ST (which only got a ym2149), there are no digidrums.

About other trackers I have no information.

Page 1/2
| 2
My MSX profile