Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/303.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
MIDI Java生成混乱的声音_Java_Audio_Midi_Synthesizer - Fatal编程技术网

MIDI Java生成混乱的声音

MIDI Java生成混乱的声音,java,audio,midi,synthesizer,Java,Audio,Midi,Synthesizer,我一直在从事一个项目,在这个项目中,我需要用java操作MIDI文件中的每个乐器。 然后我决定从序列中的每个曲目中获取每个MIDI事件,并将其发送给接收器。在此之后,线程等待每个勾号持续的时间,然后使用下一个勾号再次执行该操作。 问题是:乐器的声音和顺序变得非常混乱。 我也试着单独演奏每一首曲子,但还是一团糟! 守则: Sequence sequence = MidiSystem.getSequence(new File(source)); Synthesiz

我一直在从事一个项目,在这个项目中,我需要用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();
Sequence-Sequence=MidiSystem.getSequence(新文件(源));
Synthesizer synth=MidiSystem.getSynthesizer();
//获取MIDI消息并将其发送到合成器
Receiver rcv=synth.getReceiver();
//包含MIDI文件中的所有曲目和事件
Track[]tracks=sequence.getTracks();
synth.open();
//如果有痕迹
如果(轨迹!=null)
{
//验证序列的划分类型(PPQ、SMPT)
if(sequence.getDivisionType()==sequence.PPQ)
{
int ppq=sequence.getResolution();
//计算每个刻度所用的时间(以毫秒为单位)
长滴答时间=滴答毫秒(BPM,ppq);
//返回最长轨迹的刻度数
int longestTrackTicks=longestTrackTicks(轨迹);
//每次迭代都会向“接收者”发送一条新消息
对于(int tick=0;tick
至少,您的代码看起来像是在每一个
滴答声
毫秒打开/关闭某个东西。时期
track.get(tick)
只返回曲目中的
tick
-第个事件,而不是
tick
时刻的事件。
如果您的目标只是播放声音,Java为其提供了一个高级API,如ntabee所说,
Track.get(n)
返回曲目中的第
n
个事件;要按时间获取事件,必须手动比较事件的时间

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



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

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

问题是我需要在音乐播放时操纵乐器。这就是我以前没有用音序器的原因。这个想法是改变一些乐器演奏时的音量。此外,track.get(tick)返回MIDI事件。Java文档说MIDI事件有MIDI消息,这一个包含关于该tick处声音的所有信息。