MIDI Java生成混乱的声音

时间:2014-09-16 02:51:34

标签: java audio midi synthesizer

我一直在一个项目中工作,我需要在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();

3 个答案:

答案 0 :(得分:1)

正如ntabee所说,Track.get(n)会在赛道中返回n个事件;要及时获取事件,您必须比较事件&#39;手动。

此外,Thread.sleep()不是很精确,可以等待比预期更长的时间。 这些错误会加起来。


要实时更改MIDI信息,请告诉音序器播放您自己的Receiver,然后对事件执行任何操作并将其传递给真实的&#39; Receiver

答案 1 :(得分:0)

至少,您的代码看起来像 tickTime毫秒时打开/关闭某些内容。期。 track.get(tick)只返回跟踪中的tick个事件, {{1>}当前的事件。 如果您的目标只是播放声音,那么Java会为其提供高级API,例如, http://www.jsresources.org/examples/midi_playback_and_recording.html

答案 2 :(得分:0)

我决定使用音序器。我不知道,但是&#34;开始&#34;方法在新线程中运行,当它仍在运行时,我可以将我想要的每个乐器静音,这正是我想要的。 谢谢你的答案!