On early versions of many 8-bit computers like the Apple II, Spectrum, and even the IBM PC, there was no sound hardware other than the simple "beeper".

Programmers made sound by hitting a hardware register that pulsed the beeper on and off.

You changed the note of the beep (the tone or pitch) by changing the frequency of the pulses, which simply meant how fast or slow you hit that hardware register.

But was it also possible to control the volume on these primitive systems?

I was watching a YouTube channel of a guy programming many retro machines all in assembly with different CPUs and hardware, and at one point he mentions he doesn't know how to achieve volume control. I can't remember if I ever did it back in the day. But as the beeper wasn't amplified we always wanted it loud, so maybe we just never focused on volume?

Apparently, in the time after I'd moved from the Speccy to the Amiga, a guy named Tim Follin coded up various polyphonic Speccy beeper music routines. This is beyond my understanding to know if those controlled the music volume though.

  • 2
    The first time I heard a sound with a (roughly) constant tone and variable volume on the Apple II was Ultima II, which used a high-pitched sound that ramped up then down when you stepped through one of the gates. The best use of volume control was in Airheart. Note the Apple II gives you control over the speaker movement, making it more of a "clicker" than a "beeper". – fadden May 3 at 15:00
  • 1
    It's worth noting that to have polyphony without sounding absolutely dreadful, you basically need to have at least a couple of bits worth of volume control, otherwise adding your waves together will always introduce unpleasant artifacts. Therefore, whileI have no experience of the routines you mention, I'm confident that they did support volume control at least to somedegree. – occipita May 6 at 13:01

Yes, it's possible to effectively change the volume if you're using Pulse Width Modulation (PWM), although the timbre of the note is also affected depending on playback hardware and psycho-acoustics. Dr. Blake Troise, who makes chiptunes under the moniker Protodome, describes how in a recent paper:

The 1-Bit Instrument: The Fundamentals of 1-Bit Synthesis, Their Implementational Implications, and Instrumental Possibilities

Even though the amplitude is a constant 1-bit waveform, the narrower pulses provide a way of varying volume. These narrower pulses have incrementally less power overall to the listener; as the duty cycle approaches 0% (or, by inversion, 100%) the perceptual volume decreases with it, even though the amplitude remains the same. This effect is not a consequence of the reduction of the pulsing signal's actual, electronic, or kinetic power. Instead, the reduction in volume is a product of bandlimiting—the effect whereby frequencies beyond a particular value are not heard. [...] Thinner pulses are constructed from more powerful high-frequency harmonics than lower ones. Accordingly, as the pulses get thinner, with extremely small or extremely large duty cycles, these higher frequencies increasingly fall outside the limits of what can be replicated by the speaker. Since these elements are not present, the result is a reduction of the waveform's overall power.

Some of the earlier uses of PWM on the platforms you mention were programs from around 1980 by Paul Lutus including Electric Duet. He states:

Decreasing the duty cycle of the generating waveform increases the amplitude of high-frequency components while reducing the overall volume.

There were routines published in a few Apple II magazines that made use of this volume technique. Here's one in Nibble magazine:

Software Volume Control Goetz, Philip November 1984

It's called VOLUMETONES.DEMO on disk NIB22B.dsk.

Probably the ultimate evolution of Apple II 1-bit audio are projects written using Michael Mahon's DAC522, including RT.SYNTH and Digital Music Synthesizer & Drummer:

DAC522 is a software digital-to-analog converter for the Apple II that plays a stream of 11.025kHz sound samples through the 1-bit Apple speaker port using a pulse-width modulated (PWM) stream at a pulse rate of 22.05kHz, or two pulses per sample. The 22kHz pulse rate renders the pulses themselves virtually inaudible to human ears, but the average output, changed by varying the pulse width in proportion to sample values, reproduces the sampled sound to a precision of 5 bits.

Regarding PWM and pitch, although RT.SYNTH is single voice, its instruments are resampled dynamically to any frequency and shaped with an envelope. Here's an overview:

