Equalizer for SqueezeBox via BruteFIR
Recently I purchased a pair of Audiovector S-Sub Signature sub-woofers to supply my Audiovector S3 Super speakers with a firmer and fatter bass, which they certainly delivered. As with any setup the addition of two sub-woofers required a lot of tinkering with the setup to provide the best sound – but I was constantly faced with bass-boost problems at specific frequencies as my room was a bit too lively for the new setup.
At the hearth of my Hi-Fi setup sits a SqueezeBox Receiver which is feeding a Cambridge Audio DacMagic, but sadly neither the Receiver nor the backing SqueezeBox Server software has any default equalization features. So as any hacker would do, I put Google on the task but all I ended up with were solutions that didn’t work anymore (with the newer software).
But after many hours of tinkering, I finally have a way to combine SqueezeBox Server with the BruteFIR software to give a full parametric 128 band equalizer. Seeing how much effort it took on my part to get thus far, I thought I would share my findings with anyone interested.
Prerequisite
This hack only works if your SqueezeBox Server software is installed on a Linux based machine, as it requires the BruteFIR software and access to an underlying bash shell. This is necessary to pipe audio from the Server software, into a decoder, through BruteFIR, into an encoder and back into the Server software, but more to come later on the details.
For the interested parties, BruteFIR is a (near) real-time FIR filtering software with added logic modules for equalization and such. FIR filters is short for “finite impulse response filter” (Wikipedia). The reason for using a FIR filter I suspect despite it being considerably harder to compute than a IIR filter, is that they require no feedback and thus calculation errors will not pile up (remembering that a computer has limited calculation precession on real numbers).
So if you haven’t got BruteFIR installed yet, go fetch and install it now. You need to have the ‘brutefir’ binary accessible in your path. To check if you have this, try running:
$ which brutefir /usr/bin/brutefir
If you have BruteFIR installed and in path, you will get a path back otherwise the empty string will be printed.
Writing the BruteFIR filter
The next step is to write the filter script for BruteFIR which will apply the equalization needed. I have placed all my configurations in the path “/etc/squeezeboxserver/brutefir/filters/”, my examples assume this path exists and that you place your script there as well. It also assumes the path “/etc/squeezeboxserver/brutefir/settings/” exists, so that it can place the convolver configuration in this directory. So change as needed if that is not the case. This is my BruteFIR equalization filter script (saved in “/etc/squeezeboxserver/filters/bass_eq.cfg”)
### DEFAULT GENERAL SETTINGS ### float_bits: 64; # internal floating point precision sampling_rate: 44100; # sampling rate in Hz of audio interfaces filter_length: 1024,64; # length of filters #filter_length: 65536; overflow_warnings: true; # echo warnings to stderr if overflow occurs show_progress: false; # echo filtering progress to stderr max_dither_table_size: 0; # maximum size in bytes of precalculated dither allow_poll_mode: false; # allow use of input poll mode modules_path: "."; # extra path where to find BruteFIR modules monitor_rate: false; # monitor sample rate powersave: true; # pause filtering when input is zero lock_memory: false; # try to lock memory if realtime prio is set convolver_config: "/etc/squeezeboxserver/brutefir/settings/wisdom"; # location of convolver config file ### EQUALIZER SETTINGS ### logic: "eq" { { coeff: "equalizer"; bands: 35, 38, 41, 44, 47, 50, 54, 56; magnitude: 35/0.0, 38/0.0, 41/-4.0, 44/-6.0, 47/0.0, 50/0.0, 54/-8.0, 56/0.0; phase: 35/0, 38/0, 41/0, 44/0, 47/0, 50/0, 54/0, 56/0; }; }; coeff "equalizer" { filename: "dirac pulse"; shared_mem: true; blocks: 4; }; ### INPUT DEFAULTS ### input "l_in","r_in" { device: "file" {path: "/dev/stdin";}; # module and parameters to get audio sample: "S16_LE"; # sample format channels: 2/0,1; # number of open channels / which to use delay: 0,0; # delay in samples for each channel maxdelay: -1; # max delay for variable delays mute: false,false; # mute active on startup for each channel }; ## OUTPUT DEFAULTS ## output "l_out","r_out" { device: "file" {path: "/dev/stdout";}; # module and parameters to put audio sample: "S24_BE"; # sample format channels: 2/0,1; # number of open channels / which to use delay: 0,0; # delay in samples for each channel maxdelay: -1; # max delay for variable delays mute: false,false; # mute active on startup for each channel dither: true; # apply dither }; ### EQUALIZATION FILTER ### # Add equalizer filter "eq_l" { from_inputs: "l_in"; to_outputs: "l_out"; process: -1; # process index to run in (-1 means auto) coeff: "equalizer"; delay: 0; # predelay, in blocks crossfade: false; # crossfade when coefficient is changed }; filter "eq_r" { from_inputs: "r_in"; to_outputs: "r_out"; process: -1; # process index to run in (-1 means auto) coeff: "equalizer"; delay: 0; # predelay, in blocks crossfade: false; # crossfade when coefficient is changed };
The relevant lines are bands, magnitude and phase which control the EQ logic module of BruteFIR we use for the equalization. The line:
bands: 35, 38, 41, 44, 47, 50, 54, 56;
Specifies a comma seperated list of frequencies in Hz that you want the EQ to operate on. The line:
magnitude: 35/0.0, 38/0.0, 41/-4.0, 44/-6.0, 47/0.0, 50/0.0, 54/-8.0, 56/0.0;
Specifies the magnitude in dB of each band and lastly in line:
phase: 35/0, 38/0, 41/0, 44/0, 47/0, 50/0, 54/0, 56/0;
Specifies the phase of each band in degrees (0 – 180).
The maximum number of bands you can define is 128 and you don’t need to have even spacing between them as I have in my example (3Hz intervals). Thus it gives you a full parametric 128 band equalizer, pretty neat if you ask me.
Noteworthy is also that the above filter specifies a 16-bit Left Endian (sample: “S16_LE”) input format and 24-bit Big Endian (sample: “S24_BE”) output format with dithering enabled (this effectively upscales the audio to 24-bit using the dithering technique). To ensure the best quality upscaling and filtering in general it’s also using double precision floating point arithmetic (float_bits: 64), don’t confuse this with the CPU Architecture as double precision floats doesn’t require a 64-bit CPU!
Routing audio from SqueezeBox Server through BruteFIR
To our luck the developers of the SqueezeBox Server software had enough foresight to predict the need for custom real-time conversions of the audio streams, which is why they gave us “custom-convert.conf”. This file basically allows you to specify arbitrary shell commands as audio decoders where a range of variables are available for usage dependent on the track currently playing. We will use this to route the audio through BruteFIR. The file normally doesn’t exist by default, so you need to create the file “/etc/squeezeboxserver/custom-convert.conf” with the following content (assumes you have placed your BruteFIR filter script in the same location as me):
flc flc * * [flac] --decode --stdout --silent --force-raw-format --endian=little --sign=signed -- $FILE$ 2> /etc/squeezeboxserver/brutefir/decode.log | /usr/bin/brutefir -nodefault /etc/squeezeboxserver/brutefir/filters/bass_eq.cfg 2> /etc/squeezeboxserver/brutefir/brutefir.log | [flac] --stdout --silent -0 --force-raw-format --endian=big --sign=signed --channels=2 --bps=24 --sample-rate=44100 - 2> /etc/squeezeboxserver/brutefir/encode.log mp3 flc * * [lame] --mp3input --decode -t --silent $FILE$ - - 2> /etc/squeezeboxserver/brutefir/decode.log | /usr/bin/brutefir -nodefault /etc/squeezeboxserver/brutefir/filters/bass_eq.cfg 2> /etc/squeezeboxserver/brutefir/brutefir.log | [flac] --stdout --silent -0 --force-raw-format --endian=big --sign=signed --channels=2 --bps=24 --sample-rate=44100 - 2> /etc/squeezeboxserver/brutefir/encode.log
This configuration tells SqueezeBox Server that we have supplied it with to extra decoders, one for flac->flac decoding and one for mp3->flac. You might be wondering how flac->flac can be either a decoder or a converter, but it is. SqueezeBox Server will figure out how to playback the outputted format of our decoders/convertes.
You may have noticed that the decoder ensures the input format to BruteFIR is little endian and the encoding of the output from BruteFIR is told to expect 24-bit Big Endian format which matches the filter configuration.
The next step is activating our custom decoders, but first you need to restart the SqueezeBox Server. This is often accomplished by issuing:
$ /etc/init.d/squeezeboxserver restart
Enabling the “Equalizer” in SqueezeBox Server
To do this you need to navigate to the Server Settings web interface of your server and then navigate to Advanced -> File Types. You ought to see a screen similar to the picture to the right of this.
Here you need to select “flac/flac” for the File format “flac” under Stream format “flac” and set all other stream formats under “flac” to disabled. Likewise for File format “mp3″ under Stream format “flac” you need to select “lame/flac” and set all others to disabled.
This is to ensure that our BruteFIR “decoder” is always used when playing these two formats (I haven’t got any other formats in my collection, so you might need to find solutions for other formats if you use alac, aif or any other). The name “flac/flac” and “lame/flac” comes from the fact that our decoder setups defines flac -> flac and mp3 (lame) -> flac conversions.
You are finished
If everything has gone well, you should now be able to play a track via any SqueezeBox device and have your BruteFIR filter equalization applied to it. You can verify this by checking issuing:
$ top -U squeezeboxserver
Which displays all processes run by the user squeezeboxserver (default user for said software), and you should see one or more brutefir and flac (or lame) processes running while playing. You might experience a slight delay prior to each playback (I experience 25-100 ms, so it’s rather short), this is the time it takes to pipe through BruteFIR and everything. I don’t notice it that much, only when playing albums like Pink Floyd Animals, will I notice the short delay in-between tracks.
Problem solving
If though you are experiencing any trouble, you may need to tinker a bit more with the setup. Prior to getting to this setup I had an experience where I would get sound, but it would be speedup and contained a rather large amount of white noise and distortion. This was prior to setting the output format of BruteFIR to Big Endian, but after doing so my problem was fixed. Many of the websites I have scanned through while tinkering myself had the outset set to ”S24_LE” (or “S16_LE” if they didn’t have any upscaling with dithering) meaning Little Endian output. If you have problems with my setup you may have luck in trying to switch to Little Endian output of BruteFIR, just remember to also change the custom-convert.conf file (specifically the flac encoding command which the output of BruteFIR is piped into, my configuration specifies “–endian=big” which you will need to change to “–endian=little”). Phew that was surely quite a lot more text than I originally anticipated. But I hope someone can find good use for it and if you are having trouble getting it to work, don’t hesitate to throw a comment here on the blog.
Digital Room Correction or DRC
Well I think I need to mention, that what I have actually done is to take a piece of software meant for something a bit different and made it fit my purposes. BruteFIR is primarily used for applying Digital Room Correction to your playback, which means a correction filter based on a sweep-tone recording of your Hi-Fi equipment resulting in a near-linear performance in that specific setup.
So if by chance you get your hands on the required equipment to do such a recording of your setup, you can also add this to your BruteFIR filter for DRC and equalization. The recommendations I have found is to apply the equalization prior to the DRC filtering, as you might otherwise get problems with cutting.
Personally I haven’t been fortunate enough yet to get my hands on a professional studio quality recording mike and recording equipment to get a sweep tone recording of my setup, but mayhap some day I will get that opportunity.



