MIDI音乐设备音频单元:播放相同音高的两个音符,停止一个?

时间:2012-09-24 10:45:41

标签: core-audio midi audiounit coremidi

对于AudioUnits,我是一个新手,所以如果我的问题很基本,请原谅我。

我正在使用MusicDevice AudioUnit播放一些音符。我正在使用MusicDeviceMIDIEvent发送note-on和note-off消息。它运作良好。有时候应该同时发出多个音符,因此我可能会连续发送两条音符信息。有时候这些音符碰巧有相同的音高。然后,当我想要关闭其中一个音符时,我会为这个音调发送一个音符关闭事件。但是此消息会关闭音高的所有音符。当然这种行为很有意义,但我想问一下人们通常如何处理这个问题。

我应该使用不同的频道同时进行音符吗?或者手动管理音符,比如用一个保持当前播放音高的计数组,并且只在音高的最后一个实例停止播放后发送音符关闭事件?或完全不同的东西?

编辑:

由于这是在iOS上,我必须使用kAudioUnitSubType_Sampler作为AudioUnit子类型。虽然文档只提到这种类型是单音,但我现在怀疑它也是单声道的。这当然可以解释这种行为。我仍然想知道如果我真的有一个复音乐器我会怎么做。

编辑2:

我做了一些测试,现在在我看来,在任何频道上发送音符关闭消息会停止所有频道上相同音高的所有音符。我在http://developer.apple.com/library/ios/#samplecode/LoadPresetDemo/Introduction/Intro.html处获取了苹果示例代码并修改了stopPlay [low / mid / high] Note方法,以便在某个随机通道上发送音符关闭消息(如果必须知道,则在通道7,8和9上) , 分别)。它仍然会停止音符,尽管事实上是在通道0上发送了音符开启消息。这是预期的行为吗?

为了确保我没有犯下一个愚蠢的错误,这些是发送记录和留言信息的方法:

- (IBAction) startPlayLowNote:(id)sender {

    UInt32 noteNum = kLowNote;
    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 low note. Error code: %d '%.4s'\n", (int) result, (const char *)&result);
}



- (IBAction) stopPlayLowNote:(id)sender {

    //note the channel!
    UInt32 noteNum = kLowNote;
    UInt32 noteCommand =    kMIDIMessage_NoteOff << 4 | 7;

    OSStatus result = noErr;
    require_noerr (result = MusicDeviceMIDIEvent (self.samplerUnit, noteCommand, noteNum, 0, 0), logTheError);

    logTheError:
    if (result != noErr) NSLog (@"Unable to stop playing the low note. Error code: %d '%.4s'\n", (int) result, (const char *)&result);
}

2 个答案:

答案 0 :(得分:4)

我很确定在同一频道上相同音高的事件的两个音符之后关闭音符的行为是不确定的。有些乐器可能会关闭两个音符,有些可能会关闭一个乐器并需要关闭另一个音符以关闭另一个音符。

如果你真的需要有两个相同音高的同时音符,它们应该在不同的频道上。

关于发布代码的修改

我在您的链接中尝试了示例项目,并以与发布的代码相同的方式更改了频道。事实证明kAudioUnitSubType_Sampler确实是单音的,所以它忽略了MIDI通道参数。因此,如果您希望使用kAudioUnitSubType_Sampler同时具有两个相同音高的音符,则必须创建两个单独的实例。

请注意,kAudioUnitSubType_Sampler不是单声道的。它是复音的,因为它可以同时播放多个音高。

答案 1 :(得分:0)

使用MusicDevice.h的MusicDeviceStartNote()MusicDeviceStopNote()怎么样?它为音符使用了一个唯一的标记,因此您应该能够区分两个相同的音高。