高效地解释串行数据 我正在研究一个C++项目,它从外部USB设备读取MIDI数据。根据USB设备上的哪个音量控制器/旋钮/按钮被移动/旋转/按下(例如vol+-或静音/取消静音通道),程序应该调用某些功能
我找出哪一个音量控制器/旋钮/按钮被更改的唯一方法是使用一个相当大的switch语句,它基本上检查每个传入的midi事件 看起来有点像这样:高效地解释串行数据 我正在研究一个C++项目,它从外部USB设备读取MIDI数据。根据USB设备上的哪个音量控制器/旋钮/按钮被移动/旋转/按下(例如vol+-或静音/取消静音通道),程序应该调用某些功能,c++,performance,serial-port,processing-efficiency,C++,Performance,Serial Port,Processing Efficiency,我找出哪一个音量控制器/旋钮/按钮被更改的唯一方法是使用一个相当大的switch语句,它基本上检查每个传入的midi事件 看起来有点像这样: switch(MidiMessage.get2ndByte()){ case 1 : cout << "Fader 1 Value : " << MidiMessage.get3rdByte() << endl; case 2 : cout << "Fader 2 Value : " &
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;
...
...
...
}
开关(MidiMessage.get2ndByte()){
案例1:cout因为切换是在一个字节上完成的(因此只有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);
typedef void(*MidiAction)(MidiMessageType&message);
动作\u音量控制器\u 1(MIDI消息类型和消息)
{
大多数编译器都会将这样的大型开关编译成跳转表(或简单值的表查找),因此我建议您保留该开关
如果两种情况之间的唯一区别是前缀字符串,我建议改为这样做:
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;
const char*msg;//或std::string,如果您愿意
开关(MidiMessage.get2ndByte()){
情况1:msg=“推子1值:”;中断;
案例2:msg=“推子2值:”;中断;
案例10:msg=“按钮1值:”;中断;
默认值:msg=“?”中断;
}
不可能是std::map;
,类似的方法,如volume up和down,可以共享同一个函数指针,但根据secondByte正确操作。对于C++11(或TR2),我更喜欢std::unordered\u map
,因为它具有常量查找(假设良好的哈希)不同于<代码> STD::map < /COD>,它具有对数查找。注意到大多数旧C++实现为相同的功能提供了(非标准)<代码> HASHMAP < /代码>。实际上我现在注意到它是<代码> char < /C>作为FRST参数,因此,<代码>无序的map map /代码>将是多余的;只需做一个数组。(或函数指针的std::vector
)(如果char
值未给出有效命令,则将入口点设为错误函数)。这将是O(1),并且比无序映射快。switch语句非常有效。考虑到Midi的移动速度有多慢,这是非常不相关的。@celtschk:在我看来,你的评论实际上是一个答案。你应该用它来回答这里的问题。