2017-08-23 4 views
1

J'essaie de lire un son dans une application Java, mais l'application ne se termine jamais car le thread PulseAudio Eventloop est toujours en cours d'exécution, même après avoir essayé close l'instance Clip utilisée pour jouer le son:Le fichier audio Java ne peut pas être fermé lors de l'utilisation de Linux PulseAudio

import java.io.File; 
import java.io.IOException; 

import javax.sound.sampled.AudioFormat; 
import javax.sound.sampled.AudioInputStream; 
import javax.sound.sampled.AudioSystem; 
import javax.sound.sampled.Clip; 
import javax.sound.sampled.DataLine; 
import javax.sound.sampled.LineEvent; 
import javax.sound.sampled.LineListener; 
import javax.sound.sampled.LineUnavailableException; 
import javax.sound.sampled.UnsupportedAudioFileException; 

final class AudioClipTest { 

    public static void main(String[] args) throws UnsupportedAudioFileException, IOException, LineUnavailableException { 
     try (AudioInputStream instream = AudioSystem.getAudioInputStream(new File("resources/test-sound.wav"))){ 
      final AudioFormat format = instream.getFormat(); 
      final Clip clip = (Clip) AudioSystem.getLine(new DataLine.Info(Clip.class, format)); 
      clip.addLineListener(new LineListener() { 
       @Override 
       public void update(final LineEvent event) { 
        if (event.getType() == LineEvent.Type.STOP) { 
         System.out.println("Finished playing audio."); 
         event.getLine().close(); 
         // FIXME: This line is never reached on Linux with 
         // PulseAudio 
         System.out.println("Closed audio data line."); 
        } 
       } 
      }); 
      clip.open(instream); 
      clip.start(); 
     } 
    } 

} 

Sur ma machine Linux & dagger;, la méthode principale ci-dessus joue le son correspondant, imprime

Terminé la lecture audio.

puis de se bloquer, alors que sur un Windows & ddagger; machine imprime

Terminé la lecture audio.

Ligne de données audio fermée.

et quitte correctement.

L'implémentation réelle Clip utilisée sur la machine Linux est org.classpath.icedtea.pulseaudio.PulseAudioClip alors que sous Windows, elle est com.sun.media.sound.DirectAudioDevice.DirectClip; Que se passe-t-il ici? — Qu'est-ce que PulseAudioClip.close() qui ne revient pas?


& poignard;Distribution:Linux Mint 18,1; Noyau:4.4.0-92-generic x86_64; OpenJDK:8u131-b11-2ubuntu1.16.04.3; PulseAudio:1: 8,0-ubuntu3.3

& ddagger;Diffusion:Windows 10 Pro; Version: ; OS Build:15063,540 x64; Oracle JDK:1.8.0_144-b01; DirectX:la version 12

Répondre

0

Une façon possible de contourner ce problème est d'utiliser l'API Alsa (espace utilisateur) pour la lecture audio en utilisant Java. L'API alsa userspace redirigera vers PulseAudio (ou une autre API/table de mixage), vous devriez donc toujours avoir un son correct.

Modifier $JAVA_HOME/jre/lib/sound.properties et commenter tout ce qui concerne org.classpath.icedtea.pulseaudio et ajouter ceci:

javax.sound.sampled.Clip=com.sun.media.sound.DirectAudioDeviceProvider 
javax.sound.sampled.Port=com.sun.media.sound.PortMixerProvider 
javax.sound.sampled.SourceDataLine=com.sun.media.sound.DirectAudioDeviceProvider 
javax.sound.sampled.TargetDataLine=com.sun.media.sound.DirectAudioDeviceProvider 

En outre, s'il vous plaît fichier un bogue sur paquet openjdk de votre distribution.Les liaisons PulseAudio/Java n'ont pas été prises en charge depuis des années et doivent être supprimées.