Browse Source

implement a stable version of SLESRenderer

mikymod 12 năm trước cách đây
mục cha
commit
6dcdffe460

+ 178 - 41
engine/renderers/sles/SLESRenderer.cpp

@@ -24,34 +24,16 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 OTHER DEALINGS IN THE SOFTWARE.
 OTHER DEALINGS IN THE SOFTWARE.
 */
 */
 
 
+#include <cstring>
+
+#include "Types.h"
 #include "SLESRenderer.h"
 #include "SLESRenderer.h"
+#include "Assert.h"
+#include "MathUtils.h"
 
 
 namespace crown
 namespace crown
 {
 {
 
 
-//-----------------------------------------------------------------------------
-static const char* sl_error_to_string(SLresult error)
-{
-	switch (error)
-	{
-		case SL_RESULT_PARAMETER_INVALID: 	return "SL_RESULT_PARAMETER_INVALID";
-		case SL_RESULT_MEMORY_FAILURE: 		return "SL_RESULT_MEMORY_FAILURE";
-		case SL_RESULT_FEATURE_UNSUPPORTED: return "SL_RESULT_FEATURE_UNSUPPORTED";
-		case SL_RESULT_RESOURCE_ERROR: 		return "SL_RESULT_RESOURCE_ERROR";
-		default: 							return "SL_UNKNOWN_ERROR";
-	}
-}
-
-//-----------------------------------------------------------------------------
-#ifdef CROWN_DEBUG
-	#define SL_CHECK(function)\
-		do { SLresult error; CE_ASSERT((error = function()) == SL_RESULT_SUCCESS,\
-				"OpenSLES error: %s", sl_error_to_string(error)); } while (0)
-#else
-	#define SL_CHECK(function)\
-		function;
-#endif
-
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 AudioRenderer* AudioRenderer::create(Allocator& a)
 AudioRenderer* AudioRenderer::create(Allocator& a)
 {
 {
@@ -69,132 +51,287 @@ SLESRenderer::SLESRenderer() :
 	m_buffers_id_table(m_allocator, MAX_BUFFERS),
 	m_buffers_id_table(m_allocator, MAX_BUFFERS),
 	m_sources_id_table(m_allocator, MAX_SOURCES)
 	m_sources_id_table(m_allocator, MAX_SOURCES)
 {
 {
-
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 void SLESRenderer::init()
 void SLESRenderer::init()
 {
 {
-	slCreateEngine(&m_engine_obj, 0, NULL, 0, NULL, NULL);
-	(*m_engine_obj)->Realize(m_engine_obj, SL_BOOLEAN_FALSE);
+	SLresult result;
+
+    const SLInterfaceID ids[] = {SL_IID_ENGINE};
+    const SLboolean reqs[] = {SL_BOOLEAN_TRUE};
 
 
-	(*m_engine_obj)->GetInterface(m_engine_obj, SL_IID_ENGINE, &m_engine);
+	result = slCreateEngine(&m_engine_obj, 0, NULL, 1, ids, reqs);
+	result = (*m_engine_obj)->Realize(m_engine_obj, SL_BOOLEAN_FALSE);
 
 
-    const SLInterfaceID ids[5] = {SL_IID_NULL, SL_IID_NULL, SL_IID_NULL, SL_IID_NULL, SL_IID_NULL};
-    const SLboolean req[5] = {SL_BOOLEAN_FALSE, SL_BOOLEAN_FALSE, SL_BOOLEAN_FALSE, SL_BOOLEAN_FALSE, SL_BOOLEAN_FALSE};
+	result = (*m_engine_obj)->GetInterface(m_engine_obj, SL_IID_ENGINE, &m_engine);
 
 
-    (*m_engine)->CreateOutputMix(m_engine, &m_out_mix_obj, 1, ids, req); 
-    (*m_out_mix_obj)->Realize(m_out_mix_obj, SL_BOOLEAN_FALSE);
+    const SLInterfaceID ids1[] = {SL_IID_VOLUME};
+    const SLboolean reqs1[] = {SL_BOOLEAN_FALSE};
 
 
-    (*m_out_mix_obj)->GetInterface(m_out_mix_obj, SL_IID_ENVIRONMENTALREVERB, &m_out_mix_env_reverb);
+    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 SLESRenderer::shutdown()
 void SLESRenderer::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 SLESRenderer::set_listener(const Vec3& pos, const Vec3& vel, const Vec3& or_up, const Vec3& or_at) const
+SoundBufferId SLESRenderer::create_buffer(const void* data, const uint32_t size, const uint32_t sample_rate, const uint32_t channels, const uint32_t bxs)
 {
 {
+	SoundBufferId id = m_buffers_id_table.create();
 
 
-}
+	SoundBuffer& sl_buffer = m_buffers[id.index];
 
 
-//-----------------------------------------------------------------------------
-SoundBufferId SLESRenderer::create_buffer(const void* data, const uint32_t size, const uint32_t sample_rate, const uint32_t channels, const uint32_t bxs)
-{
+	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;
 
 
+	return id;
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 void SLESRenderer::destroy_buffer(SoundBufferId id)
 void SLESRenderer::destroy_buffer(SoundBufferId id)
 {
 {
+	CE_ASSERT(m_buffers_id_table.has(id), "SoundBuffer does not exist");
 
 
+	m_buffers_id_table.destroy(id);
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
-SoundSourceId SLESRenderer::create_source(const Vec3& pos, const Vec3& vel, const Vec3& dir, const bool loop)
+SoundSourceId SLESRenderer::create_source()
 {
 {
+	SoundSourceId id = m_sources_id_table.create();
 
 
+	SoundSource& sl_source = m_sources[id.index];
+
+	create_bufferqueue_player(sl_source);
+
+	return id;
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
-void SLESRenderer::play_source(SoundSourceId id)
+void SLESRenderer::play_source(SoundSourceId sid, SoundBufferId bid)
 {
 {
+	CE_ASSERT(m_sources_id_table.has(sid), "SoundSource does not exist");
+	CE_ASSERT(m_buffers_id_table.has(bid), "SoundBuffer does not exist");
+
+	SoundSource& s = m_sources[sid.index];
+	SoundBuffer& b = m_buffers[bid.index];
 
 
+	SLresult result;
+
+	result = (*s.player_bufferqueue)->Enqueue(s.player_bufferqueue, b.data, b.size);
+	check_sles_errors(result);
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 void SLESRenderer::pause_source(SoundSourceId id)
 void SLESRenderer::pause_source(SoundSourceId id)
 {
 {
-
+	// Must be implemented
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 void SLESRenderer::destroy_source(SoundSourceId id)
 void SLESRenderer::destroy_source(SoundSourceId id)
 {
 {
+	CE_ASSERT(m_sources_id_table.has(id), "SoundSource does not exist");
+
+	SoundSource& s = m_sources[id.index];
 
 
+	destroy_bufferqueue_player(s);
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
-void SLESRenderer::bind_buffer(SoundSourceId sid, SoundBufferId bid)
+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 SLESRenderer::set_source_min_distance(SoundSourceId id,  const float min_distance)
 {
 {
+	Log::w("Stub");
 
 
+	(void)id;
+	(void)min_distance;
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 void SLESRenderer::set_source_max_distance(SoundSourceId id,  const float max_distance)
 void SLESRenderer::set_source_max_distance(SoundSourceId id,  const float max_distance)
 {
 {
+	Log::w("Stub");
 
 
+	(void)id;
+	(void)max_distance;
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 void SLESRenderer::set_source_position(SoundSourceId id, const Vec3& pos)
 void SLESRenderer::set_source_position(SoundSourceId id, const Vec3& pos)
 {
 {
+	Log::w("Stub");
 
 
+	(void)id;
+	(void)pos;
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 void SLESRenderer::set_source_velocity(SoundSourceId id, const Vec3& vel)
 void SLESRenderer::set_source_velocity(SoundSourceId id, const Vec3& vel)
 {
 {
+	Log::w("Stub");
 
 
+	(void)id;
+	(void)vel;
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 void SLESRenderer::set_source_direction(SoundSourceId id, const Vec3& dir)
 void SLESRenderer::set_source_direction(SoundSourceId id, const Vec3& dir)
 {
 {
+	Log::w("Stub");
 
 
+	(void)id;
+	(void)dir;
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 void SLESRenderer::set_source_pitch(SoundSourceId id, const float pitch)
 void SLESRenderer::set_source_pitch(SoundSourceId id, const float pitch)
 {
 {
+	Log::w("Stub");
 
 
+	(void)id;
+	(void)pitch;	
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 void SLESRenderer::set_source_gain(SoundSourceId id, const float gain)
 void SLESRenderer::set_source_gain(SoundSourceId id, const float gain)
 {
 {
+	Log::w("Stub");
 
 
+	(void)id;
+	(void)gain;
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 void SLESRenderer::set_source_rolloff(SoundSourceId id, const float rolloff)
 void SLESRenderer::set_source_rolloff(SoundSourceId id, const float rolloff)
 {
 {
+	Log::w("Stub");
 
 
+	(void)id;
+	(void)rolloff;
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 bool SLESRenderer::source_playing(SoundSourceId id)
 bool SLESRenderer::source_playing(SoundSourceId id)
 {
 {
+	// Must be implemented
+}	
+
+//-----------------------------------------------------------------------------
+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);
+
+	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;
+		}
+	}
 }
 }
 
 
 } // namespace crown
 } // namespace crown

+ 25 - 31
engine/renderers/sles/SLESRenderer.h

@@ -29,71 +29,69 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include <SLES/OpenSLES.h>
 #include <SLES/OpenSLES.h>
 #include <SLES/OpenSLES_Android.h>
 #include <SLES/OpenSLES_Android.h>
 
 
+#include "Types.h"
 #include "AudioRenderer.h"
 #include "AudioRenderer.h"
 #include "HeapAllocator.h"
 #include "HeapAllocator.h"
 
 
 namespace crown
 namespace crown
 {
 {
 
 
+//-----------------------------------------------------------------------------
 struct SoundBuffer
 struct SoundBuffer
 {
 {
-	SLDataLocator_AndroidSimpleBufferQueue buffer_queue;
+	uint16_t*						data;
+	size_t							size;
+	uint32_t						sample_rate;
+	uint32_t						channels;
+	uint32_t						bits_per_sample;
 };
 };
 
 
+//-----------------------------------------------------------------------------
 struct SoundSource
 struct SoundSource
 {
 {
-	SLDataSource source;
+  	SLObjectItf 					player_obj;
+  	SLPlayItf 						player_play;
+  	SLAndroidSimpleBufferQueueItf 	player_bufferqueue;
+  	SLVolumeItf						player_volume;
 };
 };
 
 
-/*
-* FIXME: Can't be completed right now. It's necessary to improve ResourceManager
-* implementing support to Android Assets Manager. Otherwise we must make ugly hacks
-* using Uri Audio Players.
-*/
-class SLESRenderer : public AudioRenderer
-{
 
 
+class SLESRenderer : public AudioRenderer
+{	
 public:
 public:
 
 
 									SLESRenderer();
 									SLESRenderer();
 
 
 	void							init();
 	void							init();
-
 	void							shutdown();
 	void							shutdown();
 
 
 	void							set_listener(const Vec3& pos, const Vec3& vel, const Vec3& or_up, const Vec3& or_at) const;
 	void							set_listener(const Vec3& pos, const Vec3& vel, const Vec3& or_up, const Vec3& or_at) const;
 
 
 	SoundBufferId					create_buffer(const void* data, const uint32_t size, const uint32_t sample_rate, const uint32_t channels, const uint32_t bxs);
 	SoundBufferId					create_buffer(const void* data, const uint32_t size, const uint32_t sample_rate, const uint32_t channels, const uint32_t bxs);
-
 	void							destroy_buffer(SoundBufferId id);
 	void							destroy_buffer(SoundBufferId id);
 
 
-	SoundSourceId					create_source(const Vec3& pos, const Vec3& vel, const Vec3& dir, const bool loop);
-
-	void							play_source(SoundSourceId id);
-
+	SoundSourceId					create_source();
+	void							play_source(SoundSourceId sid, SoundBufferId bid);
 	void							pause_source(SoundSourceId id);
 	void							pause_source(SoundSourceId id);
-
 	void							destroy_source(SoundSourceId id);
 	void							destroy_source(SoundSourceId id);
 
 
-	void							bind_buffer(SoundSourceId sid, SoundBufferId bid);
-
 	void							set_source_min_distance(SoundSourceId id,  const float min_distance);
 	void							set_source_min_distance(SoundSourceId id,  const float min_distance);
-
 	void							set_source_max_distance(SoundSourceId id,  const float max_distance);
 	void							set_source_max_distance(SoundSourceId id,  const float max_distance);
-
 	void							set_source_position(SoundSourceId id, const Vec3& pos);
 	void							set_source_position(SoundSourceId id, const Vec3& pos);
-
 	void							set_source_velocity(SoundSourceId id, const Vec3& vel);
 	void							set_source_velocity(SoundSourceId id, const Vec3& vel);
-
 	void							set_source_direction(SoundSourceId id, const Vec3& dir);
 	void							set_source_direction(SoundSourceId id, const Vec3& dir);
-
 	void							set_source_pitch(SoundSourceId id, const float pitch);
 	void							set_source_pitch(SoundSourceId id, const float pitch);
-
 	void							set_source_gain(SoundSourceId id, const float gain);
 	void							set_source_gain(SoundSourceId id, const float gain);
-
 	void							set_source_rolloff(SoundSourceId id, const float rolloff);
 	void							set_source_rolloff(SoundSourceId id, const float rolloff);
+	bool							source_playing(SoundSourceId id);	
 
 
-	bool							source_playing(SoundSourceId id);
+	void 							check_sles_errors(SLresult result);
+
+private:
+
+	void							create_bufferqueue_player(SoundSource& s);
+
+	void							destroy_bufferqueue_player(SoundSource& s);
 
 
 private:
 private:
 
 
@@ -103,12 +101,8 @@ private:
 	SLEngineItf						m_engine;
 	SLEngineItf						m_engine;
 
 
 	SLObjectItf 					m_out_mix_obj;
 	SLObjectItf 					m_out_mix_obj;
-	SLVolumeItf 					m_out_mix;
-	SLEnvironmentalReverbItf 		m_out_mix_env_reverb;
-
-	SLObjectItf						m_listener;
-	SL3DLocationItf					m_listener_location;
 
 
+//-----------------------------------------------------------------------------
 
 
 	IdTable 						m_buffers_id_table;
 	IdTable 						m_buffers_id_table;
 	SoundBuffer 					m_buffers[MAX_BUFFERS];
 	SoundBuffer 					m_buffers[MAX_BUFFERS];