mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-02-16 04:09:51 +00:00
Make the OpenSL wrapper an object too, to make sure it's always initialized the same.
This commit is contained in:
parent
a453dc8123
commit
3ce8680d9a
@ -23,7 +23,8 @@
|
||||
<RootNamespace>DaSh</RootNamespace>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectName>PPSSPPWindows</ProjectName>
|
||||
<WindowsTargetPlatformVersion></WindowsTargetPlatformVersion>
|
||||
<WindowsTargetPlatformVersion>
|
||||
</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
@ -295,6 +296,18 @@
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\android\jni\native-audio-so.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\android\jni\native_audio.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\android\jni\TestRunner.cpp" />
|
||||
<ClCompile Include="..\ext\glew\glew.c">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
|
||||
@ -426,6 +439,18 @@
|
||||
<ClInclude Include="..\android\jni\app-android.h" />
|
||||
<ClInclude Include="..\android\jni\ArmEmitterTest.h" />
|
||||
<ClInclude Include="..\android\jni\Arm64EmitterTest.h" />
|
||||
<ClInclude Include="..\android\jni\native-audio-so.h">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\android\jni\native_audio.h">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\android\jni\TestRunner.h" />
|
||||
<ClInclude Include="..\ios\ViewController.h" />
|
||||
<ClInclude Include="..\Qt\Debugger\ctrldisasmview.h" />
|
||||
|
@ -195,6 +195,12 @@
|
||||
<ClCompile Include="..\android\jni\app-android.cpp">
|
||||
<Filter>Other Platforms</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\android\jni\native_audio.cpp">
|
||||
<Filter>Other Platforms</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\android\jni\native-audio-so.cpp">
|
||||
<Filter>Other Platforms</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Debugger\CtrlDisAsmView.h">
|
||||
@ -358,6 +364,12 @@
|
||||
<ClInclude Include="..\android\jni\app-android.h">
|
||||
<Filter>Other Platforms</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\android\jni\native_audio.h">
|
||||
<Filter>Other Platforms</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\android\jni\native-audio-so.h">
|
||||
<Filter>Other Platforms</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="icon1.ico">
|
||||
|
@ -13,34 +13,32 @@
|
||||
#include "../base/logging.h"
|
||||
#include "native-audio-so.h"
|
||||
|
||||
// This is kinda ugly, but for simplicity I've left these as globals just like in the sample,
|
||||
// as there's not really any use case for this where we have multiple audio devices yet.
|
||||
AudioContext::AudioContext(AndroidAudioCallback cb, int _FramesPerBuffer, int _SampleRate)
|
||||
: audioCallback(cb), framesPerBuffer(_FramesPerBuffer), sampleRate(_SampleRate) {
|
||||
if (framesPerBuffer == 0)
|
||||
framesPerBuffer = 256;
|
||||
if (framesPerBuffer < 32)
|
||||
framesPerBuffer = 32;
|
||||
if (framesPerBuffer > 4096)
|
||||
framesPerBuffer = 4096;
|
||||
|
||||
// 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;
|
||||
|
||||
// Double buffering.
|
||||
static short *buffer[2];
|
||||
static int curBuffer = 0;
|
||||
static int framesPerBuffer;
|
||||
int sampleRate;
|
||||
|
||||
static AndroidAudioCallback audioCallback;
|
||||
sampleRate = _SampleRate;
|
||||
if (sampleRate != 44100 && sampleRate != 48000) {
|
||||
ELOG("Invalid sample rate %i - choosing 44100", sampleRate);
|
||||
sampleRate = 44100;
|
||||
}
|
||||
}
|
||||
|
||||
// This callback handler is called every time a buffer finishes playing.
|
||||
// The documentation available is very unclear about how to best manage buffers.
|
||||
// I've chosen to this approach: Instantly enqueue a buffer that was rendered to the last time,
|
||||
// and then render the next. Hopefully it's okay to spend time in this callback after having enqueued.
|
||||
static void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context) {
|
||||
void OpenSLContext::bqPlayerCallbackWrap(SLAndroidSimpleBufferQueueItf bq, void *context) {
|
||||
OpenSLContext *ctx = (OpenSLContext *)context;
|
||||
ctx->BqPlayerCallback(bq);
|
||||
}
|
||||
|
||||
void OpenSLContext::BqPlayerCallback(SLAndroidSimpleBufferQueueItf bq) {
|
||||
if (bq != bqPlayerBufferQueue) {
|
||||
ELOG("Wrong bq!");
|
||||
return;
|
||||
@ -66,22 +64,10 @@ static void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context) {
|
||||
}
|
||||
|
||||
// create the engine and output mix objects
|
||||
bool OpenSLWrap_Init(AndroidAudioCallback cb, int _FramesPerBuffer, int _SampleRate) {
|
||||
audioCallback = cb;
|
||||
framesPerBuffer = _FramesPerBuffer;
|
||||
if (framesPerBuffer == 0)
|
||||
framesPerBuffer = 256;
|
||||
if (framesPerBuffer < 32)
|
||||
framesPerBuffer = 32;
|
||||
if (framesPerBuffer > 4096)
|
||||
framesPerBuffer = 4096;
|
||||
|
||||
sampleRate = _SampleRate;
|
||||
if (sampleRate != 44100 && sampleRate != 48000) {
|
||||
ELOG("Invalid sample rate %i - choosing 44100", sampleRate);
|
||||
sampleRate = 44100;
|
||||
}
|
||||
OpenSLContext::OpenSLContext(AndroidAudioCallback cb, int _FramesPerBuffer, int _SampleRate)
|
||||
: AudioContext(cb, _FramesPerBuffer, _SampleRate) {}
|
||||
|
||||
bool OpenSLContext::Init() {
|
||||
SLresult result;
|
||||
// create engine
|
||||
result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL);
|
||||
@ -137,7 +123,7 @@ bool OpenSLWrap_Init(AndroidAudioCallback cb, int _FramesPerBuffer, int _SampleR
|
||||
result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_BUFFERQUEUE,
|
||||
&bqPlayerBufferQueue);
|
||||
assert(SL_RESULT_SUCCESS == result);
|
||||
result = (*bqPlayerBufferQueue)->RegisterCallback(bqPlayerBufferQueue, bqPlayerCallback, NULL);
|
||||
result = (*bqPlayerBufferQueue)->RegisterCallback(bqPlayerBufferQueue, &bqPlayerCallbackWrap, this);
|
||||
assert(SL_RESULT_SUCCESS == result);
|
||||
result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_VOLUME, &bqPlayerVolume);
|
||||
assert(SL_RESULT_SUCCESS == result);
|
||||
@ -160,7 +146,7 @@ bool OpenSLWrap_Init(AndroidAudioCallback cb, int _FramesPerBuffer, int _SampleR
|
||||
}
|
||||
|
||||
// shut down the native audio system
|
||||
void OpenSLWrap_Shutdown() {
|
||||
OpenSLContext::~OpenSLContext() {
|
||||
if (bqPlayerPlay) {
|
||||
ILOG("OpenSLWrap_Shutdown - stopping playback");
|
||||
SLresult result;
|
||||
|
@ -1,6 +1,47 @@
|
||||
#pragma once
|
||||
|
||||
#include <SLES/OpenSLES.h>
|
||||
#include <SLES/OpenSLES_Android.h>
|
||||
|
||||
typedef int (*AndroidAudioCallback)(short *buffer, int num_samples);
|
||||
|
||||
bool OpenSLWrap_Init(AndroidAudioCallback cb, int _FramesPerBuffer, int _SampleRate);
|
||||
void OpenSLWrap_Shutdown();
|
||||
class AudioContext {
|
||||
public:
|
||||
AudioContext(AndroidAudioCallback cb, int _FramesPerBuffer, int _SampleRate);
|
||||
virtual bool Init() { return false; }
|
||||
virtual ~AudioContext() {}
|
||||
|
||||
protected:
|
||||
AndroidAudioCallback audioCallback;
|
||||
|
||||
int framesPerBuffer;
|
||||
int sampleRate;
|
||||
};
|
||||
|
||||
class OpenSLContext : public AudioContext {
|
||||
public:
|
||||
OpenSLContext(AndroidAudioCallback cb, int framesPerBuffer, int sampleRate);
|
||||
|
||||
bool Init() override;
|
||||
~OpenSLContext();
|
||||
|
||||
private:
|
||||
// engine interfaces
|
||||
SLObjectItf engineObject = nullptr;
|
||||
SLEngineItf engineEngine = nullptr;
|
||||
SLObjectItf outputMixObject = nullptr;
|
||||
|
||||
// buffer queue player interfaces
|
||||
SLObjectItf bqPlayerObject = nullptr;
|
||||
SLPlayItf bqPlayerPlay = nullptr;
|
||||
SLAndroidSimpleBufferQueueItf bqPlayerBufferQueue = nullptr;
|
||||
SLMuteSoloItf bqPlayerMuteSolo = nullptr;
|
||||
SLVolumeItf bqPlayerVolume = nullptr;
|
||||
|
||||
// Double buffering.
|
||||
short *buffer[2]{};
|
||||
int curBuffer = 0;
|
||||
|
||||
static void bqPlayerCallbackWrap(SLAndroidSimpleBufferQueueItf bq, void *context);
|
||||
void BqPlayerCallback(SLAndroidSimpleBufferQueueItf bq);
|
||||
};
|
@ -3,17 +3,15 @@
|
||||
#include "android/jni/native-audio-so.h"
|
||||
|
||||
struct AndroidAudioState {
|
||||
void *so;
|
||||
AndroidAudioCallback callback;
|
||||
bool playing;
|
||||
int frames_per_buffer;
|
||||
int sample_rate;
|
||||
AudioContext *ctx = nullptr;
|
||||
AndroidAudioCallback callback = nullptr;
|
||||
int frames_per_buffer = 0;
|
||||
int sample_rate = 0;
|
||||
};
|
||||
|
||||
AndroidAudioState *AndroidAudio_Init(AndroidAudioCallback callback, std::string libraryDir, int optimalFramesPerBuffer, int optimalSampleRate) {
|
||||
AndroidAudioState *state = new AndroidAudioState();
|
||||
state->callback = callback;
|
||||
state->playing = false;
|
||||
state->frames_per_buffer = optimalFramesPerBuffer ? optimalFramesPerBuffer : 256;
|
||||
state->sample_rate = optimalSampleRate ? optimalSampleRate : 44100;
|
||||
return state;
|
||||
@ -24,11 +22,15 @@ bool AndroidAudio_Resume(AndroidAudioState *state) {
|
||||
ELOG("Audio was shutdown, cannot resume!");
|
||||
return false;
|
||||
}
|
||||
if (!state->playing) {
|
||||
if (!state->ctx) {
|
||||
ILOG("Calling OpenSLWrap_Init_T...");
|
||||
bool init_retval = OpenSLWrap_Init(state->callback, state->frames_per_buffer, state->sample_rate);
|
||||
state->ctx = new OpenSLContext(state->callback, state->frames_per_buffer, state->sample_rate);
|
||||
ILOG("Returned from OpenSLWrap_Init_T");
|
||||
state->playing = true;
|
||||
bool init_retval = state->ctx->Init();
|
||||
if (!init_retval) {
|
||||
delete state->ctx;
|
||||
state->ctx = nullptr;
|
||||
}
|
||||
return init_retval;
|
||||
}
|
||||
return false;
|
||||
@ -39,11 +41,11 @@ bool AndroidAudio_Pause(AndroidAudioState *state) {
|
||||
ELOG("Audio was shutdown, cannot pause!");
|
||||
return false;
|
||||
}
|
||||
if (state->playing) {
|
||||
if (state->ctx) {
|
||||
ILOG("Calling OpenSLWrap_Shutdown_T...");
|
||||
OpenSLWrap_Shutdown();
|
||||
delete state->ctx;
|
||||
state->ctx = nullptr;
|
||||
ILOG("Returned from OpenSLWrap_Shutdown_T ...");
|
||||
state->playing = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -54,7 +56,7 @@ bool AndroidAudio_Shutdown(AndroidAudioState *state) {
|
||||
ELOG("Audio already shutdown!");
|
||||
return false;
|
||||
}
|
||||
if (state->playing) {
|
||||
if (state->ctx) {
|
||||
ELOG("Should not shut down when playing! Something is wrong!");
|
||||
return false;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user