要么 Apple 的 MIDI 合成代码中存在严重错误,要么我做错了什么。这是我对它的理解。当您发送弯音 MIDI 命令时,弯音的范围是 -8192 到 8191,移调到 0。(所以实际范围是 0 到 16383。)这个数字被分成两个 7 位字段,所以真的这意味着您有 128 个粗略控制值和 128 个精细控制值。
这是我编写的一个弯音示例,类似于 Apple 的LoadPresetDemo中的命令。
// 'ratio' is the % amount to bend in current pitch range, from -1.0 to 1.0
// 'note' is the MIDI note to bend
NSUInteger bendValue = 8191 + 1 + (8191 * ratio);
NSUInteger bendMSB = (bendValue >> 7) & 0x7F;
NSUInteger bendLSB = bendValue & 0x7F;
UInt32 noteNum = note;
UInt32 noteCommand = kMIDIMessage_PitchBend << 4 | 0;
OSStatus result = MusicDeviceMIDIEvent(self.samplerUnit, noteCommand, noteNum, bendMSB, bendLSB);
当bendMSB(粗调控制)改变时,音高弯曲就好了。但是当bendLSB(精细控制)改变时,什么也没有发生。换句话说,Apple 的 MIDI 合成器似乎忽略了 LSB,这意味着音符只会在听起来难看的离散块中弯曲。
这是做同样事情的另一种方法:
// 'ratio' is the % amount to bend in current pitch range, from -1.0 to 1.0
AudioUnitParameterValue bendValue = 63 + 1 + (63 * ratio); // this is a CGFloat under the hood
AudioUnitSetParameter(self.samplerUnit,
kAUGroupParameterID_PitchBend,
kAudioUnitScope_Group,
0,
bendValue,
0);
这表现出与前一个示例相同的行为。这种处理方式特别有趣的是,kAUGroupParameterID_PitchBend 的文档指定值范围应该是 -8192 到 8191,这完全行不通。实际范围似乎是 0 到 127,浮点(精细控制)被忽略。
最后,如果您进行以下调用来调整弯音范围:
// 'semitones' is the number of semitones (100 cents) to set the pitch bend range to
// 'cents' is the additional number of cents to set the pitch bend range to
UInt32 status = 0xB0 | 0;
MusicDeviceMIDIEvent(self.samplerUnit, status, 0x64, 0x00, 0); // RPN pitch bend range.
MusicDeviceMIDIEvent(self.samplerUnit, status, 0x65, 0x00, 0);
MusicDeviceMIDIEvent(self.samplerUnit, status, 0x06, semitones, 0); // Data entry MSB
MusicDeviceMIDIEvent(self.samplerUnit, status, 0x26, cents, 0); // Data entry LSB (optional)
MusicDeviceMIDIEvent(self.samplerUnit, status, 0x64, 0x7F, 0); // RPN reset
MusicDeviceMIDIEvent(self.samplerUnit, status, 0x65, 0x7F, 0);
你能猜到会发生什么吗?没错,LSB 信息会被忽略,并且音高轮范围仅会根据提供的半音数量而变化。
这里发生了什么?这是苹果的错误还是我错过了什么?(也许是一个设置参数?)或者它根本不是一个错误?也许 Apple 的合成器在设计上没有那么详细的细节?按照 MIDI 标准,这种事情合法吗?!帮助!
编辑:
当弯音范围设置为 40 个半音时,每个粗略的变化都会产生听觉上的差异。当弯音范围设置为 10 个半音时,只有每秒钟的粗略变化才会产生影响。在 2 个半音(默认值)时,需要 4 次或更多次粗调才能产生差异。
换句话说,不仅 LSB 显然被忽略了,而且似乎还有最小的 # 美分来改变音高。可以修复这些限制中的任何一个吗?如果没有,是否有任何适用于 iOS 的具有更高弯曲分辨率的软件合成器框架?
嗯...也许应用 kAudioUnitSubType_Varispeed 或 kAudioUnitSubType_NewTimePitch 会产生更好的结果...