Skip to content

Commit

Permalink
Bring all the updates to 2.4.2
Browse files Browse the repository at this point in the history
  • Loading branch information
mikebrady committed Oct 17, 2015
2 parents cfde918 + 2a6071e commit 1ebcb80
Show file tree
Hide file tree
Showing 14 changed files with 624 additions and 318 deletions.
2 changes: 1 addition & 1 deletion LIBSOXR.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ git clone git:https://git.code.sf.net/p/soxr/code libsoxr
cd libsoxr
./go
```
Be patient! This takes a long time on a Raspberry Pi -- it looks like it gets stuck at 47%, but it will finish if you let it.
Be patient! This takes a long time on a Raspberry Pi -- it looks like it gets stuck around 40% or 50%, but it will finish if you let it.

Having compiled `libsoxr`, it must now must be installed:
```
Expand Down
107 changes: 80 additions & 27 deletions README.md

Large diffs are not rendered by default.

25 changes: 25 additions & 0 deletions RELEASENOTES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,28 @@
Version 2.4.2
----
This release has important enhancements, bug fixes and documentation updates. It also appears to bring compatiblity with Synology NAS devices.


**New Features**
* Source-specified Latencies. Shairport Sync now uses the latencies specified by the audio source. Background: the AirPlay protocol used by Shairport Sync allows the audio source to specify the exact delay or latency that should be applied to the audio stream. Until now, Shairport Sync ignored this information and used fixed preset latencies that were selected on the basis of the "User-Agent" setting. Using source-specified latencies means that Shairport Sync is able adapt automatically to different sources.
Using source-specified latencies is now automatic unless non-standard static latencies have been specified in the configuration file or command line. Using non-standard latencies is usually done to compensate for delays in the back end of the system. For example, if the audio amplifier being driven by Shairport Sync has an inherent delay of its own -- as happens with many home theatre and surround sound systems -- then some users have reduced the latencies used by Shairport Sync to compensate. This usage is discouraged -- the `audio_backend_latency_offset` in the appropriate backend stanza (e.g. in the "alsa" stanza) should be used for this. Static latency settings are now deprecated, and will be removed in a future version of Shairport Sync.
* Set Volume Range. This is a new setting that allows you to use just a portion of the full range of attenuation offered by a mixer. For example, if a mixer has a minimum volume of -80 dB and a maximum of +20 dB, you might wish to use only 60 dB of the 100 dB available. This might be because the sound becomes inaudible at the lowest setting and unbearably loud at the highest setting. It is for this reason that many domestic HiFi systems have a volume control range of only 60 to 80 dB.
Another possible reason to use this setting might be because the range specified by the mixer does not match the actual capabilities of the device. For example, the Raspberry Pi's DAC that feeds the built-in audio jack claims a range of 106 dB but has a useful range of only about 35dB. The new `volume_range_db` setting in the `general` stanza allows you to specify the maximum range from highest to lowest. The range suggested for the Raspberry Pi's built-in audio DAC, which feeds the headphone jack, is 35. Using it in this case gives the volume control a much more useful range of settings.

**Bug fixes**
* Sometimes, especially when using Shairport Sync as a system output, it would not play the audio stream. This was caused by an improperly initialised variable. Fixed. Synology NAS devices now seem to be working with Shairport Sync.
* Fix in the `shairport.c`: the USE_CUSTOM_LOCAL_STATE_DIR macro was still being used when it should have been USE_CUSTOM_PID_DIR.
* Fix a crashing bug -- if metadata was enabled but a pipename was not supplied, boom.

**Other Changes**
* Initial timing accuracy improved. The estimate of when to play the starting frame of the audio sequence has improved significantly. This leads to fewer corrections being needed at the start.
* Volume ratios expressed in decibels are now consistently denominated in voltage decibels rather than power decibels. The rationale is that the levels refer to voltage levels, and power is proportional to the square of voltage.
Thus a ratio of levels of 65535 to 1 is 96.3 dB rather than the 48.15 dB used before.
* The latency figure returned to the source as part of the response to an rtsp request packet is 11,025, which may (?) be meant to indicate the minimum latency the device is capable of.
* An experimental handler for a GET_PARAMETER rtsp request has been added. It does nothing except log the occurence.
* The RTSP request dispatcher now logs an event whenever an unrecognised rtsp has been made.


Version 2.4.1
----
This release has three small bug fixes and some small documentation updates.
Expand Down
65 changes: 54 additions & 11 deletions audio_alsa.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include <stdio.h>
#include <unistd.h>
#include <memory.h>
#include <math.h>
#include <pthread.h>
#include <alsa/asoundlib.h>
#include "common.h"
Expand All @@ -43,9 +44,9 @@ static void stop(void);
static void flush(void);
static uint32_t delay(void);
static void volume(double vol);
static void linear_volume(double vol);
static void parameters(audio_parameters *info);
static int has_mute = 0;
static int has_db_vol = 0;
static double set_volume;

