瀏覽代碼

Audio support for Android using OpenSL ES. Note that multiple features (pitch, 3D audio) are not currently supported by Android.

Chris Culy 14 年之前
父節點
當前提交
7e796d6fd1

+ 47 - 0
.gitignore

@@ -77,3 +77,50 @@
 /gameplay-samples/sample03-character/Device-Release
 /gameplay-samples/sample03-character/res/shaders
 /gameplay-samples/sample03-character/sample03-character.xcodeproj/xcuserdata
+
+/gameplay-android/obj
+/gameplay-android/NUL
+/gameplay-samples/sample00-mesh/android/src
+/gameplay-samples/sample00-mesh/android/assets
+/gameplay-samples/sample00-mesh/android/bin
+/gameplay-samples/sample00-mesh/android/gen
+/gameplay-samples/sample00-mesh/android/libs
+/gameplay-samples/sample00-mesh/android/obj
+/gameplay-android/local.properties
+/gameplay-android/proguard.cfg
+/gameplay-android/project.properties
+/gameplay-samples/sample00-mesh/android/NUL
+/gameplay-samples/sample00-mesh/android/local.properties
+/gameplay-samples/sample00-mesh/android/proguard.cfg
+/gameplay-samples/sample00-mesh/android/project.properties
+/gameplay-samples/sample01-longboard/android/NUL
+/gameplay-samples/sample01-longboard/android/src
+/gameplay-samples/sample01-longboard/android/assets
+/gameplay-samples/sample01-longboard/android/bin
+/gameplay-samples/sample01-longboard/android/gen
+/gameplay-samples/sample01-longboard/android/libs
+/gameplay-samples/sample01-longboard/android/obj
+/gameplay-samples/sample01-longboard/android/project.properties
+/gameplay-samples/sample01-longboard/android/local.properties
+/gameplay-samples/sample02-spaceship/android/project.properties
+/gameplay-samples/sample02-spaceship/android/assets
+/gameplay-samples/sample02-spaceship/android/bin
+/gameplay-samples/sample02-spaceship/android/gen
+/gameplay-samples/sample02-spaceship/android/libs
+/gameplay-samples/sample02-spaceship/android/obj
+/gameplay-samples/sample02-spaceship/android/src
+/gameplay-samples/sample02-spaceship/android/proguard.cfg
+/gameplay-samples/sample02-spaceship/android/local.properties
+/gameplay-samples/sample03-character/android/project.properties
+/gameplay-samples/sample03-character/android/proguard.cfg
+/gameplay-samples/sample03-character/android/local.properties
+/gameplay-samples/sample01-longboard/android/proguard.cfg
+/gameplay-samples/sample02-spaceship/android/NUL
+/gameplay-samples/sample01-longboard/android/proguard.cfg
+/gameplay-samples/sample03-character/android/src
+/gameplay-samples/sample03-character/android/assets
+/gameplay-samples/sample03-character/android/bin
+/gameplay-samples/sample03-character/android/gen
+/gameplay-samples/sample03-character/android/libs
+/gameplay-samples/sample03-character/android/obj
+/gameplay-samples/sample03-character/android/NUL

+ 0 - 10
gameplay-android/local.properties

@@ -1,10 +0,0 @@
-# This file is automatically generated by Android Tools.
-# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
-#
-# This file must *NOT* be checked in Version Control Systems,
-# as it contains information specific to your local configuration.
-
-# location of the SDK. This is only used by Ant
-# For customization when using a Version Control System, please read the
-# header note.
-sdk.dir=C:\\Android\\android-sdk

+ 0 - 40
gameplay-android/proguard.cfg

@@ -1,40 +0,0 @@
--optimizationpasses 5
--dontusemixedcaseclassnames
--dontskipnonpubliclibraryclasses
--dontpreverify
--verbose
--optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
-
--keep public class * extends android.app.Activity
--keep public class * extends android.app.Application
--keep public class * extends android.app.Service
--keep public class * extends android.content.BroadcastReceiver
--keep public class * extends android.content.ContentProvider
--keep public class * extends android.app.backup.BackupAgentHelper
--keep public class * extends android.preference.Preference
--keep public class com.android.vending.licensing.ILicensingService
-
--keepclasseswithmembernames class * {
-    native <methods>;
-}
-
--keepclasseswithmembers class * {
-    public <init>(android.content.Context, android.util.AttributeSet);
-}
-
--keepclasseswithmembers class * {
-    public <init>(android.content.Context, android.util.AttributeSet, int);
-}
-
--keepclassmembers class * extends android.app.Activity {
-   public void *(android.view.View);
-}
-
--keepclassmembers enum * {
-    public static **[] values();
-    public static ** valueOf(java.lang.String);
-}
-
--keep class * implements android.os.Parcelable {
-  public static final android.os.Parcelable$Creator *;
-}

