mudcube / MIDI.js

:musical_keyboard: Making life easy to create a MIDI-app on the web. Includes a library to program synesthesia into your app for memory recognition or for creating trippy effects. Convert soundfonts for Guitar, Bass, Drums, ect. into code that can be read by the browser. Supports multiple simultaneous instruments and perfect timing.
http://mudcu.be/midi-js/
MIT License
3.81k stars 640 forks source link

Play a MIDI file note by note? #223

Open raul4740 opened 6 years ago

raul4740 commented 6 years ago

Is there a way to make a MIDI file playable note by note? What i intend to do is a musical piano game where you play the song note by note with keyboard events. What would be the simplest way to do this? With the player functions i can only play pause and resume the loaded midi.

shivrajsa commented 6 years ago

Please check demos on main page of MIDI.js, some are similar to your requirement. Especially Piano Typewriter and Color Piano

raul4740 commented 6 years ago

But is there a way to take a look at the code? Or do you have a basic/sample implementation or playing the midi file note by note? Thanks for replying, I appreciate it.

shivrajsa commented 6 years ago

Here is the one http://mudcu.be/midi-js/ with code https://github.com/mudcube/MIDI.js/blob/master/examples/MIDIPlayer.html It is basic example of player from this repository

raul4740 commented 6 years ago

But that player just plays the whole midi file and implements a pause/resume function. Is there a way to make it only play the first note of the midi? I managed to load it using MIDI.Player.loadFile("Final Fantasy - Prelude.mid", MIDI.Player.start); But it plays the whole song through. Also how exactly is your example loading the midi file? Do I need to implement it like you did? image

shivrajsa commented 6 years ago

Take a look at below code from same example, especially data.note which gives you note value of each note

player.addListener(function(data) {
                    var pianoKey = data.note - 21;
                    var d = colorElements[pianoKey];
                    if (d) {
                        if (data.message === 144) {
                            var map = colorMap[data.note - 27];
                            if (map) d.style.background = map.hex;
                            d.style.color = "#fff";
                        } else {
                            d.style.background = "";
                            d.style.color = "";
                        }
                    }
                });

And below are available properties of data

MIDI.Player.addListener(function(data) { // set it to your own function!
    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
    // then do whatever you want with the information!
});

It is mentioned on the project page.

shivrajsa commented 6 years ago

Check this issue https://github.com/mudcube/MIDI.js/issues/225 , it may help to solve your question

duhaime commented 3 years ago

Something like the following plays notes one by one:

MIDI.loadPlugin({
  soundfontUrl: "./soundfont/",
  instrument: "acoustic_grand_piano",
  onsuccess: function() {
    var time = 0;
    var velocity = 120;
    MIDI.setVolume(0, velocity);

    MIDI.noteOn(0, 60, velocity, time);
    MIDI.noteOff(0, 60, time + 1);

    MIDI.noteOn(0, 64, velocity, time+2);
    MIDI.noteOff(0, 64, time + 3);
  }
});

To get the sequence of notes in a midi file, you can use:

MIDI.loadPlugin({
  soundfontUrl: "./soundfont/",
  onsuccess: function() {
    MIDI.Player.loadFile('u-s-s-r.midi', function() {
      console.log(MIDI.Player.data);
    });
  }
});

The logged data contains the midi event sequence, which contains the notes. See this example.