Переглянути джерело

* Applied android audio renderer patch (thanks to prich on the forum)

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@9147 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
Sha..rd 13 роки тому
батько
коміт
381a3365ef

+ 62 - 62
engine/src/android/com/jme3/audio/android/AndroidAudioData.java

@@ -1,62 +1,62 @@
-package com.jme3.audio.android;
-
-import com.jme3.asset.AssetKey;
-import com.jme3.audio.AudioData;
-import com.jme3.audio.AudioRenderer;
-import com.jme3.util.NativeObject;
-
-public class AndroidAudioData extends AudioData {
-
-    protected AssetKey assetKey;
-    protected float currentVolume = 0f;
-
-    public AndroidAudioData(){
-        super();
-    }
-    
-    protected AndroidAudioData(int id){
-        super(id);
-    }
-    
-    public AssetKey getAssetKey() {
-        return assetKey;
-    }
-
-    public void setAssetKey(AssetKey assetKey) {
-        this.assetKey = assetKey;
-    }
-
-    @Override
-    public DataType getDataType() {
-        return DataType.Buffer;
-    }
-
-    @Override
-    public float getDuration() {
-        return 0; // TODO: ???
-    }
-
-    @Override
-    public void resetObject() {
-        this.id = -1;
-        setUpdateNeeded();  
-    }
-
-    @Override
-    public void deleteObject(Object rendererObject) {
-        ((AudioRenderer)rendererObject).deleteAudioData(this);
-    }
-
-    public float getCurrentVolume() {
-        return currentVolume;
-    }
-
-    public void setCurrentVolume(float currentVolume) {
-        this.currentVolume = currentVolume;
-    }
-
-    @Override
-    public NativeObject createDestructableClone() {
-        return new AndroidAudioData(id);
-    }
-}
+package com.jme3.audio.android;
+
+import com.jme3.asset.AssetKey;
+import com.jme3.audio.AudioData;
+import com.jme3.audio.AudioRenderer;
+import com.jme3.util.NativeObject;
+
+public class AndroidAudioData extends AudioData {
+
+    protected AssetKey<?> assetKey;
+    protected float currentVolume = 0f;
+
+    public AndroidAudioData(){
+        super();
+    }
+    
+    protected AndroidAudioData(int id){
+        super(id);
+    }
+    
+    public AssetKey<?> getAssetKey() {
+        return assetKey;
+    }
+
+    public void setAssetKey(AssetKey<?> assetKey) {
+        this.assetKey = assetKey;
+    }
+
+    @Override
+    public DataType getDataType() {
+        return DataType.Buffer;
+    }
+
+    @Override
+    public float getDuration() {
+        return 0; // TODO: ???
+    }
+
+    @Override
+    public void resetObject() {
+        this.id = -1;
+        setUpdateNeeded();  
+    }
+
+    @Override
+    public void deleteObject(Object rendererObject) {
+        ((AudioRenderer)rendererObject).deleteAudioData(this);
+    }
+
+    public float getCurrentVolume() {
+        return currentVolume;
+    }
+
+    public void setCurrentVolume(float currentVolume) {
+        this.currentVolume = currentVolume;
+    }
+
+    @Override
+    public NativeObject createDestructableClone() {
+        return new AndroidAudioData(id);
+    }
+}

+ 423 - 519
engine/src/android/com/jme3/audio/android/AndroidAudioRenderer.java

@@ -38,6 +38,9 @@ import android.content.res.AssetManager;
 import android.media.AudioManager;
 import android.media.MediaPlayer;
 import android.media.SoundPool;
+import android.util.Log;
+
+import com.jme3.asset.AssetKey;
 import com.jme3.audio.AudioNode.Status;
 import com.jme3.audio.*;
 import com.jme3.math.FastMath;
@@ -50,525 +53,426 @@ import java.util.logging.Logger;
 
 /**
  * This class is the android implementation for {@link AudioRenderer}
+ * 
  * @author larynx
- *
+ * @author plan_rich
  */