audio_output audio_alsa = {
Expand Down Expand Up @@ -183,6 +184,8 @@ static int init(int argc, char **argv) {

if (optind < argc)
die("Invalid audio argument: %s", argv[optind]);

debug(1,"Output device name is \"%s\".",alsa_out_dev);

if (!hardware_mixer)
return 0;
Expand All @@ -191,13 +194,14 @@ static int init(int argc, char **argv) {
alsa_mix_dev = alsa_out_dev;

int ret = 0;

snd_mixer_selem_id_alloca(&alsa_mix_sid);
snd_mixer_selem_id_set_index(alsa_mix_sid, alsa_mix_index);
snd_mixer_selem_id_set_name(alsa_mix_sid, alsa_mix_ctrl);

if ((snd_mixer_open(&alsa_mix_handle, 0)) < 0)
die("Failed to open mixer");
debug(1,"Mixer device name is \"%s\".",alsa_mix_dev);
if ((snd_mixer_attach(alsa_mix_handle, alsa_mix_dev)) < 0)
die("Failed to attach mixer");
if ((snd_mixer_selem_register(alsa_mix_handle, NULL, NULL)) < 0)
Expand All @@ -206,28 +210,52 @@ static int init(int argc, char **argv) {
ret = snd_mixer_load(alsa_mix_handle);
if (ret < 0)
die("Failed to load mixer element");
alsa_mix_elem = snd_mixer_find_selem(alsa_mix_handle, alsa_mix_sid);

debug(1,"Mixer Control name is \"%s\".",alsa_mix_ctrl);

alsa_mix_elem = snd_mixer_find_selem(alsa_mix_handle, alsa_mix_sid);
if (!alsa_mix_elem)
die("Failed to find mixer element");


if (snd_mixer_selem_get_playback_volume_range(alsa_mix_elem, &alsa_mix_minv, &alsa_mix_maxv) < 0)
debug(1, "Can't read mixer's [linear] min and max volumes.");
else {
if ((snd_mixer_selem_ask_playback_vol_dB(alsa_mix_elem, alsa_mix_minv, &alsa_mix_mindb) == 0) &&
(snd_mixer_selem_ask_playback_vol_dB(alsa_mix_elem, alsa_mix_maxv, &alsa_mix_maxdb) == 0)) {
has_db_vol = 1;
if (snd_mixer_selem_get_playback_dB_range (alsa_mix_elem, &alsa_mix_mindb, &alsa_mix_maxdb) == 0) {

audio_alsa.volume = &volume; // insert the volume function now we know it can do dB stuff
audio_alsa.parameters = &parameters; // likewise the parameters stuff
if (alsa_mix_mindb == -9999999) {
// trying to say that the lowest vol is mute, maybe? Raspberry Pi does this
if (alsa_mix_mindb == SND_CTL_TLV_DB_GAIN_MUTE) {
// Raspberry Pi does this
debug(1, "Lowest dB value is a mute.");
if (snd_mixer_selem_ask_playback_vol_dB(alsa_mix_elem, alsa_mix_minv + 1,
&alsa_mix_mindb) == 0)
debug(1, "Can't get dB value corresponding to a \"volume\" of 1.");
}
debug(1, "Hardware mixer has dB volume from %f to %f.", (1.0 * alsa_mix_mindb) / 100.0,
(1.0 * alsa_mix_maxdb) / 100.0);
if (config.volume_range_db) {
long suggested_alsa_min_db = alsa_mix_maxdb - (long)trunc(config.volume_range_db*100);
if (suggested_alsa_min_db > alsa_mix_mindb)
alsa_mix_mindb = suggested_alsa_min_db;
else
inform("The volume_range_db setting, %f is greater than the native range of the mixer %f, so it is ignored.",config.volume_range_db,(alsa_mix_maxdb-alsa_mix_mindb)/100.0);
}
} else {
inform("note: the hardware mixer specified -- \"%s\" -- does not have dB volume, so it can not be used for volume control.",alsa_mix_ctrl);
}
// use the linear scale and do the db conversion ourselves
debug(1, "note: the hardware mixer specified -- \"%s\" -- does not have a dB volume scale, so it can't be used.",alsa_mix_ctrl);
/*
debug(1, "Min and max volumes are %d and %d.",alsa_mix_minv,alsa_mix_maxv);
alsa_mix_maxdb = 0;
if ((alsa_mix_maxv!=0) && (alsa_mix_minv!=0))
alsa_mix_mindb = -20*100*(log10(alsa_mix_maxv*1.0)-log10(alsa_mix_minv*1.0));
else if (alsa_mix_maxv!=0)
alsa_mix_mindb = -20*100*log10(alsa_mix_maxv*1.0);
audio_alsa.volume = &linear_volume; // insert the linear volume function
audio_alsa.parameters = &parameters; // likewise the parameters stuff
debug(1,"Max and min dB calculated are %d and %d.",alsa_mix_maxdb,alsa_mix_mindb);
*/
}
}
if (snd_mixer_selem_has_playback_switch(alsa_mix_elem)) {
has_mute = 1;
Expand Down Expand Up @@ -320,7 +348,7 @@ static void play(short buf[], int samples) {
if (alsa_handle == NULL) {
ret = open_alsa_device();
if ((ret == 0) && (audio_alsa.volume))
volume(set_volume);
audio_alsa.volume(set_volume);
}
if (ret == 0) {
pthread_mutex_lock(&alsa_mutex);
Expand Down Expand Up @@ -390,6 +418,7 @@ static void parameters(audio_parameters *info) {
}

static void volume(double vol) {
// debug(1,"Volume called %f.",vol);
set_volume = vol;
double vol_setting = vol2attn(vol, alsa_mix_maxdb, alsa_mix_mindb);
// debug(1,"Setting volume db to %f, for volume input of %f.",vol_setting/100,vol);
Expand All @@ -398,3 +427,17 @@ static void volume(double vol) {
if (has_mute)
snd_mixer_selem_set_playback_switch_all(alsa_mix_elem, (vol != -144.0));
}

static void linear_volume(double vol) {
set_volume = vol;
double vol_setting = vol2attn(vol, 0, alsa_mix_mindb)/2000;
// debug(1,"Adjusted volume is %f.",vol_setting);
double linear_volume = pow(10, vol_setting);
// debug(1,"Linear volume is %f.",linear_volume);
long int_vol = alsa_mix_minv + (alsa_mix_maxv - alsa_mix_minv) * linear_volume;
// debug(1,"Setting volume to %ld, for volume input of %f.",int_vol,vol);
if (snd_mixer_selem_set_playback_volume_all(alsa_mix_elem, int_vol) != 0)
die("Failed to set playback volume");
if (has_mute)
snd_mixer_selem_set_playback_switch_all(alsa_mix_elem, (vol != -144.0));
}
17 changes: 9 additions & 8 deletions common.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,13 @@ typedef struct {
char *mdns_name;
mdns_backend *mdns;
int buffer_start_fill;
uint32_t latency;
uint32_t userSuppliedLatency; // overrides all other latencies -- use with caution
uint32_t iTunesLatency; // supplied with --iTunesLatency option
uint32_t AirPlayLatency; // supplied with --AirPlayLatency option
uint32_t ForkedDaapdLatency; // supplied with --ForkedDaapdLatency option
int32_t latency;
int32_t userSuppliedLatency; // overrides all other latencies -- use with caution
int32_t iTunesLatency; // supplied with --iTunesLatency option
int32_t AirPlayLatency; // supplied with --AirPlayLatency option
int32_t ForkedDaapdLatency; // supplied with --ForkedDaapdLatency option
int daemonise;
int statistics_requested;
int statistics_requested,use_negotiated_latencies;
char *cmd_start, *cmd_stop;
int cmd_blocking;
int tolerance; // allow this much drift before attempting to correct it
Expand All @@ -78,9 +78,10 @@ typedef struct {
char *logfile;
char *errfile;
char *configfile;
uint32_t audio_backend_buffer_desired_length; // this will be the desired number of frames in the
int32_t audio_backend_buffer_desired_length; // this will be the desired number of frames in the
// audio backend buffer -- the DAC buffer for ALSA
uint32_t audio_backend_latency_offset; // this will be the offset to compensate for any fixed latency
int32_t audio_backend_latency_offset; // this will be the offset to compensate for any fixed latency
uint32_t volume_range_db; // the range, in dB, from max dB to min dB. Zero means use the mixer's native range.
// there might be in the audio
} shairport_cfg;

Expand Down
2 changes: 1 addition & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# Process this file with autoconf to produce a configure script.

AC_PREREQ([2.50])
AC_INIT([shairport-sync], [2.4.1], [[email protected]])
AC_INIT([shairport-sync], [2.4.2], [[email protected]])
AM_INIT_AUTOMAKE
AC_CONFIG_SRCDIR([shairport.c])
AC_CONFIG_HEADERS([config.h])
Expand Down
Loading

0 comments on commit 1ebcb80

Please sign in to comment.