繁体   English   中英

Java 同时播放多个剪辑

[英]Java play multiple Clips simultaneously

因此,每次单击面板时,我的应用程序都应该播放 WAV 文件。 但现在的问题是,它在播放第二个之前等待第一个完成。 我希望能够让他们同时播放。

我把 Thread.sleep(500) 的原因是因为如果我不这样做,那么它根本不会播放声音:(

    import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;

import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.FloatControl;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.swing.JFrame;

@SuppressWarnings("serial")
public class SoundEffectPlayer extends JFrame {

    /*
     * Jframe stuff
     */
    public SoundEffectPlayer() {
        this.setSize(400, 400);
        this.setTitle("Mouse Clicker");
        this.addMouseListener(new Clicker());


        this.setVisible(true);
    }

    private class Clicker extends MouseAdapter {
        public void mouseClicked(MouseEvent e) {
            try {
                playSound(1);
            } catch (InterruptedException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }
        }
    }

    /*
     * Directory of your sound files
     * format is WAV
     */
    private static final String DIRECTORY = "file:///C:/Users/Jessica/Desktop/audio/effects/sound 1.wav";

    /*
     * The volume for sound effects
     */
    public static float soundEffectsVolume = 0.00f;

    /*
     * Loads the sound effect files from cache
     * into the soundEffects array.
     */
    public void playSound(int ID) throws InterruptedException {

        try {
            System.out.println("playing");
            Clip clip;
            URL url = new URL(DIRECTORY);
            AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(url);
            clip = AudioSystem.getClip();
            clip.open(audioInputStream);
            clip.setFramePosition(0);
            FloatControl gainControl = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN);
            gainControl.setValue(soundEffectsVolume);

            clip.start();   
            System.out.println("played");
            Thread.sleep(3000);
            System.out.println("closing");

        } catch (MalformedURLException e) {
            System.out.println("Sound effect not found: "+ID);
            e.printStackTrace();
            return;
        } catch (UnsupportedAudioFileException e) {
            System.out.println("Unsupported format for sound: "+ID);
            return;
        } catch (LineUnavailableException e) {
            e.printStackTrace();
            return;
        } catch (IOException e) {
            e.printStackTrace();
            return;
        }   
    }
    public static void main(String[] args) throws InterruptedException {
        new SoundEffectPlayer();
    }
}

更新:好的,所以我让它们同时播放,但是我想在 Clip 播放完毕后关闭线程,而不是让线程等待 500 毫秒

我怎样才能做到这一点?

我一直运行多个这样的声音。 我没有生成新线程,因为我猜 javaSound 已经在另一个线程中运行了剪辑。 主要的“游戏循环”可能会继续做自己的事情。 应用程序可以为回调注册侦听器或使用 getter 来查看剪辑正在做什么。

有时,如果我们要制作多媒体或游戏应用程序,只需使用 getter 就更容易了。 运行 gameloop 30-60fps 为大多数情况提供了足够的粒度,我们可以完全控制发生的事情和时间。 这个小 testapp 播放两个 wav 文件,第一个运行一次,第二个在 3 秒后启动,第二个循环。

// java -cp ./classes SoundTest1 clip1=sound1.wav clip2=sound2.wav
import java.util.*;
import java.io.*;
import java.net.URL;
import javax.sound.sampled.*;

public class SoundTest1 {

    public Clip play(String filename, boolean autostart, float gain) throws Exception {
        AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(new File(filename));
        Clip clip = AudioSystem.getClip();
        clip.open(audioInputStream);
        clip.setFramePosition(0);

        // values have min/max values, for now don't check for outOfBounds values
        FloatControl gainControl = (FloatControl)clip.getControl(FloatControl.Type.MASTER_GAIN);
        gainControl.setValue(gain);

        if(autostart) clip.start();
        return clip;
    }

    public static void main(String[] args) throws Exception {
        Map<String,String> params = parseParams(args);
        SoundTest1 test1 = new SoundTest1();

        Clip clip1 = test1.play(params.get("clip1"), true, -5.0f);
        Clip clip2 = test1.play(params.get("clip2"), false, 5.0f);

        final long duration=Long.MAX_VALUE;
        final int interval=500;
        float clip2IncGain=0.4f;
        for(long ts=0; ts<duration; ts+=interval) {
            System.out.println(String.format("clip1=%d/%d(%.2f), clip2=%d/%d(%.2f)"
                ,clip1.getFramePosition(), clip1.getFrameLength()
                ,((FloatControl)clip1.getControl(FloatControl.Type.MASTER_GAIN)).getValue()
                ,clip2.getFramePosition(), clip2.getFrameLength()
                ,((FloatControl)clip2.getControl(FloatControl.Type.MASTER_GAIN)).getValue()
            ));
            if (ts>6000 && !clip2.isRunning()) {
                clip2.setFramePosition(0);
                clip2.start();
            }
            if (!clip1.isRunning()) {
                clip1.close();
            }

            if(ts % 2000 == 0) {
                // values have min/max values, for now don't check for outOfBounds values
                FloatControl gainControl = (FloatControl)clip2.getControl(FloatControl.Type.MASTER_GAIN);
                float oldVal=gainControl.getValue();
                clip2IncGain = oldVal>=5.5 ? clip2IncGain*-1
                    : oldVal<=-5.5 ? clip2IncGain*-1
                    : clip2IncGain;
                gainControl.setValue(oldVal+clip2IncGain);
            }

            Thread.sleep(interval);
        }
    }

    private static Map<String,String> parseParams(String[] args) {
        Map<String,String> params = new HashMap<String,String>();
        for(String arg : args) {
            int delim = arg.indexOf('=');
            if (delim<0) params.put("", arg.trim());
            else if (delim==0) params.put("", arg.substring(1).trim());
            else params.put(arg.substring(0, delim).trim(), arg.substring(delim+1).trim() );
        }
        return params;
    }

}

有关更多信息,请参阅JavaSound 文档

尝试检查这个开源音板程序的源代码: DBoard

您对使用MediaPlayer类特别感兴趣。 你可以调用它使用

(new Thread(new MediaPlayer(PATHTOFILE)).start();

暂无
暂无

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

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