Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to make same sound initiate multiple times (overlap) on user input? #51

Closed
rifkegribenes opened this issue Dec 6, 2017 · 2 comments
Labels

Comments

@rifkegribenes
Copy link

rifkegribenes commented Dec 6, 2017

I'm preloading all my sounds by mapping over an manifest of sound urls and rendering a <Howler /> for each one, setting the src for each component from the manifest. I'm setting the playing prop as this.state.playing.includes(sound.id), so that I can have more than one sound playing at a time. When user input triggers playSound() I'm pushing that sound's id into the playing array and calling setState(). Then I added an onEnd() method to remove the sound from the array when it's finished playing.

This is all working fine except that there is one sound that I want to be able to overlap -- start playing a new instance of it before the last one has finished, if the user triggers it while another instance is still playing. That doesn't seem to be possible the way I have this set up. Is there a way to do what I'm describing? Overlapping sounds were working fine when I was just calling .play() on each sound as it was triggered, but I was trying out react-howler because I wanted to preload everything ahead of time.

@Stenerson
Copy link
Collaborator

Stenerson commented Dec 8, 2017

Hi @rifkegribenes,

I put together a quick example of the way I'd probably do overlapping sounds with a single ReactHowler instance. The trick is to call the howler method play() (vs. the ReactHowler method). In my example I'm keeping track of the IDs so I can stop each one individually. If you don't need to do that you could simplify the example even more.

import React from 'react'
import ReactHowler from 'ReactHowler'

class OverlappingSound extends React.Component {
  constructor (props) {
    super(props)

    this.state = {
      playing: false,
      soundIds: []
    }

    this.handlePlay = this.handlePlay.bind(this)
    this.handleStop = this.handleStop.bind(this)
    this.handleStopOldest = this.handleStopOldest.bind(this)
    this.sound = null
  }

  handlePlay () {
    // Calling sound.howler.play() here calls play() on the Howl object itself
    // without an ID which creates a new sound (i.e. overlap) and return an ID
    const newId = this.sound.howler.play()
    // console.log("New ID:", id)
    this.setState({
      playing: true,
      soundIds: [...this.state.soundIds, newId]
    })
  }

  handleStop () {
    // Calling sound.stop() (with no id) will stop all sounds
    this.sound.stop()
  }

  handleStopOldest () {
    // If you want to stop an individual sound you need to keep track
    // of each ID returned from this.sound.howler.play()
    // and stop a specific ID
    this.sound.stop(this.state.soundIds[0]);
    const newSoundIds = this.state.soundIds.slice(1);
    this.setState({
      soundIds: newSoundIds,
      playing: newSoundIds.length > 0
    })
  }

  render () {
    return (
      <div>
        <ReactHowler
          src={['sound.ogg', 'sound.mp3']}
          playing={this.state.playing}
          ref={node => this.sound = node}
        />
        <button onClick={this.handlePlay}>Play</button>
        <button onClick={this.handleStop}>Stop All</button>
        <button onClick={this.handleStopOldest}>Stop Oldest</button>
      </div>
    )
  }
}

export default OverlappingSound

@Stenerson
Copy link
Collaborator

I'm going to close this off. Please reopen if more discussion is needed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants