From c2083336a46a973259d03da149b3ead72074d77a Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Wed, 17 Jun 2026 17:08:50 +0200 Subject: [PATCH] impl-port: pass the zeroramp.duration to the mixer Pass the zeroramp.duration property from the node to the port and then to the mixer so that it can be configured. Add the zeroramp.duration to the docs. --- doc/dox/config/pipewire-client.conf.5.md | 1 + doc/dox/config/pipewire-props.7.md | 3 +++ doc/dox/config/pipewire-pulse.conf.5.md | 1 + src/daemon/client.conf.in | 3 ++- src/daemon/minimal.conf.in | 6 ++++-- src/daemon/pipewire-pulse.conf.in | 5 +++-- src/pipewire/impl-port.c | 8 +++++++- 7 files changed, 21 insertions(+), 6 deletions(-) diff --git a/doc/dox/config/pipewire-client.conf.5.md b/doc/dox/config/pipewire-client.conf.5.md index 321538a79..48775a0aa 100644 --- a/doc/dox/config/pipewire-client.conf.5.md +++ b/doc/dox/config/pipewire-client.conf.5.md @@ -87,6 +87,7 @@ stream.properties = { #dither.noise = 0 #dither.method = none # rectangular, triangular, triangular-hf, wannamaker3, shaped5 #debug.wav-path = "" + #zeroramp.duration = 0.005 } ``` diff --git a/doc/dox/config/pipewire-props.7.md b/doc/dox/config/pipewire-props.7.md index 3eb9e33f8..6968e0300 100644 --- a/doc/dox/config/pipewire-props.7.md +++ b/doc/dox/config/pipewire-props.7.md @@ -842,6 +842,9 @@ Dithering is only useful for conversion to a format with less than 24 bits and w disabled otherwise. \endparblock +@PAR@ node-prop zeroramp.duration = 0.005 +The duration of fade-in and fade-out of the signal in seconds on silence gaps. + ## Debug Parameters @IDX@ props @PAR@ node-prop debug.wav-path = "" diff --git a/doc/dox/config/pipewire-pulse.conf.5.md b/doc/dox/config/pipewire-pulse.conf.5.md index 9cc8d4c48..bdbd4469b 100644 --- a/doc/dox/config/pipewire-pulse.conf.5.md +++ b/doc/dox/config/pipewire-pulse.conf.5.md @@ -100,6 +100,7 @@ stream.properties = { #dither.noise = 0 #dither.method = none # rectangular, triangular, triangular-hf, wannamaker3, shaped5 #debug.wav-path = "" + #zeroramp.duration = 0.005 } ``` diff --git a/src/daemon/client.conf.in b/src/daemon/client.conf.in index 0ed0dd2d1..d4dbba285 100644 --- a/src/daemon/client.conf.in +++ b/src/daemon/client.conf.in @@ -111,7 +111,8 @@ stream.properties = { #channelmix.lfe-level = 0.5 #channelmix.stereo-widen = 0.0 #channelmix.hilbert-taps = 0 - #dither.noise = 0 + #dither.noise = 0 + #zeroramp.duration = 0.005 } stream.rules = [ diff --git a/src/daemon/minimal.conf.in b/src/daemon/minimal.conf.in index 2414da944..4a7120f08 100644 --- a/src/daemon/minimal.conf.in +++ b/src/daemon/minimal.conf.in @@ -361,7 +361,8 @@ context.objects = [ #channelmix.hilbert-taps = 0 #channelmix.disable = false #dither.noise = 0 - #node.param.Props = { + #zeroramp.duration = 0.005 + #node.param.Props = { # params = [ # audio.channels 6 # ] @@ -427,7 +428,8 @@ context.objects = [ #channelmix.hilbert-taps = 0 #channelmix.disable = false #dither.noise = 0 - #node.param.Props = { + #zeroramp.duration = 0.005 + #node.param.Props = { # params = [ # audio.format S16 # ] diff --git a/src/daemon/pipewire-pulse.conf.in b/src/daemon/pipewire-pulse.conf.in index f79c79a5f..ced8c4146 100644 --- a/src/daemon/pipewire-pulse.conf.in +++ b/src/daemon/pipewire-pulse.conf.in @@ -109,7 +109,8 @@ stream.properties = { #channelmix.surround-level = 0.707106781 #channelmix.lfe-level = 0.5 #channelmix.hilbert-taps = 0 - #dither.noise = 0 + #dither.noise = 0 + #zeroramp.duration = 0.005 } pulse.properties = { @@ -137,7 +138,7 @@ pulse.properties = { #pulse.min.quantum = 256/48000 # 5.3ms #pulse.idle.timeout = 0 # don't pause after underruns #pulse.max-streams = 64 # max streams per client - #pulse.max-sample-cache = 67108864 # max total sample cache size (64MB) + #pulse.max-sample-cache = 67108864 # max total sample cache size (64MB) #pulse.default.format = F32 #pulse.default.position = [ FL FR ] } diff --git a/src/pipewire/impl-port.c b/src/pipewire/impl-port.c index c4a654ab7..a65d6d2b3 100644 --- a/src/pipewire/impl-port.c +++ b/src/pipewire/impl-port.c @@ -543,6 +543,10 @@ static int check_properties(struct pw_impl_port *port) } else { port->passive_mode = passive_mode_from_string(str); } + if ((str = pw_properties_get(port->properties, "zeroramp.duration")) == NULL) { + if ((str = pw_properties_get(node->properties, "zeroramp.duration")) != NULL) + pw_properties_set(port->properties, "zeroramp.duration", str); + } if (media_class != NULL && (strstr(media_class, "Sink") != NULL || @@ -1093,7 +1097,7 @@ static int setup_mixer(struct pw_impl_port *port, const struct spa_pod *param) int res; const char *fallback_lib, *factory_name, *str; struct spa_handle *handle; - struct spa_dict_item items[4]; + struct spa_dict_item items[5]; char quantum_limit[16]; void *iface; struct pw_context *context = port->node->context; @@ -1153,6 +1157,8 @@ static int setup_mixer(struct pw_impl_port *port, const struct spa_pod *param) items[n_items++] = SPA_DICT_ITEM_INIT(PW_KEY_NODE_LOOP_NAME, port->node->data_loop->name); if ((str = pw_properties_get(port->properties, "control.ump")) != NULL) items[n_items++] = SPA_DICT_ITEM_INIT("control.ump", str); + if ((str = pw_properties_get(port->properties, "zeroramp.duration")) != NULL) + items[n_items++] = SPA_DICT_ITEM_INIT("zeroramp.duration", str); handle = pw_context_load_spa_handle(context, factory_name, &SPA_DICT_INIT(items, n_items));