The living room audio chain was never designed. It accreted, one reasonable decision at a time, and the result is a signal path that crosses seven protocols between a play button and a bass note: Spotify Connect in the cloud, a streamer on the LAN, a Zigbee remote, a Bluetooth subwoofer, an eARC handshake with a 2010 television, a Chromecast, and an infrared projector whose remote no longer exists. None of these devices speak each other's language. All of them answer to the same couch.
The living room audio path is a monument to the principle that every device may speak only to the device it was designed to speak to, and to nothing else. Seven protocols between a streaming service and a subwoofer. It works, every evening, and nobody who has not seen the diagram would believe why.
The necromancy of eARC
The television is from 2010. It predates apps, assistants and most of the acronyms in this
paragraph, and it has exactly one modern trick: it can hand its audio to the streamer over
eARC. The catch took a while to isolate: the audio only routes if the television itself
wakes the streamer. If the streamer is already awake when the TV comes on, the handshake
completes, every status light agrees, and no sound arrives. The streamer reports
on; only playing means sound.
So the automation does the opposite of what intuition suggests. When the television turns on, we turn the streamer off, and let the TV resurrect it. One power cycle, executed at the only moment it helps, and eighteen years of HDMI politics are settled.
The remote is dead, long live the specification
The projector is an Epson from 2008. Its remote control is wherever remotes go, and buying a replacement for a discontinued model felt like defeat. But an IR remote is not magic, it is a modulated bitstream with a published grammar, and the projector's dialect is plain NEC: a 9 ms leader, then thirty two bits at 562 microseconds a pulse, address first, command after, each followed by its complement.
leader: 9000 us mark, 4500 us space
bit 0: 562 us mark, 562 us space
bit 1: 562 us mark, 1687 us space
frame: address 0x5583 (every Epson projector since roughly forever),
then the command byte and its bitwise complement
The command table is public in the crowd-sourced IR databases: power on is 0x90, power off 0x91, and there are twenty five more, direct input selection included, which the buttons on the projector itself cannot do. We generated the Broadlink packets straight from the timing grammar, no learning, no original remote, and the very first synthesized packet woke the projector from across the room. A dashboard tab now carries all twenty seven commands, including a proper navigation pad, so the projector's menus are once again reachable from a seated position.
A subwoofer that hangs up, politely
The subwoofer is controlled over Bluetooth LE and accepts exactly one connection at a time. Its integration therefore does something civilised: sixty seconds after the last command it hangs up, so the manufacturer's phone app can get a word in, and it silently redials whenever the next command arrives.
We learned this by building it wrong. Our first volume automation was guarded by "only when connected", which reads as prudence and works as a bug: the guard blocked precisely the common case, a sub sleeping between commands, even though writing to it is what wakes it. The connection sensor spends most of its life reading "disconnected" while everything is perfectly healthy.
We would like to say we would do it differently next time. We would do it exactly the same, and be exactly as surprised that it works.
Loudness, drawn through three points
Human hearing loses low frequencies faster than the rest as volume drops, which is why quiet late night listening always sounds thin. The textbook answer is a loudness contour. The household answer: sit on the couch, find the subwoofer level that sounds right at a few volumes, and connect the dots.
It began as two points and a straight line. Then a third point arrived from a quieter
evening (volume 20, ear says minus 10) and bent the line where the straight version was one
decibel too generous. The curve is now piecewise: sub_dB = -1 - 0.5 x volume up to
volume 30, 2 - 0.6 x volume above it, continuous at the joint, clamped to the
subwoofer's range.
An automation holds the bass to that curve whenever the streamer's volume moves. The remote's volume steps arrive in bursts of three, so it waits out the burst and writes once; the subwoofer does not enjoy being dialled like a rotary phone.
A footnote a week later: after some hours of use the driver loosened up and the whole curve moved down by one decibel, measured the only way it can be, by the same ear at the same evening volume. A loudness curve is not a constant of the room; it is a constant of the room, the box and the month.
One more term joined the curve later: while the air conditioner runs, the subwoofer gets two decibels more. Its fan is a broadband hiss that sits exactly on the bottom octave, and the ear, which is very good at subtracting steady noise, subtracts a little of the bass along with it.
Three personalities and a scheduler
The subwoofer stores presets, so it now has three characters. Music is the reference: the ear-tuned crossover, phase and nothing else, because for music the correct amount of subwoofer is the amount you cannot point at.
Movie adds four decibels and a gentle shelf around 30 Hz, since film soundtracks carry an effects channel mixed with headroom that living rooms never use. Night is the diplomatic one: eight decibels down and a room gain cut that removes precisely the deep bass that travels through concrete to the neighbours, while the couch keeps most of the illusion.
An automation switches between them: television sound on the eARC path means Movie, anything else means Music, ten in the evening or the house-wide sleep flag means Night, and eight in the morning hands control back to the sources. A manual pick from the dashboard is respected for six hours before the machinery resumes, the same convention the light switches in this flat already follow: the human is always allowed to overrule the script, and the script is always allowed to forget about it by morning.
The trap worth exporting: the subwoofer reports which preset is active only in the moment one is loaded, and its preset selector reads "unknown" the rest of the time. The first version of the volume logic keyed off that selector and quietly computed nonsense.
The fix is a rule as old as SCADA: keep your own source of truth. A helper in Home Assistant declares which character the subwoofer is supposed to have; the device's selector is demoted to an actuator; every other automation reads the helper. The subwoofer is consulted about reality only when it volunteers it.
The ninety degree ear
The subwoofer's phase control ended up at 90 degrees because that is where it sounded best, which invited the obvious question: is that a real setting or a superstition? The arithmetic says real. At an 80 Hz crossover the wavelength is about 4.3 metres, so 90 degrees is a quarter of that, roughly a metre of effective path difference, which is comfortably what you get from speaker placement plus the few milliseconds a DSP subwoofer spends thinking. At the crossover the sub and the mains play the same notes; misalign them and they subtract.
The ear found the alignment first and the physics signed off afterwards, which is the correct order for a living room and the reverse of how it usually goes in this house. For the sceptical there is a classic verification: invert the sub's polarity, sweep the phase for the deepest null at the listening position, then flip polarity back. The deepest hole, inverted, is the tallest sum.
One remote to rule the blob
Holding the blob together is a small Zigbee remote that was designed to control a different manufacturer's speakers. Its community blueprint needed a fork: the upstream volume stepping only applied to grouped players, which is the kind of sentence that costs an afternoon to be able to write. It now moves volume three steps per press, and its play button first checks the streamer's input and reroutes it to Spotify when something else has wandered onto it, because a play button that plays nothing is a lie.
Its two spare gestures went to the house's sense of humour: one dot toggles the streamer's power, and a double dot asks the house spirit to show itself in colour on the nearest lamps. No protocol in the stack strictly required that last feature. It stays.
Count the seams: a cloud service, a LAN protocol, Zigbee, Bluetooth LE, eARC and CEC over HDMI, Google Cast, and raw infrared. Seven ways for machines to disagree, wired into one system by the only integrator that speaks all seven. Nobody would design this. It merely works, every evening, from the first press of a play button to the last note the neighbours generously tolerate.
A screen with no bottom
The projector needed a screen, and the screen got a motor on a Zigbee shutter switch: three commands, up, down, stop. Its upper limit is honest mechanics, the screen simply cannot roll any further. Its lower limit switch is broken, so "down" means "down until somebody says stop", which is not a position a system can rely on.
The switch's automatic calibration, the one that runs the motor to both ends and times the trip, was therefore out of the question; it would have unrolled the screen into the floor looking for a switch that no longer exists.
The manual calibration turned that defect into a feature. In manual mode the switch measures the trip up, then drives down and records "fully closed" wherever the human presses the third button. We pressed it at the height that fits the picture, a hand's width above the true end.
From then on "closed" means that height: the switch times the trip itself and stops there, and every position in between is a percentage of a run that ends at the picture, not at the floor. Our first timing run was spoiled by a well-meant stop command sent during the measurement, which taught us that a calibration in progress must be left alone; the second run, done entirely from the phone standing at the screen, took thirty seconds.
The resolution is about a centimetre per percent, so the last few millimetres were settled with one very short pulse and then frozen as a cinema position at three percent. The screen follows the projector: on when the projector comes on, up when it goes off, with the buttons on the audio tab for the times when a human wants it otherwise.