You are not logged in.

#1 2024-02-25 17:41:09

wolfsilver00
Member
Registered: 2024-02-25
Posts: 6

PipeWire ALSA [java] creating multiple streams per each sound

Hello! I need some help with an issue I can´t seem to be able to work around, symptoms are as follow:


Using an app called RuneLite, which has add-on support. There is one that gives text to speech notifications, (code here: https://github.com/JesseVii/TTS ), when the notification triggers (it does not use camberra, it comes from java itself) a new playback stream is created, the notification is heard and then it just stays there, after hundreds of notifications this of course becomes a problem, but also quite beautiful to look at ( https://imgur.com/a/kp8Ii4c )

The devices created are as follows:

[wolf@archlinux TTS]$ wpctl inspect 137
id 137, type PipeWire:Interface:Node
    adapt.follower.spa-node = ""
  * application.name = "PipeWire ALSA [java]"
    audio.adapt.follower = ""
  * client.id = "141"
    clock.quantum-limit = "8192"
  * factory.id = "8"
    factory.mode = "split"
    library.name = "audioconvert/libspa-audioconvert"
  * media.category = "Playback"
  * media.class = "Stream/Output/Audio"
    media.name = "ALSA Playback"
  * media.type = "Audio"
    node.autoconnect = "true"
  * node.description = "ALSA Playback [java]"
    node.latency = "438/22050"
  * node.name = "alsa_playback.java"
    node.rate = "1/22050"
    node.want-driver = "true"
    object.register = "false"
  * object.serial = "1370"
    stream.is-live = "true"

with only their object.serial and client.id changing. I've tried disconnecting them to wait for the timeout, but they remain there until I close the application.

best case scenario, there would be a way to make it so that every notification goes to only one stream, ive looked into wireplumber lua scripts but I've yet to find a way to do this, btw, my wireplumber is vanilla and I've not created any rules, in fact, all of my audio setup is just "as is" out of the box with no Aur packages.

Going into further detail on the device created, I have this:

Client #2421
        Driver: PipeWire
        Owner Module: 2
        Properties:
                pipewire.protocol = "protocol-native"
                pipewire.sec.socket = "pipewire-0"
                pipewire.sec.pid = "14241"
                pipewire.sec.uid = "1000"
                pipewire.sec.gid = "1000"
                pipewire.sec.label = "hex:607bd753e463000010e0a952e4630000e8ac4052e463000090aa4052e4630000e0c1373e677a0000033b2f3e677a00003000003d677a000088ad4052e4630000000000000000000000000000000000000000000000000000000000000000000070720a540200000000b8529c0dd68f3780e0a952e463000088ad4052e463000010e0a952e463000010e0a952e46300000100000000000000f08b92fefc7f0000875b853d677a00000f592d3e677a00003000003d677a000088ad4052e46300000000000000000000000000000000000000000000000000000000000000000000000000000000000000b8529c0dd68f37bc50853d677a0000220000000000000010e0a952e463000088d11b53e46300000100000000000000f08b92fefc7f0000875b853d677a00003e662d3e677a0000308c92fefc7f0000208c92fefc7f000088ffffffffffffff42ce833d677a00007051a852e46300000c000000000000000000000000000000a68c853d677a0000bc50853d677a000006de833d677a000090514b520e0000006f150f3e677a0000c86c0a54e463000042ce833d677a00007051a852e46300000c000000000000000000000000000000a68c853d677a0000bc50853d677a000006de833d677a0000000000000e0000001301000000000000040000000400000038000000000000003000000030000000b08b92fefc7f000020000000300000000000000000000000b08a92fefc7f000000b8529c0dd68f371301000000000000a030a852e46300000400000004000000fa16004000000000e87d7652e4630000a030a852e46300003000000030000000f08b92fefc7f0000008b92fefc7f000000b8529c0dd68f370000000000000000a030a852e46300007051a852e46300002800000000000000e87d7652e4630000a030a852e4630000a830a852e463000000b8529c0dd68f37487e7652e46300000000000000000000287f7652e46300000000000000000000107a7a52e463000000b8529c0dd68f37e87d7652e4630000a030a852e463000010000000000000004a2c1c3e677a0000e08b92fefc7f00003900000040000040a030a852e46300007a0e1c3e677a0000107a7a52e4630000c030a85201000000e08b92fefc7f000020000000ffffffff7051a852e4630000d90b3a3e677a000001000000806a4452e4630000677a0000208c92fefc7f00003001000000000000408c92fefc7f0000800000004040000040000040000000001f1b853d677a00003041a852e46300003041a852e46300000000000000000000908c92fefc7f000000000000000000000000000000000000808c92fefc7f000001000000000000000000000000000000000000000000000000000000000000001800000000000000a0333555e46300003001000000000000"
                module.id = "2"
                object.id = "275"
                object.serial = "2421"
                application.name = "PipeWire ALSA [java]"
                node.name = "alsa_playback.java"
                device.description = "ALSA Playback [java]"
                media.name = "ALSA Playback"
                media.type = "Audio"
                media.category = "Playback"
                config.name = "client-rt.conf"
                client.api = "alsa"
                log.level = "0"
                cpu.max-align = "32"
                default.clock.rate = "48000"
                default.clock.quantum = "1024"
                default.clock.min-quantum = "32"
                default.clock.max-quantum = "2048"
                default.clock.quantum-limit = "8192"
                default.video.width = "640"
                default.video.height = "480"
                default.video.rate.num = "25"
                default.video.rate.denom = "1"
                clock.power-of-two-quantum = "true"
                link.max-buffers = "64"
                mem.warn-mlock = "false"
                mem.allow-mlock = "true"
                settings.check-quantum = "false"
                settings.check-rate = "false"
                application.process.binary = "java"
                application.language = "en_US.UTF-8"
                application.process.id = "14241"
                application.process.user = "wolf"
                application.process.host = "archlinux"
                application.process.session_id = "2"
                window.x11.display = ":0"
                core.version = "1.0.3"
                core.name = "pipewire-wolf-14241"
                pipewire.access = "unrestricted"

Offline

#2 2024-02-25 22:18:29

V1del
Forum Moderator
Registered: 2012-10-16
Posts: 21,659

Re: PipeWire ALSA [java] creating multiple streams per each sound

Sounds like a game bug, I doubt you can "bend this right" just via wireplumber. On a random googler: https://github.com/runelite/runelite/is … 1813525702 maybe try that?

FWIW it could also be a bug in pipewire's ALSA emulation, might want to check what happens if you uninstall pipewire-alsa and install pulseaudio-alsa instead (or vice-versa if you're actually using pulseaudio-alsa currently).

