How to implement this solution in MIDI.js ?
shivrajsa opened this issue · 0 comments
shivrajsa commented
Hello I use MIDI.js in my App to play sequence of notes.
I have array of notes and array of delay, and I iterate though it using for loop.
var notes = [67, 78, 67 ,67,90, 56,..,...,....]
var delay = [.........]
for(var i=0; l < notes.length; i++)
{
MIDI.noteOn(channel, notes[i], velocity, delay[i]);
}
When array of notes is long [ 300+ ] then result is not good and browser struggles to play such long sequence.
Is it possible to schedule partial number of notes [ 25 notes ] at any given time and when it is close to finish that sequence then schedule next 25 notes so that load on browser can be controlled to get good result ?
For reference, here is the code of midi.noteOn
function of MIDI.js which uses setTimeout
function to play notes.
midi.noteOn = function(channelId, noteId, velocity, delay) {
delay = delay || 0;
/// check whether the note exists
var channel = root.channels[channelId];
var instrument = channel.instrument;
var bufferId = instrument + '' + noteId;
var buffer = audioBuffers[bufferId];
if (!buffer) {
// console.log(MIDI.GM.byId[instrument].id, instrument, channelId);
return;
}
/// convert relative delay to absolute delay
if (delay < ctx.currentTime) {
delay += ctx.currentTime;
}
/// create audio buffer
if (useStreamingBuffer) {
var source = ctx.createMediaElementSource(buffer);
} else { // XMLHTTP buffer
var source = ctx.createBufferSource();
source.buffer = buffer;
}
/// add effects to buffer
if (effects) {
var chain = source;
for (var key in effects) {
chain.connect(effects[key].input);
chain = effects[key];
}
}
/// add gain + pitchShift
var gain = (velocity / 127) * (masterVolume / 127) * 2 - 1;
source.connect(ctx.destination);
source.detune.value = detuneCents;
source.playbackRate.value = 1; // pitch shift
source.gainNode = ctx.createGain(); // gain
source.gainNode.connect(ctx.destination);
source.gainNode.gain.value = Math.min(1.0, Math.max(-1.0, gain));
source.connect(source.gainNode);
if (useStreamingBuffer) {
if (delay) {
return setTimeout(function() {
buffer.currentTime = 0;
buffer.play()
}, delay * 1000);
} else {
buffer.currentTime = 0;
buffer.play()
}
} else {
source.start(delay || 0);
}
///
sources[channelId + '' + noteId] = source;
///
return source;
};