mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-09 15:49:25 +01:00
Android: Get rid of OpenSLESStream's global state
Not sure if we're ever going to want to have more than one of these at the same time, but these global variables are a code smell nonetheless. I'm also deleting the existing member variables because they were unused.
This commit is contained in:
parent
ca22d0af57
commit
7d80b009d8
@ -14,34 +14,19 @@
|
|||||||
#include "Common/Logging/Log.h"
|
#include "Common/Logging/Log.h"
|
||||||
#include "Core/ConfigManager.h"
|
#include "Core/ConfigManager.h"
|
||||||
|
|
||||||
// engine interfaces
|
void OpenSLESStream::BQPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void* context)
|
||||||
static SLObjectItf engineObject;
|
|
||||||
static SLEngineItf engineEngine;
|
|
||||||
static SLObjectItf outputMixObject;
|
|
||||||
|
|
||||||
// buffer queue player interfaces
|
|
||||||
static SLObjectItf bqPlayerObject = nullptr;
|
|
||||||
static SLPlayItf bqPlayerPlay;
|
|
||||||
static SLAndroidSimpleBufferQueueItf bqPlayerBufferQueue;
|
|
||||||
static SLVolumeItf bqPlayerVolume;
|
|
||||||
static Mixer* 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);
|
reinterpret_cast<OpenSLESStream*>(context)->PushSamples(bq);
|
||||||
ASSERT(nullptr == context);
|
}
|
||||||
|
|
||||||
|
void OpenSLESStream::PushSamples(SLAndroidSimpleBufferQueueItf bq)
|
||||||
|
{
|
||||||
|
ASSERT(bq == m_bq_player_buffer_queue);
|
||||||
|
|
||||||
// Render to the fresh buffer
|
// Render to the fresh buffer
|
||||||
g_mixer->Mix(reinterpret_cast<short*>(buffer[curBuffer]), BUFFER_SIZE_IN_SAMPLES);
|
m_mixer->Mix(reinterpret_cast<short*>(m_buffer[m_current_buffer]), BUFFER_SIZE_IN_SAMPLES);
|
||||||
SLresult result =
|
SLresult result = (*bq)->Enqueue(bq, m_buffer[m_current_buffer], sizeof(m_buffer[0]));
|
||||||
(*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, buffer[curBuffer], sizeof(buffer[0]));
|
m_current_buffer ^= 1; // Switch buffer
|
||||||
curBuffer ^= 1; // Switch buffer
|
|
||||||
|
|
||||||
// Comment from sample code:
|
// Comment from sample code:
|
||||||
// the most likely other result is SL_RESULT_BUFFER_INSUFFICIENT,
|
// the most likely other result is SL_RESULT_BUFFER_INSUFFICIENT,
|
||||||
@ -53,15 +38,15 @@ bool OpenSLESStream::Init()
|
|||||||
{
|
{
|
||||||
SLresult result;
|
SLresult result;
|
||||||
// create engine
|
// create engine
|
||||||
result = slCreateEngine(&engineObject, 0, nullptr, 0, nullptr, nullptr);
|
result = slCreateEngine(&m_engine_object, 0, nullptr, 0, nullptr, nullptr);
|
||||||
ASSERT(SL_RESULT_SUCCESS == result);
|
ASSERT(SL_RESULT_SUCCESS == result);
|
||||||
result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
|
result = (*m_engine_object)->Realize(m_engine_object, SL_BOOLEAN_FALSE);
|
||||||
ASSERT(SL_RESULT_SUCCESS == result);
|
ASSERT(SL_RESULT_SUCCESS == result);
|
||||||
result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
|
result = (*m_engine_object)->GetInterface(m_engine_object, SL_IID_ENGINE, &m_engine_engine);
|
||||||
ASSERT(SL_RESULT_SUCCESS == result);
|
ASSERT(SL_RESULT_SUCCESS == result);
|
||||||
result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 0, 0, 0);
|
result = (*m_engine_engine)->CreateOutputMix(m_engine_engine, &m_output_mix_object, 0, 0, 0);
|
||||||
ASSERT(SL_RESULT_SUCCESS == result);
|
ASSERT(SL_RESULT_SUCCESS == result);
|
||||||
result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE);
|
result = (*m_output_mix_object)->Realize(m_output_mix_object, SL_BOOLEAN_FALSE);
|
||||||
ASSERT(SL_RESULT_SUCCESS == result);
|
ASSERT(SL_RESULT_SUCCESS == result);
|
||||||
|
|
||||||
SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2};
|
SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2};
|
||||||
@ -76,36 +61,38 @@ bool OpenSLESStream::Init()
|
|||||||
SLDataSource audioSrc = {&loc_bufq, &format_pcm};
|
SLDataSource audioSrc = {&loc_bufq, &format_pcm};
|
||||||
|
|
||||||
// configure audio sink
|
// configure audio sink
|
||||||
SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, outputMixObject};
|
SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, m_output_mix_object};
|
||||||
SLDataSink audioSnk = {&loc_outmix, nullptr};
|
SLDataSink audioSnk = {&loc_outmix, nullptr};
|
||||||
|
|
||||||
// create audio player
|
// create audio player
|
||||||
const SLInterfaceID ids[2] = {SL_IID_BUFFERQUEUE, SL_IID_VOLUME};
|
const SLInterfaceID ids[2] = {SL_IID_BUFFERQUEUE, SL_IID_VOLUME};
|
||||||
const SLboolean req[2] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
|
const SLboolean req[2] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
|
||||||
result =
|
result = (*m_engine_engine)
|
||||||
(*engineEngine)
|
->CreateAudioPlayer(m_engine_engine, &m_bq_player_object, &audioSrc, &audioSnk, 2,
|
||||||
->CreateAudioPlayer(engineEngine, &bqPlayerObject, &audioSrc, &audioSnk, 2, ids, req);
|
ids, req);
|
||||||
ASSERT(SL_RESULT_SUCCESS == result);
|
ASSERT(SL_RESULT_SUCCESS == result);
|
||||||
|
|
||||||
result = (*bqPlayerObject)->Realize(bqPlayerObject, SL_BOOLEAN_FALSE);
|
result = (*m_bq_player_object)->Realize(m_bq_player_object, SL_BOOLEAN_FALSE);
|
||||||
ASSERT(SL_RESULT_SUCCESS == result);
|
ASSERT(SL_RESULT_SUCCESS == result);
|
||||||
result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_PLAY, &bqPlayerPlay);
|
result = (*m_bq_player_object)->GetInterface(m_bq_player_object, SL_IID_PLAY, &m_bq_player_play);
|
||||||
|
ASSERT(SL_RESULT_SUCCESS == result);
|
||||||
|
result = (*m_bq_player_object)
|
||||||
|
->GetInterface(m_bq_player_object, SL_IID_BUFFERQUEUE, &m_bq_player_buffer_queue);
|
||||||
ASSERT(SL_RESULT_SUCCESS == result);
|
ASSERT(SL_RESULT_SUCCESS == result);
|
||||||
result =
|
result =
|
||||||
(*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_BUFFERQUEUE, &bqPlayerBufferQueue);
|
(*m_bq_player_object)->GetInterface(m_bq_player_object, SL_IID_VOLUME, &m_bq_player_volume);
|
||||||
ASSERT(SL_RESULT_SUCCESS == result);
|
ASSERT(SL_RESULT_SUCCESS == result);
|
||||||
result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_VOLUME, &bqPlayerVolume);
|
result = (*m_bq_player_buffer_queue)
|
||||||
|
->RegisterCallback(m_bq_player_buffer_queue, BQPlayerCallback, this);
|
||||||
ASSERT(SL_RESULT_SUCCESS == result);
|
ASSERT(SL_RESULT_SUCCESS == result);
|
||||||
result = (*bqPlayerBufferQueue)->RegisterCallback(bqPlayerBufferQueue, bqPlayerCallback, nullptr);
|
result = (*m_bq_player_play)->SetPlayState(m_bq_player_play, SL_PLAYSTATE_PLAYING);
|
||||||
ASSERT(SL_RESULT_SUCCESS == result);
|
|
||||||
result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_PLAYING);
|
|
||||||
ASSERT(SL_RESULT_SUCCESS == result);
|
ASSERT(SL_RESULT_SUCCESS == result);
|
||||||
|
|
||||||
// Render and enqueue a first buffer.
|
// Render and enqueue a first buffer.
|
||||||
curBuffer ^= 1;
|
m_current_buffer ^= 1;
|
||||||
g_mixer = m_mixer.get();
|
|
||||||
|
|
||||||
result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, buffer[0], sizeof(buffer[0]));
|
result = (*m_bq_player_buffer_queue)
|
||||||
|
->Enqueue(m_bq_player_buffer_queue, m_buffer[0], sizeof(m_buffer[0]));
|
||||||
if (SL_RESULT_SUCCESS != result)
|
if (SL_RESULT_SUCCESS != result)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -114,39 +101,39 @@ bool OpenSLESStream::Init()
|
|||||||
|
|
||||||
OpenSLESStream::~OpenSLESStream()
|
OpenSLESStream::~OpenSLESStream()
|
||||||
{
|
{
|
||||||
if (bqPlayerObject != nullptr)
|
if (m_bq_player_object != nullptr)
|
||||||
{
|
{
|
||||||
(*bqPlayerObject)->Destroy(bqPlayerObject);
|
(*m_bq_player_object)->Destroy(m_bq_player_object);
|
||||||
bqPlayerObject = nullptr;
|
m_bq_player_object = nullptr;
|
||||||
bqPlayerPlay = nullptr;
|
m_bq_player_play = nullptr;
|
||||||
bqPlayerBufferQueue = nullptr;
|
m_bq_player_buffer_queue = nullptr;
|
||||||
bqPlayerVolume = nullptr;
|
m_bq_player_volume = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (outputMixObject != nullptr)
|
if (m_output_mix_object != nullptr)
|
||||||
{
|
{
|
||||||
(*outputMixObject)->Destroy(outputMixObject);
|
(*m_output_mix_object)->Destroy(m_output_mix_object);
|
||||||
outputMixObject = nullptr;
|
m_output_mix_object = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (engineObject != nullptr)
|
if (m_engine_object != nullptr)
|
||||||
{
|
{
|
||||||
(*engineObject)->Destroy(engineObject);
|
(*m_engine_object)->Destroy(m_engine_object);
|
||||||
engineObject = nullptr;
|
m_engine_object = nullptr;
|
||||||
engineEngine = nullptr;
|
m_engine_engine = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OpenSLESStream::SetRunning(bool running)
|
bool OpenSLESStream::SetRunning(bool running)
|
||||||
{
|
{
|
||||||
SLuint32 new_state = running ? SL_PLAYSTATE_PLAYING : SL_PLAYSTATE_PAUSED;
|
SLuint32 new_state = running ? SL_PLAYSTATE_PLAYING : SL_PLAYSTATE_PAUSED;
|
||||||
return (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, new_state) == SL_RESULT_SUCCESS;
|
return (*m_bq_player_play)->SetPlayState(m_bq_player_play, new_state) == SL_RESULT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenSLESStream::SetVolume(int volume)
|
void OpenSLESStream::SetVolume(int volume)
|
||||||
{
|
{
|
||||||
const SLmillibel attenuation =
|
const SLmillibel attenuation =
|
||||||
volume <= 0 ? SL_MILLIBEL_MIN : static_cast<SLmillibel>(2000 * std::log10(volume / 100.0f));
|
volume <= 0 ? SL_MILLIBEL_MIN : static_cast<SLmillibel>(2000 * std::log10(volume / 100.0f));
|
||||||
(*bqPlayerVolume)->SetVolumeLevel(bqPlayerVolume, attenuation);
|
(*m_bq_player_volume)->SetVolumeLevel(m_bq_player_volume, attenuation);
|
||||||
}
|
}
|
||||||
#endif // HAVE_OPENSL_ES
|
#endif // HAVE_OPENSL_ES
|
||||||
|
@ -3,10 +3,12 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <thread>
|
#ifdef HAVE_OPENSL_ES
|
||||||
|
#include <SLES/OpenSLES.h>
|
||||||
|
#include <SLES/OpenSLES_Android.h>
|
||||||
|
#endif // HAVE_OPENSL_ES
|
||||||
|
|
||||||
#include "AudioCommon/SoundStream.h"
|
#include "AudioCommon/SoundStream.h"
|
||||||
#include "Common/Event.h"
|
|
||||||
|
|
||||||
class OpenSLESStream final : public SoundStream
|
class OpenSLESStream final : public SoundStream
|
||||||
{
|
{
|
||||||
@ -19,7 +21,25 @@ public:
|
|||||||
static bool IsValid() { return true; }
|
static bool IsValid() { return true; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::thread thread;
|
static void BQPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void* context);
|
||||||
Common::Event soundSyncEvent;
|
void PushSamples(SLAndroidSimpleBufferQueueItf bq);
|
||||||
|
|
||||||
|
// engine interfaces
|
||||||
|
SLObjectItf m_engine_object;
|
||||||
|
SLEngineItf m_engine_engine;
|
||||||
|
SLObjectItf m_output_mix_object;
|
||||||
|
|
||||||
|
// buffer queue player interfaces
|
||||||
|
SLObjectItf m_bq_player_object = nullptr;
|
||||||
|
SLPlayItf m_bq_player_play;
|
||||||
|
SLAndroidSimpleBufferQueueItf m_bq_player_buffer_queue;
|
||||||
|
SLVolumeItf m_bq_player_volume;
|
||||||
|
|
||||||
|
static constexpr int BUFFER_SIZE = 512;
|
||||||
|
static constexpr int BUFFER_SIZE_IN_SAMPLES = BUFFER_SIZE / 2;
|
||||||
|
|
||||||
|
// Double buffering.
|
||||||
|
short m_buffer[2][BUFFER_SIZE];
|
||||||
|
int m_current_buffer = 0;
|
||||||
#endif // HAVE_OPENSL_ES
|
#endif // HAVE_OPENSL_ES
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user