FWIW2 I just now realized you're primarily talking just about the TTS plugin but... yeah application bug. It creates a new MP3Player object for each audio file (...instead of creating that once and reusing it and passing new files to it as they come) which will create a new audio device each time and they won't be freed since the mp3player lib also creates infinite background threads (... waiting for more to playback). Said MP3 lib is also 15 years old, surely there must be something more recent to use.

Reading the source, the faulty path is only used when using the susan voice and you should be able to configure a different one. FWIW felt like trying something, this is untested, but patch the TTSPlugin file with this:

diff --git a/TTSPlugin.java b/TTSPlugin.java
index e8b0c42..77ae6b6 100644
--- a/TTSPlugin.java
+++ b/TTSPlugin.java
@@ -58,6 +58,7 @@ public class TTSPlugin extends Plugin {
 	private Dialog lastDialog;
 	private final AtomicReference<Clip> currentClip = new AtomicReference<>();
 	private final AtomicReference<Future<?>> queueTask = new AtomicReference<>();
+	private final MP3Player mp3Player = new MP3Player(System.getProperty("java.io.tmpdir") + "/ttsbriantemp.mp3");
 
 	@Inject private Client client;
 	@Inject private TTSConfig config;
@@ -90,6 +91,7 @@ public class TTSPlugin extends Plugin {
 	@Override
 	protected void startUp() {
 		// TODO: consolidate hotkey vs click message processing
+		this.mp3Player.setRepeat(true);
 		this.keyManager.registerKeyListener(this.hotkeyListener);
 		this.keyManager.registerKeyListener(this.quantityHotkeyListener);
 		this.mouseManager.registerMouseListener(this.mouseHandler);
@@ -116,6 +118,7 @@ public class TTSPlugin extends Plugin {
 		lastDialog = null;
 		menuOpenPoint = null;
 		stopClip();
+		mp3Player.stop();
 
 		// Terminate queue task
 		queue.clear();
@@ -300,7 +303,6 @@ public class TTSPlugin extends Plugin {
 
 				//Play mp3, file doesn't get deleted, but it gets overwritten every time so its no issue
 				SwingUtilities.invokeLater(() -> {
-					MP3Player mp3Player = new MP3Player(file);
 					mp3Player.play();
 				});
 
@@ -328,6 +330,7 @@ public class TTSPlugin extends Plugin {
 				clip.addLineListener(event -> {
 					LineEvent.Type type = event.getType();
 					if (type == LineEvent.Type.STOP) {
+						clip.close();
 						currentClip.compareAndSet(clip, null);
 					}
 				});
 

Last edited by V1del (2024-02-26 00:43:51)

Offline

#3 2024-02-27 01:10:41

wolfsilver00
Member
Registered: 2024-02-25
Posts: 6

Re: PipeWire ALSA [java] creating multiple streams per each sound

Thanks a lot V1del, the fix is being implemented (not by me, I'm just testing it which means I need to learn to build and test this on linux as the dev is on windows, which.. well, it's taking some time) and Ill come with news as soon as I have some big_smile

Offline

#4 2024-02-27 09:20:38

V1del
Forum Moderator
Registered: 2012-10-16
Posts: 21,659

Re: PipeWire ALSA [java] creating multiple streams per each sound

As mentioned, the quick fix for you as an end user that you should be able to test immediately would be to use another voice than susan/or the ttsengine brian so it's not using the mp3player implementation. If it goes looking for "clips" these are actually much more frequently cleaned up and I'm suspecting they don't lead to the issue.

But that's just some inference from reading the source, I'd have to download and test myself to properly verify my claims. But that the mp3Player is incorrectly used is pretty clear just from looking at both sources.

Last edited by V1del (2024-02-27 09:33:19)

Offline

Board footer

Powered by FluxBB