Library / SDK
vincentriemer/io-808 avatar
vincentriemer/io-808

io-808: a TR-808 drum machine where every sound is synthesised

An attempt at a fully recreated web-based TR-808 drum machine.

743 stars82 forksJavaScriptMIT

At a glance

What is it?
io-808 is a browser recreation of the Roland TR-808 that contains no samples at all. Every voice, from the bass drum to the cymbal, is generated with the Web Audio API, and the state is held in a Redux store that tracks more than twelve thousand steps. It is a hobby project from a bedroom producer who learned the Web Audio API by building it, and the guide is honest about which features were never finished.
Who is it for?
Adopt io-808 if you want to study how analog drum circuits are modelled in the Web Audio API, since every voice is a synthesis graph rather than a sample and the source is readable. Do not adopt it as a working instrument, because play mode, compose mode, pre-scale and tap tempo triggers are listed as not yet implemented and every pattern is hardcoded to a pre-scale of three.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 66 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The premise: no samples anywhere

io-808 is an attempt at a fully recreated web-based TR-808 drum machine, and the design constraint that defines it is stated bluntly in the dependency overview: all of the sound generated by this drum machine are synthesized using the Web Audio API, look mom, no samples.

That is a large undertaking. A drum machine is normally a collection of samples of a hardware unit, and the easier path to a web version is to record the hardware once and trigger the recordings. Recreating the sounds instead means modelling what the original circuits did, which means understanding the oscillators, filters and envelopes behind each voice and rebuilding them as an audio graph.

The author explains the motivation directly. As an amateur and bedroom music producer, he was fascinated with the impact and history of the TR-808, and while trying to learn the new Web Audio API he attempted to recreate a few of the sounds by referencing the Sound on Sound Synth Secrets series and the block diagrams of the 808 itself. It became addictive, and once he had most of the sounds done, recreating the interface and functionality was the next logical step.

So the project has two halves that happened in sequence. The synthesis came first as a way to learn an API, and the interface came second as the way to make the sounds usable. That order explains the state of the code, and it explains the pattern of what is finished and what is not.

The honesty is refreshing. The guide notes that while the sounds came fairly close to the original hardware, there is still a lot of room for improvement, and it names the two offenders directly: the cymbal and the rimshot.

The site is io808.com, and the licence is MIT, which is worth noting for a project that reproduces a well-known instrument's sound, since no sample data is redistributed.

The sound engine: Web Audio API plus one scheduling library

The sound generation itself is remarkably dependency-light, and that is the point.

The only Web Audio API related external library used is WAAClock, which is used for scheduling the drum hits. Everything else is the platform API. That is a strong statement about what the Web Audio API can do, because scheduling is normally the hard part: a drum machine has to fire hits at precise times against a clock, and if the timing is wrong the groove falls apart regardless of how good the synthesis is.

So the architecture is that the Web Audio API provides the voices, WAAClock provides the timing, and everything else in the dependency list is about the user interface and the state.

The reason WAAClock is needed at all is worth understanding, and the guide is helpful on this point. It is used for scheduling the drum hits, meaning there is a separation between when a hit is requested and when the audio is actually scheduled to sound. In a step sequencer that distinction is everything: if a user triggers a note and the sound is played immediately, the timing inherits the jitter of the input event and of the main thread, and a pattern recorded by tapping will not line up with itself on playback.

The rest of the stack is described in the same plain style. React powers the UI. Redux is used for state management, in conjunction with redux-localstorage for state persistence and react-redux for connecting the React components to the Redux store.

And then the two libraries that show this was a real engineering effort rather than a weekend demo. reselect is used for efficiently computing values from the Redux store, and the reason given is that a lot of the UI state depends on the state of other components, so the library was a lifesaver in helping with the reasoning and performance of those dependencies. The immutable data structure library is used as the primary data structure for the Redux store, and the guide explains the reason with a number: the state store in this application is quite large, seriously, there are over 12,000 steps to keep track of, so in order to ensure maximum performance for mutating the state, this library mattered, and it is a whole lot smaller than ImmutableJS.

That is the key engineering fact about the whole project. Twelve thousand steps is a sequencer with a hundred and twenty patterns' worth of sixteen-step bars, and the performance of the state layer is what determines whether the UI can keep up with what the sequencer is doing.

Styling with Radium, and the reason it is a dependency rather than a CSS file

The styling choice is Radium, and the reasoning is given in the same first-person register as the rest of the guide.

Radium is used for styling of all React components. All of the styles in the webapp are done through inline styles, and in the few places I needed something like a :hover selector, Radium provided it. It also does not hurt that it autoprefixes all of the inline styles.

So the architecture is that the entire interface is styled with inline style objects rather than with stylesheets. Radium is the layer that makes that possible, because React's style prop does not support pseudo-selectors, and Radium resolves them at build time by generating a stylesheet and mapping the class names back onto the elements. The autoprefixing comes for free with that mechanism.

This is a deliberate choice with a real trade-off. Inline styles mean the styling lives in the JavaScript, next to the component that uses it, and there is no separate stylesheet to load or maintain. The cost is that you lose the cascade and you lose the ability to restyle from outside the app, which is the sort of thing that matters for a project like a drum machine where the look is part of the appeal.

