Skip to main content
Topic: foo_out_pulse - pulseaudio output (Read 1705 times) previous topic - next topic
0 Members and 1 Guest are viewing this topic.

foo_out_pulse - pulseaudio output

Hello, I have made a component for Wine users, to interface directly with Pulseaudio. It's definitely 'beta', hopefully someone finds it useful. In the future I will try to enable streaming to other IPs, for example to allow streaming to a Raspberry Pi or similar. Please see the setup notes.

Home
Download

Re: foo_out_pulse - pulseaudio output

Reply #1
Works great.

Completely remove the pauses when wrting a lot of tags.

Thanks.

Re: foo_out_pulse - pulseaudio output

Reply #2
Works great here too. Wondering what's up with the winelib detection mode I saw in the source code. Also awaiting support for linking the foobar2000 volume control with the PulseAudio volume control, as currently, the player's own volume control is non-functional.

Re: foo_out_pulse - pulseaudio output

Reply #3
For the client library I'm using the only build of Pulseaudio available for Windows, which is pretty old (v1.1, current version is 13). I had a go at getting the latest version to build but haven't been able to yet.

I was considering ways to allow better intergration by avoiding the need to set up and use the TCP protocol - ie. communicate directly with Pulse's Unix socket like native applications do. There are two ways I can think of to do it. One is by modifying the Pulse library to directly make the syscalls for accessing the socket. The library is pretty complex so that's probably too difficult, especially as I can't even build Pulse yet.

The other is you can build a DLL using wine tooling that exports certain functions as a DLL and implements them using code compiled for Linux. You can therefore build a DLL that exports the same interface as the libpulse, and passes through every function call to the system's native libpulse.so, which then handles the socket connection etc. as usual. This is basically how Wine's own audio implementation works, except that it is more complex as is translates the Windows API to Pulse's. By passing through the libpulse API everything is much simpler, and there is basically no impedance mismatch between foobar's API and pulse's. The advantage of this is that it uses the most up to date client library on your system, which might have improvements at this point such as power use, and it avoids the need for the TCP protocol. The downside is that you're building a wine DLL that links against Wine and Pulse on your system, so I believe you will have to rebuild it for every update of those packages. Also, while it worked well for a while when I was testing it, at one point it started crashing and as you can imagine it's significantly harder to debug.

So overall I think it's not worth pursuing, the possible advantages are quite small anyway. If you are interested you can look at my libpulse-wine repo which builds the DLL, that you can drop in as a replacement to the bundled one.

Re: foo_out_pulse - pulseaudio output

Reply #4
I have made a new release, with the following changes

- Custom anti-popping seek/track change fading implementation that keeps PA fully buffered while allowing instant seeking etc. The fading is configurable in Advanced Preferences -> Playback -> Pulseaudio output
- Uses a new Pulseaudio v13 build, should fix sometimes high CPU use after seek or manual track change
- Two way PA volume control integration
- More responsive playback start/track change
- Fix bug playing very short files where playback would be delayed
- Fix hang on last item in playlist

I would be interested to see if anyone has problems with this release seeing as it has a Pulseaudio client library that I compiled myself. It seems OK for me so far. Also any problems with the fading implementation, as it assumes that the fading can be calculated at a certain speed. Maybe on certain setups the assumption will be incorrect.

If it crashes horribly, you can copy the 'pulse' folder from the previous release. The only issue with it is that after seek/track change, sometimes its CPU use will jump up until playback is stopped.

Download

Re: foo_out_pulse - pulseaudio output

Reply #5
v0.1-beta - works
v0.2-beta - playback is sped up, ~25x

Re: foo_out_pulse - pulseaudio output

Reply #6
v0.1-beta - works
v0.2-beta - playback is sped up, ~25x

Thank you for testing. Could you try the attached version please?

Could you also send me the output of the command pactl list?


Re: foo_out_pulse - pulseaudio output

Reply #8
I tested the 0.2 release on Github already, it works fine. No "speed up" issues.

Re: foo_out_pulse - pulseaudio output

Reply #9
Tested on fresh, clean, portable install, it worked then the problem returned. It scrolls through a two minute track in five seconds  :o . Must be some obscure hardware/software config issue on my side.

Apologies for wasting time.

Re: foo_out_pulse - pulseaudio output

Reply #10
Tested on fresh, clean, portable install, it worked then the problem returned. It scrolls through a two minute track in five seconds  :o . Must be some obscure hardware/software config issue on my side.

Apologies for wasting time.

I think I can see the problem causing the fast playback - I am not handling an error condition properly, instead of failing on error the playback will speed up. I'll add some better error reporting, maybe we can work out what's wrong. I would be interested in knowing your distribution/wine version/output of pactl list still if you have time. Maybe I can set up a similar test envronment.

Re: foo_out_pulse - pulseaudio output

Reply #11
Version 0.2 installed.

I test going back and forward in the songs a lot and not problem at all.

Also now the playback stops correctly at the end of playlist, stop after current and stop after queue.

And the most cool of all; the volume of foobar finally changes the pulseaudio volume.


Re: foo_out_pulse - pulseaudio output

