生成的 MIDI 音符长度

发布于 2024-09-30 21:36:44 字数 904 浏览 2 评论 0原文

我创建了一些 JavaScript 代码,可以根据传递的音符和八度音程生成 MIDI 文件。在大多数情况下,它工作得相当好。问题是 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 音符 - play(0, 4, '18') 听起来比任何其他音符 - play(1, 4, '18') 短得多? 音高似乎是正确的,只是音符的演奏长度。

我认为这可能与 C 的值为 0 有关,但我对我在这里使用 midi 所做的事情了解不够,无法发现问题。

注意:此代码不适用于 IE(任何版本)。

I created some javascript code that generates midi files based on a passed note and octave. For the most part it works rather well. The problem is that the C note (note=0) plays much shorter than any other note (1 (C#) through 11 (B)).

Here is my code:

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;
}

Why is a C note - play(0, 4, '18') sound so much shorter than any other - play(1, 4, '18')?
The pitch seems to be correct, just the note's play length.

I think it may have something to do with C being of value 0, but I don't know enough about what I'm doing here with midi to spot a problem.

NOTE: This code does not work in IE (any version).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

栀子花开つ 2024-10-07 21:36:44

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

If I remember correctly, MIDI notes are played by giving a pitch and a velocity (i.e., loudness) between 1 and 127, and stopped by giving the same pitch with a velocity of 0.

ゝ杯具 2024-10-07 21:36:44

当注释值小于 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);

When the note value is less than 16, you will end up with an invalid escape sequence, i.e. %0 instead of %00. The unescape function will not turn that into a character, but leave it unchanged. As it is two characters instead of one, it spills over into the velocity byte and the rest of the MIDI code gets out of sync.

You can use code like this to format a number into two hexadecimal digits:

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

Use it to make the note value two digits:

var note = toHex(octave*12 + note);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文