The fundamental problem a music synthesizer must address is the production of notes of many frequencies and arbitrary durations having specified waveshapes (voices). Storing all the needed combinations in limited memory is not practical.

A workable solution is to store each waveshape needed as a single-frequency sample, then resample this waveshape on the fly to create any desired frequency.

Most instrument sounds change as a note sounds. For example, many sounds have an "attack" that sounds different from the rest of the note. And many instrument sounds change in amplitude as a note is held, usually decaying in amplitude or changing in "timbre" or spectral composition. Synthesis of notes with changes appropriate to particular instruments, therefore, requires that the synthesized waveform change as a function of the length of time the note is played.

RT.SYNTH performs all the calculations required to carry out these tasks while it is generating the pulses corresponding to the previously calculated sample.

| improve this answer | |

I think the best you could do in some cases was alter the pulse width of the basic square wave the hardware could produce. That wouldn't really change the volume, but you could make the tone "thinner" or "fatter" at the same frequency.

One advanced technique used by some composers and sound drivers was "dithering", in which high-frequency random noise was added to a higher-resolution sample to make it audible at 1-bit resolution. It's a similar technique to image dithering. Another was to XOR several tones together to allow for a degree of polyphony. But there was still no actual volume control; the quieter the original sample, the noisier and less distinct a dithered version would be.

There were a number of three-tone-plus-noise sound chips commonly used in 8-bit micros which were also limited to square-wave tones, but could alter the volume and implement an ADSR curve. If you could get any sound out of them at all, you probably knew some way to set the volume.

| improve this answer | |
  • What does it mean to XOR a tone on these systems that didn't have anything like a sine-wave buffer? – hippietrail May 3 at 4:35
  • 6
    @hippietrail When the tone is just a stream of bits, you just apply the boolean XOR function across all the channels you want to mix together. – Chromatix May 3 at 5:40
  • In fact, pulse-width modulation could make the resulting sound louder or quieter depending on the analog schematics connecting the actual speaker to the hardware register. Use of integrating RC circuits was not uncommon at that time, and an RC integrating circuit made it possible to control the actual amplitude with PWM. – DmytroL May 4 at 13:41
  • 1
    @DmytroL: I don't think RC integrating circuits were common, but if one repeatedly drives a speaker cone in one direction for a few microseconds and then in the other direction for a much longer time, the distance it moves will be limited by the length of the shorter pulse. – supercat May 4 at 23:11

Essentially, you implement a 1-bit DAC in software.

There are (at least) two ways to do a 1-bit DAC. For tweaking the brightness of an LED on e.g. an Arduino, one can use pulse-width modulation (PWM) using the hardware support. This does not produce the best-quality output, for which delta-sigma modulation is preferable. It's about the same amount of code either way if you don't have hardware PWM, so one may as well choose the better one.

It's harder to reason about why delta-sigma works compared to PWM, which is not helped by Wikipedia describing it in mathematical and electrical-engineering terms which can feel a bit intimidating to programmers, but a sawtooth wave which gets steeper and resets more frequently based on a higher input voltage is equivalent to a register to which one continually adds the input value and overflows.

You may wish to visualise this by looking at a multiplication table (e.g. this one on Wikipedia). Look down the columns and you will see that there is a carry from the ones to the tens column more often as the number being multiplied (which I'll call "N") gets larger, and further that multiplication by ten causes it to overflow N times. Thus there is a direct correlation between the input value and the number of overflows.

So the trick is to get a sample from somewhere — whether a table in memory or generated in real-time — then add the sample to a register and copy the carry bit to the speaker in a tight loop. You will also need an outer loop to feed it new samples periodically.

On something like the ZX Spectrum or a simple Arduino circuit where the sound hardware is a bit-banged GPIO pin, we're sorted.

On machines with a proper sound chip, the problem becomes how to control the output like a GPIO pin. For something like the PC speaker, one can set a very high-frequency beep which is toggled on and off. The beep is mixed with the delta-sigma output which may cause beating that sounds bad, so some tweaking to the beep frequency and/or the tightness of the loop will be required to make the beat inaudible or at least tolerable. On more complex sound chips like the C64's SID, further deviousness is required.

Application of this technique to the video output may even produce plausible sampled sound on a ZX81 which is otherwise mute (or rather, generates a nasty 50Hz buzz corresponding to the video output so pretty much everybody turns the TV volume to zero). It may well have already been done, otherwise consider this a programming challenge :)

