juhovh / shairplay

Apple airplay and raop protocol server
Other
1.35k stars 228 forks source link

Is there a way to change the buffer size to a smaller value? #55

Closed soultice closed 6 years ago

soultice commented 8 years ago

I would like to decrease the buffer size as it takes my RaspberryPi several seconds to start playing sound that I am streaming, It would be nice to reduce this delay to a more real-time experience. Is there a way to recompile shairplay with a reduced buffer size? Or am I completely wrong with my idea?

MarcoWue commented 8 years ago

Apple devices feature low-latency audio streaming with reduced buffer sizes. This would be incredibly useful to have in shairplay and the software using this library like KODI.

This way one could omit audio cables and just stream audio via network: http://tuneblade.com/support/Documentation/3.html

juhovh commented 8 years ago

Currently shairplay keeps as small buffer as possible with default values, buffering is mostly left for audio output. Thanks for this document, I'll check it out and see of there's anything that could be done.

MarcoWue commented 8 years ago

@juhovh

Currently shairplay keeps as small buffer as possible with default values

I had another look into your code. Buffering is done in the _audioprocess() function of shairplay.c: if (session->buflen+buflen < sizeof(session->buffer)) { memcpy(session->buffer+session->buflen, buffer, buflen); session->buflen += buflen; return; }

Audio data is always buffered until the buffer is full. Buffer size is hardcoded to 8192 bytes in _shairplay_sessiont. Assuming stereo 16-bit audio and 48 kHz sampling frequency, this means about 42ms of latency here.

Another buffer _raoprtp->buffer is found in _raoprtp.c which is hardcoded to maximum 32 packets. Each packet should contain 4096 audio frames by default (see frameLength here). Assuming 48 kHz sampling frequency this means 85ms latency per packet. Obviously the buffer could provide lots of latency when getting full, however it seems it is processed immediately when packages arrive in the correct order.

It seems the reason for having lots of latency is within KODI. Digging a bit deeper I found that KODI uses its own callback functions for handling audio processing (see CAirTunesServer::Initialize in xbmc/network/AirTunesServer.cpp). Audio data is written to a pipe instead of directly being sent to the audio output device like shairplay actually does.