Android sound support using openSL ES. Now depends on SDK version 9.

This commit is contained in:
Xawotihs
2011-09-04 13:52:39 +00:00
parent 2d82e22303
commit 507552133d
5 changed files with 367 additions and 55 deletions

View File

@@ -18,31 +18,32 @@
#include "JTypes.h" #include "JTypes.h"
#ifdef USE_PHONON #ifdef ANDROID
#include <phonon/AudioOutput> #include <SLES/OpenSLES.h>
#include <phonon/MediaObject> #include "SLES/OpenSLES_Android.h"
#elif defined USE_PHONON
#include <phonon/AudioOutput>
#include <phonon/MediaObject>
#else #else
#ifdef WIN32 #ifdef WIN32
#include <windows.h>
#include <windows.h>
#define WITH_FMOD #define WITH_FMOD
#elif defined (PSP) #elif defined (PSP)
#include <pspgu.h> #include <pspgu.h>
#include <pspkernel.h> #include <pspkernel.h>
#include <pspdisplay.h> #include <pspdisplay.h>
#include <pspdebug.h> #include <pspdebug.h>
#include <pspctrl.h> #include <pspctrl.h>
#include <time.h> #include <time.h>
#include <string.h> #include <string.h>
#include <pspaudiolib.h> #include <pspaudiolib.h>
#include <psprtc.h> #include <psprtc.h>
#include "JAudio.h"
#include "JMP3.h"
#include "JAudio.h"
#include "JMP3.h"
#endif #endif
#ifdef WITH_FMOD #ifdef WITH_FMOD
#include "../Dependencies/include/fmod.h" #include "../Dependencies/include/fmod.h"
#endif #endif
#endif #endif
@@ -50,29 +51,32 @@
#ifdef USE_PHONON #ifdef USE_PHONON
class JMusic : public QObject class JMusic : public QObject
{ {
Q_OBJECT Q_OBJECT
#else #else
class JMusic class JMusic
{ {
#endif #endif
public: public:
JMusic(); JMusic();
~JMusic(); ~JMusic();
void Update(); void Update();
int getPlayTime(); int getPlayTime();
#ifdef USE_PHONON #ifdef USE_PHONON
Phonon::AudioOutput* mOutput; Phonon::AudioOutput* mOutput;
Phonon::MediaObject* mMediaObject; Phonon::MediaObject* mMediaObject;
public slots: public slots:
void seekAtTheBegining(); void seekAtTheBegining();
#elif defined (PSP) #elif defined (PSP)
JMP3* mTrack; JMP3* mTrack;
#elif defined WITH_FMOD #elif defined WITH_FMOD
FSOUND_SAMPLE* mTrack; // MP3 needed to be of "sample" type for FMOD, FMUSIC_MODULE is for MODs FSOUND_SAMPLE* mTrack; // MP3 needed to be of "sample" type for FMOD, FMUSIC_MODULE is for MODs
#elif defined ANDROID
SLObjectItf playerObject;
SLPlayItf playInterface;
SLSeekItf seekInterface;
#else #else
void* mTrack; void* mTrack;
#endif //WITH_FMOD #endif //WITH_FMOD
}; };
@@ -82,21 +86,25 @@ public:
class JSample class JSample
{ {
public: public:
JSample(); JSample();
~JSample(); ~JSample();
unsigned long fileSize(); unsigned long fileSize();
#if defined (PSP) #if defined (PSP)
WAVDATA *mSample; WAVDATA *mSample;
#elif defined (WITH_FMOD) #elif defined (WITH_FMOD)
FSOUND_SAMPLE *mSample; FSOUND_SAMPLE *mSample;
#elif defined (USE_PHONON) #elif defined (USE_PHONON)
Phonon::AudioOutput* mOutput; Phonon::AudioOutput* mOutput;
Phonon::MediaObject* mMediaObject; Phonon::MediaObject* mMediaObject;
void* mSample; void* mSample;
#elif defined ANDROID
SLObjectItf playerObject;
SLPlayItf playInterface;
void* mSample;
#else #else
void* mSample; void* mSample;
#endif #endif
}; };
@@ -214,9 +222,7 @@ protected:
private: private:
#ifdef WIN32 #ifdef WIN32
JMusic *mCurrentMusic; JMusic *mCurrentMusic;
#endif #endif
int mVolume; int mVolume;

306
JGE/src/android/JSfx.cpp Normal file
View File

@@ -0,0 +1,306 @@
#include "DebugRoutines.h"
// for native audio
#include <SLES/OpenSLES.h>
#include "SLES/OpenSLES_Android.h"
#include "../../include/JSoundSystem.h"
#include "../../include/JFileSystem.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
//////////////////////////////////////////////////////////////////////////
// engine interfaces
static SLObjectItf engineObject = NULL;
static SLEngineItf engineEngine;
// output mix interfaces
static SLObjectItf outputMixObject = NULL;
//////////////////////////////////////////////////////////////////////////
JMusic::JMusic()
: playerObject(0), playInterface(0), seekInterface(0)
{
}
void JMusic::Update(){
}
int JMusic::getPlayTime(){
return 0;
}
JMusic::~JMusic()
{
// destroy file descriptor audio player object, and invalidate all associated interfaces
if (playerObject != NULL) {
(*playerObject)->Destroy(playerObject);
playerObject = NULL;
playInterface = NULL;
seekInterface = NULL;
}
}
//////////////////////////////////////////////////////////////////////////
JSample::JSample()
: playerObject(0), playInterface(0)
{
}
JSample::~JSample()
{
// destroy file descriptor audio player object, and invalidate all associated interfaces
if (playerObject != NULL) {
(*playerObject)->Destroy(playerObject);
playerObject = NULL;
playInterface = NULL;
}
}
unsigned long JSample::fileSize()
{
return 0;
}
//////////////////////////////////////////////////////////////////////////
JSoundSystem* JSoundSystem::mInstance = NULL;
JSoundSystem* JSoundSystem::GetInstance()
{
if (mInstance == NULL)
{
mInstance = new JSoundSystem();
mInstance->InitSoundSystem();
}
return mInstance;
}
void JSoundSystem::Destroy()
{
if (mInstance)
{
mInstance->DestroySoundSystem();
delete mInstance;
mInstance = NULL;
}
}
JSoundSystem::JSoundSystem()
{
mVolume = 0;
mSampleVolume = 0;
}
JSoundSystem::~JSoundSystem()
{
}
void JSoundSystem::InitSoundSystem()
{
DebugTrace("InitSoundSystem enter");
SLresult result;
// create engine
result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL);
DebugTrace("result " << result);
// realize the engine
result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
DebugTrace("result " << result);
// get the engine interface, which is needed in order to create other objects
result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
DebugTrace("result " << result);
// create output mix
const SLInterfaceID ids[1] = {SL_IID_ENVIRONMENTALREVERB};
const SLboolean req[1] = {SL_BOOLEAN_FALSE};
result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 1, ids, req);
DebugTrace("result " << result);
// realize the output mix
result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE);
DebugTrace("result " << result);
DebugTrace("InitSoundSystem leave");
}
void JSoundSystem::DestroySoundSystem()
{
// destroy output mix object, and invalidate all associated interfaces
if (outputMixObject != NULL) {
(*outputMixObject)->Destroy(outputMixObject);
outputMixObject = NULL;
}
// destroy engine object, and invalidate all associated interfaces
if (engineObject != NULL) {
(*engineObject)->Destroy(engineObject);
engineObject = NULL;
engineEngine = NULL;
}
}
JMusic *JSoundSystem::LoadMusic(const char *fileName)
{
JMusic* music = new JMusic();
if (music)
{
// we should use the native asset manager instead
string fullpath = JFileSystem::GetInstance()->GetResourceFile(fileName);
int fd = open(fullpath.c_str(), O_RDONLY);
FILE* file = fdopen(fd, "r");
off_t start = 0;
off_t length;
fseek(file, 0, SEEK_END);
length = ftell(file);
SLresult result;
// configure audio source
SLDataLocator_AndroidFD loc_fd = {SL_DATALOCATOR_ANDROIDFD, fd, start, length};
SLDataFormat_MIME format_mime = {SL_DATAFORMAT_MIME, NULL, SL_CONTAINERTYPE_UNSPECIFIED};
SLDataSource audioSrc = {&loc_fd, &format_mime};
// configure audio sink
SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, outputMixObject};
SLDataSink audioSnk = {&loc_outmix, NULL};
// create audio player
const SLInterfaceID ids[2] = {SL_IID_SEEK, SL_IID_VOLUME};
const SLboolean req[2] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
result = (*engineEngine)->CreateAudioPlayer(engineEngine, &music->playerObject, &audioSrc, &audioSnk,
2, ids, req);
DebugTrace("result " << result);
// realize the player
result = (*music->playerObject)->Realize(music->playerObject, SL_BOOLEAN_FALSE);
DebugTrace("result " << result);
// get the play interface
result = (*music->playerObject)->GetInterface(music->playerObject, SL_IID_PLAY, &music->playInterface);
DebugTrace("result " << result);
// get the seek interface
result = (*music->playerObject)->GetInterface(music->playerObject, SL_IID_SEEK, &music->seekInterface);
DebugTrace("result " << result);
// get the volume interface
//result = (*music->playerObject)->GetInterface(music->playerObject, SL_IID_VOLUME, &musicVolumeInterface);
DebugTrace("result " << result);
}
return music;
}
void JSoundSystem::PlayMusic(JMusic *music, bool looping)
{
if(music && music->playerObject && music->playInterface && music->seekInterface)
{
SLresult result;
// enable whole file looping
result = (*music->seekInterface)->SetLoop(music->seekInterface,
looping?SL_BOOLEAN_TRUE:SL_BOOLEAN_FALSE, 0, SL_TIME_UNKNOWN);
assert(SL_RESULT_SUCCESS == result);
result = (*music->playInterface)->SetPlayState(music->playInterface,
SL_PLAYSTATE_PLAYING);
assert(SL_RESULT_SUCCESS == result);
}
}
void JSoundSystem::StopMusic(JMusic *music)
{
if(music && music->playerObject && music->playInterface && music->seekInterface)
{
SLresult result;
result = (*music->playInterface)->SetPlayState(music->playInterface,
SL_PLAYSTATE_STOPPED);
assert(SL_RESULT_SUCCESS == result);
}
}
void JSoundSystem::SetVolume(int volume)
{
SetMusicVolume(volume);
SetSfxVolume(volume);
}
void JSoundSystem::SetMusicVolume(int volume)
{
mVolume = volume;
}
void JSoundSystem::SetSfxVolume(int volume){
mSampleVolume = volume;
SetMusicVolume(mVolume);
}
JSample *JSoundSystem::LoadSample(const char *fileName)
{
JSample* sample = new JSample();
if (sample)
{
string fullpath = JFileSystem::GetInstance()->GetResourceFile(fileName);
int fd = open(fullpath.c_str(), O_RDONLY);
FILE* file = fdopen(fd, "r");
off_t start = 0;
off_t length;
fseek(file, 0, SEEK_END);
length = ftell(file);
SLresult result;
// configure audio source
SLDataLocator_AndroidFD loc_fd = {SL_DATALOCATOR_ANDROIDFD, fd, start, length};
SLDataFormat_MIME format_mime = {SL_DATAFORMAT_MIME, NULL, SL_CONTAINERTYPE_UNSPECIFIED};
SLDataSource audioSrc = {&loc_fd, &format_mime};
// configure audio sink
SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, outputMixObject};
SLDataSink audioSnk = {&loc_outmix, NULL};
// create audio player
const SLInterfaceID ids[1] = {SL_IID_VOLUME};
const SLboolean req[1] = {SL_BOOLEAN_TRUE};
result = (*engineEngine)->CreateAudioPlayer(engineEngine, &sample->playerObject, &audioSrc, &audioSnk,
1, ids, req);
DebugTrace("result " << result);
// realize the player
result = (*sample->playerObject)->Realize(sample->playerObject, SL_BOOLEAN_FALSE);
DebugTrace("result " << result);
// get the play interface
result = (*sample->playerObject)->GetInterface(sample->playerObject, SL_IID_PLAY, &sample->playInterface);
DebugTrace("result " << result);
// get the volume interface
//result = (*sample->playerObject)->GetInterface(sample->playerObject, SL_IID_VOLUME, &sampleVolumeInterface);
}
return sample;
}
void JSoundSystem::PlaySample(JSample *sample)
{
if(sample && sample->playerObject && sample->playInterface)
{
SLresult result;
result = (*sample->playInterface)->SetPlayState(sample->playInterface,
SL_PLAYSTATE_PLAYING);
}
}

