【问题标题】:Looping audio on separate thread in Java在Java中的单独线程上循环音频
【发布时间】:2014-06-08 22:15:34
【问题描述】:

我正在制作一个 2d RPG 游戏,我想让背景音乐正常工作。我写了一个声音类,在单独的线程上播放音乐,但我不知道如何让它循环。我的声音类如下:

package tileRPG.gfx;

import java.io.File;
import java.io.IOException;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;


public class Sound implements Runnable 
{

    private String fileLocation = "res/bgMusic.wav";

    public Sound() { }

    public void play() 
    {
        Thread t = new Thread(this);
        t.start();
    }

    public void run()
    {
        playSound(fileLocation);
    }

    private void playSound(String fileName) 
    {
        File soundFile = new File(fileName);
        AudioInputStream audioInputStream = null;
        try 
        {
            audioInputStream = AudioSystem.getAudioInputStream(soundFile);
        } 
        catch (Exception e)
        {
            e.printStackTrace();
        }
        AudioFormat audioFormat = audioInputStream.getFormat();
        SourceDataLine line = null;
        DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat);
        try 
        {
            line = (SourceDataLine) AudioSystem.getLine(info);
            line.open(audioFormat);
        } 
        catch (LineUnavailableException e) 
        {
            e.printStackTrace();
        } 
        catch (Exception e) 
        {
            e.printStackTrace();
        }
        line.start();
        int nBytesRead = 0;
        byte[] abData = new byte[128000];
        while (nBytesRead != -1) 
        {
            try 
            {
                nBytesRead = audioInputStream.read(abData, 0, abData.length);
            } 
            catch (IOException e) 
            {
                e.printStackTrace();
            }
            if (nBytesRead >= 0) 
            {
                int nBytesWritten = line.write(abData, 0, nBytesRead);
            }
        }
        line.drain();
        line.close();
    }
}

【问题讨论】:

  • 你想再玩一次吗?请确认。
  • 我希望它继续重播,直到程序结束
  • @gnomed,我想修复缩进,因为它的可读性不好。是的,如果作者不同意,他可以拒绝或撤消它。
  • 花括号的可读性问题在软件开发中是一个长期存在的争论,我认为这个网站不适合告诉人们使用一种风格而不是另一种风格(是编辑所做的一切)。可读性是一种主观意见,相比之下,我发现原来的花括号定位更具​​可读性(就像 OP 一样)。
  • 好的,@gnomed,我同意这是一个长期存在的争论,如果原因仅仅是这个,我不会修复它。如果代码是这样的,我不会修复它。还有不正确的缩进,代码区域外的大括号(看看原来的),目标是修复它。但如果作者不同意,可以撤消它。没问题。

标签: java multithreading loops audio


【解决方案1】:
public void run ()
{
    while(true)
    {
        playSound(fileLocation);
    }
}

这会创建一个无限循环。相应调整。

当您启动一个线程时,它将执行run() 方法中的任何代码,然后退出。所以这是循环重复播放声音的地方(不阻塞你的其他线程/代码)。

此解决方案无法使用您当前的代码停止该线程(并因此停止播放),但我假设您正在分阶段编写此代码。当应用程序当前播放时,线程将停止播放并退出。

【讨论】:

  • 简单而有效。感谢您的解决方案!我不敢相信我不是自己想到的
【解决方案2】:

使用递归

示例代码:

private void playSound(String fileName) 
{
   ...
   line.drain();
   line.close();

   //recursive call to same method
   playSound(fileName);
}

您可以通过将方法playSound() 的静态部分移动到run() 方法中来使其变得更好。在这种情况下,您不需要再次读取该文件。

提示:在playSound() 方法中传递SourceDataLine 而不是fileName

【讨论】:

  • 这将在播放期间(因此永远)阻止他们的代码,我认为这是不可取的。
  • 我认为他使用线程不是出于“有趣”的原因。帖子中甚至没有 main 方法,所以我不会假设他们的程序什么都不做(他们说这是一个 2D 游戏)
  • @gnomed 我已经在我的帖子中更新了它。请确认。
  • 或者他可以查看我的解决方案,该解决方案只需添加一行即可完成这项工作。我不认为一个只专注于运行另一个线程的线程是非常好的设计(这就是这段代码正在做的事情)。
  • 大声笑,但它有两个缺陷。首先,它不是最易读的。查看run() 方法,您无法判断它永远不会返回(不知道该方法是递归的)。更重要的是,它会无限地添加到内存有限的调用堆栈中,并最终导致整个应用程序崩溃(所有事物都会出现 StackOverFlow 异常!!)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-09-25
  • 1970-01-01
  • 2022-01-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多