Help with the Drum Machine needed

The machine works but it doesn’t pass three of the tests (4, 5 & 6). I’ve been stuck on this for ages and cannot seem to get any other method (i.e. using audio elements) to work for me. Anybody able to help me out?

https://codepen.io/TheTubbyNinja/pen/LYbNZYe

const sounds = [
  {
    keyName: "Q",
    asciiCode: 81,
    name: "Chord 1",
    clip: 'https://s3.amazonaws.com/freecodecamp/drums/Chord_1.mp3'
  },
  {
    keyName: "W",
    asciiCode: 87,
    name: "Chord 2",
    clip: 'https://s3.amazonaws.com/freecodecamp/drums/Chord_2.mp3'
  },
  {
    keyName: "E",
    asciiCode: 69,
    name: "Chord 3",
    clip: 'https://s3.amazonaws.com/freecodecamp/drums/Chord_3.mp3'
  },
  {
    keyName: "A",
    asciiCode: 65,
    name: "Side Stick",
    clip: 'https://s3.amazonaws.com/freecodecamp/drums/side_stick_1.mp3'
  },
  {
    keyName: "S",
    asciiCode: 83,
    name: "Open Hi-Hat",
    clip: 'https://s3.amazonaws.com/freecodecamp/drums/Dry_Ohh.mp3'
  },
  {
    keyName: "D",
    asciiCode: 68,
    name: "Closed Hi-Hat",
    clip: 'https://s3.amazonaws.com/freecodecamp/drums/Bld_H1.mp3'
  },
  {
    keyName: "Z",
    asciiCode: 90,
    name: "Kick",
    clip: 'https://s3.amazonaws.com/freecodecamp/drums/RP4_KICK_1.mp3'
  },
  {
    keyName: "X",
    asciiCode: 88,
    name: "Punch Kick",
    clip: 'https://s3.amazonaws.com/freecodecamp/drums/punchy_kick_1.mp3'
  },
  {
    keyName: "C",
    asciiCode: 67,
    name: "Snare",
    clip: 'https://s3.amazonaws.com/freecodecamp/drums/Brk_Snr.mp3'
  }
]

class DrumMachine extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      drum: ""
    };
    this.handleKeyPress = this.handleKeyPress.bind(this);
    this.handleClick = this.handleClick.bind(this);
  }
  handleClick(e) {
    let correctObj = sounds.find(entry => entry.keyName === e.target.value);
    let playSound = new Audio(correctObj.clip);
    playSound.play();
    this.setState({
      drum: correctObj.name
    })
  }
  handleKeyPress(e) {
    let valid = false;
    for (let i = 0; i < sounds.length; i++) {
      if (e.keyCode === sounds[i].asciiCode) {
        valid = true;
      }
    }
    if (valid === true) {
      let correctObj = sounds.find(entry => entry.asciiCode === e.keyCode);
      let playSound = new Audio(correctObj.clip);
      playSound.play();
      this.setState({
        drum: correctObj.name
      })
    }
  }
  render() {
    document.addEventListener("keydown", this.handleKeyPress)
    return (
      <div id="drum-machine">
        <Display 
          activeDrum={this.state.drum}
        />
        <Buttons 
          click={this.handleClick}
        />
      </div>
    )
  }
}
class Display extends React.Component {
  render() {
    return (
      <div id="display">
        {this.props.activeDrum}
      </div>
    )
  }
}
class Buttons extends React.Component {
  render() {
    return (
      <div id="drum-pad">
        <button id="chord1" class="drum-pad" value="Q" onClick={this.props.click}>
          Q
        </button>
          <button id="chord2" class="drum-pad" value="W" onClick={this.props.click}>
          W
        </button>
        <button id="chord3" class="drum-pad" value="E" onClick={this.props.click}>
          E
        </button>
        <button id="sidestick" class="drum-pad" value="A" onClick={this.props.click}>
          A
        </button>
        <button id="openhh" class="drum-pad" value="S" onClick={this.props.click}>
          S
        </button>
        <button id="closedhh" class="drum-pad" value="D" onClick={this.props.click}>
          D
        </button>
        <button id="kick" class="drum-pad" value="Z" onClick={this.props.click}>
          Z
        </button>
        <button id="punchykick" class="drum-pad" value="X" onClick={this.props.click}>
          X
        </button>
        <button id="snare" class="drum-pad" value="C" onClick={this.props.click}>
          C
        </button>
      </div>
    )
  }
}
ReactDOM.render(<DrumMachine />, document.getElementById("app"));

Hi @aidansabin !

The machine does work. But the failing tests say that the audio element does not exist.

https://developer.mozilla.org/en-US/docs/Web/API/HTMLAudioElement

I would work on incorporating that into my code.
I know you said that you tried to use the audio element but that is the requirement. Maybe you could share with the forum what you tried with the audio element.

Hope that helps!

Thank you for your reply.

This is what I’ve got and I can’t seem to get any closer. It only seems to work when pressing the key (but not when clicking) and there also seems to be a delay before I can reactivate a sound.

