3

I figured out how to make square, triangle, and sawtooth waves in pygame. However, I have no clue what kinds of waves I need to make to produce a 'noise' sound effect like you see in older computer systems.

Can anyone reveal to me how that was accomplished? I don't even know what kind of wave pattern I need to make for such a sound effect.

2
  • 2
    It isn't a wave pattern at all, it's noise. Random frequencies in random order. And like with any randomness there are many way to generate this.
    – Raffzahn
    Sep 27, 2019 at 19:11
  • 1
    I'm a little confused by what "noise" means. Got a sample? (Also by "older computer systems" for that matter; how old is that?) Sep 27, 2019 at 22:06

2 Answers 2

15

Random noise patterns were usually generated by one of two common methods back in the 80s when simple waveform generating sound chips were popular.

One technique is the Linear Feedback Shift Register or LFSR. This is basically a shift register where some of the bits are fed from one part of the register to another using a simple logic function, typically XOR. The result is pseudo-random, it will eventually repeat but for audio that didn't really matter. LFSRs were fairly easy to build in to chips and didn't require too much silicon.

Another technique was to use two out of phase timers. The key is to have the timers be free running so that they don't synchronize. This technique can actually produce extremely good true random numbers with a bit of care. Sound had a clock of some sort already to regulate playback speed, actually only one additional clock was needed to create a "good enough" result, and the simplest option was to use a series of NOT gates strung together in a loop. The speed at which changes to each gate propagates to the next is essentially random and creates a free-running and unstable oscillator, which can can be sampled periodically to generate random bits.

Finally there is another technique that is a little less common due to being more complex to set up and, particularly in the 80s, requiring a high voltage to work. P-N junctions, when reverse biased with a high enough voltage (typically 20V or more) generate random noise. That noise can be used to generate a random waveform or bits.

7
  • 1
    Downvoted. This question asks how to code a noise sound, your answer don't even begin to try to answer the question from afar.
    – motoDrizzt
    Sep 27, 2019 at 20:19
  • 8
    @motoDrizzt Coding in Python isn't anything RC.SE related - nor is copy-pasting.. That's what StackOverflow is meant for. User does provide a good start point with related (and RC.SE relevant) background information - a good reason to upvote that is.
    – Raffzahn
    Sep 27, 2019 at 20:49
  • 8
    @motoDriizzt - the question, per the title, seems to be "how did computers …", not "how to code...". Sep 27, 2019 at 22:04
  • 5
    @motoDrizzt The question doesn't ask how to code the sound, it asks how to make it. The title asks how did computers make the sound, and it's in the retro computing stack exchange, so I answered the question as written. If you have a different question please make your own and I'll try to answer it.
    – user
    Sep 29, 2019 at 9:17
  • 3
    @Mavrik Such a question would be off-topic. This is being generous and answering the interpretation of the question that is on-topic, as opposed to closing as off-topic.
    – wizzwizz4
    Sep 29, 2019 at 17:28
6

Preface:

I figured out [...] in pygame.

Pygame is an actual modern, up to date environment and not anything on topic for RC.SE at all.


TL;DR;

However, I have no clue what kinds of waves I need to make to produce a 'noise' sound effect like you see in older computer systems. I don't even know what kind of wave pattern I need to make for such a sound effect

There isn't a wave pattern at all, it's noise - the absence of a pattern. It's random frequencies in random mixture and random order.


Background

Randomness

Perfect, so called white noise (*1) is defined as a random signal with equal intensity at different frequencies. This resulting in a constant spectral density. Maybe you're old enough to remember a classic (pre digital) TV set turned to an unassigned channel? What's shown on the screen (and played on speakers) is white noise.

And like with any randomness there are many way to generate this.

Random Sound

In case of sound for computers, it just means generating a new random value per sound clock and output it. Today one may fill up a sound buffer with consecutive random values. A few hundret bytes to a few KiB will do it, depending on the quality you want. Then just loop that sound to your sound output (DAC) (*2)

