降低MIDI播放线程上的CPU

时间:2018-02-21 13:59:43

标签: c++ multithreading cpu-usage midi juce

以下函数在分离的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();
                }
            }

        }
    }
}

1 个答案:

答案 0 :(得分:0)

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

然后可以使用广播消息(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);
    }
}