2015-10-18 28 views
0

我試圖找到任何有關這方面的信息,但我一直沒有找到任何幫助。Java的midi程序選擇奇怪的行爲

我試圖製作一個程序,用於生成一個midi文件,其中包含兩個使用不同樂器(程序)一起播放的樂器。我一直在使用一個示例程序: http://www.cs.cornell.edu/courses/cs211/2008sp/examples/MidiSynth.java.txt 作爲模板,但是當我試圖人爲地製造了MIDI事件(而不是生成它們與示例程序的合成器飛),所產生的MIDI文件不似乎在意我已經切換了節目,對於文件中的每個音符使用最後一個改變後的節目,由兩個midi音軌組成,儘管我已經將節目改變數據保存到兩個音軌中。我已經貼了代碼爲我的程序beneith:

import java.io.File; 
import java.io.IOException; 

import javax.sound.midi.Sequence; 
import javax.sound.midi.Soundbank; 
import javax.sound.midi.Sequencer; 
import javax.sound.midi.Synthesizer; 
import javax.sound.midi.Instrument; 
import javax.sound.midi.MidiChannel; 
import javax.sound.midi.MidiEvent; 
import javax.sound.midi.MidiMessage; 
import javax.sound.midi.MidiSystem; 
import javax.sound.midi.ShortMessage; 
import javax.sound.midi.Track; 
import javax.sound.midi.InvalidMidiDataException;  

public class MidiTest2 
{ 
    /* This velocity is used for all notes. 
    */ 
    private static final int VELOCITY = 64; 
     final int PROGRAM = 192; 
     final int NOTEON = 144; 
     final int NOTEOFF = 128; 

     long startTime; 
     Sequence sequence; 
     Synthesizer synthesizer; 
     Sequencer sequencer; 
     Instrument instruments[]; 
     ChannelData channels[]; 
     ChannelData cc; 
     //int instrumentCounter = 0; 

     Track track; 

     MidiTest2(){ 
      try{ 
       if(synthesizer == null){ 
        if((synthesizer = MidiSystem.getSynthesizer()) == null){ 
         System.out.println("getSynthesizer() failed"); 
         return; 
        } 
       } 
       synthesizer.open(); 
       sequencer = MidiSystem.getSequencer(); 
       sequence = new Sequence(Sequence.PPQ, 10); 

      }catch(Exception e){ 
       e.printStackTrace(); 
       return; 
      } 

      Soundbank sb = synthesizer.getDefaultSoundbank(); 
      if(sb != null){ 
       instruments = synthesizer.getDefaultSoundbank().getInstruments(); 
       synthesizer.loadInstrument(instruments[0]); 
      } 

      MidiChannel midiChannels[] = synthesizer.getChannels(); 
      channels = new ChannelData[midiChannels.length]; 

      for(int i = 0; i < channels.length;++i){ 
       channels[i] = new ChannelData(midiChannels[i], i); 
      } 

      cc = channels[0]; 

     } 

     public void createShortEvent(int type, int num){ 
      ShortMessage message = new ShortMessage(); 
      try{ 
       long millis = System.currentTimeMillis() - startTime; 
       long tick = millis * sequence.getResolution()/500; 
       message.setMessage(type+cc.num, num, cc.velocity); 
       System.out.println("Type: " + message.getCommand() + ", Data1: " + message.getData1() + ", Data2: " + message.getData2() + ", Tick: " + tick); 

       MidiEvent event = new MidiEvent(message, tick); 
       track.add(event); 
      }catch (Exception e){ 
       e.printStackTrace(); 
      } 
     } 

     public void createShortEvent(int type, int num, int eventTime){ 
      ShortMessage message = new ShortMessage(); 
      try{ 
       //long millis = System.currentTimeMillis() - startTime; 
       long tick = eventTime * sequence.getResolution(); 
        message.setMessage(type+cc.num, num, cc.velocity); 

       System.out.println("Type: " + message.getCommand() + ", Data1: " + message.getData1() + ", Data2: " + message.getData2() + ", Tick: " + tick); 

       MidiEvent event = new MidiEvent(message, tick); 
       track.add(event); 
      }catch (Exception e){ 
       e.printStackTrace(); 
      } 
     } 

