- Pause audio when jME3 app is paused - Add WAV to supported formats - Add Android audio test * Minor javadoc fixes in AndroidHarness * Made jme3tools.android.Fixed class deprecated git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@9152 75d07b2b-3a1a-0410-a2c5-0572b91ccdca3.0
parent
4721c944a2
commit
b89b2428af
@ -1,115 +1,115 @@ |
|||||||
/* |
/* |
||||||
* Copyright (c) 2009-2010 jMonkeyEngine |
* Copyright (c) 2009-2010 jMonkeyEngine |
||||||
* All rights reserved. |
* All rights reserved. |
||||||
* |
* |
||||||
* Redistribution and use in source and binary forms, with or without |
* Redistribution and use in source and binary forms, with or without |
||||||
* modification, are permitted provided that the following conditions are |
* modification, are permitted provided that the following conditions are |
||||||
* met: |
* met: |
||||||
* |
* |
||||||
* * Redistributions of source code must retain the above copyright |
* * Redistributions of source code must retain the above copyright |
||||||
* notice, this list of conditions and the following disclaimer. |
* notice, this list of conditions and the following disclaimer. |
||||||
* |
* |
||||||
* * Redistributions in binary form must reproduce the above copyright |
* * Redistributions in binary form must reproduce the above copyright |
||||||
* notice, this list of conditions and the following disclaimer in the |
* notice, this list of conditions and the following disclaimer in the |
||||||
* documentation and/or other materials provided with the distribution. |
* documentation and/or other materials provided with the distribution. |
||||||
* |
* |
||||||
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors |
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors |
||||||
* may be used to endorse or promote products derived from this software |
* may be used to endorse or promote products derived from this software |
||||||
* without specific prior written permission. |
* without specific prior written permission. |
||||||
* |
* |
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
||||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
||||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
||||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
||||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
||||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
||||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
||||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
*/ |
*/ |
||||||
package com.jme3.asset; |
package com.jme3.asset; |
||||||
|
|
||||||
import com.jme3.asset.plugins.AndroidLocator; |
import com.jme3.asset.plugins.AndroidLocator; |
||||||
import com.jme3.asset.plugins.ClasspathLocator; |
import com.jme3.asset.plugins.ClasspathLocator; |
||||||
import com.jme3.audio.plugins.AndroidAudioLoader; |
import com.jme3.audio.plugins.AndroidAudioLoader; |
||||||
import com.jme3.texture.Texture; |
import com.jme3.texture.Texture; |
||||||
import com.jme3.texture.plugins.AndroidImageLoader; |
import com.jme3.texture.plugins.AndroidImageLoader; |
||||||
import java.net.URL; |
import java.net.URL; |
||||||
import java.util.logging.Logger; |
import java.util.logging.Logger; |
||||||
|
|
||||||
/** |
/** |
||||||
* <code>AndroidAssetManager</code> is an implementation of DesktopAssetManager for Android |
* <code>AndroidAssetManager</code> is an implementation of DesktopAssetManager for Android |
||||||
* |
* |
||||||
* @author larynx |
* @author larynx |
||||||
*/ |
*/ |
||||||
public class AndroidAssetManager extends DesktopAssetManager { |
public class AndroidAssetManager extends DesktopAssetManager { |
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(AndroidAssetManager.class.getName()); |
private static final Logger logger = Logger.getLogger(AndroidAssetManager.class.getName()); |
||||||
|
|
||||||
public AndroidAssetManager() { |
public AndroidAssetManager() { |
||||||
this(null); |
this(null); |
||||||
} |
} |
||||||
|
|
||||||
@Deprecated |
@Deprecated |
||||||
public AndroidAssetManager(boolean loadDefaults) { |
public AndroidAssetManager(boolean loadDefaults) { |
||||||
//this(Thread.currentThread().getContextClassLoader().getResource("com/jme3/asset/Android.cfg"));
|
//this(Thread.currentThread().getContextClassLoader().getResource("com/jme3/asset/Android.cfg"));
|
||||||
this(null); |
this(null); |
||||||
} |
} |
||||||
|
|
||||||
/** |
/** |
||||||
* AndroidAssetManager constructor |
* AndroidAssetManager constructor |
||||||
* If URL == null then a default list of locators and loaders for android is set |
* If URL == null then a default list of locators and loaders for android is set |
||||||
* @param configFile |
* @param configFile |
||||||
*/ |
*/ |
||||||
public AndroidAssetManager(URL configFile) { |
public AndroidAssetManager(URL configFile) { |
||||||
System.setProperty("org.xml.sax.driver", "org.xmlpull.v1.sax2.Driver"); |
System.setProperty("org.xml.sax.driver", "org.xmlpull.v1.sax2.Driver"); |
||||||
|
|
||||||
// Set Default Android config
|
// Set Default Android config
|
||||||
this.registerLocator("", AndroidLocator.class); |
this.registerLocator("", AndroidLocator.class); |
||||||
this.registerLocator("", ClasspathLocator.class); |
this.registerLocator("", ClasspathLocator.class); |
||||||
this.registerLoader(AndroidImageLoader.class, "jpg", "bmp", "gif", "png", "jpeg"); |
this.registerLoader(AndroidImageLoader.class, "jpg", "bmp", "gif", "png", "jpeg"); |
||||||
this.registerLoader(AndroidAudioLoader.class, "ogg", "mp3"); |
this.registerLoader(AndroidAudioLoader.class, "ogg", "mp3", "wav"); |
||||||
this.registerLoader(com.jme3.material.plugins.J3MLoader.class, "j3m"); |
this.registerLoader(com.jme3.material.plugins.J3MLoader.class, "j3m"); |
||||||
this.registerLoader(com.jme3.material.plugins.J3MLoader.class, "j3md"); |
this.registerLoader(com.jme3.material.plugins.J3MLoader.class, "j3md"); |
||||||
this.registerLoader(com.jme3.font.plugins.BitmapFontLoader.class, "fnt"); |
this.registerLoader(com.jme3.font.plugins.BitmapFontLoader.class, "fnt"); |
||||||
this.registerLoader(com.jme3.texture.plugins.DDSLoader.class, "dds"); |
this.registerLoader(com.jme3.texture.plugins.DDSLoader.class, "dds"); |
||||||
this.registerLoader(com.jme3.texture.plugins.PFMLoader.class, "pfm"); |
this.registerLoader(com.jme3.texture.plugins.PFMLoader.class, "pfm"); |
||||||
this.registerLoader(com.jme3.texture.plugins.HDRLoader.class, "hdr"); |
this.registerLoader(com.jme3.texture.plugins.HDRLoader.class, "hdr"); |
||||||
this.registerLoader(com.jme3.texture.plugins.TGALoader.class, "tga"); |
this.registerLoader(com.jme3.texture.plugins.TGALoader.class, "tga"); |
||||||
this.registerLoader(com.jme3.export.binary.BinaryImporter.class, "j3o"); |
this.registerLoader(com.jme3.export.binary.BinaryImporter.class, "j3o"); |
||||||
this.registerLoader(com.jme3.scene.plugins.OBJLoader.class, "obj"); |
this.registerLoader(com.jme3.scene.plugins.OBJLoader.class, "obj"); |
||||||
this.registerLoader(com.jme3.scene.plugins.MTLLoader.class, "mtl"); |
this.registerLoader(com.jme3.scene.plugins.MTLLoader.class, "mtl"); |
||||||
this.registerLoader(com.jme3.scene.plugins.ogre.MeshLoader.class, "meshxml", "mesh.xml"); |
this.registerLoader(com.jme3.scene.plugins.ogre.MeshLoader.class, "meshxml", "mesh.xml"); |
||||||
this.registerLoader(com.jme3.scene.plugins.ogre.SkeletonLoader.class, "skeletonxml", "skeleton.xml"); |
this.registerLoader(com.jme3.scene.plugins.ogre.SkeletonLoader.class, "skeletonxml", "skeleton.xml"); |
||||||
this.registerLoader(com.jme3.scene.plugins.ogre.MaterialLoader.class, "material"); |
this.registerLoader(com.jme3.scene.plugins.ogre.MaterialLoader.class, "material"); |
||||||
this.registerLoader(com.jme3.scene.plugins.ogre.SceneLoader.class, "scene"); |
this.registerLoader(com.jme3.scene.plugins.ogre.SceneLoader.class, "scene"); |
||||||
this.registerLoader(com.jme3.shader.plugins.GLSLLoader.class, "vert", "frag", "glsl", "glsllib"); |
this.registerLoader(com.jme3.shader.plugins.GLSLLoader.class, "vert", "frag", "glsl", "glsllib"); |
||||||
|
|
||||||
logger.info("AndroidAssetManager created."); |
logger.info("AndroidAssetManager created."); |
||||||
} |
} |
||||||
|
|
||||||
/** |
/** |
||||||
* Loads a texture. |
* Loads a texture. |
||||||
* |
* |
||||||
* @return |
* @return |
||||||
*/ |
*/ |
||||||
@Override |
@Override |
||||||
public Texture loadTexture(TextureKey key) { |
public Texture loadTexture(TextureKey key) { |
||||||
Texture tex = (Texture) loadAsset(key); |
Texture tex = (Texture) loadAsset(key); |
||||||
|
|
||||||
// XXX: This will improve performance on some really
|
// XXX: This will improve performance on some really
|
||||||
// low end GPUs (e.g. ones with OpenGL ES 1 support only)
|
// low end GPUs (e.g. ones with OpenGL ES 1 support only)
|
||||||
// but otherwise won't help on the higher ones.
|
// but otherwise won't help on the higher ones.
|
||||||
// Strongly consider removing this.
|
// Strongly consider removing this.
|
||||||
tex.setMagFilter(Texture.MagFilter.Nearest); |
tex.setMagFilter(Texture.MagFilter.Nearest); |
||||||
tex.setAnisotropicFilter(0); |
tex.setAnisotropicFilter(0); |
||||||
if (tex.getMinFilter().usesMipMapLevels()) { |
if (tex.getMinFilter().usesMipMapLevels()) { |
||||||
tex.setMinFilter(Texture.MinFilter.NearestNearestMipMap); |
tex.setMinFilter(Texture.MinFilter.NearestNearestMipMap); |
||||||
} else { |
} else { |
||||||
tex.setMinFilter(Texture.MinFilter.NearestNoMipMaps); |
tex.setMinFilter(Texture.MinFilter.NearestNoMipMaps); |
||||||
} |
} |
||||||
return tex; |
return tex; |
||||||
} |
} |
||||||
} |
} |
||||||
|
@ -1,478 +1,499 @@ |
|||||||
/* |
/* |
||||||
* Copyright (c) 2009-2010 jMonkeyEngine |
* Copyright (c) 2009-2010 jMonkeyEngine |
||||||
* All rights reserved. |
* All rights reserved. |
||||||
* |
* |
||||||
* Redistribution and use in source and binary forms, with or without |
* Redistribution and use in source and binary forms, with or without |
||||||
* modification, are permitted provided that the following conditions are |
* modification, are permitted provided that the following conditions are |
||||||
* met: |
* met: |
||||||
* |
* |
||||||
* * Redistributions of source code must retain the above copyright |
* * Redistributions of source code must retain the above copyright |
||||||
* notice, this list of conditions and the following disclaimer. |
* notice, this list of conditions and the following disclaimer. |
||||||
* |
* |
||||||
* * Redistributions in binary form must reproduce the above copyright |
* * Redistributions in binary form must reproduce the above copyright |
||||||
* notice, this list of conditions and the following disclaimer in the |
* notice, this list of conditions and the following disclaimer in the |
||||||
* documentation and/or other materials provided with the distribution. |
* documentation and/or other materials provided with the distribution. |
||||||
* |
* |
||||||
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors |
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors |
||||||
* may be used to endorse or promote products derived from this software |
* may be used to endorse or promote products derived from this software |
||||||
* without specific prior written permission. |
* without specific prior written permission. |
||||||
* |
* |
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
||||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
||||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
||||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
||||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
||||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
||||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
||||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
*/ |
*/ |
||||||
package com.jme3.audio.android; |
package com.jme3.audio.android; |
||||||
|
|
||||||
import android.app.Activity; |
import android.app.Activity; |
||||||
import android.content.Context; |
import android.content.Context; |
||||||
import android.content.res.AssetFileDescriptor; |
import android.content.res.AssetFileDescriptor; |
||||||
import android.content.res.AssetManager; |
import android.content.res.AssetManager; |
||||||
import android.media.AudioManager; |
import android.media.AudioManager; |
||||||
import android.media.MediaPlayer; |
import android.media.MediaPlayer; |
||||||
import android.media.SoundPool; |
import android.media.SoundPool; |
||||||
import android.util.Log; |
import android.util.Log; |
||||||
|
|
||||||
import com.jme3.asset.AssetKey; |
import com.jme3.asset.AssetKey; |
||||||
import com.jme3.audio.AudioNode.Status; |
import com.jme3.audio.AudioNode.Status; |
||||||
import com.jme3.audio.*; |
import com.jme3.audio.*; |
||||||
import com.jme3.math.FastMath; |
import com.jme3.math.FastMath; |
||||||
import com.jme3.math.Vector3f; |
import com.jme3.math.Vector3f; |
||||||
import java.io.IOException; |
import java.io.IOException; |
||||||
import java.util.HashMap; |
import java.util.HashMap; |
||||||
import java.util.concurrent.atomic.AtomicBoolean; |
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 |
||||||
* @author plan_rich |
* @author plan_rich |
||||||
*/ |
*/ |
||||||
public class AndroidAudioRenderer implements AudioRenderer, |
public class AndroidAudioRenderer implements AudioRenderer, |
||||||
SoundPool.OnLoadCompleteListener, MediaPlayer.OnCompletionListener { |
SoundPool.OnLoadCompleteListener, MediaPlayer.OnCompletionListener { |
||||||
|
|
||||||
private static final Logger logger = Logger |
private static final Logger logger = Logger |
||||||
.getLogger(AndroidAudioRenderer.class.getName()); |
.getLogger(AndroidAudioRenderer.class.getName()); |
||||||
private final static int MAX_NUM_CHANNELS = 16; |
private final static int MAX_NUM_CHANNELS = 16; |
||||||
private final HashMap<AudioNode, MediaPlayer> musicPlaying = new HashMap<AudioNode, MediaPlayer>(); |
private final HashMap<AudioNode, MediaPlayer> musicPlaying = new HashMap<AudioNode, MediaPlayer>(); |
||||||
private SoundPool soundPool = null; |
private SoundPool soundPool = null; |
||||||
|
|
||||||
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 Context context; |
private final Context context; |
||||||
private final AssetManager assetManager; |
private final AssetManager assetManager; |
||||||
private HashMap<Integer, AudioNode> soundpoolStillLoading = new HashMap<Integer, AudioNode>(); |
private HashMap<Integer, AudioNode> soundpoolStillLoading = new HashMap<Integer, AudioNode>(); |
||||||
private Listener listener; |
private Listener listener; |
||||||
private boolean audioDisabled = false; |
private boolean audioDisabled = false; |
||||||
|
|
||||||
private final AudioManager manager; |
private final AudioManager manager; |
||||||
|
|
||||||
public AndroidAudioRenderer(Activity context) { |
public AndroidAudioRenderer(Activity context) { |
||||||
this.context = context; |
this.context = context; |
||||||
manager = (AudioManager) context |
manager = (AudioManager) context |
||||||
.getSystemService(Context.AUDIO_SERVICE); |
.getSystemService(Context.AUDIO_SERVICE); |
||||||
context.setVolumeControlStream(AudioManager.STREAM_MUSIC); |
context.setVolumeControlStream(AudioManager.STREAM_MUSIC); |
||||||
assetManager = context.getAssets(); |
assetManager = context.getAssets(); |
||||||
} |
} |
||||||
|
|
||||||
@Override |
@Override |
||||||
public void initialize() { |
public void initialize() { |
||||||
soundPool = new SoundPool(MAX_NUM_CHANNELS, AudioManager.STREAM_MUSIC, |
soundPool = new SoundPool(MAX_NUM_CHANNELS, AudioManager.STREAM_MUSIC, |
||||||
0); |
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) { |
if (audioDisabled) { |
||||||
return; |
return; |
||||||
} |
} |
||||||
|
|
||||||
if (src.getChannel() < 0) { |
if (src.getChannel() < 0) { |
||||||
return; |
return; |
||||||
} |
} |
||||||
|
|
||||||
switch (param) { |
switch (param) { |
||||||
case Position: |
case Position: |
||||||
if (!src.isPositional()) { |
if (!src.isPositional()) { |
||||||
return; |
return; |
||||||
} |
} |
||||||
|
|
||||||
Vector3f pos = src.getWorldTranslation(); |
Vector3f pos = src.getWorldTranslation(); |
||||||
break; |
break; |
||||||
case Velocity: |
case Velocity: |
||||||
if (!src.isPositional()) { |
if (!src.isPositional()) { |
||||||
return; |
return; |
||||||
} |
} |
||||||
|
|
||||||
Vector3f vel = src.getVelocity(); |
Vector3f vel = src.getVelocity(); |
||||||
break; |
break; |
||||||
case MaxDistance: |
case MaxDistance: |
||||||
if (!src.isPositional()) { |
if (!src.isPositional()) { |
||||||
return; |
return; |
||||||
} |
} |
||||||
break; |
break; |
||||||
case RefDistance: |
case RefDistance: |
||||||
if (!src.isPositional()) { |
if (!src.isPositional()) { |
||||||
return; |
return; |
||||||
} |
} |
||||||
break; |
break; |
||||||
case ReverbFilter: |
case ReverbFilter: |
||||||
if (!src.isPositional() || !src.isReverbEnabled()) { |
if (!src.isPositional() || !src.isReverbEnabled()) { |
||||||
return; |
return; |
||||||
} |
} |
||||||
break; |
break; |
||||||
case ReverbEnabled: |
case ReverbEnabled: |
||||||
if (!src.isPositional()) { |
if (!src.isPositional()) { |
||||||
return; |
return; |
||||||
} |
} |
||||||
|
|
||||||
if (src.isReverbEnabled()) { |
if (src.isReverbEnabled()) { |
||||||
updateSourceParam(src, AudioParam.ReverbFilter); |
updateSourceParam(src, AudioParam.ReverbFilter); |
||||||
} |
} |
||||||
break; |
break; |
||||||
case IsPositional: |
case IsPositional: |
||||||
break; |
break; |
||||||
case Direction: |
case Direction: |
||||||
if (!src.isDirectional()) { |
if (!src.isDirectional()) { |
||||||
return; |
return; |
||||||
} |
} |
||||||
|
|
||||||
Vector3f dir = src.getDirection(); |
Vector3f dir = src.getDirection(); |
||||||
break; |
break; |
||||||
case InnerAngle: |
case InnerAngle: |
||||||
if (!src.isDirectional()) { |
if (!src.isDirectional()) { |
||||||
return; |
return; |
||||||
} |
} |
||||||
break; |
break; |
||||||
case OuterAngle: |
case OuterAngle: |
||||||
if (!src.isDirectional()) { |
if (!src.isDirectional()) { |
||||||
return; |
return; |
||||||
} |
} |
||||||
break; |
break; |
||||||
case IsDirectional: |
case IsDirectional: |
||||||
if (src.isDirectional()) { |
if (src.isDirectional()) { |
||||||
updateSourceParam(src, AudioParam.Direction); |
updateSourceParam(src, AudioParam.Direction); |
||||||
updateSourceParam(src, AudioParam.InnerAngle); |
updateSourceParam(src, AudioParam.InnerAngle); |
||||||
updateSourceParam(src, AudioParam.OuterAngle); |
updateSourceParam(src, AudioParam.OuterAngle); |
||||||
} else { |
} else { |
||||||
} |
} |
||||||
break; |
break; |
||||||
case DryFilter: |
case DryFilter: |
||||||
if (src.getDryFilter() != null) { |
if (src.getDryFilter() != null) { |
||||||
Filter f = src.getDryFilter(); |
Filter f = src.getDryFilter(); |
||||||
if (f.isUpdateNeeded()) { |
if (f.isUpdateNeeded()) { |
||||||
// updateFilter(f);
|
// updateFilter(f);
|
||||||
} |
} |
||||||
} |
} |
||||||
break; |
break; |
||||||
case Looping: |
case Looping: |
||||||
if (src.isLooping()) { |
if (src.isLooping()) { |
||||||
} |
} |
||||||
break; |
break; |
||||||
case Volume: |
case Volume: |
||||||
|
|
||||||
soundPool.setVolume(src.getChannel(), src.getVolume(), |
soundPool.setVolume(src.getChannel(), src.getVolume(), |
||||||
src.getVolume()); |
src.getVolume()); |
||||||
|
|
||||||
break; |
break; |
||||||
case Pitch: |
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: |
||||||
Vector3f vel = listener.getVelocity(); |
Vector3f vel = listener.getVelocity(); |
||||||
|
|
||||||
break; |
break; |
||||||
case Volume: |
case Volume: |
||||||
// alListenerf(AL_GAIN, listener.getVolume());
|
// alListenerf(AL_GAIN, listener.getVolume());
|
||||||
break; |
break; |
||||||
} |
} |
||||||
|
|
||||||
} |
} |
||||||
|
|
||||||
@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()) { |
if (distance > src.getMaxDistance()) { |
||||||
distance = src.getMaxDistance(); |
distance = src.getMaxDistance(); |
||||||
} |
} |
||||||
volume = src.getRefDistance() / distance; |
volume = src.getRefDistance() / distance; |
||||||
|
|
||||||
AndroidAudioData audioData = (AndroidAudioData) src |
AndroidAudioData audioData = (AndroidAudioData) src |
||||||
.getAudioData(); |
.getAudioData(); |
||||||
|
|
||||||
if (FastMath.abs(audioData.getCurrentVolume() - volume) > FastMath.FLT_EPSILON) { |
if (FastMath.abs(audioData.getCurrentVolume() - volume) > FastMath.FLT_EPSILON) { |
||||||
// Left / Right channel get the same volume by now, only
|
// Left / Right channel get the same volume by now, only
|
||||||
// positional
|
// positional
|
||||||
mp.setVolume(volume, volume); |
mp.setVolume(volume, volume); |
||||||
|
|
||||||
audioData.setCurrentVolume(volume); |
audioData.setCurrentVolume(volume); |
||||||
} |
} |
||||||
} |
} |
||||||
} |
} |
||||||
} |
} |
||||||
|
|
||||||
public void setListener(Listener listener) { |
public void setListener(Listener listener) { |
||||||
if (audioDisabled) { |
if (audioDisabled) { |
||||||
return; |
return; |
||||||
} |
} |
||||||
|
|
||||||
if (this.listener != null) { |
if (this.listener != null) { |
||||||
// previous listener no longer associated with current
|
// previous listener no longer associated with current
|
||||||
// renderer
|
// renderer
|
||||||
this.listener.setRenderer(null); |
this.listener.setRenderer(null); |
||||||
} |
} |
||||||
|
|
||||||
this.listener = listener; |
this.listener = listener; |
||||||
this.listener.setRenderer(this); |
this.listener.setRenderer(this); |
||||||
|
|
||||||
} |
} |
||||||
|
|
||||||
@Override |
@Override |
||||||
public void cleanup() { |
public void cleanup() { |
||||||
// Cleanup sound pool
|
// Cleanup sound pool
|
||||||
if (soundPool != null) { |
if (soundPool != null) { |
||||||
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) { |
public void onCompletion(MediaPlayer mp) { |
||||||
mp.seekTo(0); |
mp.seekTo(0); |
||||||
mp.stop(); |
mp.stop(); |
||||||
// XXX: This has bad performance -> maybe change overall structure of
|
// XXX: This has bad performance -> maybe change overall structure of
|
||||||
// mediaplayer in this audiorenderer?
|
// mediaplayer in this audiorenderer?
|
||||||
for (AudioNode src : musicPlaying.keySet()) { |
for (AudioNode src : musicPlaying.keySet()) { |
||||||
if (musicPlaying.get(src) == mp) { |
if (musicPlaying.get(src) == mp) { |
||||||
src.setStatus(Status.Stopped); |
src.setStatus(Status.Stopped); |
||||||
break; |
break; |
||||||
} |
} |
||||||
} |
} |
||||||
} |
} |
||||||
|
|
||||||
/** |
/** |
||||||
* Plays using the {@link SoundPool} of Android. Due to hard limitation of |
* 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 SoundPool: After playing more instances of the sound you only have |
||||||
* the channel of the last played instance. |
* the channel of the last played instance. |
||||||
* |
* |
||||||
* It is not possible to get information about the state of the soundpool of |
* 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 |
* a specific streamid, so removing is not possilbe -> noone knows when |
||||||
* sound finished. |
* sound finished. |
||||||
*/ |
*/ |
||||||
public void playSourceInstance(AudioNode src) { |
public void playSourceInstance(AudioNode src) { |
||||||
if (audioDisabled) { |
if (audioDisabled) { |
||||||
return; |
return; |
||||||
} |
} |
||||||
|
|
||||||
AndroidAudioData audioData = (AndroidAudioData) src.getAudioData(); |
AndroidAudioData audioData = (AndroidAudioData) src.getAudioData(); |
||||||
|
|
||||||
if (!(audioData.getAssetKey() instanceof AudioKey)) { |
if (!(audioData.getAssetKey() instanceof AudioKey)) { |
||||||
throw new IllegalArgumentException("Asset is not a AudioKey"); |
throw new IllegalArgumentException("Asset is not a AudioKey"); |
||||||
} |
} |
||||||
|
|
||||||
AudioKey assetKey = (AudioKey) audioData.getAssetKey(); |
AudioKey assetKey = (AudioKey) audioData.getAssetKey(); |
||||||
|
|
||||||
try { |
try { |
||||||
if (audioData.getId() < 0) { // found something to load
|
if (audioData.getId() < 0) { // found something to load
|
||||||
int soundId = soundPool.load( |
int soundId = soundPool.load( |
||||||
assetManager.openFd(assetKey.getName()), 1); |
assetManager.openFd(assetKey.getName()), 1); |
||||||
audioData.setId(soundId); |
audioData.setId(soundId); |
||||||
} |
} |
||||||
|
|
||||||
int channel = soundPool.play(audioData.getId(), 1f, 1f, 1, 0, 1f); |
int channel = soundPool.play(audioData.getId(), 1f, 1f, 1, 0, 1f); |
||||||
|
|
||||||
if (channel == 0) { |
if (channel == 0) { |
||||||
soundpoolStillLoading.put(audioData.getId(), src); |
soundpoolStillLoading.put(audioData.getId(), src); |
||||||
} else { |
} else { |
||||||
src.setChannel(channel); // receive a channel at the last
|
src.setChannel(channel); // receive a channel at the last
|
||||||
// playing at least
|
// playing at least
|
||||||
} |
} |
||||||
} catch (IOException e) { |
} catch (IOException e) { |
||||||
logger.log(Level.SEVERE, |
logger.log(Level.SEVERE, |
||||||
"Failed to load sound " + assetKey.getName(), e); |
"Failed to load sound " + assetKey.getName(), e); |
||||||
audioData.setId(-1); |
audioData.setId(-1); |
||||||
} |
} |
||||||
} |
} |
||||||
|
|
||||||
@Override |
@Override |
||||||
public void onLoadComplete(SoundPool soundPool, int sampleId, int status) { |
public void onLoadComplete(SoundPool soundPool, int sampleId, int status) { |
||||||
AudioNode src = soundpoolStillLoading.remove(sampleId); |
AudioNode src = soundpoolStillLoading.remove(sampleId); |
||||||
|
|
||||||
if (src == null) { |
if (src == null) { |
||||||
logger.warning("Something went terribly wrong! onLoadComplete" |
logger.warning("Something went terribly wrong! onLoadComplete" |
||||||
+ " had sampleId which was not in the HashMap of loading items"); |
+ " had sampleId which was not in the HashMap of loading items"); |
||||||
return; |
return; |
||||||
} |
} |
||||||
|
|
||||||
AudioData audioData = src.getAudioData(); |
AudioData audioData = src.getAudioData(); |
||||||
|
|
||||||
if (status == 0) // load was successfull
|
if (status == 0) // load was successfull
|
||||||
{ |
{ |
||||||
int channelIndex; |
int channelIndex; |
||||||
channelIndex = soundPool.play(audioData.getId(), 1f, 1f, 1, 0, 1f); |
channelIndex = soundPool.play(audioData.getId(), 1f, 1f, 1, 0, 1f); |
||||||
src.setChannel(channelIndex); |
src.setChannel(channelIndex); |
||||||
} |
} |
||||||
} |
} |
||||||
|
|
||||||
public void playSource(AudioNode src) { |
public void playSource(AudioNode src) { |
||||||
if (audioDisabled) { |
if (audioDisabled) { |
||||||
return; |
return; |
||||||
} |
} |
||||||
|
|
||||||
AndroidAudioData audioData = (AndroidAudioData) src.getAudioData(); |
AndroidAudioData audioData = (AndroidAudioData) src.getAudioData(); |
||||||
|
|
||||||
MediaPlayer mp = musicPlaying.get(src); |
MediaPlayer mp = musicPlaying.get(src); |
||||||
if (mp == null) { |
if (mp == null) { |
||||||
mp = new MediaPlayer(); |
mp = new MediaPlayer(); |
||||||
mp.setOnCompletionListener(this); |
mp.setOnCompletionListener(this); |
||||||
mp.setAudioStreamType(AudioManager.STREAM_MUSIC); |
mp.setAudioStreamType(AudioManager.STREAM_MUSIC); |
||||||
} |
} |
||||||
|
|
||||||
try { |
try { |
||||||
AssetKey<?> key = audioData.getAssetKey(); |
AssetKey<?> key = audioData.getAssetKey(); |
||||||
|
|
||||||
AssetFileDescriptor afd = assetManager.openFd(key.getName()); // assetKey.getName()
|
AssetFileDescriptor afd = assetManager.openFd(key.getName()); // assetKey.getName()
|
||||||
mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), |
mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), |
||||||
afd.getLength()); |
afd.getLength()); |
||||||
mp.prepare(); |
mp.prepare(); |
||||||
mp.setLooping(src.isLooping()); |
mp.setLooping(src.isLooping()); |
||||||
mp.start(); |
mp.start(); |
||||||
src.setChannel(0); |
src.setChannel(0); |
||||||
src.setStatus(Status.Playing); |
src.setStatus(Status.Playing); |
||||||
musicPlaying.put(src, mp); |
musicPlaying.put(src, mp); |
||||||
|
|
||||||
} catch (IllegalStateException e) { |
} catch (IllegalStateException e) { |
||||||
e.printStackTrace(); |
e.printStackTrace(); |
||||||
} catch (Exception e) { |
} catch (Exception e) { |
||||||
e.printStackTrace(); |
e.printStackTrace(); |
||||||
} |
} |
||||||
} |
} |
||||||
|
|
||||||
public void pauseSource(AudioNode src) { |
/** |
||||||
if (audioDisabled) { |
* Pause the current playing sounds. Both from the {@link SoundPool} and the |
||||||
return; |
* active {@link MediaPlayer}s |
||||||
} |
*/ |
||||||
|
public void pauseAll() { |
||||||
MediaPlayer mp = musicPlaying.get(src); |
soundPool.autoPause(); |
||||||
if (mp != null) { |
for (MediaPlayer mp : musicPlaying.values()) { |
||||||
mp.pause(); |
mp.pause(); |
||||||
src.setStatus(Status.Paused); |
} |
||||||
} else { |
} |
||||||
int channel = src.getChannel(); |
|
||||||
if (channel != -1) |
/** |
||||||
soundPool.pause(channel); // is not very likley to make
|
* Resume all paused sounds. |
||||||
// something useful :)
|
*/ |
||||||
} |
public void resumeAll() { |
||||||
} |
soundPool.autoResume(); |
||||||
|
for (MediaPlayer mp : musicPlaying.values()) { |
||||||
public void stopSource(AudioNode src) { |
mp.start(); //no resume -> api says call start to resume
|
||||||
if (audioDisabled) { |
} |
||||||
return; |
} |
||||||
} |
|
||||||
|
public void pauseSource(AudioNode src) { |
||||||
// can be stream or buffer -> so try to get mediaplayer
|
if (audioDisabled) { |
||||||
// if there is non try to stop soundpool
|
return; |
||||||
MediaPlayer mp = musicPlaying.get(src); |
} |
||||||
if (mp != null) { |
|
||||||
mp.stop(); |
MediaPlayer mp = musicPlaying.get(src); |
||||||
src.setStatus(Status.Paused); |
if (mp != null) { |
||||||
} else { |
mp.pause(); |
||||||
int channel = src.getChannel(); |
src.setStatus(Status.Paused); |
||||||
if (channel != -1) { |
} else { |
||||||
soundPool.pause(channel); // is not very likley to make
|
int channel = src.getChannel(); |
||||||
// something useful :)
|
if (channel != -1) |
||||||
} |
soundPool.pause(channel); // is not very likley to make
|
||||||
} |
// something useful :)
|
||||||
|
} |
||||||
} |
} |
||||||
|
|
||||||
@Override |
public void stopSource(AudioNode src) { |
||||||
public void deleteAudioData(AudioData ad) { |
if (audioDisabled) { |
||||||
|
return; |
||||||
for (AudioNode src : musicPlaying.keySet()) { |
} |
||||||
if (src.getAudioData() == ad) { |
|
||||||
MediaPlayer mp = musicPlaying.remove(src); |
// can be stream or buffer -> so try to get mediaplayer
|
||||||
mp.stop(); |
// if there is non try to stop soundpool
|
||||||
mp.release(); |
MediaPlayer mp = musicPlaying.get(src); |
||||||
src.setStatus(Status.Stopped); |
if (mp != null) { |
||||||
src.setChannel(-1); |
mp.stop(); |
||||||
ad.setId(-1); |
src.setStatus(Status.Paused); |
||||||
break; |
} else { |
||||||
} |
int channel = src.getChannel(); |
||||||
} |
if (channel != -1) { |
||||||
|
soundPool.pause(channel); // is not very likley to make
|
||||||
if (ad.getId() > 0) { |
// something useful :)
|
||||||
soundPool.unload(ad.getId()); |
} |
||||||
ad.setId(-1); |
} |
||||||
} |
|
||||||
} |
} |
||||||
|
|
||||||
@Override |
@Override |
||||||
public void setEnvironment(Environment env) { |
public void deleteAudioData(AudioData ad) { |
||||||
//not yet supported
|
|
||||||
} |
for (AudioNode src : musicPlaying.keySet()) { |
||||||
|
if (src.getAudioData() == ad) { |
||||||
@Override |
MediaPlayer mp = musicPlaying.remove(src); |
||||||
public void deleteFilter(Filter filter) { |
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) { |
||||||
|
} |
||||||
|
} |
||||||
|
@ -0,0 +1,40 @@ |
|||||||
|
package jme3test.android; |
||||||
|
|
||||||
|
import com.jme3.app.SimpleApplication; |
||||||
|
import com.jme3.audio.AudioNode; |
||||||
|
import com.jme3.input.MouseInput; |
||||||
|
import com.jme3.input.controls.InputListener; |
||||||
|
import com.jme3.input.controls.MouseButtonTrigger; |
||||||
|
import com.jme3.math.Vector3f; |
||||||
|
|
||||||
|
public class SimpleSoundTest extends SimpleApplication implements InputListener { |
||||||
|
|
||||||
|
private AudioNode gun; |
||||||
|
private AudioNode nature; |
||||||
|
|
||||||
|
@Override |
||||||
|
public void simpleInitApp() { |
||||||
|
gun = new AudioNode(assetManager, "Sound/Effects/Gun.wav"); |
||||||
|
gun.setPositional(true); |
||||||
|
gun.setLocalTranslation(new Vector3f(0, 0, 0)); |
||||||
|
gun.setMaxDistance(100); |
||||||
|
gun.setRefDistance(5); |
||||||
|
|
||||||
|
nature = new AudioNode(assetManager, "Sound/Environment/Nature.ogg", true); |
||||||
|
nature.setVolume(3); |
||||||
|
nature.setLooping(true); |
||||||
|
nature.play(); |
||||||
|
|
||||||
|
inputManager.addMapping("click", new MouseButtonTrigger(MouseInput.BUTTON_LEFT)); |
||||||
|
inputManager.addListener(this, "click"); |
||||||
|
|
||||||
|
rootNode.attachChild(gun); |
||||||
|
rootNode.attachChild(nature); |
||||||
|
} |
||||||
|
|
||||||
|
public void onAction(String name, boolean isPressed, float tpf) { |
||||||
|
if (name.equals("click") && isPressed) { |
||||||
|
gun.playInstance(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue