Как остановить звук, воспроизводимый в новой теме? - PullRequest
0 голосов
/ 10 июля 2019

Я делаю простую танковую игру, в которой есть фоновая музыка. Мне нужно, чтобы музыка остановилась всякий раз, когда игрок умирает (здоровье игроков становится равным 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 голосов
/ 11 июля 2019

Объявите летучее логическое значение. Почему летучий? Потому что он должен обновляться между потоками.

private volatile boolean playing;

Включить логическое значение в предложение while.

while(playing && nBytesRead != -1)

Сделать логическое значение доступным извне потока воспроизведения.

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

Если вы хотите отключить звук, позвоните setPlaying(false). Не забудьте сделать логическое значение истинным до запуска звука.

Единственным недостатком здесь является то, что звук может заканчиваться щелчком, поскольку он будет мгновенным. Добавление затухания включает в себя настройку и вызов объекта javax.sound.sampled.Control (мне с этим не повезло) или манипулирование данными самого PCM.

По крайней мере с SourceDataLine у нас есть доступ к байтам (в вашем массиве abData). Данные могут быть собраны в PCM в соответствии с вашим аудиоформатом, затем умножены на значение фейдера, которое изменяется от 1 до 0 в течение примерно 64 кадров, постепенно набирая значения PCM до 0, а затем принимая эти новые значения PCM и преобразовать их обратно в байты и записать это. Да, много проблем, чтобы избавиться от клика. Но оно того стоит.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...