const sounds = [
  {
    keyName: "Q",
    asciiCode: 81,
    name: "Chord 1",
    url: 'https://s3.amazonaws.com/freecodecamp/drums/Chord_1.mp3'
  },
  {
    keyName: "W",
    asciiCode: 87,
    name: "Chord 2",
    url: 'https://s3.amazonaws.com/freecodecamp/drums/Chord_2.mp3'
  },
  {
    keyName: "E",
    asciiCode: 69,
    name: "Chord 3",
    url: 'https://s3.amazonaws.com/freecodecamp/drums/Chord_3.mp3'
  },
  {
    keyName: "A",
    asciiCode: 65,
    name: "Side Stick",
    url: 'https://s3.amazonaws.com/freecodecamp/drums/side_stick_1.mp3'
  },
  {
    keyName: "S",
    asciiCode: 83,
    name: "Open Hi-Hat",
    url: 'https://s3.amazonaws.com/freecodecamp/drums/Dry_Ohh.mp3'
  },
  {
    keyName: "D",
    asciiCode: 68,
    name: "Closed Hi-Hat",
    url: 'https://s3.amazonaws.com/freecodecamp/drums/Bld_H1.mp3'
  },
  {
    keyName: "Z",
    asciiCode: 90,
    name: "Kick",
    url: 'https://s3.amazonaws.com/freecodecamp/drums/RP4_KICK_1.mp3'
  },
  {
    keyName: "X",
    asciiCode: 88,
    name: "Punch Kick",
    url: 'https://s3.amazonaws.com/freecodecamp/drums/punchy_kick_1.mp3'
  },
  {
    keyName: "C",
    asciiCode: 67,
    name: "Snare",
    url: 'https://s3.amazonaws.com/freecodecamp/drums/Brk_Snr.mp3'
  }
]

class DrumMachine extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      drum: "",
      clip: ""
    };
    this.handleKeyPress = this.handleKeyPress.bind(this);
    this.handleClick = this.handleClick.bind(this);
  }
  handleClick(e) {
    let correctObj = sounds.find(entry => entry.keyName === e.target.value);
    this.setState({
      drum: correctObj.name,
      clip: correctObj.url
    })
    let sound = document.getElementById(correctObj.keyName);
    sound.play();
  }
  handleKeyPress(e) {
    let valid = false;
    for (let i = 0; i < sounds.length; i++) {
      if (e.keyCode === sounds[i].asciiCode) {
        valid = true;
      }
    }
    if (valid === true) {
      let correctObj = sounds.find(entry => entry.asciiCode === e.keyCode);
      this.setState({
        drum: correctObj.name,
        clip: correctObj.url
      })
      let sound = document.getElementById(correctObj.keyName);
      sound.play();
    }
  }
  render() {
    document.addEventListener("keydown", this.handleKeyPress)
    return (
      <div id="drum-machine">
        <Display 
          activeDrum={this.state.drum}
        />
        <Buttons 
          click={this.handleClick}
        />
      </div>
    )
  }
}
class Display extends React.Component {
  render() {
    return (
      <div id="display">
        {this.props.activeDrum}
      </div>
    )
  }
}
class Buttons extends React.Component {
  render() {
    return (
      <div id="drum-pad">
        <a href="#">
          <div id="chord1" type="button" class="drum-pad" value="Q" onClick={this.props.click}>
            Q
            <audio id="Q" src={sounds[0].url}></audio>
          </div>
        </a>
        <a href="#">
          <div id="chord2" class="drum-pad" value="W" onClick={this.props.click}>
            W
            <audio id="W" src={sounds[1].url}></audio>
          </div>
        </a>
        <a href="#">
          <div id="chord3" class="drum-pad" value="E" onClick={this.props.click}>
            E
            <audio id="E" src={sounds[2].url}></audio>
          </div>
        </a>
        <a href="#">
          <div id="sidestick" class="drum-pad" value="A" onClick={this.props.click}>
            A
            <audio id="A" src={sounds[3].url}></audio>
          </div>
        </a>
        <a href="#">
          <div id="openhh" class="drum-pad" value="S" onClick={this.props.click}>
            S
            <audio id="S" src={sounds[4].url}></audio>
          </div>
        </a>
        <a href="#">
          <div id="closedhh" class="drum-pad" value="D" onClick={this.props.click}>
            D
            <audio id="D" src={sounds[5].url}></audio>
          </div>
        </a>
        <a href="#">
          <div id="kick" class="drum-pad" value="Z" onClick={this.props.click}>
            Z
            <audio id="Z" src={sounds[6].url}></audio>
          </div>
        </a>
        <a href="#">
          <div id="punchykick" class="drum-pad" value="X" onClick={this.props.click}>
            X
            <audio id="X" src={sounds[7].url}></audio>
          </div>
        </a>
        <a href="#">
          <div id="chord2" class="drum-pad" value="C" onClick={this.props.click}>
            C
            <audio id="C" src={sounds[8].url}></audio>
          </div>
        </a>
      </div>
    )
  }
}
ReactDOM.render(<DrumMachine />, document.getElementById("app"));

You can clear up two of the failing tests by applying the class name of clip to the audio elements.

Have you tried replicating the same logic as the handleKeypress for the handleclick? Maybe that would work.

Maybe someone else has another solution that is less repetitive.

Good luck!