2

私はJavaのMIDIファイルで各楽器を操作する必要があるプロジェクトに取り組んできました。次に、シーケンスの各トラックから各 MIDI イベントを取得し、レシーバーに送信することにしました。その後、スレッドは各ティックが続く時間を待ってから、次のティックでもう一度実行します。問題は、楽器の音とその順番がめちゃくちゃになってしまうことです。私も各トラックを単独で実行しようとしましたが、それでもめちゃくちゃです! コード:

    Sequence    sequence        = MidiSystem.getSequence(new File(source));
    Synthesizer synth           = MidiSystem.getSynthesizer();

    //Gets a MidiMessage and send it to Synthesizer
    Receiver    rcv             = synth.getReceiver();

    //Contains all tracks and events from MIDI file
    Track[]     tracks          = sequence.getTracks();
    synth.open();

    //If there are tracks
    if(tracks != null)
    {
        //Verify the division type of the sequence (PPQ, SMPT)
        if(sequence.getDivisionType() == Sequence.PPQ)
        {
            int     ppq         = sequence.getResolution();
            //Do the math to get the time (in miliseconds) each tick takes 
            long    tickTime    = TicksToMiliseconds(BPM,ppq);
            //Returns the number of ticks from the longest track
            int     longestTrackTicks   = LongestTrackTicks(tracks);

            //Each iteration sends a new message to 'receiver'
            for(int tick = 0; tick < maiorTick ; tick++)
            {   
                //Iteration of each track
                for(int trackNumber = 0; trackNumber < tracks.length; trackNumber++)
                {
                    //If the number of ticks from a track isn't already finished
                    //continue
                    if(tick < tracks[trackNumber].size())
                    {
                        MidiEvent ev = tracks[trackNumber].get(tick);
                        rcv.send(ev.getMessage(),-1);
                    }
                }
                Thread.sleep(tickTime);
            }

        }
    }
    synth.close();
4

3 に答える 3

1

ntabee が言ったように、トラックの th イベントをTrack.get(n)返します。n時間ごとにイベントを取得するには、イベントの時間を手動で比較する必要があります。

さらに、Thread.sleep()あまり正確ではなく、必要以上に長く待つことができます。これらのエラーが加算されます。


MIDI メッセージをリアルタイムで変更するには、シーケンサーに独自の を再生するように指示してReceiverから、イベントに対して必要なことを何でも実行し、それらを 'real' に渡しますReceiver

于 2014-09-16T07:32:23.993 に答える
0

シーケンサーを使うことにしました。知りませんでしたが、「開始」メソッドは新しいスレッドで実行され、実行中に必要な各楽器をミュートできます。それはまさに私が望んでいたことです。答えてくれてありがとう!

于 2014-09-16T18:19:07.063 に答える
0

少なくとも、コードはミリ秒ごとに何かを鳴らしたり鳴らしたりするように見えます。 tickTime限目。 の瞬間のイベントではなく、トラック内の - 番目track.get(tick)のイベントを返すだけです。あなたの目標が単にサウンドを再生することである場合、Java はそのための高レベル API を提供しますticktick

于 2014-09-16T03:13:12.410 に答える