playSound ({ getters, commit, state, dispatch }, opts) {
      if (typeof opts !== 'object' || opts.preloadedId) {
        const id = typeof opts !== 'object' ? opts : opts.preloadedId

        const sound = getters.getSoundById(id)
        if (!sound) {
          throw new Error(`Sound ID does not exist: ${id}`)
        }

        // Creates a new overlapping oneshot sound instance.
        const playingInstanceId = sound.play()

        // Setting volume cancels any current fade effects
        if (typeof opts?.volume === 'number') {
          // Note: It is important that this happens after the play is called.
          //       This allows us to only change the volume of the instance playing.
          //       There may still be another instance playing that has a different volume.
          sound.volume(opts.volume, playingInstanceId)
        }

        return id
      }

      if (!getters.hasTrack(opts.track)) {
        throw new Error('Invalid track specified')
      }

      const { track, unique, ...howlOpts } = opts

      if (unique && state.unique.keys.has(unique)) {
        return
      }

      if (track && track === 'background' && !me.get('music', true)) {
        // Take this opportunity to mute the background music track if we me.get('music') has been disabled
        dispatch('muteTrack', track)
      }

      // Default to playing sounds immediately upon load but allow
      // consumers to specify autoplay behavior to support scenarios
      // such as pre loading sound effects.
      if (typeof howlOpts.autoplay === 'undefined') {
        howlOpts.autoplay = true
      }

      const sound = new Howl({
        ...howlOpts,

        mute: howlOpts.muted || state.muted.all || state.muted[opts.track]
      })

      // Prevent falsy 0 by incrementing
      let soundId = Math.random() + 1
      while (getters.hasId(soundId)) {
        soundId = Math.random() + 1
      }

      if (!howlOpts.loop) {
        sound.once(
          'stop',
          () => dispatch('stopSound', { id: soundId, unload: true }))
        sound.once(
          'end',
          () => dispatch('stopSound', { id: soundId, unload: true }))
      }

      commit('addSoundToTrack', { trackName: opts.track, soundId, sound })
      if (opts.unique) {
        commit('addUniqueEntry', { id: soundId, unique })
      }

      return soundId
    }
Plays a new sound on a track.

@param opts {string|object} SoundId or Howl configuration to play
@param opts.track {string} Track to play sound on
@param opts.preloadedId {string} For playing an already loaded sound
@param opts.volume {number} Volume of sound [0, 1]

If passing in opts as a sound ID:
  Plays an existing sound. If sound is already playing it fires a new sound.

@return ID of the newly playing sound
@throws {Error} when invalid ID specified