2011-05-12 75 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以指它在匿名接口实现。

希望有所帮助。