我创建了一些基于传递的音符和八度音程生成midi文件的javascript代码。在大多数情况下,它运作得相当好。问题是C音符(音符= 0)比任何其他音符(1(C#)到11(B))短得多。
这是我的代码:
function play(note, octave, program){
var note = (octave*12 + note).toString(16);
var velocity = 'ff';
var MIDI_DATA =
'MThd%00%00%00%06%00%01%00%01%00%C0' + // midi header
'MTrk%00%00%00%0E' + // track header
'%00%C0%'+program+
'%00%90%'+note+'%'+velocity+
'%70%30%00' +
'%00%FF%2F%00';
MIDI_DATA = btoa(unescape(MIDI_DATA));
var e = document.createElement('embed');
e.src = "data:audio/mid;base64,"+MIDI_DATA;
e.type = "video/quicktime";
document.body.appendChild(e);
return e;
}
为什么C音符 - 播放(0,4,'18')听起来比任何其他声音短得多 - 播放(1,4,'18')? 音调似乎是正确的,只是音符的播放长度。
我认为它可能与C值为0有关,但我不知道我在midi做什么来发现问题。
注意:此代码在IE(任何版本)中不起作用。
答案 0 :(得分:1)
如果我没记错的话,通过给出1到127之间的音高和速度(即响度)来播放MIDI音符,并通过以0的速度给出相同的音高来停止。
答案 1 :(得分:0)
当音符值小于16时,您将得到无效的转义序列,即%0
而不是%00
。 unescape
函数不会将其转换为字符,但保持不变。因为它是两个字符而不是一个字符,它会溢出到速度字节中,其余的MIDI代码会不同步。
您可以使用这样的代码将数字格式化为两个十六进制数字:
function toHex(n) {
var code = '0' + n.toString(16);
return code.substr(code.length - 2, 2);
}
使用它将音符值设为两位数:
var note = toHex(octave*12 + note);