Java plays multiple clips at the same time

So my application needs to play the WAV file every time I click on the panel. But the problem now is that she waits for the first one to finish, until she plays the second. I want them to be able to play at the same time.

The reason I put Thread.sleep (500) is because if I don't, it won't play any sound at all :(

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

      

Update: Ok, so I made them play at the same time, but I want the stream to close when the clip finished playing, instead of waiting for the stream to be 500ms

How can i do this?

+1


source to share


2 answers


I always play several of these sounds. I am not spawning a new topic, as I believe javaSound is already triggering clips in another topic. The main "game loop" can continue to do its job. The app can register listeners for callbacks, or use receivers to see what the clips are doing.

Sometimes, if we want to make a multimedia or gaming application, it is easier to use getters. Running gameloop at 30-60fps gives us enough detail for most situations and we have complete control over what happens and when. This little testapp plays two wav files, the first one runs once, the second runs after 3 seconds, the second loop.



// 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;
    }

}

      

See the JavaSound documentation for more information.

+2


source


Try to check the source code of this open source program: DBoard .

You are especially interested in using the MediaPlayer class . You can call it using



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

      

+1


source







All Articles