获取音频以在 JAR 文件中播放 [英] Get audio to play in JAR File

查看:42
本文介绍了获取音频以在 JAR 文件中播放的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道这个问题已经被问过很多次了,我看了很多,希望能找出我的问题,但这并没有多大帮助.我得到了这个类来在我的 GUI 上播放 WAV 文件,它在检索本地文件时工作.但它在 JAR 文件中不起作用.我知道这是因为音乐类仅适用于检索本地文件,因此我需要帮助更改代码以从 JAR 检索音乐文件.

I know this question has been asked many times and I've looked at many in hopes to figure out my problems, but it didn't really help much. I was given this class to use to play WAV files on my GUI and it works when retrieving local files. But it doesn't work in a JAR file. I know this is because the music class only works for retrieving local files, so I need help changing the code to retrieve music files from the JAR.

这是 SoundPlayer 类:

Here's the SoundPlayer class:

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 抓取本地文件的地方.我只是不确定如何更改它.

In the getClip() method, I think that's where there needs to be a change since that's where the AudioInputStream is grabbing local files. I'm just not sure how to change it though.

推荐答案

jar 文件中的文件实际上不能作为文件检索.相反,您需要使用 Class 对象(通常是 this 变量)的 .getResource 以检索 URL.getResourceAsStream 为其检索 InputStream.

Files in a jar file can't actually be retrieved as a file. Instead, you need to use the Class object (usually the this variable)'s .getResource to retrieve a URL or .getResourceAsStream to retrieve an InputStream for it.

然后您可以将其中任何一个传递给 AudioSystem.getAudioInputStream 的重载之一,因为它具有 一个用于 InputStreams一个用于URLs.

You can then pass either of these into one of AudioSystem.getAudioInputStream's overloads as it has one for InputStreams and one for URLs.

这篇关于获取音频以在 JAR 文件中播放的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