+ 0 - 11
gameplay-android/project.properties

@@ -1,11 +0,0 @@
-# This file is automatically generated by Android Tools.
-# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
-#
-# This file must be checked in Version Control Systems.
-#
-# To customize properties used by the Ant build system use,
-# "ant.properties", and override values to adapt the script to your
-# project structure.
-
-# Project target.
-target=android-15

+ 2 - 0
gameplay/gameplay.vcxproj

@@ -36,6 +36,7 @@
     <ClCompile Include="src\FrameBuffer.cpp" />
     <ClCompile Include="src\Frustum.cpp" />
     <ClCompile Include="src\Game.cpp" />
+    <ClCompile Include="src\gameplay-main-android.cpp" />
     <ClCompile Include="src\gameplay-main-qnx.cpp" />
     <ClCompile Include="src\gameplay-main-win32.cpp" />
     <ClCompile Include="src\Image.cpp" />
@@ -63,6 +64,7 @@
     <ClCompile Include="src\PhysicsSocketConstraint.cpp" />
     <ClCompile Include="src\PhysicsSpringConstraint.cpp" />
     <ClCompile Include="src\Plane.cpp" />
+    <ClCompile Include="src\PlatformAndroid.cpp" />
     <ClCompile Include="src\PlatformQNX.cpp" />
     <ClCompile Include="src\PlatformWin32.cpp" />
     <ClCompile Include="src\Properties.cpp" />

+ 2 - 0
gameplay/gameplay.vcxproj.filters

@@ -70,6 +70,8 @@
     <ClCompile Include="src\VertexAttributeBinding.cpp" />
     <ClCompile Include="src\VertexFormat.cpp" />
     <ClCompile Include="src\Viewport.cpp" />
+    <ClCompile Include="src\gameplay-main-android.cpp" />
+    <ClCompile Include="src\PlatformAndroid.cpp" />
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="src\Animation.h" />

+ 65 - 1
gameplay/src/AudioBuffer.cpp

@@ -2,24 +2,36 @@
 #include "AudioBuffer.h"
 #include "FileSystem.h"
 
+#ifdef __ANDROID__
+extern AAssetManager* __assetManager;
+#endif
+
 namespace gameplay
 {
 
 // Audio buffer cache
 static std::vector<AudioBuffer*> __buffers;
 
+#ifndef __ANDROID__
 AudioBuffer::AudioBuffer(const char* path, ALuint buffer)
     : _filePath(path), _alBuffer(buffer)
 {
 }
+#else
+AudioBuffer::AudioBuffer(const char* path) : _filePath(path)
+{
+}
+#endif
 
 AudioBuffer::~AudioBuffer()
 {
+#ifndef __ANDROID__
     if (_alBuffer)
     {
         alDeleteBuffers(1, &_alBuffer);
         _alBuffer = 0;
     }
+#endif
 }
 
 AudioBuffer* AudioBuffer::create(const char* path)
@@ -39,6 +51,7 @@ AudioBuffer* AudioBuffer::create(const char* path)
         }
     }
 
+#ifndef __ANDROID__
     ALuint alBuffer;
     ALCenum al_error;
 
@@ -106,8 +119,58 @@ cleanup:
     if (alBuffer)
         alDeleteBuffers(1, &alBuffer);
     return NULL;
+#else
+    // Get the file header in order to determine the type.
+    AAsset* asset = AAssetManager_open(__assetManager, path, AASSET_MODE_RANDOM);
+    char header[12];
+    if (AAsset_read(asset, header, 12) != 12)
+    {
+        LOG_ERROR_VARG("Invalid audio buffer file: %s", path);
+        return NULL;
+    }
+
+    // Get the file descriptor for the audio file.
+    off_t start, length;
+    int fd = AAsset_openFileDescriptor(asset, &start, &length);
+    if (fd < 0)
+    {
+        LOG_ERROR_VARG("Failed to open file descriptor for asset: %s", path);
+        return NULL;
+    }
+    AAsset_close(asset);
+    SLDataLocator_AndroidFD data = {SL_DATALOCATOR_ANDROIDFD, fd, start, length};
+
+    // Set the appropriate mime type information.
+    SLDataFormat_MIME mime;
+    mime.formatType = SL_DATAFORMAT_MIME;
+    std::string pathStr = path;
+    if (memcmp(header, "RIFF", 4) == 0)
+    {
+        mime.mimeType = (SLchar*)"audio/x-wav";
+        mime.containerType = SL_CONTAINERTYPE_WAV;
+    }
+    else if (memcmp(header, "OggS", 4) == 0)
+    {
+        mime.mimeType = (SLchar*)"application/ogg";
+        mime.containerType = SL_CONTAINERTYPE_OGG;
+    }
+    else
+    {
+        LOG_ERROR_VARG("Unsupported audio file: %s", path);
+    }
+
+    buffer = new AudioBuffer(path);
+    buffer->_data = data;
+    buffer->_mime = mime;
+
+    // Add the buffer to the cache.
+    __buffers.push_back(buffer);
+
+    return buffer;
+#endif
 }
