2011-10-18 52 views
1

我的遊戲通過通常的方法播放聲音:SourceDataLine.drain()掛在OSX

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

而且用戶可以取消播放(異步):

sdl.stop(); 

此取消很好地工作在Windows下,但對於一個運行帶有Java 6的OSX 10.5.8的用戶,該程序會掛起。 Threaddump顯示播放線程在drain()中:com.sun.media.sound.MixerSourceLine.nDrain。如果用戶不中斷聲音,它會很好地完成,應用程序會繼續。

我的問題是:

  • 這是一個OSX的Java缺陷?
  • 我應該用sdl.close()而不是停止嗎?
  • 任何建議或經驗的解決方法?

編輯:我發現有類似的效果this bug報告,但該網頁說,這是固定的。

+0

此[示例](http://stackoverflow.com/questions/2064066/does-java-have-built-in-libraries-for-audio-synthesis/2065693#2065693)通常在Mac OSX 10.5.8上完成,Java 6. – trashgod

+0

@trashgod該示例沒有異步關閉。我在提到的問題中提到,如果不中斷,聲音播放良好。 – akarnokd

+0

你是否使用[BigClip]獲得相同的行爲(http://stackoverflow.com/questions/5667454/playing-audio-file-in-java-application/5668510#5668510)? –

回答

1

作爲參考,本實施例中使用close()出口通常在任一Java 5或6

調用stop(),而不是close(),在EDT掛起包括Java 5和6,除非line已經常在關閉初始線程。這似乎是drain()阻塞的預期結果,因爲停止的線路不能流失。

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); 
    } 
} 

需要Note

+0

感謝您的解釋。看來Windows JRE不符合規範。我會要求用戶通過這些修改來嘗試遊戲。 – akarnokd

+1

更改工作。謝謝。 – akarnokd