Jump to content
IGNORED

Using Pulse Density Modulation for 8-bit PCM


kool kitty89

Recommended Posts

I'm not sure if this technique is ever actually used in existing games or demos, but using 2 POKEY channels and two timers, it should be possible to get 8-bit linear PCM output through POKEY. Set one timer to the desired sample rate and set one 4-bit volume level for the upper 4 bits of a sample while the lower 4 bits go to the other channel. The second channel gets its volume then cut again to 1/16 by using the second timer to set the duration of the pulse to 1/16 of a sample period. Yes you'd get noise at low sample rates (more and more audible below 11 kHz) but that's true to some extent for harmonics of low sample rate PCM in general. (and not the same sort of squeal and noise as 1-bit PDM/PWM on a PC speaker or beeper or whatnot)

 

Using cycle timed loops instead of interrupts (or polling) for the timing would also be possible.

 

I also know using 4-bit samples in general is often more practical on the A8 due to memory constraints (and SNR often favoring 4 bit over 8 bit at low bitrates) and that PCM playback is also CPU intensive (from previous talks with malducci, I believe 50 cycles per interrupt for decently tight code) and this method would be more CPU intensive than straight 4-bit playback, but it still seems interesting at least. (8-bit output is better for software mixing too, but that's only good if you have free cycles to dedicate to mixing, and I know multiplexing 4-bit samples on a single channel is also an option there)

 

 

I may also be misusing the term PDM, pulse-width modulation might be more correct here, but I think PDM applies. (there isn't really modulation involved either, just fixed pulse width of the lower channel ... you COULD modulate a single channel to get those added 16 volume levels, but that still takes 2 timers -or careful coding- and I don't think would sound as good)

  • Like 16
Link to comment
Share on other sites

  • 2 years later...

Amazing idea!

I implemented my take on your idea here:

github.com/lybrown/hifi

Example:

aha.car.zip

Longer example:

thecart.car.zip (21MB, 10 minutes)

I implemented 44270Hz but there's headroom to go up to 65520Hz if I take out all of the NOPs.

In Altirra you can press Ctrl+Alt+1 to toggle POKEY channel 1 where the lower 4-bits are being played, so you can hear what it sounds like with just the upper 4-bits being played as normal PCM on channel 2. You can also press Ctrl+Alt+2 to toggle channel 2 so you can hear what the lower 4 bits sound like. (Hint: it basically sounds like noise. :))

I ran the 1/16 signal as fast as it can go so it's running at 111Khz (1.77Mhz / 16). At that frequency you don't really have to synchronize the signal with the PCM signal. You can just apply the 4 lower bits to the 111Khz signal and roughly three pulses will be played at that volume.

Curious if anyone with a The!Cart can try this on real hardware.

  • Like 14
Link to comment
Share on other sites

Correction: The 1/16 signal is running at 55.4KHz. I forgot that you have to divide by 2! :dunce: All the more amazing to me that this works as well as it does then, since you're only getting about 1.25 pulses per sample. I guess that's enough.Maybe I'll try pegging to as close to 1 pulse per sample as possible and see how that sounds...

 

Note: For best quality in Altirra, I've found it's best to disable non-linear mixing. This could bode poorly for the quality on real hardware. Maybe if we massage the waveform to fit the 256 voltage-levels observed on real hardware we can improve things.

Link to comment
Share on other sites

Nice!

 

Two questions.. would doing:

 

lda hi,x

ldy lo,x

sta audc2

sty audc1

 

instead of:

 

lda hi,x

sta audc2

lda lo,x

sta audc1

 

..improve anything?

 

And do you think it still would sound good at 15.7 KHz?

 

  • Like 1
Link to comment
Share on other sites

That sounds pretty good, the notice definitely noticable.

 

Strange request though... even without the low bits it sounds way better than most A8 sampling due to the high rate.

How about a test at lower bitrates like 8, 16 KHz?

  • Like 1
Link to comment
Share on other sites

Note: For best quality in Altirra, I've found it's best to disable non-linear mixing. This could bode poorly for the quality on real hardware. Maybe if we massage the waveform to fit the 256 voltage-levels observed on real hardware we can improve things.

Presumably the real voltage levels are very close together at higher volumes, losing effective bits in the same way as PCM(?)

 

BTW this is all very awesome!

Link to comment
Share on other sites

Correction: The 1/16 signal is running at 55.4KHz. I forgot that you have to divide by 2! :dunce: All the more amazing to me that this works as well as it does then, since you're only getting about 1.25 pulses per sample. I guess that's enough.Maybe I'll try pegging to as close to 1 pulse per sample as possible and see how that sounds...

 

