【问题标题】:MIDI Java generates messed soundMIDI Java 产生混乱的声音
【发布时间】:2017-10-31 18:39:37
【问题描述】:

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

【问题讨论】:

    标签: java audio midi synthesizer


    【解决方案1】:

    正如 ntabee 所说,Track.get(n) 返回轨道中的nth 事件;要按时间获取事件,您必须手动比较事件的时间。

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


    要实时更改 MIDI 消息,请告诉音序器播放到您自己的 Receiver,然后对事件执行任何您想要的操作并将它们传递给“真实的”Receiver

    【讨论】:

      【解决方案2】:

      至少,您的代码看起来像在 tickTime 毫秒时打开/关闭某些东西。时期。 track.get(tick) 只返回轨道中的tick-th 事件,不是tick此刻事件。 如果您的目标只是播放声音,Java 为其提供了高级 API,请参见例如http://www.jsresources.org/examples/midi_playback_and_recording.html

      【讨论】:

      • 问题是我需要在播放音乐时操作乐器。这就是为什么我以前没有使用音序器的原因。这个想法是在演奏时改变一些乐器的音量。此外,track.get(tick) 返回 MIDI 事件。Java 文档说 MIDI 事件具有 MIDI 消息,并且该消息包含有关该滴答声的所有信息。
      【解决方案3】:

      我决定使用音序器。我不知道,但是“开始”方法在一个新线程中运行,当它仍在运行时,我可以静音每个我想要的乐器,这正是我想要的。 感谢您的回答!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-06-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-05-13
        相关资源
        最近更新 更多