Audio Hacks

A fast Linux machine with a sound card is a great environment to try some simple digital signal processing experiments. It only takes a few lines of code to open up the audio driver and you can manipulate the audio samples on the command line. With the programs below, you can do, for example,
   cat somesong.wav | addnoise 6 | ./echo | agc | myplay
to add 6 bits worth of digital noise and an echo effect to the sound samples, and then ramp them up to the 0dB level (i.e. as loud as they can go without clipping) and then play them. Other than the echo effect, you will hear the noise wax and wane as the gain of the agc filter changes. Here are some other fun combinations.

   filt -2 < allaturca.wav | sinmult 15000 | sinmult 14000 | agc | myplay
   twotone | swirl | myplay
   cat radio.wav | sinmult 3000  | myplay
   slide | ./echo | myplay
   blip | ./echo | myplay
   backwards radio.wav | myplay
   rwalk | ./echo | ./echo | ./echo | ./echo | myplay
   resonant < wav/radio.wav | agc | myplay
   myplay < compressed.gz
On my Celeron 300A machine, none of these use more than 50% CPU. A good source of samples is an mp3 file via
   mpg123 -s file.mp3
which dumps the samples to standard output rather than to the sound card. A good source of CD-quality .wav files is the nearest CD, assuming you can run the cdda2wav program.

Full duplex operation is possible, at least on my setup (alsa sound driver and Soundblaster PCI128 sound card) so you can run myrec and myplay at the same time. For example,

   myrec | myplay
produces a sort of echo effect. Unfortunately I don't know how to stop the card from echoing recorded audio to the main output internally.

These programs all assume a raw sample stream with interleaved left and right channels, 16-bit signed samples, little-endian, at 44.1K samples/sec. This is the format of a .wav file in what Windows calls "CD quality" mode. The header of the .wav file produces a "click" at the start of the output but so what, the whole point is to keep it fun by keeping the programs really small and easy to understand and modify. Without further ado, here they are.

Download the programs

Beware that some of these are loud, so open up a mixer utility and turn the gain well down before starting to experiment.

Sources

These dump samples to the standard output. All run until you kill them with ^C.

1khz

Generates a 1khz sine wave.

twotone

Generates two different frequency sinewaves on the two channels.

random

Generates random noise.

phase

Generates a 1khz sinewave on one channel and a slightly different frequency on the other, for a phase shift effect.

blip

Generates alternating 1khz blips on the left and right channels, good for testing out the echo filter.

myrec

Records samples from the sound card.

rwalk

Generates a continuous tone with random frequency steps.

backwards file

Plays a sample file backwards.

slide

Generates a continous up/down frequency slide.

Sink

myplay

Plays samples from standard input on the sound card.

myplay_sparc

Like myplay but for an Ultrasparc 10 running Solaris

Filters

These take samples from the standard input, modify them, and pass them to the standard output.

addnoise n

This adds the specified number of bits worth of noise to the audio. For example if n=3 it may add anything from -7 to +7. Also divides the input samples by two to avoid clipping.

agc

This boosts the audio to the the 0dB level by ramping it up to just below the clipping level. When the input would cause it to go over the clipping level, it instantly backs off. This is much like the automatic record volume control on a mono VCR and a handy filter to pipe music through when computing late at night in house full of sleeping people.

echo

Needs to be invoked as ./echo because of the shell built-in command of the same name. Adds a simple echo to the sound.

filt n

A simple-minded filter. When n is positive each output sample is the average of the last n input samples. When n is negative, each output sample is the current input sample minus the average of the last last -n input samples. This gives a sort of low-pass and high-pass filter respectively. Good values to try are 50 and -5.

nukeav

Subtracts the average value of both channels from each channel. The effect is to eliminate the "center channel" and produce an out-of-phase mono signal of the difference between the channels. Not good for anything but I had to try it.

resonant

A simple-minded resonance experiment. Simply a positive feedback loop with a delay of 1 millisecond. Sort of a "shouting through a pipe" effect.

shift n

Shifts the audio sample n bits to the right. Basically just lowers the volume.

sinmult freq

Multiplies the samples by a sine wave of frequency freq Hz.

swirl

Gradually "rotates" the signal by shifting the channels around in a circular fashion, look at the source code. Surprisingly little effect on perceived sound.

truncbits n

Chops n bits off the low end of the samples to simulate the effect of a lower-resolution DAC.

Back to my miscellaneous projects page