     public void saveMidiFile(){ 
      try { 
       int[] fileTypes = MidiSystem.getMidiFileTypes(sequence); 
       if (fileTypes.length == 0) { 
        System.out.println("Can't save sequence"); 
       } else { 
        if (MidiSystem.write(sequence, fileTypes[0], new File("testmidi.mid")) == -1) { 
         throw new IOException("Problems writing to file"); 
        } 
       } 
      } catch (SecurityException ex) { 

      } catch (Exception ex) { 
       ex.printStackTrace(); 
      } 
     } 

     void run(){ 
      //System.out.println("sequence: " + sequence.getTracks().length); 
      createNewTrack(0); 
      createShortEvent(NOTEON, 60, 2); 
      createShortEvent(NOTEOFF, 60, 3); 
      createShortEvent(NOTEON, 61, 3); 
      createShortEvent(NOTEOFF, 61, 4); 
      createShortEvent(NOTEON, 62, 4); 
      createShortEvent(NOTEOFF, 62, 5); 
      createShortEvent(NOTEON, 63, 5); 
      createShortEvent(NOTEOFF, 63, 6); 

      createNewTrack(5); 

      createShortEvent(NOTEON, 50, 1); 
      createShortEvent(NOTEOFF, 50, 5); 

      playMidiFile(); 
      saveMidiFile(); 
     } 

     void printTrack(int num){ 
      Track tempTrack = sequence.getTracks()[num]; 
      System.out.println(tempTrack.get(0).getTick()); 
     } 

     void playMidiFile(){ 
      try{ 
       sequencer.open(); 
       sequencer.setSequence(sequence); 
      }catch (Exception e){ 
       e.printStackTrace(); 
      } 
      sequencer.start(); 
     } 

     void createNewTrack(int program){ 
      track = sequence.createTrack(); 
      programChange(program); 
     } 

     void programChange(int program){ 

      cc.channel.programChange(program); 
      System.out.println("program: " + program); 
      startTime = System.currentTimeMillis(); 
      createShortEvent(PROGRAM, program); 
     } 

    public static void main(String[] args) 
    { 
      MidiTest2 mt = new MidiTest2(); 
      mt.run();     
    } 

} 

的ChannelData級(即沒有做任何事情,但我想我會發布它的完整性起見):

public class ChannelData { 
    MidiChannel channel; 
    boolean solo, mono, mute, sustain; 
    int velocity, pressure, bend, reverb; 
    int row, col, num; 

    public ChannelData(MidiChannel channel, int num) { 
     this.channel = channel; 
     this.num = num; 
     velocity = pressure = bend = reverb = 64; 
    } 

    public void setComponentStates() { 

    } 

} 

在我試着用原聲鋼琴音色創作5個音符,用電鋼琴音色創作1個音符。但是,即使我在切換樂器之前創建了一個新的軌道,所有音符都會用電子鋼琴的聲音播放。

我一直試圖弄清楚現在5個小時或什麼,我都沒有想法。

+0

「我以爲我會爲了完整而張貼它」如果它不相關,請不要發佈它。同樣,這隻會發生在5個音符,還是隻發生在1? http://www.stackoverflow.com/help/mcve我並不想固執,只是在這裏有很多代碼需要通過。 –

+0

是的,我明白你的觀點。我的意思是,以使它更容易爲任何人試圖剛剛獲得運行代碼在這種情況下,我認爲這將是更好的,如果它是完整的。儘管我知道它的工作原理,但事實證明,我認爲這些代碼實際上並不重要。不管怎麼說,還是要謝謝你! – dipetriantonio

回答

0

音軌可以幫助您組織活動的自己的節目,但它們不會以任何方式影響合成器。

要能夠具有不同的設置,您必須使用不同的通道。

+0

我似乎沒有把握中音和中音的區別。對於其他人可能有同樣的問題,有什麼解決的是,當發送MIDI消息,我哈德的頻道號碼添加到消息命令類型,即信道3的節目變化是192 + 3。當我在節目改變之前這樣做了,當然還有那些應該在該頻道上播放的所有音符,一切都奏效了。謝謝! – dipetriantonio