MIDI (Musical Instrument Digital Interface) is a technical standard allowing a wide variety of electronic musical instruments, computers, and other related devices to connect and communicate with each other. In this article, we'll transform real-time MIDI input into sound using JavaScript, a popular and powerful scripting language.
Understanding the Basics of MIDI
Before diving into coding, it's essential to understand what MIDI represents. Unlike audio formats, MIDI does not contain recorded sound. Instead, MIDI contains messages, such as note on or off, pitch, velocity, and other digital signal changes. JavaScript can process these messages and turn them into musical sound output.
Setting Up the Environment
We are going to use the Web MIDI API, a cutting-edge feature in web browsers that allows interaction with MIDI hardware directly through JavaScript. To start, ensure that your browser supports the Web MIDI API.
Checking Browser Support
You can check if your browser supports MIDI with the code snippet below:
if (navigator.requestMIDIAccess) {
console.log('Web MIDI is supported.');
navigator.requestMIDIAccess().then(onMIDISuccess, onMIDIFailure);
} else {
console.log('Web MIDI is not supported in this browser.');
}
In the above example, if the browser supports the Web MIDI API, the requestMIDIAccess
method will attempt to access MIDI devices. It requires two callbacks: one for success, onMIDISuccess
, and one for failure, onMIDIFailure
.
Accessing MIDI Devices
When you have access to MIDI devices, you can map them to a usable JavaScript object:
function onMIDISuccess(midiAccess) {
const inputs = midiAccess.inputs;
inputs.forEach((input) => input.onmidimessage = handleMIDIMessage);
}
function onMIDIFailure() {
console.log('Could not access MIDI devices.');
}
Handling MIDI Messages
Once you've set up communication with MIDI devices, you can process their messages. Here's a basic function to handle the MIDI messages:
function handleMIDIMessage(message) {
const [command, note, velocity] = message.data;
switch (command) {
case 144: // Note on
if (velocity > 0) {
noteOn(note);
} else {
noteOff(note);
}
break;
case 128: // Note off
noteOff(note);
break;
}
}
function noteOn(note) {
console.log(`Note On: ${note}`);
// Insert sound synthesis code here
}
function noteOff(note) {
console.log(`Note Off: ${note}`);
// Insert code to stop sound here
}
In this example, when a note-on (command 144) is received, it calls noteOn
to trigger a sound. When a note-off (command 128) is received, it performs a noteOff
function to silence the sound. The ability to stop and start sounds makes MIDI a strong tool for controlling digital music software.
Synthesizing Sound with the Web Audio API
Now that we can capture MIDI input, we need to produce sound using the Web Audio API, which we can call at noteOn
and noteOff
. Here's a simple synthesizer set-up:
let audioContext = new (window.AudioContext || window.webkitAudioContext)();
let oscillator = null;
function noteOn(note) {
oscillator = audioContext.createOscillator();
oscillator.frequency.setValueAtTime(midiNoteToFrequency(note), audioContext.currentTime);
oscillator.connect(audioContext.destination);
oscillator.start();
}
function noteOff(note) {
if (oscillator) {
oscillator.stop();
}
}
function midiNoteToFrequency(note) {
return 440 * Math.pow(2, (note - 69) / 12);
}
In this simple synthesizer, an oscillator generates sound waves at a frequency based on the MIDI number. The function midiNoteToFrequency
converts MIDI notes to frequency using the standard formula for musical pitch conversion.
Conclusion
You've now built a basic system for transforming real-time MIDI input into sound using JavaScript. By integrating the Web MIDI API and the Web Audio API, your application can dynamically respond to MIDI inputs, opening doors to exciting real-time musical applications. As with any creative coding project, experimentation and exploration will yield the best results. Happy coding, and more importantly, happy music-making!