-public class AndroidAudioRenderer implements AudioRenderer, SoundPool.OnLoadCompleteListener, MediaPlayer.OnCompletionListener {
-
-    private static final Logger logger = Logger.getLogger(AndroidAudioRenderer.class.getName());
-    private final static int MAX_NUM_CHANNELS = 16;
-    private SoundPool soundPool = null;
-    private HashMap<AudioNode, MediaPlayer> musicPlaying = new HashMap<AudioNode, MediaPlayer>();
-    private final Vector3f listenerPosition = new Vector3f();
-    // For temp use
-    private final Vector3f distanceVector = new Vector3f();
-    private final AudioManager manager;
-    private final Context context;
-    private final AssetManager am;
-    private HashMap<Integer, AudioNode> mapLoadingAudioNodes = new HashMap<Integer, AudioNode>();
-    private final AtomicBoolean lastLoadCompleted = new AtomicBoolean();
-    private Listener listener;
-    private boolean audioDisabled = false;
-
-    public AndroidAudioRenderer(Activity context) {
-        this.context = context;
-        manager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
-        context.setVolumeControlStream(AudioManager.STREAM_MUSIC);
-        am = context.getAssets();
-    }
-
-    @Override
-    public void initialize() {
-        soundPool = new SoundPool(MAX_NUM_CHANNELS, AudioManager.STREAM_MUSIC, 0);
-        soundPool.setOnLoadCompleteListener(this);
-    }
-
-    @Override
-    public void updateSourceParam(AudioNode src, AudioParam 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()) {
-                }
-                break;
-            case Volume:
-
-                soundPool.setVolume(src.getChannel(), src.getVolume(), src.getVolume());
-
-                break;
-            case Pitch:
-
-                break;
-        }
-
-    }
-
-    @Override
-    public void updateListenerParam(Listener listener, ListenerParam param) {
-        //logger.log(Level.INFO, "updateListenerParam " + param);
-        if (audioDisabled) {
-            return;
-        }
-
-        switch (param) {
-            case Position:
-                listenerPosition.set(listener.getLocation());
-
-                break;
-            case Rotation:
-                Vector3f dir = listener.getDirection();
-                Vector3f up = listener.getUp();
-
-                break;
-            case Velocity:
-                Vector3f vel = listener.getVelocity();
-
-                break;
-            case Volume:
-                //alListenerf(AL_GAIN, listener.getVolume());
-                break;
-        }
-
-    }
-
-    @Override
-    public void update(float tpf) {
-        float distance;
-        float volume;
-
-        // Loop over all mediaplayers
-        for (AudioNode src : musicPlaying.keySet()) {
-
-            MediaPlayer mp = musicPlaying.get(src);
-            {
-                // Calc the distance to the listener
-                distanceVector.set(listenerPosition);
-                distanceVector.subtractLocal(src.getLocalTranslation());
-                distance = FastMath.abs(distanceVector.length());
-
-                if (distance < src.getRefDistance()) {
-                    distance = src.getRefDistance();
-                }
-                if (distance > src.getMaxDistance()) {
-                    distance = src.getMaxDistance();
-                }
-                volume = src.getRefDistance() / distance;
-
-                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
-                    mp.setVolume(volume, volume);
-
-                    audioData.setCurrentVolume(volume);
-                }
-
-
-            }
-        }
-    }
-
-    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);
-
-    }
-
-    @Override
-    public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
-        AudioNode src = mapLoadingAudioNodes.get(sampleId);
-        if (src.getAudioData() instanceof AndroidAudioData) {
-            AndroidAudioData audioData = (AndroidAudioData) src.getAudioData();
-
-            if (status == 0) // load was successfull
-            {
-                int channelIndex;
-                channelIndex = soundPool.play(audioData.getId(), 1f, 1f, 1, -1, 1f);
-                src.setChannel(channelIndex);
-                // Playing started ?
-                if (src.getChannel() > 0) {
-                    src.setStatus(Status.Playing);
-                }
-            } else {
-                src.setChannel(-1);
-            }
-        } else {
-            throw new IllegalArgumentException("AudioData is not of type AndroidAudioData for AudioNode " + src.toString());
-        }
-    }
-
-    @Override
-    public void cleanup() {
-        // Cleanup sound pool
-        if (soundPool != null) {
-            for (AudioNode src : mapLoadingAudioNodes.values()) {
-                if ((src.getStatus() == Status.Playing) && (src.getChannel() > 0)) {
-                    soundPool.stop(src.getChannel());
-                }
-
-                if (src.getAudioData() instanceof AndroidAudioData) {
-                    AndroidAudioData audioData = (AndroidAudioData) src.getAudioData();
-                    if (audioData.getId() > 0) {
-                        soundPool.unload(audioData.getId());
-                    }
-                }
-            }
-
-            soundPool.release();
-            soundPool = null;
-        }
-
-        // Cleanup media player
-        for (AudioNode src : musicPlaying.keySet()) {
-            MediaPlayer mp = musicPlaying.get(src);
-            {
-                mp.stop();
-                mp.release();
-                src.setStatus(Status.Stopped);
-            }
-        }
-        musicPlaying.clear();
-    }
-
-    @Override
-    public void onCompletion(MediaPlayer mp) {
-        for (AudioNode src : musicPlaying.keySet()) {
-            if (musicPlaying.get(src) == mp) {
-                mp.seekTo(0);
-                mp.stop();
-                src.setStatus(Status.Stopped);
-                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);
-                        }
-
-                    }
-
-                } 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);
-                            }
-                            soundPool.unload(audioData.getId());
-                        }
-
-                        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;
-                        }
-                        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());
-        }
-
-
-
-    }
-
-    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);
-        }
-
-
-    }
-
-    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);
-                        }
-                    }
-                }
-            }
-
-        }
-
-    }
-
-    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);
-                        }
-
-                        src.setStatus(Status.Stopped);
-
-                        if (audioData.getId() > 0) {
-                            soundPool.unload(audioData.getId());
-                        }
-                        audioData.setId(-1);
-
-
-
-                    }
-                }
-            }
-
-        }
-
-    }
-
-    public void updateAudioData(AndroidAudioData data) {
-        throw new UnsupportedOperationException("updateAudioData");
-    }
-
-    public void deleteFilter(Filter filter) {
-    }
-    
-    @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) {
-                            MediaPlayer mp = musicPlaying.get(src);
-                            mp.stop();
-                            mp.release();
-                            musicPlaying.remove(src);
-                            src.setStatus(Status.Stopped);
-                            src.setChannel(-1);
-                            break;
-                        }
-                    }
-                } else {
-                    if (audioData.getId() > 0) {
-                        soundPool.unload(audioData.getId());
-                    }
-                    audioData.setId(0);
-                }
-
-            }
-        } else {
-            throw new IllegalArgumentException("AudioData is not of type AndroidAudioData in deleteAudioData");
-        }
-    }
-
-    @Override
-    public void setEnvironment(Environment env) {
-        // TODO Auto-generated method stub
-    }
+public class AndroidAudioRenderer implements AudioRenderer,
+		SoundPool.OnLoadCompleteListener, MediaPlayer.OnCompletionListener {
+
+	private static final Logger logger = Logger
+			.getLogger(AndroidAudioRenderer.class.getName());
+	private final static int MAX_NUM_CHANNELS = 16;
+	private final HashMap<AudioNode, MediaPlayer> musicPlaying = new HashMap<AudioNode, MediaPlayer>();
+	private SoundPool soundPool = null;
+
+	private final Vector3f listenerPosition = new Vector3f();
+	// For temp use
+	private final Vector3f distanceVector = new Vector3f();
+	private final Context context;
+	private final AssetManager assetManager;
+	private HashMap<Integer, AudioNode> soundpoolStillLoading = new HashMap<Integer, AudioNode>();
+	private Listener listener;
+	private boolean audioDisabled = false;
+
+	private final AudioManager manager;
+
+	public AndroidAudioRenderer(Activity context) {
+		this.context = context;
+		manager = (AudioManager) context
+				.getSystemService(Context.AUDIO_SERVICE);
+		context.setVolumeControlStream(AudioManager.STREAM_MUSIC);
+		assetManager = context.getAssets();
+	}
+
+	@Override
+	public void initialize() {
+		soundPool = new SoundPool(MAX_NUM_CHANNELS, AudioManager.STREAM_MUSIC,
+				0);
+		soundPool.setOnLoadCompleteListener(this);
+	}
+
+	@Override
+	public void updateSourceParam(AudioNode src, AudioParam param) {
+		// logger.log(Level.INFO, "updateSourceParam " + param);
+
+		if (audioDisabled) {
+			return;
+		}
+
+		if (src.getChannel() < 0) {
+			return;
+		}
+
+		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()) {
+			}
+			break;
+		case Volume:
+
+			soundPool.setVolume(src.getChannel(), src.getVolume(),
+					src.getVolume());
+
+			break;
+		case Pitch:
+
+			break;
+		}
+
+	}
+
+	@Override
+	public void updateListenerParam(Listener listener, ListenerParam param) {
+		// logger.log(Level.INFO, "updateListenerParam " + param);
+		if (audioDisabled) {
+			return;
+		}
+
+		switch (param) {
+		case Position:
+			listenerPosition.set(listener.getLocation());
+
+			break;
+		case Rotation:
+			Vector3f dir = listener.getDirection();
+			Vector3f up = listener.getUp();
+
+			break;
+		case Velocity:
+			Vector3f vel = listener.getVelocity();
+
+			break;
+		case Volume:
+			// alListenerf(AL_GAIN, listener.getVolume());
+			break;
+		}
+
+	}
+
+	@Override
+	public void update(float tpf) {
+		float distance;
+		float volume;
+
+		// Loop over all mediaplayers
+		for (AudioNode src : musicPlaying.keySet()) {
+
+			MediaPlayer mp = musicPlaying.get(src);
+			{
+				// Calc the distance to the listener
+				distanceVector.set(listenerPosition);
+				distanceVector.subtractLocal(src.getLocalTranslation());
+				distance = FastMath.abs(distanceVector.length());
+
+				if (distance < src.getRefDistance()) {
+					distance = src.getRefDistance();
+				}
+				if (distance > src.getMaxDistance()) {
+					distance = src.getMaxDistance();
+				}
+				volume = src.getRefDistance() / distance;
+
+				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
+					mp.setVolume(volume, volume);
+
+					audioData.setCurrentVolume(volume);
+				}
+			}
+		}
+	}
+
+	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);
+
+	}
+
+	@Override
+	public void cleanup() {
+		// Cleanup sound pool
+		if (soundPool != null) {
+			soundPool.release();
+			soundPool = null;
+		}
+
+		// Cleanup media player
+		for (AudioNode src : musicPlaying.keySet()) {
+			MediaPlayer mp = musicPlaying.get(src);
+			{
+				mp.stop();
+				mp.release();
+				src.setStatus(Status.Stopped);
+			}
+		}
+		musicPlaying.clear();
+	}
+
+	@Override
+	public void onCompletion(MediaPlayer mp) {
+		mp.seekTo(0);
+		mp.stop();
+		// XXX: This has bad performance -> maybe change overall structure of
+		// mediaplayer in this audiorenderer?
+		for (AudioNode src : musicPlaying.keySet()) {
+			if (musicPlaying.get(src) == mp) {
+				src.setStatus(Status.Stopped);
+				break;
+			}
+		}
+	}
+
+	/**
+	 * Plays using the {@link SoundPool} of Android. Due to hard limitation of
+	 * the SoundPool: After playing more instances of the sound you only have
+	 * the channel of the last played instance.
+	 * 
+	 * It is not possible to get information about the state of the soundpool of
+	 * a specific streamid, so removing is not possilbe -> noone knows when
+	 * sound finished.
+	 */
+	public void playSourceInstance(AudioNode src) {
+		if (audioDisabled) {
+			return;
+		}
+
+		AndroidAudioData audioData = (AndroidAudioData) src.getAudioData();
+
+		if (!(audioData.getAssetKey() instanceof AudioKey)) {
+			throw new IllegalArgumentException("Asset is not a AudioKey");
+		}
+
+		AudioKey assetKey = (AudioKey) audioData.getAssetKey();
+
+		try {
+			if (audioData.getId() < 0) { // found something to load
+				int soundId = soundPool.load(
+						assetManager.openFd(assetKey.getName()), 1);
+				audioData.setId(soundId);
+			}
+
+			int channel = soundPool.play(audioData.getId(), 1f, 1f, 1, 0, 1f);
+
+			if (channel == 0) {
+				soundpoolStillLoading.put(audioData.getId(), src);
+			} else {
+				src.setChannel(channel); // receive a channel at the last
+											// playing at least
+			}
+		} catch (IOException e) {
+			logger.log(Level.SEVERE,
+					"Failed to load sound " + assetKey.getName(), e);
+			audioData.setId(-1);
+		}
+	}
+
+	@Override
+	public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
+		AudioNode src = soundpoolStillLoading.remove(sampleId);
+
+		if (src == null) {
+			logger.warning("Something went terribly wrong! onLoadComplete"
+					+ " had sampleId which was not in the HashMap of loading items");
+			return;
+		}
+
+		AudioData audioData = src.getAudioData();
+
+		if (status == 0) // load was successfull
+		{
+			int channelIndex;
+			channelIndex = soundPool.play(audioData.getId(), 1f, 1f, 1, 0, 1f);
+			src.setChannel(channelIndex);
+		}
+	}
+
+	public void playSource(AudioNode src) {
+		if (audioDisabled) {
+			return;
+		}
+
+		AndroidAudioData audioData = (AndroidAudioData) src.getAudioData();
+
+		MediaPlayer mp = musicPlaying.get(src);
+		if (mp == null) {
+			mp = new MediaPlayer();
+			mp.setOnCompletionListener(this);
+			mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
+		}
+
+		try {
+			AssetKey<?> key = audioData.getAssetKey();
+
+			AssetFileDescriptor afd = assetManager.openFd(key.getName()); // assetKey.getName()
+			mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(),
+					afd.getLength());
+			mp.prepare();
+			mp.setLooping(src.isLooping());
+			mp.start();
+			src.setChannel(0);
+			src.setStatus(Status.Playing);
+			musicPlaying.put(src, mp);
+
+		} catch (IllegalStateException e) {
+			e.printStackTrace();
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+	}
+
+	public void pauseSource(AudioNode src) {
+		if (audioDisabled) {
+			return;
+		}
+
+		MediaPlayer mp = musicPlaying.get(src);
+		if (mp != null) {
+			mp.pause();
+			src.setStatus(Status.Paused);
+		} else {
+			int channel = src.getChannel();
+			if (channel != -1)
+				soundPool.pause(channel); // is not very likley to make
+											// something useful :)
+		}
+	}
+
+	public void stopSource(AudioNode src) {
+		if (audioDisabled) {
+			return;
+		}
+
+		// can be stream or buffer -> so try to get mediaplayer
+		// if there is non try to stop soundpool
+		MediaPlayer mp = musicPlaying.get(src);
+		if (mp != null) {
+			mp.stop();
+			src.setStatus(Status.Paused);
+		} else {
+			int channel = src.getChannel();
+			if (channel != -1) {
+				soundPool.pause(channel); // is not very likley to make
+											// something useful :)
+			}
+		}
+
+	}
+
+	@Override
+	public void deleteAudioData(AudioData ad) {
+
+		for (AudioNode src : musicPlaying.keySet()) {
+			if (src.getAudioData() == ad) {
+				MediaPlayer mp = musicPlaying.remove(src);
+				mp.stop();
+				mp.release();
+				src.setStatus(Status.Stopped);
+				src.setChannel(-1);
+				ad.setId(-1);
+				break;
+			}
+		}
+		
+		if (ad.getId() > 0) {
+			soundPool.unload(ad.getId());
+			ad.setId(-1);
+		}
+	}
+
+	@Override
+	public void setEnvironment(Environment env) {
+		//not yet supported
+	}
+
+	@Override
+	public void deleteFilter(Filter filter) {
+	}
 }

