从音频单元的渲染线程调用 MusicDeviceMIDIEvent
Calling MusicDeviceMIDIEvent from the audio unit's render thread
关于 MusicDeviceMIDIEvent
,有一件事我不明白。在我见过的每一个例子中(搜索 Github 和 Apple 例子)它总是从主线程中使用。现在,为了使用样本偏移参数,文档指出:
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
尽管如此,即使在最简单的情况下,您只有一个采样器音频单元和一个 io 单元,您如何从音频单元的渲染线程安排 MIDI 事件,因为采样器不允许渲染回调即使它会(或者如果你使用 io 的回调只是为了点击),它也会感觉很糟糕,因为渲染回调不适用于安排 MIDI 事件?
如何从音频单元的渲染线程正确调用此函数?
renderNotify 回调是从渲染线程进行调度的完美场所。您甚至可以在 MusicDevice 本身上设置 renderNotify。这是它在 AUSampler 上的样子。
OSStatus status = AudioUnitAddRenderNotify(sampler, renderNotify, sampler);
在这个例子中,我通过 inRefCon 参数将采样器作为参考传递进来,并且我只是每 44100 个样本发送一个 note-on(144) 到 note 64,但是在应用程序中,你将传递一个 c 结构到inRefCon 对您的 MIDI 设备的引用,以及您进行调度所需的所有值。注意检查预渲染的渲染标志。
static OSStatus renderNotify(void * inRefCon,
AudioUnitRenderActionFlags * ioActionFlags,
const AudioTimeStamp * inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList * ioData) {
AudioUnit sampler = inRefCon;
if (ioActionFlags & kAudioUnitRenderAction_PreRender) {
for (int i = 0; i < inNumberFrames; i++) {
if (fmod(inTimeStamp->mSampleTime + i, 44000) == 0) {
MusicDeviceMIDIEvent(sampler,144, 64, 127, i); // i is the offset from render start, so use it for offset argument.
}
}
}
return noErr;
}
关于 MusicDeviceMIDIEvent
,有一件事我不明白。在我见过的每一个例子中(搜索 Github 和 Apple 例子)它总是从主线程中使用。现在,为了使用样本偏移参数,文档指出:
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
尽管如此,即使在最简单的情况下,您只有一个采样器音频单元和一个 io 单元,您如何从音频单元的渲染线程安排 MIDI 事件,因为采样器不允许渲染回调即使它会(或者如果你使用 io 的回调只是为了点击),它也会感觉很糟糕,因为渲染回调不适用于安排 MIDI 事件?
如何从音频单元的渲染线程正确调用此函数?
renderNotify 回调是从渲染线程进行调度的完美场所。您甚至可以在 MusicDevice 本身上设置 renderNotify。这是它在 AUSampler 上的样子。
OSStatus status = AudioUnitAddRenderNotify(sampler, renderNotify, sampler);
在这个例子中,我通过 inRefCon 参数将采样器作为参考传递进来,并且我只是每 44100 个样本发送一个 note-on(144) 到 note 64,但是在应用程序中,你将传递一个 c 结构到inRefCon 对您的 MIDI 设备的引用,以及您进行调度所需的所有值。注意检查预渲染的渲染标志。
static OSStatus renderNotify(void * inRefCon,
AudioUnitRenderActionFlags * ioActionFlags,
const AudioTimeStamp * inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList * ioData) {
AudioUnit sampler = inRefCon;
if (ioActionFlags & kAudioUnitRenderAction_PreRender) {
for (int i = 0; i < inNumberFrames; i++) {
if (fmod(inTimeStamp->mSampleTime + i, 44000) == 0) {
MusicDeviceMIDIEvent(sampler,144, 64, 127, i); // i is the offset from render start, so use it for offset argument.
}
}
}
return noErr;
}