2014-04-01 37 views
1

我需要從MIDI文件中獲取速度值。我發現,該set_tempo命令具有值0x51,所以我有這一段代碼:如何從MetaMessage.getData()返回的字節數組中獲取整數值?

for (int i = 0; i < tracks[0].size(); i++) { 
     MidiEvent event = tracks[0].get(i); 
     MidiMessage message = event.getMessage(); 
     if (message instanceof MetaMessage) { 
      MetaMessage mm = (MetaMessage) message; 
      if(mm.getType()==SET_TEMPO){ 
       // now what? 
       mm.getData(); 
      } 
     } 
    } 

但該方法的getData()返回一個字節數組!我怎樣才能把它轉換成正常的人形,a.k.a.整數? 我讀過它的格式是這樣存儲的:「tt tt tt」,但是整個大/小端,有符號/無符號和可變長度的東西使它太混亂了。

回答

5

天寶是3個字節的大端整數和位,每分鐘的計算公式爲
BPM = 60,000,000/(tt tt tt)

byte[] data = mm.getData(); 
int tempo = (data[0] & 0xff) << 16 | (data[1] & 0xff) << 8 | (data[2] & 0xff); 
int bpm = 60000000/tempo; 
1

我用:

mpq = ((data[0] & 0x7f) << 14) | ((data[1] & 0x7f) << 7) | (data[2] & 0x7f); 

其中mpq代表每季度微秒每個節拍的音符或微秒。

這樣做的推理是Midi消息僅在每個字節中使用7位來表示數據。還應該注意的是,在Java中,一個字節數據類型(其中數據是一個數組)是一個有符號整數,並且只有7個數據位的空間。

由於做這個職位,我不得不從MIDI協會如下回應:

參數號(TTTTTT)是一個24位無符號整數,在大端格式。

「Set tempo」是一個元事件,屬於SMF規範。它僅適用於標準MIDI文件,並且與其他元事件不應該通過電線實時傳輸一樣。另一方面,令您感到困惑的數據字節描述適用於有線協議。

因此,此主題的原始答案是正確的。

+0

兩種解決方案都不能提供相同的結果嗎?如果是這樣,我不明白你的解決方案的優點是什麼。 – Leprechaun

+0

結果大約相差4倍。即使第一個結果除以4,它也會與第二個結果相差最多3%,具體取決於位的模式和每個數據項中符號位的存在。測試的方法是檢查播放或錄製各種節奏的音樂的持續時間。 – user8182116

+0

這很奇怪。實際上,我幾年前在我的學士論文中使用了接受的答案。它提供了正確的結果,當打印和評估與估計的基本面相關的一些midi數據時。錄音的長度也等於繪製和評估的MIDI信號。曲目長達幾分鐘,因此立即會注意到4倍的差異。 如果你所說的是真的,我唯一能解釋的方法是隻能在特定的速度值下才能觀察到。那是對的嗎? – Leprechaun

相關問題