文档管理中心

OH_MIDI概述(C/C++)

MIDI简介

乐器数字接口(Musical Instrument Digital Interface)是一种用于电子乐器、计算机和其他设备之间进行通信的国际标准协议。同时定义了音符、控制信号等音乐数据的传输方式,广泛应用于音乐制作、舞台演出和游戏开发等领域。

从API version 24开始,Audio Kit支持MIDI(Musical Instrument Digital Interface)功能,应用可通过OH_MIDI API与外接MIDI设备(如USB MIDI键盘、蓝牙MIDI设备)进行数据交互。由于OH_MIDI采用UMP(Universal MIDI Packet)作为统一的数据交互格式,所以开发者无需关心底层协议差异,只需要以现代化的方式构建音乐创作、乐器控制和MIDI数据处理等应用。

MIDI协议版本

  • MIDI 1.0:1983年发布的经典协议,使用7位(bit)分辨率(取值范围为[0, 127]),单向通信,广泛兼容现有设备。
  • MIDI 2.0:2020年发布的新一代协议,支持32位高分辨率、双向通信、自动配置(MIDI-CI)等特性。

OH_MIDI支持连接标准MIDI 1.0设备,并通过系统服务层自动将传统的MIDI 1.0字节流转换为32位UMP格式,从而简化应用开发。同时,该架构设计在数据格式上兼容MIDI 2.0标准,为未来系统内核支持高分辨率MIDI设备提供了必要的技术基础。

UMP数据格式说明

通用MIDI数据包(Universal MIDI Packet)是MIDI 2.0标准中定义的统一数据包格式,采用32位对齐结构,可同时承载MIDI 1.0和MIDI 2.0协议消息。

协议与数据格式的关系(可以类比为"信封"和"信的内容语言"):

  • UMP:统一的32位对齐容器(信封格式)。
  • MIDI 1.0/2.0 协议:传统/现代语义(信的内容语言)。

无论选择哪种协议,数据封装格式(UMP)都是统一的。

OH_MIDI包含客户端、设备、端口和事件四个核心概念。使用OH_MIDI开发MIDI应用的基本流程为:创建客户端 → 枚举/打开设备 → 打开端口 → 收发MIDI消息 → 关闭端口/设备/客户端。完整的开发步骤和示例代码请参考使用OH_MIDI进行MIDI开发(C/C++)。

核心概念之间的关系:

  • 客户端(Client):应用与MIDI服务交互的入口。创建客户端后,可注册热插拔和错误回调、枚举已连接的设备、打开设备句柄。
  • 设备(Device):通过客户端打开的MIDI接口设备,包括USB MIDI设备和BLE MIDI设备。每个设备可打开多个端口。
  • 端口(Port):设备上的数据传输端点,分为输入端口(接收MIDI数据)和输出端口(发送MIDI数据)。
  • 事件(Event):端口收发数据的基本单元,采用UMP格式,包含时间戳(timestamp)、数据长度(length)和数据指针(data)。

OH_MIDI客户端(Client)

客户端是应用使用MIDI服务的入口点,所有MIDI操作都需要先创建客户端。同时,客户端负责管理与MIDI服务的连接、提供设备枚举、设备打开和端口管理等核心功能。

通过OH_MIDIClient_Create接口创建客户端后,应用可以获取当前连接的所有MIDI设备列表,并通过注册的回调监听设备的热插拔事件(OH_MIDICallback_OnDeviceChange)和系统级错误(OH_MIDICallback_OnError)。

关闭客户端时,系统会自动关闭该客户端名下打开的所有设备和端口(自动资源回收机制)。建议应用按相反顺序(端口→设备→客户端)主动释放资源,以保证代码逻辑清晰。

OH_MIDI设备(Device)

MIDI设备是指物理或虚拟的MIDI接口设备,包括USB MIDI键盘、蓝牙MIDI控制器等。设备连接后,MIDI服务会为其分配标识符(OH_MIDIDeviceInformation中的midiDeviceId),用于在当前会话中区分和管理不同设备。

设备信息包含设备类型(USB或蓝牙)、原生协议能力、设备名称、厂商ID、产品ID和设备地址等属性。

连接方式: USB设备通过OH_MIDIClient_OpenDevice接口同步打开,蓝牙低功耗(Bluetooth Low Energy)MIDI设备则需要通过OH_MIDIClient_OpenBLEDevice接口异步连接。

原生协议能力: 指示设备当前的通讯协议模式。在当前版本中,当设备支持多种协议时,系统会优先以MIDI 1.0模式与设备通讯,并在MIDI服务层将数据封装为MIDI 2.0 UMP格式提供给应用。

OH_MIDI端口(Port)

MIDI端口是设备上的数据传输端点,分为输入端口和输出端口。

[应用] <--接收-- [输入端口] <-- [设备]
[应用] --发送--> [输出端口] --> [设备]

每个设备可以有多个输入和输出端口。当每个端口打开时,可以通过OH_MIDIPortDescriptor结构配置期望的协议行为。

  • 数据转换:无论底层设备是MIDI 1.0还是2.0,应用层均统一收发UMP数据包。
  • 协议降级:如果应用请求发送MIDI 2.0高精度消息(UMP Type 4),但底层设备仅支持MIDI 1.0,MIDI服务层会自动将其降级转换为MIDI 1.0消息发送。
  • 自动转换说明:系统服务层会在接收方向自动将底层协议数据转换为UMP格式供应用处理。但在发送方向上,应用需要按照UMP规范自行构造OH_MIDIEvent数据。

