2017-06-06 7 views
3

私は現在、単純なモールスコードトランスレータを行っています。私は自分のコードで長いビープ音を ' - 'に、短いビープ音を '。'で演奏したいと思います。もちろん、これはお互いの後で行うべきです。しかし、私のプログラムは現在、すべてを一度に再生しています。私は間違って何をしていますか?私はお互いの後に音を鳴らしたいが、最初の音が終わるまで待つようにしたい。どうすればいいのですか?

私は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); 
    } 
} 
+0

私は' List'にすべてのオーディオファイルを置いていますが、 'LineListener'を使って行が停止した時を監視し、次のオーディオを再生し、再生するまでオーディオがなくなるまで再生する - [この例](https://stackoverflow.com/questions/34758718/panel-fails-to-show-up-concurrently-with-sound-file- in-java-swing/34758778#34758778)は、少なくともLineListenerの使い方を示しています – MadProgrammer

+0

私はまた、GUIのメインスレッド – MadProgrammer

答えて

1

これはJava Sound APIの使用をするが、基本的な考え方はあまりにも長い間、「バックプレーの終わり」を提供通知として、ほとんどのオーディオライブラリのために実行可能でなければなりません。

これは、再生したいシーケンスをキューに入れ、次のトーンを再生し、完了するまで待って次の再生を待ち、キューにトーンがなくなるまで続きます。

AudioClipは独自のスレッドで再生されるため、この例ではもう1つの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クラスのにオブザーバーを追加するために難しいことではありません"イベントを実装するためにそれを残しておきます

+0

のコンテキスト内で 'Thread.sleep'を使用することに非常に苦労しています。何らかの理由でプログラムがオーディオファイルを見つけることができません。ディレクトリにそのようなファイルはありませんが、そこにあり、古いコードと同じディレクトリが使用されています。 – Dihre

+0

さて、私は現在の作業ディレクトリにオーディオを置くことによってコードをテストしました。 'File#exists'を使ってファイルが – MadProgrammer

+0

だと思っていることを確認してみてください!オーディオファイルは.wav形式である必要があります.mp3は機能していないようです。助けをありがとう@MadProgrammer – Dihre

関連する問題