2017-10-10 40 views
0

我試圖得到一個MIDI序列的磁道數:的Java MIDI Sequence.getTracks()錯號碼

File file = new File(strSource); 
Sequence sequence = MidiSystem.getSequence(file); 
int numTracks = sequence.getTracks().length; 

...其中strSource是我的。中期的完整路徑+文件名文件。 numTracks是1,但.mid文件有16個軌道(就像我在另一個MIDI編輯器中打開它時看到的那樣)。文件類型爲0.

我在某處讀取類型爲0的文件不能在同一個通道中有多個軌道。在這種情況下,所有曲目都被強制進入單曲。那是對的嗎?我怎樣才能避免這種情況?

回答

0

看起來你是對的,類型0的文件只能保存一個。 Here你有一些信息。

不可能從類型0文件中提取每個單獨的軌道。

檢查MIDI文件類型,如果外部MIDI編輯器可以檢測到多個音軌,它可以是類型1或類型2文件,即使擴展名不匹配。

+0

其他編輯器本身創建的多個曲目。它似乎搜索程序更改消息 – paul

+0

因此,sequence.getTracks()沒有任何問題,對吧? 只是0類文件的問題 – alseether

+0

是的,類型0文件是限制。另一種工具(收割機)與我的小型MIDI工具(Anvil Studio)一樣:都從單一類型0軌道分離出來,並根據樂器編號創建多個軌道。 – paul

0

我用六角工具查看了文件... 它實際上只有一個軌道。

其他編輯器自己創建多個曲目。它似乎搜索節目更改消息,然後將事件放入新曲目。

1

我已編程的小功能,一個類型#0序列轉換到類型#1序列

/** 
* Make multiple tracks from file0 track 
* @param in : Sequence with single track 
* @return Multiple track sequence 
*/ 
private Sequence extractFile0Tracks (Sequence in) throws InvalidMidiDataException 
{ 
    Track inTrack = in.getTracks()[0]; 
    HashMap<Integer, ArrayList<MidiEvent>> msgMap = new HashMap<>(); 

    // Distribute events per channel to ArrayList map 
    for (int i = 0; i < inTrack.size(); i++) 
    { 
     MidiEvent event = inTrack.get(i); 
     MidiMessage message = event.getMessage(); 
     if (message instanceof ShortMessage) 
     { 
      ShortMessage sm = (ShortMessage) message; 
      int channel = sm.getChannel() + 1; 
      ArrayList<MidiEvent> msgList = msgMap.computeIfAbsent(channel, k -> new ArrayList<>()); 
      msgList.add(event); 
     } 
    } 

    // Create sequence with multiple tracks 
    Sequence newSeq = new Sequence(in.getDivisionType(), in.getResolution()); 
    for (ArrayList<MidiEvent> msgList : msgMap.values()) 
    { 
     Track tr = newSeq.createTrack(); 
     for (MidiEvent m1 : msgList) 
      tr.add(m1); 
    } 

    return newSeq; 
}