Drum Machine Version 1 complete

Hi Campers,

I finally finished my Drum Machine (version 1). This version passes all FCC tests, but I feel like there are improvements to be made, and I’d like to get some feedback from you.

As I am relatively new to React, I would also welcome any feedback on the way I wrote the code.

https://codepen.io/kiwisquash/pen/OeOzKW

Thanks in advance!

1 Like

I tried to play your drum machine in a musically timed rhythm and it seems to take too long to reload the sample before playing the sample again. Your code looks good and this is more how to use the audio tag.

I looked into the documentation for the audio tag and found this part relevant.

preload

This enumerated attribute is intended to provide a hint to the browser about what the author thinks will lead to the best user experience. It may have one of the following values:

  • none : Indicates that the audio should not be preloaded.
  • metadata : Indicates that only audio metadata (e.g. length) is fetched.
  • auto : Indicates that the whole audio file can be downloaded, even if the user is not expected to use it.
  • empty string : A synonym of the auto value.

The default value is different for each browser. The spec advises it to be set to metadata .

Usage notes:

  • The autoplay attribute has precedence over preload . If autoplay is specified, the browser would obviously need to start downloading the audio for playback.
  • The browser is not forced by the specification to follow the value of this attribute; it is a mere hint.

This enumerated attribute is intended to provide a hint to the browser about what the author thinks will lead to the best user experience. It may have one of the following values:

  • none : Indicates that the audio should not be preloaded.
  • metadata : Indicates that only audio metadata (e.g. length) is fetched.
  • auto : Indicates that the whole audio file can be downloaded, even if the user is not expected to use it.
  • empty string : A synonym of the auto value.

The default value is different for each browser. The spec advises it to be set to metadata .

Usage notes:

  • The autoplay attribute has precedence over preload . If autoplay is specified, the browser would obviously need to start downloading the audio for playback.
  • The browser is not forced by the specification to follow the value of this attribute; it is a mere hint.

Issues with web audio that have to be handled

  1. pre-loading into buffers after downloading all samples to be played
  2. getting samples to clip off playback when another event comes in.

i took a look at the output generated from your React code and looked at the <audio> tag.
I found no preload attribute set

First thing I would try is to set that attribute somehow like this

<audio controls preload="auto">
  <source src="horse.ogg" type="audio/ogg">
  <source src="horse.mp3" type="audio/mpeg">
  Your browser does not support the audio element.
</audio>

This might solve part of the issue.

Check out https://howlerjs.com/ as an alternative.
Take a look at how I used it in my drum sequencer (beyond the scope of the fcc project) to see how I consumed that library. I won’t plug my project here on yours but you can easily find it on the project feedback section.

Even with Howler.js my own drum sequencer has timing issues due the different implementation of the javascript engines across browsers and phones.

Using setInterval was the obvious choice but as it turns out setInterval is susceptible to timing issues due to it running on the main thread and sharing resources with the rest of the web browser. Audio programming is such a deep subject and I fell right into a rabbit hole while making it.

Check out the web audio api book http://www.allitebooks.org/web-audio-api/ if you’re interested in this stuff. Using web audio api is a bit more involved but worth it in the end. The engine runs in a separate thread completely untouched by the rest of the browser so it becomes immune to stuttering audio if used right.

1 Like

Thank you for taking the time to test my app and also for providing such a detailed feedback.

I tried setting the preload attribute to auto, but I didn’t notice a big change. I’ll try using some of the other alternatives you suggested to see if I could kill the delays.

1 Like

It probably has more to do with the length of the sample being played. <audio> tags are really meant to play songs with much more length and no regard for musicality other than the just playing the wave content. Take a look at my project code. You won’t find any audio tags at all and when you play the sequencer there is considerable overlap on the samples. Try using howler.js I think you will find the most success with that.

So the following change seems like it does the trick (at least on desktop):

document.getElementById(elem_id).play();

to

const sound = document.getElementById(elem_id);
sound.currentTime = 0;
sound.play();

I still have a pretty horrible delay on my phone browsers, but for now, I am happy that it seems to be working the way it should on desktop…

1 Like

That is the ticket! Basically what you did there is set the sample offset to 0 on each play. Don’t worry about mobile. It’s horrible for my drum sequencer as well. I’m not sure it really can be helped without getting into native IOS / Android apis.

I just did a finger drum jam on your drum machine and rocked it out! :sunglasses::100::dizzy::checkered_flag:

1 Like