Jump to content
IGNORED

PCM audio experiment


Recommended Posts

For a while now, I've been thinking about ways to do PCM audio on the 8-bit Atari better than the standard 4-bit PCM through volume-only mode. The way this used to be done with the PC speaker was through one-shot mode, which unfortunately POKEY lacks. I tried doing this with two-tone mode but wasn't able to get more than about 4.5-bit precision due to only being able to use the second half of each period. I realized last night that 16-bit linked timers could be used to create a one-shot timer by using the high timer to hold down the low timer after it has fired. The result is the attached music. I'm interested in knowing if it works for other people on real hardware, since the noise is less than I expected (there is a 15KHz carrier due to the technique used). You probably won't be able to get it running if you have a 65C02 or 65C816 due to a hack I used in the timer IRQ. Some of the 2.0 test builds of Altirra also have a regression in STIMER handling that prevents this from playing properly; 1.9 is OK, and this version has a bug fix:

 

http://www.virtualdub.org/beta/Altirra-2.00-test43.zip

http://www.virtualdub.org/beta/Altirra-2.00-test43-src.zip

 

The output sample precision is about 6.7 bits, but the volume is a bit low because three voices are being mixed.

Les Barricades Mysterieuses.zip

  • Like 4
Link to comment
Share on other sites

Nice. Why are you wanting a 1-shot Timer mode - Do you have variable delay among the samples?

 

Is this actually PWM ? I've just had a quick look through the code (it's a little hard to work out what's going on).

 

Also, have you considered doing away with IRQs and just using polling mode? The cycles saved might allow you to bump up the sample rate and/or have a screen active.

Link to comment
Share on other sites

Nice. Why are you wanting a 1-shot Timer mode - Do you have variable delay among the samples?

Is this actually PWM ? I've just had a quick look through the code (it's a little hard to work out what's going on).

 

The one-shot delay is how the sample is actually played. Timers 1+2 are configured in 16-bit mode but only timer 1 is enabled for sound. The IRQ routine hits STIMER to reset the outputs and writes the sample to AUDF1, causing a variable delay until the output toggles back. Because the two timers are in a 16-bit configuration, timer 1 can't fire again until a full 256 cycles and the IRQ routine runs again before this happens. Timer 4 drives the IRQ and runs off the 15KHz clock, which means it ignores the jitter caused by writing STIMER.

 

It's actually possible to run two voices this way, but you either have to restrict one to half volume (channel 3 only) or give up the IRQ timer (channels 3+4 linked). It's also possible to run an envelope on the voice by modifying AUDC1 but I abandoned that because it made the carrier beat as well.

 

Also, have you considered doing away with IRQs and just using polling mode? The cycles saved might allow you to bump up the sample rate and/or have a screen active.

 

I did, but that makes it difficult to run any other code. Currently, the mixer runs off the IRQ in page zero while the mainline plays notes and updates ADSR envelopes every 128 scanlines (I'm too lazy to change the MIDI parser back to VBI timing).

 

Currently, the IRQ takes about 85% of the CPU according to the profiler. The lowest I've gotten it with three voices is about 63% without the mixing clamp. I thought about polled operation as it would save a bunch of cycles, but that makes it much harder to run anything else in mainline, whereas this way you can run pretty much anything as long as there is enough CPU time. I tried to use the serial port to clock the IRQ to avoid needing to toggle IRQEN, which was 6 cycles faster, but the fastest I could run it was about 12.7KHz which drops the carrier too low in frequency. The main problem is that the 6502 just isn't very fast at updating the oscillators. I wonder how fast the VBXE blitter could do this -- if it could mix enough channels it could be enough to play some SNES music.

Link to comment
Share on other sites

Cool, thanks for testing.

 

Attached is little experimentation with a straight sound sample (the music clip is from an anime called Carnival Phantasm). This one requires 128K. The audio.obx file uses PWM, whereas audio-vol.obx uses traditional 4-bit volume only mode. The PWM output has less noise but you hear the carrier instead. I tried dropping the sample rate to 10KHz and then doubling it to 20KHz in the IRQ routine, but for some reason the carrier actually got louder. Rats. It works, but it's not something you'd want to listen to for a long time. I guess this technique belongs in the past with the original PC and the PalmPilot. :)

audio.zip

Link to comment
Share on other sites

On my "to-do" list is using VBXE to do the pick + mixing of virtual channels for digital sound.

 

The idea I have is to use the "ADD" mode to step through the waveforms, which would need to be massively repeated through VRAM. Then add all of the amplitudes together to get an 8-bit value and use a table lookup for AUDC values to store in 4 voices.

 

Not having 16-bit add of course makes things somewhat harder, but I reckon VBXE should allow many more virtual voices than a CPU only based system.

 

I wonder - could the carrier wave be attenuated a little by playing the same frequency pure tone on a pair of the opposite channels - or maybe by just playing a forced volume square wave on another channel?

Link to comment
Share on other sites

These will not load for me under SDX 4.44 and IDE + 2.0 (using the X command) and the machine just hangs. The machine is an NTSC 320kB 130XE. Your first demo did.

 

P.S.

These run under MyDOS 4.53 but that feels dirty and I have to load via SIO, not IDE+ :)

Link to comment
Share on other sites

These will not load for me under SDX 4.44 and IDE + 2.0 (using the X command) and the machine just hangs. The machine is an NTSC 320kB 130XE. Your first demo did.

 

This is probably a question of "proper" order of ext allocation. Sparta X uses the order "the farest banks first", i.e. 130XE banks will be allocated last. Programs should allocate in reverse order. But some use the same order as SDX and so the DOS gets destroyed.

 

These run under MyDOS 4.53 but that feels dirty and I have to load via SIO, not IDE+ :)

 

