2014-01-29 87 views
0

我正在研究遊戲的聲音代碼。我用的是下面的代碼:* .wav文件需要在目錄中存在的位置?

import java.io.*; 
import java.net.URL; 
import javax.sound.sampled.*; 

/** 
* This enum encapsulates all the sound effects of a game, so as to separate the sound playing 
* codes from the game codes. 
* 1. Define all your sound effect names and the associated wave file. 
* 2. To play a specific sound, simply invoke SoundEffect.SOUND_NAME.play(). 
* 3. You might optionally invoke the static method SoundEffect.init() to pre-load all the 
* sound files, so that the play is not paused while loading the file for the first time. 
* 4. You can use the static variable SoundEffect.volume to mute the sound. 
*/ 
public enum SoundEffect { 
    EXPLODE("explode.wav"), // explosion 
    GONG("gong.wav"),   // gong 
    SHOOT("shoot.wav");  // bullet 

    // Nested class for specifying volume 
    public static enum Volume { 
     MUTE, LOW, MEDIUM, HIGH 
    } 

    public static Volume volume = Volume.LOW; 

    // Each sound effect has its own clip, loaded with its own sound file. 
    private Clip clip; 

    // Constructor to construct each element of the enum with its own sound file. 
    SoundEffect(String soundFileName) { 
     try { 
     // Use URL (instead of File) to read from disk and JAR. 
     URL url = this.getClass().getClassLoader().getResource(soundFileName); 
     // Set up an audio input stream piped from the sound file. 
     AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(url); 
     // Get a clip resource. 
     clip = AudioSystem.getClip(); 
     // Open audio clip and load samples from the audio input stream. 
     clip.open(audioInputStream); 
     } catch (UnsupportedAudioFileException e) { 
     e.printStackTrace(); 
     } catch (IOException e) { 
     e.printStackTrace(); 
     } catch (LineUnavailableException e) { 
     e.printStackTrace(); 
     } 
    } 

    // Play or Re-play the sound effect from the beginning, by rewinding. 
    public void play() { 
     if (volume != Volume.MUTE) { 
     if (clip.isRunning()) 
      clip.stop(); // Stop the player if it is still running 
     clip.setFramePosition(0); // rewind to the beginning 
     clip.start();  // Start playing 
     } 
    } 

    // Optional static method to pre-load all the sound files. 
    static void init() { 
     values(); // calls the constructor for all the elements 
    } 
} 

現在,當我更換從代碼中列出的* .wav文件之一,我自己還是連名字我自己從上面的代碼中列出的文件名之一。我收到以下錯誤:

Exception in thread "main" java.lang.ExceptionInInitializerError 
    at soundTest.main(soundTest.java:19) 
Caused by: java.lang.NullPointerException 
    at com.sun.media.sound.StandardMidiFileReader.getSequence(Unknown Source) 
    at javax.sound.midi.MidiSystem.getSequence(Unknown Source) 
    at com.sun.media.sound.SoftMidiAudioFileReader.getAudioInputStream(Unknown Source) 
    at javax.sound.sampled.AudioSystem.getAudioInputStream(Unknown Source) 
    at SoundEffect.<init>(sfx.java:75) 
    at SoundEffect.<clinit>(sfx.java:55) 

從以下堆棧URL網址爲空進去,這是告訴我的* .wav文件本身沒有被讀取。

我已經嘗試了以下幾行,並且是* .wav文件存在(我知道我不能有三個項目命名相同,我已經使用過一個玩過它,然後評論它,然後再試一次另外一個,我只是刪除了「//」,使更容易閱讀):

TEST("file://C:/shoot.wav"); 
TEST("/soundTest/shoot.wav"); 
TEST("shoot.wav"); 

除了,放置文件的副本中的目錄與包(默認),src文件夾中,當然還有根(c :)。

我如何envoking枚舉是我的主要發言,其中它是所有標準的Java,主要的代碼,但有:

SoundEffect.SHOOT.play(); 

到底在哪做的* .wav文件需要在詮釋他的目錄?或者如果有另一個問題,我錯過了,請指出。我也在Windows 8.1上使用Eclipse IDE「Kepler」。我想說明發布的代碼是迄今爲止我所擁有的。

+0

根據您的示例,這些文件需要存儲在默認包中。話雖如此,我相信對於Eclipse,您需要在您的項目根目錄下創建一個「resources」文件夾,並將您希望包含在Jar中的資源放入其中。 – MadProgrammer

+0

@MadProgrammer這樣糾正我,如果我錯了,我可以拖放文件,到package_Name,然後我只是像評論說的那樣調用它?因爲我已經嘗試過並且發生同樣的錯誤。 – user3247187

+0

如果我正確理解Eclipse(我不是它的用戶),則需要在項目的頂層創建一個「resources」目錄。在這裏,你需要創建一個與SoundEffect的包結構相同的目錄結構。然後把你的文件放到這裏,乾淨並且構建......手指穿過 – MadProgrammer

回答

1

在評論中有一些討論Eclipse可能是問題。我嚴重懷疑Eclipse是否是問題。我已經使用Eclipse加載了數百個音頻文件。通常,我將這些文件放在調用代碼下一級的子目錄「audio」中,並使用相對地址形式:「audio/mySound.wav」。

這是我如何加載我的URL:爲什麼會出現在你的堆棧跟蹤MIDI引用

URL url = this.getClass().getResource("audio/" & fileName); 

我困惑的是。 MIDI與加載.wav文件無關,實際上根本不應該涉及。你確定這是正確的堆棧跟蹤?爲什麼我們看到對MIDI的引用?

有時無法識別的.wav文件格式會引發意外的錯誤。最常見的.wav是16位編碼,44100bps,立體聲,小端。你的這種格式的.wav文件是?

你的代碼有一些方面我沒有看到過這種方式實現,尤其是使用ENUMS。我會把你的話全部通過測試和驗證。我傾向於命名單個聲音對象(使用Clip或SourceDataLine的wav文件的包裝器進行播放)並以這種方式使用它們。可能是你有什麼是一個很好的組織工具,但我不清楚它是否按預期工作。

例如,靜態使用SoundEffect,如SoundEffect.SHOOT.play(),您確定它指向shoot.wav嗎?你寫了一個測試來驗證這個?結合ENUMS和靜態調用 - 對我來說有點棘手。

+0

感謝你的回覆,我是如何看到這段代碼的,是從另一個組員加入並離開的,所以我正在使用他留給我們的代碼來查看是否有任何可用的代碼。我看起來比我見過的其他「遊戲音頻代碼」簡單得多。我會嘗試你的網址建議,明天再與你聯繫。我會仔細檢查* .wav文件,看它是否是JAVA可以播放的有效類型。 – user3247187

+0

你可能會嘲笑這個,但它是真正的* .wav文件本身,不支持通過java。 SMH但是也有更多的代碼,沒有它運行沒有錯誤,但不輸出聲音。 – user3247187

+0

有時我爲了避免哭鬧而笑。我第一次遇到這個問題時非常沮喪和惱火。我的DAW更喜歡使用32位編碼導出.wavs,因此我很難搞清楚這一點,因爲我對Java音頻還不熟悉,並且對我的代碼沒有理解。問題的一部分是平庸的編碼會在其他錯誤中包裝錯誤,以至於很難找到根本原因:使用找到的代碼的bugaboos之一。 –