Reply #12
Love that you're working on this. I'm having the same superfast playback issue, running Voidlinux, Wine 5.16, and pulseaudio 13.
Do you need the whole pactl list or just the running sink?

Code: [Select]
Sink #0
State: RUNNING
Name: alsa_output.pci-0000_00_1b.0.analog-stereo
Description: Built-in Audio Analog Stereo
Driver: module-alsa-card.c
Sample Specification: s32le 2ch 48000Hz
Channel Map: front-left,front-right
Owner Module: 7
Mute: no
Volume: front-left: 20316 /  31% / -30.52 dB,   front-right: 20316 /  31% / -30.52 dB
        balance 0.00
Base Volume: 65536 / 100% / 0.00 dB
Monitor Source: alsa_output.pci-0000_00_1b.0.analog-stereo.monitor
Latency: 1999385 usec, configured 2000000 usec
Flags: HARDWARE HW_MUTE_CTRL HW_VOLUME_CTRL DECIBEL_VOLUME LATENCY
Properties:
alsa.resolution_bits = "32"
device.api = "alsa"
device.class = "sound"
alsa.class = "generic"
alsa.subclass = "generic-mix"
alsa.name = "CX20756 Analog"
alsa.id = "CX20756 Analog"
alsa.subdevice = "0"
alsa.subdevice_name = "subdevice #0"
alsa.device = "0"
alsa.card = "1"
alsa.card_name = "HDA Intel PCH"
alsa.long_card_name = "HDA Intel PCH at 0xb3614000 irq 51"
alsa.driver_name = "snd_hda_intel"
device.bus_path = "pci-0000:00:1b.0"
sysfs.path = "/devices/pci0000:00/0000:00:1b.0/sound/card1"
device.bus = "pci"
device.vendor.id = "8086"
device.vendor.name = "Intel Corporation"
device.product.id = "9c20"
device.product.name = "8 Series HD Audio Controller"
device.form_factor = "internal"
device.string = "front:1"
device.buffering.buffer_size = "768000"
device.buffering.fragment_size = "384000"
device.access_mode = "mmap+timer"
device.profile.name = "analog-stereo"
device.profile.description = "Analog Stereo"
device.description = "Built-in Audio Analog Stereo"
alsa.mixer_name = "Conexant CX20756"
alsa.components = "HDA:14f15114,1179f922,00100100"
module-udev-detect.discovered = "1"
device.icon_name = "audio-card-pci"
Ports:
analog-output-speaker: Speakers (priority: 10000, not available)
analog-output-headphones: Headphones (priority: 9900, available)
Active Port: analog-output-headphones
Formats:
pcm



Sink Input with your plugin playing at 25x speed:
Code: [Select]
Sink Input #0
Driver: protocol-native.c
Owner Module: 24
Client: 1
Sink: 0
Sample Specification: float32le 2ch 48000Hz
Channel Map: front-left,front-right
Format: pcm, format.sample_format = "\"float32le\""  format.rate = "48000"  format.channels = "2"  format.channel_map = "\"front-left,front-right\""
Corked: no
Mute: no
Volume: front-left: 65536 / 100% / 0.00 dB,   front-right: 65536 / 100% / 0.00 dB
        balance 0.00
Buffer Latency: 0 usec
Sink Latency: 1999162 usec
Resample method: copy
Properties:
media.name = "Audio"
application.name = "foobar2000"
native-protocol.peer = "TCP/IP client from 127.0.0.1:47746"
native-protocol.version = "33"
application.id = "foobar2000"
application.icon_name = "foobar2000"
application.process.id = "32"
application.process.binary = "foobar2000.exe"
application.language = "C"
window.x11.display = ":0"
application.process.machine_id = "pij"
application.process.session_id = "1"
module-stream-restore.id = "sink-input-by-application-id:foobar2000"


Sink Input with the default output playing normally:
Code: [Select]
Sink Input #1
Driver: protocol-native.c
Owner Module: 12
Client: 3
Sink: 0
Sample Specification: float32le 2ch 48000Hz
Channel Map: front-left,front-right
Format: pcm, format.sample_format = "\"float32le\""  format.rate = "48000"  format.channels = "2"  format.channel_map = "\"front-left,front-right\""
Corked: no
Mute: no
Volume: front-left: 65536 / 100% / 0.00 dB,   front-right: 65536 / 100% / 0.00 dB
        balance 0.00
Buffer Latency: 15000 usec
Sink Latency: 5053 usec
Resample method: copy
Properties:
media.name = "audio stream #3"
application.name = "foobar2000.exe"
native-protocol.peer = "UNIX socket client"
native-protocol.version = "33"
application.process.id = "7818"
application.process.binary = "wine-preloader"
application.language = "en_GB.UTF-8"
window.x11.display = ":0"
application.process.machine_id = "beee4f833bf4e74cd586ac5e5da826d4"
application.process.session_id = "1"
module-stream-restore.id = "sink-input-by-application-name:foobar2000.exe"

Obvious difference is
   Buffer Latency: 0 usec
   Sink Latency: 1999162 usec
vs
   Buffer Latency: 15000 usec
   Sink Latency: 5053 usec

