使用MIDI键盘OSX控制AudioUnit

时间:2014-01-26 21:05:44

标签: macos audiounit

我想知道一个简单的CoreAudio组件(子类型为kAudioUnitSubType_HALOutput,例如)是否可以通过MIDI键盘进行参数控制,假设MIDI音符编号被转换为插入振荡器频率?另一方面,通过GUI元素控制这样的参数就像梦一样。

我在整个网络上找不到这样一个代码的例子。 我不需要SinSynth,Sampler,MusicDevice,SoundFonts,Midi文件,GM,ADSR,插件级别的功能等。

只需要一条简单的信息或暗示如何通过midiReadProc读取的MIDI数据包中的数据传递给音频渲染回调,就像滑块的值一样。有了MIDI似乎有一个线程问题,我没有找到关于。

的文档

我更喜欢在CoreAudio API中执行此操作,如果可能的话,我确定必须这样做。

另一方面,使用Apple预制的乐器设备会让我走向一个完全错误的方向。

提前致谢,

CA

2 个答案:

答案 0 :(得分:0)

您似乎想要使用MIDI键盘控制AudioUnit的一些参数或属性。在这种情况下,您需要的只是MIDIPacket的{​​{1}}字段。 你可以看到每个字节的含义here。 之后,根据所需字节的值,您需要设置属性或参数值。

答案 1 :(得分:0)

这是对我所学习并同时开展工作的问题的简约回答。这是一个使 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()是由C.Adamson&amp; 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; ...;...)
}

其他一切都是共同良好的编程实践的问题。