| improve this answer | |
  • I do remember that I wrote my own audio sampling and playback routine once on my 48K Speccy when I was a kid, before seeing it done in any game. Impressed the hell out of myself and nobody else. 35 years later I have no memory of how the code worked (-: I think I learned from disassembling tape loading.routines. – hippietrail May 3 at 12:10
  • You can certainly get an output on a TV with a ZX81. Mastering Machine Code on your ZX81 by Toni Baker has a piano routine in chapter 12. users.waitrose.com/~thunor/mmcoyzx81/chapter12.html has an online version of the code. – PeterI May 4 at 12:29

“Even though the amplitude is a constant 1-bit waveform, the narrower pulses provide a way of varying volume. These narrower pulses have incrementally less power overall to the listener; as the duty cycle approaches 0% (or, by inversion, 100%) the perceptual volume decreases with it, even though the amplitude remains the same. This effect is not a consequence of the reduction of the pulsing signal's actual, electronic, or kinetic power. Instead, the reduction in volume is a product of bandlimiting

 — Troise, Blake. "The 1-Bit Instrument: The Fundamentals of 1-Bit Synthesis, Their Implementational Implications, and Instrumental Possibilities." Journal of Sound and Music in Games 1.1 (2020): 44-74.

Blake Troise is better known in the chiptune scene as PROTODOME, and has produced some impressive multi-channel 1-bit/PWM work, including the album 4000AD, which plays directly from a single 8-bit microcontroller with all source included.

| improve this answer | |
  • 2
    Aha, snap! We even quoted the same section. – Nick Westgate May 3 at 13:27
  • 1
    And I nearly quoted the Paul Lutus bit too! Blake's projects are really fun, and I spent far too much time writing up how to play them on ATtiny85 chips: PROTODOME’s wonderful chiptunes – scruss May 3 at 17:57
  • Yes, I came across your blog post, and it sounds like the best tutorial! – Nick Westgate May 4 at 12:14

Michael Mahon wrote a 5-bit Digital to Analog converter for stock 1 MHz, Apple II computers back in the early 1990's. Greg Templeman improved on this design to produce a 6-bit DAC. These programs would play 11KHz, 8-bit, digitized sound waveforms through the Apple II speaker by dropping the least-significant, 3 or 2 bits and using careful timing to play the waveform on top of a carrier wave (see http://mirrors.apple2.org.za/apple.cabi.net/Music.and.Sound/SIX.BIT.DAC.SHK.TXT for details).

In particular, Greg's discussion of his program mentions "Whether or not you notice the sound improvement with the sounds you play, however, you will still get the other advantage of increased bit-resolution: a greater dynamic range than other sound players, even with smaller digital steps. That is, my 6-bit DAC plays sounds louder than 5-bit (or fewer) players."

Of course, the ability to play digitized sound samples through the Apple II speakers also implies you can play both louder and quieter samples, so it seems the volume control was achievable at least through this means.

By the by, Michael Mahon later based a new, 5-bit sound DAC on Greg's 6-bit DAC design, but with a 22KHz carrier wave rather than 11KHz, effectively eliminating the (audible) annoying "whine" of the carrier wave from the sound output. His discussion of that project can be found here.

| improve this answer | |

Its possible and PWM controlled DAC is the answer. All you need is single digital pin output and fast enough I/O hooked up to non linear load (like Speaker, or capacitance or RC filter) ...

This can be used to play PCM samples (among other things)...

  1. set PWM base frequency high enough

    the frequency should be higher than human can hear otherwise you would hear a high pitch sound in the background. However if CPU I/O is not fast enough you just use lower one. For example telephony uses sounds up to ~4KHz so PWM with 8KHz is enough to produce telephony quality sound (its enough for "recognizable" human language even if voice is up to 12KHz).

  2. PWM -> DAC

    each period of PWM transfers some energy to the speaker. For AC coupled loads The amount is highest with ratio 1:1 (50% is L and 50% is H). The further you are from this the lower energy is transfered. This is sort of DAC.

  3. PCM

    PCM is analog variable sampled (by ADC) as digital numbers (for DAC) that reproduces the original analog variable (up to a point). So we can sample sound in form of PCM (like *.wav files) and play it with PWM on Speaker.

When you put all this into SW 1bit digital Speaker you will need:

2 * f_sound * n_volumes = f_IO

where f_sound is the max frequency of sound produced (samplerate/2), n_volumes is the number of different sound volumes produceable and f_IO is required frequency of I/O to produce this sound.

If we think about ZX then we need in inner most loop something like this (highly unoptimized):

l2: ...

    ld a,0        ; 7T
    out (254),a   ;11T
    ld bc,(adr_L) ;20T
l0: djnz l0       ;17/12T
    ld a,255      ; 7T
    out (254),a   ;11T
    ld bc,(adr_H) ;20T
l1: djnz l1       ;17/12T
    jp l2         ;14T

summing up to ~104T per PWM period. If we consider 4 volumes, another ~50T for sound fetching or generating and 4MHz CPU then:

f_sound = 4000000/(2*4*(104 + 50))
f_sound = ~3.2 KHz

which is more or less like the telephony quality sound. So yes it was possible to have such sound on old 8bit computers. The code is just my pure attempt I wrote just now and can be optimized a lot more so I imagine you could go even to 8KHz after optimizations made...

I created similar PCM sample player on my ZX ages ago where the sound was sampled by ADC hooked to 8255 of my ZX clone (Didaktik Gama 89) and then could be played latter on internal Speaker. It was capable of storing just a few seconds (IIRC ~15sec) into memory but it worked. Sorry I do not remember the samplerate I was able to achieve but it was higher than 4KHz.

However this technique requires a lot of CPU time that prohibits other stuff like gfx, game logic etc to be done at the same time unless other HW capabilities are exploited. For example on PC there is the PIT i8253 that can make part of the stuff for you ...

On top of all this you can achieve also polyphony. With volume control its easy you just sum up the 2 or more channels together with saturation.

However its possible to do it also without the volume control (the 1bit sound video from youtube you linked use this technique). Its done by combining the 1bit digital signals together.

For more info see:

| improve this answer | |

You totally had control of the pitch of the beeper from pre-programmed registers but no volume control of beepers without using tricks. Note that 99.9% of the early digital CD chips had no digital control of the volume and playback speed, it was a potentiometer.

For c64, the volume register design flaw in the original 6581 chip was used to play back samples. Every time the volume register value was altered, an audible click could be heard. By changing the first 4 bits of the register at $D418 fast enough, samples can be played back with rates up to some kHz (depends on the code and what else uses rastertime) with 4 bit resolution.

The trouble was the 4/16/32 kb of ram, 64 kilobytes of ram for the C64. A 2 bit audio file of one second is about 8kb.

The Computer Music Melodian was the first professional digital sampler which came out in 1976 for 60,000 dollars and it was 12 bit, it's from the same time as the apple II...

The Fairlight CMI from 1979 also cost 60,000 dollars and it was 16 bit.

So you can imagine what kind of audio a 500 dollar computer had in 1975-1980. 1 bit. The c64 samples actually hacked the volume control to play samples.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.