Skip to content

Commit

Permalink
3.3.7rc0
Browse files Browse the repository at this point in the history
  • Loading branch information
mikebrady committed Jul 6, 2020
1 parent 8e46117 commit bdc2dca
Show file tree
Hide file tree
Showing 37 changed files with 3,138 additions and 3,671 deletions.
2 changes: 1 addition & 1 deletion FREEBSD.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ Next, configure the build and compile it:

```
$ autoreconf -i -f
./configure --with-libdaemon --with-avahi --with-ssl=openssl --with-sndio --with-libdaemon --with-os=freebsd --with-freebsd-service
$ ./configure --with-libdaemon --with-avahi --with-ssl=openssl --with-sndio --with-libdaemon --with-os=freebsd --with-freebsd-service
$ make
```
Add `--with-alsa` if you wish to include the ALSA back end. Omit the `--with-sndio` if you don't want the `sndio` back end. Omit the `--with-freebsd-service` if you don't want to install a FreeBSD startup script, runtime folder and user and group -- see below for more details.
Expand Down
30 changes: 15 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ For more about the motivation behind Shairport Sync, please see the wiki at http

Synchronisation, Latency, "Stuffing"
---------
The AirPlay protocol uses an agreed *latency* – the time difference, or delay, between the time represented by a sound sample's `timestamp` and the time it is actually played by the audio output device, typically a Digital to Audio Converter (DAC). The latency to be used is specified by the audio source when it negotiates with Shairport Sync. Most sources set a latency of two seconds. Recent versions of iTunes and forkedDaapd use a latency of just over 2.25 seconds. A latency of this length allows AirPlay players to correct for network delays, processing time variations and so on.
The AirPlay protocol uses an agreed *latency* – the time difference, or delay, between the time represented by a sound sample's `timestamp` and the time it is actually played by the audio output device, typically a Digital to Audio Converter (DAC). The latency to be used is specified by the audio source when it negotiates with Shairport Sync. Most sources set a latency of two seconds. Recent versions of iTunes and forkedDaapd use a latency of just over 2.25 seconds. A latency of this length allows AirPlay players to correct for network delays, processing time variations and so on.

As mentioned previously, Shairport Sync implements full audio synchronisation when used with `alsa`, `sndio` or PulseAudio systems. This is done by monitoring the timestamps present in data coming from the audio source and the timing information from the audio system, e.g. `alsa`. To maintain the latency required for exact synchronisation, if the output device is running slow relative to the source, Shairport Sync will delete frames of audio to allow the device to keep up. If the output device is running fast, Shairport Sync will insert frames to keep time. The number of frames inserted or deleted is so small as to be almost inaudible on normal audio material. Frames are inserted or deleted as necessary at pseudorandom intervals. Alternatively, with `libsoxr` support, Shairport Sync can resample the audio feed to ensure the output device can keep up. This is less obtrusive than insertion and deletion but requires a good deal of processing power — most embedded devices probably can't support it. The process of insertion/deletion or resampling is rather inelegantly called “stuffing”.

