使用 MIDI 键盘 OSX 控制 AudioUnit
Posted
技术标签:
【中文标题】使用 MIDI 键盘 OSX 控制 AudioUnit【英文标题】:controlling an AudioUnit with MIDI keyboard OSX 【发布时间】:2014-01-26 21:05:43 【问题描述】:我想了解一个简单的 CoreAudio 组件(例如 kAudioUnitSubType_HALOutput 子类型)是否可以通过 MIDI 键盘进行参数控制,假设 MIDI 音符编号被转换为内插振荡器频率?另一方面,通过 GUI 元素控制这样的参数就像做梦一样。
我在整个网络上都找不到这样的代码示例。 我不需要 SinSynth、Sampler、MusicDevice、SoundFonts、Midi 文件、GM、ADSR、插件级别的功能等。
只需要一条简单的信息或提示,说明如何将通过 midiReadProc 读取的 MIDI 数据包中的数据传递给音频渲染回调,就像滑块的值一样。使用 MIDI 似乎存在线程问题,我没有找到相关文档。
我更喜欢在 CoreAudio API 中进行,如果可能的话,我相信一定是这样。
另一方面,使用 Apple 预先构建的乐器设备会导致我走向完全错误的方向。
提前致谢,
加拿大
【问题讨论】:
【参考方案1】:您似乎想使用 MIDI 键盘来控制 AudioUnit 的一些参数或属性。在这种情况下,您只需要获取MIDIPacket
的data
字段。
每个字节意味着你可以看here。
之后,根据所需字节的值,您需要设置属性或参数值。
【讨论】:
【参考方案2】:这是我在此期间学习并完成工作的问题的简约答案。这是使 midiReadProc 生成 audioRenderProc 可以接受作为参数的值的问题。请注意,这适用于独立应用程序。对于编写 AU 插件,我建议了解和使用 Apple 提供的 CoreAudioUtilityClasses。 C 中 createMidi 的最简单示例:
//these have to be declared somewhere
MIDIClientRef midiclient;
MIDIPortRef midiin;
void createMIDI (void)
//create MIDI input and client - - - - - - - - - - -
midiclient = 0;
CheckError(MIDIClientCreate(CFSTR("MIDI_Client"),
NULL,
/*midiClientNotifyRefCon*/NULL,
&midiclient),
"MIDI Client Create Error\n");
CheckError(MIDIInputPortCreate(midiclient,
CFSTR("MIDI_Input"),
midiReadProc,
NULL,
&midiin),
"MIDI Port Create Error\n");
//connect MIDI - - - - - - - - - - - - - - - - - - -
ItemCount mSrcs = MIDIGetNumberOfSources();
printf("MIDI Sources: %ld\n", (long)mSrcs);
ItemCount iSrc;
for (iSrc=0; iSrc<mSrcs; iSrc++)
MIDIEndpointRef src = MIDIGetSource(iSrc);
MIDIPortConnectSource(midiin, src, NULL);
CheckError( ) 是仿照 “Learning Core Audio” 的通用实用函数,作者 C.Adamson 和 K.Avila,ISBN 0-321-63684-8 ...
...和一个纯 C midiReadProc 模板。请注意,许多 MIDI 硬件制造商并未实施标准化的 noteOff 事件,而是实施了由零速度 noteOn 组成的“黑客”版本,因为据称改善了 MIDI 延迟问题,但他们几乎没有记录它。因此,必须检查两种情况:
void midiReadProc(const MIDIPacketList *packetList,
void* readProcRefCon,
void* srcConnRefCon)
Byte note;
Byte velocity;
MIDIPacket *packet = (MIDIPacket*)packetList->packet;
int count = packetList->numPackets;
for (int k=0; k < count; k++)
Byte midiStatus = packet->data[0];
Byte midiChannel = midiStatus & 0x0F;
Byte midiCommand = midiStatus >> 4;
if ((midiCommand == 0x08)||(midiCommand == 0x09))
if(midiCommand == 0x09)
note = packet->data[1] & 0x7F;
velocity = packet->data[2] & 0x7F;
if (velocity == 0x0) //"hacked" note-off
; //do something
else//note on
; //do something
if(midiCommand == 0x08) //proper note-off
;//do something
else
;//do something else
packet = MIDIPacketNext(packet);
//end for (k = 0; ...;...)
其他一切都是常见的良好编程实践问题。
【讨论】:
以上是关于使用 MIDI 键盘 OSX 控制 AudioUnit的主要内容,如果未能解决你的问题,请参考以下文章
用于 Arduino 的 Korg Nanokey MIDI 控制器?