grapheqd stands for graphical equalizer daemon. It displays the frequency spectrum of an audio signal via its HTML5 webpage or ASCII based telnet interface. grapheqd runs as a daemon on either Linux with OpenWRT in mind, or FreeBSD. Thus, it uses either ALSA or OSS, choosen at compile time. As FFT computation might require a lot CPU resources on systems without mathematical coprocessor, grapheqd can operate in a client/server mode, where a remote instance on a more powerful system does not use an actual sound device, but connects to a grapheqd instance running on a system with limited CPU power. In such scenarios, you should point your web browser or telnet client only to the remote instance. grapheqd supports PCM signals with one or two channels (read: mono or stereo) and 16 bits per channel. Your audio device must be capable of sampling at 44100 or 48000 Hz. You need a modern web browser with support for JavaScript, CSS3, and websockets in order to access the web interface.


Back in the 80ies and 90ies hifis and stereos came with a graphical equalizer as a separate, physical device, or could be equipped with one. You don't easily find one of these nowadays, at least not for the consumer market. I have never found any use of actually adjusting the audio signal, but always liked the fluorescent dot matrix displays or LCDs. grapheqd tries to reassemble this.


The web interface runs on port 8083 by default:

Point your telnet client to port 8083 as well, and simply enter a c followed by Enter to access the ASCII interface in color mode:

If your terminal does not support colors and/or escape sequences, press m followed by Enter:


$ ./grapheqd -h
graphedq version 4
PCM driver: OSS

grapheqd [-a <address>] [-c <address>] [-d] [-l <port>] [-p <pid file>]
         [-r <port>] [-s <soundcard>] [-u <user>]
grapheqd -h

  -a <address>      listen on this address; default:
  -c <address>      connect to another grapheqd running at this address, do
                    not use any actual audio hardware; cannot be used in
                    conjunction with option -s
  -d                run in foreground, and log to stdout/stderr, do not detach
                    detach from terminal, do not log to syslog
  -l <port>         listen on this port; default: 8083
  -p <pid file>     daemonize and save pid to this file; no default, pid gets
                    not written to any file
  -r <port>         connect to a remote grapheqd on this port; default: 8083
  -s <soundcard>    read PCM from this soundcard; default: /dev/dsp0; cannot
                    be used in conjunction with either option -c or -r
  -u <user>         switch to this user; no default, run as invoking user
  -h                show this help ;-)




  1. Either clone this repository:
    $ git clone
    or grab an official release from this site
  2. If you haven't fetched KISS FFT yet, do it now:
    $ git clone ../kissfft
  3. Call make. It will use Makefile or GNUmakefile on FreeBSD or Linux, respectively, and fetch KISS FFT automatically if you haven't done it, and will compile everything.
  4. Optionally, if you want systemd integration, call make with USE_SYSTEMD=1
  5. You now have grapheqd in the current directory. Either call it directly, copy it somewhere, or run sudo make install, which will place it to /usr/local/sbin. Then either add it to your RC init or systemd configuration, or use the provided scripts grapheqd.service, grapheqd.openrc, or, which make install has copied to /lib/systemd/system, /etc/init.d, or /usr/local/etc/rc.d, respectively.


Create a directory package/grapheqd inside your copy of the OpenWRT source tree, and download openwrt/Makefile to that directory. Now run make menuconfig, and under Multimedia select grapheqd. Optionally, select kmod-usb-audio under Kernel modules -> Sound Support. Then build OpenWRT as usual, e.g. by calling make. is a copy of that Makefile.

Under the hood

Per channel, grapheqd passes 4096 16 bit audio samples (mono or stereo) at a time to FFT, and pushes calculated linear frequency data to all connected clients, thus resulting in roughly 11 or 12 updates per second if your hardware supports sampling at 44100 or 48000 Hz, respectively. The web interface adjusts the labels under each band (vertical bar) to match its frequency range. If only mono audio is available, then the FFT is called just once per loop, while the output data is duplicated. If no client is connected, then no PCM data is read and FFT does not burn CPU cycles unnecessarily.

The internal web serving routines (to put it nicely) use static and predetermined buffers where possible. printf() and family are not used in the hot code paths and loops.


Source code