Java clip not working

牧云@^-^@ 提交于 2019-12-02 23:39:30

问题


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 the clip to run. However, no it doesn't seem to play anything.

The code is compiled without any error...

public class Audio
{
    private Clip clip;

    private Thread thread; 

    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 start()
    {
        Runnable r = new Runnable() {
            public void run()
            {
                loop();
            }
        };
        thread = new Thread(r);
        thread.start();
    }

    public void loop ()
    {       
        // Rewind the media to the beginning of the clip.
        this.clip.setFramePosition(0);

        // Continuously play the clip.
        this.clip.loop(Clip.LOOP_CONTINUOUSLY);

        try
        {
            Thread.sleep(5000);
        } catch (InterruptedException e)
        {
            e.printStackTrace();
        }
    }

UPDATE

I found the problem! The problem is because of the audio file. I used a different audio file and I can hear the sound with the code above.

It is just really annoying that the code compiled without any error or warning. I detected the problem by getting the audio format, then pass it to an object of class DataLine.Info. Then, retrieve the clip from the Data Line.

So, basically instead of getting the clip by:

this.clip = AudioSystem.getClip();

I would get the clip by:

AudioFormat format = audioStream.getFormat();
DataLine.Info info = new DataLine.Info(Clip.class, format);
this.clip = (Clip) AudioSystem.getLine(info);

When I compiled with this, Java threw below error:

No line matching interface Clip supporting format PCM_SIGNED 48000.0 Hz, 24 bit

So, I replaced the audio file, and it worked !


回答1:


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


来源:https://stackoverflow.com/questions/24131591/java-clip-not-working

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!