有效地解释串行数据

时间:2011-12-07 18:57:55

标签: c++ performance serial-port processing-efficiency

我正在开发一个从外部USB设备读取MIDI数据的c ++项目。该程序应该调用某些功能,具体取决于USB设备上的哪个推子/旋钮/按钮是shiftet / rotate / press(例如vol + - 或静音/取消静音通道)。

我想出找到哪个推子/旋钮/按钮被改变的唯一方法是使用一个非常大的开关语句,基本上检查每个传入的midi事件。

看起来像这样:

switch(MidiMessage.get2ndByte()){

    case 1 : cout << "Fader 1 Value : " << MidiMessage.get3rdByte() << endl;  
    case 2 : cout << "Fader 2 Value : " << MidiMessage.get3rdByte() << endl;  
    case 10 : cout << "Button 1 Value : << "MidiMessage.get3rdByte() << endl;  
    ...
    ...
    ...
}

有没有更有效/更聪明的方法来做到这一点?

2 个答案:

答案 0 :(得分:2)

由于你的切换是在一个字节上完成的(因此只有256个不同的值;我很确定MIDI文件基于8位字节),最好的选择可能是使用一个简单的函数指针数组:

typedef void (*MidiAction)(MidiMessageType& message);

action_fader_1(MidiMessageType& message)
{
  std::cout << "Fader 1 Value : " << message.get3rdByte() << std::endl;
}

action_fader_2(MidiMessageType& message)
{
  std::cout << "Fader 2 Value : " << message.get3rdByte() << std::endl;
}

...

MidiAction midi_actions[256] = {
   /*  0 */ action_whatever,
   /*  1 */ action_fader_1,
   /*  2 */ action_fader_2,
   ...
   /* 10 */ action_button_1,
   ...
};

...

// this goes where your switch statement was:
midi_actions[MidiAction.get2ndByte()](MidiAction);

这个数组只使用1KB(32位平台)或2KB(64位平台),保证了恒定的时间查找,没有隐藏的开销,并且可能你的编译器在内部实现了你的big switch语句作为查询表(所以只有你得到的开销是一个额外的函数调用。)

请注意,如果字节值无效,则数组条目应指向显式错误函数(而不是简单的0),因此您的程序可以正常处理错误。

答案 1 :(得分:1)

大多数编译器会将这样的大型开关编译成跳转表(或者查找简单值的表),所以我建议你保留开关。

如果案例之间的唯一区别是前缀字符串,我建议改为做这样的事情:

const char *msg; // or std::string if you prefer

switch(MidiMessage.get2ndByte()){

    case 1 : msg = "Fader 1 Value : "; break;
    case 2 : msg = "Fader 2 Value : "; break;
    case 10: msg = "Button 1 Value : "; break;
    default: msg = "?"; break;
}

cout << msg << MidiMessage.get3rdByte() << endl;