TL;DR: You will likely not be able to play any audio using Java on WSL2 and there is not much you can do about it.
On my WSL2 machine I was not able to play any audio using java.sound.sampled package. Java does not recognize any devices (mixers).
The call to AudioSystem.getMixerInfo() returns an empty array. I debugged this and this is what I found.
Java Sound relies on ALSA for audio functionality. ALSA libraries are installed on Linux kernel by default so you don’t have to do anything extra to install them. see:
siddjain@beelink:~$ dpkg -l | grep alsa
ii alsa-topology-conf 1.2.5.1-2 all ALSA topology configuration files
ii alsa-ucm-conf 1.2.6.3-1ubuntu1.12 all ALSA Use Case Manager configuration files
siddjain@beelink:~$ dpkg -l | grep libasound2
ii libasound2:amd64 1.2.6.1-1ubuntu1 amd64 shared library for ALSA applications
ii libasound2-data 1.2.6.1-1ubuntu1 all Configuration files and profiles for ALSA drivers
but there is a utility package (package containing non-essential but useful utilities) that you can install by running
$ sudo apt install alsa-utils
so I did that. Then run:
aplay -l
which is supposed to list audio devices but does not show anything on my machine. And that is why Java fails as well.
But why does aplay -l not list any devices? after all I can play sound using ffplay.
The answer lies in the fact that ffplay does not use ALSA. Instead it uses pulseaudio. What is pulseaudio?
PulseAudio is a software mixer [1]:
>ALSA is the kernel level sound mixer, it manages your sound card directly. ALSA by itself can only handle one application at a time.
>PulseAudio is a software mixer, on top of the userland (like you’d run an app). When it runs, it uses Alsa – without dmix – and manages every kind of mixing, the devices, network devices, everything by itself.
Ok so what next? Next, I installed another set of utils (this time PulseAudio utils):
sudo apt install pulseaudio-utils
Then I ran:
$ pactl list sinks
Sink #1
State: SUSPENDED
Name: RDPSink
Description: RDP Sink
Driver: module-rdp-sink.c
Sample Specification: s16le 2ch 44100Hz
Channel Map: front-left,front-right
Owner Module: 19
Mute: no
Volume: front-left: 65536 / 100% / 0.00 dB, front-right: 65536 / 100% / 0.00 dB
balance 0.00
Base Volume: 65536 / 100% / 0.00 dB
Monitor Source: RDPSink.monitor
Latency: 0 usec, configured 0 usec
Flags: DECIBEL_VOLUME LATENCY
Properties:
device.description = "RDP Sink"
device.class = "abstract"
device.icon_name = "audio-card"
Formats:
pcm
We can see it lists a device. However on close inspection we can see this is not a real soundcard. What is happening here is that the system is using an RDP (Remote Desktop Protocol) audio sink (RDPSink), which means that audio is being redirected through a remote desktop session instead of a local sound card. This explains why:
aplay -lreturns “no soundcards found” (because there is no physical sound card available).- Java Sound (
getMixerInfo()) returns an empty array (because it cannot find an ALSA-backed audio device). ffplaystill works (because it is using PulseAudio, which supports networked audio devices like RDP).
Ok so what next now? Can we tell Java Sound to use PulseAudio instead of ALSA [1]? Well, its pretty involved [2]:
>It is a known issue that the proprietary Oracle JDK and JRE builds do not support PulseAudio.
>The IcedTea project got a PulseAudio backend that is designed for use with OpenJDK. This work is licensed under the GPL and this prevents oracle to use the code in their closed source builds unless Oracle decide to opensource their entire JDK/JRE.
>You as an individual can take a build the IcedTea PulseAudio back-end found in IcedTea/OpenJDK builds and use them with the Oracle JDK/JRE but you are not allowed to distribute the combination since it would be a violation of the copyright license. The setup instructions is found in the following bugreport.
To conclude, when ListAudioDevices is run on Windows:
javac ListAudioDevices.java
java ListAudioDevices
it prints out following:
Available mixers:
Mixer: Port Speakers (Intel? Smart Sound Te
Target Line Info:
Line: SPEAKER target port
Mixer: Port LG Ultra HD (Intel(R) Display A
Target Line Info:
Line: Master Volume target port
Mixer: Port Microphone (Intel? Smart Sound
Source Line Info:
Line: MICROPHONE source port
Target Line Info:
Line: Master Volume target port
Mixer: Port Desktop Microphone (Microsoft?
Source Line Info:
Line: MICROPHONE source port
Target Line Info:
Line: Master Volume target port
Mixer: Primary Sound Driver
Source Line Info:
Line: interface SourceDataLine supporting 8 audio formats, and buffers of at least 32 bytes
Line: interface Clip supporting 8 audio formats, and buffers of at least 32 bytes
Mixer: Speakers (Intel? Smart Sound Technology (Intel? SST))
Source Line Info:
Line: interface SourceDataLine supporting 8 audio formats, and buffers of at least 32 bytes
Line: interface Clip supporting 8 audio formats, and buffers of at least 32 bytes
Mixer: LG Ultra HD (Intel(R) Display Audio)
Source Line Info:
Line: interface SourceDataLine supporting 8 audio formats, and buffers of at least 32 bytes
Line: interface Clip supporting 8 audio formats, and buffers of at least 32 bytes
Mixer: Primary Sound Capture Driver
Target Line Info:
Line: interface TargetDataLine supporting 8 audio formats, and buffers of at least 32 bytes
Mixer: Desktop Microphone (Microsoft? LifeCam HD-3000)
Target Line Info:
Line: interface TargetDataLine supporting 8 audio formats, and buffers of at least 32 bytes
Mixer: Microphone (Intel? Smart Sound Technology (Intel? SST))
Target Line Info:
Line: interface TargetDataLine supporting 8 audio formats, and buffers of at least 32 bytes