How to stop a music Clip in Java?

2019-01-12 12:03发布

问题:

I am working with some classmates on a game, we have programmed quite everything but the music until now. The music.java class is posted below.

We have a problem stopping our sound, so I need a way to stop this clip from playing so we can actually start another clip, that way we can shift through music during our game (like when you start a game, the song should be different from the main menu). Can someone help me with this problem?

Even if I can just destroy the object to make a new one, if that's a possibility, I am willing to do that, but I do not have a clue how to do this. I would rather have a possibility to Stop the current clip file, and replace it with a new one.

package sound;

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.Clip;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.FloatControl;
import javax.sound.sampled.LineEvent;
import javax.sound.sampled.LineListener;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;


public class Music implements LineListener, Runnable
{

private File soundFile;
private Thread thread;
private static Music player;
private Music audio;
private Clip clip;
private boolean stoppen = false;


/**
* Private because of the singleton
*/
public Music()
{
}

/**
* Play a siren sound
*/
public void playSiren(String musicFileName)
{
    audio = getPlayer();

    audio.playSirenFile(musicFileName);
}

/**
* Play the siren file
*/
private void playSirenFile(String musicFileName)
{
    this.soundFile = new File("Music/"+musicFileName+".wav");
    thread = new Thread(this);
    thread.setName("SoundPlayer");
    thread.start();
}

/**
* Invoked when the thread kicks off
*/
public void run()
{
    try
    {
        AudioInputStream stream =     AudioSystem.getAudioInputStream(this.soundFile);
        AudioFormat format = stream.getFormat();

/**
* we can't yet open the device for ALAW/ULAW playback, convert
* ALAW/ULAW to PCM
*/
            if ((format.getEncoding() == AudioFormat.Encoding.ULAW) ||    (format.getEncoding() == AudioFormat.Encoding.ALAW))
            {
            AudioFormat tmp = new AudioFormat(
                AudioFormat.Encoding.PCM_SIGNED,
            format.getSampleRate(),
            format.getSampleSizeInBits() * 2, format.getChannels(),
            format.getFrameSize() * 2, format.getFrameRate(), true);
            stream = AudioSystem.getAudioInputStream(tmp, stream);
            format = tmp;
        }
        DataLine.Info info = new DataLine.Info(Clip.class, stream
        .getFormat(), ((int) stream.getFrameLength() * format
        .getFrameSize()));

        this.clip = (Clip) AudioSystem.getLine(info);
        this.clip.addLineListener(this);
        this.clip.open(stream);
        this.clip.start();
        try
        {
            thread.sleep(99);
        }
        catch (Exception e)
        {
        }
        while (clip.isActive() && thread != null)
        {
            try
            {
                thread.sleep(99);
            }
            catch (Exception e)
            {
                break;
            }
        }
        clip.loop(999999999);
        clip.drain();


    }
    catch (UnsupportedAudioFileException e)
    {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    catch (IOException e)
    {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    catch (LineUnavailableException e)
    {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
}

private static Music getPlayer()
{
    if (player == null)
    {
        player = new Music();
    }
    return player;
}

public void update(LineEvent event)
{
}

public void stopClip()
{
    //TODO NEED HELP HERE
}

public void startClip()
{
    //TODO need help here
}
public void volume(float volume)
{

    //TODO NEED HELP HERE
    /*
    FloatControl gainControl = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN);
    gainControl.setValue(-50.0f); // Reduce volume IN DECIBELS
    clip.start();
        */
    }
}

Stuff you might need to know:

In my GuiController, I make a new Music object, through the method playSiren I give my songname, and then it automatically runs.

回答1:

Look into the DataLine.stop() method. Clip implements DataLine.


E.G. ClipControl.java

import java.awt.event.*;
import javax.swing.*;
import javax.sound.sampled.*;
import java.net.URL;

class ClipControl {

    public static void main(String[] args) throws Exception {
        URL url = new URL("http://pscode.org/media/leftright.wav");
        AudioInputStream ais = AudioSystem.getAudioInputStream(url);
        final Clip clip = AudioSystem.getClip();
        clip.open( ais );
        Runnable r = new Runnable() {
            public void run() {
                final JToggleButton startStop = new JToggleButton("Stop");
                startStop.addActionListener( new ActionListener() {
                    public void actionPerformed(ActionEvent ae) {
                        if (startStop.isSelected()) {
                            clip.stop();
                            startStop.setText("Start");
                        } else {
                            clip.loop(-1);
                            clip.start();
                            startStop.setText("Stop");
                        }
                    }
                } );
                clip.loop(-1);
                JOptionPane.showMessageDialog(null, startStop);
            }
        };
        SwingUtilities.invokeLater(r);
    }
}