mikebrady / shairport-sync

AirPlay and AirPlay 2 audio player
Other
7.29k stars 574 forks source link

Buffer longer than 2 sec? #697

Closed DapperDapp closed 6 years ago

DapperDapp commented 6 years ago

Hello, I'm trying to create a mobile-ish pi device that can go in and out of wifi range and continue playing from buffer while out of range for about 10 seconds, and then refill the buffer while in range with no interruption in audio playback. If there needs to be a long latency to achieve this that is okay.

I have sharepoint sync running on Volumio and I have tried increasing the buffer settings like crazy, but I'm not getting more than a couple seconds runtime offline. Can someone let me know if what I'm trying to achieve is possible and if so how to do it? Thanks! here are my settings:

general =
{
    name = "mrPi";
    log_verbosity = 0;
    audio_backend_buffer_desired_length_in_seconds = 10;
    drift_tolerance_in_seconds = 10; // allow a timing error of this number of seconds of drift away from exact synchronisation before attempting to correct it
    resync_threshold_in_seconds = 10;
    audio_backend_latency_offset_in_seconds = 10;
    audio_backend_silent_lead_in_time = 10;
};

alsa =
{
  output_device = "${device}";
  period_size = 100000;
  buffer_size= 1920000;
  disable_synchronization = "yes";

};

sessioncontrol =
{
  allow_session_interruption = "yes";
  run_this_after_play_ends = "/usr/local/bin/volumio stopairplay";
};

metadata =
{
    enabled = "yes";
    include_cover_art = "no";
    //pipe_name = "/tmp/shairport-sync-metadata";
    //pipe_timeout = 5000;
    socket_address = "127.0.0.1";
    socket_port = 5555;
};
mikebrady commented 6 years ago

Thanks for the post. Shairport Sync picks up the latency automatically from the source, and is designed for latency of not more than about 3.5 seconds. There is an old command-line option -L <frames> where you specify the number of frames of latency (44,100 per second), but it is deprecated and doesn't do a range check, so may well crash Shairport Sync.

The AirPlay spec in not public, but as far as I remember, an AirPlay source doesn't keep old frames of audio for more than a few seconds.

DapperDapp commented 6 years ago

Hey thanks Mike! I really appreciate the project and your help.

The -L option worked up to about 350,000 frames before giving me:

Aliasing of buffer index -- reset. This is not a problem though because its close to my 10 second goal. The problem I ran into though was that when the pi disconnects for any amount of time, that lost audio is not recovered during the long latency period as I was hoping. Basically, the cut out in audio is just delayed 7 seconds. I'm using default options in the config file, besides the -L command line option.

Is it possible for sharepoint to resync the dropped audio? Or are you saying that the source discards the old frames, and they can not be resent.

mikebrady commented 6 years ago

Thanks for the update, but I’m afraid I’m going to rain on your parade a bit.

Shairport Sync has 512 buffers each holding 352 audio “frames” or samples, with 44,100 samples per second. Thus, the maximum delay possible could be 180,224 frames, or just over 4 seconds.

If you keep below that figure (actually, you need to leave a little spare, say 32 buffers) then the missing samples should be recovered. I could modify Shairport Sync (not “sharepoint” BTW) to use 1,024 or 2,048 buffers (it has to be a power of 2), but you’d have to compile it according to the README here. Would you be up for that?

DapperDapp commented 6 years ago

That would be amazing! I would definitely compile Shairport Sync and try it out.

So you're saying that I could drop wifi connection for up to 4, or more seconds and then reconnect and recover those frames?

Here are some headphones that do something similar to what I'm trying to make using the airplay 2 long buffer time. They call the feature "infinity range":

https://www.kickstarter.com/projects/1465125457/e-cliptm-wireless-high-fidelity-headphones-with-ai/description

Thanks again for your help.

mikebrady commented 6 years ago

Thanks. It might take a few days...

DapperDapp commented 6 years ago

Okay, I will get set up to compile and test when you finish.

On Sat, May 12, 2018, 12:05 PM Mike Brady notifications@github.com wrote:

Thanks. It might take a few days...

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/mikebrady/shairport-sync/issues/697#issuecomment-388576212, or mute the thread https://github.com/notifications/unsubscribe-auth/AkDz0aVyWL7Be2M3qeryzOh3qUsHbzYKks5txzKVgaJpZM4T6qkk .

mikebrady commented 6 years ago

