2017-05-31 22 views
0

私はmidiファイルの最初のトラックからメロディのテンポを抽出し、それをノートイベントを含む残りのトラックに適用しようとしています。トラック1から抽出したテンポをMIDIファイルの他のトラックにどのように適用するのですか?

ぼんやりと私はnoteOn()のメッセージの後に一定時間毎にメモを再生した後にThread.sleep()メソッドを置き換えようとしていました。だから私はトラック全体のテンポを失っている。

先に質問した質問How does Midi TEMPO message apply to other tracks?から最初のトラックからテンポ情報を抽出するのに成功しましたが、残りのトラックには適用できません。

これを実行する特定の機能はありますか?私は検索しようとしましたが見つかりませんでした。

これは参考用です。

 int trackNumber = 0; 

    for (Track track : sequence.getTracks()) { 

     trackNumber++;   
     System.out.println(); 
     for (int i=0; i < track.size(); i++) { 

      MidiEvent event = track.get(i); 
      MidiMessage message = event.getMessage(); 

      if (message instanceof MetaMessage) { 

      MetaMessage mm = (MetaMessage) message; 
      if(mm.getType()==SET_TEMPO){ 

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

      if (message instanceof ShortMessage) { 
       ShortMessage sm = (ShortMessage) message; 
       if (sm.getCommand() == NOTE_ON) { 

        int key = sm.getData1(); 
        int velocity = sm.getData2();      
        channels[0].noteOn(key,velocity); 
        Thread.sleep(280);//Pays all the note for fixed duration  
       } 
       else if (sm.getCommand() == NOTE_OFF) { 

        int key = sm.getData1(); 
        int velocity = sm.getData2(); 
        channels[0].noteOff(key); 

       } 
      } 
     } 

     System.out.println(); 
    } 
} 
+0

最初のトラックからSetTempoイベントをクローンし、[add](https://docs.oracle.com/javase/7/docs/api/javax/sound/midi/Track.html#add(javax.sound。 midi.MidiEvent))インスタンスを同じタイムスタンプを持つ他のトラックに複製します。 – Maxim

答えて

0

複数のトラックのイベントが同時に発生するため、トラックを別々に処理することはできません。

あなたはどちらか

  • は、1つのリストにすべてのイベントを配置する必要があり、かつ(同じタイムスタンプを持つイベントは彼らの順序を維持し、安定したソートアルゴリズムを使用していることが、確認してください)、そのタイムスタンプによってそれらを並べ替えます。または
  • には、各トラックの現在の位置があり、どのイベントが次のイベントであるかを判断するときは、すべてのトラックを検索して、最もタイムスタンプの小さい未使用イベントを探します。

再生中にテンポが変化する可能性があるので、bpmの値では不十分です。 How to correctly convert MIDI ticks to milliseconds?およびHow can I parse a tempo of midi using Java?を参照してください。

+0

私が理解したところでは、イベントをタイムスタンプ値に従ってソートした後、それを評価したデルタ時間値をパラメータとして 'Thread.sleep(millisec)'関数に渡す必要があります。これがあなたが説明しようとしているものであれば教えてください。ありがとう。 – BitWriter

+0

ティックはミリ秒単位ではなく、デルタタイムは1つのトラック内のイベント間にあります。ソート後、隣接するイベント間のタイマー間隔を再度計算する必要があります。 –

関連する問題