Add the option to use a flat volume control profile.

This commit is contained in:
Mike Brady
2018-01-29 22:28:22 +00:00
parent c6aa6fd27d
commit f83b86ec23
6 changed files with 44 additions and 2 deletions
+1
View File
@@ -1,6 +1,7 @@
/*
* 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
+14
View File
@@ -664,6 +664,19 @@ uint32_t uatoi(const char *nptr) {
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.
@@ -725,6 +738,7 @@ double vol2attn(double vol, long max_db, long min_db) {
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;
}
+10
View File
@@ -61,6 +61,11 @@ enum playback_mode_type {
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,
@@ -157,6 +162,7 @@ typedef struct {
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
@@ -219,6 +225,10 @@ char *base64_enc(uint8_t *input, int length);
#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);
+6 -2
View File
@@ -2416,8 +2416,12 @@ void player_volume_without_notification(double airplay_volume, rtsp_conn_info *c
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) {
+3
View File
@@ -24,6 +24,9 @@ general =
// 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.
+10
View File
@@ -622,6 +622,16 @@ int parse_options(int argc, char **argv) {
"\"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 */