我需要一些帮助来理解Apple / iOS LoadPresetDemo源代码中的一些简单的C位移位。这很简单,但需要一大堆空间来提供背景,所以感谢与我的关系。
我试图理解为什么程序员正在使用这一行:
UInt32 noteCommand = kMIDIMessage_NoteOn << 4 | 0;
程序员已经在代码中的其他地方定义了常量(下面)。当我拿出我的计算器并输入0x9并将其向左移动4位时,我得到0x90。我把这个数字插入代码代替代码上面的行运行正常,所以我很困惑。我的两个问题:
为什么程序员不将常量定义为 0x90 ?
上述代码中 OR 运算符的用途是什么?
我知道这是一个小而愚蠢的细节,但我想知道这背后是否有一个很好的理由并且理解比特转换更好(没有双关语......)。完整的方法和细节如下。 - 谢谢!
// some MIDI constants:
enum {
kMIDIMessage_NoteOn = 0x9,
kMIDIMessage_NoteOff = 0x8,
};
// Play the mid note
- (IBAction) startPlayMidNote:(id)sender {
UInt32 noteNum = kMidNote;
UInt32 onVelocity = 127;
UInt32 noteCommand = kMIDIMessage_NoteOn << 4 | 0;
OSStatus result = noErr;
require_noerr (result = MusicDeviceMIDIEvent(self.samplerUnit, noteCommand, noteNum, onVelocity, 0), logTheError);
logTheError:
if (result != noErr) NSLog (@"Unable to start playing the mid note. Error code: %d '%.4s'\n", (int) result, (const char *)&result);
}
// Stop the mid note
- (IBAction) stopPlayMidNote:(id)sender {
UInt32 noteNum = kMidNote;
UInt32 noteCommand = kMIDIMessage_NoteOff << 4 | 0;
OSStatus result = noErr;
require_noerr (result = MusicDeviceMIDIEvent(self.samplerUnit, noteCommand, noteNum, 0, 0), logTheError);
logTheError:
if (result != noErr) NSLog (@"Unable to stop playing the mid note. Error code: %d '%.4s'\n", (int) result, (const char *)&result);
}
/*!
@function MusicDeviceMIDIEvent
@abstract Used to sent MIDI channel messages to an audio unit
@discussion This is the API used to send MIDI channel messages to an audio unit. The status and data parameters
are used exactly as described by the MIDI specification, including the combination of channel and
command in the status byte.
@param inUnit
The audio unit
@param inStatus
The MIDI status byte
@param inData1
The first MIDI data byte (value is in the range 0 < 128)
@param inData2
The second MIDI data byte (value is in the range 0 < 128). If the MIDI status byte only has one
data byte, this should be set to zero.
@param inOffsetSampleFrame
If you are scheduling the MIDI Event from the audio unit's render thread, then you can supply a
sample offset that the audio unit may apply when applying that event in its next audio unit render.
This allows you to schedule to the sample, the time when a MIDI command is applied and is particularly
important when starting new notes. If you are not scheduling in the audio unit's render thread,
then you should set this value to 0
@result noErr, or an audio unit error code
*/
extern OSStatus
MusicDeviceMIDIEvent( MusicDeviceComponent inUnit,
UInt32 inStatus,
UInt32 inData1,
UInt32 inData2,
UInt32 inOffsetSampleFrame) __OSX_AVAILABLE_STARTING(__MAC_10_0,__IPHONE_5_0);
答案 0 :(得分:7)
作者以这种方式编写代码的原因最有可能使其更容易理解。 MIDI事件代码分为2部分,其中高4位是事件,低4位是通道号。通过向您显示一个恒定左移4位和OR为0,他表示MIDI事件正在使用该常量作为通道0上的事件代码。
答案 1 :(得分:1)
除了隐式转换为int
之外,我不确定除零的位OR是否会完成任何事情。我怀疑这就是为什么OR存在的原因,IIRC,enum
值的位移会导致int
无论如何......
将常量定义为0x9
并将它们移位四位而不是使用0x90
的原因可能与来自API规范,在线协议文档的常量有关,或者之类的东西。位移也将限制常量的有效大小的大小。在这种情况下,我相信它将被截断为28位。
答案 2 :(得分:1)
在此处添加详细信息以获得完整性。
位移的目的是为了能够指定通道
UInt32 noteCommand = kMIDIMessage_NoteOn << 4 | 0;
产量:144
UInt32 noteCommand = kMIDIMessage_NoteOn << 4 | 1;
产量:145
等
答案 3 :(得分:0)
我不熟悉Objective-C,但我猜测OR的0与Objective-C中的无操作一样,与普通的C一样。
因此,kMIDIMessage_NoteOff << 4 | 0
与kMIDIMessage_NoteOff << 4
相同 - 原始程序员可能因为某种原因忘记删除它。
答案 4 :(得分:0)
移位是一种快速的方式(左移)或加法(右移)乘以2(在你的情况下是四次)。
当您想要在很小的空间中存储状态位(标志)时,位操作可能很有用。在这种情况下,枚举可能是来自库的常量,他无法改变。
OR为0对我没有意义,除非他想清除溢出位,如果有的话?