Jump to content
Vuurniac

4-bit PCM audio on the 2600?

Recommended Posts

I have recently created a player for the NES that (at of a cost of 47.7% of the CPU time) is capable of playing 7-bit sampled audio at a sampling rate of 8 272Hz. I'm wondering about the possibilities with the 2600, especially some method that could work in games. A music player that would update AUDV0 on every second scanline could produce 4-bit sound at 7 860 Hz, which is enough for music like this. I made this with a bit crusher plugin just to get an idea of what it would sound like. This piece is the Ant Caves theme from MediEvil for the PlayStation. At this rate, you can pack two samples into a single byte, so the space cost is half the sampling rate, 3 930 bytes per second. This song in particular would be 7 860Hz×126 seconds / 2 = 495 180 bytes. This would fit perfectly in a 512k cartridge, but who's saying you'd need over two minutes of music in total? Taking summed output and streaming it to a channel output? It's been done before in Pitfall II, it's been done in Stella's Stocking, and in Cheitiry.

My question would be... is this a rational proposition?

Share this post


Link to post
Share on other sites

Would you plan on offloading the processing to a chip on the cartridge like Pitfall 2 does? You could do quite a lot of you moved the hard work off to a separate processor. (And space would always be an issue, but like you said, you could shrink that down)

Share this post


Link to post
Share on other sites

Are you looking to just play prerecorded data, or create it on the fly? Stay Frosty 2 uses an updated version of DPC+ and creates 3 voice 4-bit music on the fly, whereas some builds of Frantic play back prerecorded data (go to page 7 for speech only examples).

Share this post


Link to post
Share on other sites

I have recently created a player for the NES that (at of a cost of 47.7% of the CPU time) is capable of playing 7-bit sampled audio at a sampling rate of 8 272Hz. I'm wondering about the possibilities with the 2600, especially some method that could work in games. A music player that would update AUDV0 on every second scanline could produce 4-bit sound at 7 860 Hz, which is enough for music like this. I made this with a bit crusher plugin just to get an idea of what it would sound like. This piece is the Ant Caves theme from MediEvil for the PlayStation. At this rate, you can pack two samples into a single byte, so the space cost is half the sampling rate, 3 930 bytes per second. This song in particular would be 7 860Hz×126 seconds / 2 = 495 180 bytes. This would fit perfectly in a 512k cartridge, but who's saying you'd need over two minutes of music in total? Taking summed output and streaming it to a channel output? It's been done before in Pitfall II, it's been done in Stella's Stocking, and in Cheitiry.

My question would be... is this a rational proposition?

 

You reminded me of NES game "The Three Stooges" for which I did the audio/speech in the title sequence. "Hey fellas, we're in the wrong game!" - what, 20 years ago now :( That was also sampled audio and I recall that we were able to adjust the playback speed to get the voices right. But I don't recall much other than that.

  • Like 1

Share this post


Link to post
Share on other sites

I have recently created a player for the NES that (at of a cost of 47.7% of the CPU time) is capable of playing 7-bit sampled audio at a sampling rate of 8 272Hz. I'm wondering about the possibilities with the 2600, especially some method that could work in games.

 

Tjoppen has done some great work on samples on the VCS, for example here (source code with encoder is included in the download). That is certainly not usable during a game, but might give you some ideas.

 

There's also a thread somewhere on these forums about this topic, but right now I'm not sure how to find it. ;)

 

Playing samples during a game kernel doesn't seem very viable though. Not only do you usually need every cycle to display the game and will have a hard time spending instructions on audio; there's also the problem of where to store the audio data. It has to be in the same bank as the kernel and the gfx data it uses, and you cannot really afford two bank switched every second scanline on top of the audio register updates.

Share this post


Link to post
Share on other sites

I implemented two channel digital audio for the title screen in Boulder Dash. It takes away a lot of valuable CPU cycles, so I doubt it is very useful for a stock Atari 2600 without extra hardware (like DPC+).

 

And the kernel is only the easy part, keeping the audio writes exactly spaced outside the exactly timed kernel is a quite tedious challenge.

Edited by Thomas Jentzsch
  • Like 1

Share this post


Link to post
Share on other sites

I made a music player that incorporates 4-bit PCM playback for percussion. It's probably not very useful for games since a lot of raster time is used to decode bytes into pairs of samples.

 

But if you have a kernel that can realistically only use half of all the scanlines, or maybe just don't pack samples together, I can see something like it being useful in a game. The trick, then, is to play a few samples at correct/nearly correct rates and intervals during your vblank code. For percussion in particularly it doesn't need to be very exact. It's more of a problem if you have pitched sounds.

 

Some examples: https://soundcloud.com/boomlinde/oil https://soundcloud.com/boomlinde/quantum-branch

Source code: https://bitbucket.org/boomlinde/vcs-music/src

Share this post


Link to post
Share on other sites

I added a Doh! speech in my 4K Flappy that is sold in the AtariAge store.

I am (with help) also hacking Berzerk into Dr. Who vs. Daleks in 16K with sampled Daleks. Omegamatrix rewrote the playback kernel so it holds a 262 scan line.

Speech is only played on blank screens between mazes.

 

Check them out. Links are in my signature, and check out Frantic, which was using the DPC+ to play speech during gameplay.

I used Tjoppens Sound Coder source, which uses the whole 32K to digitize 1 min 10 seconds, to digitize "Popcorn".

The link to Sound Coder is also farther down this thread:

http://atariage.com/forums/topic/213275-atari-2600-demoscene/?p=2954156

 

I have some beeper demos for 2600. I'd love to know how to make those for the 2600.

