生成midi音符长度

时间:2010-11-09 00:36:02

标签: javascript midi

我创建了一些基于传递的音符和八度音程生成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(任何版本)中不起作用。

2 个答案:

答案 0 :(得分:1)

如果我没记错的话,通过给出1到127之间的音高和速度(即响度)来播放MIDI音符,并通过以0的速度给出相同的音高来停止。

答案 1 :(得分:0)

当音符值小于16时,您将得到无效的转义序列,即%0而不是%00unescape函数不会将其转换为字符,但保持不变。因为它是两个字符而不是一个字符,它会溢出到速度字节中,其余的MIDI代码会不同步。

您可以使用这样的代码将数字格式化为两个十六进制数字:

function toHex(n) {
  var code = '0' + n.toString(16);
  return code.substr(code.length - 2, 2);
}

使用它将音符值设为两位数:

var note = toHex(octave*12 + note);