diff --git a/README.html b/README.html
index 515febb..fb7ddaa 100644
--- a/README.html
+++ b/README.html
@@ -9,13 +9,13 @@ href="https://github.com/FDH2/UxPlay">https://github.com/FDH2/UxPlay
(where ALL user issues should be posted, and latest versions can be
found).
-- NEW in v1.68: improved support for one-time
-Apple-style “pin” codes introduced in 1.67: a register of pin-registered
-clients is now optionally maintained to check returning clients; a
-simpler method for generating a persistent public key (based on the MAC
-address, which now can be set in the UxPlay startup file) is now the
-default. (The pem-file method introduced in 1.67 is still available with
-the ’-key” option.)
+- NEW in v1.68: Volume-control improvements, plus
+improved support for Apple-style one-time “pin” codes introduced in
+1.67: a register of pin-registered clients can now optionally be
+maintained to check returning clients; a simpler method for generating a
+persistent public key (based on the MAC address, which can be set in the
+UxPlay startup file) is now the default. (The OpenSSL “pem-file” method
+introduced in 1.67 is still available with the ’-key” option.)
Highlights:
@@ -517,6 +517,11 @@ on the client to match audio on the server, so leads to a slight delay
before a pause or track-change initiated on the client takes effect on
the audio played by the server.
+AirPlay volume-control attenuates volume (gain) by up to -30dB: the
+range -30dB:0dB can be rescaled from Low:0 (Low <
+0), or Low:High, using the option
+“-db _Low_” or “-db _Low_:_High_” (Rescaling
+is linear in decibels).
The -vsync and -async options also allow an optional positive (or
negative) audio-delay adjustment in milliseconds for
fine-tuning : -vsync 20.5 delays audio relative to video by
@@ -941,6 +946,17 @@ have any effect.
Audio-only mode, but this option may be useful as a command-line option
to switch off a -async option set in a “uxplayrc”
configuration file.
+-db low[:high] Rescales the
+AirPlay volume-control attenuation (gain) from -30dB:0dB to
+low:0dB or low:high. The lower limit
+low must be negative (attenuation); the upper limit
+high can be either sign. (GStreamer restricts
+volume-augmentation by high so that it cannot exceed +20dB).
+The rescaling is “flat”, so that for -db -50:10, a change in Airplay
+attenuation by -7dB is translated to a -7 x (60/30) = -14dB attenuation,
+and the maximum volume (AirPlay 0dB) is a 10dB augmentation, and Airplay
+-30dB would become -50dB. Note that the minimum AirPlay value (-30dB
+exactly) is translated to “mute”.
-s wxh (e.g. -s 1920x1080 , which is the default )
sets the display resolution (width and height, in pixels). (This may be
a request made to the AirPlay client, and perhaps will not be the final
@@ -1494,11 +1510,13 @@ an AppleTV6,2 with sourceVersion 380.20.1 (an AppleTV 4K 1st gen,
introduced 2017, running tvOS 12.2.1), so it does not seem to matter
what version UxPlay claims to be.
Changelog
-1.68 2023-12-25 Introduced a simpler (default) method for generating
+
1.68 2023-12-26 Introduced a simpler (default) method for generating
a persistent public key from the server MAC address (which can now be
set with the -m option). (The previous pem-file method is still
available with -key option). New option -reg to maintain a register of
-pin-authenticated clients.
+pin-authenticated clients. Corrected volume-control: now inteprets
+AirPlay volume range -30dB:0dB as (gain/amplitude) decibel attenuation,
+with new option -db low[:high] for “flat” rescaling of the dB range.
1.67 2023-11-30 Add support for Apple-style one-time pin
authentication of clients with option “-pin”: (uses SRP6a authentication
protocol and public key persistence). Detection with error message of
diff --git a/README.md b/README.md
index eb97463..8fadec5 100644
--- a/README.md
+++ b/README.md
@@ -2,10 +2,10 @@
### Now developed at the GitHub site [https://github.com/FDH2/UxPlay](https://github.com/FDH2/UxPlay) (where ALL user issues should be posted, and latest versions can be found).
- * _**NEW in v1.68**: improved support for one-time Apple-style "pin" codes introduced in 1.67: a register of pin-registered clients is
- now optionally maintained to check returning clients; a simpler method for generating a persistent public key (based on
- the MAC address, which now can be set in the UxPlay startup file) is now the default. (The pem-file method introduced in 1.67 is
- still available with the '-key" option.)_
+ * _**NEW in v1.68**: Volume-control improvements, plus improved support for Apple-style one-time "pin" codes introduced in 1.67: a
+ register of pin-registered clients can now optionally be maintained to check returning clients; a simpler method for generating
+ a persistent public key (based on the MAC address, which can be set in the UxPlay startup file) is now the default. (The OpenSSL
+ "pem-file" method introduced in 1.67 is still available with the '-key" option.)_
## Highlights:
@@ -415,6 +415,9 @@ if you want to follow the Apple Music lyrics on the client while listening to su
delays the video on the client to match audio on the server, so leads to
a slight delay before a pause or track-change initiated on the client takes effect on the audio played by the server.
+AirPlay volume-control attenuates volume (gain) by up to -30dB: the range -30dB:0dB can be rescaled from _Low_:0 (_Low_ < 0), or _Low_:_High_, using the
+option "`-db _Low_`" or "``-db _Low_:_High_``" (Rescaling is linear in decibels).
+
The -vsync and -async options
also allow an optional positive (or negative) audio-delay adjustment in _milliseconds_ for fine-tuning : `-vsync 20.5`
delays audio relative to video by 0.0205 secs; a negative value advances it.)
@@ -741,6 +744,13 @@ using UxPlay as a second monitor for a mac computer, or monitoring a webcam; wit
**-async no**. This is the still the default behavior in Audio-only mode, but this option may be useful as a command-line option to switch off a
`-async` option set in a "uxplayrc" configuration file.
+**-db _low_[:_high_]** Rescales the AirPlay volume-control attenuation (gain) from -30dB:0dB to _low_:0dB or _low_:_high_. The lower limit _low_
+ must be negative (attenuation); the upper limit _high_ can be either sign. (GStreamer restricts volume-augmentation by _high_ so that it
+ cannot exceed +20dB).
+ The rescaling is "flat", so that for -db -50:10, a change in Airplay attenuation by -7dB is translated to a -7 x (60/30) = -14dB attenuation,
+ and the maximum volume (AirPlay 0dB) is a 10dB augmentation, and Airplay -30dB would become -50dB. Note that the minimum AirPlay value (-30dB exactly)
+ is translated to "mute".
+
**-s wxh** (e.g. -s 1920x1080 , which is the default ) sets the display resolution (width and height,
in pixels). (This may be a
request made to the AirPlay client, and perhaps will not
@@ -1178,10 +1188,11 @@ tvOS 12.2.1), so it does not seem to matter what version UxPlay claims to be.
# Changelog
-1.68 2023-12-25 Introduced a simpler (default) method for generating a persistent public key from the server MAC
- address (which can now be set with the -m option).
- (The previous pem-file method is still available with -key option).
- New option -reg to maintain a register of pin-authenticated clients.
+1.68 2023-12-26 Introduced a simpler (default) method for generating a persistent public key from the server MAC
+ address (which can now be set with the -m option). (The previous pem-file method is still available
+ with -key option). New option -reg to maintain a register of pin-authenticated clients. Corrected
+ volume-control: now inteprets AirPlay volume range -30dB:0dB as (gain/amplitude) decibel attenuation,
+ with new option -db low[:high] for "flat" rescaling of the dB range.
1.67 2023-11-30 Add support for Apple-style one-time pin authentication of clients with option "-pin":
(uses SRP6a authentication protocol and public key persistence). Detection with error message
diff --git a/README.txt b/README.txt
index 664bd5c..b2e488a 100644
--- a/README.txt
+++ b/README.txt
@@ -2,13 +2,14 @@
### Now developed at the GitHub site (where ALL user issues should be posted, and latest versions can be found).
-- ***NEW in v1.68**: improved support for one-time Apple-style "pin"
- codes introduced in 1.67: a register of pin-registered clients is
- now optionally maintained to check returning clients; a simpler
- method for generating a persistent public key (based on the MAC
- address, which now can be set in the UxPlay startup file) is now the
- default. (The pem-file method introduced in 1.67 is still available
- with the '-key" option.)*
+- ***NEW in v1.68**: Volume-control improvements, plus improved
+ support for Apple-style one-time "pin" codes introduced in 1.67: a
+ register of pin-registered clients can now optionally be maintained
+ to check returning clients; a simpler method for generating a
+ persistent public key (based on the MAC address, which can be set in
+ the UxPlay startup file) is now the default. (The OpenSSL "pem-file"
+ method introduced in 1.67 is still available with the '-key"
+ option.)*
## Highlights:
@@ -509,6 +510,11 @@ helped to prevent this previously when timestamps were not being used.)
slight delay before a pause or track-change initiated on the client
takes effect on the audio played by the server.
+AirPlay volume-control attenuates volume (gain) by up to -30dB: the
+range -30dB:0dB can be rescaled from *Low*:0 (*Low* \< 0), or
+*Low*:*High*, using the option "`-db _Low_`" or "`-db _Low_:_High_`"
+(Rescaling is linear in decibels).
+
The -vsync and -async options also allow an optional positive (or
negative) audio-delay adjustment in *milliseconds* for fine-tuning :
`-vsync 20.5` delays audio relative to video by 0.0205 secs; a negative
@@ -944,6 +950,16 @@ changing this does not seem to have any effect*.
mode, but this option may be useful as a command-line option to switch
off a `-async` option set in a "uxplayrc" configuration file.
+**-db *low*\[:*high*\]** Rescales the AirPlay volume-control attenuation
+(gain) from -30dB:0dB to *low*:0dB or *low*:*high*. The lower limit
+*low* must be negative (attenuation); the upper limit *high* can be
+either sign. (GStreamer restricts volume-augmentation by *high* so that
+it cannot exceed +20dB). The rescaling is "flat", so that for -db
+-50:10, a change in Airplay attenuation by -7dB is translated to a -7 x
+(60/30) = -14dB attenuation, and the maximum volume (AirPlay 0dB) is a
+10dB augmentation, and Airplay -30dB would become -50dB. Note that the
+minimum AirPlay value (-30dB exactly) is translated to "mute".
+
**-s wxh** (e.g. -s 1920x1080 , which is the default ) sets the display
resolution (width and height, in pixels). (This may be a request made to
the AirPlay client, and perhaps will not be the final resolution you
@@ -1531,11 +1547,13 @@ what version UxPlay claims to be.
# Changelog
-1.68 2023-12-25 Introduced a simpler (default) method for generating a
+1.68 2023-12-26 Introduced a simpler (default) method for generating a
persistent public key from the server MAC address (which can now be set
with the -m option). (The previous pem-file method is still available
with -key option). New option -reg to maintain a register of
-pin-authenticated clients.
+pin-authenticated clients. Corrected volume-control: now inteprets
+AirPlay volume range -30dB:0dB as (gain/amplitude) decibel attenuation,
+with new option -db low\[:high\] for "flat" rescaling of the dB range.
1.67 2023-11-30 Add support for Apple-style one-time pin authentication
of clients with option "-pin": (uses SRP6a authentication protocol and
diff --git a/renderers/audio_renderer.h b/renderers/audio_renderer.h
index b405dfe..0786283 100644
--- a/renderers/audio_renderer.h
+++ b/renderers/audio_renderer.h
@@ -33,7 +33,8 @@ extern "C" {
#include "../lib/logger.h"
bool gstreamer_init();
-void audio_renderer_init(logger_t *logger, const char* audiosink, const bool *audio_sync, const bool *video_sync);
+void audio_renderer_init(logger_t *logger, const char* audiosink, const bool *audio_sync, const bool *video_sync,
+ float db_low, float db_high);
void audio_renderer_start(unsigned char* compression_type);
void audio_renderer_stop();
void audio_renderer_render_buffer(unsigned char* data, int *data_len, unsigned short *seqnum, uint64_t *ntp_time);
diff --git a/renderers/audio_renderer_gstreamer.c b/renderers/audio_renderer_gstreamer.c
index 2b131e1..dd8f658 100644
--- a/renderers/audio_renderer_gstreamer.c
+++ b/renderers/audio_renderer_gstreamer.c
@@ -40,6 +40,7 @@ static gboolean render_audio = FALSE;
static gboolean async = FALSE;
static gboolean vsync = FALSE;
static gboolean sync = FALSE;
+static float vol_low, vol_high;
typedef struct audio_renderer_s {
GstElement *appsrc;
@@ -125,14 +126,17 @@ bool gstreamer_init(){
return (bool) check_plugins ();
}
-void audio_renderer_init(logger_t *render_logger, const char* audiosink, const bool* audio_sync, const bool* video_sync) {
+void audio_renderer_init(logger_t *render_logger, const char* audiosink, const bool* audio_sync,
+ const bool* video_sync, const float db_low, const float db_high) {
GError *error = NULL;
GstCaps *caps = NULL;
GstClock *clock = gst_system_clock_obtain();
g_object_set(clock, "clock-type", GST_CLOCK_TYPE_REALTIME, NULL);
logger = render_logger;
-
+ vol_low = db_low;
+ vol_high = db_high;
+
aac = check_plugin_feature (avdec_aac);
alac = check_plugin_feature (avdec_alac);
@@ -356,11 +360,15 @@ void audio_renderer_render_buffer(unsigned char* data, int *data_len, unsigned s
}
void audio_renderer_set_volume(float volume) {
- float avol;
- if (fabs(volume) < 28) {
- avol=floorf(((28-fabs(volume))/28)*10)/10;
- g_object_set(renderer->volume, "volume", avol, NULL);
- }
+ /* scale volume from range -30dB:0dB to vol_low: vol_high */
+ double vol = (double) vol_low;
+ if ((volume <= 0) && (volume > -30)) {
+ vol = (double) (vol_low + ((vol_high - vol_low) * (30.0 + volume) / 30));
+ }
+ gdouble avol = (gdouble) pow(10, vol/20);
+ if (avol > 10) avol = 10;
+ if (volume <= -30) avol = 0;
+ g_object_set(renderer->volume, "volume", avol, NULL);
}
void audio_renderer_flush() {
diff --git a/uxplay.1 b/uxplay.1
index 99f3a79..5c817e7 100644
--- a/uxplay.1
+++ b/uxplay.1
@@ -31,6 +31,11 @@ UxPlay 1.68: An open\-source AirPlay mirroring (+ audio streaming) server:
.TP
\fB\-async\fR no Switch off audio/(client)video timestamp synchronization.
.TP
+\fB\-db\fI l[:h]\fR Set minumum volume attenuation to l dB (decibels, negative);
+.IP
+ optional: set maximum to h dB (+ or -); default -30.0:0.0
+.PP
+.TP
\fB\-s\fR wxh[@r]Set display resolution [refresh_rate] default 1920x1080[@60]
.TP
\fB\-o\fR Set display "overscanned" mode on (not usually needed)
diff --git a/uxplay.cpp b/uxplay.cpp
index 623d220..78111b4 100644
--- a/uxplay.cpp
+++ b/uxplay.cpp
@@ -136,6 +136,8 @@ static std::string dacpfile = "";
static bool registration_list = false;
static std::string pairing_register = "";
static std::vector registered_keys;
+static float db_low = -30;
+static float db_high = 0;
/* logging */
@@ -574,6 +576,8 @@ static void print_info (char *name) {
printf("-vsync no Switch off audio/(server)video timestamp synchronization \n");
printf("-async [x]Audio-Only mode: sync audio to client video (default: no)\n");
printf("-async no Switch off audio/(client)video timestamp synchronization\n");
+ printf("-db l[:h] Set minimum volume attenuation to l dB (decibels, negative);\n");
+ printf(" optional: set maximum to h dB (+ or -); default -30.0:0.0 dB\n");
printf("-s wxh[@r]Set display resolution [refresh_rate] default 1920x1080[@60]\n");
printf("-o Set display \"overscanned\" mode on (not usually needed)\n");
printf("-fs Full-screen (only works with X11, Wayland and VAAPI)\n");
@@ -1090,6 +1094,32 @@ static void parse_arguments (int argc, char *argv[]) {
dacpfile.append(get_homedir());
dacpfile.append("/.uxplay.dacp");
}
+ } else if (arg == "-db") {
+ bool db_bad = true;
+ float db1, db2;
+ char *start = NULL;
+ if ( i < argc -1) {
+ char *end1, *end2;
+ start = argv[i+1];
+ db1 = strtof(start, &end1);
+ if (end1 > start && *end1 == ':') {
+ db2 = strtof(++end1, &end2);
+ if ( *end2 == '\0' && end2 > end1 && db1 < 0 && db1 < db2) {
+ db_bad = false;
+ }
+ } else if (*end1 =='\0' && end1 > start && db1 < 0 ) {
+ db_bad = false;
+ db2 = 0;
+ }
+ }
+ if (db_bad) {
+ fprintf(stderr, "%s %s requires argument \"low\" or \"low:high\" where low < 0 and high > low are decibel gain values\n", argv[i], start);
+ exit(1);
+ }
+ i++;
+ db_low = db1;
+ db_high = db2;
+ printf("db range %f:%f\n", db_low, db_high);
} else {
fprintf(stderr, "unknown option %s, stopping (for help use option \"-h\")\n",argv[i]);
exit(1);
@@ -1929,7 +1959,7 @@ int main (int argc, char *argv[]) {
logger_set_level(render_logger, log_level);
if (use_audio) {
- audio_renderer_init(render_logger, audiosink.c_str(), &audio_sync, &video_sync);
+ audio_renderer_init(render_logger, audiosink.c_str(), &audio_sync, &video_sync, db_low, db_high);
} else {
LOGI("audio_disabled");
}