- This topic has 1 reply, 1 voice, and was last updated February 18, 2014 at 8:45 am by Anonymous.
October 25, 2013 at 7:48 pm #1056607MadPsyParticipant
Here’s a quick how to on sending audio from either a Linux box or Mac to another Linux box.
This is useful if you want to, for example, play Spotify on your laptop and send it over WiFi to your PC plugged into your HiFi.
Third Party Tools
There are many tools out there which can do this, but they all have their pros n cons.
1) Mac/Windows to Linux
Airfoil (Rogue Amoeba | Airfoil)
This works well, but is not free (speech or beer). It has a Linux and Android receiver (called the ‘speakers’) and the source can be Windows or Mac. It supports Mac Air devices, such as Apple TV and Airport Express. I found ‘Speakers’ doesn’t work on my Android box (see below).
This is a nice receiver for Air, OS X/IOS devices for Android. I use this on my Android TV Box (7dayshop Android 4.2 (Jellybean) Dual Core Wi-Fi Internet TV Media Centre – 8GB – 7DAYSHOP.COM). It works most of the time, but stutters like mad sometimes, but it is free (beer).
Note: Everyone should get one of those Android TV boxes, its £40 and pretty much a tablet with HDMI output for the TV. Can watch Netflix, iPlayer, pretty much every App works, except ‘Speakers’ 🙁 Not sure if its root-able yet, I’ve not managed anyway, which is a shame, as a VNC server running on it would be ideal.
This is ye ol faithfull ‘just works’ solution. Problem is it’s far from simple and far far overspec’ed for what we’re trying to achieve here. It’s designed for a different job – Internet radio.
There are many many more solutions, but they are all (in my opinion) overly complex solutions to a simple problem which can be solved using a much fundamentally simpler method.
All Air and Icecast solutions, by design, have at least a 2 second lag. It’s to allow a large buffer to negate any delay in data transmission. it’s not required on a home LAN, only over the Internet (due to high latency and jitter). This is most irritating as it means there’s always a delay between when you expect to hear sound and when you do, my solution below has around 100ms of lag, which is like a short echo, but that’s not an issue as you’re not going to listen to it locally and through your HiFi at the same time. This means when you press play it appears pretty much instantaneous.
So I figured there has to be a much simpler way to get audio from one machine to another on your own home network. My philosophy to these sort of problems is always simple is better, period. I’ve written hundreds of Perl, Bash, PHP scripts to do complex tasks over the years and the one thing i know is the simpler you make it the more reliable and easier to maintain it is.
Note: This is uncompressed audio, meaning whatever you play is sent and received in its raw form. In short, if you send it shite, it will play shite, if you play FLAC/PCM it will play it as is. This requires around 200KB/sec, which is nothing over a LAN.
What you’ll need:
1) An ubuntu computer plugged into your HiFi
2) A wired or wireless network
3) A Mac or Linux machine to send audio from (In my case a Mac laptop connected over wireless)
Some Background how and why this is possible:
Mac and Linux are beautifully designed operating systems. There are some fundamental reasons for this:
1) Every device, directory, proc etc is a FILE. This means you can pipe data to and from anything to anything over a socket.
2) The desktop and audio systems are server/client based. This means you can turn X11 and Pulseaudio into network-available services. That’s right.. the desktop you see on the screen and the audio you hear can be sent over a network, not just to your monitor & soundcard – the important thing here is they can do this *natively* with no 3rd party tools.
A mac is slightly different, but the same basic principles apply. OS X is based on *BSD. This means it retains the UNIX (SysV) style approach to its core design.
MacPorts (The MacPorts Project — Home) – A simple explanation, this is like ‘apt-get’ in Debian/Ubuntu and allows you to easily install packages.
Mac to Ubuntu
Recent Ubuntu releases use PulseAudio as its sound server. You can use this to send and receive audio data over a network in semi-realtime. PulseAudio, although opernsource, hasn’t yet been ported to Mac, instead we’ll use ESD (Enlightened Sound Daemon) as the ‘sender’ as its available via MacPorts.
On your ubuntu box, run (as your user, as PA runs per user by default):
nc -u -l 1337 | pacat –latency-msec=1
This will do 2 things:
1) Start NetCat listening on UDP port 1337
2) Pipe the stream from NetCat to ‘pact’ **This is important, recent versions of PA it won’t accept raw ESD streams, therefore you can’t just use PA server to accept the stream**
NetCat allows you to send and receive TCP/UDP packets in raw form, no bells and whistles, just simple socket connections over a network.
pacat is PulseAudio’s tool for sending audio to the PA server. It has a million options but for this example lets keep it simple.
Your ubuntu box is now ready to accept raw audio from another device on the network.
On your Mac:
Install MacPorts – see website.
Install ESD (ports install esd)
This is important. See Soundflower « Cycling 74
Soundflower is like jackd for Linux, it’s an audio routing daemon which will internally redirect audio on a loopback interface to make it available to ESD to then record and send off over the network. You need to set the input and output devices to the 2channel sound flower device in sound preferences.
Once that is done, the final bit is simple:
1) Start the ESD server:
esd -tcp -bind ::1 &
This makes ESD listen locally for TCP connections from the ESD recording tool (the & tells it to fork to the background)
2) Start the recorder and pipe it to NetCat, replace 192.168.0.2 with the IP of your Ubuntu box used as the reciever:
esdrec -s ::1 | nc -u 192.168.0.2 1337
This first starts the ESD recorder, which takes a raw audio stream from ESD itself and pipes it (via the | symbol) to NetCat, which instead of listening on a port just sends it over the network to UDP port 1337.
The keen eyed amongst you will have noticed we’re using a mix of TCP and UDP for transport. TCP is used locally, and UDP when it’s sent on the wire. The reason is simple:
1) Latency locally is negligible. Therefore TCP on a local loopback interface is just fine.
2) Latency on a network is important, as is jitter. Once on a network, regardless of medium (wired ethernet or wireless) latency and jitter is a factor. We use UDP for its ‘send and forget’ characteristics. Where TCP has error checking and retry algorithums, UDP doesn’t. For our purposes we don’t want the overhead TCP has, we just want the sender to send, and the receiver to receive. If packets are being corrupted on a LAN to such an extent it’s breaking the stream you have more pressing issues which need fixed on your network.
Ubuntu to Ubuntu
I’ve not yet tried this but there is one basic major difference. You can use PulseAudio to send and receive directly, without the ESD and NetCat nonsense. PulseAudio server on the reciever can be told to listen on a port and ‘parec’ on the sender can talk directly to the PA server.
I don’t have specifics on this just now, but it’s going to be pretty much the same, if not simpler:
1) Configure PA on the receiver to listen on a port (natively! not via nc)
2) Start parec on the sender to send directly to the PA server
Have fun! If anyone has any questions please ask. Don’t leave it too long though as I’ll probably move onto a new project and forget everything I’ve just explained 🙂February 18, 2014 at 8:45 am #1276100Anonymous
Good Explanation for Sending audio from one computer to another, I will try to follow above steps 🙂
- You must be logged in to reply to this topic.