背景
MIDI文件与WAV或MP3音频文件完全不同。MP3和WAV文件包含表示音频“记录”的字节,而MIDI文件具有存储在MIDI事件中的一系列MIDI消息,这些信息通知MIDI合成器要播放的虚拟乐器或MIDI音序器应使用的播放速度。这些消息存储在轨道中,轨道的集合构成一个MIDI序列,其事件可由音序器分析,并将其消息从音序器传输到合成器的接收器。
在大多数情况下,存储在MIDI事件中的MIDI消息是“音符开”消息,它告诉合成器播放特定的音符,或者是“音符关”消息,告诉合成器停止播放音符。这些消息包含两个数据字节,第一个数据字节通知合成器该音符的速度(较高的速度会导致一个更大的音符),而第二个字节则通知合成器该音符的演奏(即中音C)。事件本身还包含刻度,用于告知音序器何时发送消息。
挑战
面临的挑战是编写一个完整的程序或函数,以单轨MIDI序列分析一系列Note On和Note Off MIDI消息,并向STDOUT输出一个图表,该图表显示何时打开特定音符,何时关闭这些音符以及这些音符的速度。图表的纵轴表示音符值,应按以下说明进行标记,横轴表示以MIDI音调为单位的时间(尽管应保持未标记状态,以减少复杂性和间距问题)。
您的输入可能是四个单独的数组或列表,每个数组或列表包含一系列整数值。包含四个带有一系列整数值的子数组/子列表的二维数组或列表;或任何其他方便的方式;这表示音轨中具有“音符开启”和“音符关闭”消息的MIDI事件集合。这些数组中的第一个数组中的值指定音符,第二个数组中的音符指定力度,事件滴答声中的第三个音符,和音符关闭事件音符的第四个音符。例如,给定四个这样的数组:
{60, 62, 64, 65, 67}
{20, 40, 60, 80, 100}
{ 0, 4, 8, 12, 16}
{ 2, 6, 10, 14, 18}
分析每个数组的第一个元素会产生两个事件:在滴答0处发生的事件,其中包含一条消息,其中包含Note On命令,note 60(中间C)和note速度为20;以及在第2滴答处发生的事件,并带有一条带有“音符关闭”命令且音符和力度相同的消息。
规则
图表的左侧应显示降序显示的数字0到127(代表音符值),音符开始时,每个音符的持续时间(音符关闭记号减去音符开启记号)以及音符的力度。表示音符的符号取决于其速度:
- 0-15:
O
- 16-31:
=
- 32-47:
#
- 48-63:
-
- 64-79:
@
- 80-95:
+
- 96-111:
0
- 112-127:
*
您可以假设以下内容:
- 音符和力度的值将在[0,127]范围内。
- 四个阵列中每个阵列的长度将始终彼此相等。
这里有一些例子:
{60, 62, 64, 65, 67}
{20, 40, 60, 80, 100}
{ 0, 4, 8, 12, 16}
{ 2, 6, 10, 14, 18}
127|
126|
125|
...
67 | 00
66 |
65 | ++
64 | --
63 |
62 | ##
61 |
60 |==
59 |
...
2 |
1 |
0 |
{60, 48, 62, 47, 64, 45, 65, 43, 67, 41, 65, 43, 64, 45, 62, 47, 60, 48}
{63, 31, 75, 90, 12, 23, 122, 104, 33, 19, 57, 42, 5, 82, 109, 86, 95, 71}
{0, 0, 2, 2, 4, 4, 6, 6, 8, 8, 10, 10, 12, 12, 14, 14, 16, 16}
{2, 2, 4, 4, 6, 6, 8, 8, 10, 10, 12, 12, 14, 14, 16, 16, 18, 18}
127|
126|
...
68 |
67 | ##
66 |
65 | ** --
64 | OO OO
63 |
62 | @@ 00
61 |
60 |-- ++
59 |
...
49 |
48 |== @@
47 | ++ ++
46 |
45 | == ++
44 |
43 | 00 ##
42 |
41 | ==
40 |
...
1 |
0 |
这是一个示例,显示《欢乐颂》的前几个音符:
{48, 55, 64, 64, 65, 67, 55, 67, 65, 64, 62, 52, 55, 60, 60, 62, 64, 55, 64, 62, 62}
{45, 45, 63, 63, 63, 63, 89, 66, 66, 66, 66, 30, 30, 103, 103, 103, 103, 127, 55, 55, 55}
{ 0, 0, 0, 4, 8, 12, 16, 16, 20, 24, 28, 32, 32, 32, 36, 40, 44, 48, 48, 54, 56}
{16, 16, 2, 6, 10, 14, 32, 18, 22, 26, 30, 48, 48, 34, 38, 42, 46, 64, 50, 55, 64}
127|
...
67 | -- @@
66 |
65 | -- @@
64 |-- -- @@ 00 --
63 |
62 | @@ 00 - --------
61 |
60 | 00 00
59 |
58 |
57 |
56 |
55 |################++++++++++++++++================****************
54 |
53 |
52 | ================
51 |
50 |
49 |
48 |################
...
0 |
您可以将分数降低25%如果提交的内容以实际的MIDI序列为输入,可以分析您选择的任何音轨的Note On和Note Off消息,前提是它至少包含四个带有Note On和Note Off消息的事件,然后输出,如上所述的图表。
这是代码高尔夫,所以最短的代码获胜。祝好运!