/*
* Copyright 2012 Benjamin Glatzel <benjamin.glatzel@me.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.terasology.logic.manager;
import com.bulletphysics.linearmath.QuaternionUtil;
import org.terasology.asset.AssetType;
import org.terasology.asset.AssetUri;
import org.terasology.audio.OpenALManager;
import org.terasology.audio.Sound;
import org.terasology.audio.SoundPool;
import org.terasology.audio.SoundSource;
import org.terasology.components.CharacterMovementComponent;
import org.terasology.components.world.BlockComponent;
import org.terasology.components.world.LocationComponent;
import org.terasology.entitySystem.EntityRef;
import javax.vecmath.Quat4f;
import javax.vecmath.Vector3d;
import javax.vecmath.Vector3f;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;
/**
* Simple managing class for loading and accessing audio files.
*
* @author Benjamin Glatzel <benjamin.glatzel@me.com>
* @author t3hk0d3 <contact@tehkode.ru>
*/
public abstract class AudioManager implements SoundManager {
protected Logger logger = Logger.getLogger(this.getClass().getCanonicalName());
private static AudioManager _instance = null;
protected Map<String, Sound> _audio = new HashMap<String, Sound>();
protected Map<String, SoundPool> _pools = new HashMap<String, SoundPool>();
protected AudioManager() {
}
protected abstract boolean checkDistance(Vector3d soundSource);
/**
* Returns sound pool with specified name
* <b>WARNING! Method will throw IllegalArgumentException if specified sound pool is not found</b>
*
* @param pool Sound pool name
* @return Sound pool object
*/
@Override
public SoundPool getSoundPool(String pool) {
SoundPool soundPool = _pools.get(pool);
if (soundPool == null) {
throw new IllegalArgumentException("Unknown pool '" + pool + "', typo? Available pools: " + _pools.keySet());
}
return soundPool;
}
@Override
public SoundSource getSoundSource(String pool, Sound sound, int priority) {
return getSoundPool(pool).getSource(sound, priority);
}
@Override
public SoundSource getSoundSource(String pool, AssetUri soundUri, int priority) {
Sound sound = (Sound) AssetManager.load(soundUri);
if (sound != null) {
return getSoundPool(pool).getSource(sound, priority);
}
return null;
}
/**
* Stops all playback.
*/
@Override
public void stopAllSounds() {
for (SoundPool pool : _pools.values()) {
pool.stopAll();
}
}
/**
* Returns AudioManager instance
*
* @return
*/
public static AudioManager getInstance() {
if (_instance == null) {
_instance = new OpenALManager();
}
return _instance;
}
/**
* Returns sound source for specified sound from "sfx" pool with normal priority
*
* @param uri Sound uri
* @return Sound source object, or null if there is no free sound sources in effects pool
*/
public static SoundSource source(AssetUri uri) {
return source(uri, PRIORITY_NORMAL);
}
/**
* Returns sound source for specified sound from "sfx" pool
*
* @param uri
* @param priority Priority
* @return Sound source object, or null if there is no free sound sources in effects pool
*/
public static SoundSource source(AssetUri uri, int priority) {
return getInstance().getSoundSource("sfx", uri, priority);
}
/**
* Returns sound source for specified sound from "sfx" pool with normal priority
*
* @param sound Sound object
* @return Sound source object, or null if there is no free sound sources in effects pool
*/
public static SoundSource source(Sound sound) {
return source(sound, PRIORITY_NORMAL);
}
/**
* Returns sound source for specified sound from "sfx" pool with normal priority
*
* @param sound Sound object
* @param priority Sound priority
* @return Sound source object, or null if there is no free sound sources in effects pool
*/
public static SoundSource source(Sound sound, int priority) {
return getInstance().getSoundSource("sfx", sound, priority);
}
/**
* 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);
}
/**
* 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);
}
/**
* Plays specified sound with gain = 1.0f
*
* @param uri Sound uri
* @return Sound source object, or null if there is no free sound sources in effects pool
*/
public static SoundSource play(AssetUri uri) {
return play(uri, null, 1.0f, PRIORITY_NORMAL);
}
/**
* Plays specified sound with specified gain
*
* @param uri Sound uri
* @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, float gain) {
return play(uri, null, gain, PRIORITY_NORMAL);
}
/**
* 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 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, Vector3d pos, float gain, int priority) {
SoundSource source = source(sound, pos, gain, priority);
if (source == null) {
return null;
}
return source.setGain(gain).play();
}
/**
* 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 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();
}
private static Vector3f getEntityPosition(EntityRef entity) {
LocationComponent loc = entity.getComponent(LocationComponent.class);
if (loc != null) {
return loc.getWorldPosition();
}
BlockComponent blockComp = entity.getComponent(BlockComponent.class);
if (blockComp != null) {
return blockComp.getPosition().toVector3f();
}
return null;
}
private static Vector3f getEntityDirection(EntityRef entity) {
LocationComponent loc = entity.getComponent(LocationComponent.class);
if (loc != null) {
Quat4f rot = loc.getWorldRotation();
Vector3f dir = new Vector3f(0, 0, -1);
QuaternionUtil.quatRotate(rot, dir, dir);
return dir;
}
return new Vector3f();
}
private static Vector3f getEntityVelocity(EntityRef entity) {
CharacterMovementComponent charMove = entity.getComponent(CharacterMovementComponent.class);
if (charMove != null) {
return charMove.getVelocity();
}
return new Vector3f();
}
/**
* 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) AssetManager.load(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();
}
public static SoundSource playMusic(String shortUri) {
AssetUri uri = new AssetUri(AssetType.MUSIC, shortUri);
return playMusic(uri);
}
}