When Life Gives You a PC Beeper...

A Musical PC Beeper

    After making a basic MIDI parser, I didn't know what to do with it. It could tell you some interesting things about the MIDI file, but I couldn't really apply it to anything. Then, after turning on my computer one day, I had a cliche lightbulb over my head. The computer beeper makes one chirp when the computer posts, and I noticed that the same speaker played different pitches on different motherboards. It made sense to me then, that there was somewhere I could control the pitch and duration of each beep.

    After a quick google search, it turns out that there is an easy way to do this using ioctl() offered by the <sys/ioctl.h> header. From what I know, ioctl() uses a file handle to /dev/console to perform low-level system calls. More importantly, I can simulate PC beeper beeps using it.

Demo:


    The ioctl() takes the file handle to /dev/console as the first parameter, and in order to use the pc beeper, the macro KDMKTONE is passed as the second. Now, the last parameter is a little strange to someone who hasn't dabbled in low-level programming. The last parameter is an 64 bit integer that contains the duration in microseconds as the high 32 bits, and the frequency in the low 32 bits. Concatenation of these values is pretty easy, and allows us to play basic tones on the beeper. However, the ioctl() call knows nothing about the pc beeper itself, so when you try to play the frequency of an A note (440 hz), you won't hear anything. I don't remember where I got this magic number from, but it turns out, the magic math that "tunes" the speaker is 1193180 divided by the frequency, so if you want to play an A, the frequency needed is 1193180/440. Now, all that was left was to wrap the functionality in a way that I could feed my parsed midi input into the pc beeper. This was pretty easy, and sure enough I had one of the coolest speakers in the world.

    As someone who firmly believes in throwing the worst at your software, I fed the program a black midi, and it... kinda worked. The one problem with the speaker, is that it isn't apparent how to play multiple frequencies at once. So when I play a black midi with multiple voices, it skips from low note to high note and sounds pretty glitchy.

    About a year later, I made some obfuscated code using the pc beeper code I had written before after seeing a Youtuber named Bisqwit obfuscate a program that greets the user based on the time of day. As someone who's never obfuscated a program before, I felt pretty happy with the result of my obfuscation. I initially hardcoded the once-popular meme "Caramelldansen" into a C array of durations and frequencies to be played by the speaker. This song was perfect because it only contains 3 types of notes: quarter notes, eigth notes, and dotted quarter notes. I also used it because I had a midi for it on hand, and it gave a sense of nostalgia. I then slowly condensed it down until it was a string which contained the frequencies in the first 7 characters, and the song's notes in the last however many characters. I then removed all the macro names and added some defines to shorten the verbosity. I can't even remember what the main function does, but I believe it opens the handle to /dev/console and then iterates It doesn't even compile with warnings!

The obfuscated code:

/*
 *    caramelldansen.c
 *
 *    Authored by: Karl Kreuze
 *
 *    Plays the song caramelldansen on the PC beeper ( reqires sudo! )
*/
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>
#define n ((*(s+((s[i+7]&56)>>3))*2)+277)
#define l (s[i+7]&192)>>6
char*s="\0\021/E_m\213\200`XИPXP\230\240\210`X\220P\230PX`\230\220\200`XИPXP\230\240\260h`\220P\230X\240\230\220";
int main(){for(int i=0,fd=open("/dev/console",1);i<41;++i){ioctl(fd,19248,180000*l<<16|1193180/n);usleep(180000*l);}}

Last updated: Fri 24 September 2021