-    
+
+#ifndef __ANDROID__
 bool AudioBuffer::loadWav(FILE* file, ALuint buffer)
 {
     unsigned char stream[12];
@@ -265,5 +328,6 @@ bool AudioBuffer::loadOgg(FILE* file, ALuint buffer)
 
     return true;
 }
+#endif
 
 }

+ 14 - 1
gameplay/src/AudioBuffer.h

@@ -18,11 +18,17 @@ class AudioBuffer : public Ref
     friend class AudioSource;
 
 private:
-
+#ifndef __ANDROID__
     /**
      * Constructor.
      */
     AudioBuffer(const char* path, ALuint buffer);
+#else
+    /**
+     * Constructor.
+     */
+    AudioBuffer(const char* path);
+#endif
 
     /**
      * Destructor.
@@ -38,12 +44,19 @@ private:
      */
     static AudioBuffer* create(const char* path);
     
+#ifndef __ANDROID__
     static bool loadWav(FILE* file, ALuint buffer);
     
     static bool loadOgg(FILE* file, ALuint buffer);
+#endif
 
     std::string _filePath;
+#ifndef __ANDROID__
     ALuint _alBuffer;
+#else
+    SLDataLocator_AndroidFD _data;
+    SLDataFormat_MIME _mime;
+#endif
 };
 
 }

+ 138 - 1
gameplay/src/AudioController.cpp

@@ -10,17 +10,27 @@ namespace gameplay
 
 std::list<AudioSource*> AudioController::_playingSources;
 
+
+#ifndef __ANDROID__
 AudioController::AudioController() 
     : _alcDevice(NULL), _alcContext(NULL)
 {
 }
+#else
+AudioController::AudioController() 
+    : _engineObject(NULL), _engineEngine(NULL), _outputMixObject(NULL), _listenerObject(NULL),
+    _listenerDoppler(NULL), _listenerLocation(NULL)
+{
+}
+#endif
 
 AudioController::~AudioController()
 {
 }
 
 void AudioController::initialize()
