在 MIDI 播放线程上降低 CPU

Lowering CPU on MIDI playback thread

下面的函数是 运行 在分离的 std::thread 上。代码本身是使用 JUCE API(因此 Array<> object & MidiMessage)编写的。

 void triggerMidiMessages(Array<Array<MidiMessage>> messageBundle) 
{
    //for each group of messages (bar) within the bundle
    for(int bar = 0; bar < messageBundle.size(); bar ++)
    {   
        //store our message from the bundle for playback
        Array<MidiMessage> messages;
        messages.clear();
        messages = messageBundle[bar];

        //intialise start time
        double timestart = Time::getMillisecondCounterHiRes();

        //for each midi inside a single "gene"
        for(int i = 0; i <= messages.size();)
        {
            double elapsedTime = Time::getMillisecondCounterHiRes() - timestart;

            //output message whens appropriate
            if(elapsedTime > messages[i].getTimeStamp())
            {
                //output this message
                masterMidiOutput->sendMessageNow(messages[i]);

                //increment through the array
                i++;
            }
        }
    }
}

我需要实时输出 MIDI 消息,但不必 运行 通过循环条件以至于 CPU 运行 非常热。

有什么想法吗?我对如何以不需要用计时器不断检查的顺序播放消息感到困惑。

提前致谢。

//=========================================== ========================== 更新尝试休眠线程...

void triggerMidiMessages(Array<Array<MidiMessage>> messageBundle)
{
    //for each group of messages (bar) within a bundle
    for(int bar = 0; bar < messageBundle.size(); bar ++)
    {   
        //store our message from the bundle for playback
        Array<MidiMessage> messages;
        messages.clear();
        messages = messageBundle[bar];
        }

        //intialise start time
        double previousTimeStamp = 0;

        //for each midi inside a single "gene"
        for(int i = 0; i <= messages.size();)
        {
            //fire off all note on messages
            while(messages[i].isNoteOn())
            {
                masterMidiOutput->sendMessageNow(messages[i]);
                i++; //increment to the next
            }

            //fire off all note off messages
            while(!messages[i].isNoteOn())
            {
                masterMidiOutput->sendMessageNow(messages[i]);
                 i++; // do the next one

                //if the next message is back to a note on command
                if(messages[i+1].isNoteOn() == true)
                {
                    //sleep for x amount of time
                    int sleepTime = messages[i].getTimeStamp() - previousTimeStamp;
                    std::this_thread::sleep_for(std::chrono::milliseconds(sleepTime));
                    previousTimeStamp = messages[i].getTimeStamp();
                }
            }

        }
    }
}

要停止线程内的构建,最好打开和关闭计时器对象并逐条触发每条消息。

广播消息 (Action Broadcaster ) 可以用来跟踪索引。

这里有一些示例代码来给出总体思路:

MIDIThing::MIDIThing ()
{
    startTimer(1); //start a timer
}

void MIDIThing::start ()
{
    playstate = 1;
    startTime = Time::getCurrentTime().toMilliseconds();
}

void MIDIThing::timerCallback()
{
    if (playstate == 1) {
        Time::getMillisecondCounterHiRes();
        int64 target;
        if (Time::getCurrentTime().toMilliseconds() > target) {
            //fire off the message
        }

        //ended (possibly on a condition)
        ActionBroadcaster::sendActionMessage(FINISHED_PLAYBACK);
    }
}