Java clip not working

前端 未结 1 1683
爱一瞬间的悲伤
爱一瞬间的悲伤 2021-01-29 14:24

Can someone please help me understand why this code below doesn\'t work?

I start the clip by calling method start(). This method creates a new thread for th

1条回答
  •  深忆病人
    2021-01-29 14:35

    clip.loop is a non-blocking call. That is, once you call it (and it does what it does), it will return, this means your thread will exit and, unless there is another non-daemon thread running, the JVM will exit.

    I had thought you might be able to use Clip#drain to cause it to block until the clip had completed, but technically, the clip won't complete...in the normal sense.

    Instead, I set up my own loop...

    public void start() {
        Runnable r = new Runnable() {
        public void run() {
            while (true) {
                clip.setFramePosition(0);
                clip.start();
                clip.drain();
            }
        }
        };
        thread = new Thread(r);
        thread.start();
    }
    

    Now, this could be an issue, because the Thread is a non-daemon thread and will never end...Instead of while (true) { you should setup some kind volitle flag which you set to false and help terminate the loop...

    For example...

    import java.io.IOException;
    import java.net.URL;
    import java.util.logging.Level;
    import java.util.logging.Logger;
    import javax.sound.sampled.AudioInputStream;
    import javax.sound.sampled.AudioSystem;
    import javax.sound.sampled.Clip;
    import javax.sound.sampled.LineUnavailableException;
    
    public class Audio {
    
        private Clip clip;
    
        private Thread thread;
        private volatile boolean keepPlaying = true;
    
        public static void main(String[] args) {
            Audio audio = new Audio("Kalimba.wav");
            audio.start();
    
            try {
                Thread.sleep(5000);
            } catch (InterruptedException ex) {
            }
            audio.stop();
        }
    
        public Audio(String audioFile) {
            AudioInputStream audioStream = null;
    
            URL audioURL = this.getClass().getClassLoader().getResource(audioFile);
    
            // Obtain audio input stream from the audio file and load the information
            // into main memory using the URL path retrieved from above.
            try {
                audioStream = AudioSystem.getAudioInputStream(audioURL);
            } catch (Exception e) {
                e.printStackTrace();
                System.exit(1);
            }
    
            try {
                // Retrieve the object of class Clip from the Data Line.
                this.clip = AudioSystem.getClip();
    
                // Load the audio input stream into memory for future play-back.
                this.clip.open(audioStream);
            } catch (LineUnavailableException e) {
                e.printStackTrace();
                System.exit(1);
            } catch (IOException e) {
                e.printStackTrace();
                System.exit(1);
            }
        }
    
        public void stop() {
            if (thread != null) {
    
                keepPlaying = false;
                clip.stop();
                thread.interrupt();
    
            }
        }
    
        public void start() {
            Runnable r = new Runnable() {
                public void run() {
                    while (keepPlaying) {
                        clip.setFramePosition(0);
                        clip.start();
                        clip.drain();
                    }
                }
            };
            thread = new Thread(r);
            thread.start();
        }
    }
    

    Updated

    There a few things wrong with the above example (IMHO), which can be fixed with a simple object monitor.

    So, instead of a volatile flag and a while loop, we can use the Clip#loop functionality and simply use Object#wait and Object#notify instead, for example

    import java.io.IOException;
    import java.net.URL;
    import javax.sound.sampled.AudioInputStream;
    import javax.sound.sampled.AudioSystem;
    import javax.sound.sampled.Clip;
    import javax.sound.sampled.LineUnavailableException;
    
    public class Audio {
    
        private Clip clip;
    
        private Thread thread;
        private final Object loopLock = new Object();
    
        public static void main(String[] args) {
            Audio audio = new Audio("Music.wav");
            audio.start();
    
            try {
                Thread.sleep(5000);
            } catch (InterruptedException ex) {
            }
            audio.stop();
        }
    
        public Audio(String audioFile) {
            AudioInputStream audioStream = null;
    
            URL audioURL = this.getClass().getClassLoader().getResource(audioFile);
    
            // Obtain audio input stream from the audio file and load the information
            // into main memory using the URL path retrieved from above.
            try {
                audioStream = AudioSystem.getAudioInputStream(audioURL);
            } catch (Exception e) {
                e.printStackTrace();
                System.exit(1);
            }
    
            try {
                // Retrieve the object of class Clip from the Data Line.
                this.clip = AudioSystem.getClip();
    
                // Load the audio input stream into memory for future play-back.
                this.clip.open(audioStream);
            } catch (LineUnavailableException e) {
                e.printStackTrace();
                System.exit(1);
            } catch (IOException e) {
                e.printStackTrace();
                System.exit(1);
            }
        }
    
        public void stop() {
            synchronized (loopLock) {
                loopLock.notifyAll();
            }
        }
    
        public void start() {
            Runnable r = new Runnable() {
                public void run() {
                    clip.setFramePosition(0);
                    clip.loop(Clip.LOOP_CONTINUOUSLY);
                    synchronized (loopLock) {
                        try {
                            loopLock.wait();
                        } catch (InterruptedException ex) {
                        }
                    }
                    clip.stop();
                }
            };
            thread = new Thread(r);
            thread.start();
        }
    }
    

    0 讨论(0)
提交回复
热议问题