Expand All @@ -42,7 +42,7 @@ What else?
* An [MPRIS](https://specifications.freedesktop.org/mpris-spec/2.2/) interface, partially complete and very functional, including access to metadata and artwork, and some limited remote control.
* An interface to [MQTT](https://en.wikipedia.org/wiki/MQTT), an often-used protocol in home automation projects.
* A native D-Bus interface, including access to metadata and artwork, some limited remote control and some system settings.

Heritage
-------
Shairport Sync is a substantial rewrite of the fantastic work done in Shairport 1.0 by James Laird and others — please see https://github.com/abrasive/shairport/blob/master/README.md#contributors-to-version-1x for a list of the contributors to Shairport 1.x and Shairport 0.x. From a "heritage" point of view, Shairport Sync is a fork of Shairport 1.0.
Expand All @@ -67,7 +67,7 @@ See [here](https://github.com/mikebrady/shairport-sync/blob/master/INSTALL.md) f

Shairport Sync may already be available as a package in your Linux distribution (search for `shairport-sync` – the package named `shairport` is a different program). Packages are available on recent versions of Debian, Ubuntu, Arch, OpenWrt and possibly more:

**Ubuntu:** A `shairport-sync` installer package is available for Ubuntu. Additionally, a Personal Package Archives for Shairport Sync master and development branches are available at https://launchpad.net/~dantheperson.
**Ubuntu:** A `shairport-sync` installer package is available for Ubuntu. Additionally, a Personal Package Archives for Shairport Sync master and development branches are available at https://launchpad.net/~dantheperson.

**Debian:** shairport-sync is in the Debian archive.

Expand All @@ -77,7 +77,7 @@ Shairport Sync may already be available as a package in your Linux distribution

To build and install the latest version of Shairport Sync, an [Arch Linux build and installation guide](https://github.com/mikebrady/shairport-sync-for-arch-linux) is available, based on original work by [Elia Cereda](https://github.com/EliaCereda).

**Mac OS X:** A HomeBrew package exists for Shairport Sync. With HomeBrew installed, Shairport Sync can be installed using the command:
**Mac OS X:** A HomeBrew package exists for Shairport Sync. With HomeBrew installed, Shairport Sync can be installed using the command:
```
$brew install shairport-sync
```
Expand All @@ -93,7 +93,7 @@ If you wish to build and install the latest version of Shairport Sync on Debian,

**Remove Old Versions of Shairport Sync and its Startup Scripts**

You should check to see if `shairport-sync` is already installed – you can use the command `$ which shairport-sync` to find where it is located, if installed. If it is installed you should delete it – you may need superuser privileges. After deleting, check again in case further copies are installed elsewhere.
You should check to see if `shairport-sync` is already installed – you can use the command `$ which shairport-sync` to find where it is located, if installed. If it is installed you should delete it – you may need superuser privileges. After deleting, check again in case further copies are installed elsewhere.

You should also remove the startup script files `/etc/systemd/system/shairport-sync.service`, `/lib/systemd/system/shairport-sync.service` and `/etc/init.d/shairport-sync` if they exist – new ones will be installed in necessary.

Expand Down Expand Up @@ -125,13 +125,13 @@ If PulseAudio in not installed, you'll get something like this:
```
$ pactl info
-bash: pactl: command not found
$
$
```
If your system does not use PulseAudio, then it is likely that it uses the Advanced Linux Sound Architecture (ALSA), so you should build Shairport Sync with the ALSA backend. By the way, many systems with PulseAudio also have ALSA (in fact, PulseAudio is effectively a client of ALSA); in those cases you should choose the PulseAudio backend.

If PulseAudio is not installed, there is no necessity to install it for Shairport Sync. In fact, Shairport Sync works better without it.

**Building**
**Building**

To build Shairport Sync from sources on Debian, Ubuntu, Raspbian, etc. follow these instructions.

Expand Down Expand Up @@ -181,7 +181,7 @@ $ autoreconf -i -f

(Don't worry -- there's a recommended set of configuration options further down.)

- `--with-alsa` include the ALSA backend module to audio to be output through the Advanced Linux Sound Architecture (ALSA) system directly. This is recommended for highest quality.
- `--with-alsa` include the ALSA backend module to audio to be output through the Advanced Linux Sound Architecture (ALSA) system directly. This is recommended for highest quality.
- `--with-pa` include the PulseAudio audio back end. This is recommended if your Linux installation already has PulseAudio installed. Although ALSA would be better, it requires direct and exclusive access to to a real (hardware) soundcard, and this is often impractical if PulseAudio is installed.
- `--with-stdout` include an optional backend module to enable raw audio to be output through standard output (stdout).
- `--with-pipe` include an optional backend module to enable raw audio to be output through a unix pipe.
Expand All @@ -201,9 +201,9 @@ $ autoreconf -i -f

**Determine if it's a `systemd` or a "System V" installation:**

If you wish to have Shairport Sync start automatically when your system boots, you need to figure out what so-called "init system" your system is using. (If you are using Shairport Sync with PulseAudio, as installed in many desktop systems, this section doesn't apply.)
If you wish to have Shairport Sync start automatically when your system boots, you need to figure out what so-called "init system" your system is using. (If you are using Shairport Sync with PulseAudio, as installed in many desktop systems, this section doesn't apply.)

There are a number of init systems in use: `systemd`, `upstart` and "System V" among others, and it's actually difficult to be certain which one your system is using. Fortunately, for Shairport Sync, all you have to do is figure out if it's a `systemd` init system or not. If it is not a `systemd` init system, you can assume that it is either a System V init system or else it is compatible with a System V init system. Recent systems tend to use `systemd`, whereas older systems use `upstart` or the earlier System V init system.
There are a number of init systems in use: `systemd`, `upstart` and "System V" among others, and it's actually difficult to be certain which one your system is using. Fortunately, for Shairport Sync, all you have to do is figure out if it's a `systemd` init system or not. If it is not a `systemd` init system, you can assume that it is either a System V init system or else it is compatible with a System V init system. Recent systems tend to use `systemd`, whereas older systems use `upstart` or the earlier System V init system.

The easiest way is to look at the first few lines of the `init` manual. Enter the command:

Expand Down Expand Up @@ -365,7 +365,7 @@ Note: Shairport Sync can take configuration settings from command line options.

**Raspberry Pi**

The Raspberry Pi Models A and B have a built-in audio DAC that is connected to the device's headphone jack. Apart from a loud click when used for the first time after power-up, it is now quite adequate for casual listening.
The Raspberry Pi Models A and B have a built-in audio DAC that is connected to the device's headphone jack. Apart from a loud click when used for the first time after power-up, it is now quite adequate for casual listening.

To get the benefits of improvements in the Pi's software and firmware, you should update to the Raspian release of October 2018 or later, as a number of improvements have been made to the built-in DAC.

Expand Down Expand Up @@ -405,7 +405,7 @@ The System V init script at `/etc/init.d/shairport-sync` has a bare minimum :
Examples
--------

Here are some examples of complete configuration files.
Here are some examples of complete configuration files.

```
general = {
Expand Down Expand Up @@ -518,15 +518,15 @@ The UDP metadata format is very simple - the first four bytes are the metadata *

Latency
-------
Latency is the exact time from a sound signal's original timestamp until that signal actually "appears" on the output of the audio output device, usually a Digital to Audio Converter (DAC), irrespective of any internal delays, processing times, etc. in the computer.
Latency is the exact time from a sound signal's original timestamp until that signal actually "appears" on the output of the audio output device, usually a Digital to Audio Converter (DAC), irrespective of any internal delays, processing times, etc. in the computer.

Shairport Sync uses latencies supplied by the source, typically either 2 seconds or just over 2.25 seconds. You shouldn't need to change them.

Problems can arise when you are trying to synchronise with speaker systems — typically surround-sound home theatre systems — that have their own inherent delays. You can compensate for an inherent delay using the appropriate backend (typically `alsa`) `audio_backend_latency_offset_in_seconds`. Set this offset (in frames) to compensate for a fixed delay in the audio back end; for example, if the output device delays by 100 ms, set this to -0.1.

Resynchronisation
-------------
Shairport Sync actively maintains synchronisation with the source.
Shairport Sync actively maintains synchronisation with the source.
If synchronisation is lost — say due to a busy source or a congested network — Shairport Sync will mute its output and resynchronise. The loss-of-sync threshold is a very conservative 0.050 seconds — i.e. the actual time and the expected time must differ by more than 50 ms to trigger a resynchronisation. Smaller disparities are corrected by insertions or deletions, as described above.
* You can vary the resync threshold, or turn resync off completely, with the `general` `resync_threshold_in_seconds` setting.

Expand All @@ -537,7 +537,7 @@ Playback synchronisation is allowed to wander — to "drift" — a small amount

Some Statistics
---------------
If you turn on the `general` `statistics` setting, a heading like this will be output to the console or log file:
If you turn on the `general` `statistics` setting, a heading like this will be output to the log file (or to `STDERR` if the `-u` command line option is chosen):
```
sync error in milliseconds, net correction in ppm, corrections in ppm, total packets, missing packets, late packets, too late packets, resend requests, min DAC queue size, min buffer occupancy, max buffer occupancy, source nominal frames per second, source actual frames per second, output frames per second, source clock drift in ppm, source clock drift sample count, rough calculated correction in ppm
```
Expand Down
20 changes: 9 additions & 11 deletions activity_monitor.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ void going_active(int block) {
command_execute(config.cmd_active_start, "", block);
#ifdef CONFIG_METADATA
debug(2, "abeg"); // active mode begin
send_ssnc_metadata('pend', NULL, 0, 1); // contains cancellation points
send_ssnc_metadata('abeg', NULL, 0, 1); // contains cancellation points
#endif

#ifdef CONFIG_DBUS_INTERFACE
Expand All @@ -89,7 +89,7 @@ void going_inactive(int block) {
command_execute(config.cmd_active_stop, "", block);
#ifdef CONFIG_METADATA
debug(2, "aend"); // active mode end
send_ssnc_metadata('pend', NULL, 0, 1); // contains cancellation points
send_ssnc_metadata('aend', NULL, 0, 1); // contains cancellation points
#endif

#ifdef CONFIG_DBUS_INTERFACE
Expand Down Expand Up @@ -196,21 +196,19 @@ void *activity_monitor_thread_code(void *arg) {
} else {
state = am_timing_out;

uint64_t time_to_wait_for_wakeup_fp =
(uint64_t)(config.active_state_timeout * 1000000); // resolution of microseconds
time_to_wait_for_wakeup_fp = time_to_wait_for_wakeup_fp << 32;
time_to_wait_for_wakeup_fp = time_to_wait_for_wakeup_fp / 1000000;
uint64_t time_to_wait_for_wakeup_ns = (uint64_t)(config.active_state_timeout * 1000000000);

#ifdef COMPILE_FOR_LINUX_AND_FREEBSD_AND_CYGWIN_AND_OPENBSD
uint64_t time_of_wakeup_fp = get_absolute_time_in_fp() + time_to_wait_for_wakeup_fp;
sec = time_of_wakeup_fp >> 32;
nsec = ((time_of_wakeup_fp & 0xffffffff) * 1000000000) >> 32;
uint64_t time_of_wakeup_ns = get_absolute_time_in_ns() + time_to_wait_for_wakeup_ns;
sec = time_of_wakeup_ns / 1000000000;
nsec = time_of_wakeup_ns % 1000000000;
time_for_wait.tv_sec = sec;
time_for_wait.tv_nsec = nsec;
#endif

#ifdef COMPILE_FOR_OSX
sec = time_to_wait_for_wakeup_fp >> 32;
nsec = ((time_to_wait_for_wakeup_fp & 0xffffffff) * 1000000000) >> 32;
sec = time_to_wait_for_wakeup_ns / 1000000000;
nsec = time_to_wait_for_wakeup_ns % 1000000000;
time_for_wait.tv_sec = sec;
time_for_wait.tv_nsec = nsec;
#endif
Expand Down
1 change: 0 additions & 1 deletion alac.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
*
*/


#ifndef __ALAC__DECOMP_H
#define __ALAC__DECOMP_H

Expand Down
42 changes: 31 additions & 11 deletions audio.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ void parse_general_audio_options(void) {
* are set before any options are chosen */
int value;
double dvalue;
const char *str = 0;
if (config.cfg != NULL) {

/* Get the desired buffer size setting (deprecated). */
Expand All @@ -147,10 +148,10 @@ void parse_general_audio_options(void) {
/* Get the desired buffer size setting in seconds. */
if (config_lookup_float(config.cfg, "general.audio_backend_buffer_desired_length_in_seconds",
&dvalue)) {
if ((dvalue < 0) || (dvalue > 1.5)) {
if (dvalue < 0) {
die("Invalid audio_backend_buffer_desired_length_in_seconds value: \"%f\". It "
"should be between 0 and "
"1.5, default is %.3f seconds",
"should be 0.0 or greater."
" The default is %.3f seconds",
dvalue, config.audio_backend_buffer_desired_length);
} else {
config.audio_backend_buffer_desired_length = dvalue;
Expand Down Expand Up @@ -190,23 +191,42 @@ void parse_general_audio_options(void) {
/* Get the latency offset in seconds. */
if (config_lookup_float(config.cfg, "general.audio_backend_latency_offset_in_seconds",
&dvalue)) {
if ((dvalue < -1.75) || (dvalue > 1.75)) {
die("Invalid audio_backend_latency_offset_in_seconds \"%f\". It "
"should be between -1.75 and +1.75, default is 0 seconds",
dvalue);
config.audio_backend_latency_offset = dvalue;
}

/* Check if the length of the silent lead-in ia set to \"auto\". */
if (config_lookup_string(config.cfg, "general.audio_backend_silent_lead_in_time", &str)) {
if (strcasecmp(str, "auto") == 0) {
config.audio_backend_silent_lead_in_time_auto = 1;
} else {
config.audio_backend_latency_offset = dvalue;
if (config.audio_backend_silent_lead_in_time_auto == 1)
warn("Invalid audio_backend_silent_lead_in_time \"%s\". It should be \"auto\" or the "
"lead-in time in seconds. "
"It remains set to \"auto\". Note: numbers should not be placed in quotes.",
str);
else
warn("Invalid output rate \"%s\". It should be \"auto\" or the lead-in time in seconds. "
"It remains set to %f. Note: numbers should not be placed in quotes.",
str, config.audio_backend_silent_lead_in_time);
}
}

/* Get the desired length of the silent lead-in. */
if (config_lookup_float(config.cfg, "general.audio_backend_silent_lead_in_time", &dvalue)) {
if ((dvalue < 0.0) || (dvalue > 4)) {
die("Invalid audio_backend_silent_lead_in_time \"%f\". It "
"must be between 0.0 and 4.0 seconds. Omit setting to use the default value",
dvalue);
if (config.audio_backend_silent_lead_in_time_auto == 1)
warn("Invalid audio_backend_silent_lead_in_time \"%f\". It "
"must be between 0.0 and 4.0 seconds. Omit the setting to use the automatic value. "
"The setting remains at \"auto\".",
dvalue);
else
warn("Invalid audio_backend_silent_lead_in_time \"%f\". It "
"must be between 0.0 and 4.0 seconds. Omit the setting to use the automatic value. "
"It remains set to %f.",
dvalue, config.audio_backend_silent_lead_in_time);
} else {
config.audio_backend_silent_lead_in_time = dvalue;
config.audio_backend_silent_lead_in_time_auto = 0;
}
}
}
Expand Down
Loading

0 comments on commit bdc2dca

Please sign in to comment.