【问题标题】:controlling an AudioUnit with MIDI keyboard OSX使用 MIDI 键盘 OSX 控制 AudioUnit
【发布时间】: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 预先构建的乐器设备会导致我走向完全错误的方向。

提前致谢,

加拿大

【问题讨论】:

    标签: macos audiounit


    【解决方案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; ...;...)
      }
      

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-09-24
        • 2017-03-14
        • 1970-01-01
        • 2017-01-25
        • 1970-01-01
        • 1970-01-01
        • 2018-05-30
        相关资源
        最近更新 更多