The CoCo has two internal sources for generating audio. One of those is a 1-bit output for generating square waves, similar to what was available on the original IBM PC. The other is a 6-bit DAC for generating 64 levels of unsigned PCM audio. Also available is an audio source line tied to the external cartridge slot. A handful of cartridges were available for the CoCo that took advantage of this feature, including the Tandy Speech/Sound Cartridge (SSC). A fourth potential sound source is the cassette port, but that source seems impractical for use in a game like Fahrfall.
The best option both in terms of maximizing the sound quality and in terms of minimizing the cycle budget cost would be to use an SSC for music and sound effects. The SSC includes both an AY-3-8913 Programmable Sound Generator and an SPO256-AL2 Speech Processor, making it capable of producing a wide variety of sounds with limited intervention from the CPU. Unfortunately, the SSC is somewhat rare these days and many potential CoCoNuts don't have an SSC at all. I may save SSC support as a back-up plan in case I can't get Fahrfall to produce CPU-driven music to my satisfaction. For the near term, I will stick to a few simple sound effects that I know the CPU can drive already.
Using the DAC to produce sounds would be the next best option in terms of sound quality. Unfortunately, producing non-square waveforms at any but the lowest of frequencies will require timing more precise than Fahrfall is prepared to do at the moment. However, the vertical synchronization timing should be able to produce a few effects based on square waves. For now, Fahrfall will stick to use of the 1-bit sound output.
Timing The Waves
What can one do with a 1-bit output and a 60 Hz timer? Well, alternating between '0' and '1' on that output every cycle will generate a low, raspy tone. Modulating that tone can produce a "tic-tic-tic" sound, and we can pretend that the "tic-tic-tic" sounds like a series of footfalls as someone walks across a moving platform. :-)
It just so happens that the background scrolls in Fahrfall are already running during every frame cycle, each following a repeating sequence of 2, 4, 6, or 8 frames. Hitting the 1-bit output in each half of the 2-frame sequence provides the basic tone, and enabling or disabling the output every other frame of the 4-frame sequence provides the modulation for the "tic-tic-tic" sound. Using a variable to control the value written to the 1-bit output when it goes "high" (so that sometimes "high" really just writes a '0' value, the same as "low") allows for the sound output to happen without any conditional branching. This makes it very cost-effective to have the footfall sound available when the player object is moving on the platforms and to still be able to turn it off when the player object is standing still or falling.
In addition to the footfall sound, I also wanted a sound to go along with the end of each game. Since the game is already over at that point, it is OK for everything to stop while such a sound is played. So, I expanded Fahrfall's "game over" routine to poll the horizontal sync signal for about a quarter of a second. After each horizontal sync signal, the LFSR is advanced and the data from the LFSR is used to drive the 1-bit sound output. This produces a white noise output that is slightly disconcerting -- just enough to let the player know that the game is over and that they should feel bad about it... :-)
The addition of these simple effects makes a difference when playing Fahrfall. It just feels a bit more "real" now, and the white noise at the end of the game is just enough of a scold to make you "feel" it -- hopefully enough to make you want to play some more! In the future, I want to add music to the title screen and some background music to the game itself. But for now, this seems to be good enough.
Just a few more days left for the RetroChallenge Winter Warmup... Keep watching for more updates!