Creating a Piano using Reactjs - Audio( ) WebAPI and Hooks
Tags: react, javascript, webdev, github
Published: 2022-07-12 12:59:44

I recently participated in the **Hackbytes hackathon 2022 on Devfolio**, where I had created a piano using Reactjs. It was too good to be real. So, I thought of sharing the processs of actually creating one using Reactjs. Note that I will be ignoring the CSS Part and will only be focussing on Javascript.

So get Ready !

## **Download all the key sounds in mp3 format**
The first thing it to download all the key sounds. You must have a minimum of 7 white key sounds + 5 black key sounds = 12 key sounds ( 1 octave ) of any scale.<br>
I recommend downloading all the mp3 files from here - [https://freesound.org/people/Tesabob2001/packs/12995/](https://freesound.org/people/Tesabob2001/packs/12995/)
OR you can download the zip file of my repo on Github and navigate to - _/client/src/Components/Music/Sounds_ and extract all of them.<br>
Store all the mp3 files in a folder named 'Sounds'
Rename all the files in the below format for simplicity.
![audio files name](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eqr31h9pqmmm43wxclot.png)
 

## **Javascript Code**
Now comes the fun part! Which is the code. Create a component first ( a js/jsx file ). We will then have to create an object of the class ' _Audio_ ' and access its properties to play the sound.
_Sample code :_

![sample audio code](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/96vbhdimwkrt0kjy9i3m.png)

We will be creating an object for each and every mp3 file.

```  
  const C4 = new Audio(require('./Sounds/C4.mp3'));
  const Db4 = new Audio(require("./Sounds/Db4.mp3"));
  const D4 = new Audio(require("./Sounds/D4.mp3"));
  const Eb4 = new Audio(require("./Sounds/Eb4.mp3"));
  const E4 = new Audio(require("./Sounds/E4.mp3"));
  const F4 = new Audio(require("./Sounds/F4.mp3"));
  const Gb4 = new Audio(require("./Sounds/Gb4.mp3"));
  const G4 = new Audio(require("./Sounds/G4.mp3"));
  const Ab4 = new Audio(require("./Sounds/Ab4.mp3"));
  const A4 = new Audio(require("./Sounds/A4.mp3"));
  const Bb4 = new Audio(require("./Sounds/Bb4.mp3"));
  const B4 = new Audio(require("./Sounds/B4.mp3"));
  const C5 = new Audio(require("./Sounds/C5.mp3"));
  const Db5 = new Audio(require("./Sounds/Db5.mp3"));
  const D5 = new Audio(require("./Sounds/D5.mp3"));
  const Eb5 = new Audio(require("./Sounds/Eb5.mp3"));
  const E5 = new Audio(require("./Sounds/E5.mp3"));
```
 
The next step is to create a function named _playSound()_ which will accept audio object as an argument, create a cloned node and play the audio. 
More information about _cloneNode()_ can be found on the official docs - <a href = "https://developer.mozilla.org/en-US/docs/Web/API/Node/cloneNode">cloneNode() MDN Docs</a> | <a href = "https://developer.mozilla.org/en-US/docs/Web/API/HTMLAudioElement/Audio">HTMLAudioElement MDN Docs</a> | <a href = "https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/play">play() MDN Docs</a>

```
  const playSound = audio => {
    // creating a cloned node of the audio object
    const clone = audio.cloneNode()
    
    // calling the play() method to play the mp3 file
    clone.play()
  }
```


Next is importing the **useState hook** and we will be creating a variable named the piano key and a modifier function which will have a boolean value. This will toggle the state of the variable when we click on a particular key ( meaning - that when we click on a button ). If the key is clicked, we set the toggle_Key_ to ' __True__ ' , else ' __False__ '.We will be creating useState hooks for each and every key. 

```
import { useState } from 'react';
```
 
```
  // keys 
  const [C4Key , toggleC4key] = useState(false);
  const [Db4Key , toggleDb4key] = useState(false);
  const [D4Key , toggleD4key] = useState(false);
  const [Eb4Key , toggleEb4key] = useState(false);
  const [E4Key , toggleE4key] = useState(false);
  const [F4Key , toggleF4key] = useState(false);
  const [Gb4Key , toggleGb4key] = useState(false);
  const [G4Key , toggleG4key] = useState(false);
  const [Ab4Key , toggleAb4key] = useState(false);
  const [A4Key , toggleA4key] = useState(false);
  const [Bb4Key , toggleBb4key] = useState(false);
  const [B4Key , toggleB4key] = useState(false);
  const [C5Key , toggleC5key] = useState(false);
  const [Db5Key , toggleDb5key] = useState(false);
  const [D5Key , toggleD5key] = useState(false);
  const [Eb5Key , toggleEb5key] = useState(false);
  const [E5Key , toggleE5key] = useState(false);
```

Next is Creating the onClick() function. This is the function which will be called when a button is clicked. An event object will be passed to the function which will invoke 2 functions - _playSound()_ and _toggleKey()_ functions. We will be creating onClick() functions for each and every key ( ie- 12 keys ). 

```
  const playC4 = (e) => {
    playSound(C4);
    toggleC4key(true);
    setTimeout(() => {
        toggleC4key(false);
    }, 200);
  }
```
  
Create similar functions named - playDb4, playD4, playEb4 .... and pass the respective audio objects to the _playSound()_ function. 
The **setTimeout()** function here is used as a time Period for which the particular key will be in active ( toggled as true ) state ( ie - _for how long is it pressed_ ). I have set the value to 200ms, which after 200ms the key will be toggled off. 

Next, will be creating a button element and defining the **onClick() handler**. 

```
<button className='white-btn C4' onClick={(e)=> playC4(e)} />
<button className='Db4' onClick = {(e) => playDb4(e)} />
<button className='white-btn D4' onClick={(e)=> playD4(e)} />
<button className='white-btn E4' onClick={(e)=> playE4(e)} />
<button className='white-btn F4' onClick={(e)=> playF4(e)} />
```

---

Replicate the buttons for the rest of the keys as well and the piano should be done! You can check the code on my github for any help - <a href = "https://github.com/atharva0300/Hackbytes-2022/blob/main/client/src/Components/Music/TimeLine1.js">Code</a> | all the mp3 audio files can be extracted from <a href = "https://github.com/atharva0300/Hackbytes-2022/tree/main/client/src/Components/Music/Sounds">Audio Files</a> | Repo Link - <a href = "https://github.com/atharva0300/Hackbytes-2022">Github Repo</a> | Use the app here <a href = "https://hackbytes-2022.herokuapp.com/music">Heroku App</a>. Cover Image credits : <a href = "https://wallpaperaccess.com/react-js">Wallpaper Access</a>