SourceDataLine.drain() висит на OSX
Моя игра воспроизводит звук обычным способом:
sdl.open();
sdl.start();
sdl.write(data, 0, data.length);
sdl.drain();
sdl.stop();
sdl.close();
И пользователь может отменить воспроизведение (асинхронно):
sdl.stop();
Эта отмена хорошо работает под Windows, но для одного пользователя, работающего под управлением OSX 10.5.8 с Java 6, программа зависает. Threaddump показывает поток воспроизведения внутри стока (): com.sun.media.sound.MixerSourceLine.nDrain
, Если пользователь не прерывает звук, он завершается хорошо, и приложение продолжается.
Мои вопросы:
- Это ошибка OSX Java?
- Должен ли я использовать
sdl.close()
вместо остановки? - Любые предложения или опыт в обход?
Изменить: я нашел этот отчет об ошибке с похожими эффектами, но на странице написано, что это исправлено.
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://stackru.com/questions/7803310
* @see https://stackru.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
,