在 iOS 上用 midi 演奏打击乐器

Playing Percussion instruments with midi on iOS

我有一个可以处理多种 MIDI 乐器的应用程序。除了演奏打击乐器外,一切都很好。我知道为了在 General MIDI 中演奏打击乐,您必须将事件发送到通道 10。我尝试了很多不同的东西,但我不知道如何让它工作,这是我如何工作的一个例子我正在为旋律乐器和打​​击乐器做这件事。

    // Melodic instrument
    MusicDeviceMIDIEvent(self.samplerUnit, 0x90, (UInt8)pitch, 127, 0);

    // Percussion Instruments
    MusicDeviceMIDIEvent(self.samplerUnit, 0x99, (UInt8)pitch, 127, 0);

采样器单位是 AudioUnit,音高通过我的 UI.

以整数形式给出

提前致谢!

假设您加载了某种通用 MIDI 声音字体或类似字体,您需要在发送 pitch/velocity 信息之前设置正确的状态字节。因此,如果是标准 MIDI 鼓组(通道 9),您可以在 Swift:

中执行类似的操作
var status  = OSStatus(noErr)
let drumCommand = UInt32( 0xC9 | 0 )
let noteOnCommand = UInt32(0x90 | channel)
status = MusicDeviceMIDIEvent(self._samplerUnit, drumCommand, 0, 0, 0) // set device
status = MusicDeviceMIDIEvent(self._samplerUnit, noteOnCommand, noteNum, velocity, 0)  // sends note ON message

无需为 MIDI note off 消息做任何特别的事情。

好的,我让它工作了。我想我加载声音字体的方式使通道的东西不做任何事情。相反,我必须将 AUSamplerBankPresetData 上的 bankMSB 属性 设置为 kAUSampler_DefaultPercussionBankMSB 而不是 kAUSampler_DefaultMelodicBankMSB

我专门为敲击添加了不同的字体加载方法:

- (OSStatus) loadPercussionWithSoundFont: (NSURL *)bankURL {
    OSStatus result = noErr;

    // fill out a bank preset data structure
    AUSamplerBankPresetData bpdata;
    bpdata.bankURL  = (__bridge CFURLRef) bankURL;
    bpdata.bankMSB  = kAUSampler_DefaultPercussionBankMSB;
    bpdata.bankLSB  = kAUSampler_DefaultBankLSB;
    bpdata.presetID = (UInt8) 32;

    // set the kAUSamplerProperty_LoadPresetFromBank property
    result = AudioUnitSetProperty(self.samplerUnit,
                                  kAUSamplerProperty_LoadPresetFromBank,
                                  kAudioUnitScope_Global,
                                  0,
                                  &bpdata,
                                  sizeof(bpdata));

    // check for errors
    NSCAssert (result == noErr,
               @"Unable to set the preset property on the Sampler. Error code:%d '%.4s'",
               (int) result,
               (const char *)&result);

    return result;
}