This is a drum machine created for my dear friend Matt Miller for Friendmas.
The drum machine isn't a typical drum machine with snares, kicks, and hats; instead, this drum machine uses samples of Matt saying random phrases - samples which I acquired under false pretenses. Sorry Matt.
I'd like to acknowledge Vincent Riemer for his excellent React/Redux drum machine io808. Much of the patterns in this repo were based off his decisions.
Enjoy!
npm install
should do the trick.
Then npm run start
The files for configuring and loading the samples, and making the drum machine work are located directly under the src folder.
drumConfig.js exports an array of objects that configure each drum. These objects have five keys:
- label - Currently not used, but this field was orignally intended to display the sample name within the drum section.
- type - This identifies the particular drum type. This field needs to be unique amongst all the drum configs as it is used heavily throughout the application as an identifier.
- color - This decides what color the drum pad row will be for this drum.
- MATT_MODE - This is a pointer to the locatino of the drum sample to play when the drum machine is in MATT_MODE
- TIANA_MODE - Same as above except for TIANA_MODE
drumControls.js exports the initial state for the parameters that control each drum - speed, level, and pan, which correspond to playbackRate, gain, and pan, respectively, in the Web Audio context.
drumBuffer.js exports an empty object that will be filled with the buffers of each audio sample upon load. Since the Redux state doesn't support non-serializable data, we simply store a key in the state that we can use to grab the buffer data from the drumBuffer object.
DrumLoader.js is rendered into the root element to trigger loading each drum listed under drumConfig.js.
Sequencer.js is rendered into the root element to control playback of sounds using the Redux state and Web Audio API. It is also responsible for dispatching the action that moves the Redux state step counter forward. Currently, this file also contains the methods connecting each drum through the various audio nodes like pan, gain, and playback rate. This should probably be refactored so the playSound
method need to be so declarative in nature. It'd be nice to link the parameters exported by drumControls.js
to the playSound
method in a more interface-like manner. Currently, if we wanted to add a new effect, we'd have to write a new key in the drumControls object, and then write more code in the playSound
method to interpret that key correctly.
audioCtx.js exports the audioContext and WAAClock instance that will be shared throughout the entire application.
The layout
folder shows the different sections of the application. ControlSection
is the bottom section of the app that controls tempo, pause/play, etc. DrumSection
which is the left hand section of the app for controlling drum parameters. PadSection
which is the main section where the drum pads are. Each of these folders exports the main layout within the respective index.js
file. The container components should be found under the connectedComponents
file. These components retrieve the Redux state and pass it to the presentation components. Ideally, all the presentation components should be under the components
folder. Right now, most of the presentation components are found in the connectedComponents
file. That's my bad. I started rushing.
All the main sections are used by the AppLayout
component to lay out the application. The app uses flexbox as it's main layout resource. This might have to be changed, as basic testing has revealed a lot of computation is wasted when resizing the window. I think flexbox might be to blame.
-
It would be nice to have the actual sound files, which currently reside under the
wav
folder, to be hosted elsewhere on some CDN or something. -
Create a more reusable
button
component. The app uses the CSS property radial-gradient and box-shadow to create the Maschine-like styled buttons. It'd be nice to have a componentButton
that can take as props width, height, and colors to apply to the radial gradient and box shadow properties. -
A Solo button would be nice to have to.
-
Export to .wav would be nice.
-
Save and share beats. This would require the most work, as adding this feature means putting in server side code to store all the needed parts of the Redux state to play a beat. And since this app is currently all client side, that'd be a big change.