/**
   * Returns sound source from "sfx" pool configured for specified sound, position and gain
   *
   * @param uri Sound uri
   * @param pos Sound source position
   * @param gain Sound source gain
   * @return Sound source object, or null if there is no free sound sources in effects pool
   */
  public static SoundSource source(AssetUri uri, Vector3d pos, float gain, int priority) {
    SoundSource source = source(uri, priority);
    if (source == null) {
      return null;
    }

    return (pos != null ? source.setPosition(pos).setAbsolute(true) : source).setGain(gain);
  }
  /**
   * Plays specified sound at specified position and with specified gain
   *
   * @param sound Sound object
   * @param pos Sound source position
   * @param gain Sound source gain
   * @return Sound source object, or null if there is no free sound sources in effects pool
   */
  public static SoundSource play(Sound sound, Vector3f pos, float gain, int priority) {
    SoundSource source = source(sound, new Vector3d(pos), gain, priority);

    if (source == null) {
      return null;
    }

    return source.setGain(gain).play();
  }
  /**
   * Plays specified sound at specified position and with specified gain
   *
   * @param uri Sound uri
   * @param pos Sound source position
   * @param gain Sound source gain
   * @return Sound source object, or null if there is no free sound sources in effects pool
   */
  public static SoundSource play(AssetUri uri, Vector3d pos, float gain, int priority) {
    SoundSource source = source(uri, pos, gain, priority);

    if (source == null) {
      return null;
    }

    return source.play();
  }
  /**
   * Plays specified music
   *
   * @param uri Music uri
   * @return Sound source object, or null if there is no free sound sources in music pool
   */
  public static SoundSource playMusic(AssetUri uri) {
    SoundPool pool = AudioManager.getInstance().getSoundPool("music");

    pool.stopAll();

    Sound sound = (Sound) Assets.get(uri);
    if (sound == null) return null;

    SoundSource source = pool.getSource(sound);

    if (source == null) { // no free music slots
      return null;
    }

    return source.setGain(0.1f).play();
  }
  /**
   * Plays specified sound tuned for specified entity
   *
   * @param sound Sound object
   * @param entity Entity sounding
   * @param gain Sound source gain
   * @param priority Sound priority
   * @return Sound source object, or null if there is no free sound sources in effects pool
   */
  public static SoundSource play(Sound sound, EntityRef entity, float gain, int priority) {
    Vector3f pos = getEntityPosition(entity);
    if (pos == null) return null;

    SoundSource source = source(sound, new Vector3d(pos), gain, priority);

    if (source == null) {
      // Nof free sound sources
      return null;
    }

    return source
        .setVelocity(new Vector3d(getEntityVelocity(entity)))
        .setDirection(new Vector3d(getEntityDirection(entity)))
        .play();
  }
  /**
   * Returns sound source from "sfx" pool configured for specified sound, position and gain
   *
   * @param sound Sound object
   * @param pos Sound source position
   * @param gain Sound source gain
   * @return Sound source object, or null if there is no free sound sources in effects pool
   */
  public static SoundSource source(Sound sound, Vector3d pos, float gain, int priority) {
    SoundSource source = source(sound, priority);

    if (source == null) {
      return null;
    }

    if (pos != null) {
      if (!getInstance().checkDistance(pos)) {
        return null;
      }

      source.setPosition(pos).setAbsolute(true);
    }

    return source.setGain(gain);
  }