2011-01-13 18 views
3

複数のMIDIノートをコレクションに追加できるアプリケーションを作成しています。ここから「再生」ボタンを押すと、アプリケーションは各ノートを繰り返してスピーカーで再生します。Java MIDIトラックで重複するノートを再生する

私は、ユーザがリストに追加するノートの詳細を保持するMIDIMessageクラスを作成しました。詳細はピッチ、ベロシティ、ディレイ、およびチャンネルです。

これらのメッセージはそれぞれ、タイプがMIDIMessageのArrayListに保存されます。

次に、イテレータオブジェクトにコレクションのイテレータをアタッチし、まだ使用されていないコレクション内の要素が残っているときにサウンドを再生します。

何らかの理由で、コレクションに1つの音符だけを追加しても、常に同じ音程、長さ、および速さで2つの音符が再生されます。

また、コレクションにいくつの音符があるにしても、各音符は同時に演奏されます。その間に何らかの遅延があると想定しました。続き

は私が現時点で使用していますコードです:

MIDIMessage:

package javatest; 

public class MIDIMessage 
{ 
    private int pitch; 
    private int velocity; 
    private int channel; 

    public MIDIMessage(int p, int v, int c) 
    { 
     pitch = p; 
     velocity = v; 
     channel = c; 
    } 

    public int GetPitch() 
    { 
     return this.pitch; 
    } 

    public int GetVelocity() 
    { 
     return this.velocity; 
    } 

    public int GetChannel() 
    { 
     return this.channel; 
    } 
} 

コレクションにメモを追加する:ノートを演奏

public void AddToList() 
    { 
     int channel = jComboBoxChannels.getSelectedIndex(); 
     int pitch = jComboBoxPitch.getSelectedIndex(); 
     int velocity = ((Integer)jSpinnerVelocity.getValue());  
     collection.add(new MIDIMessage(pitch,velocity,channel)); 
    } 

try 
     { 
      jButton1.setEnabled(false); 
      Sequencer sequencer = MidiSystem.getSequencer(); 
      sequencer.open(); 
      Sequence sequence = new Sequence(Sequence.PPQ,1); 
      Track track = sequence.createTrack(); 

      Iterator itr = collection.iterator(); 
      int i = 0; 

      while(itr.hasNext()) 
      { 
       MIDIMessage msg = (MIDIMessage)itr.next(); 

       ShortMessage noteOnMsg = new ShortMessage(); 
       //Signal/Channel/Pitch/Velocity 
       noteOnMsg.setMessage(ShortMessage.NOTE_ON, msg.GetChannel(),msg.GetPitch(),msg.GetVelocity()); 

       ShortMessage noteOffMsg = new ShortMessage(); 
       //Signal/Channel/Pitch/Velocity 
       noteOffMsg.setMessage(ShortMessage.NOTE_OFF,msg.GetChannel(),msg.GetPitch(),msg.GetVelocity()); 

       track.add(new MidiEvent(noteOnMsg,0)); 
       track.add(new MidiEvent(noteOffMsg,1)); 
       //i = i+1; 
      } 

      sequencer.setSequence(sequence); 
      sequencer.setTempoInBPM(120); 
      sequencer.setLoopCount(1); 

      sequencer.start(); 

      Thread.sleep(1000); 
     } 

答えて

1

ノートが二回再生され、なぜ私はわからないんだけど、これは間違いなく間違っている:

  track.add(new MidiEvent(noteOnMsg,0)); 
      track.add(new MidiEvent(noteOffMsg,1)); 

あなたがhereを見ることができるように、MidiEventは、メッセージやMIDIティックで構成されています。ティック0には常にnoteOnMsgを追加し、ティック1にはnoteOffMsgを追加します。これは、複数の音符がすべて同時に再生される理由を説明するものです。代わりにこのような何かをしたい:

startTick = 0; 

while(itr.hasNext()) { 
    [...] 
    track.add(new MidiEvent(noteOnMsg,startTick)); 
    track.add(new MidiEvent(noteOffMsg,startTick + how_long_the_note_is_played)); 
    startTick += difference_between_this_note_and_the_next; 
    [...] 
} 

私は何をお使いのdelay手段わからないんだけど、あなたはここでそれを使うことができれば、私は代わりに、わかりやすい変数名を使用しています。あなたはMIDIを使用する必要があります

注ここティック - あなたはMIDIで秒を変換したい場合はダニ、this SO question(というかその答え)を参照してください:[?1つのMIDIでどのくらいティック]

式は60000/(BPM * PPQ) (ミリ秒)です。

+0

申し訳ありませんが、メモの再生時間と現在のメモと次のメモとの違いはどのようにわかりますか?また、遅延はエラーでした。私は古いソースファイルのC/Pコードでした。 –

+0

*音符の長さと、現在の音符と次の音符の違いを定義します。 "ビート"ごとにノートを演奏したい場合は、両方の変数に 'Sequence.PPQ'を使ってみてください。 – schnaader

+0

私が言っていることは、ノートの長さをどのように定義するのか分からないということです。長さを取得するために使用できる方法はありますか?たとえば、私は新しいMidiEvent(noteOnMsg、1).getTick)を呼び出すことができることに気付きました。私はMidiEventを別々に作成し、それをトラックに追加して、Tickを変数に設定できるようにする必要があると感じています。 –

関連する問題