繁体   English   中英

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

[英]How to stop a sound played in a new thread?

我正在做一个简单的坦克游戏,它有背景音乐。 每当播放器死亡时,我都需要停止播放音乐(播放器健康状态为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();
    }
}

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

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值并将其转换回字节并写入。 是的,要摆脱点击会带来很多麻烦。 但很值得。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM