2011-10-18 6 views
1

Mon jeu reproduit le son via la méthode habituelle:SourceDataLine.drain() se bloque sur OSX

sdl.open(); 
sdl.start(); 
sdl.write(data, 0, data.length); 
sdl.drain(); 
sdl.stop(); 
sdl.close(); 

Et l'utilisateur peut annuler la lecture (de façon asynchrone):

sdl.stop(); 

Cette annulation fonctionne bien sous Windows, mais pour un utilisateur exécutant OSX 10.5.8 avec Java 6, le programme se bloque. Threaddump montre que le fil de lecture est à l'intérieur de drain(): com.sun.media.sound.MixerSourceLine.nDrain. Si l'utilisateur n'interrompt pas le son, il se termine bien et l'application continue.

Mes questions sont les suivantes:

  • Est-ce un bug Java OSX?
  • Devrais-je utiliser sdl.close() au lieu d'arrêter?
  • Avez-vous des suggestions ou de l'expérience sur une solution de contournement?

Modifier: J'ai trouvé this rapport de bogue avec des effets similaires, mais la page dit il est fixé.

+0

Cet exemple [http://stackoverflow.com/questions/2064066/does-java-have-built-in-libraries-for-audio-synthesis/2065693#2065693] se termine normalement sous Mac OSX 10.5.8 , Java 6. – trashgod

+0

@trashgod Cet exemple n'est pas fermé de manière asynchrone. J'ai mentionné dans la question que lorsqu'il n'est pas interrompu, le son joue bien. – akarnokd

+0

Avez-vous le même comportement en utilisant [BigClip] (http://stackoverflow.com/questions/5667454/playing-audio-file-in-java-application/5668510#5668510)? –

Répondre

1

Pour référence, cet exemple en utilisant close() sorties normalement sous Java 5 6.

Invoquer stop(), plutôt que close(), sur l'EDT se bloque à la fois Java 5 et 6 à moins que le line a déjà été fermé normalement sur la fil initial. Cela semble être le résultat attendu du blocage drain(), car une ligne arrêtée ne peut pas être drainée.

import java.awt.EventQueue; 
import javax.sound.sampled.AudioFormat; 
import javax.sound.sampled.AudioSystem; 
import javax.sound.sampled.LineUnavailableException; 
import javax.sound.sampled.SourceDataLine; 
import javax.swing.JOptionPane; 

/** 
* @see https://stackoverflow.com/questions/7803310 
* @see https://stackoverflow.com/questions/2065693 
*/ 
public class Tone { 

    public static void main(String[] args) throws LineUnavailableException { 
     final AudioFormat af = 
      new AudioFormat(Note.SAMPLE_RATE, 8, 1, true, true); 
     final SourceDataLine line = AudioSystem.getSourceDataLine(af); 
     EventQueue.invokeLater(new Runnable() { 

      public void run() { 
       JOptionPane.showMessageDialog(null, "Halt"); 
       //line.stop(); // stops and hangs on drain 
       line.close(); 
      } 
     }); 
     line.open(af, Note.SAMPLE_RATE); 
     line.start(); 
     for (Note n : Note.values()) { 
      play(line, n, 500); 
      play(line, Note.REST, 10); 
     } 
     line.drain(); 
     line.close(); 
    } 

    private static void play(SourceDataLine line, Note note, int ms) { 
     ms = Math.min(ms, Note.SECONDS * 1000); 
     int length = Note.SAMPLE_RATE * ms/1000; 
     int count = line.write(note.data(), 0, length); 
    } 
} 

Nécessite Note.

+0

Merci pour l'explication. Il semble que Windows JRE ne soit pas conforme aux spécifications. Je vais demander à l'utilisateur d'essayer le jeu avec ces modifications. – akarnokd

+1

Les modifications ont fonctionné. Merci. – akarnokd