-{    
+{
+#ifndef __ANDROID__
     _alcDevice = alcOpenDevice (NULL);
     if (!_alcDevice)
     {
@@ -43,10 +53,52 @@ void AudioController::initialize()
     {
         LOG_ERROR_VARG("AudioController::initialize() error. Unable to make OpenAL context current. Error: %d\n", alcErr);
     }
+#else
+    // Create the engine.
+    SLresult result = slCreateEngine(&_engineObject, 0, NULL, 0, NULL, NULL);
+    if (result != SL_RESULT_SUCCESS)
+    {
+        LOG_ERROR("AudioController::initialize() error. Unable to create OpenSL engine.");
+        return;
+    }
+
+    // Realize the engine.
+    result = (*_engineObject)->Realize(_engineObject, SL_BOOLEAN_FALSE);
+    if (result != SL_RESULT_SUCCESS)
+    {
+        LOG_ERROR("AudioController::initialize() error. Unable to realize OpenSL engine.");
+        return;
+    }
+
+    // Get the engine interface in order to create other objects later on.
+    result = (*_engineObject)->GetInterface(_engineObject, SL_IID_ENGINE, &_engineEngine);
+    if (result != SL_RESULT_SUCCESS)
+    {
+        LOG_ERROR("AudioController::initialize() error. Unable to retrieve OpenSL engine interface.");
+        return;
+    }
+
+    // Create the output mix.
+    result = (*_engineEngine)->CreateOutputMix(_engineEngine, &_outputMixObject, 0, NULL, NULL);
+    if (result != SL_RESULT_SUCCESS)
+    {
+        LOG_ERROR("AudioController::initialize() error. Unable to create OpenSL output mix.");
+        return;
+    }
+
+    // Realize the output mix.
+    result = (*_outputMixObject)->Realize(_outputMixObject, SL_BOOLEAN_FALSE);
+    if (result != SL_RESULT_SUCCESS)
+    {
+        LOG_ERROR("AudioController::initialize() error. Unable to realize OpenSL output mix.");
+        return;
+    }
+#endif
 }
 
 void AudioController::finalize()
 {
+#ifndef __ANDROID__
     alcMakeContextCurrent(NULL);
     if (_alcContext)
     {
@@ -58,6 +110,20 @@ void AudioController::finalize()
         alcCloseDevice(_alcDevice);
         _alcDevice = NULL;
     }
+#else
+    if (_outputMixObject != NULL)
+    {
+        (*_outputMixObject)->Destroy(_outputMixObject);
+        _outputMixObject = NULL;
+    }
+
+    if (_engineObject != NULL)
+    {
+        (*_engineObject)->Destroy(_engineObject);
+        _engineObject = NULL;
+        _engineEngine = NULL;
+    }
+#endif
 }
 
 void AudioController::pause()
@@ -99,10 +165,81 @@ void AudioController::update(long elapsedTime)
     AudioListener* listener = AudioListener::getInstance();
     if (listener)
     {
+#ifndef __ANDROID__
         alListenerf(AL_GAIN, listener->getGain());
         alListenerfv(AL_ORIENTATION, (ALfloat*)&listener->getOrientationForward());
         alListenerfv(AL_VELOCITY, (ALfloat*)&listener->getVelocity());
         alListenerfv(AL_POSITION, (ALfloat*)&listener->getPosition());
+#else
+        if (!_listenerObject)
+        {
+            const SLInterfaceID interfaces[3] = {SL_IID_3DDOPPLER, SL_IID_3DLOCATION};
+            const SLboolean required[3] = {SL_BOOLEAN_FALSE, SL_BOOLEAN_FALSE};
+            SLresult result = (*_engineEngine)->CreateListener(_engineEngine, &_listenerObject, 2, interfaces, required);
+            if (result != SL_RESULT_SUCCESS)
+            {
+                WARN("AudioController: failed to create listener.");
+                return;
+            }
+
+            result = (*_listenerObject)->Realize(_listenerObject, SL_BOOLEAN_FALSE);
+            if (result != SL_RESULT_SUCCESS)
+            {
+                WARN("AudioController: failed to realize listener.");
+                return;
+            }
+
+            // Get the doppler interface in order to set the listener's velocity.
+            result = (*_listenerObject)->GetInterface(_listenerObject, SL_IID_3DDOPPLER, &_listenerDoppler);
+            if (result != SL_RESULT_SUCCESS)
+            {
+                WARN("AudioController: Unable to retrieve listener doppler interface.");
+                return;
+            }
+
+            // Get the location interface in order to set the listener's position and orientation.
+            result = (*_listenerObject)->GetInterface(_listenerObject, SL_IID_3DLOCATION, &_listenerLocation);
+            if (result != SL_RESULT_SUCCESS)
+            {
+                WARN("AudioController: Unable to retrieve listener location interface.");
+                return;
+            }
+        }
+        
+        SLVec3D f;
+        f.x = listener->getOrientationForward().x;
+        f.y = listener->getOrientationForward().y;
+        f.z = listener->getOrientationForward().z;
+        SLVec3D a;
+        a.x = listener->getOrientationUp().x;
+        a.y = listener->getOrientationUp().y;
+        a.z = listener->getOrientationUp().z;
+        SLresult result = (*_listenerLocation)->SetOrientationVectors(_listenerLocation, &f, &a);
+        if (result != SL_RESULT_SUCCESS)
+        {
+            WARN("AudioController: Unable to set listener orientation.");
+        }
+
+        SLVec3D p;
+        p.x = listener->getPosition().x;
+        p.y = listener->getPosition().y;
+        p.z = listener->getPosition().z;
+        result = (*_listenerLocation)->SetLocationCartesian(_listenerLocation, &p);
+        if (result != SL_RESULT_SUCCESS)
+        {
+            WARN("AudioController: Unable to set listener location.");
+        }
+
+        SLVec3D v;
+        v.x = listener->getVelocity().x;
+        v.y = listener->getVelocity().y;
+        v.z = listener->getVelocity().z;
+        result = (*_listenerDoppler)->SetVelocityCartesian(_listenerDoppler, &v);
+        if (result != SL_RESULT_SUCCESS)
+        {
+            WARN("AudioController: Unable to set listener velocity.");
+        }
+#endif
     }
 }
 

+ 9 - 0
gameplay/src/AudioController.h

@@ -54,8 +54,17 @@ private:
      */
     void update(long elapsedTime);
 
+#ifndef __ANDROID__
     ALCdevice* _alcDevice;
     ALCcontext* _alcContext;
+#else
+    SLObjectItf _engineObject;
+    SLEngineItf _engineEngine;
+    SLObjectItf _outputMixObject;
+    SLObjectItf _listenerObject;
+    SL3DDopplerItf _listenerDoppler;
+    SL3DLocationItf _listenerLocation;
+#endif
     static std::list<AudioSource*> _playingSources;     // List of currently running sources.
 };
 

+ 238 - 3
gameplay/src/AudioSource.cpp

@@ -1,11 +1,15 @@
 #include "Base.h"
 #include "Node.h"
 #include "AudioBuffer.h"
+#include "AudioController.h"
 #include "AudioSource.h"
