|
@@ -64,165 +64,161 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|
import java.util.logging.Level;
|
|
import java.util.logging.Level;
|
|
import java.util.logging.Logger;
|
|
import java.util.logging.Logger;
|
|
|
|
|
|
-
|
|
|
|
/**
|
|
/**
|
|
* This class is the android implementation for {@link AudioRenderer}
|
|
* This class is the android implementation for {@link AudioRenderer}
|
|
* @author larynx
|
|
* @author larynx
|
|
*
|
|
*
|
|
*/
|
|
*/
|
|
-public class AndroidAudioRenderer implements AudioRenderer, SoundPool.OnLoadCompleteListener, MediaPlayer.OnCompletionListener
|
|
|
|
-{
|
|
|
|
|
|
+public class AndroidAudioRenderer implements AudioRenderer, SoundPool.OnLoadCompleteListener, MediaPlayer.OnCompletionListener {
|
|
|
|
|
|
private static final Logger logger = Logger.getLogger(AndroidAudioRenderer.class.getName());
|
|
private static final Logger logger = Logger.getLogger(AndroidAudioRenderer.class.getName());
|
|
private final static int MAX_NUM_CHANNELS = 16;
|
|
private final static int MAX_NUM_CHANNELS = 16;
|
|
-
|
|
|
|
private SoundPool soundPool = null;
|
|
private SoundPool soundPool = null;
|
|
- private HashMap<AudioNode, MediaPlayer> musicPlaying = new HashMap<AudioNode, MediaPlayer>();
|
|
|
|
-
|
|
|
|
|
|
+ private HashMap<AudioNode, MediaPlayer> musicPlaying = new HashMap<AudioNode, MediaPlayer>();
|
|
private final Vector3f listenerPosition = new Vector3f();
|
|
private final Vector3f listenerPosition = new Vector3f();
|
|
// For temp use
|
|
// For temp use
|
|
private final Vector3f distanceVector = new Vector3f();
|
|
private final Vector3f distanceVector = new Vector3f();
|
|
-
|
|
|
|
private final AudioManager manager;
|
|
private final AudioManager manager;
|
|
private final Context context;
|
|
private final Context context;
|
|
private final AssetManager am;
|
|
private final AssetManager am;
|
|
-
|
|
|
|
private HashMap<Integer, AudioNode> mapLoadingAudioNodes = new HashMap<Integer, AudioNode>();
|
|
private HashMap<Integer, AudioNode> mapLoadingAudioNodes = new HashMap<Integer, AudioNode>();
|
|
-
|
|
|
|
private final AtomicBoolean lastLoadCompleted = new AtomicBoolean();
|
|
private final AtomicBoolean lastLoadCompleted = new AtomicBoolean();
|
|
-
|
|
|
|
-
|
|
|
|
private Listener listener;
|
|
private Listener listener;
|
|
private boolean audioDisabled = false;
|
|
private boolean audioDisabled = false;
|
|
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- public AndroidAudioRenderer(Activity context)
|
|
|
|
- {
|
|
|
|
|
|
+ public AndroidAudioRenderer(Activity context) {
|
|
this.context = context;
|
|
this.context = context;
|
|
- manager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
|
|
|
|
|
|
+ manager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
|
|
context.setVolumeControlStream(AudioManager.STREAM_MUSIC);
|
|
context.setVolumeControlStream(AudioManager.STREAM_MUSIC);
|
|
am = context.getAssets();
|
|
am = context.getAssets();
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
@Override
|
|
@Override
|
|
- public void initialize()
|
|
|
|
- {
|
|
|
|
- soundPool = new SoundPool(MAX_NUM_CHANNELS, AudioManager.STREAM_MUSIC, 0);
|
|
|
|
|
|
+ public void initialize() {
|
|
|
|
+ soundPool = new SoundPool(MAX_NUM_CHANNELS, AudioManager.STREAM_MUSIC, 0);
|
|
soundPool.setOnLoadCompleteListener(this);
|
|
soundPool.setOnLoadCompleteListener(this);
|
|
}
|
|
}
|
|
|
|
|
|
@Override
|
|
@Override
|
|
- public void updateSourceParam(AudioNode src, AudioParam param)
|
|
|
|
- {
|
|
|
|
|
|
+ public void updateSourceParam(AudioNode src, AudioParam param) {
|
|
//logger.log(Level.INFO, "updateSourceParam " + param);
|
|
//logger.log(Level.INFO, "updateSourceParam " + param);
|
|
-
|
|
|
|
- if (audioDisabled)
|
|
|
|
- return;
|
|
|
|
-
|
|
|
|
- if (src.getChannel() < 0)
|
|
|
|
- return;
|
|
|
|
-
|
|
|
|
- assert src.getChannel() >= 0;
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- switch (param){
|
|
|
|
- case Position:
|
|
|
|
- if (!src.isPositional())
|
|
|
|
- return;
|
|
|
|
-
|
|
|
|
- Vector3f pos = src.getWorldTranslation();
|
|
|
|
- break;
|
|
|
|
- case Velocity:
|
|
|
|
- if (!src.isPositional())
|
|
|
|
- return;
|
|
|
|
-
|
|
|
|
- Vector3f vel = src.getVelocity();
|
|
|
|
- break;
|
|
|
|
- case MaxDistance:
|
|
|
|
- if (!src.isPositional())
|
|
|
|
- return;
|
|
|
|
- break;
|
|
|
|
- case RefDistance:
|
|
|
|
- if (!src.isPositional())
|
|
|
|
- return;
|
|
|
|
- break;
|
|
|
|
- case ReverbFilter:
|
|
|
|
- if (!src.isPositional() || !src.isReverbEnabled())
|
|
|
|
- return;
|
|
|
|
- break;
|
|
|
|
- case ReverbEnabled:
|
|
|
|
- if (!src.isPositional())
|
|
|
|
- return;
|
|
|
|
-
|
|
|
|
- if (src.isReverbEnabled()){
|
|
|
|
- updateSourceParam(src, AudioParam.ReverbFilter);
|
|
|
|
- }
|
|
|
|
- break;
|
|
|
|
- case IsPositional:
|
|
|
|
- break;
|
|
|
|
- case Direction:
|
|
|
|
- if (!src.isDirectional())
|
|
|
|
- return;
|
|
|
|
-
|
|
|
|
- Vector3f dir = src.getDirection();
|
|
|
|
- break;
|
|
|
|
- case InnerAngle:
|
|
|
|
- if (!src.isDirectional())
|
|
|
|
- return;
|
|
|
|
- break;
|
|
|
|
- case OuterAngle:
|
|
|
|
- if (!src.isDirectional())
|
|
|
|
- return;
|
|
|
|
- break;
|
|
|
|
- case IsDirectional:
|
|
|
|
- if (src.isDirectional()){
|
|
|
|
- updateSourceParam(src, AudioParam.Direction);
|
|
|
|
- updateSourceParam(src, AudioParam.InnerAngle);
|
|
|
|
- updateSourceParam(src, AudioParam.OuterAngle);
|
|
|
|
- }else{
|
|
|
|
- }
|
|
|
|
- break;
|
|
|
|
- case DryFilter:
|
|
|
|
- if (src.getDryFilter() != null){
|
|
|
|
- Filter f = src.getDryFilter();
|
|
|
|
- if (f.isUpdateNeeded()){
|
|
|
|
- //updateFilter(f);
|
|
|
|
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- break;
|
|
|
|
- case Looping:
|
|
|
|
- if (src.isLooping()){
|
|
|
|
|
|
+ if (audioDisabled) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (src.getChannel() < 0) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ assert src.getChannel() >= 0;
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ switch (param) {
|
|
|
|
+ case Position:
|
|
|
|
+ if (!src.isPositional()) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ Vector3f pos = src.getWorldTranslation();
|
|
|
|
+ break;
|
|
|
|
+ case Velocity:
|
|
|
|
+ if (!src.isPositional()) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ Vector3f vel = src.getVelocity();
|
|
|
|
+ break;
|
|
|
|
+ case MaxDistance:
|
|
|
|
+ if (!src.isPositional()) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+ case RefDistance:
|
|
|
|
+ if (!src.isPositional()) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+ case ReverbFilter:
|
|
|
|
+ if (!src.isPositional() || !src.isReverbEnabled()) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+ case ReverbEnabled:
|
|
|
|
+ if (!src.isPositional()) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (src.isReverbEnabled()) {
|
|
|
|
+ updateSourceParam(src, AudioParam.ReverbFilter);
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+ case IsPositional:
|
|
|
|
+ break;
|
|
|
|
+ case Direction:
|
|
|
|
+ if (!src.isDirectional()) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ Vector3f dir = src.getDirection();
|
|
|
|
+ break;
|
|
|
|
+ case InnerAngle:
|
|
|
|
+ if (!src.isDirectional()) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+ case OuterAngle:
|
|
|
|
+ if (!src.isDirectional()) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+ case IsDirectional:
|
|
|
|
+ if (src.isDirectional()) {
|
|
|
|
+ updateSourceParam(src, AudioParam.Direction);
|
|
|
|
+ updateSourceParam(src, AudioParam.InnerAngle);
|
|
|
|
+ updateSourceParam(src, AudioParam.OuterAngle);
|
|
|
|
+ } else {
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+ case DryFilter:
|
|
|
|
+ if (src.getDryFilter() != null) {
|
|
|
|
+ Filter f = src.getDryFilter();
|
|
|
|
+ if (f.isUpdateNeeded()) {
|
|
|
|
+ //updateFilter(f);
|
|
}
|
|
}
|
|
- break;
|
|
|
|
- case Volume:
|
|
|
|
-
|
|
|
|
- soundPool.setVolume(src.getChannel(), src.getVolume(), src.getVolume());
|
|
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+ case Looping:
|
|
|
|
+ if (src.isLooping()) {
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+ case Volume:
|
|
|
|
|
|
- break;
|
|
|
|
- case Pitch:
|
|
|
|
|
|
+ soundPool.setVolume(src.getChannel(), src.getVolume(), src.getVolume());
|
|
|
|
+
|
|
|
|
+ break;
|
|
|
|
+ case Pitch:
|
|
|
|
+
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
@Override
|
|
@Override
|
|
- public void updateListenerParam(Listener listener, ListenerParam param)
|
|
|
|
- {
|
|
|
|
|
|
+ public void updateListenerParam(Listener listener, ListenerParam param) {
|
|
//logger.log(Level.INFO, "updateListenerParam " + param);
|
|
//logger.log(Level.INFO, "updateListenerParam " + param);
|
|
- if (audioDisabled)
|
|
|
|
|
|
+ if (audioDisabled) {
|
|
return;
|
|
return;
|
|
-
|
|
|
|
- switch (param){
|
|
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ switch (param) {
|
|
case Position:
|
|
case Position:
|
|
listenerPosition.set(listener.getLocation());
|
|
listenerPosition.set(listener.getLocation());
|
|
|
|
|
|
break;
|
|
break;
|
|
case Rotation:
|
|
case Rotation:
|
|
Vector3f dir = listener.getDirection();
|
|
Vector3f dir = listener.getDirection();
|
|
- Vector3f up = listener.getUp();
|
|
|
|
|
|
+ Vector3f up = listener.getUp();
|
|
|
|
|
|
break;
|
|
break;
|
|
case Velocity:
|
|
case Velocity:
|
|
@@ -237,436 +233,358 @@ public class AndroidAudioRenderer implements AudioRenderer, SoundPool.OnLoadComp
|
|
}
|
|
}
|
|
|
|
|
|
@Override
|
|
@Override
|
|
- public void update(float tpf)
|
|
|
|
- {
|
|
|
|
|
|
+ public void update(float tpf) {
|
|
float distance;
|
|
float distance;
|
|
float volume;
|
|
float volume;
|
|
-
|
|
|
|
|
|
+
|
|
// Loop over all mediaplayers
|
|
// Loop over all mediaplayers
|
|
- for (AudioNode src : musicPlaying.keySet())
|
|
|
|
- {
|
|
|
|
-
|
|
|
|
|
|
+ for (AudioNode src : musicPlaying.keySet()) {
|
|
|
|
+
|
|
MediaPlayer mp = musicPlaying.get(src);
|
|
MediaPlayer mp = musicPlaying.get(src);
|
|
{
|
|
{
|
|
// Calc the distance to the listener
|
|
// Calc the distance to the listener
|
|
distanceVector.set(listenerPosition);
|
|
distanceVector.set(listenerPosition);
|
|
distanceVector.subtractLocal(src.getLocalTranslation());
|
|
distanceVector.subtractLocal(src.getLocalTranslation());
|
|
distance = FastMath.abs(distanceVector.length());
|
|
distance = FastMath.abs(distanceVector.length());
|
|
-
|
|
|
|
- if (distance < src.getRefDistance())
|
|
|
|
|
|
+
|
|
|
|
+ if (distance < src.getRefDistance()) {
|
|
distance = src.getRefDistance();
|
|
distance = src.getRefDistance();
|
|
- if (distance > src.getMaxDistance())
|
|
|
|
- distance = src.getMaxDistance();
|
|
|
|
|
|
+ }
|
|
|
|
+ if (distance > src.getMaxDistance()) {
|
|
|
|
+ distance = src.getMaxDistance();
|
|
|
|
+ }
|
|
volume = src.getRefDistance() / distance;
|
|
volume = src.getRefDistance() / distance;
|
|
-
|
|
|
|
- AndroidAudioData audioData = (AndroidAudioData)src.getAudioData();
|
|
|
|
-
|
|
|
|
- if (FastMath.abs(audioData.getCurrentVolume() - volume) > FastMath.FLT_EPSILON)
|
|
|
|
- {
|
|
|
|
|
|
+
|
|
|
|
+ AndroidAudioData audioData = (AndroidAudioData) src.getAudioData();
|
|
|
|
+
|
|
|
|
+ if (FastMath.abs(audioData.getCurrentVolume() - volume) > FastMath.FLT_EPSILON) {
|
|
// Left / Right channel get the same volume by now, only positional
|
|
// Left / Right channel get the same volume by now, only positional
|
|
mp.setVolume(volume, volume);
|
|
mp.setVolume(volume, volume);
|
|
-
|
|
|
|
|
|
+
|
|
audioData.setCurrentVolume(volume);
|
|
audioData.setCurrentVolume(volume);
|
|
}
|
|
}
|
|
-
|
|
|
|
-
|
|
|
|
|
|
+
|
|
|
|
+
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
- public void setListener(Listener listener)
|
|
|
|
- {
|
|
|
|
- if (audioDisabled)
|
|
|
|
- return;
|
|
|
|
|
|
+ public void setListener(Listener listener) {
|
|
|
|
+ if (audioDisabled) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
|
|
- if (this.listener != null){
|
|
|
|
- // previous listener no longer associated with current
|
|
|
|
- // renderer
|
|
|
|
- this.listener.setRenderer(null);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- this.listener = listener;
|
|
|
|
- this.listener.setRenderer(this);
|
|
|
|
|
|
+ if (this.listener != null) {
|
|
|
|
+ // previous listener no longer associated with current
|
|
|
|
+ // renderer
|
|
|
|
+ this.listener.setRenderer(null);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ this.listener = listener;
|
|
|
|
+ this.listener.setRenderer(this);
|
|
|
|
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
@Override
|
|
@Override
|
|
- public void onLoadComplete(SoundPool soundPool, int sampleId, int status)
|
|
|
|
- {
|
|
|
|
|
|
+ public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
|
|
AudioNode src = mapLoadingAudioNodes.get(sampleId);
|
|
AudioNode src = mapLoadingAudioNodes.get(sampleId);
|
|
- if (src.getAudioData() instanceof AndroidAudioData)
|
|
|
|
- {
|
|
|
|
- AndroidAudioData audioData = (AndroidAudioData)src.getAudioData();
|
|
|
|
-
|
|
|
|
- if (status == 0) // load was successfull
|
|
|
|
|
|
+ if (src.getAudioData() instanceof AndroidAudioData) {
|
|
|
|
+ AndroidAudioData audioData = (AndroidAudioData) src.getAudioData();
|
|
|
|
+
|
|
|
|
+ if (status == 0) // load was successfull
|
|
{
|
|
{
|
|
int channelIndex;
|
|
int channelIndex;
|
|
- channelIndex = soundPool.play(audioData.getSoundId(), 1f, 1f, 1, -1, 1f);
|
|
|
|
|
|
+ channelIndex = soundPool.play(audioData.getId(), 1f, 1f, 1, -1, 1f);
|
|
src.setChannel(channelIndex);
|
|
src.setChannel(channelIndex);
|
|
// Playing started ?
|
|
// Playing started ?
|
|
- if (src.getChannel() > 0)
|
|
|
|
- {
|
|
|
|
|
|
+ if (src.getChannel() > 0) {
|
|
src.setStatus(Status.Playing);
|
|
src.setStatus(Status.Playing);
|
|
}
|
|
}
|
|
|
|
+ } else {
|
|
|
|
+ src.setChannel(-1);
|
|
}
|
|
}
|
|
- else
|
|
|
|
- {
|
|
|
|
- src.setChannel(-1);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
|
|
+ } else {
|
|
throw new IllegalArgumentException("AudioData is not of type AndroidAudioData for AudioNode " + src.toString());
|
|
throw new IllegalArgumentException("AudioData is not of type AndroidAudioData for AudioNode " + src.toString());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
@Override
|
|
@Override
|
|
- public void cleanup()
|
|
|
|
- {
|
|
|
|
|
|
+ public void cleanup() {
|
|
// Cleanup sound pool
|
|
// Cleanup sound pool
|
|
- if (soundPool != null)
|
|
|
|
- {
|
|
|
|
- for (AudioNode src: mapLoadingAudioNodes.values())
|
|
|
|
- {
|
|
|
|
- if ((src.getStatus() == Status.Playing) && (src.getChannel() > 0))
|
|
|
|
- {
|
|
|
|
|
|
+ if (soundPool != null) {
|
|
|
|
+ for (AudioNode src : mapLoadingAudioNodes.values()) {
|
|
|
|
+ if ((src.getStatus() == Status.Playing) && (src.getChannel() > 0)) {
|
|
soundPool.stop(src.getChannel());
|
|
soundPool.stop(src.getChannel());
|
|
}
|
|
}
|
|
-
|
|
|
|
- if (src.getAudioData() instanceof AndroidAudioData)
|
|
|
|
- {
|
|
|
|
- AndroidAudioData audioData = (AndroidAudioData)src.getAudioData();
|
|
|
|
- if (audioData.getSoundId() > 0)
|
|
|
|
- {
|
|
|
|
- soundPool.unload(audioData.getSoundId());
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
|
|
+
|
|
|
|
+ if (src.getAudioData() instanceof AndroidAudioData) {
|
|
|
|
+ AndroidAudioData audioData = (AndroidAudioData) src.getAudioData();
|
|
|
|
+ if (audioData.getId() > 0) {
|
|
|
|
+ soundPool.unload(audioData.getId());
|
|
|
|
+ }
|
|
|
|
+ }
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
soundPool.release();
|
|
soundPool.release();
|
|
soundPool = null;
|
|
soundPool = null;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
// Cleanup media player
|
|
// Cleanup media player
|
|
- for (AudioNode src : musicPlaying.keySet())
|
|
|
|
- {
|
|
|
|
|
|
+ for (AudioNode src : musicPlaying.keySet()) {
|
|
MediaPlayer mp = musicPlaying.get(src);
|
|
MediaPlayer mp = musicPlaying.get(src);
|
|
- {
|
|
|
|
|
|
+ {
|
|
mp.stop();
|
|
mp.stop();
|
|
mp.release();
|
|
mp.release();
|
|
src.setStatus(Status.Stopped);
|
|
src.setStatus(Status.Stopped);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- musicPlaying.clear();
|
|
|
|
|
|
+ musicPlaying.clear();
|
|
}
|
|
}
|
|
|
|
|
|
@Override
|
|
@Override
|
|
- public void onCompletion(MediaPlayer mp)
|
|
|
|
- {
|
|
|
|
- for (AudioNode src : musicPlaying.keySet())
|
|
|
|
- {
|
|
|
|
- if (musicPlaying.get(src) == mp)
|
|
|
|
- {
|
|
|
|
- mp.seekTo(0);
|
|
|
|
|
|
+ public void onCompletion(MediaPlayer mp) {
|
|
|
|
+ for (AudioNode src : musicPlaying.keySet()) {
|
|
|
|
+ if (musicPlaying.get(src) == mp) {
|
|
|
|
+ mp.seekTo(0);
|
|
mp.stop();
|
|
mp.stop();
|
|
src.setStatus(Status.Stopped);
|
|
src.setStatus(Status.Stopped);
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
}
|
|
}
|
|
-
|
|
|
|
- public void playSourceInstance(AudioNode src)
|
|
|
|
- {
|
|
|
|
- if (audioDisabled)
|
|
|
|
- return;
|
|
|
|
-
|
|
|
|
- AndroidAudioData audioData;
|
|
|
|
- int soundId = 0;
|
|
|
|
-
|
|
|
|
- if (src.getAudioData() instanceof AndroidAudioData)
|
|
|
|
- {
|
|
|
|
- audioData = (AndroidAudioData)src.getAudioData();
|
|
|
|
-
|
|
|
|
- if (audioData.getAssetKey() instanceof AudioKey)
|
|
|
|
- {
|
|
|
|
- AudioKey assetKey = (AudioKey) audioData.getAssetKey();
|
|
|
|
-
|
|
|
|
- // streaming audionodes get played using android mediaplayer, non streaming uses SoundPool
|
|
|
|
- if (assetKey.isStream())
|
|
|
|
- {
|
|
|
|
- MediaPlayer mp;
|
|
|
|
- if (musicPlaying.containsKey(src))
|
|
|
|
- {
|
|
|
|
- mp = musicPlaying.get(src);
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- mp = new MediaPlayer();
|
|
|
|
- mp.setOnCompletionListener(this);
|
|
|
|
- //mp = MediaPlayer.create(context, new Ur );
|
|
|
|
- musicPlaying.put(src, mp);
|
|
|
|
- }
|
|
|
|
- if (!mp.isPlaying())
|
|
|
|
- {
|
|
|
|
- try {
|
|
|
|
- AssetFileDescriptor afd = am.openFd(assetKey.getName());
|
|
|
|
- mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
|
|
|
|
-
|
|
|
|
- mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
|
|
|
|
- mp.prepare();
|
|
|
|
- mp.setLooping(src.isLooping());
|
|
|
|
- mp.start();
|
|
|
|
- src.setChannel(1);
|
|
|
|
- src.setStatus(Status.Playing);
|
|
|
|
- } catch (IllegalArgumentException e)
|
|
|
|
- {
|
|
|
|
- logger.log(Level.SEVERE, "Failed to play " + assetKey.getName(), e);
|
|
|
|
- } catch (IllegalStateException e) {
|
|
|
|
- // TODO Auto-generated catch block
|
|
|
|
- logger.log(Level.SEVERE, "Failed to play " + assetKey.getName(), e);
|
|
|
|
- } catch (IOException e) {
|
|
|
|
- // TODO Auto-generated catch block
|
|
|
|
- logger.log(Level.SEVERE, "Failed to play " + assetKey.getName(), e);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
|
|
+
|
|
|
|
+ public void playSourceInstance(AudioNode src) {
|
|
|
|
+ if (audioDisabled) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ AndroidAudioData audioData;
|
|
|
|
+ int soundId = 0;
|
|
|
|
+
|
|
|
|
+ if (src.getAudioData() instanceof AndroidAudioData) {
|
|
|
|
+ audioData = (AndroidAudioData) src.getAudioData();
|
|
|
|
+
|
|
|
|
+ if (audioData.getAssetKey() instanceof AudioKey) {
|
|
|
|
+ AudioKey assetKey = (AudioKey) audioData.getAssetKey();
|
|
|
|
+
|
|
|
|
+ // streaming audionodes get played using android mediaplayer, non streaming uses SoundPool
|
|
|
|
+ if (assetKey.isStream()) {
|
|
|
|
+ MediaPlayer mp;
|
|
|
|
+ if (musicPlaying.containsKey(src)) {
|
|
|
|
+ mp = musicPlaying.get(src);
|
|
|
|
+ } else {
|
|
|
|
+ mp = new MediaPlayer();
|
|
|
|
+ mp.setOnCompletionListener(this);
|
|
|
|
+ //mp = MediaPlayer.create(context, new Ur );
|
|
|
|
+ musicPlaying.put(src, mp);
|
|
|
|
+ }
|
|
|
|
+ if (!mp.isPlaying()) {
|
|
|
|
+ try {
|
|
|
|
+ AssetFileDescriptor afd = am.openFd(assetKey.getName());
|
|
|
|
+ mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
|
|
|
|
+
|
|
|
|
+ mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
|
|
|
|
+ mp.prepare();
|
|
|
|
+ mp.setLooping(src.isLooping());
|
|
|
|
+ mp.start();
|
|
|
|
+ src.setChannel(1);
|
|
|
|
+ src.setStatus(Status.Playing);
|
|
|
|
+ } catch (IllegalArgumentException e) {
|
|
|
|
+ logger.log(Level.SEVERE, "Failed to play " + assetKey.getName(), e);
|
|
|
|
+ } catch (IllegalStateException e) {
|
|
|
|
+ // TODO Auto-generated catch block
|
|
|
|
+ logger.log(Level.SEVERE, "Failed to play " + assetKey.getName(), e);
|
|
|
|
+ } catch (IOException e) {
|
|
|
|
+ // TODO Auto-generated catch block
|
|
|
|
+ logger.log(Level.SEVERE, "Failed to play " + assetKey.getName(), e);
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
}
|
|
}
|
|
- else
|
|
|
|
- {
|
|
|
|
- // Low latency Sound effect using SoundPool
|
|
|
|
- if (audioData.isUpdateNeeded() || (audioData.getSoundId() <= 0))
|
|
|
|
- {
|
|
|
|
- if (audioData.getSoundId() > 0)
|
|
|
|
- {
|
|
|
|
- if (src.getChannel() > 0)
|
|
|
|
- {
|
|
|
|
- soundPool.stop(src.getChannel());
|
|
|
|
- src.setChannel(-1);
|
|
|
|
- }
|
|
|
|
- soundPool.unload(audioData.getSoundId());
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- try
|
|
|
|
- {
|
|
|
|
- soundId = soundPool.load(am.openFd(assetKey.getName()), 1);
|
|
|
|
- }
|
|
|
|
- catch (IOException e)
|
|
|
|
- {
|
|
|
|
- logger.log(Level.SEVERE, "Failed to load sound " + assetKey.getName(), e);
|
|
|
|
- soundId = -1;
|
|
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
+ // Low latency Sound effect using SoundPool
|
|
|
|
+ if (audioData.isUpdateNeeded() || (audioData.getId() <= 0)) {
|
|
|
|
+ if (audioData.getId() > 0) {
|
|
|
|
+ if (src.getChannel() > 0) {
|
|
|
|
+ soundPool.stop(src.getChannel());
|
|
|
|
+ src.setChannel(-1);
|
|
}
|
|
}
|
|
- audioData.setSoundId(soundId);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // Sound failed to load ?
|
|
|
|
- if (audioData.getSoundId() <= 0)
|
|
|
|
- {
|
|
|
|
- throw new IllegalArgumentException("Failed to load: " + assetKey.getName());
|
|
|
|
|
|
+ soundPool.unload(audioData.getId());
|
|
}
|
|
}
|
|
- else
|
|
|
|
- {
|
|
|
|
- int channelIndex;
|
|
|
|
- channelIndex = soundPool.play(audioData.getSoundId(), 1f, 1f, 1, -1, 1f);
|
|
|
|
- if (channelIndex == 0)
|
|
|
|
- {
|
|
|
|
- // Loading is not finished
|
|
|
|
- // Store the soundId and the AudioNode for async loading and later play start
|
|
|
|
- mapLoadingAudioNodes.put(audioData.getSoundId(), src);
|
|
|
|
- }
|
|
|
|
- src.setChannel(channelIndex);
|
|
|
|
|
|
+
|
|
|
|
+ try {
|
|
|
|
+ soundId = soundPool.load(am.openFd(assetKey.getName()), 1);
|
|
|
|
+ } catch (IOException e) {
|
|
|
|
+ logger.log(Level.SEVERE, "Failed to load sound " + assetKey.getName(), e);
|
|
|
|
+ soundId = -1;
|
|
}
|
|
}
|
|
-
|
|
|
|
- // Playing started ?
|
|
|
|
- if (src.getChannel() > 0)
|
|
|
|
- {
|
|
|
|
- src.setStatus(Status.Playing);
|
|
|
|
|
|
+ audioData.setId(soundId);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Sound failed to load ?
|
|
|
|
+ if (audioData.getId() <= 0) {
|
|
|
|
+ throw new IllegalArgumentException("Failed to load: " + assetKey.getName());
|
|
|
|
+ } else {
|
|
|
|
+ int channelIndex;
|
|
|
|
+ channelIndex = soundPool.play(audioData.getId(), 1f, 1f, 1, -1, 1f);
|
|
|
|
+ if (channelIndex == 0) {
|
|
|
|
+ // Loading is not finished
|
|
|
|
+ // Store the soundId and the AudioNode for async loading and later play start
|
|
|
|
+ mapLoadingAudioNodes.put(audioData.getId(), src);
|
|
}
|
|
}
|
|
|
|
+ src.setChannel(channelIndex);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Playing started ?
|
|
|
|
+ if (src.getChannel() > 0) {
|
|
|
|
+ src.setStatus(Status.Playing);
|
|
}
|
|
}
|
|
-
|
|
|
|
}
|
|
}
|
|
|
|
+
|
|
}
|
|
}
|
|
- else
|
|
|
|
- {
|
|
|
|
- throw new IllegalArgumentException("AudioData is not of type AndroidAudioData for AudioNode " + src.toString());
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
|
|
+ } else {
|
|
|
|
+ throw new IllegalArgumentException("AudioData is not of type AndroidAudioData for AudioNode " + src.toString());
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
|
|
-
|
|
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
- public void playSource(AudioNode src)
|
|
|
|
- {
|
|
|
|
- if (audioDisabled)
|
|
|
|
- return;
|
|
|
|
|
|
+ public void playSource(AudioNode src) {
|
|
|
|
+ if (audioDisabled) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ //assert src.getStatus() == Status.Stopped || src.getChannel() == -1;
|
|
|
|
+
|
|
|
|
+ if (src.getStatus() == Status.Playing) {
|
|
|
|
+ return;
|
|
|
|
+ } else if (src.getStatus() == Status.Stopped) {
|
|
|
|
+ playSourceInstance(src);
|
|
|
|
+ }
|
|
|
|
|
|
- //assert src.getStatus() == Status.Stopped || src.getChannel() == -1;
|
|
|
|
|
|
|
|
- if (src.getStatus() == Status.Playing)
|
|
|
|
- {
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
- else if (src.getStatus() == Status.Stopped)
|
|
|
|
- {
|
|
|
|
- playSourceInstance(src);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
-
|
|
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
- public void pauseSource(AudioNode src)
|
|
|
|
- {
|
|
|
|
- if (audioDisabled)
|
|
|
|
- return;
|
|
|
|
-
|
|
|
|
- if (src.getStatus() == Status.Playing)
|
|
|
|
- {
|
|
|
|
- if (src.getAudioData() instanceof AndroidAudioData)
|
|
|
|
- {
|
|
|
|
- AndroidAudioData audioData = (AndroidAudioData)src.getAudioData();
|
|
|
|
- if (audioData.getAssetKey() instanceof AudioKey)
|
|
|
|
- {
|
|
|
|
- AudioKey assetKey = (AudioKey) audioData.getAssetKey();
|
|
|
|
-
|
|
|
|
- if (assetKey.isStream())
|
|
|
|
- {
|
|
|
|
- MediaPlayer mp;
|
|
|
|
- if (musicPlaying.containsKey(src))
|
|
|
|
- {
|
|
|
|
- mp = musicPlaying.get(src);
|
|
|
|
- mp.pause();
|
|
|
|
- src.setStatus(Status.Paused);
|
|
|
|
- }
|
|
|
|
|
|
+ public void pauseSource(AudioNode src) {
|
|
|
|
+ if (audioDisabled) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (src.getStatus() == Status.Playing) {
|
|
|
|
+ if (src.getAudioData() instanceof AndroidAudioData) {
|
|
|
|
+ AndroidAudioData audioData = (AndroidAudioData) src.getAudioData();
|
|
|
|
+ if (audioData.getAssetKey() instanceof AudioKey) {
|
|
|
|
+ AudioKey assetKey = (AudioKey) audioData.getAssetKey();
|
|
|
|
+
|
|
|
|
+ if (assetKey.isStream()) {
|
|
|
|
+ MediaPlayer mp;
|
|
|
|
+ if (musicPlaying.containsKey(src)) {
|
|
|
|
+ mp = musicPlaying.get(src);
|
|
|
|
+ mp.pause();
|
|
|
|
+ src.setStatus(Status.Paused);
|
|
}
|
|
}
|
|
- else
|
|
|
|
- {
|
|
|
|
- assert src.getChannel() != -1;
|
|
|
|
-
|
|
|
|
- if (src.getChannel() > 0)
|
|
|
|
- {
|
|
|
|
- soundPool.pause(src.getChannel());
|
|
|
|
- src.setStatus(Status.Paused);
|
|
|
|
- }
|
|
|
|
|
|
+ } else {
|
|
|
|
+ assert src.getChannel() != -1;
|
|
|
|
+
|
|
|
|
+ if (src.getChannel() > 0) {
|
|
|
|
+ soundPool.pause(src.getChannel());
|
|
|
|
+ src.setStatus(Status.Paused);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ }
|
|
|
|
+
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
- public void stopSource(AudioNode src)
|
|
|
|
- {
|
|
|
|
- if (audioDisabled)
|
|
|
|
- return;
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- if (src.getStatus() != Status.Stopped)
|
|
|
|
- {
|
|
|
|
- if (src.getAudioData() instanceof AndroidAudioData)
|
|
|
|
- {
|
|
|
|
- AndroidAudioData audioData = (AndroidAudioData)src.getAudioData();
|
|
|
|
- if (audioData.getAssetKey() instanceof AudioKey)
|
|
|
|
- {
|
|
|
|
- AudioKey assetKey = (AudioKey) audioData.getAssetKey();
|
|
|
|
- if (assetKey.isStream())
|
|
|
|
- {
|
|
|
|
- MediaPlayer mp;
|
|
|
|
- if (musicPlaying.containsKey(src))
|
|
|
|
- {
|
|
|
|
- mp = musicPlaying.get(src);
|
|
|
|
- mp.stop();
|
|
|
|
- src.setStatus(Status.Stopped);
|
|
|
|
- src.setChannel(-1);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- int chan = src.getChannel();
|
|
|
|
- assert chan != -1; // if it's not stopped, must have id
|
|
|
|
-
|
|
|
|
- if (src.getChannel() > 0)
|
|
|
|
- {
|
|
|
|
- soundPool.stop(src.getChannel());
|
|
|
|
- src.setChannel(-1);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
|
|
+ public void stopSource(AudioNode src) {
|
|
|
|
+ if (audioDisabled) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ if (src.getStatus() != Status.Stopped) {
|
|
|
|
+ if (src.getAudioData() instanceof AndroidAudioData) {
|
|
|
|
+ AndroidAudioData audioData = (AndroidAudioData) src.getAudioData();
|
|
|
|
+ if (audioData.getAssetKey() instanceof AudioKey) {
|
|
|
|
+ AudioKey assetKey = (AudioKey) audioData.getAssetKey();
|
|
|
|
+ if (assetKey.isStream()) {
|
|
|
|
+ MediaPlayer mp;
|
|
|
|
+ if (musicPlaying.containsKey(src)) {
|
|
|
|
+ mp = musicPlaying.get(src);
|
|
|
|
+ mp.stop();
|
|
src.setStatus(Status.Stopped);
|
|
src.setStatus(Status.Stopped);
|
|
-
|
|
|
|
- if (audioData.getSoundId() > 0)
|
|
|
|
- {
|
|
|
|
- soundPool.unload(audioData.getSoundId());
|
|
|
|
- }
|
|
|
|
- audioData.setSoundId(-1);
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-
|
|
|
|
|
|
+ src.setChannel(-1);
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ int chan = src.getChannel();
|
|
|
|
+ assert chan != -1; // if it's not stopped, must have id
|
|
|
|
+
|
|
|
|
+ if (src.getChannel() > 0) {
|
|
|
|
+ soundPool.stop(src.getChannel());
|
|
|
|
+ src.setChannel(-1);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ src.setStatus(Status.Stopped);
|
|
|
|
+
|
|
|
|
+ if (audioData.getId() > 0) {
|
|
|
|
+ soundPool.unload(audioData.getId());
|
|
}
|
|
}
|
|
|
|
+ audioData.setId(-1);
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- }
|
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
|
|
- public void updateAudioData(AndroidAudioData data)
|
|
|
|
- {
|
|
|
|
|
|
+ public void updateAudioData(AndroidAudioData data) {
|
|
throw new UnsupportedOperationException("updateAudioData");
|
|
throw new UnsupportedOperationException("updateAudioData");
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ public void deleteFilter(Filter filter) {
|
|
|
|
+ }
|
|
|
|
+
|
|
@Override
|
|
@Override
|
|
- public void deleteAudioData(AudioData ad)
|
|
|
|
- {
|
|
|
|
- if (ad instanceof AndroidAudioData)
|
|
|
|
- {
|
|
|
|
- AndroidAudioData audioData = (AndroidAudioData)ad;
|
|
|
|
- if (audioData.getAssetKey() instanceof AudioKey)
|
|
|
|
- {
|
|
|
|
- AudioKey assetKey = (AudioKey) audioData.getAssetKey();
|
|
|
|
- if (assetKey.isStream())
|
|
|
|
- {
|
|
|
|
- for (AudioNode src : musicPlaying.keySet())
|
|
|
|
- {
|
|
|
|
- if (src.getAudioData() == ad)
|
|
|
|
- {
|
|
|
|
|
|
+ public void deleteAudioData(AudioData ad) {
|
|
|
|
+ if (ad instanceof AndroidAudioData) {
|
|
|
|
+ AndroidAudioData audioData = (AndroidAudioData) ad;
|
|
|
|
+ if (audioData.getAssetKey() instanceof AudioKey) {
|
|
|
|
+ AudioKey assetKey = (AudioKey) audioData.getAssetKey();
|
|
|
|
+ if (assetKey.isStream()) {
|
|
|
|
+ for (AudioNode src : musicPlaying.keySet()) {
|
|
|
|
+ if (src.getAudioData() == ad) {
|
|
MediaPlayer mp = musicPlaying.get(src);
|
|
MediaPlayer mp = musicPlaying.get(src);
|
|
mp.stop();
|
|
mp.stop();
|
|
mp.release();
|
|
mp.release();
|
|
musicPlaying.remove(src);
|
|
musicPlaying.remove(src);
|
|
src.setStatus(Status.Stopped);
|
|
src.setStatus(Status.Stopped);
|
|
src.setChannel(-1);
|
|
src.setChannel(-1);
|
|
- break;
|
|
|
|
|
|
+ break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- if (audioData.getSoundId() > 0)
|
|
|
|
- {
|
|
|
|
- soundPool.unload(audioData.getSoundId());
|
|
|
|
|
|
+ } else {
|
|
|
|
+ if (audioData.getId() > 0) {
|
|
|
|
+ soundPool.unload(audioData.getId());
|
|
}
|
|
}
|
|
- audioData.setSoundId(0);
|
|
|
|
|
|
+ audioData.setId(0);
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
}
|
|
}
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
|
|
+ } else {
|
|
throw new IllegalArgumentException("AudioData is not of type AndroidAudioData in deleteAudioData");
|
|
throw new IllegalArgumentException("AudioData is not of type AndroidAudioData in deleteAudioData");
|
|
- }
|
|
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
@Override
|
|
@Override
|
|
public void setEnvironment(Environment env) {
|
|
public void setEnvironment(Environment env) {
|
|
// TODO Auto-generated method stub
|
|
// TODO Auto-generated method stub
|
|
-
|
|
|
|
}
|
|
}
|
|
-
|
|
|
|
-
|
|
|
|
}
|
|
}
|