The repository layout shows the design in more detail. There is an svg/ directory, which is where the 808's panel graphics come from, and a static/ directory. There is an 808js.sketch file, so the interface design was done in Sketch and exported as SVG, which is a normal pipeline for recreating a hardware panel faithfully. There is also a theme.css and a theme.js at the root, plus the base splash and favicon images, and a CNAME file, which is the GitHub Pages custom domain configuration for io808.com.

The splashscreens/ directory holds the app icons for mobile home screens, which is a detail that only matters if you intend to add the app to a phone's home screen, which for a web app of this kind is a reasonable thing to want.

What is not implemented, which is the honest part of the feature list

There is a section headed Features Not Yet Implemented, and it is the most useful part of the guide for anyone considering this project.

The reason given is a deadline rather than a technical obstacle. In order to meet his personal deadline of 8/08 for his initial release, the author had to skip a few of the features of the original 808.

The list is specific. PLAY mode. COMPOSE mode. PRE-SCALE, with the note that every pattern is currently hardcoded to 3. And adding triggers via the TAP button.

So the sequencer part of the machine is the incomplete part. The sounds are largely there, and the interface is there, but the workflow features of the original hardware are not. PLAY mode on the real 808 is the mode where the machine plays a pattern continuously rather than waiting for you to trigger each step, and COMPOSE mode is where you record into the pattern while the sequencer runs. Both of those are missing, and PRE-SCALE being hardcoded to 3 means the swing and the note-length variations the hardware offered are not there either.

The TAP button is a different kind of gap, because that is about input rather than about sequencing. Tap tempo, where you tap a button in time and the machine infers the tempo, is a small feature that is entirely missing, which is a bit of a shame given that a drum machine built around a Web Audio clock is exactly the kind of thing where tap tempo would be natural to implement.

The closing note says the author will be continuously working on these features as well as improving the synthesis of each sound to greater match the sounds of the original hardware. So the intent is clear, and the list is a to-do rather than a permanent limitation. But it is a to-do that has been on the list for a while: the last push to the repository was on 2026-08-18, and the package version is 2.0.0.

The build: two webpack bundles, a generated tutorial, and two deployment targets

The build setup is the part of the repository that has aged most, and it is worth reading because it explains how a project like this gets to a static site.

The scripts in package.json are the map. The build runs a clean, then build:webpack, then build:docs. The webpack step is the interesting one because it builds twice, once with the modern configuration and once with the legacy one, under the names modern and legacy. That is a deliberate split for browser support, and the browserslist field at the root of the manifest sets the target as greater than 0.2 percent, not dead, not op_mini all.

The documentation is generated rather than written. build:docs runs node buildTutorial.js in production mode, and the repository has a tutorial/ directory that it generates into. There is a separate tutorialDev.js for the development loop, and the tutorial-dev script runs it. The built tutorial is a separate artefact from the app, which is a reasonable choice for a project that wants an in-app guide without shipping a documentation site.

There are two deployment paths, and both are in the repository. deploy-ghpages.sh is the GitHub Pages path, which pairs with the CNAME file for the custom domain, and vercel.json configures Vercel as the alternative. The two-path setup reflects the project's history: GitHub Pages for the io808.com domain and Vercel as the modern default.

The rest of the toolchain is conventional for the era. Babel with the React preset and the class properties plugin, babel-loader, css-loader and html-loader, dart-sass, clean-css and autoprefixer, and webpack with separate dev and prod config files at the root. The ESLint setup is old, with eslint at 6.1.0 and the react and react-hooks plugins, and there is a .prettierrc for formatting with a fmt script that runs prettier over the source.

One entry stands out. The test script is true, which is a shell command that succeeds unconditionally. There is no test suite. The guide does not claim otherwise, and for a project of this kind, where the output is an audio graph and the interface is the verification, that is an understandable thing to leave out.

Editorial conclusion

Adopt io-808 if you want to study how analog drum circuits are modelled in the Web Audio API, since every voice is a synthesis graph rather than a sample and the source is readable. Do not adopt it as a working instrument, because play mode, compose mode, pre-scale and tap tempo triggers are listed as not yet implemented and every pattern is hardcoded to a pre-scale of three. Before you rely on it, read the feature list and check the last push date of 2026-08-18, and expect to work around the missing sequencer modes rather than a missing sound.

Frequently asked questions

Does io-808 use samples of the original TR-808?

No. All of the sound is synthesized using the Web Audio API, with no samples, and the only Web Audio related external library is WAAClock for scheduling the drum hits. The only non-original dependency in the audio path is WAAClock.

Which features of the original TR-808 are missing from io-808?

PLAY mode, COMPOSE mode, PRE-SCALE, which is hardcoded to 3 for every pattern, and adding triggers via the TAP button. The guide says these were skipped to meet a personal deadline of 8/08 for the initial release.

Why does io-808 use a small immutable library for its Redux store?

The state store is large, with over 12,000 steps to keep track of, so the library was used for maximum performance when mutating state, and it is a whole lot smaller than ImmutableJS. reselect is used alongside it for efficiently computing values from the store.

How is io-808 hosted?

There are two deployment paths in the repository, a deploy-ghpages.sh script paired with a CNAME file for the io808.com custom domain, and a vercel.json for Vercel. The build script compiles the webpack bundles twice, for modern and legacy browser targets, and then generates the tutorial documentation.

Official sources

  1. Issues
  2. License: MIT
  3. Project website
  4. README
  5. vincentriemer/io-808 on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/vincentriemer-io-808.svg)](https://hysenlabs.com/projects/vincentriemer-io-808)

Was this useful?