+#include "Game.h"
 
 namespace gameplay
 {
 
+
+#ifndef __ANDROID__
 AudioSource::AudioSource(AudioBuffer* buffer, ALuint source) 
     : _alSource(source), _buffer(buffer), _looped(true), _gain(1.0f), _pitch(1.0f), _node(NULL)
 {
@@ -15,14 +19,86 @@ AudioSource::AudioSource(AudioBuffer* buffer, ALuint source)
     alSourcef(_alSource, AL_GAIN, _gain);
     alSourcefv(_alSource, AL_VELOCITY, (const ALfloat*)&_velocity);
 }
+#else
+AudioSource::AudioSource(AudioBuffer* buffer, const SLObjectItf& player)
+    : _playerObject(player), _playerDoppler(NULL), _playerLocation(NULL), _playerPlay(NULL), _playerPitch(NULL),
+    _playerSeek(NULL), _playerVolume(NULL), _buffer(buffer), _looped(true), _gain(1.0f), _pitch(1.0f), _node(NULL)
+{
+    // Get the different interfaces for the OpenSL audio player that we need.
+    SLresult result = (*_playerObject)->GetInterface(_playerObject, SL_IID_3DDOPPLER, &_playerDoppler);
+    if(result != SL_RESULT_SUCCESS)
+    {
+        WARN("AudioSource::AudioSource() - Failed to get 3D doppler interface for OpenSL audio player.");
+    }
+    
+    result = (*_playerObject)->GetInterface(_playerObject, SL_IID_3DLOCATION, &_playerLocation);
+    if(result != SL_RESULT_SUCCESS)
+    {
+        WARN("AudioSource::AudioSource() - Failed to get 3D location interface for OpenSL audio player.");
+    }
+
+    result = (*_playerObject)->GetInterface(_playerObject, SL_IID_PLAY, &_playerPlay);
+    if(result != SL_RESULT_SUCCESS)
+    {
+        WARN("AudioSource::AudioSource() - Failed to get play interface for OpenSL audio player.");
+    }
+
+    result = (*_playerObject)->GetInterface(_playerObject, SL_IID_PITCH, &_playerPitch);
+    if(result != SL_RESULT_SUCCESS)
+    {
+        WARN("AudioSource::AudioSource() - Failed to get rate pitch interface for OpenSL audio player.");
+    }
+
+    result = (*_playerObject)->GetInterface(_playerObject, SL_IID_SEEK, &_playerSeek);
+    if(result != SL_RESULT_SUCCESS)
+    {
+        WARN("AudioSource::AudioSource() - Failed to get seek interface for OpenSL audio player.");
+    }
+
+    result = (*_playerObject)->GetInterface(_playerObject, SL_IID_VOLUME, &_playerVolume);
+    if(result != SL_RESULT_SUCCESS)
+    {
+        WARN("AudioSource::AudioSource() - Failed to get volume interface for OpenSL audio player.");
+    }
+
+    // Get the max volume level (used to convert from our API's parameter to OpenSL's expected units).
+    if (_playerVolume)
+    {
+        result = (*_playerVolume)->GetMaxVolumeLevel(_playerVolume, &_maxVolume);
+        if (result != SL_RESULT_SUCCESS)
+        {
+            WARN("AudioSource::AudioSource() - Failed to get the max volume level for OpenSL audio player (needed for parameter conversion).");
+        }
+    }
+
+    setLooped(_looped);
+    setPitch(_pitch);
+    setGain(_gain);
+    setVelocity(_velocity);
+}
+#endif
 
 AudioSource::~AudioSource()
 {
+#ifndef __ANDROID__
     if (_alSource)
     {
         alDeleteSources(1, &_alSource);
         _alSource = 0;
     }
+#else
+    if (_playerObject)
+    {
+        (*_playerObject)->Destroy(_playerObject);
+        _playerObject = NULL;
+        _playerDoppler = NULL;
+        _playerLocation = NULL;
+        _playerPlay = NULL;
+        _playerPitch = NULL;
+        _playerSeek = NULL;
+        _playerVolume = NULL;
+    }
+#endif
 
     SAFE_RELEASE(_buffer);
 }
@@ -52,17 +128,44 @@ AudioSource* AudioSource::create(const char* path)
     if (buffer == NULL)
         return NULL;
 
+#ifndef __ANDROID__
     // Load the audio source.
-    ALuint alSource;
+    ALuint alSource = 0;
+
     alGenSources(1, &alSource);
     if (alGetError() != AL_NO_ERROR)
     {
         SAFE_RELEASE(buffer);
-        LOG_ERROR("AudioSource::createAudioSource Error generating audio source.");
+        LOG_ERROR("AudioSource::createAudioSource - Error generating audio source.");
         return NULL;
     }
-
+    
     return new AudioSource(buffer, alSource);
+#else
+    AudioController* audioController = Game::getInstance()->getAudioController();
+    SLDataLocator_OutputMix locator = {SL_DATALOCATOR_OUTPUTMIX, audioController->_outputMixObject};
+
+    SLDataSource dataSource = {&buffer->_data, &buffer->_mime};
+    SLDataSink dataSink = {&locator, NULL};
+
+    SLObjectItf player;
+    const SLInterfaceID interfaces[] = {SL_IID_3DDOPPLER, SL_IID_3DLOCATION, SL_IID_PLAY, SL_IID_PITCH, SL_IID_SEEK, SL_IID_VOLUME};
+    const SLboolean required[] = {SL_BOOLEAN_FALSE, SL_BOOLEAN_FALSE, SL_BOOLEAN_FALSE, SL_BOOLEAN_FALSE, SL_BOOLEAN_FALSE, SL_BOOLEAN_FALSE};
+    SLresult result = (*audioController->_engineEngine)->CreateAudioPlayer(audioController->_engineEngine, &player, &dataSource, &dataSink, 6, interfaces, required);
+    if (result != SL_RESULT_SUCCESS)
+    {
+        WARN("AudioSource::create - Failed to create OpenSL audio player.");
+        return NULL;
+    }
+
+    result = (*player)->Realize(player, SL_BOOLEAN_FALSE);
+    if(result != SL_RESULT_SUCCESS)
+    {
+        WARN("AudioSource::create - Failed to realize OpenSL audio player.");
+    }
+
+    return new AudioSource(buffer, player);
+#endif
 }
 
 AudioSource* AudioSource::create(Properties* properties)
