|
|
@@ -24,12 +24,15 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
|
OTHER DEALINGS IN THE SOFTWARE.
|
|
|
*/
|
|
|
|
|
|
+#include <SLES/OpenSLES.h>
|
|
|
+#include <SLES/OpenSLES_Android.h>
|
|
|
#include <cstring>
|
|
|
|
|
|
#include "Types.h"
|
|
|
-#include "SLESRenderer.h"
|
|
|
#include "Assert.h"
|
|
|
#include "MathUtils.h"
|
|
|
+#include "SoundRenderer.h"
|
|
|
+#include "SLESRenderer.h"
|
|
|
|
|
|
namespace crown
|
|
|
{
|
|
|
@@ -38,175 +41,297 @@ uint16_t* loop_data;
|
|
|
size_t loop_size;
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
-AudioRenderer* AudioRenderer::create(Allocator& a)
|
|
|
+void check_sles_errors(SLresult result)
|
|
|
{
|
|
|
- return CE_NEW(a, SLESRenderer);
|
|
|
+ CE_ASSERT(result == SL_RESULT_SUCCESS, "SL_ERROR_CODE: %d", result);
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
-void AudioRenderer::destroy(Allocator& a, AudioRenderer* renderer)
|
|
|
+void source_callback(SLAndroidSimpleBufferQueueItf caller, void* source)
|
|
|
{
|
|
|
- CE_DELETE(a, renderer);
|
|
|
-}
|
|
|
+ (void)caller;
|
|
|
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-SLESRenderer::SLESRenderer() :
|
|
|
- m_buffers_id_table(m_allocator, MAX_BUFFERS),
|
|
|
- m_sources_id_table(m_allocator, MAX_SOURCES)
|
|
|
-{
|
|
|
+ SoundSource* s = (SoundSource*)source;
|
|
|
+
|
|
|
+ if (s->m_loop)
|
|
|
+ { // FIXME FIXME FIXME
|
|
|
+ (*s->m_player_bufferqueue)->Enqueue(s->m_player_bufferqueue, loop_data, loop_size);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ (*s->m_player_play)->SetPlayState(s->m_player_play, SL_PLAYSTATE_STOPPED);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
-void SLESRenderer::init()
|
|
|
+class SoundRendererBackend
|
|
|
{
|
|
|
- SLresult result;
|
|
|
+public:
|
|
|
+ //-----------------------------------------------------------------------------
|
|
|
+ void init()
|
|
|
+ {
|
|
|
+ SLresult result;
|
|
|
+
|
|
|
+ const SLInterfaceID ids[] = {SL_IID_ENGINE};
|
|
|
+ const SLboolean reqs[] = {SL_BOOLEAN_TRUE};
|
|
|
+
|
|
|
+ result = slCreateEngine(&m_engine_obj, 0, NULL, 1, ids, reqs);
|
|
|
+ result = (*m_engine_obj)->Realize(m_engine_obj, SL_BOOLEAN_FALSE);
|
|
|
+
|
|
|
+ result = (*m_engine_obj)->GetInterface(m_engine_obj, SL_IID_ENGINE, &m_engine);
|
|
|
+
|
|
|
+ const SLInterfaceID ids1[] = {SL_IID_VOLUME};
|
|
|
+ const SLboolean reqs1[] = {SL_BOOLEAN_FALSE};
|
|
|
+
|
|
|
+ result = (*m_engine)->CreateOutputMix(m_engine, &m_out_mix_obj, 1, ids1, reqs1);
|
|
|
+ result = (*m_out_mix_obj)->Realize(m_out_mix_obj, SL_BOOLEAN_FALSE);
|
|
|
+ }
|
|
|
+
|
|
|
+ //-----------------------------------------------------------------------------
|
|
|
+ void shutdown()
|
|
|
+ {
|
|
|
+ if (m_out_mix_obj)
|
|
|
+ {
|
|
|
+ (*m_out_mix_obj)->Destroy(m_out_mix_obj);
|
|
|
+ m_out_mix_obj = NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (m_engine_obj)
|
|
|
+ {
|
|
|
+ (*m_engine_obj)->Destroy(m_engine_obj);
|
|
|
+ m_engine_obj = NULL;
|
|
|
+ m_engine = NULL;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //-----------------------------------------------------------------------------
|
|
|
+ void create_source(SoundSource& s)
|
|
|
+ {
|
|
|
+ SLresult result;
|
|
|
+
|
|
|
+ int32_t speakers = SL_SPEAKER_FRONT_CENTER;
|
|
|
+
|
|
|
+ // Configures buffer queue
|
|
|
+ SLDataLocator_AndroidSimpleBufferQueue buffer_queue = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2};
|
|
|
+
|
|
|
+ // Configures audio format
|
|
|
+ SLDataFormat_PCM format_pcm;
|
|
|
+ format_pcm.formatType = SL_DATAFORMAT_PCM;
|
|
|
+ format_pcm.numChannels = 1; // Mono
|
|
|
+ format_pcm.samplesPerSec = SL_SAMPLINGRATE_44_1;
|
|
|
+ format_pcm.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16;
|
|
|
+ format_pcm.containerSize = SL_PCMSAMPLEFORMAT_FIXED_16;
|
|
|
+ format_pcm.channelMask = speakers;
|
|
|
+ format_pcm.endianness = SL_BYTEORDER_LITTLEENDIAN;
|
|
|
+
|
|
|
+ // Configures audio source
|
|
|
+ SLDataSource audio_source;
|
|
|
+ audio_source.pLocator = &buffer_queue;
|
|
|
+ audio_source.pFormat = &format_pcm;
|
|
|
+
|
|
|
+ // Configures audio output mix
|
|
|
+ SLDataLocator_OutputMix out_mix;
|
|
|
+ out_mix.locatorType = SL_DATALOCATOR_OUTPUTMIX;
|
|
|
+ out_mix.outputMix = m_out_mix_obj;
|
|
|
+
|
|
|
+ // Configures audio sink
|
|
|
+ SLDataSink audio_sink;
|
|
|
+ audio_sink.pLocator = &out_mix;
|
|
|
+ audio_sink.pFormat = NULL;
|
|
|
|
|
|
- const SLInterfaceID ids[] = {SL_IID_ENGINE};
|
|
|
- const SLboolean reqs[] = {SL_BOOLEAN_TRUE};
|
|
|
+ // Creates sound player
|
|
|
+ const SLInterfaceID ids[] = {SL_IID_PLAY, SL_IID_BUFFERQUEUE, SL_IID_VOLUME};
|
|
|
+ const SLboolean reqs[] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
|
|
|
|
|
|
- result = slCreateEngine(&m_engine_obj, 0, NULL, 1, ids, reqs);
|
|
|
- result = (*m_engine_obj)->Realize(m_engine_obj, SL_BOOLEAN_FALSE);
|
|
|
+ result = (*m_engine)->CreateAudioPlayer(m_engine, &s.m_player_obj, &audio_source, &audio_sink, 3, ids, reqs);
|
|
|
+ check_sles_errors(result);
|
|
|
|
|
|
- result = (*m_engine_obj)->GetInterface(m_engine_obj, SL_IID_ENGINE, &m_engine);
|
|
|
+ result = (*s.m_player_obj)->Realize(s.m_player_obj, SL_BOOLEAN_FALSE);
|
|
|
+ check_sles_errors(result);
|
|
|
|
|
|
- const SLInterfaceID ids1[] = {SL_IID_VOLUME};
|
|
|
- const SLboolean reqs1[] = {SL_BOOLEAN_FALSE};
|
|
|
+ // Gets interfaces
|
|
|
+ result = (*s.m_player_obj)->GetInterface(s.m_player_obj, SL_IID_PLAY, &s.m_player_play);
|
|
|
+ check_sles_errors(result);
|
|
|
|
|
|
- result = (*m_engine)->CreateOutputMix(m_engine, &m_out_mix_obj, 1, ids1, reqs1);
|
|
|
- result = (*m_out_mix_obj)->Realize(m_out_mix_obj, SL_BOOLEAN_FALSE);
|
|
|
+ result = (*s.m_player_obj)->GetInterface(s.m_player_obj, SL_IID_BUFFERQUEUE, &s.m_player_bufferqueue);
|
|
|
+ check_sles_errors(result);
|
|
|
+
|
|
|
+ result = (*s.m_player_obj)->GetInterface(s.m_player_obj, SL_IID_VOLUME, &s.m_player_volume);
|
|
|
+ check_sles_errors(result);
|
|
|
+
|
|
|
+ (*s.m_player_bufferqueue)->RegisterCallback(s.m_player_bufferqueue, source_callback, &s);
|
|
|
+ }
|
|
|
+
|
|
|
+ //-----------------------------------------------------------------------------
|
|
|
+ void destroy_source(SoundSource& s)
|
|
|
+ {
|
|
|
+ if (s.m_player_obj)
|
|
|
+ {
|
|
|
+ SLuint32 state;
|
|
|
+ (*s.m_player_obj)->GetState(s.m_player_obj, &state);
|
|
|
+
|
|
|
+ if (state == SL_OBJECT_STATE_REALIZED)
|
|
|
+ {
|
|
|
+ (*s.m_player_bufferqueue)->Clear(s.m_player_bufferqueue);
|
|
|
+ (*s.m_player_obj)->AbortAsyncOperation(s.m_player_obj);
|
|
|
+ (*s.m_player_obj)->Destroy(s.m_player_obj);
|
|
|
+
|
|
|
+ s.m_player_obj = NULL;
|
|
|
+ s.m_player_play = NULL;
|
|
|
+ s.m_player_bufferqueue = NULL;
|
|
|
+ s.m_player_volume = NULL;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+private:
|
|
|
+
|
|
|
+ SLObjectItf m_engine_obj;
|
|
|
+ SLEngineItf m_engine;
|
|
|
+
|
|
|
+ SLObjectItf m_out_mix_obj;
|
|
|
+
|
|
|
+ SoundBuffer m_buffers[MAX_SOUND_BUFFERS];
|
|
|
+ SoundSource m_sources[MAX_SOUND_SOURCES];
|
|
|
+
|
|
|
+private:
|
|
|
+
|
|
|
+ friend class SoundRenderer;
|
|
|
+ // friend source_callback(SLAndroidSimpleBufferQueueItf caller, void* source);
|
|
|
+};
|
|
|
+
|
|
|
+//-----------------------------------------------------------------------------
|
|
|
+SoundRenderer::SoundRenderer(Allocator& allocator) :
|
|
|
+ m_allocator(allocator),
|
|
|
+ m_buffers_id_table(default_allocator(), MAX_SOUND_BUFFERS),
|
|
|
+ m_sources_id_table(default_allocator(), MAX_SOUND_SOURCES)
|
|
|
+{
|
|
|
+ m_backend = CE_NEW(default_allocator(), SoundRendererBackend);
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
-void SLESRenderer::shutdown()
|
|
|
+SoundRenderer::~SoundRenderer()
|
|
|
{
|
|
|
- if (m_out_mix_obj)
|
|
|
+ if (m_backend)
|
|
|
{
|
|
|
- (*m_out_mix_obj)->Destroy(m_out_mix_obj);
|
|
|
- m_out_mix_obj = NULL;
|
|
|
+ CE_DELETE(default_allocator(), m_backend);
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
- if (m_engine_obj)
|
|
|
- {
|
|
|
- (*m_engine_obj)->Destroy(m_engine_obj);
|
|
|
- m_engine_obj = NULL;
|
|
|
- m_engine = NULL;
|
|
|
- }
|
|
|
+//-----------------------------------------------------------------------------
|
|
|
+void SoundRenderer::init()
|
|
|
+{
|
|
|
+ m_backend->init();
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
-SoundBufferId SLESRenderer::create_buffer(const void* data, const uint32_t size, const uint32_t sample_rate, const uint32_t channels, const uint32_t bxs)
|
|
|
+void SoundRenderer::shutdown()
|
|
|
{
|
|
|
- SoundBufferId id = m_buffers_id_table.create();
|
|
|
+ m_backend->shutdown();
|
|
|
+}
|
|
|
+
|
|
|
+//-----------------------------------------------------------------------------
|
|
|
+void SoundRenderer::set_listener(const Vec3& pos, const Vec3& vel, const Vec3& or_up, const Vec3& or_at) const
|
|
|
+{
|
|
|
+ Log::w("Stub");
|
|
|
|
|
|
- SoundBuffer& sl_buffer = m_buffers[id.index];
|
|
|
+ (void)pos;
|
|
|
+ (void)vel;
|
|
|
+ (void)or_up;
|
|
|
+ (void)or_at;
|
|
|
+}
|
|
|
|
|
|
- sl_buffer.data = (uint16_t*)data;
|
|
|
- sl_buffer.size = size;
|
|
|
- sl_buffer.sample_rate = sample_rate;
|
|
|
- sl_buffer.channels = channels;
|
|
|
- sl_buffer.bits_per_sample = bxs;
|
|
|
+//-----------------------------------------------------------------------------
|
|
|
+SoundBufferId SoundRenderer::create_buffer(const void* data, const uint32_t size, const uint32_t sample_rate, const uint32_t channels, const uint32_t bits)
|
|
|
+{
|
|
|
+ SoundBufferId id = m_buffers_id_table.create();
|
|
|
+
|
|
|
+ m_backend->m_buffers[id.index].create(data, size, sample_rate, channels, bits);
|
|
|
|
|
|
return id;
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
-void SLESRenderer::destroy_buffer(SoundBufferId id)
|
|
|
+void SoundRenderer::destroy_buffer(SoundBufferId id)
|
|
|
{
|
|
|
CE_ASSERT(m_buffers_id_table.has(id), "SoundBuffer does not exist");
|
|
|
|
|
|
+ m_backend->m_buffers[id.index].destroy();
|
|
|
+
|
|
|
m_buffers_id_table.destroy(id);
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
-SoundSourceId SLESRenderer::create_source()
|
|
|
+void SoundRenderer::bind_buffer_to_source(SoundBufferId bid, SoundSourceId sid)
|
|
|
{
|
|
|
- SoundSourceId id = m_sources_id_table.create();
|
|
|
-
|
|
|
- SoundSource& sl_source = m_sources[id.index];
|
|
|
+ CE_ASSERT(m_buffers_id_table.has(bid), "SoundBuffer does not exist");
|
|
|
+ CE_ASSERT(m_sources_id_table.has(sid), "SoundSource does not exist");
|
|
|
|
|
|
- create_bufferqueue_player(sl_source);
|
|
|
+ SoundBuffer& b = m_backend->m_buffers[bid.index];
|
|
|
+ SoundSource& s = m_backend->m_sources[sid.index];
|
|
|
|
|
|
- sl_source.loop = false;
|
|
|
+ int32_t result = (*s.m_player_bufferqueue)->Enqueue(s.m_player_bufferqueue, b.m_data, b.m_size);
|
|
|
+ check_sles_errors(result);
|
|
|
|
|
|
- return id;
|
|
|
+ if (s.m_loop)
|
|
|
+ {
|
|
|
+ loop_data = b.m_data;
|
|
|
+ loop_size = b.m_size;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
-SoundSourceId SLESRenderer::create_loop_source()
|
|
|
+SoundSourceId SoundRenderer::create_source(bool loop)
|
|
|
{
|
|
|
SoundSourceId id = m_sources_id_table.create();
|
|
|
|
|
|
- SoundSource& sl_source = m_sources[id.index];
|
|
|
+ SoundSource& sl_source = m_backend->m_sources[id.index];
|
|
|
|
|
|
- create_bufferqueue_player(sl_source);
|
|
|
+ m_backend->create_source(sl_source);
|
|
|
|
|
|
- sl_source.loop = true;
|
|
|
+ sl_source.m_loop = loop;
|
|
|
|
|
|
return id;
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
-void SLESRenderer::play_source(SoundSourceId sid, SoundBufferId bid)
|
|
|
+void SoundRenderer::play_source(SoundSourceId id)
|
|
|
{
|
|
|
- CE_ASSERT(m_sources_id_table.has(sid), "SoundSource does not exist");
|
|
|
- CE_ASSERT(m_buffers_id_table.has(bid), "SoundBuffer does not exist");
|
|
|
+ CE_ASSERT(m_sources_id_table.has(id), "SoundSource does not exist");
|
|
|
|
|
|
- SoundSource& s = m_sources[sid.index];
|
|
|
- SoundBuffer& b = m_buffers[bid.index];
|
|
|
+ SoundSource& s = m_backend->m_sources[id.index];
|
|
|
|
|
|
- SLresult result;
|
|
|
+ SLresult result = (*s.m_player_play)->SetPlayState(s.m_player_play, SL_PLAYSTATE_PLAYING);
|
|
|
|
|
|
- result = (*s.player_bufferqueue)->Enqueue(s.player_bufferqueue, b.data, b.size);
|
|
|
check_sles_errors(result);
|
|
|
-
|
|
|
- // Checks if source is a loop
|
|
|
- if (s.loop)
|
|
|
- {
|
|
|
- // Saves in extarnal pointer sound data for looping
|
|
|
- loop_data = b.data;
|
|
|
- loop_size = b.size;
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
-void SLESRenderer::pause_source(SoundSourceId id)
|
|
|
+void SoundRenderer::pause_source(SoundSourceId id)
|
|
|
{
|
|
|
CE_ASSERT(m_sources_id_table.has(id), "SoundSource does not exist");
|
|
|
|
|
|
- SoundSource& s = m_sources[id.index];
|
|
|
+ SoundSource& s = m_backend->m_sources[id.index];
|
|
|
|
|
|
- SLresult result;
|
|
|
-
|
|
|
- result = (*s.player_play)->SetPlayState(s.player_play, SL_PLAYSTATE_STOPPED);
|
|
|
+ SLresult result = (*s.m_player_play)->SetPlayState(s.m_player_play, SL_PLAYSTATE_PAUSED);
|
|
|
|
|
|
check_sles_errors(result);
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
-void SLESRenderer::destroy_source(SoundSourceId id)
|
|
|
+void SoundRenderer::destroy_source(SoundSourceId id)
|
|
|
{
|
|
|
CE_ASSERT(m_sources_id_table.has(id), "SoundSource does not exist");
|
|
|
|
|
|
- SoundSource& s = m_sources[id.index];
|
|
|
+ SoundSource& s = m_backend->m_sources[id.index];
|
|
|
|
|
|
- destroy_bufferqueue_player(s);
|
|
|
+ m_backend->destroy_source(s);
|
|
|
|
|
|
m_sources_id_table.destroy(id);
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
-void SLESRenderer::set_listener(const Vec3& pos, const Vec3& vel, const Vec3& or_up, const Vec3& or_at) const
|
|
|
-{
|
|
|
- Log::w("Stub");
|
|
|
-
|
|
|
- (void)pos;
|
|
|
- (void)vel;
|
|
|
- (void)or_up;
|
|
|
- (void)or_at;
|
|
|
-}
|
|
|
-
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-void SLESRenderer::set_source_min_distance(SoundSourceId id, const float min_distance)
|
|
|
+void SoundRenderer::set_source_min_distance(SoundSourceId id, const float min_distance)
|
|
|
{
|
|
|
Log::w("Stub");
|
|
|
|
|
|
@@ -215,7 +340,7 @@ void SLESRenderer::set_source_min_distance(SoundSourceId id, const float min_di
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
-void SLESRenderer::set_source_max_distance(SoundSourceId id, const float max_distance)
|
|
|
+void SoundRenderer::set_source_max_distance(SoundSourceId id, const float max_distance)
|
|
|
{
|
|
|
Log::w("Stub");
|
|
|
|
|
|
@@ -224,7 +349,7 @@ void SLESRenderer::set_source_max_distance(SoundSourceId id, const float max_di
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
-void SLESRenderer::set_source_position(SoundSourceId id, const Vec3& pos)
|
|
|
+void SoundRenderer::set_source_position(SoundSourceId id, const Vec3& pos)
|
|
|
{
|
|
|
Log::w("Stub");
|
|
|
|
|
|
@@ -233,7 +358,7 @@ void SLESRenderer::set_source_position(SoundSourceId id, const Vec3& pos)
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
-void SLESRenderer::set_source_velocity(SoundSourceId id, const Vec3& vel)
|
|
|
+void SoundRenderer::set_source_velocity(SoundSourceId id, const Vec3& vel)
|
|
|
{
|
|
|
Log::w("Stub");
|
|
|
|
|
|
@@ -242,7 +367,7 @@ void SLESRenderer::set_source_velocity(SoundSourceId id, const Vec3& vel)
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
-void SLESRenderer::set_source_direction(SoundSourceId id, const Vec3& dir)
|
|
|
+void SoundRenderer::set_source_direction(SoundSourceId id, const Vec3& dir)
|
|
|
{
|
|
|
Log::w("Stub");
|
|
|
|
|
|
@@ -251,7 +376,7 @@ void SLESRenderer::set_source_direction(SoundSourceId id, const Vec3& dir)
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
-void SLESRenderer::set_source_pitch(SoundSourceId id, const float pitch)
|
|
|
+void SoundRenderer::set_source_pitch(SoundSourceId id, const float pitch)
|
|
|
{
|
|
|
Log::w("Stub");
|
|
|
|
|
|
@@ -260,7 +385,7 @@ void SLESRenderer::set_source_pitch(SoundSourceId id, const float pitch)
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
-void SLESRenderer::set_source_gain(SoundSourceId id, const float gain)
|
|
|
+void SoundRenderer::set_source_gain(SoundSourceId id, const float gain)
|
|
|
{
|
|
|
Log::w("Stub");
|
|
|
|
|
|
@@ -269,7 +394,7 @@ void SLESRenderer::set_source_gain(SoundSourceId id, const float gain)
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
-void SLESRenderer::set_source_rolloff(SoundSourceId id, const float rolloff)
|
|
|
+void SoundRenderer::set_source_rolloff(SoundSourceId id, const float rolloff)
|
|
|
{
|
|
|
Log::w("Stub");
|
|
|
|
|
|
@@ -278,124 +403,17 @@ void SLESRenderer::set_source_rolloff(SoundSourceId id, const float rolloff)
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
-bool SLESRenderer::source_playing(SoundSourceId id)
|
|
|
+bool SoundRenderer::source_playing(SoundSourceId id)
|
|
|
{
|
|
|
CE_ASSERT(m_sources_id_table.has(id), "SoundSource does not exist");
|
|
|
|
|
|
- SoundSource& s = m_sources[id.index];
|
|
|
+ SoundSource& s = m_backend->m_sources[id.index];
|
|
|
|
|
|
SLuint32 state;
|
|
|
|
|
|
- (*s.player_play)->GetPlayState(s.player_play, &state);
|
|
|
+ (*s.m_player_play)->GetPlayState(s.m_player_play, &state);
|
|
|
|
|
|
return state == SL_PLAYSTATE_PLAYING;
|
|
|
}
|
|
|
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-void SLESRenderer::check_sles_errors(SLresult result)
|
|
|
-{
|
|
|
- CE_ASSERT(result == SL_RESULT_SUCCESS, "SL_ERROR_CODE: %d", result);
|
|
|
-}
|
|
|
-
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-void SLESRenderer::create_bufferqueue_player(SoundSource& s)
|
|
|
-{
|
|
|
- SLresult result;
|
|
|
-
|
|
|
- int32_t speakers = SL_SPEAKER_FRONT_CENTER;
|
|
|
-
|
|
|
- // Configures buffer queue
|
|
|
- SLDataLocator_AndroidSimpleBufferQueue buffer_queue = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2};
|
|
|
-
|
|
|
- // Configures audio format
|
|
|
- SLDataFormat_PCM format_pcm;
|
|
|
- format_pcm.formatType = SL_DATAFORMAT_PCM;
|
|
|
- format_pcm.numChannels = 1; // Mono
|
|
|
- format_pcm.samplesPerSec = SL_SAMPLINGRATE_44_1;
|
|
|
- format_pcm.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16;
|
|
|
- format_pcm.containerSize = SL_PCMSAMPLEFORMAT_FIXED_16;
|
|
|
- format_pcm.channelMask = speakers;
|
|
|
- format_pcm.endianness = SL_BYTEORDER_LITTLEENDIAN;
|
|
|
-
|
|
|
- // Configures audio source
|
|
|
- SLDataSource audio_source;
|
|
|
- audio_source.pLocator = &buffer_queue;
|
|
|
- audio_source.pFormat = &format_pcm;
|
|
|
-
|
|
|
- // Configures audio output mix
|
|
|
- SLDataLocator_OutputMix out_mix;
|
|
|
- out_mix.locatorType = SL_DATALOCATOR_OUTPUTMIX;
|
|
|
- out_mix.outputMix = m_out_mix_obj;
|
|
|
-
|
|
|
- // Configures audio sink
|
|
|
- SLDataSink audio_sink;
|
|
|
- audio_sink.pLocator = &out_mix;
|
|
|
- audio_sink.pFormat = NULL;
|
|
|
-
|
|
|
- // Creates sound player
|
|
|
- const SLInterfaceID ids[] = {SL_IID_PLAY, SL_IID_BUFFERQUEUE, SL_IID_VOLUME};
|
|
|
- const SLboolean reqs[] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
|
|
|
-
|
|
|
- result = (*m_engine)->CreateAudioPlayer(m_engine, &s.player_obj, &audio_source, &audio_sink, 3, ids, reqs);
|
|
|
- check_sles_errors(result);
|
|
|
-
|
|
|
- result = (*s.player_obj)->Realize(s.player_obj, SL_BOOLEAN_FALSE);
|
|
|
- check_sles_errors(result);
|
|
|
-
|
|
|
- // Gets interfaces
|
|
|
- result = (*s.player_obj)->GetInterface(s.player_obj, SL_IID_PLAY, &s.player_play);
|
|
|
- check_sles_errors(result);
|
|
|
-
|
|
|
- result = (*s.player_obj)->GetInterface(s.player_obj, SL_IID_BUFFERQUEUE, &s.player_bufferqueue);
|
|
|
- check_sles_errors(result);
|
|
|
-
|
|
|
- result = (*s.player_obj)->GetInterface(s.player_obj, SL_IID_VOLUME, &s.player_volume);
|
|
|
- check_sles_errors(result);
|
|
|
-
|
|
|
- (*s.player_bufferqueue)->RegisterCallback(s.player_bufferqueue, player_callback, &s);
|
|
|
-
|
|
|
- result = (*s.player_play)->SetPlayState(s.player_play, SL_PLAYSTATE_PLAYING);
|
|
|
- check_sles_errors(result);
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-void SLESRenderer::destroy_bufferqueue_player(SoundSource& s)
|
|
|
-{
|
|
|
- if (s.player_obj)
|
|
|
- {
|
|
|
- SLuint32 state;
|
|
|
- (*s.player_obj)->GetState(s.player_obj, &state);
|
|
|
-
|
|
|
- if (state == SL_OBJECT_STATE_REALIZED)
|
|
|
- {
|
|
|
- (*s.player_bufferqueue)->Clear(s.player_bufferqueue);
|
|
|
- (*s.player_obj)->AbortAsyncOperation(s.player_obj);
|
|
|
- (*s.player_obj)->Destroy(s.player_obj);
|
|
|
-
|
|
|
- s.player_obj = NULL;
|
|
|
- s.player_play = NULL;
|
|
|
- s.player_bufferqueue = NULL;
|
|
|
- s.player_volume = NULL;
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
-void player_callback(SLAndroidSimpleBufferQueueItf caller, void* source)
|
|
|
-{
|
|
|
- (void)caller;
|
|
|
-
|
|
|
- SoundSource* s = (SoundSource*)source;
|
|
|
-
|
|
|
- if (s->loop)
|
|
|
- {
|
|
|
- (*s->player_bufferqueue)->Enqueue(s->player_bufferqueue, loop_data, loop_size);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- (*s->player_play)->SetPlayState(s->player_play, SL_PLAYSTATE_STOPPED);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
} // namespace crown
|