Skip to content
Tech News
← Back to articles

ZX Spectrum: Experimenting with 1-Bit Sound

read original get Retro Games THE Spectrum → more articles
Why This Matters

A hobbyist deep-dive into squeezing multichannel sound (chords), PCM and PWM playback out of the ZX Spectrum's single-bit beeper, echoing earlier tricks on the Apple II and IBM PC speaker. It's a reminder that retro hardware constraints still teach practical signal-processing and optimization lessons, and the author's candid logging of failures alongside successes is unusually useful documentation.

Key Takeaways
Worth a Look

Retro Games THE Spectrum — If reading about 1-bit beeper chords makes you want to hear them yourself, THE Spectrum is a modern full-size recreation of the classic ZX Spectrum that plugs into a modern TV via HDMI. It's a tidy way to explore Spectrum sound and software without hunting down decades-old hardware.

See Retro Games THE Spectrum on Amazon → Affiliate link — we may earn a commission on purchases, at no extra cost to you. Product picked by AI based on this article; it is not a tested recommendation.

As part of the ZX Spectrum tour, I implemented some routines that would let you play simple tones out of the 1-bit beeper. These were in large part inspired by earlier work I did on the Apple II. We know that’s not the limit, though, because we got some improbably good results out of the IBM PC’s 1-bit speaker as well. My original plan for this week was to replicate some of the advanced PC speaker techniques on the ZX Spectrum. Unfortunately, that didn’t work out as well as I’d hoped, but that’s OK because I ended up getting a bunch of other things working instead.

The main things I accomplished this week revolve around multichannel sound through the 1-bit speaker—basically, playing chords. On the side, I also recreated the simple 1-bit PCM playback from the PC Speaker article and experimented briefly with the more advanced PWM technique. Both of those end up informing some of the work with chord playback as well.

This won’t be a comprehensive guide this week; I record my failures as well as my successes on this blog, and this week racked up more than its fair share of failures.

Pulse Code Modulation and Pulse Width Modulation

Pulse code modulation is a pretty simple concept: a waveform is sampled as a series of values between 0 and some maximum value, and those values are sent to the hardware to be converted into speaker voltages. The larger the maximum value, the more finely-grained your control of the amplitude, and the more rapidly you send samples, the more finely-grained your control of the frequency. (One fundamental rule of signal processing is that you cannot accurately sample a waveform with a frequency more than half your sample rate.) PCM waves are generally described by the number of bits used to express each sample and then the sample rate—a high quality sample might be 16-bit 44kHz, while most use cases might be served by an 8-bit sample at sampling rates as low as 8 kHz.

The Spectrum can access its memory at approximately 1MHz, so we will be able to hit a respectable 16kHz playback even under direct, cycle-counted CPU control. However, the speaker is only ever on or off. That means that this is 1-bit PCM, which we should expect to sound pretty bad; we’ll be getting the kind of distortion that you’d get when blowing a speaker out with too much amplification, but all the time and even at low volumes.

Different models of Spectrum had slightly different CPU speeds; I’ll be using the 48K’s clock which ran at a flat 3.5 MHz for my cycle counting. Dividing that by 16,000 samples per second reveals that we’ll have to wait 219 cycles between writes. That’s a pretty cozy amount of time; we can pack a 1-bit PCM recording 8 samples to a byte and easily be able to consume it. Samples will consume about 2KB per second, which is tight on a 48K system but not disastrously so. The main problem, as we will see, will be the distortion of the sound. The implementation of this technique poses no special challenges.

Pulse width modulation is a little trickier but it promises much higher audio quality. At the electrical-signal level, PWM data sends a 1-bit pulse once every sample, and the length of the pulse indicates the intended strength of the audio signal at that sample point. (Compare PCM, which effectively sends a multi-bit digital value over the wire to accomplish this. PWM is more analog than PCM, despite being more aggressively 1-bit.) At the physical level, this manifests as a consequence of the fact that while electrical signals can change from 1 to 0 and back in a matter of nanoseconds, the physical speaker attached to the device will require tens of microseconds to actually make the journey between its “in” and “out” states. By switching the signal off at various points in its journey, the speaker’s total strength varies in a far more precisely-controllable manner than 1-bit PCM provides.

On the IBM PC, the 1-bit speaker is tied to a hardware timer, and high-quality audio may be generated by feeding that timer 7-bit PCM data. The Spectrum is not so helpful, and we’ll have to manage it with cycle counting. I did not manage to get a PWM system working to my satisfaction on the Spectrum; I do however have some leads and am convinced that the technique overall is sound.

Cycle-Exact Delays on the Z80

... continue reading