@@ -114,6 +217,7 @@ AudioSource* AudioSource::create(Properties* properties)
 
 AudioSource::State AudioSource::getState() const
 {
+#ifndef __ANDROID__
     ALint state;
     alGetSourcei(_alSource, AL_SOURCE_STATE, &state);
 
@@ -128,18 +232,63 @@ AudioSource::State AudioSource::getState() const
         default:         
             return INITIAL;
     }
+#else
+    if (_playerPlay != NULL)
+    {
+        SLuint32 state;
+        SLresult result = (*_playerPlay)->GetPlayState(_playerPlay, &state);
+        if (result != SL_RESULT_SUCCESS)
+        {
+            WARN("AudioSource::getState() failed to get player state.");
+        }
+
+        switch (state)
+        {
+            case SL_PLAYSTATE_PLAYING:
+                return PLAYING;
+            case SL_PLAYSTATE_PAUSED:
+                return PAUSED;
+            case SL_PLAYSTATE_STOPPED:
+                return STOPPED;
+            default:
+                return INITIAL;
+        }
+    }
+#endif
 
     return INITIAL;
 }
 
 void AudioSource::play()
 {
+#ifndef __ANDROID__
     alSourcePlay(_alSource);
+#else
+    if (_playerPlay != NULL)
+    {
+        SLresult result = (*_playerPlay)->SetPlayState(_playerPlay, SL_PLAYSTATE_PLAYING);
+        if (result != SL_RESULT_SUCCESS)
+        {
+            WARN("AudioSource::play() failed to set player state.");
+        }
+    }
+#endif
 }
 
 void AudioSource::pause()
 {
+#ifndef __ANDROID__
     alSourcePause(_alSource);
+#else
+    if (_playerPlay != NULL)
+    {
+        SLresult result = (*_playerPlay)->SetPlayState(_playerPlay, SL_PLAYSTATE_PAUSED);
+        if (result != SL_RESULT_SUCCESS)
+        {
+            WARN("AudioSource::pause() failed to set player state.");
+        }
+    }
+#endif
 }
 
 void AudioSource::resume()
@@ -152,12 +301,34 @@ void AudioSource::resume()
 
 void AudioSource::stop()
 {
+#ifndef __ANDROID__
     alSourceStop(_alSource);
+#else
+    if (_playerPlay != NULL)
+    {
+        SLresult result = (*_playerPlay)->SetPlayState(_playerPlay, SL_PLAYSTATE_STOPPED);
+        if (result != SL_RESULT_SUCCESS)
+        {
+            WARN("AudioSource::stop() failed to set player state.");
+        }
+    }
+#endif 
 }
 
 void AudioSource::rewind()
 {
+#ifndef __ANDROID__
     alSourceRewind(_alSource);
+#else
+    if (_playerPlay != NULL)
+    {
+        SLresult result = (*_playerPlay)->SetMarkerPosition(_playerPlay, 0);
+        if (result != SL_RESULT_SUCCESS)
+        {
+            WARN("AudioSource::rewind() failed to set player marker position.");
+        }
+    }
+#endif
 }
 
 bool AudioSource::isLooped() const
