Linux Active Crossover is working!

[Update: now running on a fanless Bay Trail processor]

After a few evenings of half-hearted attempts to port my Windows code and make the changes needed to run on Linux, I finally got my head around what was needed, and it works! Unfortunately I’m not at the house where the amp and speakers are so I can’t try it ‘in anger’ but at least I can tell that I’m getting what sounds like correctly-filtered Spotify or CD from the three stereo outputs.

On a ten year old Dell GX520 it’s using about 16% of the CPU, and when you add in Spotify at about another 16% plus the snd-aloop driver and all the other stuff going on in an internet-connected PC, it comes to about 40% CPU, which is a bit higher than I had hoped – there’s a tiny amount of fan noise. Maybe there is scope to improve the efficiency of the crossover software: at the moment I am reading and writing 32 bit integers to/from the sound cards (one is a dummy sound card of course) but doing all the processing in floating point which therefore involves converting each sample twice with a potentially expensive operation. Maybe this can be speeded up. And I can always find a faster, cooler PC of course.

[13/07/15] In response to a comment, the point of all this is not just to implement basic crossover filtering, but to correct the drivers’ individual responses based on measurements, producing zero phase shift for each driver, and therefore perfect (or as close as possible) acoustic crossovers and zero overall phase shift. EQ such as baffle step correction is overlaid onto the filters’ responses without costing anything extra in CPU power. Individual driver delays are also added. I am not claiming this is unique, but nor is it commonplace. In terms of an active crossover it is the no-compromises version.

I have had this system working for a couple of years on a Windows PC, but Linux will be a cheaper and more elegant solution.

[UPDATE 18/0715] I have it running with the speakers with a choice of two sound cards: Asus Xonar DS and Creative X-Fi. It’s just a case of changing a few characters in the xover config file.

The control loop algorithm for maintaining the average sample rate at input and output (and avoiding any resampling) is an interesting problem to solve and I have had fun trying different algorithms based on PID loops and plotting the result out as a graph. The output sample rate is fixed, set by the card, and has to be inferred from the time between calls to send chunks of data to the output card but there will be a level of jitter on this due to the other things that the multi-threaded program is doing. We know the precise sample rate at the input (the snd-aloop loopback driver) because we are setting it. The aim is to keep the difference between number of samples read and number of samples output to the DACs at a constant level, but as we are sending and receiving chunks of data the instantaneous figure is fluctuating all the time. I presume that similar calculations are being performed in the adaptive resampling that would be usual when connecting together digital audio systems with differing sample rates – the difference being that this would affect the audio (subtly, but it undeniably would), while the aim of my scheme is that the timing adjustments merely affect the fill level of a FIFO, the sample rate being rigidly fixed and defined by the DAC.

[UPDATE 31/07/15]

Feeling confident, I bought an Asus Xonar U7 USB 7.1 sound card. This is based on the CM6632A chipset. I got it working but… trying to set the format to signed 32 bit within my program failed when addressing the device as “hw”. It also failed with S24_3LE and various other sample formats. However, 16 bit was accepted. Consulting the web, people commonly seem to have this issue with both CM6631A and CM6632A on Linux, and their workaround is simply to use “plughw” instead. However, if the “hw” device rejects a format, then, supposedly, the hardware cannot support it. All the “plughw” device does is automatically allow the OS to convert samples from the format you are using into one that the card can use. So I have a feeling that the card is only running in 16 bit mode, regardless of what my code is sending it.

If an application chooses a PCM parameter (sampling rate, channel count or sample format) which the hardware does not support, the hw plugin returns an error. Therefore the next most important plugin is the plug plugin which performs channel duplication, sample value conversion and resampling when necessary.

[03/08/15 UPDATE] Got back to the house where my system lives after the weekend, and was able to try my Asus Xonar U7 again. This time it accepted S24_3LE! Could this be the issue with hot-plugging versus not hot-plugging that other people on the web have seen? I have a feeling that my previous tests were with the U7 hot-plugged into a PC that was already on. Anyway, I now seem to be in business with the U7 and it sounds good.


