使用 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 的一些参数或属性。在这种情况下,您只需要获取MIDIPacketdata 字段。 每个字节意味着你可以看here。 之后,根据所需字节的值,您需要设置属性或参数值。

【讨论】:

【参考方案2】:

这是我在此期间学习并完成工作的问题的简约答案。这是使 midiReadProc 生成 audioRenderProc 可以接受作为参数的值的问题。请注意,这适用于独立应用程序。对于编写 AU 插件,我建议了解和使用 Apple 提供的 CoreAudioUtilityClassesC 中 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的主要内容,如果未能解决你的问题,请参考以下文章

如何将midi从java程序发送到OSX上的IAC总线

开发者的如何优雅的使用OSX

MIDI 键盘不适用于所有平台

用于 Arduino 的 Korg Nanokey MIDI 控制器?

从 MIDI 键盘录制音频文件并使用 android studio 存储

iPad替代midi键盘