首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用CoreMIDI虚拟回送MIDI端口

用CoreMIDI虚拟回送MIDI端口
EN

Stack Overflow用户
提问于 2021-06-27 16:32:28
回答 2查看 239关注 0票数 0

我试图在macOS上使用C中的CoreMIDI编写简单的回送虚拟MIDI端口。首先,我似乎无法理解所有的CoreMIDI术语。请看以下图片:

代码语言:javascript
复制
┌─────────────┐
│ MIDI DEVICE │
│             │
└─OUT──────IN─┘
  ↓         ↑
event     event
  ↓         ↑
──A─────────B──  application
  ↓         ↑

所以我们有个MIDI装置。从设备的角度来看,该设备具有出端口和端口。因此,通过外部端口MIDI设备发送MIDI数据,并通过端口接收数据。

但是现在让我们从应用程序的角度来看这个系统。对于来自MIDI设备的应用程序MIDI数据,实际上是通过app从设备输出端口接收到(上图中的点A )。而来自应用程序的数据,则由设备通过其内部端口从app (point B)接收。

所以我的第一个问题是API代表AB?CoreMIDI中有四个概念:

  • source
  • destination
  • input端口
  • 输出端口

那么,如果我们想从MIDI设备接收MIDI数据,我们应该使用什么?我想我们需要这样的东西:

代码语言:javascript
复制
void MyReadProc(const MIDIPacketList *pktlist, void *readProcRefCon, void *srcConnRefCon)
{
}

...

MIDIClientRef client;
MIDIClientCreate(CFSTR("CLIENT"), NULL, NULL, &client);
    
MIDIPortRef inPort;
MIDIInputPortCreate(client, CFSTR("TEST"), MyReadProc, NULL, &inPort);
    
MIDIPortConnectSource(inPort, srcEndpoint, NULL);

其中srcEndpointMIDIEndpointRef,表示源。

当我们想要将MIDI数据发送到设备时,会发生许多有趣的事情。我们是使用MIDISend还是MIDIReceived

现在,我需要展示一下环回端口的实现:

代码语言:javascript
复制
#include <stdio.h>
#include <CoreFoundation/CoreFoundation.h>
#include <CoreMIDI/CoreMIDI.h>
#include <mach/mach_time.h>
#include <string.h>

void MyReadProc(const MIDIPacketList *pktlist, void *readProcRefCon, void *srcConnRefCon)
{
    if (readProcRefCon != NULL && srcConnRefCon != NULL)
    {
        MIDIPortRef portRef = *((MIDIPortRef*)readProcRefCon);
        MIDIEndpointRef destRef = *((MIDIEndpointRef*)srcConnRefCon);
        
        OSStatus result = MIDISend(portRef, destRef, pktlist);
        
        printf("B\n");
    }
}

...

MIDIClientRef client;
MIDIClientCreate(CFSTR("CLIENT"), NULL, NULL, &client);
    
MIDIPortRef outPort;
MIDIOutputPortCreate(client, CFSTR("TEST"), &outPort);
    
MIDIEndpointRef destEndpoint;
MIDIDestinationCreate(client, CFSTR("TEST"), MyReadProc, NULL, &destEndpoint);
    
MIDIPortRef inPort;
MIDIInputPortCreate(client, CFSTR("TEST"), MyReadProc, &outPort, &inPort);
    
MIDIEndpointRef srcEndpoint;
MIDISourceCreate(client, CFSTR("TEST"), &srcEndpoint);
    
MIDIPortConnectSource(inPort, srcEndpoint, &destEndpoint);

好的,我可以创建输入MIDI端口,将其连接到源和接收事件。但是,回送意味着如果我发送数据到测试端口(通过输出端口、目的地、源、MIDISend/Received,其他什么?),我希望立即从端口中的测试中接收数据。

我真的不明白该如何构建这个回送系统,以及用户将如何与它交互?

所以应该是系统中的两个端口(或者源和目的地?)。用户以某种方式获取对out端口(或源或目的地?)的引用,通过它发送数据,并通过引用in端口(或源或目的地?)获取数据。我的头好像爆炸了。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-06-28 10:51:53

好的,我终于想出了如何用CoreMIDI构建回送系统。

  1. Source是一个输入的设备,从应用程序的角度来看,

是一个输出的设备。

因此,我们只需要创建带有回调的目的地,在其中我们将通知源(使用MIDIReceived)新的MIDI数据到达。因此,我们在MIDIDestinationCreate中提供源引用作为回调的参数,并在回调中使用这个源。

票数 2
EN

Stack Overflow用户

发布于 2021-07-15 02:25:35

第一件事是不要使用MIDIReadProc。它不仅受到反对和不支持,而且也有问题。见https://bradleyross.github.io/ObjectiveC-Examples/Documentation/BRossTools/FunctionalArea.htmlhttps://bradleyross.github.io/ObjectiveC-Examples/Documentation/BRossTools/CoreMidi.html

客户端是一个虚拟的MIDI设备,可以是控制器、排序器、合成器等。输入和输出端口是客户端的一部分,其中包括源和目的地。当您附加带有USB连接的MIDI设备时,将自动为这些设备创建源和目的地。

您还可以使用MIDIDestinationCreate和MIDISourceCreate (带有适当的后缀)为客户端附加虚拟源和目的地。因此,回送可能涉及具有输出端口和虚拟目的地的客户端。然后将输出端口附加到虚拟目的地。另一种选择是具有输入端口和虚拟源,并将源连接到输入端口。

我自己还在努力理解这件事。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68153232

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档