
Making a MacBook Pro sound like a MacBook Pro on Omarchy
The speakers were fine. Apple runs an EQ curve and Linux does not. Measuring it, fixing a PipeWire realtime bug along the way, and a skill so an agent can do it for you.

I wiped macOS off a 2014 15 inch MacBook Pro and put Omarchy on it. Omarchy is DHH's Arch plus Hyprland setup, and it is the nicest Linux desktop I have used on this machine. Everything worked out of the box except one thing. The speakers sounded like a pair of earbuds sitting on the desk five feet away. No bass, no low mids, all top end. Under macOS the same speakers were genuinely good for a laptop.
I gave the problem to Claude Code and told it to check what earlier sessions had already tried. That turned into a long evening. This is what it found, what it got wrong along the way, and the fix that finally stuck. There is a skill at the end so you can hand the whole thing to your own agent.
The wrong theory
The obvious guess was that the woofers were not being driven. This MacBook uses a Cirrus CS4208 codec with two DACs. One feeds the tweeters, one feeds the woofers, and ALSA exposes them as Speaker and Bass Speaker. The earlier session had been circling that idea: try a 4.0 channel profile, try kernel model overrides, poke GPIO pins in case one of them enabled the bass amplifier.
None of that helped, and a chunk of the evidence for it was wrong. When you mute the Bass Speaker control in amixer to test the tweeters alone, WirePlumber notices the mute and PipeWire soft mutes the entire output. You hear nothing from either driver and conclude the woofers are dead. I noticed the speaker icon in the bar flip to muted during one of the tests, which is what gave it away.
Once the muting moved to the codec level with hda-verb, muting a single DAC amplifier instead of an ALSA control, both drivers were clearly alive. A loud sine sweep settled it. The laptop was visibly vibrating on the desk at 40 Hz. The woofers were fine.
The real problem
Claude then measured the speakers with the internal mic. Play a log sweep, record it, take the peak level in each third octave band. The result was a steep tilt. Relative to the midrange, 250 Hz was 19 dB down. 400 Hz was 12 dB down. Everything above 3 kHz was 7 to 10 dB up. That is exactly what "earbuds across the room" sounds like.
So the hardware was never broken. Apple runs a correction curve in software, and Linux does not. Nobody has fixed this in a driver on any distro because there is nothing to fix in the driver. The fix is EQ.
Where the sound was dying every two seconds
Halfway through, a second problem showed up. YouTube would play for two seconds, stop, play two seconds, stop. The EQ filter chain Claude built with PipeWire's filter chain module was dying about once a second. Later, when I installed EasyEffects myself, it said it was launching and never appeared.
This turned out to be one bug with three faces. rtkit was not installed when the machine booted. xdg-desktop-portal started, asked rtkit for the realtime limits, got nothing, and cached RTTimeUSecMax as zero. When rtkit was installed later, the portal kept the cached zero. PipeWire's realtime module handed every client a realtime thread with a CPU time limit of zero microseconds, and the kernel killed each one on its first tick.
Claude proved it rather than guessed at it. ftrace on signal_generate filtered for signal 9 showed the kernel sending the kill to the data loop thread. strace on a client showed prlimit64 setting RLIMIT_RTTIME to zero right before it died. Restarting the portal made it report 200000 and every client stopped dying. rtkit is enabled at boot now so it cannot happen again.
If your PipeWire apps vanish on launch after a fresh Omarchy install, check this before anything else. The command is in the skill.
The fix that stuck
The correction lives in EasyEffects now. A 70 Hz high pass to keep the woofers out of trouble, an 11 dB low shelf at 250 Hz, two bells adding back the low mids, a small cut at 1.1 kHz, a 9 dB high shelf cut above 2.5 kHz, and a limiter at the end. The equalizer runs with 8 dB of input gain reduction so the shelf has headroom. When kick drums popped instead of thumped, the answer was less drive into the limiter, not less bass.
EasyEffects starts hidden at login from Omarchy's autostart.lua, so the laptop just sounds right when it comes up. Since the whole curve is a preset with a GUI, I can nudge the bands by ear without touching a config file.
It is not macOS good. The mic that measured the curve is deaf below 120 Hz, so the bottom octave is by ear. But it is a laptop with bass again, and Omarchy stays.
The skill
The whole procedure, the preset JSON, the portal check, and the measurement method are in a skill file you can drop into ~/.claude/skills or hand to any agent: macbook-speaker-eq.md. It is written for MacBookPro11,x models with the CS4208 codec. Other MacBooks have a different tilt, so measure first and reuse the method rather than the numbers.