Continuing the Minimal Computing   theme, this post is about audio programming in C (on Linux and OpenBSD).
My first real interest in computers stems from making Drum and Bass as a teenager. I've retained that interest but never tried programming any audio. While exploring OpenBSD I discovered how simply the OS implements sound functionality and (unlike others) gives it kernel-space priority, making it an enticing platform for this kind of work.
Starting to make sound, from the ground up, is a topic many programmers may have covered during university, I hadn't and wish that I had.
The simplest way to make a noise in OpenBSD:
# play white noise cat > /dev/audio < /dev/random & # stop kill %1
/dev/random is a file/stream of random bytes, /dev/audio is a file that represents the sound-interface. Cool but generating a musical sound would be better. The simplest way to do this would be to send a stream of bytes to /dev/audio. A "square wave" is basic, a period of bytes at one number/level, followed by another stream at a different level.
I know a little Linux X86 Assembly  so the most minimal audio program I could think up was: build a square-wave in assembly. The only problem being that the program was specific to Linux. To work between Linux and OpenBSD (and almost any other OS/architecture) I decided to satisfy another long-standing curiosity. I'd build some wave generators in the C programming-language .
I bought two books: The C Programming Language  which is a "classic" but also a little dry and based on an old standard (ANSI/c89, as in 1989); and Learn C and Build Your Own Lisp , witch is based on C99 (the same as OpenBSD) and is really well written.
For my programs I wanted to build "wave-forms" , the basic forms are square, saw, triangle and sine. Generating these and many other types of audio are well covered problems, I've seen many great tools  that are open-source and worth playing with . (Especially anything by Paul Batchelor).
But as brilliant as those tool are, I wanted to learn for myself and to keep things very simple and easy to debug. I also like that classic 80's game-sound (chip-tunes ) so making the waves in 8-bit-mono, using unsigned integers seemed like the way to go.
I setup my tools (Vim, GCC, make and musl lib-c ) and it started to flow:
Square: Saw: Triangle:
Then I got hung up on Sine and trigonometry... Having paid little attention in school I was very impressed by Khan Academy, an afternoon of "school" and it started to come together.
It still didn't sound quite right but ears (or my ears) are not that good at relating audio irregularities to code. I wanted to visualise what I was hearing. I needed an oscilloscope, the next best thing is GNU Plot.
Now it was obvious (and obscene?):
I had the quadrants of my wave being "rendered" in the wrong order and was looping over the edges of each cycle.
GNUPlot is the shit!
300 +-+----+------+------+------+------+-----+------+------+------+----+-+ + + + + + + + + + + + | '-' using 1:2 A | 250 +-+ AAAAAA AAAAAA +-+ | AAA AA AAA AA | | AA AAA AA AA | 200 +-+ AA AA AA A +-+ | AA AA AA A | | AA A AA A | 150 +AA A AA AA +-+ |A AA AA AA | A AA A AA | | AA A AA | 100 +-+ AA AA A +-+ | AA AA A | | AA AA A | 50 +-+ AA AA A+-+ | AA AA AA| + + + + AAA AAA + + + + AA 0 +-+----+------+------+------+AAAAA-+-----+------+------+------+----+-+ 0 50 100 150 200 250 300 350 400 450 500
- Minimal Definitions, Minimal Computing - Notes
- Minimal Computing: Thought Pieces
- x86 Assembly With Linux (Exercises)
- Minimal Sound
- The C Programming Language
- Learn C - Build Your Own Lisp
- Rudenoise's Audio Links
- Paul Batchelor's Blog
- musl libc
- Kahn Academy Trigonometry