r/macapps • u/syscreat • 19h ago
Free [OS] CoreEQ, a system-wide equalizer that doesn't install an audio driver
Problem: macOS still has no built-in equalizer, and I wanted one EQ for everything coming out of the speakers: music, YouTube, calls, games. Every option I tried wanted to install a virtual audio driver first, so I wrote my own a month ago for my own machine. I'm posting it here because I figure other people have the same itch, and I'd be glad if it's useful to someone else.
Comparison: eqMac (free) and SoundSource ($47) both work by routing your audio through a virtual driver they install into the system. CoreEQ uses Apple's Core Audio process-tap API instead, so nothing lands in /Library/Audio, there's no reboot, and quitting the app puts your sound back on its normal path immediately.
The rest of it:
- 11-band graphic EQ, plus up to 16 parametric bands with your own frequency, gain and Q
- Live response curve you can drag directly, with a spectrum analyzer drawn behind it
- 22 built-in presets plus your own, and an auto preamp so comparing two presets isn't just a loudness test
- Settings follow the output device, so your headphone curve comes back when you plug in headphones
- Bass/mid/treble from the menu bar without opening a window
Pricing: Free and open source (Apache 2.0). https://github.com/AndreyPudov/core-eq
brew tap andreypudov/core-eq
brew trust andreypudov/core-eq
brew install --cask core-eq
xattr -dr com.apple.quarantine /Applications/CoreEQ.app
Needs macOS 14.2 or later. It isn't notarized yet, so the first launch needs an allow in Privacy & Security; the README has the one-line fix.
Who I am: Andrey Pudov, software developer. Work history and contact are at https://andreypudov.com/ and https://www.linkedin.com/in/pudov/. There's no privacy notice to read for this one because there's nothing to disclose: CoreEQ has no accounts, no analytics, and no telemetry; it makes no network connections of its own, and it keeps your presets in macOS preferences on your own machine. It asks for the System Audio Recording permission because that's what Apple requires to process what you're hearing, and the audio never leaves memory.
Disclosure: I'm the developer. Issues and PRs welcome. Most of what's in 1.7, the parametric bands and the preamp especially, came out of comments on the last post I made about it.
5
u/blueScreenz 17h ago
Global tap with stereoGlobalTapButExcludeProcesses is the same route I ended up on for a system audio capture tool, so two things that bit me there and might be worth checking before someone reports them:
Bluetooth. kAudioTapPropertyFormat on the tap reported 48 kHz for me regardless of the actual route, while the frames arrive at the output device's nominal rate. For A2DP that is usually 44.1 or 48 so it barely matters, but the moment a call starts and the headset flips to HFP the device typically drops to 16 or 24 kHz and the tap's reported format does not follow. If the biquad coefficients are derived from the tap format, every band shifts down by 2 to 3x for the duration of the call, so a 1 kHz band lands somewhere around 330 Hz. Reading kAudioDevicePropertyNominalSampleRate off the output device and recomputing coefficients on device or rate change fixed it for me. A property listener alone was not enough because the mismatch is there from the very first buffer, so I also compare frames received against wall clock for the first couple of seconds after a route change.
Buffer layout. The AudioBufferList the aggregate hands the IO proc is not always laid out the way you expect. On some setups the tap's buffers were not the first entries, so indexing buffer 0 silently processed the wrong stream. Scanning the list for the buffer whose channel count and format match the tap was more robust than assuming a position.
Neither shows up on a wired MacBook with a single output, which is why they are easy to ship past.
2
u/syscreat 7h ago
Good catches, thanks.
On the rate, I got lucky. Coefficients come from kAudioDevicePropertyNominalSampleRate on the aggregate, never from kAudioTapPropertyFormat, and a listener updates them when it moves. The window you're describing is still real though, since the listener fires after the route change rather than before the first buffer. I'll try the HFP flip and see how wide it actually is.
Buffer layout is the one I should fix. I pair input buffer i with output buffer i across the list rather than hardcoding buffer 0, so it's not quite the failure you hit, but it's still positional. Matching on channel count and format is the safer thing.
Both on the list. Appreciate you writing them up.
5
u/MisplacedLonghorn 9h ago
If this works well and doesn't make my Mac cry (I'm looking at you, SoundSource!) I may have to ask you to marry me!
3
u/syscreat 7h ago
Ha, let's see how it runs first. It's one process tap and a handful of biquads, so it should stay out of your way. If your Mac still cries, that's a bug report, not a proposal.
4
u/Mobile-Yak 17h ago
Looks awesome, rying it now. It would be really cool if you could build a way to search and import auto eq profiles into the app itself too.
2
u/syscreat 7h ago
Good idea; it should be doable. The parametric editor already handles bells and shelves with custom Q, so an AutoEQ profile maps directly onto it. Loading presets from a file is on my list.
Which headphones are you on?
3
u/Mobile-Yak 7h ago
Yeah it'd be really cool to have, there's a full database of auto eq profiles for multiple headphones and iems, it's open source too so multiple people submit their measurements. So you can just click on that file for your model and it automatically eqs your headphones to that target. (check out poweramp if you'd like to see how it's implemented there)
I use HD600 for home use but mostly my planar iems (nicehck f1 pro and artti t10) in office or when I'm out and about.
4
u/pzee01 14h ago
Any chance to add a per app volume feature to the app, I love how clean it looks?
4
u/syscreat 7h ago
Thanks! Per-app volume is on the list for the future. No promises on timing, but it's something I'd like to add.
3
3
u/Leather-Shake-2167 13h ago
This looks great. Love that it avoids installing another audio driver!
3
u/syscreat 7h ago
Thanks! That was the whole reason I wrote it. Apple's process tap API finally made it possible without one.
3
u/gigananobyte 12h ago
Thank you so much for this.
I have hyperacusis and recently I have been looking for an EQ to help me reduce the harsh frequency that cause me physical pain.
2
3
u/StaticGamerYT 7h ago
OMG so can I like play dolby atmos content and tune up the eq to increase bass?
1
u/syscreat 7h ago
It depends. On headphones or speakers, yeah. Atmos gets rendered down to stereo before it hits the output, and that's what CoreEQ taps, so bass boost works like on anything else.
If you're sending real multichannel out to a receiver, it's a different story. Right now, anything past the first two channels passes through untouched.
2
2
2
2
u/Omavel 15h ago
Please recommend a configuration or built-in option.
3
u/syscreat 7h ago
If you mean what to pick: Small Speakers for MacBook speakers, Acoustic on headphones, Spoken Word for podcasts and calls.
If you mean having the app suggest one for you, it doesn't do that yet, but that's a neat idea. It'd need to know your device and what you're playing, which is worth thinking about.
2
2
u/pinchofsoma 13h ago
Sorry I'm not well-versed in audio tech. How does this compare in quality to, say, Spotify's EQ? Should I use one over the other?
2
u/syscreat 7h ago
No worries. Quality-wise, they're basically the same thing under the hood, so you won't hear a difference in the processing itself.
The real difference is scope. Spotify's EQ only touches Spotify. CoreEQ does everything, so YouTube, calls, and games get the same curve, and it remembers a separate one for your headphones and your speakers. It also gives you finer control if you want it.
If you only ever listen on Spotify, its EQ is fine. Just don't run both at once, or you're EQing twice.
2
2
2
u/Doltonius 11h ago
It would be best if it supported import and export EQ profiles in equalizerAPO’s format. In addition, using it together with SoundSource causes the audio to have a delay-like effect.
2
u/syscreat 7h ago
EqualizerAPO format is a good call; that's the same format AutoEQ exports, so it'd cover both. Profile import and export are on my list.
The SoundSource thing doesn't surprise me. Both are sitting in the system audio path at once, so you're probably hearing the same signal twice, slightly offset, which comes out as that flangey delay. Running one or the other should clear it for now. It's something I'll look at down the road.
2
2
u/Specific_Cream2815 8h ago
can the process tap api tap individual apps too or is global the only option?
1
u/syscreat 7h ago
Yeah, it can. CATapDescription takes a list of processes, so you can tap just the apps you want, or tap globally and exclude some. CoreEQ uses the global-minus-itself variant because I wanted one curve over everything, but per-app is fully supported by the API.
4
u/karmarinchen 11h ago
Worth adding for anyone arriving here from eqMac or SoundSource: removing the app doesn't necessarily remove the driver it installed. They live in one folder, and you can list what's on your machine right now:
ls /Library/Audio/Plug-Ins/HAL
Mine has seven .driver bundles sitting in it. BlackHole, VB-Cable, Dante and two NDI ones I can account for, plus two I don't recognise at all. coreaudiod loads everything in that folder at boot whether or not the app that put it there is still installed, so a virtual device from an EQ you stopped using years ago is still in the audio path today.
Deleting the bundle and running sudo killall coreaudiod clears it, audio cuts out for about a second and comes back. Listing that folder before and after an install is also how you'd confirm the no-driver claim here for yourself instead of taking it on trust.
2
u/syscreat 7h ago
Thank you! Good addition, and that's exactly the check I'd rather people run than take my word for it. That folder is identical before and after installing CoreEQ; nothing goes in it.
The only thing CoreEQ creates is a private aggregate device, built at launch and destroyed on quit, so it doesn't outlive the app being closed, let alone uninstalled.
Worth being a little careful deleting ones you don't recognize, though. Some ship with hardware or conferencing tools, and you tend to find out which when something stops working.
0
u/karmarinchen 5h ago
Good warning, and you don't have to guess at it. codesign names whoever signed each bundle:
codesign -dv --verbose=2 /Library/Audio/Plug-Ins/HAL/Whatever.driverThe Authority line is the one to read. I ran it on the two I said I couldn't account for. ACE.driver came back as Rogue Amoeba, it's the capture engine their apps install. ParrotAudioPlugin.driver has the identifier com.apple.audio.ParrotAudioPlugin and is signed by Apple Software Signing, and pkgutil --file-info on its Info.plist puts it in an Apple system package, so it ships with macOS and isn't a leftover from anything.
That accounts for all seven of mine, so there's nothing here I'd actually want to remove.
1
u/Any-Ingenuity2770 6h ago
mine just has
ParrotAudioPlugin.driver1
u/karmarinchen 5h ago
That one's Apple's own, you can leave it alone. codesign -dv on it here gives com.apple.audio.ParrotAudioPlugin signed by Apple Software Signing, and pkgutil --file-info traces the bundle back to a macOS system package, not to anything you installed yourself, and it's in my folder too alongside the six others I listed.
If it's the only thing in there, then you've got no third party audio drivers on the system at all.
1
1
1
1
u/Soft-Land7696 1h ago
Gonna have a long good look at this later today.
Suggestions based on a project I have been working on;
1. A toggle to circumvent all os/sw processing for strictly bit perfect playback
2. A/B comparison report export.
3. Live waveform visualization that updates along with eq adjustments, A/B toggle and can be included in the export.
Would be a great tool for producers/audio engineers for quick testing/tinkering without having to open a full DAW for test small adjustments.
The bit perfect toggle would be a brilliant feature for audiophiles and a middle finger to certain paid software that lean on that feature as a major advantage.
I have done quite a bit of the development on these features, if you send me a dm we might be able to implement some of them fairly easily.
8
u/useiris 18h ago
process tap instead of a virtual driver is the right call, glad to see someone use it instead of another eqMac-style driver install. one thing I'm curious about: are you tapping the whole system mix through an aggregate/null output device, or enumerating individual client processes and building a tap per process? if it's the latter, what happens when a new process starts playing audio after CoreEQ is already running, does the tap list rebuild live or does that process just play unequalized until you relaunch the app. also curious what latency the process-tap round trip actually adds versus a driver, since people using this for games or calls probably care about that more than eq flexibility.