View File

@@ -3,10 +3,10 @@
package="org.libsdl.app" package="org.libsdl.app"
android:versionCode="1" android:versionCode="1"
android:versionName="1.0"> android:versionName="1.0">
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"></uses-permission>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<application android:label="@string/app_name" android:icon="@drawable/icon" android:debuggable="true" android:theme="@android:style/Theme.NoTitleBar.Fullscreen"> <application android:label="@string/app_name" android:icon="@drawable/icon" android:debuggable="true" android:theme="@android:style/Theme.NoTitleBar.Fullscreen">
<activity android:name="SDLActivity" <activity android:name="SDLActivity"
android:configChanges="orientation" android:configChanges="orientation"
@@ -20,5 +20,5 @@
android:configChanges="keyboard|keyboardHidden|orientation"/> android:configChanges="keyboard|keyboardHidden|orientation"/>
</application> </application>
<uses-sdk android:minSdkVersion="8" /> <uses-sdk android:minSdkVersion="9" />
</manifest> </manifest>

View File

@@ -8,4 +8,4 @@
# project structure. # project structure.
# Project target. # Project target.
target=android-8 target=android-9

View File

@@ -31,7 +31,7 @@ LOCAL_SRC_FILES := $(SDL_PATH)/src/main/android/SDL_android_main.cpp \
$(MTG_PATH)/src/ActionElement.cpp \ $(MTG_PATH)/src/ActionElement.cpp \
$(MTG_PATH)/src/ActionLayer.cpp \ $(MTG_PATH)/src/ActionLayer.cpp \
$(MTG_PATH)/src/ActionStack.cpp \ $(MTG_PATH)/src/ActionStack.cpp \
$(MTG_PATH)/src/AIHints.cpp \ $(MTG_PATH)/src/AIHints.cpp \
$(MTG_PATH)/src/AIMomirPlayer.cpp \ $(MTG_PATH)/src/AIMomirPlayer.cpp \
$(MTG_PATH)/src/AIPlayer.cpp \ $(MTG_PATH)/src/AIPlayer.cpp \
$(MTG_PATH)/src/AIStats.cpp \ $(MTG_PATH)/src/AIStats.cpp \
@@ -81,11 +81,11 @@ LOCAL_SRC_FILES := $(SDL_PATH)/src/main/android/SDL_android_main.cpp \
$(MTG_PATH)/src/GuiPhaseBar.cpp \ $(MTG_PATH)/src/GuiPhaseBar.cpp \
$(MTG_PATH)/src/GuiPlay.cpp \ $(MTG_PATH)/src/GuiPlay.cpp \
$(MTG_PATH)/src/GuiStatic.cpp \ $(MTG_PATH)/src/GuiStatic.cpp \
$(MTG_PATH)/src/IconButton.cpp \ $(MTG_PATH)/src/IconButton.cpp \
$(MTG_PATH)/src/ManaCost.cpp \ $(MTG_PATH)/src/ManaCost.cpp \
$(MTG_PATH)/src/ManaCostHybrid.cpp \ $(MTG_PATH)/src/ManaCostHybrid.cpp \
$(MTG_PATH)/src/MenuItem.cpp \ $(MTG_PATH)/src/MenuItem.cpp \
$(MTG_PATH)/src/ModRules.cpp \ $(MTG_PATH)/src/ModRules.cpp \
$(MTG_PATH)/src/MTGAbility.cpp \ $(MTG_PATH)/src/MTGAbility.cpp \
$(MTG_PATH)/src/MTGCard.cpp \ $(MTG_PATH)/src/MTGCard.cpp \
$(MTG_PATH)/src/MTGCardInstance.cpp \ $(MTG_PATH)/src/MTGCardInstance.cpp \
@@ -164,17 +164,17 @@ LOCAL_SRC_FILES := $(SDL_PATH)/src/main/android/SDL_android_main.cpp \
$(JGE_PATH)/src/hge/hgeparticle.cpp \ $(JGE_PATH)/src/hge/hgeparticle.cpp \
$(JGE_PATH)/src/hge/hgerect.cpp \ $(JGE_PATH)/src/hge/hgerect.cpp \
$(JGE_PATH)/src/hge/hgevector.cpp \ $(JGE_PATH)/src/hge/hgevector.cpp \
$(JGE_PATH)/src/zipFS/zfsystem.cpp \ $(JGE_PATH)/src/zipFS/zfsystem.cpp \
$(JGE_PATH)/src/zipFS/ziphdr.cpp \ $(JGE_PATH)/src/zipFS/ziphdr.cpp \
$(JGE_PATH)/src/zipFS/zstream.cpp \ $(JGE_PATH)/src/zipFS/zstream.cpp \
$(JGE_PATH)/src/pc/JSfx.cpp \ $(JGE_PATH)/src/android/JSfx.cpp \
$(JGE_PATH)/src/pc/JGfx.cpp \ $(JGE_PATH)/src/pc/JGfx.cpp \
$(JGE_PATH)/src/JNetwork.cpp \ $(JGE_PATH)/src/JNetwork.cpp \
$(JGE_PATH)/src/pc/JSocket.cpp \ $(JGE_PATH)/src/pc/JSocket.cpp \
$(BOOST_PATH)/lib/pthread/thread.cpp \ $(BOOST_PATH)/lib/pthread/thread.cpp \
$(BOOST_PATH)/lib/pthread/once.cpp $(BOOST_PATH)/lib/pthread/once.cpp
LOCAL_LDLIBS := -lGLESv1_CM -llog -lz LOCAL_LDLIBS := -lGLESv1_CM -llog -lz -lOpenSLES
include $(BUILD_SHARED_LIBRARY) include $(BUILD_SHARED_LIBRARY)