Michael, you are nothing less than a technical genius! I am so impressed with your knowledge of computing, at such an early age. You are goin to earn a lot of money some day, i´m sure. Hope to see you soon, you son of a gun!
@Rasmus: Thank you for your kind words. =) Well we can’t all be gifted with musical talent, so I’m trying to get this IT thing going – I heard it’s the new big thing. =P
@All: I’ve corrected a little formatting problem in my custom-convert.conf, there had leaked in a few > ‘s in there, which should have been >. So if you are having any problems – this might be it (if you’ve copy-pasted directly)
Thanks, you saved me a lot of headache with your clear configuration guidelines. And now…. enjoy some music
Hi Olivier.
I’m happy to hear that you found good use of my findings and hope you have had an enjoyable experience with getting your equalization just right =)
…and happy listening.
Thanks for sharing this. It’s opened a world of exploration for me.
As a note to other novice hacks, I was unable to:
“Likewise for File format “mp3″ under Stream format “flac” you need to select “lame/flac” and set all others to disabled.”
After head scratching some I found that I didn’t have LAME installed.
And, after hours of head scratching to no avail…what is the syntax to add a second logic module(CLI). I’d like to adjust the EQ via telnet/script.
Thanks
Hi Turck.
I’m glad you were able to use my findings for something useful, alas there were some head scratching over details I apparently overlooked (naturally not everybody per default have lame installed) =).
Just gave it a look about how to enable CLI logic for the filter (not having tried it, I’m giving a qualified guess) should be as simple as adding the line:
logic: “cli” { port: 3000; };
Anywhere in the configuration, perhaps in the top even before the EQ logic module.
I found a description of the CLI module in the BruteFIR manual at: http://www.ludd.luth.se/~torger/brutefir.html#bflogic_cli
And I found a example configuration using exactly the copied line for the CLI module at: http://wiki.slimdevices.com/index.php/Brutefir_Filter
I hope this works for you, otherwise you are more than welcome to reply again. =)
Best regards, Michael
Hi !
Seems that brutefir doesn’t accept using 2 logic modules at the same time.
Eg. both “cli” and “eq” cannot be used at the same time.
brutefir gives error : “Field is already set.”
Looks like a little bug.
Brutefir is great thought!
Found the solution examining the source code :
Use the following syntax :
logic:
“cli” { port: 3000; },
“eq” {
{
coeff: “eq-night”;
bands: 35, 100, 200;
magnitude: 35/0.0, 100/0.0, 200/-20.0;
phase: 35/0, 100/0, 200/0;
};
};
Xavier
Hi Xavier.
Oh what a pickle, but I see that I even couldn’t manage to read your original comment before you had already found the correct way of doing it, awesomeness. ;-D
Anyway, thanks for sharing your findings.
Best regards, Michael Dahl
Hi Michael,
Truly great stuff. I am positive you will receive a lot of attention once the news spreads in the SBS.community!
I run SBS on a QNAP-109II (NAS) which has a 500 MHz processor (specs here: http://www.qnap.com/pro_detail_hardware.asp?p_id=91).
Which processor do you use?
With your configuration of filters how much CPU-load do you get? and how much of that is due to BruteFIR?
I am worried that my slow CPU can’t do the job.
If it looks like there is a chance I will try it and report back, though.
Cheers
-thomas
Hi Thomas.
Well I’m glad to hear that you found my how-to useful, it is a wonder why SqueezeBox Server/Player’s doesn’t already contain this feature.
It is naturally a good question if your QNAP hardware will pull BruteFIR, but I imagine it would be able to do so depending on the average load you have.
I’m running it from an old Intel Celeron 2.4 Ghz machine, which has absolutely no problems – just did a quick test and I am seeing an 5-10% CPU load average for all related processes while playing audio from a single player.
In total I have 8 processes active while transcoding and playing, 2 flac (one for encoding, one for decoding), one sh process (just the shell interpreter being run for the custom-convert.conf file), 4 brutefir processes and the squeezeboxserver process. Of these the squeezebox process takes the 2% load on average.
I’m looking forward to hearing of your findings regarding doing the filtering on your embedded hardware – I would be surprised if it is unable to do it – it’s none the less a very basic filter and 500Mhz is a bucket load of cycles for doing DSP. =)
Best regards, Michael Dahl
Hi again Michael,
I have given up on getting the parametric equalizer running on my QNAP
First, there is no compiler for the embedded system so development is done using cross-compilers. I think it is quite a task setting up a cross compiling environment.