Note: For best quality in Altirra, I've found it's best to disable non-linear mixing. This could bode poorly for the quality on real hardware. Maybe if we massage the waveform to fit the 256 voltage-levels observed on real hardware we can improve things.

 

That's actually great. I mean the fact the 1/16 signal doesn't have to run at sample frequency at all. You can the 8kHz sample rate without the 1/16 signal being audible. Simply run the 1/16 signal as high as real hardware can reliably mix it.

  • Like 1
Link to comment
Share on other sites

Its frequency really is 110840 Hz (PAL), there is no divide by two when hi-pass filter is enabled.

 

Oh yeah, because the waveforms are XOR'ed so you get two pulses per period. Awesome!

 

BTW, I tried other periods like 1/13, 1/14, 1/15, 1/17 and some of them sound pretty good. Maybe something to tune for real hardware?

 

Nice!

 

Two questions.. would doing:

 

lda hi,x

ldy lo,x

sta audc2

sty audc1

 

instead of:

 

lda hi,x

sta audc2

lda lo,x

sta audc1

 

..improve anything?

 

And do you think it still would sound good at 15.7 KHz?

 

 

I actually had it that way at first (first version), but I was trying to make the cart code simpler so I tried it the other way and it sounded the same to me. Need to break out the test and measurement equipment for a quantitative answer. :)

 

That sounds pretty good, the notice definitely noticable.

 

Strange request though... even without the low bits it sounds way better than most A8 sampling due to the high rate.

How about a test at lower bitrates like 8, 16 KHz?

 

On my todo list. :)

 

Presumably the real voltage levels are very close together at higher volumes, losing effective bits in the same way as PCM(?)

 

BTW this is all very awesome!

 

That's what I'm guessing as well. I wonder if there are also non-monotonic transitions in POKEY's DACs like there are in GTIA for example between luminances 7 and 8 in 16-luma mode. Maybe if we had an accurate model of POKEY's DACs we could massage the waveform data to compensate.

 

This is bloody remarkable. Pity there isn't time to issue IDE sector read requests, otherwise we could play huge files direct from FAT partitions on one of the currently available hard disk solutions. Really astounding quality, though.

 

I wouldn't say IDE is out of the question. There's quite a bit of CPU left over. :)

  • Like 2
Link to comment
Share on other sites

I wouldn't say IDE is out of the question. There's quite a bit of CPU left over. :)

I ran the AHA tune in Altirra and it looked like the CPU was flat-out at first, but I can see now the NOP and there's also time to update HPOSP0 every few cycles, so yeah. :) The trick will be waiting for the IDE sector buffer to become ready after a read request. Ideally you'd continue playing during that phase, but since we'd be feeding directly off the IDE data register, we'd be stuck for a few milliseconds waiting for the data to become ready. Such a player would be pretty convenient, though.

  • Like 4
Link to comment
Share on other sites

Just thinking: we don't need a pointer at all if reading from the IDE data register: it's just repeated loads from the same location, plus the overhead of reading the next cluster (assuming we issue multi-sector reads to grab whole clusters at a time).

  • Like 3
Link to comment
Share on other sites

Holly shit. Really PCM 8bit @ 44khz ?! This sounds amazing. What a great idea.

 

So can this idea be applied only with Pokey or is that idea convertible to e.g. C64 SID? (I'm asking that I can provocate my C64-fanboy neighbor *gg)

Link to comment
Share on other sites

 

 

I wouldn't say IDE is out of the question. There's quite a bit of CPU left over. icon_smile.gif

 

At at the end you guys discover that there is still CPU left for some smart MP3-decoding *ggg

But honestly, how much of an impact to quality would it be with IDE data feed?

Link to comment
Share on other sites

Holly shit. Really PCM 8bit @ 44khz ?! This sounds amazing. What a great idea.

 

So can this idea be applied only with Pokey or is that idea convertible to e.g. C64 SID? (I'm asking that I can provocate my C64-fanboy neighbor *gg)

 

See here. :)

  • Like 1
Link to comment
Share on other sites

But honestly, how much of an impact to quality would it be with IDE data feed?

Avery's video player issues multi-sector reads (17 sectors) and expects the data to be ready 4ms after issuing the command, and this equates to 47 scan lines (during which he plays buffered audio). Here, we'd be issuing 8 sector or 16 sector reads (for 4K or 8K clusters), with the sector numbers derived from a pre-computed list built when traversing the FAT chain when the file was first opened. So it seems to me some clever method of keeping the player running during that 4ms wait period is required (it may be less than 4ms, and we can get out early by polling the DRQ bit). Perhaps some clever interleave would allow preparation of a cache large enough to keep things moving during down-time.

 

This is all assuming the current data rate is somehow preserved, ideally resulting in no quality reduction. :)

Edited by flashjazzcat
  • Like 2
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...