19 thoughts on “Linux Active Crossover is working!

  1. Intrigued by you blog I started researching and apparently the big boys just enter stuff like
    “ecasound -z:mixmode,sum -x \
    -a:pre -i:mysong.mp3 -pf:pre.ecp -o:loop,1 \
    -a:woofer,tweeter -i:loop,1 \
    -a:woofer -pf:woofer.ecp -chorder:1,2,0,0 \
    -a:tweeter -pf:tweeter.ecp -chorder:0,0,1,2 \
    -a:woofer,tweeter -f:16,4,44100 -o:alsa,Your-card:Your-Device”

    after defining the filters
    “# pre.ecp
    pre = -el:RTpara,-8.5,82,2.6
    # woofer.ecp
    woofer = -el:RTlr4lowpass,1500 -el:RTlowshelf,4.0,150,0.71
    # tweeter.ecp
    tweeter = -el:RTlr4hipass,1500 -el:delay_0.01s,0.0019,1 -eadb:-4.5”



    1. Hi Sexton16. That’s great and extremely neat! But just not quite what I was after. Individual speaker drivers exhibit their own phase shifts and simple low pass and band pass filters using IIR (infinite impulse response) introduce further phase shifts. Conventionally, the speaker designer attempts to ensure that the phase shifts for the individual drivers combined with their filters match each other through the crossover. If they don’t match there is a “suck-out” where the drivers partially cancel each other out through the crossover. However, even if the designer achieves a good match there are still overall frequency-dependent phase shifts. The received wisdom is that people can’t hear phase so this doesn’t matter, but other people dispute this. I think the ecasound solution you link to can certainly provide an active crossover, but it won’t ensure the phase matching. If the filters are steep (say 8th order) the suck-outs if present will be narrow and may not even be particularly audible. There will still be overall phase shifts because of the drivers and IIR filters.

      What I wanted to do with my system was to bypass the whole issue by providing an inverse phase shift based on measurements for each driver, and aim for zero individual, and overall, phase shift. I would claim that you can hear this.

      It necessitates the use of FIR filters (finite impulse response) and the ability to load in impulse response files containing the information necessary to apply the inverse phase shift. In addition, I want to be able to apply some gentle EQ like baffle step correction, and this can be overlaid onto the same crossover filters i.e. it takes no extra computing power to do. I could probably have done it all with off-the-shelf software of one sort or another, but I’m not convinced I could do it without sample rate conversion along the way, or have the same degree of control over it. Hence the posts about what looks like a complex solution, but ultimately works well.


      1. Hello, wouldn’t be nice to write tutorial on active crossovers step by step,how and what to install. You know same thing like for Dummy’s.


          1. Hi Gintas and antoine

            I am very shy of committing to such a thing, because that’s when messing about and pondering on ideas mutates into actual work! To be really useful, a tutorial has to go into great detail, and even then, another person’s system will throw up problems that the tutorial doesn’t cover. And I don’t necessarily think my system is the most sensible way of doing it. I would suggest starting with that ecasound stuff that sexton16 mentions above.

            Beyond that, you’d be looking to do whatever is necessary to make the system truly ‘neutral’ i.e.
            Reversing phase shifts measured in the drivers (near field measurements will do i.e. mic close to the driver so no need to worry about ambient reflections)
            Adding in the appropriate delays for the different front-back displacements of the drivers
            Compensating for in-room frequency response (e.g. baffle step correction)

            Maybe all of this can be done with ecasound and other plugins..?

            I just happen to enjoy messing around with that stuff – although maybe even I have reached my limit and may never touch the software again.

            It might be much easier to buy a commercial software package running on Windows, or a DEQX unit (not cheap, though).


  2. I’m a long-time fan, and user, of Linux and I’m wanting to set up a Linux media system in my car rather than a standard head unit. I’ve been searching the ‘net for ideas like this so I can have an audiophile-grade system. But I am entirely unclear on what you’ve done. How many channels do you have? How many could you create? Can you delay the channels individually? Are the adjustments made CLI or GUI? Can the channels then be individually equalized?


    1. Thanks for the comment. The idea of my system is to use the standard Linux snd-aloop dummy sound card driver as the default ‘sound card’ so any music apps send their outputs to it. I can then take the stereo audio stream from there and process it myself in my own software and send my software’s output to the real sound card. In my case I am producing 6 channels of output (woofer x 2, mid x 2, tweeter x 2) but the sound card actually has 8 channels. My software is performing FIR filtering of the stereo audio (using FFTs) in order to produce the six channels of crossover-filtered audio – the FIR could also include EQ curves etc. The software also allows delays of the individual channels by a number of samples. In my Windows version of the code I had a GUI, but for Linux so far it’s just a text config file.

      For your car system, would you be thinking of building an active crossover?


      1. Active is the only way to go for me. Passive isn’t flexible enough to allow adjustments. The system I have sketched out is ludicrously overkill with a 4-way split on the front left, right, and center channels as outlined in this interesting article;

        Then there’s the 2-way split with delay and attenuation on the L and R rear speakers to simulate the ambiance of a larger environment. And, finally, stereo subwoofers to add impact to the occasional effects found in the music I tend to listen to. That’s eighteen channels to tweak. I imagine it would be possible to stack bandpass filters with high/low filters to create the various bands. But that seems a very hack solution. That’s why I started researching Linux audio processing solutions. I really like the idea of being able to tailor the processor to suit the system.

        The problem is that I am only marginally competent with Linux and virtually useless with audio. Me researching this topic is very much akin to a blind man doing needlepoint.


        1. Hmm. I wouldn’t actually know how to go about generating that many channels using a general purpose PC and operating system. I would be relying on the fact that from a single sound card my 8 channels will all be perfectly synchronised at the sample level. If I have to use more than one sound card, I wouldn’t be able to guarantee that they were locked together. Also, my particular scheme depends on a single sound card setting the overall sample rate in order to avoid software re-sampling for avoiding drift. Not saying it can’t be done, however.

          My ‘philosophy’ is a little different from the author of the link in your comment above. He is using standard filters to provide the crossovers, which results in overall phase shifts because of the filters and the drivers themselves. My approach is to use measurements and FIR filters to flatten the phase – something which is still considered a bit exotic (and by many people unnecessary) even in this day and age.

          For your system have you considered simply buying some hardware crossovers like the ones Behringer makes? I imagine they have predictable, low latency and so you might simply be able to run a few in parallel to achieve what you want. They’re ridiculously cheap. Feed your standard stereo output from Linux into a bank of Behringer units, and you’d have an instant active crossover system.


          1. Actually, I have just started looking into that idea. I didn’t realize how “simple”it is to build a crossover circuit. It seems very plausible that I could get all the capacitors, inductors, etc. and solder them all into a single box which would split the simple stereo input into all the various bands I want. But I would still need some sort of DSP to do the delay/attenuation on the fill speakers. Having a single box to split the signal is still a reasonably elegant solution. And it does simplify the Linux system considerably since I wouldn’t have to fuss with esoteric audio programs.

            I had looked at BruteFIR. But I honestly don’t understand FIR/IIR at all. So it seems the hardware route is more suited to my abilities.


            1. Now there’s an interesting thought– an entire PA rack system in a car. Good thing we’re talking about a large car.


  3. Hello,

    I have a Xonar U7 and want to use Lubuntu.
    I have a pair of high-end speakers and a subwoofer.

    Could you please help me to correctly set up my sound card on Lubuntu ?
    I’d like to get a high pass filter for the speakers.
    And get the subwoofer working for a true 2.1 system.

    Thank you in advance.
    Best regards.


  4. Hello,

    I am trying to config the Xonar U7 with brutefir on ubuntu mate 16.10.

    I am having a problem with setting up the device id etcs.

    I am trying to use the 8 channels analog output of the U7 to do some active crossover (via rephase)

    Can you show me an examp of your config file for the 3-way active crover that you did with the U7?



Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s