OH_MIDI事件(Event)

MIDI事件是MIDI数据传输的基本单元。OH_MIDI强制使用UMP(Universal MIDI Packet)格式,统一承载MIDI 1.0和MIDI 2.0数据。

每个事件包含三个核心字段:

  • 时间戳(timestamp):纳秒级精度。取值范围为[0, 2^63-1]纳秒。0表示立即发送。
  • 数据长度(length):表示data数组中32位字(Word)的数量。取值范围为[1, 128]。
  • UMP数据指针(data):指向4字节对齐的uint32_t数组。

完整消息类型参考

UMP格式通过消息类型(Message Type)区分不同消息。MT是UMP数据包的最高4位,决定了消息的功能范围、数据包大小和状态字段大小。

展开
MT值 名称 大小(bit) 说明
0x0 Utility Messages 32 实用消息,如JR时间戳。
0x1 System Real Time and System Common Messages 32 系统实时消息和系统公共消息(不含System Exclusive)。
0x2 MIDI 1.0 Channel Voice Messages 32 MIDI 1.0通道声音消息,兼容现有设备。
0x3 Data Messages 64 数据消息,如SysEx(包含System Exclusive)。
0x4 MIDI 2.0 Channel Voice Messages 64 MIDI 2.0高分辨率Channel Voice消息。
0x5 Data Messages 128 数据消息。
0x6 Reserved 32 保留供未来使用。
0x7 Reserved 32 保留供未来使用。
0x8 Reserved 64 保留供未来使用。
0x9 Reserved 64 保留供未来使用。
0xA Reserved 64 保留供未来使用。
0xB Reserved 96 保留供未来使用。
0xC Reserved 96 保留供未来使用。
0xD Flex Data Messages 128 Flex Data灵活数据消息,如文本、歌词。
0xE Reserved 128 保留供未来使用。
0xF UMP Stream Messages 128 UMP流消息,如端点发现、功能块配置。
注意
  • 大多数应用场景下,开发者只需使用MT 0x2(MIDI 1.0通道声音)和MT 0x4(MIDI 2.0通道声音)即可完成MIDI音符的发送与接收。
  • 接收回调中的events数组及其包含的data指针仅在回调执行期间有效。应用如需保留MIDI数据供后续处理,必须在回调返回前将数据深拷贝到应用自己的内存中,以避免访问过期指针导致的未定义行为。

术语表

展开
术语 全称 说明
UMP Universal MIDI Packet 通用MIDI数据包,32位对齐的统一容器格式。
MT Message Type 消息类型,UMP数据包最高4位,决定消息功能和大小。
SysEx System Exclusive 系统独占消息,用于厂商自定义数据传输。
JR Jitter Reduction 抖动消除,网络/蓝牙传输时的时间戳同步机制。
Channel Voice 通道声音消息 控制音符、力度、控制器等的核心消息类型。
Flex Data 灵活数据 MIDI 2.0新增,支持文本、歌词等128位长消息。
MIDI-CI MIDI Capability Inquiry MIDI能力查询,MIDI 2.0的设备自动配置协议。

约束与限制

  • 同时打开的设备数量限制:单个客户端最多可同时打开16个MIDI设备。超过限制时,OH_MIDIClient_OpenDevice接口将返回OH_MIDI_STATUS_TOO_MANY_OPEN_DEVICES错误。

  • 每个设备的端口数量限制:每个MIDI设备最多可有64个端口(输入+输出总计)。单个客户端最多可同时打开64个端口。超过限制时,OH_MIDIDevice_OpenInputPort或OH_MIDIDevice_OpenOutputPort接口将返回OH_MIDI_STATUS_TOO_MANY_OPEN_PORTS错误。

  • 缓冲区大小限制:共享内存缓冲区大小为4KB。发送大量MIDI消息时,如果缓冲区填满,OH_MIDIDevice_Send接口将返回OH_MIDI_STATUS_WOULD_BLOCK。建议应用批量发送消息,并在收到此错误后延迟10ms再重试。

  • 线程模型和回调执行环境:所有回调(OH_MIDIDevice_OnReceived、OH_MIDICallback_OnDeviceChange、OH_MIDICallback_OnError)在高优先级系统线程上执行。回调中应避免执行阻塞操作、大量计算或I/O操作,以免影响MIDI系统的实时性能。

  • 内存安全:OH_MIDIDevice_OnReceived回调中的events数组及其包含的数据指针仅在回调期间有效。如需保留数据,必须在回调返回前复制。访问过期指针会导致未定义行为(崩溃、内存损坏)。

  • 资源管理顺序:关闭客户端时会自动关闭所有设备和端口。建议应用按相反顺序关闭资源,以保证代码逻辑清晰。

    此顺序为推荐做法,用于保证代码逻辑清晰,但系统提供自动资源回收机制确保资源正确释放。

  • 设备类型特性差异:

    • USB MIDI设备:通过USB连接,支持低延迟传输,设备枚举通过系统USB驱动完成。
    • 蓝牙MIDI设备:通过蓝牙BLE连接,需要ohos.permission.ACCESS_BLUETOOTH权限,使用OH_MIDIClient_OpenBLEDevice接口异步打开。

相关参考