Merge pull request #973 from minggo/iss1278_effect_android

fixed #1278: stop effect when unloading effect
This commit is contained in:
minggo 2012-06-06 00:41:26 -07:00
commit 6cf8ea283d
4 changed files with 312 additions and 364 deletions

View File

@ -23,6 +23,7 @@ THE SOFTWARE.
****************************************************************************/ ****************************************************************************/
package org.cocos2dx.lib; package org.cocos2dx.lib;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map; import java.util.Map;
@ -44,10 +45,12 @@ public class Cocos2dxSound {
private float mLeftVolume; private float mLeftVolume;
private float mRightVolume; private float mRightVolume;
// sound id and stream id map // sound path and stream ids map
private HashMap<Integer,Integer> mSoundIdStreamIdMap; // a file may be played many times at the same time
// sound path and sound id map // so there is an array map to a file path
private HashMap<String,Integer> mPathSoundIDMap; private HashMap<String,ArrayList<Integer>> mPathStreamIDsMap;
private HashMap<String, Integer> mPathSoundIdMap;
private static final String TAG = "Cocos2dxSound"; private static final String TAG = "Cocos2dxSound";
private static final int MAX_SIMULTANEOUS_STREAMS_DEFAULT = 5; private static final int MAX_SIMULTANEOUS_STREAMS_DEFAULT = 5;
@ -55,8 +58,8 @@ public class Cocos2dxSound {
private static final int SOUND_PRIORITY = 1; private static final int SOUND_PRIORITY = 1;
private static final int SOUND_QUALITY = 5; private static final int SOUND_QUALITY = 5;
private final int INVALID_SOUND_ID = -1; private final static int INVALID_SOUND_ID = -1;
private final int INVALID_STREAM_ID = -1; private final static int INVALID_STREAM_ID = -1;
public Cocos2dxSound(Context context){ public Cocos2dxSound(Context context){
this.mContext = context; this.mContext = context;
@ -64,53 +67,48 @@ public class Cocos2dxSound {
} }
public int preloadEffect(String path){ public int preloadEffect(String path){
int soundId = INVALID_SOUND_ID; Integer soundID = this.mPathSoundIdMap.get(path);
// if the sound is preloaded, pass it if (soundID == null) {
if (this.mPathSoundIDMap.get(path) != null){ soundID = createSoundIdFromAsset(path);
soundId = this.mPathSoundIDMap.get(path).intValue(); this.mPathSoundIdMap.put(path, soundID);
} else {
soundId = createSoundIdFromAsset(path);
if (soundId != INVALID_SOUND_ID){
// the sound is loaded but has not been played
this.mSoundIdStreamIdMap.put(soundId, INVALID_STREAM_ID);
// record path and sound id map
this.mPathSoundIDMap.put(path, soundId);
}
} }
return soundId; return soundID;
} }
public void unloadEffect(String path){ public void unloadEffect(String path){
// get sound id and remove from mPathSoundIDMap // stop effects
Integer soundId = this.mPathSoundIDMap.remove(path); ArrayList<Integer> streamIDs = this.mPathStreamIDsMap.get(path);
if (streamIDs != null) {
for (Integer streamID : streamIDs) {
this.mSoundPool.stop(streamID);
}
}
this.mPathStreamIDsMap.remove(path);
if (soundId != null){ // unload effect
// unload effect Integer soundID = this.mPathSoundIdMap.get(path);
this.mSoundPool.unload(soundId.intValue()); this.mSoundPool.unload(soundID);
this.mPathSoundIdMap.remove(path);
// remove record from mSoundIdStreamIdMap
this.mSoundIdStreamIdMap.remove(soundId);
}
} }
public int playEffect(String path, boolean isLoop){ public int playEffect(String path, boolean isLoop){
Integer soundId = this.mPathSoundIDMap.get(path); Integer soundId = this.mPathSoundIdMap.get(path);
int streamId = INVALID_STREAM_ID;
if (soundId != null){ if (soundId != null){
// the sound is preloaded, stop it first
this.mSoundPool.stop(soundId);
// play sound // play sound
int streamId = this.mSoundPool.play(soundId.intValue(), this.mLeftVolume, streamId = this.mSoundPool.play(soundId.intValue(), this.mLeftVolume,
this.mRightVolume, SOUND_PRIORITY, isLoop ? -1 : 0, SOUND_RATE); this.mRightVolume, SOUND_PRIORITY, isLoop ? -1 : 0, SOUND_RATE);
// record sound id and stream id map // record stream id
this.mSoundIdStreamIdMap.put(soundId, streamId); ArrayList<Integer> streamIds = this.mPathStreamIDsMap.get(path);
if (streamIds == null) {
streamIds = new ArrayList<Integer>();
this.mPathStreamIDsMap.put(path, streamIds);
}
streamIds.add(streamId);
} else { } else {
// the effect is not prepared // the effect is not prepared
soundId = preloadEffect(path); soundId = preloadEffect(path);
@ -133,54 +131,53 @@ public class Cocos2dxSound {
playEffect(path, isLoop); playEffect(path, isLoop);
} }
return soundId.intValue(); return streamId;
} }
public void stopEffect(int soundId){ public void stopEffect(int streamID){
Integer streamId = this.mSoundIdStreamIdMap.get(soundId); this.mSoundPool.stop(streamID);
if (streamId != null && streamId.intValue() != INVALID_STREAM_ID){ // remove record
this.mSoundPool.stop(streamId.intValue()); for (String path : this.mPathStreamIDsMap.keySet()) {
this.mPathSoundIDMap.remove(soundId); if (this.mPathStreamIDsMap.get(path).contains(streamID)) {
this.mPathStreamIDsMap.get(path).remove(this.mPathStreamIDsMap.get(path).indexOf(streamID));
break;
}
} }
} }
public void pauseEffect(int soundId){ public void pauseEffect(int streamID){
Integer streamId = this.mSoundIdStreamIdMap.get(soundId); this.mSoundPool.pause(streamID);
if (streamId != null && streamId.intValue() != INVALID_STREAM_ID){
this.mSoundPool.pause(streamId.intValue());
this.mPathSoundIDMap.remove(soundId);
}
} }
public void resumeEffect(int soundId){ public void resumeEffect(int streamID){
Integer streamId = this.mSoundIdStreamIdMap.get(soundId); this.mSoundPool.resume(streamID);
if (streamId != null && streamId.intValue() != INVALID_STREAM_ID){
this.mSoundPool.resume(streamId.intValue());
this.mPathSoundIDMap.remove(soundId);
}
} }
public void pauseAllEffects(){ public void pauseAllEffects(){
// autoResume is available since level 8 this.mSoundPool.autoPause();
pauseOrResumeAllEffects(true);
} }
public void resumeAllEffects(){ public void resumeAllEffects(){
// autoPause() is available since level 8 // autoPause() is available since level 8
pauseOrResumeAllEffects(false); this.mSoundPool.autoResume();
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public void stopAllEffects(){ public void stopAllEffects(){
Iterator<?> iter = this.mSoundIdStreamIdMap.entrySet().iterator(); // stop effects
while (iter.hasNext()){ if (! this.mPathStreamIDsMap.isEmpty()) {
Map.Entry<Integer, Integer> entry = (Map.Entry<Integer, Integer>)iter.next(); Iterator<?> iter = this.mPathStreamIDsMap.entrySet().iterator();
int soundId = entry.getKey(); while (iter.hasNext()){
this.stopEffect(soundId); Map.Entry<String, ArrayList<Integer>> entry = (Map.Entry<String, ArrayList<Integer>>)iter.next();
} for (int streamID : entry.getValue()) {
this.mSoundPool.stop(streamID);
}
}
}
// remove records
this.mPathStreamIDsMap.clear();
} }
public float getEffectsVolume(){ public float getEffectsVolume(){
@ -200,17 +197,21 @@ public class Cocos2dxSound {
this.mLeftVolume = this.mRightVolume = volume; this.mLeftVolume = this.mRightVolume = volume;
// change the volume of playing sounds // change the volume of playing sounds
Iterator<?> iter = this.mSoundIdStreamIdMap.entrySet().iterator(); if (! this.mPathStreamIDsMap.isEmpty()) {
while (iter.hasNext()){ Iterator<?> iter = this.mPathStreamIDsMap.entrySet().iterator();
Map.Entry<Integer, Integer> entry = (Map.Entry<Integer, Integer>)iter.next(); while (iter.hasNext()){
this.mSoundPool.setVolume(entry.getValue(), mLeftVolume, mRightVolume); Map.Entry<String, ArrayList<Integer>> entry = (Map.Entry<String, ArrayList<Integer>>)iter.next();
} for (int streamID : entry.getValue()) {
this.mSoundPool.setVolume(streamID, mLeftVolume, mRightVolume);
}
}
}
} }
public void end(){ public void end(){
this.mSoundPool.release(); this.mSoundPool.release();
this.mPathSoundIDMap.clear(); this.mPathStreamIDsMap.clear();
this.mSoundIdStreamIdMap.clear(); this.mPathSoundIdMap.clear();
initData(); initData();
} }
@ -234,25 +235,11 @@ public class Cocos2dxSound {
} }
private void initData(){ private void initData(){
this.mSoundIdStreamIdMap = new HashMap<Integer,Integer>(); this.mPathStreamIDsMap = new HashMap<String,ArrayList<Integer>>();
this.mPathSoundIdMap = new HashMap<String, Integer>();
mSoundPool = new SoundPool(MAX_SIMULTANEOUS_STREAMS_DEFAULT, AudioManager.STREAM_MUSIC, SOUND_QUALITY); mSoundPool = new SoundPool(MAX_SIMULTANEOUS_STREAMS_DEFAULT, AudioManager.STREAM_MUSIC, SOUND_QUALITY);
mPathSoundIDMap = new HashMap<String,Integer>();
this.mLeftVolume = 0.5f; this.mLeftVolume = 0.5f;
this.mRightVolume = 0.5f; this.mRightVolume = 0.5f;
} }
@SuppressWarnings("unchecked")
private void pauseOrResumeAllEffects(boolean isPause){
Iterator<?> iter = this.mSoundIdStreamIdMap.entrySet().iterator();
while (iter.hasNext()){
Map.Entry<Integer, Integer> entry = (Map.Entry<Integer, Integer>)iter.next();
int soundId = entry.getKey();
if (isPause) {
this.pauseEffect(soundId);
} else {
this.resumeEffect(soundId);
}
}
}
} }

View File

@ -23,6 +23,7 @@ THE SOFTWARE.
****************************************************************************/ ****************************************************************************/
package org.cocos2dx.lib; package org.cocos2dx.lib;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map; import java.util.Map;
@ -44,10 +45,12 @@ public class Cocos2dxSound {
private float mLeftVolume; private float mLeftVolume;
private float mRightVolume; private float mRightVolume;
// sound id and stream id map // sound path and stream ids map
private HashMap<Integer,Integer> mSoundIdStreamIdMap; // a file may be played many times at the same time
// sound path and sound id map // so there is an array map to a file path
private HashMap<String,Integer> mPathSoundIDMap; private HashMap<String,ArrayList<Integer>> mPathStreamIDsMap;
private HashMap<String, Integer> mPathSoundIdMap;
private static final String TAG = "Cocos2dxSound"; private static final String TAG = "Cocos2dxSound";
private static final int MAX_SIMULTANEOUS_STREAMS_DEFAULT = 5; private static final int MAX_SIMULTANEOUS_STREAMS_DEFAULT = 5;
@ -55,8 +58,8 @@ public class Cocos2dxSound {
private static final int SOUND_PRIORITY = 1; private static final int SOUND_PRIORITY = 1;
private static final int SOUND_QUALITY = 5; private static final int SOUND_QUALITY = 5;
private final int INVALID_SOUND_ID = -1; private final static int INVALID_SOUND_ID = -1;
private final int INVALID_STREAM_ID = -1; private final static int INVALID_STREAM_ID = -1;
public Cocos2dxSound(Context context){ public Cocos2dxSound(Context context){
this.mContext = context; this.mContext = context;
@ -64,53 +67,48 @@ public class Cocos2dxSound {
} }
public int preloadEffect(String path){ public int preloadEffect(String path){
int soundId = INVALID_SOUND_ID; Integer soundID = this.mPathSoundIdMap.get(path);
// if the sound is preloaded, pass it if (soundID == null) {
if (this.mPathSoundIDMap.get(path) != null){ soundID = createSoundIdFromAsset(path);
soundId = this.mPathSoundIDMap.get(path).intValue(); this.mPathSoundIdMap.put(path, soundID);
} else {
soundId = createSoundIdFromAsset(path);
if (soundId != INVALID_SOUND_ID){
// the sound is loaded but has not been played
this.mSoundIdStreamIdMap.put(soundId, INVALID_STREAM_ID);
// record path and sound id map
this.mPathSoundIDMap.put(path, soundId);
}
} }
return soundId; return soundID;
} }
public void unloadEffect(String path){ public void unloadEffect(String path){
// get sound id and remove from mPathSoundIDMap // stop effects
Integer soundId = this.mPathSoundIDMap.remove(path); ArrayList<Integer> streamIDs = this.mPathStreamIDsMap.get(path);
if (streamIDs != null) {
for (Integer streamID : streamIDs) {
this.mSoundPool.stop(streamID);
}
}
this.mPathStreamIDsMap.remove(path);
if (soundId != null){ // unload effect
// unload effect Integer soundID = this.mPathSoundIdMap.get(path);
this.mSoundPool.unload(soundId.intValue()); this.mSoundPool.unload(soundID);
this.mPathSoundIdMap.remove(path);
// remove record from mSoundIdStreamIdMap
this.mSoundIdStreamIdMap.remove(soundId);
}
} }
public int playEffect(String path, boolean isLoop){ public int playEffect(String path, boolean isLoop){
Integer soundId = this.mPathSoundIDMap.get(path); Integer soundId = this.mPathSoundIdMap.get(path);
int streamId = INVALID_STREAM_ID;
if (soundId != null){ if (soundId != null){
// the sound is preloaded, stop it first
this.mSoundPool.stop(soundId);
// play sound // play sound
int streamId = this.mSoundPool.play(soundId.intValue(), this.mLeftVolume, streamId = this.mSoundPool.play(soundId.intValue(), this.mLeftVolume,
this.mRightVolume, SOUND_PRIORITY, isLoop ? -1 : 0, SOUND_RATE); this.mRightVolume, SOUND_PRIORITY, isLoop ? -1 : 0, SOUND_RATE);
// record sound id and stream id map // record stream id
this.mSoundIdStreamIdMap.put(soundId, streamId); ArrayList<Integer> streamIds = this.mPathStreamIDsMap.get(path);
if (streamIds == null) {
streamIds = new ArrayList<Integer>();
this.mPathStreamIDsMap.put(path, streamIds);
}
streamIds.add(streamId);
} else { } else {
// the effect is not prepared // the effect is not prepared
soundId = preloadEffect(path); soundId = preloadEffect(path);
@ -133,54 +131,53 @@ public class Cocos2dxSound {
playEffect(path, isLoop); playEffect(path, isLoop);
} }
return soundId.intValue(); return streamId;
} }
public void stopEffect(int soundId){ public void stopEffect(int streamID){
Integer streamId = this.mSoundIdStreamIdMap.get(soundId); this.mSoundPool.stop(streamID);
if (streamId != null && streamId.intValue() != INVALID_STREAM_ID){ // remove record
this.mSoundPool.stop(streamId.intValue()); for (String path : this.mPathStreamIDsMap.keySet()) {
this.mPathSoundIDMap.remove(soundId); if (this.mPathStreamIDsMap.get(path).contains(streamID)) {
this.mPathStreamIDsMap.get(path).remove(this.mPathStreamIDsMap.get(path).indexOf(streamID));
break;
}
} }
} }
public void pauseEffect(int soundId){ public void pauseEffect(int streamID){
Integer streamId = this.mSoundIdStreamIdMap.get(soundId); this.mSoundPool.pause(streamID);
if (streamId != null && streamId.intValue() != INVALID_STREAM_ID){
this.mSoundPool.pause(streamId.intValue());
this.mPathSoundIDMap.remove(soundId);
}
} }
public void resumeEffect(int soundId){ public void resumeEffect(int streamID){
Integer streamId = this.mSoundIdStreamIdMap.get(soundId); this.mSoundPool.resume(streamID);
if (streamId != null && streamId.intValue() != INVALID_STREAM_ID){
this.mSoundPool.resume(streamId.intValue());
this.mPathSoundIDMap.remove(soundId);
}
} }
public void pauseAllEffects(){ public void pauseAllEffects(){
// autoResume is available since level 8 this.mSoundPool.autoPause();
pauseOrResumeAllEffects(true);
} }
public void resumeAllEffects(){ public void resumeAllEffects(){
// autoPause() is available since level 8 // autoPause() is available since level 8
pauseOrResumeAllEffects(false); this.mSoundPool.autoResume();
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public void stopAllEffects(){ public void stopAllEffects(){
Iterator<?> iter = this.mSoundIdStreamIdMap.entrySet().iterator(); // stop effects
while (iter.hasNext()){ if (! this.mPathStreamIDsMap.isEmpty()) {
Map.Entry<Integer, Integer> entry = (Map.Entry<Integer, Integer>)iter.next(); Iterator<?> iter = this.mPathStreamIDsMap.entrySet().iterator();
int soundId = entry.getKey(); while (iter.hasNext()){
this.stopEffect(soundId); Map.Entry<String, ArrayList<Integer>> entry = (Map.Entry<String, ArrayList<Integer>>)iter.next();
} for (int streamID : entry.getValue()) {
this.mSoundPool.stop(streamID);
}
}
}
// remove records
this.mPathStreamIDsMap.clear();
} }
public float getEffectsVolume(){ public float getEffectsVolume(){
@ -200,17 +197,21 @@ public class Cocos2dxSound {
this.mLeftVolume = this.mRightVolume = volume; this.mLeftVolume = this.mRightVolume = volume;
// change the volume of playing sounds // change the volume of playing sounds
Iterator<?> iter = this.mSoundIdStreamIdMap.entrySet().iterator(); if (! this.mPathStreamIDsMap.isEmpty()) {
while (iter.hasNext()){ Iterator<?> iter = this.mPathStreamIDsMap.entrySet().iterator();
Map.Entry<Integer, Integer> entry = (Map.Entry<Integer, Integer>)iter.next(); while (iter.hasNext()){
this.mSoundPool.setVolume(entry.getValue(), mLeftVolume, mRightVolume); Map.Entry<String, ArrayList<Integer>> entry = (Map.Entry<String, ArrayList<Integer>>)iter.next();
} for (int streamID : entry.getValue()) {
this.mSoundPool.setVolume(streamID, mLeftVolume, mRightVolume);
}
}
}
} }
public void end(){ public void end(){
this.mSoundPool.release(); this.mSoundPool.release();
this.mPathSoundIDMap.clear(); this.mPathStreamIDsMap.clear();
this.mSoundIdStreamIdMap.clear(); this.mPathSoundIdMap.clear();
initData(); initData();
} }
@ -234,25 +235,11 @@ public class Cocos2dxSound {
} }
private void initData(){ private void initData(){
this.mSoundIdStreamIdMap = new HashMap<Integer,Integer>(); this.mPathStreamIDsMap = new HashMap<String,ArrayList<Integer>>();
this.mPathSoundIdMap = new HashMap<String, Integer>();
mSoundPool = new SoundPool(MAX_SIMULTANEOUS_STREAMS_DEFAULT, AudioManager.STREAM_MUSIC, SOUND_QUALITY); mSoundPool = new SoundPool(MAX_SIMULTANEOUS_STREAMS_DEFAULT, AudioManager.STREAM_MUSIC, SOUND_QUALITY);
mPathSoundIDMap = new HashMap<String,Integer>();
this.mLeftVolume = 0.5f; this.mLeftVolume = 0.5f;
this.mRightVolume = 0.5f; this.mRightVolume = 0.5f;
} }
@SuppressWarnings("unchecked")
private void pauseOrResumeAllEffects(boolean isPause){
Iterator<?> iter = this.mSoundIdStreamIdMap.entrySet().iterator();
while (iter.hasNext()){
Map.Entry<Integer, Integer> entry = (Map.Entry<Integer, Integer>)iter.next();
int soundId = entry.getKey();
if (isPause) {
this.pauseEffect(soundId);
} else {
this.resumeEffect(soundId);
}
}
}
} }

View File

@ -23,6 +23,7 @@ THE SOFTWARE.
****************************************************************************/ ****************************************************************************/
package org.cocos2dx.lib; package org.cocos2dx.lib;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map; import java.util.Map;
@ -44,10 +45,12 @@ public class Cocos2dxSound {
private float mLeftVolume; private float mLeftVolume;
private float mRightVolume; private float mRightVolume;
// sound id and stream id map // sound path and stream ids map
private HashMap<Integer,Integer> mSoundIdStreamIdMap; // a file may be played many times at the same time
// sound path and sound id map // so there is an array map to a file path
private HashMap<String,Integer> mPathSoundIDMap; private HashMap<String,ArrayList<Integer>> mPathStreamIDsMap;
private HashMap<String, Integer> mPathSoundIdMap;
private static final String TAG = "Cocos2dxSound"; private static final String TAG = "Cocos2dxSound";
private static final int MAX_SIMULTANEOUS_STREAMS_DEFAULT = 5; private static final int MAX_SIMULTANEOUS_STREAMS_DEFAULT = 5;
@ -55,8 +58,8 @@ public class Cocos2dxSound {
private static final int SOUND_PRIORITY = 1; private static final int SOUND_PRIORITY = 1;
private static final int SOUND_QUALITY = 5; private static final int SOUND_QUALITY = 5;
private final int INVALID_SOUND_ID = -1; private final static int INVALID_SOUND_ID = -1;
private final int INVALID_STREAM_ID = -1; private final static int INVALID_STREAM_ID = -1;
public Cocos2dxSound(Context context){ public Cocos2dxSound(Context context){
this.mContext = context; this.mContext = context;
@ -64,53 +67,48 @@ public class Cocos2dxSound {
} }
public int preloadEffect(String path){ public int preloadEffect(String path){
int soundId = INVALID_SOUND_ID; Integer soundID = this.mPathSoundIdMap.get(path);
// if the sound is preloaded, pass it if (soundID == null) {
if (this.mPathSoundIDMap.get(path) != null){ soundID = createSoundIdFromAsset(path);
soundId = this.mPathSoundIDMap.get(path).intValue(); this.mPathSoundIdMap.put(path, soundID);
} else {
soundId = createSoundIdFromAsset(path);
if (soundId != INVALID_SOUND_ID){
// the sound is loaded but has not been played
this.mSoundIdStreamIdMap.put(soundId, INVALID_STREAM_ID);
// record path and sound id map
this.mPathSoundIDMap.put(path, soundId);
}
} }
return soundId; return soundID;
} }
public void unloadEffect(String path){ public void unloadEffect(String path){
// get sound id and remove from mPathSoundIDMap // stop effects
Integer soundId = this.mPathSoundIDMap.remove(path); ArrayList<Integer> streamIDs = this.mPathStreamIDsMap.get(path);
if (streamIDs != null) {
for (Integer streamID : streamIDs) {
this.mSoundPool.stop(streamID);
}
}
this.mPathStreamIDsMap.remove(path);
if (soundId != null){ // unload effect
// unload effect Integer soundID = this.mPathSoundIdMap.get(path);
this.mSoundPool.unload(soundId.intValue()); this.mSoundPool.unload(soundID);
this.mPathSoundIdMap.remove(path);
// remove record from mSoundIdStreamIdMap
this.mSoundIdStreamIdMap.remove(soundId);
}
} }
public int playEffect(String path, boolean isLoop){ public int playEffect(String path, boolean isLoop){
Integer soundId = this.mPathSoundIDMap.get(path); Integer soundId = this.mPathSoundIdMap.get(path);
int streamId = INVALID_STREAM_ID;
if (soundId != null){ if (soundId != null){
// the sound is preloaded, stop it first
this.mSoundPool.stop(soundId);
// play sound // play sound
int streamId = this.mSoundPool.play(soundId.intValue(), this.mLeftVolume, streamId = this.mSoundPool.play(soundId.intValue(), this.mLeftVolume,
this.mRightVolume, SOUND_PRIORITY, isLoop ? -1 : 0, SOUND_RATE); this.mRightVolume, SOUND_PRIORITY, isLoop ? -1 : 0, SOUND_RATE);
// record sound id and stream id map // record stream id
this.mSoundIdStreamIdMap.put(soundId, streamId); ArrayList<Integer> streamIds = this.mPathStreamIDsMap.get(path);
if (streamIds == null) {
streamIds = new ArrayList<Integer>();
this.mPathStreamIDsMap.put(path, streamIds);
}
streamIds.add(streamId);
} else { } else {
// the effect is not prepared // the effect is not prepared
soundId = preloadEffect(path); soundId = preloadEffect(path);
@ -133,54 +131,53 @@ public class Cocos2dxSound {
playEffect(path, isLoop); playEffect(path, isLoop);
} }
return soundId.intValue(); return streamId;
} }
public void stopEffect(int soundId){ public void stopEffect(int streamID){
Integer streamId = this.mSoundIdStreamIdMap.get(soundId); this.mSoundPool.stop(streamID);
if (streamId != null && streamId.intValue() != INVALID_STREAM_ID){ // remove record
this.mSoundPool.stop(streamId.intValue()); for (String path : this.mPathStreamIDsMap.keySet()) {
this.mPathSoundIDMap.remove(soundId); if (this.mPathStreamIDsMap.get(path).contains(streamID)) {
this.mPathStreamIDsMap.get(path).remove(this.mPathStreamIDsMap.get(path).indexOf(streamID));
break;
}
} }
} }
public void pauseEffect(int soundId){ public void pauseEffect(int streamID){
Integer streamId = this.mSoundIdStreamIdMap.get(soundId); this.mSoundPool.pause(streamID);
if (streamId != null && streamId.intValue() != INVALID_STREAM_ID){
this.mSoundPool.pause(streamId.intValue());
this.mPathSoundIDMap.remove(soundId);
}
} }
public void resumeEffect(int soundId){ public void resumeEffect(int streamID){
Integer streamId = this.mSoundIdStreamIdMap.get(soundId); this.mSoundPool.resume(streamID);
if (streamId != null && streamId.intValue() != INVALID_STREAM_ID){
this.mSoundPool.resume(streamId.intValue());
this.mPathSoundIDMap.remove(soundId);
}
} }
public void pauseAllEffects(){ public void pauseAllEffects(){
// autoResume is available since level 8 this.mSoundPool.autoPause();
pauseOrResumeAllEffects(true);
} }
public void resumeAllEffects(){ public void resumeAllEffects(){
// autoPause() is available since level 8 // autoPause() is available since level 8
pauseOrResumeAllEffects(false); this.mSoundPool.autoResume();
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public void stopAllEffects(){ public void stopAllEffects(){
Iterator<?> iter = this.mSoundIdStreamIdMap.entrySet().iterator(); // stop effects
while (iter.hasNext()){ if (! this.mPathStreamIDsMap.isEmpty()) {
Map.Entry<Integer, Integer> entry = (Map.Entry<Integer, Integer>)iter.next(); Iterator<?> iter = this.mPathStreamIDsMap.entrySet().iterator();
int soundId = entry.getKey(); while (iter.hasNext()){
this.stopEffect(soundId); Map.Entry<String, ArrayList<Integer>> entry = (Map.Entry<String, ArrayList<Integer>>)iter.next();
} for (int streamID : entry.getValue()) {
this.mSoundPool.stop(streamID);
}
}
}
// remove records
this.mPathStreamIDsMap.clear();
} }
public float getEffectsVolume(){ public float getEffectsVolume(){
@ -200,17 +197,21 @@ public class Cocos2dxSound {
this.mLeftVolume = this.mRightVolume = volume; this.mLeftVolume = this.mRightVolume = volume;
// change the volume of playing sounds // change the volume of playing sounds
Iterator<?> iter = this.mSoundIdStreamIdMap.entrySet().iterator(); if (! this.mPathStreamIDsMap.isEmpty()) {
while (iter.hasNext()){ Iterator<?> iter = this.mPathStreamIDsMap.entrySet().iterator();
Map.Entry<Integer, Integer> entry = (Map.Entry<Integer, Integer>)iter.next(); while (iter.hasNext()){
this.mSoundPool.setVolume(entry.getValue(), mLeftVolume, mRightVolume); Map.Entry<String, ArrayList<Integer>> entry = (Map.Entry<String, ArrayList<Integer>>)iter.next();
} for (int streamID : entry.getValue()) {
this.mSoundPool.setVolume(streamID, mLeftVolume, mRightVolume);
}
}
}
} }
public void end(){ public void end(){
this.mSoundPool.release(); this.mSoundPool.release();
this.mPathSoundIDMap.clear(); this.mPathStreamIDsMap.clear();
this.mSoundIdStreamIdMap.clear(); this.mPathSoundIdMap.clear();
initData(); initData();
} }
@ -234,25 +235,11 @@ public class Cocos2dxSound {
} }
private void initData(){ private void initData(){
this.mSoundIdStreamIdMap = new HashMap<Integer,Integer>(); this.mPathStreamIDsMap = new HashMap<String,ArrayList<Integer>>();
this.mPathSoundIdMap = new HashMap<String, Integer>();
mSoundPool = new SoundPool(MAX_SIMULTANEOUS_STREAMS_DEFAULT, AudioManager.STREAM_MUSIC, SOUND_QUALITY); mSoundPool = new SoundPool(MAX_SIMULTANEOUS_STREAMS_DEFAULT, AudioManager.STREAM_MUSIC, SOUND_QUALITY);
mPathSoundIDMap = new HashMap<String,Integer>();
this.mLeftVolume = 0.5f; this.mLeftVolume = 0.5f;
this.mRightVolume = 0.5f; this.mRightVolume = 0.5f;
} }
@SuppressWarnings("unchecked")
private void pauseOrResumeAllEffects(boolean isPause){
Iterator<?> iter = this.mSoundIdStreamIdMap.entrySet().iterator();
while (iter.hasNext()){
Map.Entry<Integer, Integer> entry = (Map.Entry<Integer, Integer>)iter.next();
int soundId = entry.getKey();
if (isPause) {
this.pauseEffect(soundId);
} else {
this.resumeEffect(soundId);
}
}
}
} }

View File

@ -23,6 +23,7 @@ THE SOFTWARE.
****************************************************************************/ ****************************************************************************/
package org.cocos2dx.lib; package org.cocos2dx.lib;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map; import java.util.Map;
@ -44,10 +45,12 @@ public class Cocos2dxSound {
private float mLeftVolume; private float mLeftVolume;
private float mRightVolume; private float mRightVolume;
// sound id and stream id map // sound path and stream ids map
private HashMap<Integer,Integer> mSoundIdStreamIdMap; // a file may be played many times at the same time
// sound path and sound id map // so there is an array map to a file path
private HashMap<String,Integer> mPathSoundIDMap; private HashMap<String,ArrayList<Integer>> mPathStreamIDsMap;
private HashMap<String, Integer> mPathSoundIdMap;
private static final String TAG = "Cocos2dxSound"; private static final String TAG = "Cocos2dxSound";
private static final int MAX_SIMULTANEOUS_STREAMS_DEFAULT = 5; private static final int MAX_SIMULTANEOUS_STREAMS_DEFAULT = 5;
@ -55,8 +58,8 @@ public class Cocos2dxSound {
private static final int SOUND_PRIORITY = 1; private static final int SOUND_PRIORITY = 1;
private static final int SOUND_QUALITY = 5; private static final int SOUND_QUALITY = 5;
private final int INVALID_SOUND_ID = -1; private final static int INVALID_SOUND_ID = -1;
private final int INVALID_STREAM_ID = -1; private final static int INVALID_STREAM_ID = -1;
public Cocos2dxSound(Context context){ public Cocos2dxSound(Context context){
this.mContext = context; this.mContext = context;
@ -64,53 +67,48 @@ public class Cocos2dxSound {
} }
public int preloadEffect(String path){ public int preloadEffect(String path){
int soundId = INVALID_SOUND_ID; Integer soundID = this.mPathSoundIdMap.get(path);
// if the sound is preloaded, pass it if (soundID == null) {
if (this.mPathSoundIDMap.get(path) != null){ soundID = createSoundIdFromAsset(path);
soundId = this.mPathSoundIDMap.get(path).intValue(); this.mPathSoundIdMap.put(path, soundID);
} else {
soundId = createSoundIdFromAsset(path);
if (soundId != INVALID_SOUND_ID){
// the sound is loaded but has not been played
this.mSoundIdStreamIdMap.put(soundId, INVALID_STREAM_ID);
// record path and sound id map
this.mPathSoundIDMap.put(path, soundId);
}
} }
return soundId; return soundID;
} }
public void unloadEffect(String path){ public void unloadEffect(String path){
// get sound id and remove from mPathSoundIDMap // stop effects
Integer soundId = this.mPathSoundIDMap.remove(path); ArrayList<Integer> streamIDs = this.mPathStreamIDsMap.get(path);
if (streamIDs != null) {
for (Integer streamID : streamIDs) {
this.mSoundPool.stop(streamID);
}
}
this.mPathStreamIDsMap.remove(path);
if (soundId != null){ // unload effect
// unload effect Integer soundID = this.mPathSoundIdMap.get(path);
this.mSoundPool.unload(soundId.intValue()); this.mSoundPool.unload(soundID);
this.mPathSoundIdMap.remove(path);
// remove record from mSoundIdStreamIdMap
this.mSoundIdStreamIdMap.remove(soundId);
}
} }
public int playEffect(String path, boolean isLoop){ public int playEffect(String path, boolean isLoop){
Integer soundId = this.mPathSoundIDMap.get(path); Integer soundId = this.mPathSoundIdMap.get(path);
int streamId = INVALID_STREAM_ID;
if (soundId != null){ if (soundId != null){
// the sound is preloaded, stop it first
this.mSoundPool.stop(soundId);
// play sound // play sound
int streamId = this.mSoundPool.play(soundId.intValue(), this.mLeftVolume, streamId = this.mSoundPool.play(soundId.intValue(), this.mLeftVolume,
this.mRightVolume, SOUND_PRIORITY, isLoop ? -1 : 0, SOUND_RATE); this.mRightVolume, SOUND_PRIORITY, isLoop ? -1 : 0, SOUND_RATE);
// record sound id and stream id map // record stream id
this.mSoundIdStreamIdMap.put(soundId, streamId); ArrayList<Integer> streamIds = this.mPathStreamIDsMap.get(path);
if (streamIds == null) {
streamIds = new ArrayList<Integer>();
this.mPathStreamIDsMap.put(path, streamIds);
}
streamIds.add(streamId);
} else { } else {
// the effect is not prepared // the effect is not prepared
soundId = preloadEffect(path); soundId = preloadEffect(path);
@ -133,54 +131,53 @@ public class Cocos2dxSound {
playEffect(path, isLoop); playEffect(path, isLoop);
} }
return soundId.intValue(); return streamId;
} }
public void stopEffect(int soundId){ public void stopEffect(int streamID){
Integer streamId = this.mSoundIdStreamIdMap.get(soundId); this.mSoundPool.stop(streamID);
if (streamId != null && streamId.intValue() != INVALID_STREAM_ID){ // remove record
this.mSoundPool.stop(streamId.intValue()); for (String path : this.mPathStreamIDsMap.keySet()) {
this.mPathSoundIDMap.remove(soundId); if (this.mPathStreamIDsMap.get(path).contains(streamID)) {
this.mPathStreamIDsMap.get(path).remove(this.mPathStreamIDsMap.get(path).indexOf(streamID));
break;
}
} }
} }
public void pauseEffect(int soundId){ public void pauseEffect(int streamID){
Integer streamId = this.mSoundIdStreamIdMap.get(soundId); this.mSoundPool.pause(streamID);
if (streamId != null && streamId.intValue() != INVALID_STREAM_ID){
this.mSoundPool.pause(streamId.intValue());
this.mPathSoundIDMap.remove(soundId);
}
} }
public void resumeEffect(int soundId){ public void resumeEffect(int streamID){
Integer streamId = this.mSoundIdStreamIdMap.get(soundId); this.mSoundPool.resume(streamID);
if (streamId != null && streamId.intValue() != INVALID_STREAM_ID){
this.mSoundPool.resume(streamId.intValue());
this.mPathSoundIDMap.remove(soundId);
}
} }
public void pauseAllEffects(){ public void pauseAllEffects(){
// autoResume is available since level 8 this.mSoundPool.autoPause();
pauseOrResumeAllEffects(true);
} }
public void resumeAllEffects(){ public void resumeAllEffects(){
// autoPause() is available since level 8 // autoPause() is available since level 8
pauseOrResumeAllEffects(false); this.mSoundPool.autoResume();
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public void stopAllEffects(){ public void stopAllEffects(){
Iterator<?> iter = this.mSoundIdStreamIdMap.entrySet().iterator(); // stop effects
while (iter.hasNext()){ if (! this.mPathStreamIDsMap.isEmpty()) {
Map.Entry<Integer, Integer> entry = (Map.Entry<Integer, Integer>)iter.next(); Iterator<?> iter = this.mPathStreamIDsMap.entrySet().iterator();
int soundId = entry.getKey(); while (iter.hasNext()){
this.stopEffect(soundId); Map.Entry<String, ArrayList<Integer>> entry = (Map.Entry<String, ArrayList<Integer>>)iter.next();
} for (int streamID : entry.getValue()) {
this.mSoundPool.stop(streamID);
}
}
}
// remove records
this.mPathStreamIDsMap.clear();
} }
public float getEffectsVolume(){ public float getEffectsVolume(){
@ -200,17 +197,21 @@ public class Cocos2dxSound {
this.mLeftVolume = this.mRightVolume = volume; this.mLeftVolume = this.mRightVolume = volume;
// change the volume of playing sounds // change the volume of playing sounds
Iterator<?> iter = this.mSoundIdStreamIdMap.entrySet().iterator(); if (! this.mPathStreamIDsMap.isEmpty()) {
while (iter.hasNext()){ Iterator<?> iter = this.mPathStreamIDsMap.entrySet().iterator();
Map.Entry<Integer, Integer> entry = (Map.Entry<Integer, Integer>)iter.next(); while (iter.hasNext()){
this.mSoundPool.setVolume(entry.getValue(), mLeftVolume, mRightVolume); Map.Entry<String, ArrayList<Integer>> entry = (Map.Entry<String, ArrayList<Integer>>)iter.next();
} for (int streamID : entry.getValue()) {
this.mSoundPool.setVolume(streamID, mLeftVolume, mRightVolume);
}
}
}
} }
public void end(){ public void end(){
this.mSoundPool.release(); this.mSoundPool.release();
this.mPathSoundIDMap.clear(); this.mPathStreamIDsMap.clear();
this.mSoundIdStreamIdMap.clear(); this.mPathSoundIdMap.clear();
initData(); initData();
} }
@ -234,25 +235,11 @@ public class Cocos2dxSound {
} }
private void initData(){ private void initData(){
this.mSoundIdStreamIdMap = new HashMap<Integer,Integer>(); this.mPathStreamIDsMap = new HashMap<String,ArrayList<Integer>>();
this.mPathSoundIdMap = new HashMap<String, Integer>();
mSoundPool = new SoundPool(MAX_SIMULTANEOUS_STREAMS_DEFAULT, AudioManager.STREAM_MUSIC, SOUND_QUALITY); mSoundPool = new SoundPool(MAX_SIMULTANEOUS_STREAMS_DEFAULT, AudioManager.STREAM_MUSIC, SOUND_QUALITY);
mPathSoundIDMap = new HashMap<String,Integer>();
this.mLeftVolume = 0.5f; this.mLeftVolume = 0.5f;
this.mRightVolume = 0.5f; this.mRightVolume = 0.5f;
} }
@SuppressWarnings("unchecked")
private void pauseOrResumeAllEffects(boolean isPause){
Iterator<?> iter = this.mSoundIdStreamIdMap.entrySet().iterator();
while (iter.hasNext()){
Map.Entry<Integer, Integer> entry = (Map.Entry<Integer, Integer>)iter.next();
int soundId = entry.getKey();
if (isPause) {
this.pauseEffect(soundId);
} else {
this.resumeEffect(soundId);
}
}
}
} }