如何停止在新线程中播放的声音?

时间:2019-07-10 11:21:27

标签: java audio

我正在做一个简单的坦克游戏,它有背景音乐。每当播放器死亡时,我都需要停止播放音乐(播放器健康状态为0)。我该怎么办?

我尝试通过在play()函数外部释放线程并使用t.stop()停止线程来停止线程,但这没有用。

package com.company;

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

import javax.sound.sampled.*;

public class Sound implements Runnable
{

    private String fileLocation;
    public String getFileLocation() {
        return fileLocation;
    }

    public Sound() {
    }



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

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



    public 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();
    }
}

1 个答案:

答案 0 :(得分:0)

声明一个易失的布尔值。为什么易挥发?因为它需要跨线程更新。

private volatile boolean playing;

在while子句中包含布尔值。

while(playing && nBytesRead != -1)

使布尔值可从播放线程外部访问。

public void setPlaying(boolean) {
    this.playing = playing;
}

要关闭声音时,请致电setPlaying(false)。不要忘记在声音开始之前将布尔值设为true。

这里唯一的缺点是声音可能会以喀哒声结束,因为它会立即发出声音。添加淡入淡出包括设置和调用javax.sound.sampled.Control对象(我对它们有好运),或摆弄PCM数据本身。

至少使用SourceDataLine,我们可以访问字节(在您的abData数组中)。可以根据您的音频格式将数据组合成PCM,然后将其乘以推子值(在诸如64帧之类的过程中,从1到0),逐渐将PCM值降低到0,然后取这些新的PCM值。并将其转换回字节并写入。是的,要摆脱点击会带来很多麻烦。但是值得。