有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

音频Java剪辑不工作

有人能帮我理解为什么下面的代码不起作用吗

我通过调用方法start()开始剪辑。此方法将创建一个新线程以运行剪辑。然而,不,它似乎什么都没放

代码编译时没有任何错误

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

更新

我发现了问题!问题在于音频文件。我使用了一个不同的音频文件,我可以通过上面的代码听到声音

代码编译时没有任何错误或警告,这真是令人讨厌。我通过获取音频格式检测到问题,然后将其传递给DataLine类的对象。信息。然后,从数据行检索片段

因此,基本上不是通过以下方式获得剪辑:

this.clip = AudioSystem.getClip();

我将通过以下方式获得剪辑:

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

当我用这个编译时,Java抛出了以下错误:

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

所以,我更换了音频文件,它工作了


共 (1) 个答案

  1. # 1 楼答案

    clip.loop是一个非阻塞调用。也就是说,一旦调用它(它执行它所执行的操作),它将返回,这意味着您的线程将退出,除非有另一个非守护进程线程在运行,否则JVM将退出

    我原以为您可以使用Clip#drain使其阻塞,直到剪辑完成,但从技术上讲,剪辑不会完成。。。在正常意义上

    相反,我建立了自己的循环

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

    现在,这可能是一个问题,因为Thread是一个非守护进程线程,永远不会结束。。。您应该设置某种volitle标志,将其设置为false并帮助终止循环,而不是while (true) {

    例如

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

    已更新

    上面的示例(IMHO)有一些错误,可以用简单的对象监视器来修复

    因此,我们可以使用Clip#loop功能,而不使用volatile标志和while循环,只需使用Object#waitObject#notify

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