I did need to get the ownership and groups right (chgr and chown).
Second I already have performance issues with SBS 7.5.1 and some of the plug-ins I use (MultiLibrary and Custom Browse) so the extra load of convolving would make this even worse.
On the bright side: I got it working on my Desktop exactly as you described
Now it works beautifully
I am considering buying a dedicated server instead of running SBS off my NAS.
I do have access to all the equipment needed to measure for a proper DRC, but I am not sure when I will have time to do it.
Thanks a million for the setup instructions.
-thomas
PS: Back to tweaking the filters…
Hi Thomas, and welcome back.
It’s too bad to hear that it wouldn’t work (or well the time investment to maybe getting it working is way too high) on your QNAP – but yes, I’m pretty sure I would have said enough when confronted with having to cross compile and what not, especially when it’s unsure if it will even be able to run it, once deployed.
But excellent that it worked on your desktop and that it was nearly problem free.
Happy that my blog helped you.
Actually in the meantime I have bought myself a dedicated hardware parametric equalizer (Behringer FBQ2496), measurement microphone and what not, and am now running with a setup configured via RoomEQ Wizard which you probably already know.
I’ve been thinking about writing another blog desribing the process of setting up your measurement equipment, midi interfacing with the hardware, doing calibration of your measurement equipment, measuring the room, optimizing filters and applying a house curve to get the most natural sounding equalization. Might be something you would be interested in as well?
Anyway sounds very interesting with a dedicated server for the SBS software and mayhap also the equalization / room correction. Please do keep me updated.
Maybe, though, it would be better to buy a dedicated parametric EQ and keep SBS running off of your QNAP? Might be cheaper in the end, and give you more integration options, so that instead of only having SBS equalized, every input source is now equalized.
Best regards, Michael Dahl
Hi again Michael,
I thought about getting a dedicated parametric EQ as you have, but then realised that I could build my own dedicated server just as cheap! I don’t really use other sources, so I got a motherboard with Atom CPU integrated, 2 GB RAM and a Mini_ITX box for 1500 DKK.
Here are the components:
http://www.proshop.dk/showproduct.aspx?prodid=304907
http://www.proshop.dk/showproduct.aspx?prodid=317647
http://www.proshop.dk/showproduct.aspx?prodid=149724
I am going to put my QNAP up for sale now
This setup is really quick, silent and doesn’t use much power. The plugin for SBS called SrvrPowerCtrl can put the server machine in suspend mode and (I hope) do a wake-up-on LAN. I haven’t had the time to check this out yet.
I have had one issue with the parametric equaliser. In the middle of playback some tracks systematically stop and the following track in the playlist is played. This happens for different tracks, but always in the same specific point in time for each track (depending on the track). Have you ever experienced this?
The brutefir log says it has skipped the track due to “underflow” (sorry don’t have the exact wording of the error message where I am just now). So it looks like the solution is to recompile brutefir with a flag to ignore this. Alternatively (and probably easier) I could change your setup to use little endian, but I am not sure it will solve my problem.
Catch you later
-thomas
Hi
Just wanted to say thanks : i just followed the instructions, made a chgrp and a chown on new files and directories and it works like a charm.
Very helpful and useful page, thanks again !