@@ -167,6 +338,7 @@ bool AudioSource::isLooped() const
 
 void AudioSource::setLooped(bool looped)
 {
+#ifndef __ANDROID__
      // Clear error state.
     alGetError();
     alSourcei(_alSource, AL_LOOPING, (looped) ? AL_TRUE : AL_FALSE);
@@ -176,6 +348,16 @@ void AudioSource::setLooped(bool looped)
     {
         LOG_ERROR_VARG("AudioSource::setLooped Error: %d", error);
     }
+#else
+    if (_playerSeek)
+    {
+        SLresult result = (*_playerSeek)->SetLoop(_playerSeek, looped, 0, SL_TIME_UNKNOWN);
+        if (result != SL_RESULT_SUCCESS)
+        {
+            WARN("AudioSource::setLooped() failed.");
+        }
+    }
+#endif
 
     _looped = looped;
 }
@@ -187,7 +369,19 @@ float AudioSource::getGain() const
 
 void AudioSource::setGain(float gain)
 {
+#ifndef __ANDROID__
     alSourcef(_alSource, AL_GAIN, gain);
+#else
+    if (_playerVolume)
+    {
+        SLmillibel volume = gain * (_maxVolume - SL_MILLIBEL_MIN) + SL_MILLIBEL_MIN;
+        SLresult result = (*_playerVolume)->SetVolumeLevel(_playerVolume, volume);
+        if (result != SL_RESULT_SUCCESS)
+        {
+            WARN("AudioSource::setGain() failed to set player gain.");
+        }
+    }
+#endif
     _gain = gain;
 }
 
@@ -198,7 +392,18 @@ float AudioSource::getPitch() const
 
 void AudioSource::setPitch(float pitch)
 {
+#ifndef __ANDROID__
     alSourcef(_alSource, AL_PITCH, pitch);
+#else
+    if (_playerPitch)
+    {
+        SLresult result = (*_playerPitch)->SetPitch(_playerPitch, (SLpermille)(pitch * 1000));
+        if (result != SL_RESULT_SUCCESS)
+        {
+            WARN("AudioSource::setPitch() failed to set player pitch.");
+        }
+    }
+#endif
     _pitch = pitch;
 }
 
@@ -209,7 +414,22 @@ const Vector3& AudioSource::getVelocity() const
 
 void AudioSource::setVelocity(const Vector3& velocity)
 {
+#ifndef __ANDROID__
     alSourcefv(_alSource, AL_VELOCITY, (ALfloat*)&velocity);
+#else
+    if (_playerDoppler)
+    {
+        SLVec3D v;
+        v.x = velocity.x;
+        v.y = velocity.y;
+        v.z = velocity.z;
+        SLresult result = (*_playerDoppler)->SetVelocityCartesian(_playerDoppler, &v);
+        if (result != SL_RESULT_SUCCESS)
+        {
+            WARN("AudioSource::setVelocity - failed to set velocity.");
+        }
+    }
+#endif
     _velocity = velocity;
 }
 
@@ -240,7 +460,22 @@ void AudioSource::setNode(Node* node)
 
 void AudioSource::transformChanged(Transform* transform, long cookie)
 {
+#ifndef __ANDROID__
     alSourcefv(_alSource, AL_POSITION, (const ALfloat*)&transform->getTranslation());
+#else
+    if (_playerLocation)
+    {
+        SLVec3D position;
+        position.x = transform->getTranslationX();
+        position.y = transform->getTranslationY();
+        position.z = transform->getTranslationZ();
+        SLresult result = (*_playerLocation)->SetLocationCartesian(_playerLocation, &position);
+        if (result != SL_RESULT_SUCCESS)
+        {
+            WARN("AudioSource::transformChanged - failed to update location.");
+        }
+    }
+#endif
 }
 
 }

+ 21 - 0
gameplay/src/AudioSource.h

@@ -146,11 +146,21 @@ public:
 
 private:
 
+#ifndef __ANDROID__
     /**
      * Constructor that takes an AudioBuffer.
      */
     AudioSource(AudioBuffer* buffer, ALuint source);
 
+#else
+
+    /**
+     * Constructor that takes an AudioBuffer.
+     */
+    AudioSource(AudioBuffer* buffer, const SLObjectItf& player);
+#endif
+
+
     /**
      * Destructor.
      */
@@ -166,7 +176,18 @@ private:
      */
     void transformChanged(Transform* transform, long cookie);
 
+#ifndef __ANDROID__
     ALuint _alSource;
+#else
+    SLObjectItf _playerObject;
+    SL3DDopplerItf _playerDoppler;
+    SL3DLocationItf _playerLocation;
+    SLPlayItf _playerPlay;
+    SLPitchItf _playerPitch;
+    SLSeekItf _playerSeek;
+    SLVolumeItf _playerVolume;
+    SLmillibel _maxVolume;
+#endif
     AudioBuffer* _buffer;
     bool _looped;
     float _gain;

