今天在利用JAVA3D播放聲音的時候,碰到一個很奇怪的問題,那就是聲音設備無法初始化。它拋出如下異常:
java.lang.UnsupportedOperationException: No AudioDevice specified
但是教程上面包括SUN的例子里面都是這樣寫的,他那樣寫肯定有它的道理,他不可能寫一個錯誤的代碼吧?那心里就納悶了,為什么我的電腦就是播放不了呢,難道又像播放MIDI一樣,因為裝了JMF的原因?我把JMF也缷了,電腦也重啟了,還是不行,該不會是人品問題吧:(
后來查看錯誤的調用順序,發現是這句話拋出了異常:
......
viewer.createAudioDevice();
......
也就是在生成音頻設備的時候,這個方法會生成并初始化好音頻設備,我們在播放音頻的時候,一定需要調此方法的。
然后再看這句話里面的代碼,說到這里,突然覺得用JAVA挺爽的,可以看到你用的類的JAVA的源碼,Viewver是JAVA3D里面的類,查看這個方法,發現這個方法如下:
if (physicalEnvironment == null) {
System.err.println("Java 3D: createAudioDevice: physicalEnvironment is null");
return null;
}
try {
String audioDeviceClassName =
(String) java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction() {
public Object run() {
return System.getProperty("j3d.audiodevice");
}
});
if (audioDeviceClassName == null) {
throw new UnsupportedOperationException("No AudioDevice specified");
}
// Issue 341: try the current class loader first before trying the
// system class loader
Class audioDeviceClass = null;
try {
audioDeviceClass = Class.forName(audioDeviceClassName);
} catch (ClassNotFoundException ex) {
// Ignore excpetion and try system class loader
}
if (audioDeviceClass == null) {
ClassLoader audioDeviceClassLoader =
(ClassLoader) java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction() {
public Object run() {
return ClassLoader.getSystemClassLoader();
}
});
if (audioDeviceClassLoader == null) {
throw new IllegalStateException("System ClassLoader is null");
}
audioDeviceClass = Class.forName(audioDeviceClassName, true,
audioDeviceClassLoader);
}
Class physEnvClass = PhysicalEnvironment.class;
Constructor audioDeviceConstructor =
audioDeviceClass.getConstructor(new Class[] {physEnvClass});
PhysicalEnvironment[] args = new PhysicalEnvironment[] { physicalEnvironment };
AudioEngine3DL2 mixer =
(AudioEngine3DL2) audioDeviceConstructor.newInstance((Object[])args);
mixer.initialize();
return mixer;
}
catch (Throwable e) {
e.printStackTrace();
physicalEnvironment.setAudioDevice(null);
System.err.println("Java 3D: audio is disabled");
return null;
}
}
然后再細看異常是在
if (audioDeviceClassName == null) {
throw new UnsupportedOperationException("No AudioDevice specified");
}
這一句拋出來的,而audioDeviceClassName 是通過System.getProperty("j3d.audiodevice");來獲得的,之所以會拋出這個異常,還是因為系統沒有j3d.audiodevice的屬性,后來我輸出System的所有Properties看了一下,果然沒有j3d.audiodevice的屬性,那就怪了,為什么我的電腦會沒有這個屬性呢?
后來才知道,本來這個屬性裝了JAVA3D以后都會有的,但是由于JAVA3D1.3發現了一個BUG,一個播放聲音的BUG,所以在后續的版本中把這個屬性去掉了,也就是不再讓人用JAVA3D來播放聲音了。我用的是JAVA3D1.5,所以就沒有這個屬性了,所以音頻設備也就初始化不了了。
那怎么樣呢?JAVA不裝這個屬性,我們自己指定就是了,于是在viewer.createAudioDevice();代碼調用之前,我調用如下代碼為它設置這個屬性,讓它可以自己找到音頻播放設備:
System.setProperty("j3d.audiodevice", "com.sun.j3d.audioengines.javasound.JavaSoundMixer");
這樣就好了,我們在播放的時候,使用的就是com.sun.j3d.audioengines.javasound.JavaSoundMixer來播放了,不過,因為有BUG的報道,所以用它播放可能會出現一些問題,聽說現在JOAL正在努力解決這個問題。讓我們共同期待吧。
JOAL的地址:https://joal.dev.java.net
JOGL的地址:https://jogl.dev.java.net
盡管千里冰封
依然擁有晴空
你我共同品味JAVA的濃香.