Applying permanent convolution for mobile/offline listening

I’m a fan of applying convolution filters for headphone correction purposes applied by Roon. One issue is that the lack of a Roon mobile solution and my archaic portable device (iPod classic) means that headphone correction is an at-home luxury. I’ve also got a poly that can carry music on a microSD for trips, etc. and offline correction for that would be nice. I figured it must be possible to apply the convolution outside of Roon and save the results. Use a filter for your headphones of choice, and load the transformed files onto your device/card and all should be good. There are some obvious disadvantages:

  • it’s not an approach that scales well if you like to use different headphones
  • you can’t apply it to streamed material
  • if you buy new headphones you have to reencode everything

Anyways, I needed a way to apply a convolution filter created by AutoEQ and thought I’d try ffmeg the “swiss army knife” of FOSS AV transcoding. Turns out it’s pretty straightforward:

ffmpeg -i <path to input file>  \
  -i <path to autoEQ filter> \
  -lavfi afir <output_file>

A real life example:

ffmpeg -i 01-01-Alt-J-3WW-SMR.flac \
  -i Shure\ SE535\ linear\ phase\ 44100Hz.wav \
  -lavfi afir ./convolved/01-01-Alt-J-3WW-SMR.flac

Finally, if you don’t have ffmpeg (Roon requires it but it might not be easily accessible) but you used Docker this docker command will do the same thing but everything needs to be under the same directory:

docker run -v $(pwd):$(pwd) -w $(pwd) jrottenberg/ffmpeg /
  -i 01-01-Alt-J-3WW-SMR.flac \
  -i Shure\ SE535\ linear\ phase\ 44100Hz.wav \
  -lavfi afir ./convolved/01-01-Alt-J-3WW-SMR.flac

No idea if I’m the only person who’s interested in this use case, but it’s working quite nicely and it’s easy to script batch conversions from the above. Happy to answer questions if anyone’s got them.

4 Likes

I can apply convolution on my Hiby DAP but it’s only fixed for one frequency so you have to manually change it. But I never use it never got on with AutoEQ settings always took the fun out of the listening it me.

Thank you for sharing this! Being able to apply your own convolution filter is my favorite Roon feature by far. It just removes the need for external software or hardware solutions (like Dirac).
For ‘dumb’ devices, your solution seems to be the only way to apply correction, so enthusiasts should find it useful. I’m curious though: did you try to find a DSP app for smartphones that supports arbitrary convolution filters?

1 Like

I didn’t since neither of my two portable devices are smartphones so I needed a permanent encoding solution.

Again you say potato… I rarely listen without filters although I’m rolling my own versions using the AutoEQ code so I can tweak them some. In truth it’s more likely the (Harman) target you don’t like, these dictate the final sound and you can select other targets.

Well, for me, a smartphone is a portable device :slight_smile: Mine has 256GB of storage vs. my iPod classic’s 160GB. Also, unlike with the iPod, I could use an external DAC with my smartphone if I wanted to. You trade a bit of convenience for flexibility.

Most likely , I just feel changing the sound from what was designed and engineered just defeats the purpose of buying them in the first place. Call me old fashioned I suppose. I have used DSP with speakers but in the end had to give up and find speakers that worked with my room and me better. To me it feels a little like square peg round hole if you know what I mean, but no disrespect to those that like to twiddle.

1 Like

I think most of us consider a phone a portable device :slight_smile: . I have a smartphone and use it with BT Headphones but prefer wired headphones for the most part. I don’t like using the phone battery for playing music and find the chained phone to DAC thing too painful. I like the iPod Classic because it’s small and “complete”, I’ve replaced the disk with SD cards so there’s loads of space and no skipping. I know it’s not the last word in anything now but it still works.

This is a definite “different strokes” thing, I tend to buy gear and coerce it to sound similar. This means I tend to buy for particular purposes, e.g. portable, or in the garden but not to get different sounds. TBC, I’m not suggesting everything I own sounds the same, or that I don’t listen to kit before buying. But I do twiddle and tinker some looking for improvements. That’s something of a personality trait :wink: One thing I like about the hobby is while we have pretty different approaches to systems and listening we do share a lot of musical tastes in common. Enjoy the music :slight_smile:

1 Like

That’s cool, I didn’t know you can do that. I got my iPod mostly as memorabilia, after it was discontinued, so I’m not sure I want to tinker with it. Outside home, I listen mostly in my car, and running Android Auto on my phone is all I need.

Most probably engineers used calibrated monitors during mastering, so I think calibrating speakers brings you closer to what was intended.

There’s a few around. I’ve had the quad version of an iFlash for a few years now and it’s worked flawlessly. I see they now do an mSata adapter which is pretty insane, and bizarrely tempting :wink:

1 Like

I’ve been around the houses playing with this and learned quite a bit while I was at it. I worried that ffmpeg might not be doing a good job, tried sox and got similar paranoia. My final solution was to use a Python signal processing library and do it myself. This 85 line gist has the basis of a multithreaded batch Python convolver, that honours the original file’s sample rate.

2 Likes

Nice! What kind of performance are you getting? I have my own implementation of convolution, up-sampling, noise-shaping etc. (Not necessarily because I’m paranoid; it started more like a practical knowledge test that evolved into a project.) I’m looking into porting to OpenCL to parallelize and offload to GPU.

1 Like

Briefly, about 150 tracks per thread per hour. Enough to convolve my whole collection (about 25K tracks) overnight if I throw all 16 threads at it. That’s acceptable for me, it’s a one-off job.

That’s also the case here, each step and a “oh that’s how that works” took me further down the rabbit hole…

@killdozer - I don’t suppose you happen to know whether any of the solutions you tried would work natively with DSD (DSD256)? Mainly out of intellectual curiosity I bought a DSD256 album (well, tape transfer actually) without really considering that I wouldn’t have the horsepower to apply my room correction convolution in real time. Since it’s a bit of a one-off, I’d quite like to convolve it offline, without resorting to a PCM conversion. I can’t seem to find a clear example of this for SOX but suspect that’s my ignorance.

Have you tried that and it didn’t work?

Well, there’s going to be some conversion, whether you call it PCM or not, even if you convert it back to DSD. Also, trying to avoid PCM would make some sense if your DAC played DSD natively. Now that you satisfied your intellectual curiosity, you might as well convert it to PCM and use that when going through your room correction.

Yes - 0.4x processing speed and dropouts…normally I play upsampled DSD256 at 2.2x processing speed without a hitch.

It does - I use an RME ADI-2 Pro FS R BE with DSD Direct (AKM 4493).

I assume you enabled '“native” DSD processing (or whatever it’s called)? Did you try turning it off?

Thanks - no I didn’t, as I just wanted to explore keeping the processing in DSD (whatever audible difference this does or doesn’t hold). However, I’ll give this a go out of curiosity, as will be interesting to see the processing impact. I guess it would also give me a comparator if i do come up with an offline solution.

The only difference between processing “native” DSD and “going through PCM” is a down-sampling to 358.2 kHz before convolution and an up-sampling back to 11.2 MHz before delta-sigma modulation. That’s not going to affect anything in the audible range, but will save a lot of computing resources.

Well, it does at least allow me to apply the convolution…just (1.4x processing speed)…if I find an offline solution for staying in DSD then I’ll compare the two (for my own curiosity).

Edit: Actually, I accidentally turned off the parallelize option at the same time…with that on it’s back to a more healthy 1.8x.

Again, except for the sample rate conversions I mentioned, which are the least consequential in this particular signal path, everything is the same, so you’re not really staying in DSD. At 1.8x speed, you already have the solution on your hand.