DFRobot Leonardo & Xbee R3 实现MIDI播放

2022-02-161.2万
精华项目
AI 快速预览详细 收起
本文介绍了如何使用DFRobot Leonardo & Xbee R3板子实现MIDI消息发送,并通过电脑软件进行播放。首先,通过MIDI编辑软件找到主要音轨并提取数据,然后使用MIDI转CSV工具将MIDI文件转换为CSV文件。接着,编写简单的代码来发送MIDI消息,实现音乐播放。这种方法比手动输入乐谱更省时省力,并且可以通过播放软件确认结果是否正确。
MIDI(Musical Instrument Digital Interface)乐器数字接口 ,是20 世纪80 年代初为解决电声乐器之间的通信问题而提出的。MIDI是编曲界最广泛的音乐标准格式,可称为“计算机能理解的乐谱”。它用音符的数字控制信号来记录音乐。一首完整的MIDI音乐只有几十KB大,而能包含数十条音乐轨道。几乎所有的现代音乐都是用MIDI加上音色库来制作合成的。MIDI传输的不是声音信号, 而是音符、控制参数等指令,它指示MIDI 设备要做什么,怎么做, 如演奏哪个音符、多大音量等。它们被统一表示成MIDI消息(MIDIMessage)
这次的目标是使用 DFRobot DFRobot Leonardo & Xbee R3板子来实现发送 MIDI消息,然后通过电脑上的软件进行播放。这个板子的核心是Atmel 32U4 单片机,内部支持 USB Device,因此可以用来将自身模拟为一个USBMIDI设备(你可以想象为一个自动演奏的钢琴键盘)。
首先介绍一下歌曲的获得。经过研究,可以在网上找到MIDI文件,然后使用MIDI编辑软件打开之。这里我使用的是 MCH MixPad。通常MIDI会有多个音轨,比如伴奏等等。这时候需要找到主要的音轨,可以通过下图指示出来的位置选择对不同的音轨静音然后预览。下面的MIDI文件中第一个(最上面)的音轨是主旋律,里面包含我们需要的数据。
DFRobot Leonardo & Xbee R3 实现MIDI播放图3
接下来我们需要将这个音轨提取出来。我这里使用一个MIDICSV的小工具。这个工具有两个软件,一个是将MIDI转为CSV 的,另外一个是相反的,将CSV中的数据生成为 MIDI
DFRobot Leonardo & Xbee R3 实现MIDI播放图1
使用非常简单,输入 MID文件名然后再给出生成的名称,然后就得到了数据:
DFRobot Leonardo & Xbee R3 实现MIDI播放图2
前面提到了,MIDI文件中有多个音轨,生成的 CSV文件中,会以Start_track字符串作为标志开启数据记录。比如:下面  Title_t Track 1 开始的数据就是我们需要的。
DFRobot Leonardo & Xbee R3 实现MIDI播放图4
简单看一下数据:
DFRobot Leonardo & Xbee R3 实现MIDI播放图5
第一列是数据的类型号,比如2开始的都是前面提到的Track1 数据。接下来是这个事件发生的时间。然后Note_on_c是表示一个消息,后面是它的参数,第一个参数是 Channel 号;然后是Note(可以理解为钢琴的按键编号,一般 60 对应的C4);最后是按键力度,0表示按键抬起。整理上面的数据然后我们就有一个 .h 文件:
DFRobot Leonardo & Xbee R3 实现MIDI播放图6
接下来是软件的设计,代码很简单,开始之后不断检查时间标志,如果当前取得的时间大于Current指向的时间那就发送后面的 midi 消息。
  1. #include "MIDIUSB.h"
  2. #include "chysx.h"
  3. uint32_t start;
  4. uint16_t current = 0;
  5. // First parameter is the event type (0x09 = note on, 0x08 = note off).
  6. // Second parameter is note-on/note-off, combined with the channel.
  7. // Channel can be anything between 0-15. Typically reported to the user as 1-16.
  8. // Third parameter is the note number (48 = middle C).
  9. // Fourth parameter is the velocity (64 = normal, 127 = fastest).
  10. void noteOn(byte channel, byte pitch, byte velocity) {
  11.   midiEventPacket_t noteOn = {0x09, 0x90 | channel, pitch, velocity};
  12.   MidiUSB.sendMIDI(noteOn);
  13. }
  14. void setup() {
  15.   Serial.begin(115200);
  16.      start = millis();
  17. }
  18. // First parameter is the event type (0x0B = control change).
  19. // Second parameter is the event type, combined with the channel.
  20. // Third parameter is the control number number (0-119).
  21. // Fourth parameter is the control value (0-127).
  22. void controlChange(byte channel, byte control, byte value) {
  23.   midiEventPacket_t event = {0x0B, 0xB0 | channel, control, value};
  24.   MidiUSB.sendMIDI(event);
  25. }
  26. void loop() {
  27.   
  28.   if (millis() - start > music[current].time*3) {
  29.     Serial.println(current);
  30.     noteOn(0, music[current].ctrlnum, music[current].value);
  31.     MidiUSB.flush();
  32.     noteOn(0, music[current + 1].ctrlnum, music[current + 1].value);
  33.     MidiUSB.flush();
  34.     if (current == 302) {
  35.       current = 0;
  36.       start = millis();
  37.     } else {
  38.       current += 2;
  39.     }
  40.   }
  41. }
复制代码

其中的判断语句  if (millis() - start >music[current].time*3)  可以用来调整播放速度,如果想慢一点就增加乘以的数值,反之就是加速。
本文最关键的部分在于如何获得歌谱,这样的方法比自己对照乐谱敲出来省事得多,另外还可以用播放软件来确认结果是否正确。

参考:


创作许可协议

本项目采用 None(不开放任何权利,保留所有权利) 进行许可。

评论(7)
三春牛-创客
三春牛-创客
MIDI播放
三春牛-创客
三春牛-创客
6666666666
三春牛-创客
三春牛-创客
呵呵呵呵
三春牛-创客
三春牛-创客
值得学习!
三春牛-创客
三春牛-创客
大神厉害了!
三春牛-创客
三春牛-创客
哇!!!!!!!!!
zoologist
zoologist
作者
本文提到的 MIDI 文件下载
MIDICSV 工具
完整的源代码

测试的视频[media=x,500,375]https://www.bilibili.com/video/BV1fF41177Rx/[/media]
- 没有更多了 -