你如何转置midi文件?

时间:2014-02-26 19:16:10

标签: javascript html5 audio midi web-midi

我正在使用这个MIDI.js库:https://github.com/mudcube/MIDI.js

要加载插件并播放midi文件,我这样做:

window.onload = function () {
    MIDI.loadPlugin({
        soundfontUrl: "./soundfont/",
        instruments: [ "acoustic_grand_piano" ],
        callback: function() {
            MIDI.programChange(0, 0);   
                    _player = MIDI.Player;

        }
    });

};

function playSong(){            
        _player.timeWarp = 1; // speed the song is played back
        _player.loadFile(song[songid], _player.start);

        _player.addListener(function(data) {
            var now = data.now; // where we are now
            var end = data.end; // time when song ends
            var channel = data.channel; // channel note is playing on
            var message = data.message; // 128 is noteOff, 144 is noteOn
            var note = data.note; // the note
            var velocity = data.velocity; // the velocity of the note


        });
}

var songid = 0;
var song = ['data:audio/mid;base64,TVRoZAAAAA...

我的问题是,无论如何在播放之前转换这个midi文件?基本上我想解析midi文件(.mid文件或base64格式),将所有笔记改为+1,然后将其发送给播放器。有什么办法在javascript中做到这一点吗?

1 个答案:

答案 0 :(得分:0)

这不是一个完整的答案,但如果你仍然陷入困境,它可能会指出你正确的方向。它基于花几分钟时间查看MIDI.js的源代码以及它构建的几个软件包。我假设你想在读入文件时应用转置,并且对保存转置文件不是特别感兴趣。

  1. addListener方法不太可能有用。它看起来像是在音符被发送到合成器后立即发生的回调,即改变音高太迟了。
  2. 您需要找到将传入文件字符转换为javascript数组元素的函数。那可能是在jasmid库中。
  3. 如果您真的很幸运,开发人员将提供一个钩子,您可以使用该钩子设置回调以在函数将它们写入数组之前更改事件属性。否则,您需要相应地修改该功能。如果你能让它运行良好,试着说服开发人员将其修补到源代码中 - 否则你就会卡住维护自己的库分支。
  4. 希望这有帮助。

    编辑:我认为你想要的文件是https://github.com/gasman/jasmid/blob/master/midifile.js。您可以在处理从第155行开始的音符开事件的情况下应用转置

    case 0x09:
        event.noteNumber = param1;
        event.velocity = stream.readInt8();
        if (event.velocity == 0) {
            event.subtype = 'noteOff';
        } else {
            event.subtype = 'noteOn';
        }
        return event;
    

    或者,也就是说,在将返回的事件推到第227行的轨道数组之前

    while (!trackStream.eof()) {
        var event = readEvent(trackStream);
        tracks[i].push(event);