【问题标题】:How to stop a music Clip?如何停止音乐剪辑?
【发布时间】:2011-04-29 14:44:49
【问题描述】:

我正在和一些同学一起开发一个游戏,到目前为止,除了音乐之外,我们已经编写了几乎所有的东西。 music.java 类发布在下面。

我们在停止声音时遇到了问题,因此我需要一种方法来停止播放此剪辑,这样我们才能真正开始另一个剪辑,这样我们就可以在游戏期间切换音乐(例如,当您开始游戏时,歌曲应该不同于主菜单)。

即使我可以摧毁物体来制造一个新的,如果有可能,我愿意这样做,但我不知道如何做到这一点。我宁愿有可能停止当前的剪辑文件,并用新的文件替换它。

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

在我的 GuiController 中,我创建了一个新的 Music 对象,通过 playSiren 方法我给了我的歌曲名称,然后它会自动运行。

【问题讨论】:

    标签: java eclipse audio


    【解决方案1】:

    查看DataLine.stop() 方法。 Clip 实现 DataLine


    例如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);
        }
    }
    

    【讨论】:

    • @Andrew 很抱歉再次打扰你,我可以看到你是如何在同一个班级停止剪辑的,但你也可以在另一个班级这样做吗?
    • @Andrew 很抱歉再次打扰您,我可以看到您是如何在同一个班级中停止剪辑的,但是您也可以在另一个班级中这样做吗?因为当面板变得可见时,我不知道该怎么做;
    • @Jonathan:“你在同一个班级停止了你的剪辑”实际上并非如此。当您编译该源代码时,会生成 3 个类。第一个是ClipControl.class,其中创建了Clip。第二个和第三个是匿名内部类,名称为 ClipControl$1.classRunnableClipControl$1$1.classActionListener。在ActionListener 中,Clip 被切换为启动/停止。归根结底,这并不是关于声音剪辑,而是成员的可见性以及代码的设计。也许您应该就此提出一个新问题。
    • @andrew 非常感谢您在这件事上的帮助,我认为我们从中得到了很多智慧,仍然想知道如何做到这一点,因为我们不需要按钮来切换音乐,所以我们不能真正在那个剪辑上放置一个 actionListener,但是非常感谢 ^^ 我们会想办法的
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-06-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-12
    • 1970-01-01
    相关资源
    最近更新 更多