Hi there. I've pushed an update to the development branch to handle longer latencies. As it stands, it's no better than the present version, but it can easily be tweaked -- I've tested it out to 20 seconds. If you could build and test it as is, then by changing line 60 of player.h you can make it handle a longer latency.

DapperDapp commented 6 years ago

Thankyou very much for working on that so fast I will test it out today.

Was it able to recover frames because of the longer latency?

On May 15, 2018 6:59 AM, "Mike Brady" notifications@github.com wrote:

Hi there. I've pushed an update to the development branch to handle longer latencies. As it stands, it's no better than the present version, but it can easily be tweaked -- I've tested it out to 20 seconds. If you could build and test it as is, then by changing line 60 of player.h you can make it handle a longer latency.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/mikebrady/shairport-sync/issues/697#issuecomment-389177205, or mute the thread https://github.com/notifications/unsubscribe-auth/AkDz0SqcAKVdrVDGHpzXphJ_txxD39gWks5tyt9egaJpZM4T6qkk .

mikebrady commented 6 years ago

The updated version spreads requests for missing packets out over the latency period -- there will be a maximum of 8 in total, whereas the present version stops after about two seconds, max.

As I mentioned before, it's not clear whether AirPlay sources will keep packets around for resending for more than a small number of seconds, so that resend requests might not be satisfied after that time. If you turn on log verbosity to 2, you'll get some more information about unsuccessful resend requests.

DapperDapp commented 6 years ago

Okay I tried settingint64_t latency:20; in line 60 and restarting but I didn't notice a change, do I need to change the config file as well?

mikebrady commented 6 years ago

No, that's not correct. On the development branch (make sure you're not on the master branch), line 60 of player.h reads:

#define BUFFER_FRAMES 1024

Change that to:

#define BUFFER_FRAMES 2048

and run make again to rebuild the binary. This gives it the ability to have a range of latencies up to about 15 seconds.

Then you can user the regular -L command line option with something like: -L 441000 to get a latency of 10 seconds.

mikebrady commented 6 years ago

If it's problematic, let me know and I'll create a separate branch.

DapperDapp commented 6 years ago

No problem, I'm still learning over here. So I was able to make with the increased frame and run with the latency and it did actually recover about 2 seconds unplugged! Before it didn't seem to recover any amount so thats an improvement. At above 2 seconds the excess seems to not be recovered. That may be a limitation on the source?

mikebrady commented 6 years ago

Thanks, yeah, it may well be a limitation of the source, and I guess different sources (e.g. iTunes, iOS) might have different limitations. Some third-party sources actually allow you to vary the latency; not sure how good they are though. The thing is that the AirPlay specifications have never been published, so much remains unknown about them :(...

DapperDapp commented 6 years ago

I think that Airplay 2 is supposed to hold a longer buffer. Have you been able to test it with shairport sync yet?

DapperDapp commented 6 years ago

Not yet, I am trying to update my iPhone to 11.04 with Airplay 2 right now. I will let you know how it goes.

DapperDapp commented 6 years ago

Apple isn't sending the update at the moment, so I don't know how long it will be until I get to test it :(

mikebrady commented 6 years ago

AirPlay 2 seems very different to AirPlay, so I don’t think Shairport Sync will be compatible. It seems as if Apple is keeping regular AirPlay alongside AirPlay 2, as least for the present...

DapperDapp commented 6 years ago

Hi @mikebrady , I think I am going to try and make my own Airplay source next week, using this library: https://github.com/lperrin/node_airtunes

And try changing the buffer size in the config file to be 10 seconds long:

https://github.com/lperrin/node_airtunes/blob/96b1a1743ab3288d977692494c5c441026750d2e/lib/config.js

I'm hoping that node_airtunes running on one pi as the source, and your modified shairport-sync with the longer buffer running on the other will allow a greater buffer for the overall system. I wanted to see what you thought in case you knew whether or not it would work already and I should't waste my time. Thank you.

mikebrady commented 6 years ago

Hi. I haven't any particular experience with node_airtunes, I'm afraid, but it looks well-made.

DapperDapp commented 6 years ago

I thought that I would post that I tried the increased shairport buffer to test with an Airplay 2 device, but the results are the same, about a 2 sec buffer. I'm assuming the source must be auto detecting the version and is working backward compatible to version 1. I still need to try that node_airtunes source.

mikebrady commented 6 years ago

That’s interesting, thanks. I did want Nader about it.