+ 9 - 2
gameplay/src/Base.h

@@ -154,8 +154,13 @@ extern void printError(const char* format, ...);
     #define NOMINMAX
 #endif
 
-// Audio (OpenAL)
-#if defined (__QNX__) || defined(__ANDROID__)
+// Audio (OpenAL, OpenSL, OggVorbis)
+#ifdef __ANDROID__
+#include <SLES/OpenSLES.h>
+#include <SLES/OpenSLES_Android.h>
+#else
+
+#ifdef __QNX__
 #include <AL/al.h>
 #include <AL/alc.h>
 #elif WIN32
@@ -165,7 +170,9 @@ extern void printError(const char* format, ...);
 #include <OpenAL/al.h>
 #include <OpenAL/alc.h>
 #endif
+
 #include <vorbis/vorbisfile.h>
+#endif
 
 // Screen/Window
 #define WINDOW_WIDTH        1024

+ 0 - 10
gameplay/src/Game.cpp

@@ -90,10 +90,8 @@ bool Game::startup()
     _animationController = new AnimationController();
     _animationController->initialize();
 
-    #if 0
     _audioController = new AudioController();
     _audioController->initialize();
-    #endif
 
     _physicsController = new PhysicsController();
     _physicsController->initialize();
@@ -113,10 +111,8 @@ void Game::shutdown()
         _animationController->finalize();
         SAFE_DELETE(_animationController);
 
-        #if 0
         _audioController->finalize();
         SAFE_DELETE(_audioController);
-        #endif
 
         _physicsController->finalize();
         SAFE_DELETE(_physicsController);
@@ -134,9 +130,7 @@ void Game::pause()
         _state = PAUSED;
         _pausedTimeLast = Platform::getAbsoluteTime();
         _animationController->pause();
-        #if 0
         _audioController->pause();
-        #endif
         _physicsController->pause();
     }
 }
@@ -148,9 +142,7 @@ void Game::resume()
         _state = RUNNING;
         _pausedTimeTotal += Platform::getAbsoluteTime() - _pausedTimeLast;
         _animationController->resume();
-        #if 0
         _audioController->resume();
-        #endif
         _physicsController->resume();
     }
 }
@@ -190,9 +182,7 @@ void Game::frame()
     update(elapsedTime);
 
     // Audio Rendering.
-    #if 0
     _audioController->update(elapsedTime);
-    #endif
     // Graphics Rendering.
     render(elapsedTime);
 

+ 2 - 1
gameplay/src/PhysicsRigidBody.h

@@ -35,7 +35,8 @@ public:
     {
         SHAPE_BOX,
         SHAPE_SPHERE,
-        SHAPE_NONE
+        SHAPE_NONE,
+        SHAPE_MAX = 10
     };
 
     /** 

+ 0 - 7
gameplay/src/PlatformAndroid.cpp

@@ -403,8 +403,6 @@ Platform* Platform::create(Game* game)
         checkErrorEGL("eglCreateWindowSurface");
         goto error;
     }
-
-    LOGI("Platform::create - 3");
     
     if (eglMakeCurrent(__eglDisplay, __eglSurface, __eglSurface, __eglContext) != EGL_TRUE)
     {
@@ -415,8 +413,6 @@ Platform* Platform::create(Game* game)
     eglQuerySurface(__eglDisplay, __eglSurface, EGL_WIDTH, &__width);
     eglQuerySurface(__eglDisplay, __eglSurface, EGL_HEIGHT, &__height);
     
-    WARN_VARG("Platform::create - WIDTH: %d HEIGHT = %d" , __width, __height);
-    
     // Set vsync.
     eglSwapInterval(__eglDisplay, WINDOW_VSYNC ? 1 : 0);
 
@@ -425,8 +421,6 @@ Platform* Platform::create(Game* game)
 
     if (strstr(__glExtensions, "GL_OES_vertex_array_object") || strstr(__glExtensions, "GL_ARB_vertex_array_object"))
     {
-        WARN("Platform::create - VAOs supported");
-        
         // Disable VAO extension for now.
         glBindVertexArray = (PFNGLBINDVERTEXARRAYOESPROC)eglGetProcAddress("glBindVertexArrayOES");
         glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSOESPROC)eglGetProcAddress("glDeleteVertexArrays");
@@ -467,7 +461,6 @@ int Platform::enterMessagePump()
             clock_gettime(CLOCK_REALTIME, &__timespec);
             __timeStart = timespec2millis(&__timespec);
             __timeAbsolute = 0L;
-            WARN_VARG("Platform::enterMessagePump() - WIDTH: %d HEIGHT = %d" , __width, __height);
             _game->run(__width, __height);
             
             state = 1;