簡體   English   中英

我想在彼此之后播放聲音,但讓它們等到第一個完成。 我該怎么做?

[英]I want to play sounds after each other but make them wait until the first one is done. How do I do it?

我目前正在做一個簡單的莫爾斯代碼翻譯器,我希望我的代碼在' - '上發出一聲長嗶聲,並在'。'上發出一聲短促的嗶聲,當然這要在彼此之后完成。 但我的節目目前正在播放。 我究竟做錯了什么?

我嘗試添加一個onCompletionListener,但Netbeans 8.1出錯,無法解決問題。

    //Play the morse code
public void playButton(ActionEvent event){
    String morse = mcTextField.getText();
    char[] charArray = morse.toCharArray();
    for(int x = 0; x<charArray.length; x++){

        if(charArray[x] == '.'){
            playBeep(shortBeep);
        }
        else if(charArray[x] == '-'){
            playBeep(longBeep);
        }
        else{
            sleep(500);
        }
        sleep(1000);
    }
    }



private void playBeep(String name){
    String musicFile = name;   

    Media sound = new Media(new File(musicFile).toURI().toString());
    MediaPlayer mediaPlayer = new MediaPlayer(sound);
    mediaPlayer.play();

    sleep(1000);   

}

 private void sleep(int duration){
    try{
        Thread.sleep(duration);
    }catch(Exception e){
        System.out.println("Did not work."+e);
    }
}

這使用了Java Sound API ,但是對於大多數音頻庫來說基本思想應該是可行的,只要提供“播放結束”通知即可。

所有這一切都是,將您要播放的序列放入隊列,播放下一個音,等到它完成並播放下一個音,直到隊列中沒有其他音調。

因為AudioClip在它自己的線程中播放,所以它使用另一個Thread來允許該示例“等待”序列完全播放。 如果您是從UI框架執行此操作,那么您可以在沒有額外開銷的情況下離開。

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.LineEvent;
import javax.sound.sampled.LineListener;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;

public class Test {

    public static void main(String[] args) throws InterruptedException {
        try {
            new Test();
        } catch (UnsupportedAudioFileException | IOException | LineUnavailableException ex) {
            ex.printStackTrace();
        }
    }

    public Test() throws UnsupportedAudioFileException, IOException, LineUnavailableException {
        Sound longBeep = new Sound(new File(...));
        Sound shortBeep = new Sound(new File(...));

        List<Sound> message = new ArrayList<Sound>(9);
        message.add(shortBeep);
        message.add(shortBeep);
        message.add(shortBeep);
        message.add(longBeep);
        message.add(longBeep);
        message.add(longBeep);
        message.add(shortBeep);
        message.add(shortBeep);
        message.add(shortBeep);

        play(message);
    }

    public void play(List<Sound> message) {
        try {
            List<Sound> queue = new ArrayList<>(message);
            Transmit transmit = new Transmit(message);
            Thread thread = new Thread(transmit);
            thread.start();
            transmit.waitFor();
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
    }

    public class Transmit implements Runnable {

        private List<Sound> queue;
        private ReentrantLock lock;
        private Condition playCondition;

        public Transmit(List<Sound> message) {
            this.queue = new ArrayList<>(message);

            lock = new ReentrantLock();
            playCondition = lock.newCondition();
        }

        @Override
        public void run() {
            playNext();
        }

        public void waitFor() throws InterruptedException {
            lock.lock();
            if (!queue.isEmpty()) {
                try {
                    playCondition.await();
                } finally {
                    lock.unlock();
                }
            } else {
                lock.unlock();
            }
        }

        protected void playNext() {
            if (queue.size() > 0) {
                lock.lock();
                try {
                    System.out.println("Play Next");
                    Sound sound = queue.remove(0);
                    sound.addLineListener(new LineListener() {
                        @Override
                        public void update(LineEvent event) {
                            if (event.getType().equals(LineEvent.Type.STOP)) {
                                sound.removeLineListener(this);
                                System.out.println("Audio Completed");
                                playNext();
                            }
                        }
                    });
                    sound.play();
                } finally {
                    lock.unlock();
                }
            } else {
                lock.lock();
                try {
                    playCondition.signalAll();
                } finally {
                    lock.unlock();
                }
            }
        }

    }

    public class Sound {

        private Clip audio;

        public Sound(AudioInputStream audioInputStream) throws LineUnavailableException, IOException {
            audio = AudioSystem.getClip();
            audio.open(audioInputStream);
        }

        public Sound(File file) throws UnsupportedAudioFileException, IOException, LineUnavailableException {
            this(AudioSystem.getAudioInputStream(file));
        }

        public Sound(URL url) throws UnsupportedAudioFileException, IOException, LineUnavailableException {
            this(AudioSystem.getAudioInputStream(url));
        }

        public Sound(InputStream stream) throws UnsupportedAudioFileException, IOException, LineUnavailableException {
            this(AudioSystem.getAudioInputStream(stream));
        }

        public void close() {
            Objects.requireNonNull(audio, "Audio Clip has not been initalised");
            audio.close();
        }

        public void play() {
            Objects.requireNonNull(audio, "Audio Clip has not been initalised");
            audio.setFramePosition(0);
            audio.start();
        }

        public void addLineListener(LineListener listener) {
            Objects.requireNonNull(audio, "Audio Clip has not been initalised");
            audio.addLineListener(listener);
        }

        public void removeLineListener(LineListener listener) {
            Objects.requireNonNull(audio, "Audio Clip has not been initalised");
            audio.removeLineListener(listener);
        }
    }

}

如果你想知道序列什么時候完成,而不會遇到使用waitFor方法的麻煩,那么為一個生成“完成序列”事件的Transmit類添加一個觀察者並不困難,但是我會把它留給你實施

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM