I want to be able to watch movies and videos on the TV, but I want the audio to be heard only through headphones.
And I had a few requirements:
- Low latency
One solution is to run a headphone extension cable from the TV. But that gets unwieldy pretty quickly for distances greater than a few feet.
I want the audio to be heard by multiple people at the same time through each individual set of headphones.
The audio has to be rendered with the least amount of latency possible so that the video could be watchable. If the audio is delayed, then the dialog/sound effects/etc wouldn’t be in-sync with the video.
Since my HTPC is Ubuntu 12.04 running XBMC, I figured I could reuse some existing OSS software to stream audio from Ubuntu to a mobile device. And since I have an Android phone, I figured I would start there.
This project was really easy to implement because PulseAudio on Ubuntu already supports a TCP stream of uncompressed PCM audio. The only requirement is to add a few lines (below) to enable the module.
The documentation for the module is at http://www.freedesktop.org/wiki/Software/PulseAudio/Documentation/User/Modules/#index20h3
And the Android app simply reads data from a socket and uses Android’s AudioTrack to render the audio. The app is based on the random music player SDK example.
It’s so glitchy
The challenge is to try to keep the video on the TV synced with the audio. And that means rendering the audio with the lowest latency possible.
The very first versions of the app do not handle this well. Basically, when the app detects it’s falling behind, it simply starts dropping data left and right. This results in obvious glitches in audio. It sacrifices quality for latency because delayed audio while watching movies sucks.
Improvements will be made.
Setting up PulseAudio
[Also check out the link to the module documentation above]
There are only a couple of steps:
- Determine which source to stream
- Edit config files so with the proper parameters
- Restart PulseAudio
I am running Ubuntu 12.04.
Determine which source to use
Open up a terminal in Ubuntu and type
pactl list sources short
This will spit out a bunch of text, but what you’re looking for is the ‘analog-stereo.monitor.’ I have edited the output from my machine and highlighted important items in red.
0 alsa_output.pci-0000_01_00.1.hdmi-stereo.monitor module-alsa-card.c s16le 2ch 44100Hz SUSPENDED 1 alsa_output.pci-0000_00_1b.0.analog-stereo.monitor module-alsa-card.c s16le 2ch 44100Hz SUSPENDED 2 alsa_input.pci-0000_00_1b.0.analog-stereo module-alsa-card.c s16le 2ch 44100Hz SUSPENDED
Look for “analog-stereo.monitor” and take note of the index number on the left. In my case, it’s 1.
Edit config files
You will need to edit the config files to load this module with the specific parameters. To do so, type (you will need the sudo password)
gksu gedit /etc/pulse/default.pa
Add the following line near the bottom, substituting your source index:
load-module module-simple-protocol-tcp source=1 record=true port=12345
I had problems with the default port of 4711 because it seems to be already in use and so I just choose 12345.
For mono, you can use channels=1 and for a lower sampling rate rate=24000. The app has been updated to include support for this in an attempt to reduce latency.
If you are hearing static, try changing the audio format generated by pulse from 32bit little endian to 16bit little endian (link).
load-module module-simple-protocol-tcp source=1 record=true port=12345 format=s16le
Restart PulseAudio with the new configuration
pulseaudio -k pulseaudio --start
And that should be it.
Start up the app, type in IP address/port of the Ubuntu box and stream audio to your Android device.
A corresponding Windows server has been published to github. Please see the following for more information: https://kaytat.com/blog/?p=332