2011-05-12 74 views
1

我寫了這個簡短的程序來學習javax.sound.midi系統。這是使用Java 6.輸出如預期的那樣(一系列由Sequencer事件觸發的System.out.println()字符串),但問題是,在最後的聲音效果之後,程序停留在循環中, t按預期終止。終止Java Midi輸出

誰能告訴如何解決這個問題?感謝您的幫助:

import javax.sound.midi.MidiEvent; 
import javax.sound.midi.ShortMessage; 
import javax.sound.midi.InvalidMidiDataException; 
import javax.sound.midi.ControllerEventListener; 
import javax.sound.midi.Sequencer; 
import javax.sound.midi.MidiSystem; 
import javax.sound.midi.Sequence; 
import javax.sound.midi.Track; 
import javax.sound.midi.InvalidMidiDataException; 
import javax.sound.midi.MidiUnavailableException; 

class MySound { 

    public static MidiEvent makeEvent(int comd, int chan, int one, 
             int two, int tick) { 
     MidiEvent event = null; 

     try { 

      ShortMessage a = new ShortMessage(); 
      a.setMessage(comd, chan, one, two); 
      event = new MidiEvent(a, tick); 

     } catch (InvalidMidiDataException imde) { 

      imde.printStackTrace(); 
     }  

     return event; 
    } 
} 

class MyControllerListener implements ControllerEventListener { 

    public void controlChange(ShortMessage event) { 

     System.out.println("la"); 
    } 
} 

class SoundEffects { 

    public static void main(String[] args) { 

     try { 

      Sequencer seq = MidiSystem.getSequencer(); 
      seq.open(); 

      int[] events = { 127 }; 

      MyControllerListener mcl = new MyControllerListener(); 

      seq.addControllerEventListener(mcl, events); 

      Sequence s = new Sequence(Sequence.PPQ, 4); 

      Track t = s.createTrack(); 

      for (int i = 5; i < 60; i += 4) { 

       t.add(MySound.makeEvent(144, 1, i, 100, i)); 
       t.add(MySound.makeEvent(176, 1, 127, 0, i)); 
       t.add(MySound.makeEvent(128, 1, i, 100, i + 2)); 
      } 

      seq.setSequence(s); 

      seq.setTempoInBPM(220); 

      seq.start(); 

     } catch (InvalidMidiDataException imde) { 

      imde.printStackTrace(); 

     } catch (MidiUnavailableException mue) { 

       mue.printStackTrace(); 
     }  
    } 
} 

回答

4

您需要在音軌播放完畢後調用seq.close()。做到這一點的方法是添加一個元信息偵聽器,並在遇到類型爲0x2F的消息(這是非可選元消息「軌道結尾」)時調用close()。您的代碼會是這個樣子:

 seq.addMetaEventListener(new MetaEventListener() { 

      @Override 
      public void meta(MetaMessage metaMsg) { 
       if (metaMsg.getType() == 0x2F) { 
        seq.close(); 
       } 
      } 
     }); 

請注意,您需要在final改性劑添加到seq以指它在匿名接口實現。

希望有所幫助。