Now, for early computers this isn't a great solution. In fact no data based solution would have been great, as it requires attention of the CPU and precious memory space as well. That's why they got sound generators. So the natural choice to add (white) noise was implementing a random number generator in hardware and send it's output to the DAC and amplifier chain (including optional filters). A simple way to do so is adding a Linear Feedback Shift Register with sufficient length to tap the desired data word and enough 'filler' digits to provide the right feedback. For quality of randomness length and feedback are connected - more feedback means less length needed.

As said, there are many other ways to generate randomness, the LFSR is just a common one, especially for early systems.

Example: The C64's SID

For example for Commodore's SID a 24 bit Fibonaci type LFSR was used (*3). More than enough for taping 8 output bits, but since they used only two feedback bits a shorter length would be way less desirable (*4).

Taping was done at bits 2, 4, 7, 11, 13, 16, 20, 22
Feedback was taken from bits 17 and 22, XORed together.

A pseudo code to generate SID noise may look like this

byte GetNoiseByte()
{
 static unsigned int LSFR : 24 =0x7FFFF8;
 unsigned int NewBit;

 GetNoiseByte = LSFR[22]<<7
              + LSFR[20]<<6
              + LSFR[16]<<5
              + LSFR[13]<<4
              + LSFR[11]<<3
              + LSFR[ 7]<<2
              + LSFR[ 4]<<1
              + LSFR[ 2]

 NewBit       = LSFR[17] XOR LSFR[22];
 
 LSFR         = (LSFR << 1) OR NewBit;
}

This code will produce exactly the same number random sequence as a SID does (*5).


*1 - Other 'colours' of noise are pink, brown or grey, depending on the signal intensity (loudness) across frequencies. Strictly classic sound generators are never true white noise, but good enough for game purpose.

*2 - Nice side effect, when using (simple) software random number generators, such a sequence may have frequency properties noticeable to listeners when looped.

One way to keep that down will be to play a shifting window, that gets repositioned every repeat. Using prime numbers for buffer length, window and repositioning distance will reduce chances repetition a lot (and/or reduce needed buffer size).

The effect is even more noticeable when producing stereo, having different content in both buffers won't help (And using the same buffer twice produces only mono). Again a shifting window does solve this. Best by using a different offset value for each so no stereo artefacts repeat (early on). In fact, by doing so, a single buffer for both channels will be preferable, as it guarantees that the spectrum for both sides will be exactly the same.

A good combination of values may be

  • Table Length: 1021 (biggest prime below 1024)
  • Window Size: 1019 (next smaller prime)
  • Offset First Chanel: 3
  • Offset Second Channel: 5

With these values the pattern repeats after more than a million uses. At CD rate (44 kHz) that'll be after more than 25 seconds - wayout side any harmonics. For all practical use 251, 241, 3, 5 in would do as well - keeping all values in 8 bit range - ofc, now even more in need of good randomness.

*3 - Well, 23 were used, the lowest bit was always 1 to simplify the structure.

*4 - I guess there is more to it when going into all the math about, for real world estimations, remembering this simple relation will do it.

*5 - I do not recommend to use it. Just go ahead and use whatever random number generator sour modern system offers - they are way better and incredible more weighted in their randomness.

3
  • 1
    Honestly, I was more interested in knowing what the soundwave actually looked like. I found my own way to generate square, triangle, and sawtooth waves (both left-leaning and right-leaning), but I had no idea what the resulting array should look like to create a white noise sound. Based on the comments I've been getting, I'm thinking it would be sufficient to create an array filled with random numbers? That i can do.
    – user15292
    Sep 27, 2019 at 20:40
  • @user15292 Such a question would be off topic on RC.SE, as it is in no way related to classic systems. So the answer does show what has been done and why. Nonetheless, if you read close, you'll see that your array solution has been described. Take care to note the implications described in footnote#2.
    – Raffzahn
    Sep 27, 2019 at 20:55
  • 1
    If it's helpful at all, most of the C64's contemporaries were much less sophisticated than it at audio — although they often also used an LFSR, they tapped just one bit for output. So their noise output is just [pseudo-]random jumping between one of two levels. That's true of the AY (in the Atari ST, ZX Spectrum, Amstrad CPC, MSX et al) and the SN76489 (cloned in the Master System, actually in the ColecoVision, BBC Micro, TI-99/4a and PCjr).
    – Tommy
    Sep 29, 2019 at 15:58

You must log in to answer this question.