此README文件旨在给出MIKMIDI的概述。有关MIKMIDI的更完整文档,请参阅此处。有关疑问,请联系Andrew Madsen。
MIKMIDI
MIKMIDI是一个由Andrew Madsen创建的简单易用的Mac和iOS MIDI库,由他和Mixed In Key的Chris Flesner开发。它适用于编写Objective-C或Swift macOS或iOS app的程序员的用途,使用MIDI。它可以与外部MIDI设备通信,读取和写入MIDI文件,录制和播放MIDI等。MIKMIDI用于提供我们DJ应用<-reference>Flow、主打应用<-reference>Mixed In Key以及我们作曲软件<-reference>Odesi在Mac版本中的MIDI功能。
MIKMIDI可用于针对Mac OS X 10.7及更高版本和iOS 6及更高版本的app。本README中的示例代码用Swift编写。然而,MIKMIDI也可以轻松地从Objective-C代码中使用。
MIKMIDI遵循MIT许可协议,这意味着您可以在封闭源和开源项目中免费使用它。但是,即使在封闭源项目中,您也必须包含MIKMIDI版权声明的公开可访问拷贝,可在LICENSE文件中找到。
如果您对MIKMIDI有任何疑问或建议,请联系维护者。我们随时欢迎贡献。有关更多信息,请参阅我们的贡献指南。我们也非常愿意听到您正在使用它在哪些酷炫的项目中。
如何使用MIKMIDI
MIKMIDI附带一个用于构建iOS和macOS框架的项目。您也可以使用CocoaPods或Carthage进行安装。有关将MIKMIDI添加到项目的详细说明,请参阅MIKMIDI维基上的此页面。
关于Swift的说明:MIKMIDI使用Objective-C编写,但完全支持Swift。唯一的限制是,仅影响Swift但不受Objective-C影响的API更改(例如改进的nullability标注,针对Swift的API名称优化等),并非仅限于主要版本,有时也会包含在次要版本发行中。错误修复/补丁发行版不会破坏Swift 或 Objective-C API。Objective-C API将在主要版本内保持稳定,例如1.y.z。
MIKMIDI概述
MIKMIDI具有Objective-C接口,与CoreMIDI的纯C API不同,这使得将MIDI支持添加到Cocoa/Cocoa Touch应用程序变得更加容易。在核心上,MIKMIDI由围绕底层CoreMIDI API构建的相对较薄的Objective-C包装器组成。MIKMIDI的设计很大程度上是受CoreMIDI设计的启发和驱动的。因此,熟悉CoreMIDI的高级组件可能有助于理解和使用MIKMIDI。
MIKMIDI不仅限于针对现有CoreMIDI功能的Objective-C接口。MIKMIDI提供了一些高级功能。这些包括:消息路由、定序、录制等。还包括旨在帮助实现MIDI学习UI的功能,以便用户可以创建自定义MIDI映射文件。这些MIDI映射文件将特定MIDI硬件上的物理控件与其应用程序中的对应接收器(例如,屏幕按钮、旋钮、乐器等)关联起来。
为了理解MIKMIDI,最好将其分解为其主要子系统
- 设备支持 —— 包括设备发现、连接/断开连接和发送/接收MIDI消息的支持。
- 命令 —— 包含代表从和发送到MIDI设备和端点的各种MIDI消息类型的类。
- 映射 —— 支持生成、保存、加载和使用将物理MIDI控件与应用程序功能关联的文件。
- 文件 —— 支持读取和写入MIDI文件。
- 合成 —— 支持将MIDI转换为音频,例如播放MIDI文件和接收来自MIDI键盘的输入。
- 定序 —— MIDI的录制和播放。
当然,这些子系统是联合使用以启用复杂功能的。
设备支持
MIKMIDI的设备支持架构基于底层的CoreMIDI架构。有几种类用于表示设备的不同部分。所有这些类都是MIKMIDIObject
的子类。以下列出这些类。括号中为相应的CoreMIDI类。
- MIKMIDIObject (MIDIObjectRef) -- 抽象基类,为所有以下类提供。包含所有MIDI对象共有的属性。
- MIKMIDIDevice (MIDIDeviceRef) -- 表示单个物理设备,例如DJ控制器、MIDI键盘、MIDI鼓组等。
- MIKMIDIEntity (MIDIEntityRef) -- 将相关的端点分组。由MIKMIDIDevice管理,包含MIKMIDIEndpoints。
- MIKMIDIEndpoint (MIDIEndpointRef) -- 抽象基类,代表MIDI端点。不直接使用,仅通过其子类MIKMIDISourceEndpoint和MIKMIDIDestinationEndpoint。
- MIKMIDISourceEndpoint -- 表示MIDI源。MIDI源接收应用程序可以听到和处理的消息。
- MIKMIDIDestinationEndpoint -- 表示MIDI目标。您的应用程序将MIDI消息传递到目标端点,以便将它们发送到设备。
MIKMIDIDeviceManager
是一个单例类,用于设备发现和发送/接收端点之间的MIDI消息。要获取系统上可用的MIDI设备列表,请在对共享设备管理器的调用-availableDevices
。
let availableDevices = MIKMIDIDeviceManager.shared.availableDevices
MIKMIDIDeviceManager
还包括检索'虚拟'端点的能力,以启用与其他MIDI应用程序或设备的通信(例如,作为虚拟端点而不是物理设备的Native Instruments控制器)。
MIKMIDIDeviceManager
的availableDevices
、virtualSources
和virtualDestinations
属性符合键值观察(KVO)规范。这意味着例如,在OS X应用程序中,可以将availableDevices
绑定到NSPopupMenu
以提供自动更新的连接MIDI设备列表。它们还可以直接使用键值观察来观察,当设备连接或断开连接等事件发生时被通知。此外,MIKMIDIDeviceManager
还会发布以下通知:MIKMIDIDeviceWasAddedNotification
、MIKMIDIDeviceWasRemovedNotification
、MIKMIDIVirtualEndpointWasAddedNotification
、MIKMIDIVirtualEndpointWasRemovedNotification
。
使用MIKMIDIDeviceManager
可以订阅接收来自MIDI设备的消息以及发送消息。要接收来自MIKMIDIDevice
的消息,您必须连接设备并提供一个事件处理器块,在接收到消息时会被调用。这通过connect(_:, eventHandler:)
方法完成。当您不再想要接收消息时,必须调用disconnectConnection(forToken:)
方法。要将MIDI消息发送到MIKMIDIDevice
,从设备获取适当的MIKMIDIDestinationEndpoint
,然后调用MIKMIDIDeviceManager.send(_: [MIKMIDICommand], to:)
方法,传递一个包含MIKMIDICommand
实例的数组。例如
let noteOn = MIKMIDINoteOnCommand(note: 60, velocity: 127, channel: 0, timestamp: Date())
let noteOff = MIKMIDINoteOffCommand(note: 60, velocity: 127, channel: 0, timestamp: Date().advanced(by: 0.5))
try MIKMIDIDeviceManager.shared.send([noteOn, noteOff], to: destinationEndpoint)
如果您之前使用过CoreMIDI,您可能熟悉MIDIClientRef
和MIDIPortRef
。这些是MIKMIDI内部使用的,但MIKMIDI的“公共”API不会直接暴露 - 或其Objective-C等价物。相反,MIKMIDIDeviceManager
允许向/从MIKMIDIEndpoint
发送和接收消息。
MIDI消息
在MIKMIDI中,MIDI消息是对象。这些对象是MIKMIDICommand
具体子类的实例。每种MIDI消息类型(例如,控制更改、音符开启、系统专用等)都有一个相应的类(例如,MIKMIDIControlChangeCommand)。每个命令类都有特定于该消息类型的属性。默认情况下,MIKMIDI命令是不可变的。每个命令类型也提供了可变版本。
MIDI映射
MIKMIDI包含帮助应用程序添加MIDI映射支持的功能。MIDI映射指的是将特定硬件控制器的物理控件映射到应用程序中特定功能的特性。MIKMIDI的映射支持包括生成、保存、加载和使用映射文件的功能,这些文件将物理控件与应用程序特定功能关联起来。它还包括通过“MIDI学习”样式界面帮助实现系统,该系统允许最终用户轻松地生成自己的映射。
MIKMIDI MIDI映射功能的主要组件包括
- MIKMIDIMapping - 模型类,包含将传入消息映射到适当应用程序功能的信息。
- MIKMIDIMappingManager - 单例管理器,用于加载、保存和检索应用程序捆绑和用户自定义的映射文件。
- MIKMIDIMappingGenerator - 可以监听传入MIDI消息并将它们与应用程序功能关联的类,创建自定义的MIDI映射文件。
MIDI文件
MIKMIDI包含帮助轻松读取和写入MIDI文件的功能。此支持主要由以下提供:
- MIKMIDISequence - 用于表示MIDI序列的类,可以从MIDI文件中读取或写入。
- MIKMIDITrack - MIKMIDISequence包含一个或多个MIKMIDITracks。
- MIKMIDIEvent - MIKMIDIEvent及其特定子类用于表示MIKMIDITracks中包含的MIDI事件。
MIDI合成
MIDI合成是将MIDI事件/消息转换为可听音频的过程。这通过使用MIKMIDISynthesizer
实现。还包括一个MIKMIDISynthesizer
的子类MIKMIDIEndpointSynthesizer
,它可以非常容易地连接到MIDI终端来合成传入的MIDI消息。
let endpoint = midiDevice.entities.first!.sources.first!
let synth = try MIKMIDIEndpointSynthesizer(midiSource: endpoint)
MIDI序列
MIKMIDISequencer
可用于播放和录制到MIKMIDISequence
。它包括一些在实现MIDI录制和回放时非常有用的高级功能。然而,在最简单的情况下,MIKMIDISequencer可以用来加载MIDI文件并播放,如下所示
let sequence = try! MIKMIDISequence(fileAt: midiFileURL)
let sequencer = MIKMIDISequencer(sequence: sequence)
sequencer.startPlayback()