You can still load them using the IDE+ binary loader.

Edited by drac030
Link to comment
Share on other sites

A low-pass filter is what is actually needed here, specifically one that cuts off 15.7KHz and above (they're called low pass and high pass after which frequencies they allow through). This is a bit short of POKEY's capabilities, though.....

 

My first thought on the SDX load failure was also bank conflict, but that wasn't it... turns out the SDX loader simply didn't like me fiddling with PORTB at all. Changing the banks in the 320K configuration didn't help and didn't work even with 128K and USE OSRAM. I was configuring the extended bank and then letting DOS load into it, which apparently SDX doesn't like, so I had to modify it instead to load through a temporary buffer and then copy in. I've included updated versions that should load now under SDX with the X command, although you'll need to run OSRAM if you're using all of extended memory. There are 128K, 192K, and 320K versions included now. Sorry, I hardcoded the banks because I'm an extended RAM n00b.

 

Also included is an experiment at reducing the carrier. Switching to polling already helped a little bit -- at least, given my level of hearing, your dog may disagree -- but another thing I'm trying in this version is adding a little bit of inverted carrier using channel 3 to try to partially cancel it. I tried using two channel pairs to get double precision and volume but had problems with excessive distortion. I'm guessing the cause has to do with POKEY's nonlinear output.

audio2.zip

Link to comment
Share on other sites

so here is why you named your emulator "altirra", you're a big fan of anime. )))

 

 

Lol...You took your time Sergey....

 

This was answered moons ago on the blog after I asked him a few times :)

 

@Phaeron: Did you see the post from Draco about the broken ATR 1st sector in this thread?

Link to comment
Share on other sites

@Phaeron: Did you see the post from Draco about the broken ATR 1st sector in this thread?

 

Yes, he did. We have swapped few PMs about that, but no solution so far. Basically the problem is that when Altirra "mounts" ATR images from the saved configuration, 512-byters are not accessible because the emulator thinks they're 90k SD disks. Therefore the PERCOM block returned on an inquiry is wrong, in consequence SDX and tools get fooled into thinking that the sector size is 128 bytes, etc.

 

The problem disappears, when you open the File -> Disk drives and "remount" the ATRs in question manually. However, when you quit Altirra and load it back, the problem returns.

Edited by drac030
Link to comment
Share on other sites

I haven't looked at the high-pass filter / polycounters in depth but here are two general observations:

 

1. Many different bit sequences have the same average but some may integrate better than others.

 

2. It may be possible to play deeper samples using 4 or 5-bit volume-only mode for the MSBs and PWM / PDM for the LSBs.

Link to comment
Share on other sites

@Phaeron: Did you see the post from Draco about the broken ATR 1st sector in this thread?

 

Yes, he did. We have swapped few PMs about that, but no solution so far. Basically the problem is that when Altirra "mounts" ATR images from the saved configuration, 512-byters are not accessible because the emulator thinks they're 90k SD disks. Therefore the PERCOM block returned on an inquiry is wrong, in consequence SDX and tools get fooled into thinking that the sector size is 128 bytes, etc.

 

The problem disappears, when you open the File -> Disk drives and "remount" the ATRs in question manually. However, when you quit Altirra and load it back, the problem returns.

 

 

Thanks for passing that on Draco..

Link to comment
Share on other sites

I haven't looked at the high-pass filter / polycounters in depth but here are two general observations:

 

1. Many different bit sequences have the same average but some may integrate better than others.

 

2. It may be possible to play deeper samples using 4 or 5-bit volume-only mode for the MSBs and PWM / PDM for the LSBs.

 

Filters - already established they're probably no use for digital stuff but the other factor is that they have no influence when you're using forced volume mode.

 

2. I reckon that might work really well. Traditional method for the higher bits and PWM to give the lower 3 or 4 bits. The advantage should be that the carrier frequency is a lot quieter.

 

 

Request to phaeron - how about some 8-bit stuff, use bits 7-3 with 2 voices in forced volume and bits 2-0 with another voice PWM? Or maybe start simple, just 4 bits forced on 1 voice, 2 or 3 bits PWM on another.

Link to comment
Share on other sites

Hmm, lots of interest all of a sudden. I feel like I'm at a time zone disadvantage. :)

 

Music synthesis is more annoying to deal with than sample playback, so I jumped on the latter for a while. The results seem to be that it's pretty hard to get something significantly better, especially with what little CPU is available in the synth, so I think the digital part of the synth is about as good as it's going to get, except maybe I can add the channel 3 inverse carrier since it's free in terms of CPU time. Mixing volume only with PWM seems doable but much harder to deal with since the analog nature of the output has to be accounted for, and it's a lot harder to make sure the volume levels match up -- emulators are still very far from emulating analog effects properly. Activating more channels also increases distortion from high volume, which might be possible to compensate for with pre-distortion but I haven't looked into that.

 

In addition, I'd have to beef up the MIDI parser and VBI routine and create some new waveforms to get some new music in. Three channel polyphony isn't much but that could be made to work; the lack of percussion support is what worries me the most. Also, you'll have to suffer through whatever is in my MIDI directory. :-D

 

I'm working on the issues that Drac030 has identified with double and quad density disk support. I found what was causing the failures on boot -- the reset routine for the disk was reinitializing the PERCOM block to default instead of the one from the disk image -- but I still need to fix up a couple of issues in the SIO hook. Expect an update soon.

 

Oh yeah, about that demo... it seems to work fine for me (picture attached; test-44 only has disk changes from test-43). Note that Altirra doesn't emulate PAL color blending unless you enable PAL artifacting (this is actually a detail of the TV set decoding). I have to say, very colorful, though.

post-16457-0-50233200-1319003200_thumb.png

Edited by phaeron
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...