/*
* libalsa output driver. This file is part of Shairport.
* Copyright (c) Muffinman, Skaman 2013
+ * Copyright (c) Mike Brady 2014 -- 2018
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
return r;
}
+
+double flat_vol2attn(double vol, long max_db, long min_db) {
+ double vol_setting = min_db;
+
+ if ((vol <= 0.0) && (vol >= -30.0)) {
+ vol_setting = ((max_db - min_db)*(30.0+vol)/30)+min_db;
+ debug(2,"Linear Volume Setting: %f in range %ld to %ld.",vol_setting,min_db,max_db);
+ } else if (vol != -144.0) {
+ debug(1, "Linear volume request value %f is out of range: should be from 0.0 to -30.0 or -144.0.",
+ vol);
+ }
+ return vol_setting;
+}
// Given a volume (0 to -30) and high and low attenuations available in the mixer in dB, return an
// attenuation depending on the volume and the function's transfer function
// See http://tangentsoft.net/audio/atten.html for data on good attenuators.
vol_setting = min_db; // for safety, return the lowest setting...
}
// debug(1,"returning an attenuation of %f.",vol_setting);
+ debug(2,"Standard profile Volume Setting for Airplay vol %f: %f in range %ld to %ld.",vol,vol_setting,min_db,max_db);
return vol_setting;
}
ST_right_only,
} playback_mode_type;
+enum volume_control_profile_type {
+ VCP_standard = 0,
+ VCP_flat,
+} volume_control_profile_type;
+
enum decoders_supported_type {
decoder_hammerton = 0,
decoder_apple_alac,
uint32_t volume_range_db; // the range, in dB, from max dB to min dB. Zero means use the mixer's
// native range.
enum sps_format_t output_format;
+ enum volume_control_profile_type volume_control_profile;
int output_rate;
#ifdef CONFIG_CONVOLUTION
#define RSA_MODE_KEY (1)
uint8_t *rsa_apply(uint8_t *input, int inlen, int *outlen, int mode);
+// given a volume (0 to -30) and high and low attenuations in dB*100 (e.g. 0 to -6000 for 0 to -60
+// dB), return an attenuation depending on a linear interpolation along along the range
+double flat_vol2attn(double vol, long max_db, long min_db);
+
// given a volume (0 to -30) and high and low attenuations in dB*100 (e.g. 0 to -6000 for 0 to -60
// dB), return an attenuation depending on the transfer function
double vol2attn(double vol, long max_db, long min_db);
config.output->mute(0); // unmute mute if it's there
if (config.ignore_volume_control == 1)
scaled_attenuation = max_db;
- else
- scaled_attenuation = vol2attn(airplay_volume, max_db, min_db);
+ else if (config.volume_control_profile == VCP_standard)
+ scaled_attenuation = vol2attn(airplay_volume, max_db, min_db);
+ else if (config.volume_control_profile == VCP_flat)
+ scaled_attenuation = flat_vol2attn(airplay_volume, max_db, min_db);
+ else debug(1,"Unrecognised volume control profile");
+
if (hw_range_db) {
// if there is a hardware mixer
if (scaled_attenuation <= hw_max_db) {
// ignore_volume_control = "no"; // set this to "yes" if you want the volume to be at 100% no matter what the source's volume control is set to.
// volume_range_db = 60 ; // use this advanced setting to set the range, in dB, you want between the maximum volume and the minimum volume. Range is 30 to 150 dB. Leave it commented out to use mixer's native range.
// volume_max_db = 0.0 ; // use this advanced setting, which must have a decimal point in it, to set the maximum volume, in dB, you wish to use.
+// volume_control_profile = "standard" ; // use this advanced setting to specify how the airplay volume is transferred to the mixer volume.
+// "standard" makes the volume change more quickly than logarithmically at lower values and slower at higher values.
+// "flat" makes the volume change logarithmically at all values.
// The setting is for the hardware mixer, if chosen, or the software mixer otherwise. The value must be in the mixer's range (0.0 to -96.2 for the software mixer).
// Leave it commented out to use mixer's maximum volume.
// run_this_when_volume_is_set = "/full/path/to/application/and/args"; // Run the specified application whenever the volume control is set or changed.
"\"reverse stereo\", \"both left\", \"both right\"");
}
+ /* Get the volume control profile setting -- "standard" or "flat" */
+ if (config_lookup_string(config.cfg, "general.volume_control_profile", &str)) {
+ if (strcasecmp(str, "standard") == 0)
+ config.volume_control_profile = VCP_standard;
+ else if (strcasecmp(str, "flat") == 0)
+ config.volume_control_profile = VCP_flat;
+ else
+ die("Invalid volume_control_profile choice \"%s\". It should be \"standard\" (default) or \"flat\"");
+ }
+
/* Get the interface to listen on, if specified Default is all interfaces */
/* we keep the interface name and the index */