锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

【低功耗蓝牙】④ 蓝牙MIDI协议

时间:2022-09-25 05:00:00 bf3v系列圆柱形光电传感器

摘要

蓝牙MIDI协议是智能乐器和计算机之间数据通信的协议格式。本文主要介绍了低功耗蓝牙的协议格式MIDI协议的步骤,以及MIDI依靠指令的数据格式ESP32芯片MicroPython蓝牙是平台给出的MIDI协议的实现代码。

蓝牙MIDI实现电子二胡:https://www.bilibili.com/video/BV1sh411i7at
蓝牙MIDI卡林巴电子琴的实现:https://www.bilibili.com/video/BV135411w73B

MIDI协议

MIDI 是 Musical Instrument Digital Interface 翻译成中文作为音乐数字接口。 世纪80 20世纪初提出的通信协议是为了解决电声乐器之间的通信问题。协议传输的数据内容主要是描述乐器的一些动作,如按下或抬起钢琴上的按钮、按钮的强度等。

如下图所示,将电子琴连接到电脑上,就可以捕捉电子琴在电脑上演奏的动作:

传统MIDI接口

传统的MIDI协议通常使用电缆来实现,乐器必须经常移动,所以使用起来不是很方便。2014年,苹果设计支持低功耗蓝牙(BLE)的MIDI该协议用于通信乐器和智能手机/计算机。MMA(MIDI2015年6月,制造商成员协会将该协议列为行业标准。自从智能手机普及以来,蓝牙已经加入了许多电子乐器MIDI智能教学可以通过蓝牙连接到手机或平板电脑。

蓝牙MIDI协议

蓝牙MIDI协议使用低功耗蓝牙GATT协议格式仍输层,协议格式仍然是有线的MIDI协议一致。想通过低功耗蓝牙设备实现MIDI协议应满足以下两个要求:

① 在广播数据中广播128 Bit 的UUID:03B80E5A-EDE8-4B33-A751-6CE34EC4C700

② GATT包含一个UUID为03B80E5A-EDE8-4B33-A751-6CE34EC4C700服务中应该有一个服务UUID为7772E5DB-3868-4112-A1A9-F2669D106BF3.该特性的操作权限为 ReadWriteNotify


蓝牙MIDI通过上述特点完成数据交互。需要注意的是,广播数据中必须广播MIDI服务的UUID,才能被手机电脑等识别成MIDI设备。

MIDI指令格式

如上图所示,一个MIDI指令包含5个字节:

前两个字节表示时间戳,第一个字节的前两个必须是10 , 第二个字节的第一个必须是1(时间戳可以不填,全部为零),所以前两个字节通常是0x80,0x80。
第三个字节表示设备的动作,如按键或抬起、音量调节等。
第四字节和第五字节是参数,其含义应根据第三字节确定。

在MIDI在指令中,每个音符都有相应的编码,一些简单的音符和MIDI下表对应编码:

上表中没有半音。下图以钢琴为例,给出了一些按钮对应MIDI编码:

思考白键E5对应的MIDI编码是多少?

以99的力度按下钢琴上的钢琴C4键,对应的MIDI指令是:

80 80 90 48 63 

第三个字节90表示按钮,第四个字节48表示钢琴上的按钮C4.最后一个字节63表示按压力为0x63(十进制99)。

抬起钢琴C4键,对应的MIDI指令是:

80 80 80 48 00 

第三个字节80表示按钮抬起,第四个字节48表示按钮C第五字节毫无意义。

更多MIDI请参考指令的用法MIDI官网:https://www.midi.org

蓝牙MIDI协议实现代码

以下是基础ESP32 MicroPython平台的蓝牙MIDI设备代码,实现一个按钮,按键时发送按钮按指令,按键抬起时发送按钮抬指令。

 from machine import Pin from time import sleep_ms import time import ubluetooth #导入BLE功能模块  ble = ubluetooth.BLE()  #创建BLE设备 ble.active(True)  #打开BLE  MIDI_SERVER_UUID = ubluetooth.UUID('03B80E5A-EDE8-4B33-A751-6CE34EC4C700') MIDI_CHAR_UUID    = ubluetooth.UUID('7772E5DB-3868-4112-A1A9-F2669D106BF3')  MIDI_CHAR = (MIDI_CHAR_UUID, ubluetooth.FLAG_READ | ubluetooth.FLAG_WRITE | ubluetooth.FLAG_NOTIFY , ) MIDI_SERVER = (MIDI_SERVER_UUID, (MIDI_CHAR ,  ) , ) #把MIDI特性放入MIDI服务   SERVICES = (MIDI_SERVER, )  #把MIDI将服务放入服务集和中 ((char_midi, ), ) = ble.gatts_register_services(SERVICES)  #注册服务到gatts

#设置BLE广播数据并开始广播
ble.gap_advertise(100, adv_data = b'\x02\x01\x05'
                                + b'\x11\x07\x00\xC7\xC4\x4E\xE3\x6C\x51\xA7\x33\x4B\xE8\xEd\x5A\x0E\xB8\x03'
                                + b'\x05\x09\x4D\x49\x44\x49')

key1=Pin(0,Pin.IN,Pin.PULL_UP)
last_status = key1.value()  #记录上次按键的值
while True:
    if not key1.value() == last_status: #状态发生改变
      last_status = key1.value() #记录当前按键值

      if key1.value() == 0: #按键按下
        print("Key Down") #蓝牙连接后方能发送数据
        ble.gatts_notify(0, char_midi, b'\x80\x80\x90\x48\x63')

      else:
        print("Key UP") #按键抬起
        ble.gatts_notify(0, char_midi, b'\x80\x80\x80\x48\x00')

上述代码仅仅实现了一个按键,有兴趣的同学可以都实现几个按键,做成一个完整的乐器。

手机端APP

我们刚刚完成的代码仅仅完成了相关指令的发送,设备本身并不能发出声音,要想发出声音,需要手机或者电脑端软件的配合。手机端有很多APP支持蓝牙MIDI协议,iOS系统推荐库乐队 Echo Piano Lite ,Android系统推荐 泡泡钢琴自乐班,部分这些软件可通过下图二维码下载:

Echo Piano Lite 连接MIDI设备

泡泡钢琴 连接蓝牙MIDI设备

上一章节:【低功耗蓝牙】③ 蓝牙服务和特性的创建

下一章节:【低功耗蓝牙】⑤ 蓝牙HID协议

作者:我是鹏老师

锐单商城拥有海量元器件数据手册IC替代型号,打造电子元器件IC百科大全!

相关文章