betway88必威体育
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » 【蓝牙乐器DIY】蓝牙MIDI协议

共47条 1/5 1 2 3 4 5 ›| 跳转至

【蓝牙乐器DIY】蓝牙MIDI协议

菜鸟
2022-03-15 00:11:17     打赏

midi_575x60.gif

摘要

蓝牙MIDI协议是智能乐器与计算机之间数据通信的协议格式,本文章主要介绍了通过低功耗蓝牙实现MIDI协议的步骤,以及MIDI指令的数据格式,最后介绍了一些可以在手机上使用的蓝牙MIDI APP,以及使用ESP32蓝牙模块实现的一些简单的电子乐器。

MIDI协议

MIDI 是 Musical Instrument Digital Interface 的简称,翻译成汉语为音乐数字接口。是20 世纪80 年代初为解决电声乐器之间的通信问题而提出的一种通信协议。协议传输的数据内容也主要是描述乐器的一些动作,比如钢琴上的按键按下或者抬起,按键按下的力度等等。

如下图所示,把电子琴连接到电脑上,就能在电脑上捕获电子琴演奏的动作:

1647312888529476.png

传统MIDI接口

传统的MIDI协议往往使用线缆实现,乐器又要经常移动,所以使用起来并不是很方便。苹果公司在2014年设计了支持低功耗蓝牙(BLE)的MIDI协议,用于乐器与智能手机/电脑通信。MMA(MIDI制造商成员协会)于2015年6月将该协议列为行业标准。智能手机普及以来,很多电子乐器中都加入了蓝牙MIDI的功能,可以通过蓝牙与手机或者平板电脑连接,从而实现智能教学。 

1647312938364321.png

蓝牙MIDI接口

蓝牙MIDI协议

蓝牙MIDI协议是使用低功耗蓝牙GATT作为传输层,协议格式仍与有线MIDI协议一致。想要通过低功耗蓝牙设备实现MIDI协议,需满足如下两个要求:

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

1647313030913616.png

二、GATT中要包含一个UUID为03B80E5A-EDE8-4B33-A751-6CE34EC4C700的服务,该服务里面要有一个UUID为7772E5DB-3868-4112-A1A9-F2669D106BF3的特性,并且该特性的操作权限为 Read,Write,Notify。

1647313076449231.png

蓝牙MIDI服务架构

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

MIDI指令格式

1647313120464413.png

MIDI指令格式

如上图所示,一个MIDI指令包含5个字节,前两个字节表示时间戳,其中第一个字节的前两位必须是10,第二个字节的第一位必须是1(时间戳可不填,全零),所以前两个字节通常是0x80,0x80。第三个字节表示设备的动作,比如按键按下或抬起,音量调节等等。第四个字节和第五个字节是参数,其含义要根据第三个字节决定。

在MIDI指令中,每一个音符都有对应的编码,部分简朴音符与MIDI编码对应如下表:

1647313175395058.png

上述表格中没有半音,下图以钢琴为例,给出了部分按键对应的MIDI编码:

1647313212604293.png

思考白键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表示琴键C4,第五字节无意义。

更多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系统推荐 泡泡钢琴,这些软件可通过下图二维码下载

1647313280496406.png

1647313325712479.png

1647313368350090.png

与对应的手机APP配合,就可以通过蓝牙硬件模拟智能乐器在手机上演奏了! 




关键词: 蓝牙     MIDI     乐器     DIY    

专家
2022-03-15 00:13:06     打赏
2楼

谢谢楼主分享


专家
2022-03-15 00:57:02     打赏
3楼

谢谢分享


专家
2022-03-15 05:38:39     打赏
4楼

谢谢分享


专家
2022-03-15 06:24:58     打赏
5楼

学习


专家
2022-03-15 06:57:20     打赏
6楼

谢谢分享


专家
2022-03-15 07:14:07     打赏
7楼

学习了,谢谢楼主的分享


专家
2022-03-15 09:39:01     打赏
8楼

谢谢分享


高工
2022-03-15 09:43:50     打赏
9楼

good


工程师
2022-03-15 12:38:38     打赏
10楼

学习


共47条 1/5 1 2 3 4 5 ›| 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]