It’s also easy on Android. I just did it and it works fine. You just need to modify:
CocosDenshion/Android/SimpleAudioEngine.cpp
before
unsigned int SimpleAudioEngine::playEffect(const char* pszFilePath, bool bLoop)
{
return playEffectJNI(pszFilePath, bLoop);
}
after
unsigned int SimpleAudioEngine::playEffect(const char* pszFilePath, bool bLoop, float pitch, float pan, float gain)
{
return playEffectJNI(pszFilePath, bLoop, pitch, pan, gain);
}
CocosDenshion/Android/jni/SimpleAudioEngineJni.cpp
before
unsigned int playEffectJNI(const char* path, bool bLoop)
{
// int playEffect(String)
JniMethodInfo methodInfo;
int ret = 0;
if (! getStaticMethodInfo(methodInfo, "playEffect", "(Ljava/lang/String;Z)I"))
{
return ret;
}
jstring stringArg = methodInfo.env->NewStringUTF(path);
ret = methodInfo.env->CallStaticIntMethod(methodInfo.classID, methodInfo.methodID, stringArg, bLoop);
methodInfo.env->DeleteLocalRef(stringArg);
methodInfo.env->DeleteLocalRef(methodInfo.classID);
return (unsigned int)ret;
}
after
unsigned int playEffectJNI(const char* path, bool bLoop, float pitch, float pan, float gain)
{
// int playEffect(String)
JniMethodInfo methodInfo;
int ret = 0;
if (! getStaticMethodInfo(methodInfo, "playEffect", "(Ljava/lang/String;ZFFF)I"))
{
return ret;
}
jstring stringArg = methodInfo.env->NewStringUTF(path);
ret = methodInfo.env->CallStaticIntMethod(methodInfo.classID, methodInfo.methodID, stringArg, bLoop, pitch, pan, gain);
methodInfo.env->DeleteLocalRef(stringArg);
methodInfo.env->DeleteLocalRef(methodInfo.classID);
return (unsigned int)ret;
}
CocosDenshion/Android/jni/SimpleAudioEngineJni.h
before
extern unsigned int playEffectJNI(const char* path, bool bLoop);
after
extern unsigned int playEffectJNI(const char* path, bool bLoop, float pitch, float pan, float gain);
/src/org/cocos2dx/lib/Cocos2dxActivity.java
before
public static int playEffect(String path, boolean isLoop){
return soundPlayer.playEffect(path, isLoop);
}
after
public static int playEffect(String path, boolean isLoop, float pitch, float pan, float gain){
return soundPlayer.playEffect(path, isLoop, pitch, pan, gain);
}
/src/org/cocos2dx/lib/Cocos2dxSound.java
before
public int playEffect(String path, boolean isLoop){
Integer soundId = this.mPathSoundIDMap.get(path);
if (soundId != null){
// the sound is preloaded, stop it first
this.mSoundPool.stop(soundId);
// play sound
int streamId = this.mSoundPool.play(soundId.intValue(), this.mLeftVolume, this.mRightVolume, SOUND_PRIORITY, isLoop ? -1 : 0, SOUND_RATE);
// record sound id and stream id map
this.mSoundIdStreamIdMap.put(soundId, streamId);
} else {
// the effect is not prepared
soundId = preloadEffect(path);
if (soundId == INVALID_SOUND_ID){
// can not preload effect
return INVALID_SOUND_ID;
}
/*
* Someone reports that, it can not play effect for the
* first time. If you are lucky to meet it. There are two
* ways to resolve it.
* 1. Add some delay here. I don't know how long it is, so
* I don't add it here.
* 2. If you use 2.2(API level 8), you can call
* SoundPool.setOnLoadCompleteListener() to play the effect.
* Because the method is supported from 2.2, so I can't use
* it here.
*/
playEffect(path, isLoop);
}
return soundId.intValue();
}
after
public int playEffect(String path, boolean isLoop, float pitch, float pan, float gain){
Integer soundId = this.mPathSoundIDMap.get(path);
if (soundId != null){
// the sound is preloaded, stop it first
this.mSoundPool.stop(soundId);
// parameters; pan = -1 for left channel, 1 for right channel, 0 for both channels
float leftVolume = Math.max(0.0f, Math.min(1.0f, this.mLeftVolume * gain * Math.max(0.0f, Math.min(1.0f, 1.0f - pan))));
float rightVolume = Math.max(0.0f, Math.min(1.0f, this.mRightVolume * gain * Math.max(0.0f, Math.min(1.0f, 1.0f + pan))));
float soundRate = Math.max(0.5f, Math.min(2.0f, SOUND_RATE * pitch));
// play sound
int streamId = this.mSoundPool.play(soundId.intValue(), leftVolume, rightVolume, SOUND_PRIORITY, isLoop ? -1 : 0, soundRate);
// record sound id and stream id map
this.mSoundIdStreamIdMap.put(soundId, streamId);
} else {
// the effect is not prepared
soundId = preloadEffect(path);
if (soundId == INVALID_SOUND_ID){
// can not preload effect
return INVALID_SOUND_ID;
}
/*
* Someone reports that, it can not play effect for the
* first time. If you are lucky to meet it. There are two
* ways to resolve it.
* 1. Add some delay here. I don't know how long it is, so
* I don't add it here.
* 2. If you use 2.2(API level 8), you can call
* SoundPool.setOnLoadCompleteListener() to play the effect.
* Because the method is supported from 2.2, so I can't use
* it here.
*/
playEffect(path, isLoop, pitch, pan, gain);
}
return soundId.intValue();
}