+ 19 - 26
engine/src/android/com/jme3/audio/plugins/AndroidAudioLoader.java

@@ -1,26 +1,19 @@
-package com.jme3.audio.plugins;
-
-import com.jme3.asset.AssetInfo;
-import com.jme3.asset.AssetLoader;
-import com.jme3.audio.android.AndroidAudioData;
-import java.io.IOException;
-import java.io.InputStream;
-
-public class AndroidAudioLoader implements AssetLoader 
-{
-
-    @Override
-    public Object load(AssetInfo assetInfo) throws IOException 
-    {
-
-        InputStream in = assetInfo.openStream();
-        if (in != null)
-        {            
-            in.close();
-        }
-        AndroidAudioData result = new AndroidAudioData();
-        result.setAssetKey( assetInfo.getKey() );
-        return result;
-    }
-
-}
+package com.jme3.audio.plugins;
+
+import com.jme3.asset.AssetInfo;
+import com.jme3.asset.AssetLoader;
+import com.jme3.audio.android.AndroidAudioData;
+import java.io.IOException;
+
+public class AndroidAudioLoader implements AssetLoader 
+{
+
+    @Override
+    public Object load(AssetInfo assetInfo) throws IOException 
+    {
+        AndroidAudioData result = new AndroidAudioData();
+        result.setAssetKey( assetInfo.getKey() );
+        return result;
+    }
+
+}