Hope that's a help. Let me know if you need the full print.

Re: foo_out_pulse - pulseaudio output

Reply #13
Thank you that's actually very useful.

Re: foo_out_pulse - pulseaudio output

Reply #14
For your sink,

Code: [Select]
Latency: 1999385 usec, configured 2000000 usec

If you restart Pulseaudio (pulseaudio -k) and don't use my plugin, is the sink latency still set that high initially or is it lower at first?

Re: foo_out_pulse - pulseaudio output

Reply #15
Ah, that's just because I set "default-fragments = 2; default-fragment-size-msec = 1000" a while back to try and mitigate some stutter issues I was having. Changed it to default-fragment-size-msec = 300 and your plugin's still playing skippedyquick so I don't think that's related.

Re: foo_out_pulse - pulseaudio output

Reply #16
Makes sense, I think the zero buffer is just because of a failure to set up the stream correctly. Would you be able to try changing to interrupt scheduling in PA? You can change it in default.pa, change the line
Code: [Select]
load-module module-udev-detect
to be
Code: [Select]
load-module module-udev-detect tsched=0

You can check it's enabled with
Code: [Select]
pactl list | grep tsched

Re: foo_out_pulse - pulseaudio output

Reply #17
That works!

New Sink Input with your plugin playing at normal speed.
Code: [Select]
Sink Input #1
        Driver: protocol-native.c
        Owner Module: 24
        Client: 4
        Sink: 0
        Sample Specification: float32le 2ch 48000Hz
        Channel Map: front-left,front-right
        Format: pcm, format.sample_format = "\"float32le\""  format.rate = "48000"  format.channels = "2"  format.channel_map = "\"front-left,front-right\""
        Corked: no
        Mute: no
        Volume: front-left: 65536 / 100% / 0.00 dB,   front-right: 65536 / 100% / 0.00 dB
                balance 0.00
        Buffer Latency: 1974187 usec
        Sink Latency: 600895 usec
        Resample method: copy
        Properties:
                media.name = "Audio"
                application.name = "foobar2000"
                native-protocol.peer = "TCP/IP client from 127.0.0.1:49614"
                native-protocol.version = "33"
                application.id = "foobar2000"
                application.icon_name = "foobar2000"
                application.process.id = "32"
                application.process.binary = "foobar2000.exe"
                application.language = "C"
                window.x11.display = ":0"
                application.process.machine_id = "pij"
                application.process.session_id = "1"
                module-stream-restore.id = "sink-input-by-application-id:foobar2000"

Re: foo_out_pulse - pulseaudio output

Reply #18
OK thanks, I think I have worked out the problem. You can change that option back if you prefer - it's supposed to be better but is problematic on some hardware.

Re: foo_out_pulse - pulseaudio output

Reply #19
New version v0.3, hopefully fixes the speed issue. I could reproduce it once but not again - it seems kind of random, so I'd appreciate feedback

Download

edit: oh no it looks like it didn't fix it >,<



Re: foo_out_pulse - pulseaudio output

Reply #21
I tried to test this but for some reason I keep getting "connection refused" in the log when trying to play in foobar2000.

I have followed the instructions to add the line to /etc/pulse/default.pa and rebooted but still the same. I'm on Ubuntu 20.04, any ideas?

Re: foo_out_pulse - pulseaudio output

Reply #22
After investigating the sped-up playback bug and looking at some similar issues from other projects, I am somewhat convinced it's a bug in Pulseaudio or certain ALSA drivers. I'd suggest using tsched=0 if you have that issue. I have left the workaround in in case it's useful, however it's behind a preference in the advanced preferences page.

This version also has some fixes to smooth out visualisations.

Download 0.5

I tried to test this but for some reason I keep getting "connection refused" in the log when trying to play in foobar2000.

I have followed the instructions to add the line to /etc/pulse/default.pa and rebooted but still the same. I'm on Ubuntu 20.04, any ideas?

Is pulseaudio running? Normally when an application tries to output audio, Pulseaudio is started automatically, however that won't work when using it over the network, so you have to start it yourself. You can start it by running 'pulseaudio -D' or opening pavucontrol and waiting for it to connect.

Re: foo_out_pulse - pulseaudio output

Reply #23
Is pulseaudio running? Normally when an application tries to output audio, Pulseaudio is started automatically, however that won't work when using it over the network, so you have to start it yourself. You can start it by running 'pulseaudio -D' or opening pavucontrol and waiting for it to connect.

Yes, it's up and running. I can verify with pavucontrol and foobar2000 recognizes it with the default output component. It's just that when I switch the output to foo_out_pulse I get nothing.

Is there any other way I can test playing something via the native-protocol-tcp module?

Re: foo_out_pulse - pulseaudio output

Reply #24
Yes you can try running any other application with the environment variable PULSE_SERVER set to 127.0.0.1, eg

Code: [Select]
PULSE_SERVER=127.0.0.1 mpv test.mp3

If that works, is there any other output in the foobar console when it fails? Could you try with release 0.1 from github?

 
SimplePortal 1.0.0 RC1 © 2008-2020