mirror of https://github.com/axmolengine/axmol.git
SimpleAudioEngine:Fixed thread safety problem on android.
This commit is contained in:
parent
a364d6ecfc
commit
6fec9c40b0
|
@ -29,15 +29,14 @@ import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.concurrent.Semaphore;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
import com.chukong.cocosplay.client.CocosPlayClient;
|
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.media.AudioManager;
|
import android.media.AudioManager;
|
||||||
import android.media.SoundPool;
|
import android.media.SoundPool;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.chukong.cocosplay.client.CocosPlayClient;
|
||||||
|
|
||||||
public class Cocos2dxSound {
|
public class Cocos2dxSound {
|
||||||
// ===========================================================
|
// ===========================================================
|
||||||
// Constants
|
// Constants
|
||||||
|
@ -61,10 +60,8 @@ public class Cocos2dxSound {
|
||||||
|
|
||||||
private final HashMap<String, Integer> mPathSoundIDMap = new HashMap<String, Integer>();
|
private final HashMap<String, Integer> mPathSoundIDMap = new HashMap<String, Integer>();
|
||||||
|
|
||||||
private final ArrayList<SoundInfoForLoadedCompleted> mEffecToPlayWhenLoadedArray = new ArrayList<SoundInfoForLoadedCompleted>();
|
private ConcurrentHashMap<Integer, SoundInfoForLoadedCompleted> mPlayWhenLoadedEffects =
|
||||||
|
new ConcurrentHashMap<Integer, SoundInfoForLoadedCompleted>();
|
||||||
private int mStreamIdSyn;
|
|
||||||
private Semaphore mSemaphore;
|
|
||||||
|
|
||||||
private static final int MAX_SIMULTANEOUS_STREAMS_DEFAULT = 5;
|
private static final int MAX_SIMULTANEOUS_STREAMS_DEFAULT = 5;
|
||||||
private static final int MAX_SIMULTANEOUS_STREAMS_I9100 = 3;
|
private static final int MAX_SIMULTANEOUS_STREAMS_I9100 = 3;
|
||||||
|
@ -86,7 +83,7 @@ public class Cocos2dxSound {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initData() {
|
private void initData() {
|
||||||
if (Cocos2dxHelper.getDeviceModel().indexOf("GT-I9100") != -1) {
|
if (Cocos2dxHelper.getDeviceModel().contains("GT-I9100")) {
|
||||||
this.mSoundPool = new SoundPool(Cocos2dxSound.MAX_SIMULTANEOUS_STREAMS_I9100, AudioManager.STREAM_MUSIC, Cocos2dxSound.SOUND_QUALITY);
|
this.mSoundPool = new SoundPool(Cocos2dxSound.MAX_SIMULTANEOUS_STREAMS_I9100, AudioManager.STREAM_MUSIC, Cocos2dxSound.SOUND_QUALITY);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -97,22 +94,8 @@ public class Cocos2dxSound {
|
||||||
|
|
||||||
this.mLeftVolume = 0.5f;
|
this.mLeftVolume = 0.5f;
|
||||||
this.mRightVolume = 0.5f;
|
this.mRightVolume = 0.5f;
|
||||||
|
|
||||||
this.mSemaphore = new Semaphore(0, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===========================================================
|
|
||||||
// Getter & Setter
|
|
||||||
// ===========================================================
|
|
||||||
|
|
||||||
// ===========================================================
|
|
||||||
// Methods for/from SuperClass/Interfaces
|
|
||||||
// ===========================================================
|
|
||||||
|
|
||||||
// ===========================================================
|
|
||||||
// Methods
|
|
||||||
// ===========================================================
|
|
||||||
|
|
||||||
public int preloadEffect(final String path) {
|
public int preloadEffect(final String path) {
|
||||||
if (CocosPlayClient.isEnabled() && !CocosPlayClient.isDemo()) {
|
if (CocosPlayClient.isEnabled() && !CocosPlayClient.isDemo()) {
|
||||||
CocosPlayClient.updateAssets(path);
|
CocosPlayClient.updateAssets(path);
|
||||||
|
@ -149,6 +132,8 @@ public class Cocos2dxSound {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static int LOAD_TIME_OUT = 500;
|
||||||
|
|
||||||
public int playEffect(final String path, final boolean loop, float pitch, float pan, float gain){
|
public int playEffect(final String path, final boolean loop, float pitch, float pan, float gain){
|
||||||
Integer soundID = this.mPathSoundIDMap.get(path);
|
Integer soundID = this.mPathSoundIDMap.get(path);
|
||||||
int streamID = Cocos2dxSound.INVALID_STREAM_ID;
|
int streamID = Cocos2dxSound.INVALID_STREAM_ID;
|
||||||
|
@ -157,7 +142,7 @@ public class Cocos2dxSound {
|
||||||
// parameters; pan = -1 for left channel, 1 for right channel, 0 for both channels
|
// parameters; pan = -1 for left channel, 1 for right channel, 0 for both channels
|
||||||
|
|
||||||
// play sound
|
// play sound
|
||||||
streamID = this.doPlayEffect(path, soundID.intValue(), loop, pitch, pan, gain);
|
streamID = this.doPlayEffect(path, soundID, loop, pitch, pan, gain);
|
||||||
} else {
|
} else {
|
||||||
// the effect is not prepared
|
// the effect is not prepared
|
||||||
soundID = this.preloadEffect(path);
|
soundID = this.preloadEffect(path);
|
||||||
|
@ -166,21 +151,19 @@ public class Cocos2dxSound {
|
||||||
return Cocos2dxSound.INVALID_SOUND_ID;
|
return Cocos2dxSound.INVALID_SOUND_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
// only allow one playEffect at a time, or the semaphore will not work correctly
|
SoundInfoForLoadedCompleted info = new SoundInfoForLoadedCompleted(path, loop, pitch, pan, gain);
|
||||||
synchronized(this.mSoundPool) {
|
mPlayWhenLoadedEffects.putIfAbsent(soundID, info);
|
||||||
// add this effect into mEffecToPlayWhenLoadedArray, and it will be played when loaded completely
|
|
||||||
mEffecToPlayWhenLoadedArray.add(new SoundInfoForLoadedCompleted(path, soundID.intValue(), loop,
|
|
||||||
pitch, pan, gain));
|
|
||||||
|
|
||||||
|
synchronized(info) {
|
||||||
try {
|
try {
|
||||||
// wait OnloadedCompleteListener to set streamID
|
info.wait(LOAD_TIME_OUT);
|
||||||
this.mSemaphore.acquire();
|
}
|
||||||
|
catch (Exception e) {
|
||||||
streamID = this.mStreamIdSyn;
|
e.printStackTrace();
|
||||||
} catch(Exception e) {
|
|
||||||
return Cocos2dxSound.INVALID_SOUND_ID;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
streamID = info.effectID;
|
||||||
|
mPlayWhenLoadedEffects.remove(soundID);
|
||||||
}
|
}
|
||||||
|
|
||||||
return streamID;
|
return streamID;
|
||||||
|
@ -280,7 +263,7 @@ public class Cocos2dxSound {
|
||||||
this.mSoundPool.release();
|
this.mSoundPool.release();
|
||||||
this.mPathStreamIDsMap.clear();
|
this.mPathStreamIDsMap.clear();
|
||||||
this.mPathSoundIDMap.clear();
|
this.mPathSoundIDMap.clear();
|
||||||
this.mEffecToPlayWhenLoadedArray.clear();
|
this.mPlayWhenLoadedEffects.clear();
|
||||||
|
|
||||||
this.mLeftVolume = 0.5f;
|
this.mLeftVolume = 0.5f;
|
||||||
this.mRightVolume = 0.5f;
|
this.mRightVolume = 0.5f;
|
||||||
|
@ -346,21 +329,20 @@ public class Cocos2dxSound {
|
||||||
// ===========================================================
|
// ===========================================================
|
||||||
|
|
||||||
public class SoundInfoForLoadedCompleted {
|
public class SoundInfoForLoadedCompleted {
|
||||||
public int soundID;
|
|
||||||
public boolean isLoop;
|
public boolean isLoop;
|
||||||
public float pitch;
|
public float pitch;
|
||||||
public float pan;
|
public float pan;
|
||||||
public float gain;
|
public float gain;
|
||||||
public String path;
|
public String path;
|
||||||
|
public int effectID;
|
||||||
|
|
||||||
public SoundInfoForLoadedCompleted(String path, int soundId, boolean isLoop,
|
public SoundInfoForLoadedCompleted(String path, boolean isLoop, float pitch, float pan, float gain) {
|
||||||
float pitch, float pan, float gain) {
|
|
||||||
this.path = path;
|
this.path = path;
|
||||||
this.soundID = soundId;
|
|
||||||
this.isLoop = isLoop;
|
this.isLoop = isLoop;
|
||||||
this.pitch = pitch;
|
this.pitch = pitch;
|
||||||
this.pan = pan;
|
this.pan = pan;
|
||||||
this.gain = gain;
|
this.gain = gain;
|
||||||
|
effectID = Cocos2dxSound.INVALID_SOUND_ID;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -370,26 +352,14 @@ public class Cocos2dxSound {
|
||||||
public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
|
public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
|
||||||
if (status == 0)
|
if (status == 0)
|
||||||
{
|
{
|
||||||
// only play effect that are in mEffecToPlayWhenLoadedArray
|
SoundInfoForLoadedCompleted info = mPlayWhenLoadedEffects.get(sampleId);
|
||||||
for ( SoundInfoForLoadedCompleted info : mEffecToPlayWhenLoadedArray) {
|
if (info != null) {
|
||||||
if (sampleId == info.soundID) {
|
info.effectID = doPlayEffect(info.path, sampleId, info.isLoop, info.pitch, info.pan, info.gain);
|
||||||
// set the stream id which will be returned by playEffect()
|
synchronized (info) {
|
||||||
mStreamIdSyn = doPlayEffect(info.path, info.soundID, info.isLoop, info.pitch, info.pan, info.gain);
|
info.notifyAll();
|
||||||
|
}
|
||||||
/*
|
}
|
||||||
* Remove it from array, because we will break here.
|
}
|
||||||
* So it is safe to do.
|
|
||||||
*/
|
|
||||||
mEffecToPlayWhenLoadedArray.remove(info);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
mStreamIdSyn = Cocos2dxSound.INVALID_SOUND_ID;
|
|
||||||
}
|
|
||||||
|
|
||||||
mSemaphore.release();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue