Not able to play audio in Java

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 -l returns “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).
  • ffplay still 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
This entry was posted in Computers, programming, Software and tagged . Bookmark the permalink.

Leave a comment