简体   繁体   English

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

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

I'm making a simple tank game and it has its background music. 我正在做一个简单的坦克游戏,它有背景音乐。 I need the music to stop whenever the player dies (players health int becomes 0). 每当播放器死亡时,我都需要停止播放音乐(播放器健康状态为0)。 How do i do it? 我该怎么做?

I tried stopping the thread by declraring the thread outside of the play() function and stopping it with t.stop() but it didn't work. 我试图通过在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();
    }
}

Declare a volatile boolean. 声明一个易失的布尔值。 Why volatile? 为什么易挥发? Because it needs to update across threads. 因为它需要跨线程更新。

private volatile boolean playing;

Include the boolean in the while clause. 在while子句中包含布尔值。

while(playing && nBytesRead != -1)

Make the boolean accessible from outside the playback thread. 使布尔值可从播放线程外部访问。

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

When you want to turn off the sound, call setPlaying(false) . 当您想要关闭声音时,请调用setPlaying(false) Don't forget to make the boolean true before the sound is started. 不要忘记在声音开始之前将布尔值设为true。

The only drawback here is that the sound may end with a click, since it will be instant. 唯一的缺点是声音可能会发出喀哒声,因为它会立即发出声音。 Adding a fade involves setting up and invoking a javax.sound.sampled.Control object (I've had dubious luck with these), or fiddling with the PCM data itself. 添加淡入淡出涉及设置并调用javax.sound.sampled.Control对象(我对它们有好运),或摆弄PCM数据本身。

At least with a SourceDataLine , we have access to the bytes (in your abData array). 至少使用SourceDataLine ,我们可以访问字节(在您的abData数组中)。 The data can be assembled into PCM according to your audio format, then multiplied by a fader value that goes from 1 to 0 over the course of something like 64 frames, dialing the PCM values down to 0 gradually, and then taking these new PCM values and converting them back to bytes and writing that. 可以根据您的音频格式将数据组合成PCM,然后将其乘以推子值(在诸如64帧之类的过程中,从1到0),逐渐将PCM值降低到0,然后取这些新PCM值并将其转换回字节并写入。 Yes, a lot of trouble just to get rid of a click. 是的,要摆脱点击会带来很多麻烦。 But worth it. 但很值得。

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

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