summaryrefslogtreecommitdiff
path: root/Source/Core/AudioCommon/Src/OpenSLESStream.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/Core/AudioCommon/Src/OpenSLESStream.cpp')
-rw-r--r--Source/Core/AudioCommon/Src/OpenSLESStream.cpp145
1 files changed, 145 insertions, 0 deletions
diff --git a/Source/Core/AudioCommon/Src/OpenSLESStream.cpp b/Source/Core/AudioCommon/Src/OpenSLESStream.cpp
new file mode 100644
index 0000000000..b0913a1895
--- /dev/null
+++ b/Source/Core/AudioCommon/Src/OpenSLESStream.cpp
@@ -0,0 +1,145 @@
+// Copyright (C) 2003 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+#ifdef ANDROID
+#include "Common.h"
+#include <assert.h>
+#include "OpenSLESStream.h"
+
+#include <SLES/OpenSLES.h>
+#include <SLES/OpenSLES_Android.h>
+
+// engine interfaces
+static SLObjectItf engineObject;
+static SLEngineItf engineEngine;
+static SLObjectItf outputMixObject;
+
+// buffer queue player interfaces
+static SLObjectItf bqPlayerObject = NULL;
+static SLPlayItf bqPlayerPlay;
+static SLAndroidSimpleBufferQueueItf bqPlayerBufferQueue;
+static SLMuteSoloItf bqPlayerMuteSolo;
+static SLVolumeItf bqPlayerVolume;
+static CMixer *g_mixer;
+#define BUFFER_SIZE 512
+#define BUFFER_SIZE_IN_SAMPLES (BUFFER_SIZE / 2)
+
+// Double buffering.
+static short buffer[2][BUFFER_SIZE];
+static int curBuffer = 0;
+
+static void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context) {
+ assert(bq == bqPlayerBufferQueue);
+ assert(NULL == context);
+
+ short *nextBuffer = buffer[curBuffer];
+ int nextSize = sizeof(buffer[0]);
+
+ SLresult result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, nextBuffer, nextSize);
+
+ // Comment from sample code:
+ // the most likely other result is SL_RESULT_BUFFER_INSUFFICIENT,
+ // which for this code example would indicate a programming error
+ assert(SL_RESULT_SUCCESS == result);
+
+ curBuffer ^= 1; // Switch buffer
+ // Render to the fresh buffer
+ g_mixer->Mix(reinterpret_cast<short *>(buffer[curBuffer]), BUFFER_SIZE_IN_SAMPLES);
+}
+bool OpenSLESStream::Start()
+{
+ SLresult result;
+ // create engine
+ result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL);
+ assert(SL_RESULT_SUCCESS == result);
+ result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
+ assert(SL_RESULT_SUCCESS == result);
+ result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
+ assert(SL_RESULT_SUCCESS == result);
+ result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 0, 0, 0);
+ assert(SL_RESULT_SUCCESS == result);
+ result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE);
+ assert(SL_RESULT_SUCCESS == result);
+
+ SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2};
+ SLDataFormat_PCM format_pcm = {
+ SL_DATAFORMAT_PCM,
+ 2,
+ SL_SAMPLINGRATE_44_1,
+ SL_PCMSAMPLEFORMAT_FIXED_16,
+ SL_PCMSAMPLEFORMAT_FIXED_16,
+ SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT,
+ SL_BYTEORDER_LITTLEENDIAN
+ };
+
+ SLDataSource audioSrc = {&loc_bufq, &format_pcm};
+
+ // 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_BUFFERQUEUE, SL_IID_VOLUME};
+ const SLboolean req[2] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
+ result = (*engineEngine)->CreateAudioPlayer(engineEngine, &bqPlayerObject, &audioSrc, &audioSnk, 2, ids, req);
+ assert(SL_RESULT_SUCCESS == result);
+
+ result = (*bqPlayerObject)->Realize(bqPlayerObject, SL_BOOLEAN_FALSE);
+ assert(SL_RESULT_SUCCESS == result);
+ result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_PLAY, &bqPlayerPlay);
+ assert(SL_RESULT_SUCCESS == result);
+ result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_BUFFERQUEUE,
+ &bqPlayerBufferQueue);
+ assert(SL_RESULT_SUCCESS == result);
+ result = (*bqPlayerBufferQueue)->RegisterCallback(bqPlayerBufferQueue, bqPlayerCallback, NULL);
+ assert(SL_RESULT_SUCCESS == result);
+ result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_PLAYING);
+ assert(SL_RESULT_SUCCESS == result);
+
+ // Render and enqueue a first buffer. (or should we just play the buffer empty?)
+ curBuffer = 0;
+
+ result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, buffer[curBuffer], sizeof(buffer[curBuffer]));
+ if (SL_RESULT_SUCCESS != result) {
+ return false;
+ }
+ curBuffer ^= 1;
+ g_mixer = m_mixer;
+ return true;
+}
+
+void OpenSLESStream::Stop()
+{
+ if (bqPlayerObject != NULL) {
+ (*bqPlayerObject)->Destroy(bqPlayerObject);
+ bqPlayerObject = NULL;
+ bqPlayerPlay = NULL;
+ bqPlayerBufferQueue = NULL;
+ bqPlayerMuteSolo = NULL;
+ bqPlayerVolume = NULL;
+ }
+ if (outputMixObject != NULL) {
+ (*outputMixObject)->Destroy(outputMixObject);
+ outputMixObject = NULL;
+ }
+ if (engineObject != NULL) {
+ (*engineObject)->Destroy(engineObject);
+ engineObject = NULL;
+ engineEngine = NULL;
+ }
+}
+#endif