0

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

我想出找出哪个推子/旋钮/按钮被更改的唯一方法是使用一个相当大的 switch 语句,它基本上检查每个传入的 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;  
    ...
    ...
    ...
}

没有更有效/更智能的方法来做到这一点吗?

4

2 回答 2

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 位平台),提供有保证的恒定时间查找,没有隐藏的开销,并且可能你的编译器在内部将你的大 switch 语句实现为查找表(所以你得到的唯一开销是一个额外的函数调用)。

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

于 2012-01-08T17:45:54.333 回答
0

Most compilers will compile a large switch like that into a jump table (or a table lookup for simple values), so I would suggest you keep the switch.

If the only difference between the cases is the prefix string, I would suggest doing something like this instead:

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;
于 2012-01-08T18:10:09.583 回答