xSqueeker Demo (2011) (Szuwarek, Factor 6) (PAL).bin

Share this post


Link to post
Share on other sites

xSqueeker Demo

Impressive! Does this use DPC+?

 

No DPC+. That's a 4K file.

I think the first part is using the TIA sounds to talk speech with phonemes, or unit of sound in specified language, which I also think is not English.

The music is the "beeper engine". I don't know how that tiny bit of data plays for so long, or how it is made. It gets slower, then when it goes fast again I think that's where it loops.

There's even 76 empty bytes unused!

 

I wanted to try sampling using 2 bits, but I can only modify the tools I use. I can't program from scratch the perl script and the asm decoding I have. So far I have failed packing four 2-bits into a byte in perl, and then breaking them back out in asm to play.

Share this post


Link to post
Share on other sites

I wonder how much ROM would be necessary for just the first part of the song and if a kernel with just 2 LDAs and 3 STA's would work with it.

Share this post


Link to post
Share on other sites

The music is the "beeper engine". I don't know how that tiny bit of data plays for so long, or how it is made.

As far as I understand the code, they are playing predefined pattern, which are converted into digitized music on-the-fly.

 

BTW: The demo is playing 4 channels in parallel, each uses one volume bit. Very clever.

Share this post


Link to post
Share on other sites

I wonder how much ROM would be necessary for just the first part of the song and if a kernel with just 2 LDAs and 3 STA's would work with it.

 

Not sure what you're asking here.

My sample playback started with routines I found in AtariAge's Blogs.

It was some long-ago member's successful attempt at digitizing and playback.

The digitizing is in a Perl script that takes an 8-bit, 4,000Hz WAV and packs two nybbles of volume data into each byte.

His 6507 asm playback routine does not bother with a display kernel, overscan or vertical blank, it just bangs on the Volume register.

It took quite a complex kernel just to get samples and keep a 262 scan line count in the Berzerk hack I'm doing, and even that blanks during sampled speech (but now doesn't de-synch the display).

 

If you want playback during an active screen, you will have to do as the experts say and update Vol every scan line, or every other scan line, including during Vertical Blank and Overscan.

 

The DPC/DPC+ music is similar as it is allowing 3 in tune frequencies to play short 32-byte envelopes which are like a sample fragment. This also has to be in the 6507 display kernel every(or every other) line, including vertical blank and overscan.

The less you update or if the timing throws thing off, the noisier (scratchy ) the sound becomes.

Share this post


Link to post
Share on other sites

As far as I understand the code, they are playing predefined pattern, which are converted into digitized music on-the-fly.

 

BTW: The demo is playing 4 channels in parallel, each uses one volume bit. Very clever.

That's not what I thought, and really WOW!

I'll have to visit the Atari 8-bit more and learn more about squeaker/ beepers.

I think the classic Sinclair computer only had music by using a beeper engine?

Share this post


Link to post
Share on other sites

After some experiments, I think I understand how AUDV0 is manipulated. This is how the code works:

  1. When there is no overflow in any of the additions (plus the extra check), AUDV0 is set to 15 (maximum)
  2. When any overflow happens, the corresponding bit(s) is/are set in AUDV0

While there are 4 volumes (1,2,4 and 8 ) set in step 2, the delta to 15 shows a much lower relative difference (-14, -13, -11, -7). This is very similar to setting AUDV0 to 0. So, if you replace the calculated volume with 0, you don't notice any difference.

 

The adc #$20 seems to be a hack, which is used to widen the off-time of the channel which is used to play the bass. This increases the volume of this channel. As far as I understand, the volume depends on the relation between on and off times. The bass notes have a very low value added, thus the overflow happens very rarely, which would result into a very uneven relation and a very low volume. The hack makes the relation much better.

 

I wonder how to create a better controlled on/off relation which should allow an independent volume control for all four channels.

Share this post


Link to post
Share on other sites

Not sure what you're asking here.

 

Its a 4K demo. I'm wondering how much of the music I could fit in while only using 0.5K or 1K for it. My kernel would be simple, and if you are saying I would only need to update AUDV0 once per scan line then I won't have any problem there.

Edited by BNE Jeff

Share this post


Link to post
Share on other sites

 

Its a 4K demo. I'm wondering how much of the music I could fit in while only using 0.5K or 1K.

My 4K Flappy has Homer saying, "Doh!"

That's around 600K.

  • Like 1

Share this post


Link to post
Share on other sites

My 4K Flappy has Homer saying, "Doh!"

That's around 600K.

 

Thanks- I'm talking about the squeeker music though. It seems to use much less memory than sampling doesn't it?

Share this post


Link to post
Share on other sites

Yes, but at the cost of utilizing the CPU by 100%.

 

Commented source code attached.

xsqueeker_org.asm

Edited by Thomas Jentzsch
  • Like 2

Share this post


Link to post
Share on other sites

I wonder what happens if you update AUDFx instead of AUDVx very frequently. Theoretically you should be able to create any frequency by mixing the closest two frequencies the TIA can create. I did this in Star Castle Arcade (but with a quite low update frequency) for the siren sound. With a higher update frequency, the quality should become very good.

 

And how about updating both, Volumen and Frequency independently? Could you create two different voices that way?

Share this post


Link to post
Share on other sites

Theoretically you should be able to create any frequency by mixing the closest two frequencies the TIA can create.

 

In my last experiments with this I didn't have any luck. Maybe it's nice on a per-frame basis, but I tried doing it every few scan lines and it did not have the effect I anticipated. I am not sure how the Atari 2600 derives phase for its waveforms, but I think the problem is related to that.

Share this post


Link to post
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.

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...