当前位置: 首页 > 知识库问答 >
问题:

如何在(

江正德
2023-03-14

我在做一个宠物项目(一种游戏)。我遇到了一个问题:当从控制台用命令调用应用程序时:

C:\java -jar MyGame.jar

播放短的声音,但不播放长的声音。所有声音都在JAR中的“/资产”文件夹中。

音频的路径如下所示:

C:\MyGame.jar\assets\background_music.wav

例如射击或跳跃。对于长音频数据,仅播放前 0.5 秒。

例如:如果您加载长度为0.834秒的声音,那么它会循环(背景音乐),声音将循环播放!(WAV 文件,0.843 秒,48 KB)。但是,如果加载 WAV 文件 2 秒且大小为 115 KB,则只会播放 0.5-1 秒。如果加载 WAV 背景音乐文件 15 秒(或 7 秒),大小为 110 - 2000 KB 及以上,则将播放相同的 0.5 秒。每 15 秒(或 7 秒)(如果您说“循环播放”)。

也就是说,文件被加载,它的长度被加载,标记被放置在开头和结尾,但我只听到前0.5秒的音频(每个“x”-sec,其中“x”是剪辑的长度)。

音频上传方法:

public static InputStream uploadAudio (String path){
    InputStream sourceSound = null;
    try{

        final File jarFile = new File(ResourceLoader.class.getProtectionDomain().getCodeSource().getLocation().getPath());
        if(jarFile.isFile()) {  // Run with JAR file

            final JarFile jar = new JarFile(jarFile);


            InputStream fileInputStreamReader =(jar.getInputStream(jar.getEntry(path)));
            byte[] byteArray = new byte[fileInputStreamReader.available()];
            fileInputStreamReader.read(byteArray);

            InputStream newInputStreamFromArray =  new BufferedInputStream(new ByteArrayInputStream(byteArray));

            sourceSound = newInputStreamFromArray;
            jar.close();

        } else { // Run with IDE

            URL url = ResourceLoader.class.getResource( "../" + path);
            InputStream fileInputStreamReader = new BufferedInputStream(new FileInputStream(url.getPath()));
            sourceSound = fileInputStreamReader;
        }

    }catch (IOException e){
        e.printStackTrace();
    }
    return sourceSound;
}

音频播放类的一部分:

public class Sound implements AutoCloseable {
private boolean released = false;
private AudioInputStream stream = null;
private Clip clip = null;
private FloatControl volumeControl = null;
private boolean playing = false;

public Sound(InputStream inputStream) {
    try {
        stream = AudioSystem.getAudioInputStream(inputStream);
        clip = AudioSystem.getClip();
        clip.open(stream);
        clip.addLineListener(new Listener());
        volumeControl = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN);
        released = true;
    } catch (IOException | UnsupportedAudioFileException | LineUnavailableException exc) {
        exc.printStackTrace();
        released = false;

        close();
    }
}


public void playLoop(boolean breakOld){
    if (released) {
        if (breakOld) {
            clip.stop();
            clip.loop(Clip.LOOP_CONTINUOUSLY);
            playing = true;
        } else if (!isPlaying()) {
            clip.loop(Clip.LOOP_CONTINUOUSLY);
            playing = true;
        }
    }

}
public void playLoop(){
    playLoop(true);
}

没有错误。该程序有效。背景声音循环播放,但只有剪辑的0.5秒。播放短声音(拍摄或跳跃声音)。一切都在IDE中工作:短声音和完整的背景音乐。

共有1个答案

孙夕
2023-03-14

问题解决了!(可能不是最好的方式)。我的问题是我采取了方法

 public static Image uploadImage (String path)

并重写了其中的一部分音频。在映像方法中,有一个用于解压缩 JAR 的字符串。

  InputStream fileInputStreamReader = (jar.getInputStream (jar.getEntry (path)));

接下来,我编写了音频代码。它并没有直接工作:对于

 InputStream sourceSound = new BufferedInputStream (fileInputStreamReader);
 ... ...
return sourceSound;

下一步 - 我添加了:

            InputStream fileInputStreamReader =(jar.getInputStream(jar.getEntry(path)));
            byte[] byteArray = new byte[fileInputStreamReader.available()];
            fileInputStreamReader.read(byteArray);

            InputStream newInputStreamFromArray =  new BufferedInputStream(
                                      new ByteArrayInputStream(byteArray));

            sourceSound = newInputStreamFromArray;

它奏效了!(我是这么想的)。在这里发布问题后,我开始认为并非所有输入流都是用字节[]字节数组编写的。我制作了字节数组的副本,并将其写入文件“H:/1.wav”。

这是我在文件中看到的:

RIFFp[) WAVEfmt      D¬  ±   dataäZ) ÿ1VÿEÿR¾ÿVëÿH .
.....................................................................................
.....................................................................................

还有etс。数据被切断了。没有内容。

图像的工作代码:

 BufferedImage sourceImage = null;
                InputStream fileInputStreamReader = jar.getInputStream(jar.getJarEntry(path));
                sourceImage = ImageIO.read(fileInputStreamReader);//magic ImageIO.read () !!!!

同样不适用于音频:

InputStream fileInputStreamReader =(jar.getInputStream(jar.getEntry(path)));
            byte[] byteArray = new byte[fileInputStreamReader.available()];
            fileInputStreamReader.read(byteArray);

我想我没有学好Java=)所以我现在就这样解决了这个问题:

        InputStream fileInputStreamReader =(jar.getInputStream(jar.getEntry(path)));
        byte[] byteArray = new byte[fileInputStreamReader.available()];

        int i = 0;
        int byteRead;
        while ((byteRead = fileInputStreamReader.read()) != -1) {
            byteArray[i] = (byte) byteRead;
            i++;
        }

        InputStream newInputStreamFromArray =  new BufferedInputStream(new ByteArrayInputStream(byteArray));

长音频和短音频现在可以正常地从罐子中读取。

如果有人知道如何做得更好——我会很高兴听到答案。

 类似资料:
  • 问题内容: 我有一个水平线,我需要将每个垂直线居中。我的标记如下。每个都有一个边框,我需要物品及其内容垂直位于中间。请帮忙; 我是CSS新手。 问题答案: 我假设由于您使用的是XML声明,因此您不必担心IE或较旧的浏览器。 所以,你可以使用和像这样:

  • 问题内容: 我有下表: 如果给定的ID不存在,我想插入具有默认Val的ID。但是,如果它已经存在,我想增加Val的值。 我有以下代码: 并且它可以工作,但是我想用一个SQL语句来完成。我可以吗? 编辑 : 从@ Xikinho90的答案,我的最终代码是 问题答案: 您可以使用插入或替换。 我认为这可以解决问题 您只需要用输入的ID替换数字 谢谢奇科

  • 我在为android版本添加提升时遇到一些问题 例如:如果我想根据材质设计为抽屉布局添加立面,我应该怎么做?

  • 我在这里看到了下面的代码。描述说: 我们还可以使用自动 我确实理解汽车的衰退

  • 问题内容: 我还不能弄清楚如何在Swift中获取a的子字符串: 我无法在Swift中创建范围。在Playground中自动完成并不是超级有帮助-这说明: 我在Swift标准参考库中找不到任何有帮助的东西。这是另一个疯狂的猜测: 还有这个: 我看过其他答案(在SwiftString中查找字符的索引),似乎暗示着由于是的桥类型,因此“旧”方法应该起作用,但尚不清楚如何- 例如,这也不起作用(似乎不是有

  • 在Perl中,使用Moo,可以围绕sub实现sub,它将围绕类中的其他方法。 如何在Raku中实现这种行为,最好使用角色?