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
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.
Beware that some of these are loud, so
open up a mixer utility and turn the gain well down before starting to experiment.
These dump samples to the standard output. All run until you kill them with ^C.
Generates a 1khz sine wave.
Generates two different frequency sinewaves on the two channels.
Generates random noise.
Generates a 1khz sinewave on one channel and a slightly different
frequency on the other, for a phase shift effect.
Generates alternating 1khz blips on the left and right channels,
good for testing out the echo filter.
Records samples from the sound card.
Generates a continuous tone with random frequency steps.
Plays a sample file backwards.
Generates a continous up/down frequency slide.
Plays samples from standard input on the sound card.
Like myplay but for an Ultrasparc 10 running Solaris
These take samples from the standard input, modify them, and
pass them to the standard output.
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
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.
Needs to be invoked as ./echo because of the shell built-in
command of the same name. Adds a simple echo to the sound.
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.
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.
A simple-minded resonance experiment. Simply a positive feedback loop with
a delay of 1 millisecond. Sort of a "shouting through a pipe" effect.
Shifts the audio sample n bits to the right. Basically just
lowers the volume.
Multiplies the samples by a sine wave of frequency freq Hz.
Gradually "rotates" the signal by shifting the channels around in a
circular fashion, look at the source code. Surprisingly little effect
on perceived sound.
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