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.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.Semaphore;
|
||||
|
||||
import com.chukong.cocosplay.client.CocosPlayClient;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import android.content.Context;
|
||||
import android.media.AudioManager;
|
||||
import android.media.SoundPool;
|
||||
import android.util.Log;
|
||||
|
||||
import com.chukong.cocosplay.client.CocosPlayClient;
|
||||
|
||||
public class Cocos2dxSound {
|
||||
// ===========================================================
|
||||
// Constants
|
||||
|
@ -61,10 +60,8 @@ public class Cocos2dxSound {
|
|||
|
||||
private final HashMap<String, Integer> mPathSoundIDMap = new HashMap<String, Integer>();
|
||||
|
||||
private final ArrayList<SoundInfoForLoadedCompleted> mEffecToPlayWhenLoadedArray = new ArrayList<SoundInfoForLoadedCompleted>();
|
||||
|
||||
private int mStreamIdSyn;
|
||||
private Semaphore mSemaphore;
|
||||
private ConcurrentHashMap<Integer, SoundInfoForLoadedCompleted> mPlayWhenLoadedEffects =
|
||||
new ConcurrentHashMap<Integer, SoundInfoForLoadedCompleted>();
|
||||
|
||||
private static final int MAX_SIMULTANEOUS_STREAMS_DEFAULT = 5;
|
||||
private static final int MAX_SIMULTANEOUS_STREAMS_I9100 = 3;
|
||||
|
@ -86,7 +83,7 @@ public class Cocos2dxSound {
|
|||
}
|
||||
|
||||
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);
|
||||
}
|
||||
else {
|
||||
|
@ -97,22 +94,8 @@ public class Cocos2dxSound {
|
|||
|
||||
this.mLeftVolume = 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) {
|
||||
if (CocosPlayClient.isEnabled() && !CocosPlayClient.isDemo()) {
|
||||
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){
|
||||
Integer soundID = this.mPathSoundIDMap.get(path);
|
||||
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
|
||||
|
||||
// play sound
|
||||
streamID = this.doPlayEffect(path, soundID.intValue(), loop, pitch, pan, gain);
|
||||
streamID = this.doPlayEffect(path, soundID, loop, pitch, pan, gain);
|
||||
} else {
|
||||
// the effect is not prepared
|
||||
soundID = this.preloadEffect(path);
|
||||
|
@ -166,21 +151,19 @@ public class Cocos2dxSound {
|
|||
return Cocos2dxSound.INVALID_SOUND_ID;
|
||||
}
|
||||
|
||||
// only allow one playEffect at a time, or the semaphore will not work correctly
|
||||
synchronized(this.mSoundPool) {
|
||||
// add this effect into mEffecToPlayWhenLoadedArray, and it will be played when loaded completely
|
||||
mEffecToPlayWhenLoadedArray.add(new SoundInfoForLoadedCompleted(path, soundID.intValue(), loop,
|
||||
pitch, pan, gain));
|
||||
SoundInfoForLoadedCompleted info = new SoundInfoForLoadedCompleted(path, loop, pitch, pan, gain);
|
||||
mPlayWhenLoadedEffects.putIfAbsent(soundID, info);
|
||||
|
||||
synchronized(info) {
|
||||
try {
|
||||
// wait OnloadedCompleteListener to set streamID
|
||||
this.mSemaphore.acquire();
|
||||
|
||||
streamID = this.mStreamIdSyn;
|
||||
} catch(Exception e) {
|
||||
return Cocos2dxSound.INVALID_SOUND_ID;
|
||||
info.wait(LOAD_TIME_OUT);
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
streamID = info.effectID;
|
||||
mPlayWhenLoadedEffects.remove(soundID);
|
||||
}
|
||||
|
||||
return streamID;
|
||||
|
@ -280,7 +263,7 @@ public class Cocos2dxSound {
|
|||
this.mSoundPool.release();
|
||||
this.mPathStreamIDsMap.clear();
|
||||
this.mPathSoundIDMap.clear();
|
||||
this.mEffecToPlayWhenLoadedArray.clear();
|
||||
this.mPlayWhenLoadedEffects.clear();
|
||||
|
||||
this.mLeftVolume = 0.5f;
|
||||
this.mRightVolume = 0.5f;
|
||||
|
@ -346,21 +329,20 @@ public class Cocos2dxSound {
|
|||
// ===========================================================
|
||||
|
||||
public class SoundInfoForLoadedCompleted {
|
||||
public int soundID;
|
||||
public boolean isLoop;
|
||||
public float pitch;
|
||||
public float pan;
|
||||
public float gain;
|
||||
public String path;
|
||||
public int effectID;
|
||||
|
||||
public SoundInfoForLoadedCompleted(String path, int soundId, boolean isLoop,
|
||||
float pitch, float pan, float gain) {
|
||||
public SoundInfoForLoadedCompleted(String path, boolean isLoop, float pitch, float pan, float gain) {
|
||||
this.path = path;
|
||||
this.soundID = soundId;
|
||||
this.isLoop = isLoop;
|
||||
this.pitch = pitch;
|
||||
this.pan = pan;
|
||||
this.gain = gain;
|
||||
effectID = Cocos2dxSound.INVALID_SOUND_ID;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -370,26 +352,14 @@ public class Cocos2dxSound {
|
|||
public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
|
||||
if (status == 0)
|
||||
{
|
||||
// only play effect that are in mEffecToPlayWhenLoadedArray
|
||||
for ( SoundInfoForLoadedCompleted info : mEffecToPlayWhenLoadedArray) {
|
||||
if (sampleId == info.soundID) {
|
||||
// set the stream id which will be returned by playEffect()
|
||||
mStreamIdSyn = doPlayEffect(info.path, info.soundID, info.isLoop, info.pitch, info.pan, info.gain);
|
||||
|
||||
/*
|
||||
* 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();
|
||||
SoundInfoForLoadedCompleted info = mPlayWhenLoadedEffects.get(sampleId);
|
||||
if (info != null) {
|
||||
info.effectID = doPlayEffect(info.path, sampleId, info.isLoop, info.pitch, info.pan, info.gain);
|
||||
synchronized (info) {
|
||||
info.notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue