Table of Contents
What are MIDI and WebMIDI exactly?
Why would I want to do this?
What kind of things can I build?
What do I need to get started?
A MIDI controller
A WebMIDI-capable browser
Desktop
Mobile / Tablet
Hello, WebMIDI
Anatomy of a MIDI message
How this translates into WebMIDI and JavaScript
What kind of hardware can I use?
Can I build my own hardware?
Summary
Home Web Front-end CSS Tutorial Dip Your Toes Into Hardware With WebMIDI

Dip Your Toes Into Hardware With WebMIDI

Apr 13, 2025 am 10:30 AM

Dip Your Toes Into Hardware With WebMIDI

Did you know there is a well-supported browser API that allows you to interface with interesting and even custom-built hardware using a mature protocol that predates the web? Let me introduce you to MIDI and the WebMIDI API and show you how it presents a unique opportunity for front-end developers to break outside the browser and dabble in the world of hardware programming without leaving the relative comfort of JavaScript and the DOM.

What are MIDI and WebMIDI exactly?

MIDI is a niche protocol designed for musical instruments to communicate with each other. It was standardized in 1983 and is maintained to this day by an organization consisting of music industry companies and representatives. It’s not wildly different than how the W3C dictates and preserves web standards, in some sense.

The WebMIDI API is the browser-based implementation of this protocol and allows our web applications to “speak” MIDI and communicate with any MIDI-capable hardware that might be connected to a user’s device.

Not a musician? Don’t worry! We’ll discover very quickly that this simple protocol designed for electronic musical instruments can be used to build fun, interactive, and completely non-musical things.

Why would I want to do this?

Great question. The shortest answer: because it’s fun!

If that answer isn’t satisfying enough for you I’ll offer this: Creating something that straddles the line between the physical world and virtual world we spend most of our days building things for is a good exercise in thinking differently. It’s an opportunity for creative tinkering and for considering and creating new user interfaces and experiences to navigate. I truly think this kind of playful exploration helps make us use different parts of our brains and makes us better developers in the long-haul.

What kind of things can I build?

What do I need to get started?

Here are the prerequisites to start experimenting with WebMIDI:

A MIDI controller

This might be the trickiest part. You’ll need to procure a MIDI-capable piece of hardware to experiment with. You might be able to find something cheap on Craigslist, Amazon or AliExpress. Or — if you’re really ambitious and have an Arduino available — you can build your own (see the end of this article for more information about this).

A WebMIDI-capable browser

This browser support data is from Caniuse, which has more detail. A number indicates that browser supports the feature at that version and up.

Desktop

Mobile / Tablet

As of this writing, according to caniuse.com it’s supported by approximately 73% of browsers, though most of the heavy-lifting is done by Chromium. Any Chromium-based browser will support WebMIDI—that includes Electron apps and the newer Chromium-based Microsoft Edge. It’s also supported on Opera and the Samsung Internet Browser. On Firefox it’s still being discussed but hopefully coming sooner than later.

Hello, WebMIDI

Once you’ve procured both of those things we can start writing some code! Working with the WebMIDI is not terribly different than working with other browser APIs like the Geolocation or MediaDevices APIs, if you’re familiar with either of those.

The high-level flow looks like this:

  • We detect availability of the WebMIDI API in the browser.
  • If detected, we request permission from the user to access it.
  • Once we’re granted permission, we now have access to additional methods to detect and communicate with any connected MIDI devices.

Let’s see that in action:

if ("requestMIDIAccess" in navigator) {
  // The Web MIDI API is available to us!
}
Copy after login

Now, assuming we’re in a WebMIDI-capable browser, let’s request access:

navigator.requestMIDIAccess()
.then((access) => {
  // The user gave us permission. Now we can
  // access the MIDI-capable devices connected
  // to the user's machine.
})
.catch((error) => {
  // Permission was not granted. :(
});
Copy after login

If the user gives us permission, we should now have access to the MIDIAccess interface. This helps us build a list of the devices that we can receive MIDI input from and send MIDI output to.

Let’s do that next. This is the code that goes inside the function we’re passing into then from the previous code snippet:

const inputs = access.inputs;
const outputs = access.outputs;

// Iterate through each connected MIDI input device
inputs.forEach((midiInput) => {
  // Do something with the MIDI input device
});

// Iterate through each connected MIDI output device
outputs.forEach((midioutput) => {
  // Do something with the MIDI output device 
});
Copy after login

You might be wondering what the difference is between a MIDI input and output device. Some devices are setup to only send MIDI information to the computer (these will be listed as inputs) and others can receive information from the computer (these will appear as outputs). It’s not uncommon that a device can be send and receive, so you will find it listed under both.

Now that we have code that can iterate through all the connected MIDI devices, there are basically only two things we’ll want to do;

  • If it’s an input device, we’ll want to listen for any incoming MIDI messages emitting from it.
  • If it’s an output device, we might want to send MIDI message to it.

The code for setting up an event listener to respond to any incoming MIDI messages from our input devices looks very similar to an event listener you might setup for other DOM events, except in this case, the event we’re listening for is the midimessage event:

midiInput.addEventListener('midimessage', (event) => {
  // the `event` object will have a `data` property
  // that contains an array of 3 numbers. For examples:
  // [144, 63, 127]
})
Copy after login

If we want to send a MIDI message to an output device the code we can do so like this;

outputsend([144, 63, 127]);
Copy after login

Here is a CodePen demo with most of this put together for you. It will let you know about all of the MIDI inputs and output devices connected to your system and show you incoming MIDI messages as they happen:

See the Pen
WebMIDI Basic Test by George Mandis (@georgemandis)
on CodePen.

You might be wondering a couple things at this point:

  • When you’re listening for the midimessage event, how do I make heads or tails of that three number array in event.data?
  • Why did you send an array of three numbers to your MIDI output device and why did you send those specific numbers?

The answer to both of these questions lies in further exploring and understanding how the MIDI protocol works and the problems it was designed to solve.

Anatomy of a MIDI message

When a MIDI controller “speaks” to another MIDI-capable device or computer, they are sending and receiving MIDI messages with one another. The protocol underlying this communication is fairly simple in practice but a little verbose when explained. Still, I’ll try.

Every MIDI message consists of three bytes consisting of 8-bits (0-255). Represented in binary, a message might look like this:

10010000 | 00111100 | 01111111
Copy after login

There are only two types of MIDI messages: Status and data. Every message will consist of one status byte and two data bytes.

The status byte is intended to communicate what kind of message is being delivered, including things like:

  • Note On
  • Note Off
  • Pitch Bend Change
  • Control/Mode Change
  • Program Change

…and many others.

If you’re coming at this from a non-musical background, these status messages might seem kind of strange, but don’t worry too much about it. The data byte is intended to provide more information and context to the status. To give an example, if I have a MIDI piano plugged into my machine and press a key to play a note, it would send a “Note On” status byte accompanied by data bytes indicating which note I played, and perhaps how hard I pressed it.

A status byte will always begin with the number 1 and data bytes with the number 0.

1x0010000 | 0x0111100 | 0x1111111
    ^status     ^data1      ^data2
Copy after login

For data bytes that leaves 7-bits to express the data in that byte. That gives us an integer range of 0-127.

For status bytes, the next 3-bits after the first describe the type of status message while the remaining 4-bits describe the channel. To break down our binary representation:

1x001x0000
Copy after login

How this translates into WebMIDI and JavaScript

As you may have guessed from the code samples earlier, with the WebMIDI API, we seldom have to deal with these binary representations directly. When we send and receive these messages in JavaScript we simply use arrays like this:

[144, 63, 127]
Copy after login

If you’re working with existing musical hardware, it’s helpful to have this deeper understanding of how and why the messages are structured the way they are. It’s helpful to know that receiving a 144 in your first byte means a note is being turned on in the first channel and that a 128 would indicate that a note is being turned off.

However, if we’re building non-musical experiences and creating our own hardware, these numbers can be repurposed to represent whatever you want!

What kind of hardware can I use?

Any MIDI-capable device that can be connected to your computer should also be accessible through the WebMIDI API. Devices that are capable of sending MIDI data to another MIDI-capable device are often called MIDI controllers. A common example would be a simple, piano-style keyboard like this Korg nanoKey2:

But they can vary widely in appearance and modes of interaction. Buttons are certainly common, but you might also find some that incorporate dials or pressure-sensitive pads like the AKAI LPD8:

Others use more abstract and interesting modes of interaction, including mapping motion or breath to MIDI signals. For example, this controller (The Hothand from Source Audio) uses three accelerometers to map hand gestures to MIDI messages:

Some controllers can both send and receive MIDI messages, allowing for you to have a true two-way conversation with the physical world. The Novation Launchpad is a classic example — buttons can be pressed to send messages and messages can also be received to dynamically change colors on the device:

Can I build my own hardware?

It turns out they’re not terribly difficult to build and you can find a lot of home-brewed MIDI controllers out in the wild. They can get much more elaborate in a hurry. Some can be downright bananas:

Building your own MIDI controller will take you a bit outside the world of JavaScript, but it’s still surprisingly accessible if you’re familiar with or interested in the Arduino platform. The Circuit Playground Classic from Adafruit is a great device to get started with and you can find starter code to flash to the device and make it into a multi-faceted MIDI controller here on GitHub.

Summary

The WebMIDI API is a low-barrier-to-entry way for front-end developers to start experimenting with basic hardware and software interactions. The implementation is relatively straightforward compared to some other hardware web APIs (like Bluetooth) and the MIDI standard is well-documented. There are lots of existing MIDI-capable devices out there to experiment or build cool things with, and if you really want to go all-out and start building your own custom MIDI hardware for your project, you can do that too.

Go out there and make something!

The above is the detailed content of Dip Your Toes Into Hardware With WebMIDI. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

Vue 3 Vue 3 Apr 02, 2025 pm 06:32 PM

It's out! Congrats to the Vue team for getting it done, I know it was a massive effort and a long time coming. All new docs, as well.

Building an Ethereum app using Redwood.js and Fauna Building an Ethereum app using Redwood.js and Fauna Mar 28, 2025 am 09:18 AM

With the recent climb of Bitcoin’s price over 20k $USD, and to it recently breaking 30k, I thought it’s worth taking a deep dive back into creating Ethereum

Can you get valid CSS property values from the browser? Can you get valid CSS property values from the browser? Apr 02, 2025 pm 06:17 PM

I had someone write in with this very legit question. Lea just blogged about how you can get valid CSS properties themselves from the browser. That's like this.

Stacked Cards with Sticky Positioning and a Dash of Sass Stacked Cards with Sticky Positioning and a Dash of Sass Apr 03, 2025 am 10:30 AM

The other day, I spotted this particularly lovely bit from Corey Ginnivan’s website where a collection of cards stack on top of one another as you scroll.

A bit on ci/cd A bit on ci/cd Apr 02, 2025 pm 06:21 PM

I'd say "website" fits better than "mobile app" but I like this framing from Max Lynch:

Comparing Browsers for Responsive Design Comparing Browsers for Responsive Design Apr 02, 2025 pm 06:25 PM

There are a number of these desktop apps where the goal is showing your site at different dimensions all at the same time. So you can, for example, be writing

Using Markdown and Localization in the WordPress Block Editor Using Markdown and Localization in the WordPress Block Editor Apr 02, 2025 am 04:27 AM

If we need to show documentation to the user directly in the WordPress editor, what is the best way to do it?

Why are the purple slashed areas in the Flex layout mistakenly considered 'overflow space'? Why are the purple slashed areas in the Flex layout mistakenly considered 'overflow space'? Apr 05, 2025 pm 05:51 PM

Questions about purple slash areas in Flex layouts When using Flex layouts, you may encounter some confusing phenomena, such as in the developer tools (d...

See all articles