获取在JAR文件中播放的音频

时间:2016-06-06 00:08:37

标签: java swing

我知道这个问题已被多次询问,我已经看过很多人希望弄清楚我的问题,但它并没有多大帮助。我被赋予这个类用于在我的GUI上播放WAV文件,它在检索本地文件时起作用。但它在JAR文件中不起作用。我知道这是因为音乐类只适用于检索本地文件,因此我需要帮助更改代码以从JAR中检索音乐文件。

这是SoundPlayer类:

package extra;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.LineEvent;
import javax.sound.sampled.LineListener;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;

import org.pscode.xui.sound.bigclip.BigClip;

/**
 * A class to play audio clips. Caches previously-played clips,
 * allowing fast re-playback of previously played sounds.
 * 
 * @author Anon
 * @version 1.51
 */

public class SoundPlayer {

/** A cache of previously-played audio clips. */
private final Map<String, Clip> myClips = new HashMap<String, Clip>();

/**
 * Plays the audio file with the given file name.
 * This method returns instantly, without waiting for the clip to finish playing.
 * 
 * @param theFilename The name of the file to play.
 * @return a Clip object representing the sound played.
 * @throws IllegalArgumentException if there is a problem reading from the sound file.
 */
public Clip play(final String theFilename) throws IllegalArgumentException {
    return loop(theFilename, 1);
}

/** 
 * Plays the clip with the given file name in a continuous loop.
 * The clip keeps looping until it is later stopped by calling the 
 * stop() method. This function returns instantly
 *    
 * @param theFilename The name of the file to play.
 * @return a Clip object representing the sound played.
 * @throws IllegalArgumentException if there is a problem reading from the sound file.
 */
public Clip loop(final String theFilename) throws IllegalArgumentException {
    return loop(theFilename, Clip.LOOP_CONTINUOUSLY);
}

/** 
 * Plays the clip with the given file name in a loop.
 * The clip loops until it has played the specified number of times,
 * or until it is later stopped by calling the stop() method.
 * This function returns instantly, without waiting for the clip to finish looping.
 *
 * @param theFilename The name of the file to play.
 * @param theNumberOfTimes The number of times to loop the clip.
 * @return a Clip object representing the sound played.
 * @exception IllegalArgumentException if there is a problem reading from the sound file.
 */
public Clip loop(final String theFilename, final int theNumberOfTimes) 
    throws IllegalArgumentException {

    final Clip clip = getClip(theFilename);

    if (clip != null) {
        clip.loop(theNumberOfTimes);
    }

    return clip;
}

/**
 * Pauses the clip with the given file name.
 * If the clip is later played, it will resume from where it was paused.
 * Calling this method does not resume a thread that is 
 * suspended on a playAndWait() or a loopAndWait().
 * 
 * If stop() is called on a paused clip, it will reset to the
 * beginning of the clip for the next play.
 * 
 * @param theFilename The name of the file to pause.
 * @exception IllegalArgumentException if there is a problem reading from
 * or playing the sound file.
 */
public void pause(final String theFilename) throws IllegalArgumentException {
    final Clip clip = getClip(theFilename);

    if (clip != null) {
        final int pos = clip.getFramePosition();
        clip.stop();
        clip.setFramePosition(pos);
    }
}

/** 
 * Stops the clip with the specified filename
 * (and wakes up any threads waiting for it to finish playing).
 * 
 * @param theFilename The name of the file to stop.
 * @return a Clip object representing the sound stopped.
 * @exception IllegalArgumentException if there is a problem reading from the sound file.
 */
public Clip stop(final String theFilename) 
    throws IllegalArgumentException {
    final Clip clip = getClip(theFilename);
    stopClip(clip);

    return clip;
}

/** 
 * Stops all currently playing sound clips
 * (and wakes up the threads waiting for them to finish playing).
 */
public void stopAll() {
    for (final Clip clip : myClips.values()) {
        stopClip(clip);
    }
}   

/** 
 * Preloads the clip at the given file name.
 * This means the clip will be available faster, when requested for playing the first time.
 * @param theFilename The name of the file to preload.
 * @return a Clip object representing the preloaded sound.
 * @exception IllegalArgumentException if there is a problem reading from the sound file.
 */
public Clip preLoad(final String theFilename) 
    throws IllegalArgumentException {
    return getClip(theFilename);
}


/**
 * Returns a Clip object for a filename, either by creating
 * a new one or loading it from the cache.
 * 
 * @param theFilename The name of the file to load.
 * @return a Clip object, or null if one is not found.
 * @exception IllegalArgumentException if there is a problem reading from the sound file.
 */
private Clip getClip(final String theFilename) throws IllegalArgumentException {
    BigClip clip = null;
    AudioInputStream ais = null;

    if (myClips.containsKey(theFilename)) {
        clip = (BigClip) myClips.get(theFilename);
    } else {
        // read audio file from disk
        try {
            ais = AudioSystem.getAudioInputStream(new File(theFilename));


            clip = new BigClip();
            clip.open(ais);
            clip.addLineListener(new LineListener() {
                /** 
                 * Responds to audio events generated by clips. 
                 * 
                 * @param theEvent The event generated.
                 */
                public void update(final LineEvent theEvent) {
                    if (theEvent.getType() == LineEvent.Type.STOP) {
                        // clip is done playing
                        stopClip((Clip) theEvent.getSource());
                    }
                }
            });
            myClips.put(theFilename, clip);
        } catch (final UnsupportedAudioFileException uafe) {
            throw new IllegalArgumentException
            ("Not a valid supported audio file: \"" + theFilename + "\"", uafe);
        } catch (final LineUnavailableException lue) {
            lue.printStackTrace();
            throw new IllegalArgumentException
            ("Line is not available to play sound \"" + theFilename + " \"", lue);
        } catch (final IOException ioe) {
            throw new IllegalArgumentException
            ("I/O error while reading file: \"" + theFilename + "\" ", ioe);
        }
    }

    return clip;
}

/**
 * Stops the playing of the specified clip.
 * 
 * @param theClip The clip.
 */
private void stopClip(final Clip theClip) {
    if (theClip != null) {
        synchronized (theClip) {
            theClip.stop();
            theClip.setFramePosition(0);
            theClip.notifyAll();  // awaken threads waiting for this Clip
        }
    }
}
}

// end of class SoundPlayer

在getClip()方法中,我认为需要进行更改,因为AudioInputStream正在抓取本地文件。我不知道如何更改它。

2 个答案:

答案 0 :(得分:0)

jar文件中的文件实际上无法作为文件检索。相反,您需要使用Class对象(通常是this变量)的scipy skew code来检索URL.getResource以检索{{1}对于它。

然后,您可以将其中任何一个传递到InputStream的重载之一,因为它有.getResourceAsStreamone for InputStreams

答案 1 :(得分:0)

使用ClassLoader.getSystemResource("path/inside/of/jar")

如果目标只是播放声音:

试试TinySound。我最近在我正在开发的一个项目中使用了它,它的设计非常简单易用。请确保您使用.wav.ogg个文件,您可以使用http://media.io/转换为这两个文件。