Prechádzať zdrojové kódy

First part of the 'SoundWorld - big rewrite'

Daniele Bartolini 12 rokov pred
rodič
commit
5d48c78ab9

+ 3 - 2
engine/Android.mk

@@ -97,6 +97,9 @@ include $(CLEAR_VARS)
 
 LOCAL_MODULE    := crown
 LOCAL_SRC_FILES :=\
+\
+	audio/backend/SLESSoundWorld.cpp\
+\
 	core/bv/Circle.cpp\
 	core/bv/Frustum.cpp\
 	core/bv/Rect.cpp\
@@ -197,8 +200,6 @@ LOCAL_SRC_FILES :=\
 \
 	ConsoleServer.cpp\
 	Device.cpp\
-\
-	audio/sles/SLESRenderer.cpp\
 
 LOCAL_C_INCLUDES	:=\
 	$(LOCAL_PATH)/\

+ 2 - 6
engine/CMakeLists.txt

@@ -385,7 +385,7 @@ set (LUA_HEADERS
 set (AUDIO_SRC)
 
 set (AUDIO_HEADERS
-	audio/SoundRenderer.h
+	audio/SoundWorld.h
 	audio/OggDecoder.h
 )
 
@@ -478,11 +478,7 @@ if (LINUX)
 	)
 
 	list (APPEND AUDIO_SRC
-		audio/al/ALRenderer.cpp
-	)
-
-	list (APPEND AUDIO_HEADERS
-		audio/al/ALRenderer.h
+		audio/backend/ALSoundWorld.cpp
 	)
 
 	list (APPEND CROWN_LIBRARIES

+ 1 - 1
engine/Crown.h

@@ -140,5 +140,5 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "FontResource.h"
 
 // Engine/Audio
-#include "SoundRenderer.h"
+#include "SoundWorld.h"
 #include "OggDecoder.h"

+ 0 - 23
engine/Device.cpp

@@ -52,7 +52,6 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "TempAllocator.h"
 #include "ResourcePackage.h"
 #include "ConsoleServer.h"
-#include "SoundRenderer.h"
 #include "World.h"
 #include "LuaStack.h"
 #include "WorldManager.h"
@@ -95,7 +94,6 @@ Device::Device()
 	, m_filesystem(NULL)
 	, m_lua_environment(NULL)
 	, m_renderer(NULL)
-	, m_sound_renderer(NULL)
 
 	, m_bundle_compiler(NULL)
 	, m_console(NULL)
@@ -180,10 +178,6 @@ void Device::init()
 	m_lua_environment->init();
 	Log::d("Lua environment created.");
 
-	m_sound_renderer = CE_NEW(m_allocator, SoundRenderer)(m_allocator);
-	m_sound_renderer->init();
-	Log::d("SoundRenderer created.");
-
 	m_physx = CE_NEW(m_allocator, Physics)();
 	Log::d("Physics created.");
 
@@ -223,14 +217,6 @@ void Device::shutdown()
 		CE_DELETE(m_allocator, m_physx);
 	}
 
-	Log::d("Releasing SoundRenderer...");
-	if (m_sound_renderer)
-	{
-		m_sound_renderer->shutdown();
-
-		CE_DELETE(m_allocator, m_sound_renderer);
-	}
-
 	Log::d("Releasing LuaEnvironment...");
 	if (m_lua_environment)
 	{
@@ -323,12 +309,6 @@ Renderer* Device::renderer()
 	return m_renderer;
 }
 
-//-----------------------------------------------------------------------------
-SoundRenderer* Device::sound_renderer()
-{
-	return m_sound_renderer;
-}
-
 //-----------------------------------------------------------------------------
 Keyboard* Device::keyboard()
 {
@@ -426,9 +406,6 @@ void Device::frame()
 		}
 
 		m_renderer->frame();
-
-		// FIXME: SoundRenderer should not be updated each frame
-		m_sound_renderer->frame();
 	}
 
 	clear_lua_temporaries();

+ 0 - 5
engine/Device.h

@@ -49,7 +49,6 @@ class OsWindow;
 class Renderer;
 class ResourceManager;
 class ResourcePackage;
-class SoundRenderer;
 class Touch;
 class World;
 class WorldManager;
@@ -145,8 +144,6 @@ public:
 	OsWindow*				window();
 	Renderer*				renderer();
 
-	SoundRenderer*			sound_renderer();
-
 	Keyboard*				keyboard();
 	Mouse*					mouse();
 	Touch*					touch();
@@ -195,8 +192,6 @@ protected:
 	LuaEnvironment*			m_lua_environment;
 	Renderer*				m_renderer;
 
-	SoundRenderer*			m_sound_renderer;
-
 	// Private subsystems
 	BundleCompiler*			m_bundle_compiler;
 	ConsoleServer*			m_console;

+ 0 - 133
engine/audio/SoundRenderer.h

@@ -1,133 +0,0 @@
-/*
-Copyright (c) 2013 Daniele Bartolini, Michele Rossi
-Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
-
-Permission is hereby granted, free of charge, to any person
-obtaining a copy of this software and associated documentation
-files (the "Software"), to deal in the Software without
-restriction, including without limitation the rights to use,
-copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the
-Software is furnished to do so, subject to the following
-conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
-OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-OTHER DEALINGS IN THE SOFTWARE.
-*/
-
-#pragma once
-
-#include "IdTable.h"
-#include "Allocator.h"
-#include "Types.h"
-
-#define	MAX_SOUND_BUFFERS 64
-#define MAX_SOUND_SOURCES 64
-
-namespace crown
-{
-//-----------------------------------------------------------------------------
-class SoundRendererImpl;
-struct SoundResource;
-struct Vector3;
-
-//-----------------------------------------------------------------------------
-typedef Id	SoundBufferId;
-typedef	Id	SoundSourceId;
-
-//-----------------------------------------------------------------------------
-class SoundRenderer
-{
-public:
-							SoundRenderer(Allocator& allocator);
-
-							~SoundRenderer();
-
-	void					init();
-
-	void					shutdown();
-
-	void					pause();
-
-	void					unpause();
-
-	void					frame();
-
-	void					set_listener(const Vector3& pos, const Vector3& vel, const Vector3& or_up, const Vector3& or_at) const;
-
-	SoundBufferId			create_sound_buffer(void* data, size_t size, uint32_t sample_rate, uint32_t num_channels, uint16_t bits_ps);
-
-	void					destroy_sound_buffer(SoundBufferId id);
-
-	SoundSourceId			create_sound_source();
-
-	void					destroy_sound_source(SoundSourceId id);
-
-	void					bind_buffer(SoundBufferId buffer, SoundSourceId source);
-
-	void					unbind_buffer(SoundSourceId id);
-
-	void					play_sound(SoundSourceId id);
-
-	void					pause_sound(SoundSourceId id);
-
-	void					set_sound_loop(SoundSourceId id, bool loop);
-
-	void					set_sound_min_distance(SoundSourceId id, const float min_distance);
-
-	void					set_sound_max_distance(SoundSourceId id, const float max_distance);
-
-	void					set_sound_position(SoundSourceId id, const Vector3& pos);
-
-	void					set_sound_velocity(SoundSourceId id, const Vector3& vel);
-
-	void					set_sound_direction(SoundSourceId id, const Vector3& dir);
-
-	void					set_sound_pitch(SoundSourceId id, const float pitch);
-
-	void					set_sound_gain(SoundSourceId id, const float gain);
-
-	void					set_sound_rolloff(SoundSourceId id, const float rolloff);
-
-	float					sound_min_distance(SoundSourceId id) const;
-
-	float					sound_max_distance(SoundSourceId id) const;
-	
-	Vector3					sound_position(SoundSourceId id) const;
-
-	Vector3					sound_velocity(SoundSourceId id) const;
-
-	Vector3					sound_direction(SoundSourceId id) const;
-
-	float					sound_pitch(SoundSourceId id) const;
-
-	float					sound_gain(SoundSourceId id) const;
-
-	float					sound_rolloff(SoundSourceId id) const;
-
-	int32_t					sound_queued_buffers(SoundSourceId id) const;
-
-	int32_t					sound_processed_buffers(SoundSourceId id) const;
-
-	bool					sound_playing(SoundSourceId id);
-
-private:
-
-	Allocator& 					m_allocator;
-	SoundRendererImpl*			m_impl;
-	bool 						m_is_paused;
-
-	IdTable<MAX_SOUND_BUFFERS>	m_buffers_id_table;
-	IdTable<MAX_SOUND_SOURCES>	m_sources_id_table;
-};
-
-} // namespace crown

+ 62 - 0
engine/audio/SoundWorld.h

@@ -0,0 +1,62 @@
+/*
+Copyright (c) 2013 Daniele Bartolini, Michele Rossi
+Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#pragma once
+
+#include "Types.h"
+
+#define MAX_SOUND_INSTANCES 64
+
+namespace crown
+{
+
+class Allocator;
+struct Vector3;
+struct Matrix4x4;
+typedef Id SoundInstanceId;
+
+class SoundWorld
+{
+public:
+
+	virtual ~SoundWorld() {};
+
+	virtual SoundInstanceId play(const char* name, bool loop, float volume) = 0;
+	virtual void stop(SoundInstanceId id) = 0;
+
+	virtual void set_sound_positions(uint32_t count, const SoundInstanceId* ids, const Vector3* positions) = 0;
+	virtual void set_sound_ranges(uint32_t count, const SoundInstanceId* ids, const float* ranges) = 0;
+	virtual void set_sound_volumes(uint32_t count, const SoundInstanceId* ids, const float* volumes) = 0;
+
+	virtual void set_listener_pose(const Matrix4x4& pose) = 0;
+
+	virtual void update() = 0;
+
+	static SoundWorld* create(Allocator& a);
+	static void destroy(Allocator& a, SoundWorld* sw);
+};
+
+} // namespace crown 

+ 0 - 387
engine/audio/al/ALRenderer.cpp

@@ -1,387 +0,0 @@
-/*
-Copyright (c) 2013 Daniele Bartolini, Michele Rossi
-Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
-
-Permission is hereby granted, free of charge, to any person
-obtaining a copy of this software and associated documentation
-files (the "Software"), to deal in the Software without
-restriction, including without limitation the rights to use,
-copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the
-Software is furnished to do so, subject to the following
-conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
-OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-OTHER DEALINGS IN THE SOFTWARE.
-*/
-
-#include "SoundRenderer.h"
-#include "ALRenderer.h"
-#include "SoundResource.h"
-#include "StringUtils.h"
-#include "Log.h"
-
-namespace crown
-{
-
-// ALRenderer
-class SoundRendererImpl
-{
-public:
-	
-	//-----------------------------------------------------------------------------
-	SoundRendererImpl() :
-		m_device(NULL),
-		m_context(NULL)
-	{
-	}
-
-	//-----------------------------------------------------------------------------
-	void init()
-	{
-		m_device = alcOpenDevice(NULL);
-		
-		if (!m_device)
-		{
-			CE_ASSERT(false, "Cannot open audio device");
-		}
-
-		m_context = alcCreateContext(m_device, NULL);
-
-		if (!m_context)
-		{
-			CE_ASSERT(false, "Cannot create context");		
-		}
-
-		AL_CHECK(alcMakeContextCurrent(m_context));
-
-		AL_CHECK(alDistanceModel(AL_INVERSE_DISTANCE_CLAMPED));
-
-		AL_CHECK(alDopplerFactor(1.0f));
-		AL_CHECK(alDopplerVelocity(343.0f));
-
-		// Default listener
-		Vector3 pos(0.0f, 0.0f, 0.0f);
-		Vector3 vel(0.0f, 0.0f, 0.0f);
-		Vector3 at(0.0f, 0.0f, -1.0f);
-		Vector3 up(0.0f, 1.0f, 0.0f);
-
-		set_listener(pos, vel, at, up);		
-	}
-
-	//-----------------------------------------------------------------------------
-	void shutdown()
-	{
-		alcDestroyContext(m_context);
-	    alcCloseDevice(m_device);
-	}
-
-	//-----------------------------------------------------------------------------
-	void set_listener(const Vector3& pos, const Vector3& vel, const Vector3& or_up, const Vector3& or_at)
-	{
-		AL_CHECK(alListener3f(AL_POSITION, pos.x, pos.y, pos.z));
-		AL_CHECK(alListener3f(AL_VELOCITY, vel.x, vel.y, vel.z));
-
-		ALfloat orientation[] = { or_up.x, or_up.y, or_up.z,
-									or_at.x, or_at.y, or_at.z };
-
-		AL_CHECK(alListenerfv(AL_ORIENTATION, orientation));
-	}
-
-private:
-
-	ALCdevice*				m_device;
-	ALCcontext*				m_context;
-
-	SoundBuffer	 			m_buffers[MAX_SOUND_BUFFERS];
-	SoundSource				m_sources[MAX_SOUND_SOURCES];
-
-private:
-
-	friend class 			SoundRenderer;
-};
-
-//-----------------------------------------------------------------------------
-SoundRenderer::SoundRenderer(Allocator& allocator)
-	: m_allocator(allocator)
-{
-	m_impl = CE_NEW(m_allocator, SoundRendererImpl);
-}
-
-//-----------------------------------------------------------------------------
-SoundRenderer::~SoundRenderer()
-{
-	if (m_impl)
-	{
-		CE_DELETE(m_allocator, m_impl);
-	}
-}
-
-//-----------------------------------------------------------------------------
-void SoundRenderer::init()
-{
-	m_impl->init();
-}
-
-//-----------------------------------------------------------------------------
-void SoundRenderer::shutdown()
-{
-	m_impl->shutdown();
-}
-
-//-----------------------------------------------------------------------------
-void SoundRenderer::frame()
-{
-
-}
-
-//-----------------------------------------------------------------------------
-void SoundRenderer::set_listener(const Vector3& pos, const Vector3& vel, const Vector3& or_up, const Vector3& or_at) const
-{
-	m_impl->set_listener(pos, vel, or_up, or_at);
-}
-
-//-----------------------------------------------------------------------------
-SoundBufferId SoundRenderer::create_sound_buffer(void* data, size_t size, uint32_t sample_rate, uint32_t num_channels, uint16_t bits_ps)
-{
-	SoundBufferId id = m_buffers_id_table.create();
-
-	m_impl->m_buffers[id.index].create(sample_rate, num_channels, bits_ps);
-	m_impl->m_buffers[id.index].update(data, size);
-
-	return id;
-}
-
-//-----------------------------------------------------------------------------
-void SoundRenderer::destroy_sound_buffer(SoundBufferId id)
-{
-	CE_ASSERT(m_buffers_id_table.has(id), "SoundBuffer does not exists");
-
-	m_impl->m_buffers[id.index].destroy();
-
-	m_buffers_id_table.destroy(id);
-}
-
-//-----------------------------------------------------------------------------
-SoundSourceId SoundRenderer::create_sound_source()
-{
-	SoundSourceId id = m_sources_id_table.create();
-
-	m_impl->m_sources[id.index].create();
-
-	return id;
-}
-
-//-----------------------------------------------------------------------------
-void SoundRenderer::destroy_sound_source(SoundSourceId id)
-{
-	CE_ASSERT(m_sources_id_table.has(id), "SoundSource does not exists");
-
-	m_impl->m_sources[id.index].destroy();
-
-	m_sources_id_table.destroy(id);
-}
-
-//-----------------------------------------------------------------------------
-void SoundRenderer::bind_buffer(SoundBufferId buffer, SoundSourceId source)
-{
-	CE_ASSERT(m_buffers_id_table.has(buffer), "SoundBuffer does not exists");
-	CE_ASSERT(m_sources_id_table.has(source), "SoundSource does not exists");
-
-	m_impl->m_sources[source.index].bind_buffer(m_impl->m_buffers[buffer.index].m_id);
-}
-
-//-----------------------------------------------------------------------------
-void SoundRenderer::unbind_buffer(SoundSourceId id)
-{
-	CE_ASSERT(m_sources_id_table.has(id), "SoundSource does not exists");
-
-	m_impl->m_sources[id.index].unbind_buffer();
-}
-
-//-----------------------------------------------------------------------------
-void SoundRenderer::play_sound(SoundSourceId id)
-{
-	CE_ASSERT(m_sources_id_table.has(id), "SoundSource does not exists");
-
-	m_impl->m_sources[id.index].play();
-}
-
-//-----------------------------------------------------------------------------
-void SoundRenderer::pause_sound(SoundSourceId id)
-{
-	CE_ASSERT(m_sources_id_table.has(id), "SoundSource does not exists");
-
-	m_impl->m_sources[id.index].pause();
-}
-
-//-----------------------------------------------------------------------------
-void SoundRenderer::set_sound_loop(SoundSourceId id, bool loop)
-{
-	CE_ASSERT(m_sources_id_table.has(id), "SoundSource does not exists");
-
-	m_impl->m_sources[id.index].loop(loop);
-}
-
-//-----------------------------------------------------------------------------
-void SoundRenderer::set_sound_min_distance(SoundSourceId id, const float min_distance)
-{
-	CE_ASSERT(m_sources_id_table.has(id), "SoundSource does not exists");
-
-	m_impl->m_sources[id.index].set_min_distance(min_distance);
-}
-
-//-----------------------------------------------------------------------------
-void SoundRenderer::set_sound_max_distance(SoundSourceId id, const float max_distance)
-{
-	CE_ASSERT(m_sources_id_table.has(id), "SoundSource does not exists");
-
-	m_impl->m_sources[id.index].set_max_distance(max_distance);
-}
-
-//-----------------------------------------------------------------------------
-void SoundRenderer::set_sound_position(SoundSourceId id, const Vector3& pos)
-{
-	CE_ASSERT(m_sources_id_table.has(id), "SoundSource does not exists");
-
-	m_impl->m_sources[id.index].set_position(pos);
-}
-
-//-----------------------------------------------------------------------------
-void SoundRenderer::set_sound_velocity(SoundSourceId id, const Vector3& vel)
-{
-	CE_ASSERT(m_sources_id_table.has(id), "SoundSource does not exists");
-
-	m_impl->m_sources[id.index].set_velocity(vel);
-}
-
-//-----------------------------------------------------------------------------
-void SoundRenderer::set_sound_direction(SoundSourceId id, const Vector3& dir)
-{
-	CE_ASSERT(m_sources_id_table.has(id), "SoundSource does not exists");
-
-	m_impl->m_sources[id.index].set_direction(dir);
-}
-
-//-----------------------------------------------------------------------------
-void SoundRenderer::set_sound_pitch(SoundSourceId id, const float pitch)
-{
-	CE_ASSERT(m_sources_id_table.has(id), "SoundSource does not exists");
-
-	m_impl->m_sources[id.index].set_pitch(pitch);
-}
-
-//-----------------------------------------------------------------------------
-void SoundRenderer::set_sound_gain(SoundSourceId id, const float gain)
-{
-	CE_ASSERT(m_sources_id_table.has(id), "SoundSource does not exists");
-
-	m_impl->m_sources[id.index].set_gain(gain);
-}
-
-//-----------------------------------------------------------------------------
-void SoundRenderer::set_sound_rolloff(SoundSourceId id, const float rolloff)
-{
-	CE_ASSERT(m_sources_id_table.has(id), "SoundSource does not exists");
-
-	m_impl->m_sources[id.index].set_rolloff(rolloff);
-}
-
-//-----------------------------------------------------------------------------
-float SoundRenderer::sound_min_distance(SoundSourceId id) const
-{
-	CE_ASSERT(m_sources_id_table.has(id), "SoundSource does not exists");
-
-	return m_impl->m_sources[id.index].min_distance();
-}
-
-//-----------------------------------------------------------------------------
-float SoundRenderer::sound_max_distance(SoundSourceId id) const
-{
-	CE_ASSERT(m_sources_id_table.has(id), "SoundSource does not exists");
-
-	return m_impl->m_sources[id.index].max_distance();
-}
-
-//-----------------------------------------------------------------------------
-Vector3 SoundRenderer::sound_position(SoundSourceId id) const
-{
-	CE_ASSERT(m_sources_id_table.has(id), "SoundSource does not exists");
-
-	return m_impl->m_sources[id.index].position();
-}
-
-//-----------------------------------------------------------------------------
-Vector3 SoundRenderer::sound_velocity(SoundSourceId id) const
-{
-	CE_ASSERT(m_sources_id_table.has(id), "SoundSource does not exists");
-
-	return m_impl->m_sources[id.index].velocity();
-}
-
-//-----------------------------------------------------------------------------
-Vector3 SoundRenderer::sound_direction(SoundSourceId id) const
-{
-	CE_ASSERT(m_sources_id_table.has(id), "SoundSource does not exists");
-
-	return m_impl->m_sources[id.index].direction();
-}
-
-//-----------------------------------------------------------------------------
-float SoundRenderer::sound_pitch(SoundSourceId id) const
-{
-	CE_ASSERT(m_sources_id_table.has(id), "SoundSource does not exists");
-
-	return m_impl->m_sources[id.index].pitch();
-}
-
-//-----------------------------------------------------------------------------
-float SoundRenderer::sound_gain(SoundSourceId id) const
-{
-	CE_ASSERT(m_sources_id_table.has(id), "SoundSource does not exists");
-
-	return m_impl->m_sources[id.index].gain();
-}
-
-//-----------------------------------------------------------------------------
-float SoundRenderer::sound_rolloff(SoundSourceId id) const
-{
-	CE_ASSERT(m_sources_id_table.has(id), "SoundSource does not exists");
-
-	return m_impl->m_sources[id.index].rolloff();
-}
-
-//-----------------------------------------------------------------------------
-int32_t SoundRenderer::sound_queued_buffers(SoundSourceId id) const
-{
-	CE_ASSERT(m_sources_id_table.has(id), "SoundSource does not exists");
-
-	return m_impl->m_sources[id.index].queued_buffers();
-}
-
-//-----------------------------------------------------------------------------
-int32_t SoundRenderer::sound_processed_buffers(SoundSourceId id) const
-{
-	CE_ASSERT(m_sources_id_table.has(id), "SoundSource does not exists");
-
-	return m_impl->m_sources[id.index].processed_buffers();
-}
-
-//-----------------------------------------------------------------------------
-bool SoundRenderer::sound_playing(SoundSourceId id)
-{
-	CE_ASSERT(m_sources_id_table.has(id), "SoundSource does not exists");
-
-	return m_impl->m_sources[id.index].is_playing();
-}
-
-} // namespace crown

+ 0 - 348
engine/audio/al/ALRenderer.h

@@ -1,348 +0,0 @@
-/*
-Copyright (c) 2013 Daniele Bartolini, Michele Rossi
-Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
-
-Permission is hereby granted, free of charge, to any person
-obtaining a copy of this software and associated documentation
-files (the "Software"), to deal in the Software without
-restriction, including without limitation the rights to use,
-copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the
-Software is furnished to do so, subject to the following
-conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
-OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-OTHER DEALINGS IN THE SOFTWARE.
-*/
-
-#pragma once
-
-#include <AL/al.h>
-#include <AL/alc.h>
-
-#include "SoundResource.h"
-#include "Vector3.h"
-#include "Log.h"
-
-namespace crown
-{
-
-//-----------------------------------------------------------------------------
-static const char* al_error_to_string(ALenum error)
-{
-	switch (error)
-	{
-		case AL_INVALID_ENUM: return "AL_INVALID_ENUM";
-		case AL_INVALID_VALUE: return "AL_INVALID_VALUE";
-		case AL_INVALID_OPERATION: return "AL_INVALID_OPERATION";
-		case AL_OUT_OF_MEMORY: return "AL_OUT_OF_MEMORY";
-		default: return "UNKNOWN_AL_ERROR";
-	}
-}
-
-//-----------------------------------------------------------------------------
-#ifdef CROWN_DEBUG
-	#define AL_CHECK(function)\
-		function;\
-		do { ALenum error; CE_ASSERT((error = alGetError()) == AL_NO_ERROR,\
-				"OpenAL error: %s", al_error_to_string(error)); } while (0)
-#else
-	#define AL_CHECK(function)\
-		function;
-#endif
-
-//-----------------------------------------------------------------------------
-struct SoundBuffer
-{
-	//-----------------------------------------------------------------------------
-	void create(uint32_t sample_rate, uint32_t num_channels, uint16_t bits_ps)
-	{
-		// Generates AL buffers
-		AL_CHECK(alGenBuffers(1, &m_id));
-
-		// TODO: check sample rate validity
-		m_sample_rate = sample_rate;
-		
-		switch(bits_ps)
-		{
-			case 8:
-			{
-				m_format = num_channels > 1 ? AL_FORMAT_STEREO8 : AL_FORMAT_MONO8;
-				break;
-			}
-			case 16:
-			{
-				m_format = num_channels > 1 ? AL_FORMAT_STEREO16 : AL_FORMAT_MONO16;
-				break;
-			}
-			default:
-			{
-				CE_ASSERT(false, "Wrong number of bits per sample.");
-			}
-		}
-	}
-
-	//-----------------------------------------------------------------------------
-	void update(void* data, size_t size)
-	{
-		AL_CHECK(alBufferData(m_id, m_format, data, size, m_sample_rate));
-	}
-
-	//-----------------------------------------------------------------------------
-	void destroy()
-	{
-		AL_CHECK(alDeleteBuffers(1, &m_id));
-	}
-
-public:
-
-	ALuint			m_id;
-	ALuint 			m_format;
-	uint32_t		m_sample_rate;
-};
-
-//-----------------------------------------------------------------------------
-struct SoundSource
-{
-	//-----------------------------------------------------------------------------
-	void create()
-	{
-		AL_CHECK(alGenSources(1, &m_id));
-/*
-		AL_CHECK(alSourcef(m_id, AL_PITCH, 1.0f));
-		AL_CHECK(alSourcef(m_id, AL_REFERENCE_DISTANCE, 0.1f));
-		AL_CHECK(alSourcef(m_id, AL_MAX_DISTANCE, 1000.0f));
-*/
-	}
-
-	//-----------------------------------------------------------------------------
-	void destroy()
-	{
-		AL_CHECK(alDeleteSources(1, &m_id));
-	}
-
-	//-----------------------------------------------------------------------------
-	void bind_buffer(ALuint buffer)
-	{
-		AL_CHECK(alSourceQueueBuffers(m_id, 1, &buffer));
-	}
-
-	//-----------------------------------------------------------------------------
-	ALuint unbind_buffer()
-	{
-		ALuint buffer;
-
-		AL_CHECK(alSourceUnqueueBuffers(m_id, 1, &buffer));
-
-		return buffer;
-	}
-
-	//-----------------------------------------------------------------------------
-	void play()
-	{
-		AL_CHECK(alSourcePlay(m_id));
-
-		m_playing = true;
-	}
-
-	//-----------------------------------------------------------------------------
-	void pause()
-	{
-		AL_CHECK(alSourcePause(m_id));
-
-		m_playing = false;
-	}
-
-	//-----------------------------------------------------------------------------
-	void loop(bool loop)
-	{
-		ALint value = loop ? AL_TRUE : AL_FALSE;
-		
-		AL_CHECK(alSourcei(m_id, AL_LOOPING, value));
-
-		m_looping = loop;
-	}
-
-	//-----------------------------------------------------------------------------
-	void set_min_distance(const float min_distance)
-	{
-		AL_CHECK(alSourcef(m_id, AL_REFERENCE_DISTANCE, min_distance));
-	}
-
-	//-----------------------------------------------------------------------------
-	void set_max_distance( const float max_distance)
-	{
-		AL_CHECK(alSourcef(m_id, AL_MAX_DISTANCE, max_distance));
-	}
-
-	//-----------------------------------------------------------------------------
-	void set_position(const Vector3& pos)
-	{
-		AL_CHECK(alSource3f(m_id, AL_POSITION, pos.x, pos.y, pos.z));
-	}
-
-	//-----------------------------------------------------------------------------
-	void set_velocity(const Vector3& vel)
-	{
-		AL_CHECK(alSource3f(m_id, AL_VELOCITY, vel.x, vel.y, vel.z));
-	}
-
-	//-----------------------------------------------------------------------------
-	void set_direction(const Vector3& dir)
-	{
-		AL_CHECK(alSource3f(m_id, AL_DIRECTION, dir.x, dir.y, dir.z));
-	}
-
-	//-----------------------------------------------------------------------------
-	void set_pitch(const float pitch)
-	{
-		AL_CHECK(alSourcef(m_id, AL_PITCH, pitch));
-	}
-
-	//-----------------------------------------------------------------------------
-	void set_gain(const float gain)
-	{
-		AL_CHECK(alSourcef(m_id, AL_GAIN, gain));
-	}
-
-	//-----------------------------------------------------------------------------
-	void set_rolloff(const float rolloff)
-	{
-		AL_CHECK(alSourcef(m_id, AL_ROLLOFF_FACTOR, rolloff));
-	}
-
-	//-----------------------------------------------------------------------------
-	float min_distance() const
-	{
-		ALfloat min_distance;
-
-		alGetSourcef(m_id, AL_REFERENCE_DISTANCE, &min_distance);
-
-		return min_distance;
-	}
-
-	//-----------------------------------------------------------------------------
-	float max_distance() const
-	{
-		ALfloat max_distance;
-
-		alGetSourcef(m_id, AL_MAX_DISTANCE, &max_distance);
-
-		return max_distance;
-	}
-
-	//-----------------------------------------------------------------------------
-	Vector3 position() const
-	{
-		ALfloat tmp[3];
-		alGetSourcefv(m_id, AL_POSITION, tmp);
-
-		Vector3 pos;
-		pos.x = tmp[0];
-		pos.y = tmp[1];
-		pos.z = tmp[2];
-
-		return pos;
-	}
-
-	//-----------------------------------------------------------------------------
-	Vector3 velocity() const
-	{
-		ALfloat tmp[3];
-		alGetSourcefv(m_id, AL_VELOCITY, tmp);
-
-		Vector3 vel;
-		vel.x = tmp[0];
-		vel.y = tmp[1];
-		vel.z = tmp[2];
-
-		return vel;
-	}
-
-	//-----------------------------------------------------------------------------
-	Vector3 direction() const
-	{
-		ALfloat tmp[3];
-		alGetSourcefv(m_id, AL_DIRECTION, tmp);
-
-		Vector3 dir;
-		dir.x = tmp[0];
-		dir.y = tmp[1];
-		dir.z = tmp[2];
-
-		return dir;	
-	}
-
-	//-----------------------------------------------------------------------------
-	float pitch() const
-	{
-		ALfloat pitch;
-		alGetSourcef(m_id, AL_PITCH, &pitch);
-
-		return pitch;
-	}
-
-	//-----------------------------------------------------------------------------
-	float gain() const
-	{
-		ALfloat gain;
-		alGetSourcef(m_id, AL_GAIN, &gain);
-
-		return gain;
-	}
-
-	//-----------------------------------------------------------------------------
-	float rolloff() const
-	{
-		ALfloat rolloff;
-		alGetSourcef(m_id, AL_ROLLOFF_FACTOR, &rolloff);
-
-		return rolloff;
-	}
-
-	//-----------------------------------------------------------------------------
-	bool is_playing() const
-	{
-		ALint source_state;
-		alGetSourcei(m_id, AL_SOURCE_STATE, &source_state);
-
-		return source_state == AL_PLAYING;
-	}
-
-	//-----------------------------------------------------------------------------
-	int32_t queued_buffers()
-	{
-		int32_t queued;
-		alGetSourcei(m_id, AL_BUFFERS_QUEUED, &queued);
-
-		return queued;
-	}
-
-	//-----------------------------------------------------------------------------
-	int32_t processed_buffers()
-	{
-		int32_t processed;
-		alGetSourcei(m_id, AL_BUFFERS_PROCESSED, &processed);
-
-		return processed;
-	}
-
-public:
-
-	ALuint			m_id;
-
-	bool			m_playing :1;
-	bool			m_looping :1;
-	bool			m_positional :1;
-};
-
-} // namespace crown

+ 277 - 0
engine/audio/backend/ALSoundWorld.cpp

@@ -0,0 +1,277 @@
+/*
+Copyright (c) 2013 Daniele Bartolini, Michele Rossi
+Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include <AL/al.h>
+#include <AL/alc.h>
+
+#include "SoundWorld.h"
+#include "IdArray.h"
+#include "Allocator.h"
+#include "Vector3.h"
+#include "Matrix4x4.h"
+#include "Resource.h"
+#include "Device.h"
+#include "ResourceManager.h"
+#include "SoundResource.h"
+#include "List.h"
+#include "TempAllocator.h"
+
+namespace crown
+{
+
+//-----------------------------------------------------------------------------
+static const char* al_error_to_string(ALenum error)
+{
+	switch (error)
+	{
+		case AL_INVALID_ENUM: return "AL_INVALID_ENUM";
+		case AL_INVALID_VALUE: return "AL_INVALID_VALUE";
+		case AL_INVALID_OPERATION: return "AL_INVALID_OPERATION";
+		case AL_OUT_OF_MEMORY: return "AL_OUT_OF_MEMORY";
+		default: return "UNKNOWN_AL_ERROR";
+	}
+}
+
+//-----------------------------------------------------------------------------
+#ifdef CROWN_DEBUG
+	#define AL_CHECK(function)\
+		function;\
+		do { ALenum error; CE_ASSERT((error = alGetError()) == AL_NO_ERROR,\
+				"OpenAL error: %s", al_error_to_string(error)); } while (0)
+#else
+	#define AL_CHECK(function) function;
+#endif
+
+//-----------------------------------------------------------------------------
+struct SoundInstance
+{
+	void create(SoundResource* sr)
+	{
+		AL_CHECK(alGenSources(1, &m_source));
+
+		// AL_CHECK(alSourcef(m_source, AL_PITCH, 1.0f));
+		// AL_CHECK(alSourcef(m_source, AL_REFERENCE_DISTANCE, 0.1f));
+		// AL_CHECK(alSourcef(m_source, AL_MAX_DISTANCE, 1000.0f));
+
+		// Generates AL buffers
+		AL_CHECK(alGenBuffers(1, &m_buffer));
+
+		ALenum format;
+		switch (sr->bits_ps())
+		{
+			case 8: format = sr->channels() > 1 ? AL_FORMAT_STEREO8 : AL_FORMAT_MONO8; break;
+			case 16: format = sr->channels() > 1 ? AL_FORMAT_STEREO16 : AL_FORMAT_MONO16; break;
+			default: CE_FATAL("Number of bits per sample not supported."); break;
+		}
+		AL_CHECK(alBufferData(m_buffer, format, sr->data(), sr->size(), sr->sample_rate()));
+
+		m_resource = sr;
+	}
+
+	void destroy()
+	{
+		stop();
+		AL_CHECK(alDeleteBuffers(1, &m_buffer));
+		AL_CHECK(alDeleteSources(1, &m_source));
+	}
+
+	void play(bool loop, float volume)
+	{
+		set_volume(volume);
+		AL_CHECK(alSourcei(m_source, AL_LOOPING, (loop ? AL_TRUE : AL_FALSE)));
+		AL_CHECK(alSourceQueueBuffers(m_source, 1, &m_buffer));
+		AL_CHECK(alSourcePlay(m_source));
+	}
+
+	void pause()
+	{
+		AL_CHECK(alSourcePause(m_source));
+	}
+
+	void stop()
+	{
+		ALuint buffer;
+		AL_CHECK(alSourceUnqueueBuffers(m_source, 1, &buffer));
+	}
+
+	bool finished()
+	{
+		ALint state;
+		AL_CHECK(alGetSourcei(m_source, AL_SOURCE_STATE, &state));
+		return !(state == AL_PLAYING);
+	}
+
+	void set_position(const Vector3& pos)
+	{
+		AL_CHECK(alSourcefv(m_source, AL_POSITION, pos.to_float_ptr()));
+	}
+
+	void set_range(float range)
+	{
+	}
+
+	void set_volume(float volume)
+	{
+		AL_CHECK(alSourcef(m_source, AL_GAIN, volume));
+	}
+
+public:
+
+	SoundInstanceId m_id;
+	SoundResource* m_resource;
+	ALuint m_buffer;
+	ALuint m_source;
+};
+
+class ALSoundWorld : public SoundWorld
+{
+public:
+
+	ALSoundWorld()
+	{
+		m_device = alcOpenDevice(NULL);
+		CE_ASSERT(m_device, "Cannot open OpenAL audio device");
+
+		m_context = alcCreateContext(m_device, NULL);
+		CE_ASSERT(m_context, "Cannot create OpenAL context");
+
+		AL_CHECK(alcMakeContextCurrent(m_context));
+
+		AL_CHECK(alDistanceModel(AL_INVERSE_DISTANCE_CLAMPED));
+
+		AL_CHECK(alDopplerFactor(1.0f));
+		AL_CHECK(alDopplerVelocity(343.0f));
+
+		set_listener_pose(Matrix4x4::IDENTITY);
+	}
+
+	virtual ~ALSoundWorld()
+	{
+		alcDestroyContext(m_context);
+	    alcCloseDevice(m_device);
+	}
+
+	virtual SoundInstanceId play(const char* name, bool loop, float volume)
+	{
+		return play((SoundResource*) device()->resource_manager()->lookup(SOUND_EXTENSION, name), loop, volume);
+	}
+
+	SoundInstanceId play(SoundResource* sr, bool loop, float volume)
+	{
+		SoundInstance instance;
+		instance.create(sr);
+		SoundInstanceId id = m_playing_sounds.create(instance);
+		m_playing_sounds.lookup(id).m_id = id;
+		instance.play(loop, volume);
+	}
+
+	virtual void stop(SoundInstanceId id)
+	{
+		SoundInstance& instance = m_playing_sounds.lookup(id);
+		instance.destroy();
+		m_playing_sounds.destroy(id);
+	}
+
+	virtual void set_sound_positions(uint32_t count, const SoundInstanceId* ids, const Vector3* positions)
+	{
+		for (uint32_t i = 0; i < m_playing_sounds.size(); i++)
+		{
+			m_playing_sounds[i].set_position(positions[i]);
+		}
+	}
+
+	virtual void set_sound_ranges(uint32_t count, const SoundInstanceId* ids, const float* ranges)
+	{
+		for (uint32_t i = 0; i < m_playing_sounds.size(); i++)
+		{
+			m_playing_sounds[i].set_range(ranges[i]);
+		}
+	}
+
+	virtual void set_sound_volumes(uint32_t count, const SoundInstanceId* ids, const float* volumes)
+	{
+		for (uint32_t i = 0; i < m_playing_sounds.size(); i++)
+		{
+			m_playing_sounds[i].set_volume(volumes[i]);
+		}		
+	}
+
+	virtual void set_listener_pose(const Matrix4x4& pose)
+	{
+		const Vector3 pos = pose.translation();
+		const Vector3 up = pose.y();
+		const Vector3 at = -pose.z();
+
+		AL_CHECK(alListener3f(AL_POSITION, pos.x, pos.y, pos.z));
+		//AL_CHECK(alListener3f(AL_VELOCITY, vel.x, vel.y, vel.z));
+
+		const ALfloat orientation[] = { up.x, up.y, up.z, at.x, at.y, at.z };
+		AL_CHECK(alListenerfv(AL_ORIENTATION, orientation));
+		m_listener_pose = pose;
+	}
+
+	virtual void update()
+	{
+		TempAllocator256 alloc;
+		List<SoundInstanceId> to_delete(alloc);
+
+		// Check what sounds finished playing
+		for (uint32_t i = 0; i < m_playing_sounds.size(); i++)
+		{
+			SoundInstance& instance = m_playing_sounds[i];
+			if (instance.finished())
+			{
+				to_delete.push_back(instance.m_id);
+			}
+		}
+
+		// Destroy instances which finished playing
+		for (uint32_t i = 0; i < to_delete.size(); i++)
+		{
+			stop(to_delete[i]);
+		}
+	}
+
+private:
+
+	IdArray<MAX_SOUND_INSTANCES, SoundInstance> m_playing_sounds;
+	Matrix4x4 m_listener_pose;
+
+	ALCdevice* m_device;
+	ALCcontext* m_context;
+};
+
+SoundWorld* SoundWorld::create(Allocator& a)
+{
+	return CE_NEW(a, ALSoundWorld)();
+}
+
+void SoundWorld::destroy(Allocator& a, SoundWorld* sw)
+{
+	CE_DELETE(a, sw);
+}
+
+} // namespace crown

+ 439 - 0
engine/audio/backend/SLESSoundWorld.cpp

@@ -0,0 +1,439 @@
+/*
+Copyright (c) 2013 Daniele Bartolini, Michele Rossi
+Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+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 "SoundWorld.h"
+#include "IdArray.h"
+#include "Allocator.h"
+#include "Vector3.h"
+#include "Matrix4x4.h"
+#include "Resource.h"
+#include "Device.h"
+#include "ResourceManager.h"
+#include "SoundResource.h"
+#include "List.h"
+#include "TempAllocator.h"
+#include "Queue.h"
+
+namespace crown
+{
+
+static const char* sles_error_to_string(SLresult result)
+{
+	switch (result)
+	{
+	case SL_RESULT_SUCCESS: return "SL_RESULT_SUCCESS";
+	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";
+	case SL_RESULT_IO_ERROR: return "SL_RESULT_IO_ERROR";
+	case SL_RESULT_PRECONDITIONS_VIOLATED: return "SL_RESULT_PRECONDITIONS_VIOLATED";
+	case SL_RESULT_CONTENT_CORRUPTED: return "SL_RESULT_CONTENT_CORRUPTED";
+	case SL_RESULT_CONTENT_UNSUPPORTED: return "SL_RESULT_CONTENT_UNSUPPORTED";
+	case SL_RESULT_CONTENT_NOT_FOUND: return "SL_RESULT_CONTENT_NOT_FOUND";
+	case SL_RESULT_PERMISSION_DENIED: return "SL_RESULT_PERMISSION_DENIED";
+	case SL_RESULT_BUFFER_INSUFFICIENT: return "SL_RESULT_BUFFER_INSUFFICIENT";
+	default: return "SL_RESULT_UNKNOWN";
+	}
+}
+
+//-----------------------------------------------------------------------------
+void check_sles_errors(SLresult result)
+{
+	CE_ASSERT(result == SL_RESULT_SUCCESS, "SL_ERROR_CODE: %s", sles_error_to_string(result));
+}
+
+namespace sles_sound_world
+{
+	// Queue of instances to stop at next update()
+	static Queue<SoundInstanceId>* s_stop_queue = NULL;
+
+	void init()
+	{
+		s_stop_queue = CE_NEW(default_allocator(), Queue<SoundInstanceId>)(default_allocator());
+	}
+
+	void shutdown()
+	{
+		CE_DELETE(default_allocator(), s_stop_queue);
+	}
+
+	static void player_callback(SLPlayItf caller, void* context, SLuint32 event)
+	{
+		SoundInstanceId id;
+		id.decode((uint32_t) context);
+
+		s_stop_queue->push_back(id);
+	}
+
+	static SLmillibel gain_to_attenuation(SLVolumeItf vol_itf, float volume)
+	{
+		SLmillibel volume_mb;
+		if (volume <= 0.02f) return SL_MILLIBEL_MIN;
+		else if (volume >= 1.0f)
+		{
+			(*vol_itf)->GetMaxVolumeLevel(vol_itf, &volume_mb);
+			return volume_mb;
+		}
+
+		volume_mb = M_LN2 / log(1.0f / (1.0f - volume)) * -1000.0f;
+		if (volume_mb > 0) volume_mb = SL_MILLIBEL_MIN;
+		return volume_mb;
+	}
+}
+
+//-----------------------------------------------------------------------------
+struct SoundInstance
+{
+	void create(SLEngineItf engine, SLObjectItf out_mix_obj, SoundInstanceId id, SoundResource* sr)
+	{
+		m_sl_engine = engine;
+		m_out_mix_obj = out_mix_obj;
+		m_resource = sr;
+		m_finished = false;
+		m_id = id;
+
+		// Configures buffer queue
+		SLDataLocator_AndroidSimpleBufferQueue buffer_queue = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2};
+
+		// Configures audio format
+		SLDataFormat_PCM format_pcm;
+		format_pcm.formatType = SL_DATAFORMAT_PCM;
+
+		// Sets channels
+		switch (sr->channels())
+		{
+			case 1:
+			{
+				format_pcm.numChannels = 1;
+				format_pcm.channelMask = SL_SPEAKER_FRONT_CENTER;
+				break;
+			}
+			case 2:
+			{
+				format_pcm.numChannels = 2;
+				format_pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
+				break;
+			}
+			default:
+			{
+				CE_FATAL("Oops, wrong number of channels");
+				break;
+			}
+		}
+
+		// Sets sample rate
+		switch (sr->sample_rate())
+		{
+			case 8000: format_pcm.samplesPerSec = SL_SAMPLINGRATE_8; break;
+			case 11025: format_pcm.samplesPerSec = SL_SAMPLINGRATE_11_025; break;
+			case 16000: format_pcm.samplesPerSec = SL_SAMPLINGRATE_16; break;
+			case 22050: format_pcm.samplesPerSec = SL_SAMPLINGRATE_22_05; break;
+			case 24000: format_pcm.samplesPerSec = SL_SAMPLINGRATE_24; break;
+			case 32000: format_pcm.samplesPerSec = SL_SAMPLINGRATE_32; break;
+			case 44100: format_pcm.samplesPerSec = SL_SAMPLINGRATE_44_1; break;
+			case 48000: format_pcm.samplesPerSec = SL_SAMPLINGRATE_48; break;
+			case 64000: format_pcm.samplesPerSec = SL_SAMPLINGRATE_64; break;
+			case 88200: format_pcm.samplesPerSec = SL_SAMPLINGRATE_88_2; break;
+			case 96000: format_pcm.samplesPerSec = SL_SAMPLINGRATE_96; break;
+			case 192000: format_pcm.samplesPerSec = SL_SAMPLINGRATE_192; break;
+			default: CE_FATAL("Oops, sample rate not supported"); break;
+		}	
+		
+		format_pcm.samplesPerSec = SL_SAMPLINGRATE_44_1;
+		format_pcm.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16;
+		format_pcm.containerSize = SL_PCMSAMPLEFORMAT_FIXED_16;
+		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};
+
+		SLresult result = (*m_sl_engine)->CreateAudioPlayer(m_sl_engine, &m_player_obj, &audio_source, &audio_sink, 3, ids, reqs);
+		check_sles_errors(result);
+
+		result = (*m_player_obj)->Realize(m_player_obj, SL_BOOLEAN_FALSE);
+		check_sles_errors(result);
+
+		// Gets interfaces
+		result = (*m_player_obj)->GetInterface(m_player_obj, SL_IID_PLAY, &m_player_play);
+		check_sles_errors(result);
+
+		result = (*m_player_obj)->GetInterface(m_player_obj, SL_IID_BUFFERQUEUE, &m_player_bufferqueue);
+		check_sles_errors(result);
+
+		result = (*m_player_obj)->GetInterface(m_player_obj, SL_IID_VOLUME, &m_player_volume);
+		check_sles_errors(result);
+
+		//(*m_player_bufferqueue)->RegisterCallback(m_player_bufferqueue, SoundInstance::buffer_callback, this);
+		(*m_player_play)->SetCallbackEventsMask(m_player_play, SL_PLAYEVENT_HEADATEND);
+		(*m_player_play)->RegisterCallback(m_player_play, sles_sound_world::player_callback, (void*) id.encode());
+
+		// Manage simple sound or stream
+		// m_streaming = sr->sound_type() == SoundType::OGG;
+
+		// if (m_streaming)
+		// {
+		// 	m_decoder.init((char*)sr->data(), sr->size());
+
+		// 	m_decoder.stream();
+		// 	(*m_player_bufferqueue)->Enqueue(m_player_bufferqueue, m_decoder.data(), m_decoder.size());
+		// }
+		// else
+		{
+			(*m_player_bufferqueue)->Enqueue(m_player_bufferqueue, sr->data(), sr->size());
+		}
+	}
+
+	void destroy()
+	{
+		// if (m_streaming)
+		// {
+		// 	m_decoder.shutdown();
+		// }
+		stop();
+		(*m_player_bufferqueue)->Clear(m_player_bufferqueue);
+		(*m_player_obj)->AbortAsyncOperation(m_player_obj);
+		(*m_player_obj)->Destroy(m_player_obj);
+	}
+
+	void play(bool loop, float volume)
+	{
+		set_volume(volume);
+		SLresult result = (*m_player_play)->SetPlayState(m_player_play, SL_PLAYSTATE_PLAYING);
+		check_sles_errors(result);
+	}
+
+	void pause()
+	{
+		SLresult result = (*m_player_play)->SetPlayState(m_player_play, SL_PLAYSTATE_PAUSED);
+		check_sles_errors(result);
+	}
+
+	void stop()
+	{
+		SLresult res = (*m_player_play)->SetPlayState(m_player_play, SL_PLAYSTATE_STOPPED);
+		check_sles_errors(res);
+	}
+
+	bool finished()
+	{
+		return m_finished;
+	}
+
+	void set_volume(float volume)
+	{
+		SLresult res = (*m_player_volume)->SetVolumeLevel(m_player_volume, sles_sound_world::gain_to_attenuation(m_player_volume, volume));
+		check_sles_errors(res);
+	}
+
+	void set_range(float range)
+	{
+	}
+
+	void set_position(const Vector3& pos)
+	{
+	}
+
+	static void buffer_callback(SLAndroidSimpleBufferQueueItf caller, void* context)
+	{
+		SoundInstance* s = (SoundInstance*) context;
+
+		// if (s->is_playing())
+		// {
+		// 	s->m_processed_buffers++;
+
+		// 	if (s->m_decoder.stream())
+		// 	{
+		// 		(*s->m_player_bufferqueue)->Enqueue(s->m_player_bufferqueue, s->m_decoder.data(), s->m_decoder.size());
+		// 	}
+		// 	else if (s->m_looping)
+		// 	{
+		// 		s->m_decoder.rewind();
+		// 		s->m_decoder.stream();
+		// 		(*s->m_player_bufferqueue)->Enqueue(s->m_player_bufferqueue, s->m_decoder.data(), s->m_decoder.size());	
+		// 	}
+		// 	else
+		// 	{
+		// 		s->pause();
+		// 	}
+		// }
+	}
+
+public:
+
+	SoundInstanceId m_id;
+	SoundResource* m_resource;
+
+	SLEngineItf m_sl_engine;
+	SLObjectItf m_out_mix_obj;
+	SLObjectItf m_player_obj;
+	SLPlayItf m_player_play;
+	SLAndroidSimpleBufferQueueItf m_player_bufferqueue;
+	SLVolumeItf m_player_volume;
+
+	uint32_t m_processed_buffers;
+	bool m_finished;
+	// OggDecoder m_decoder;
+};
+
+class SLESSoundWorld : public SoundWorld
+{
+public:
+
+	SLESSoundWorld()
+		: m_to_stop(default_allocator())
+	{
+		sles_sound_world::init();
+		SLresult result;
+
+		const SLInterfaceID ids[] = {SL_IID_ENGINE};
+		const SLboolean reqs[] = {SL_BOOLEAN_TRUE};
+		const SLEngineOption opts[] = { (SLuint32) SL_ENGINEOPTION_THREADSAFE, (SLuint32) SL_BOOLEAN_TRUE };
+
+		result = slCreateEngine(&m_sl_object, 1, opts, 1, ids, reqs);
+		result = (*m_sl_object)->Realize(m_sl_object, SL_BOOLEAN_FALSE);
+
+		result = (*m_sl_object)->GetInterface(m_sl_object, SL_IID_ENGINE, &m_sl_engine);
+
+		const SLInterfaceID ids1[] = {SL_IID_VOLUME};
+		const SLboolean reqs1[] = {SL_BOOLEAN_FALSE};
+
+		result = (*m_sl_engine)->CreateOutputMix(m_sl_engine, &m_out_mix_obj, 1, ids1, reqs1); 
+		result = (*m_out_mix_obj)->Realize(m_out_mix_obj, SL_BOOLEAN_FALSE);
+	}
+
+	virtual ~SLESSoundWorld()
+	{
+		(*m_out_mix_obj)->Destroy(m_out_mix_obj);
+		(*m_sl_object)->Destroy(m_sl_object);
+		sles_sound_world::shutdown();
+	}
+
+	virtual SoundInstanceId play(const char* name, bool loop, float volume)
+	{
+		return play((SoundResource*) device()->resource_manager()->lookup(SOUND_EXTENSION, name), loop, volume);
+	}
+
+	SoundInstanceId play(SoundResource* sr, bool loop, float volume)
+	{
+		SoundInstance dummy;
+		SoundInstanceId id = m_playing_sounds.create(dummy);
+
+		SoundInstance& instance = m_playing_sounds.lookup(id);
+		instance.create(m_sl_engine, m_out_mix_obj, id, sr);
+		instance.play(loop, volume);
+	}
+
+	virtual void stop(SoundInstanceId id)
+	{
+		SoundInstance& instance = m_playing_sounds.lookup(id);
+		instance.destroy();
+		m_playing_sounds.destroy(id);
+	}
+
+	virtual void set_sound_positions(uint32_t count, const SoundInstanceId* ids, const Vector3* positions)
+	{
+		for (uint32_t i = 0; i < m_playing_sounds.size(); i++)
+		{
+			m_playing_sounds[i].set_position(positions[i]);
+		}
+	}
+
+	virtual void set_sound_ranges(uint32_t count, const SoundInstanceId* ids, const float* ranges)
+	{
+		for (uint32_t i = 0; i < m_playing_sounds.size(); i++)
+		{
+			m_playing_sounds[i].set_range(ranges[i]);
+		}
+	}
+
+	virtual void set_sound_volumes(uint32_t count, const SoundInstanceId* ids, const float* volumes)
+	{
+		for (uint32_t i = 0; i < m_playing_sounds.size(); i++)
+		{
+			m_playing_sounds[i].set_volume(volumes[i]);
+		}
+	}
+
+	virtual void set_listener_pose(const Matrix4x4& pose)
+	{
+		m_listener_pose = pose;
+	}
+
+	virtual void update()
+	{
+		const uint32_t num_to_stop = sles_sound_world::s_stop_queue->size();
+		for (uint32_t i = 0; i < num_to_stop; i++)
+		{
+			const SoundInstanceId id = sles_sound_world::s_stop_queue->front();
+			sles_sound_world::s_stop_queue->pop_front();
+
+			if (!m_playing_sounds.has(id)) continue;
+			stop(id);
+		}
+	}
+
+private:
+
+	IdArray<MAX_SOUND_INSTANCES, SoundInstance> m_playing_sounds;
+	Matrix4x4 m_listener_pose;
+	Queue<SoundInstanceId> m_to_stop;
+
+	SLObjectItf m_sl_object;
+	SLEngineItf m_sl_engine;
+	SLObjectItf m_out_mix_obj;
+};
+
+SoundWorld* SoundWorld::create(Allocator& a)
+{
+	return CE_NEW(a, SLESSoundWorld)();
+}
+
+void SoundWorld::destroy(Allocator& a, SoundWorld* sw)
+{
+	CE_DELETE(a, sw);
+}
+
+} // namespace crown

+ 0 - 135
engine/audio/sles/SLESRenderer.cpp

@@ -1,135 +0,0 @@
-/*
-Copyright (c) 2013 Daniele Bartolini, Michele Rossi
-Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
-
-Permission is hereby granted, free of charge, to any person
-obtaining a copy of this software and associated documentation
-files (the "Software"), to deal in the Software without
-restriction, including without limitation the rights to use,
-copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the
-Software is furnished to do so, subject to the following
-conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
-OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-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 "Assert.h"
-#include "SoundRenderer.h"
-#include "SLESRenderer.h"
-#include "Vector3.h"
-
-namespace crown
-{
-
-//-----------------------------------------------------------------------------
-class SoundRendererImpl
-{
-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()
-	{
-		// for (uint32_t i = 0; i < MAX_SOUNDS; i++)
-		// {
-		// 	m_sounds[i].destroy();
-		// }
-
-		// 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;
-		// }
-	}
-
-public:
-
-	SLObjectItf						m_engine_obj;
-	SLEngineItf						m_engine;
-
-	SLObjectItf 					m_out_mix_obj;
-
-private:
-
-	friend class SoundRenderer;
-};
-
-SoundRenderer::SoundRenderer(Allocator& allocator) : m_allocator(allocator) {}
-SoundRenderer::~SoundRenderer() {}
-void SoundRenderer::init() {}
-void SoundRenderer::shutdown() {}
-void SoundRenderer::pause() {}
-void SoundRenderer::unpause() {}
-void SoundRenderer::frame() {}
-void SoundRenderer::set_listener(const Vector3& pos, const Vector3& vel, const Vector3& or_up, const Vector3& or_at) const {}
-SoundBufferId SoundRenderer::create_sound_buffer(void* data, size_t size, uint32_t sample_rate, uint32_t num_channels, uint16_t bits_ps) {}
-void SoundRenderer::destroy_sound_buffer(SoundBufferId id) {}
-SoundSourceId SoundRenderer::create_sound_source() {}
-void SoundRenderer::destroy_sound_source(SoundSourceId id) {}
-void SoundRenderer::bind_buffer(SoundBufferId buffer, SoundSourceId source) {}
-void SoundRenderer::unbind_buffer(SoundSourceId id) {}
-void SoundRenderer::play_sound(SoundSourceId id) {}
-void SoundRenderer::pause_sound(SoundSourceId id) {}
-void SoundRenderer::set_sound_loop(SoundSourceId id, bool loop) {}
-void SoundRenderer::set_sound_min_distance(SoundSourceId id, const float min_distance) {}
-void SoundRenderer::set_sound_max_distance(SoundSourceId id, const float max_distance) {}
-void SoundRenderer::set_sound_position(SoundSourceId id, const Vector3& pos) {}
-void SoundRenderer::set_sound_velocity(SoundSourceId id, const Vector3& vel) {}
-void SoundRenderer::set_sound_direction(SoundSourceId id, const Vector3& dir) {}
-void SoundRenderer::set_sound_pitch(SoundSourceId id, const float pitch) {}
-void SoundRenderer::set_sound_gain(SoundSourceId id, const float gain) {}
-void SoundRenderer::set_sound_rolloff(SoundSourceId id, const float rolloff) {}
-float SoundRenderer::sound_min_distance(SoundSourceId id) const {}
-float SoundRenderer::sound_max_distance(SoundSourceId id) const {}
-Vector3 SoundRenderer::sound_position(SoundSourceId id) const {}
-Vector3 SoundRenderer::sound_velocity(SoundSourceId id) const {}
-Vector3 SoundRenderer::sound_direction(SoundSourceId id) const {}
-float SoundRenderer::sound_pitch(SoundSourceId id) const {}
-float SoundRenderer::sound_gain(SoundSourceId id) const {}
-float SoundRenderer::sound_rolloff(SoundSourceId id) const {}
-int32_t SoundRenderer::sound_queued_buffers(SoundSourceId id) const {}
-int32_t SoundRenderer::sound_processed_buffers(SoundSourceId id) const {}
-bool SoundRenderer::sound_playing(SoundSourceId id) {}
-
-} // namespace crown

+ 0 - 370
engine/audio/sles/SLESRenderer.h

@@ -1,370 +0,0 @@
-/*
-Copyright (c) 2013 Daniele Bartolini, Michele Rossi
-Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
-
-Permission is hereby granted, free of charge, to any person
-obtaining a copy of this software and associated documentation
-files (the "Software"), to deal in the Software without
-restriction, including without limitation the rights to use,
-copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the
-Software is furnished to do so, subject to the following
-conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
-OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-OTHER DEALINGS IN THE SOFTWARE.
-*/
-
-#pragma once
-
-#include "SoundResource.h"
-#include "OggDecoder.h"
-#include "Vector3.h"
-#include "Log.h"
-
-namespace crown
-{
-
-static const char* sles_error_to_string(SLresult result)
-{
-	switch (result)
-	{
-	case SL_RESULT_SUCCESS: return "SL_RESULT_SUCCESS";
-	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";
-	case SL_RESULT_IO_ERROR: return "SL_RESULT_IO_ERROR";
-	case SL_RESULT_PRECONDITIONS_VIOLATED: return "SL_RESULT_PRECONDITIONS_VIOLATED";
-	case SL_RESULT_CONTENT_CORRUPTED: return "SL_RESULT_CONTENT_CORRUPTED";
-	case SL_RESULT_CONTENT_UNSUPPORTED: return "SL_RESULT_CONTENT_UNSUPPORTED";
-	case SL_RESULT_CONTENT_NOT_FOUND: return "SL_RESULT_CONTENT_NOT_FOUND";
-	case SL_RESULT_PERMISSION_DENIED: return "SL_RESULT_PERMISSION_DENIED";
-	case SL_RESULT_BUFFER_INSUFFICIENT: return "SL_RESULT_BUFFER_INSUFFICIENT";
-	default: return "SL_RESULT_UNKNOWN";
-	}
-}
-
-//-----------------------------------------------------------------------------
-void check_sles_errors(SLresult result)
-{
-	CE_ASSERT(result == SL_RESULT_SUCCESS, "SL_ERROR_CODE: %s", sles_error_to_string(result));
-}
-
-//-----------------------------------------------------------------------------
-struct Sound
-{
-					Sound();
-
-	void 			create(SLEngineItf engine, SLObjectItf out_mix_obj, SoundResource* resource);
-	void 			update();
-	void 			destroy();
-	void 			play();
-	void 			pause();
-	void			unpause();
-	void 			loop(bool loop);
-
-	bool 			is_created() const;
-	bool 			is_playing() const;
-
-	static void 	buffer_callback(SLAndroidSimpleBufferQueueItf caller, void* sound);
-
-public:
-
-	SoundResource*					m_res;
-
-	SLEngineItf						m_engine;
-	SLObjectItf 					m_out_mix_obj;
-	SLObjectItf 					m_player_obj;
-	SLPlayItf 						m_player_play;
-	SLAndroidSimpleBufferQueueItf 	m_player_bufferqueue;
-	SLVolumeItf						m_player_volume;
-
-	uint32_t						m_processed_buffers;
-	
-	uint16_t* 						m_data;
-	size_t	  						m_size;
-	uint32_t  						m_sample_rate;
-	uint32_t  						m_channels;
-	uint32_t  						m_bits;
-
-	bool 							m_created :1;
-	bool							m_playing :1;
-	bool							m_looping :1;
-	bool							m_streaming :1;
-	bool 							m_positional :1;
-
-	OggDecoder						m_decoder;
-};
-
-//-----------------------------------------------------------------------------
-inline void Sound::buffer_callback(SLAndroidSimpleBufferQueueItf caller, void* sound)
-{
-	Sound* s = (Sound*)sound;
-
-	if (s->is_playing())
-	{
-		s->m_processed_buffers++;
-
-		if (s->m_decoder.stream())
-		{
-			(*s->m_player_bufferqueue)->Enqueue(s->m_player_bufferqueue, s->m_decoder.data(), s->m_decoder.size());
-		}
-		else if (s->m_looping)
-		{
-			s->m_decoder.rewind();
-			s->m_decoder.stream();
-			(*s->m_player_bufferqueue)->Enqueue(s->m_player_bufferqueue, s->m_decoder.data(), s->m_decoder.size());	
-		}
-		else
-		{
-			s->pause();
-		}
-	}
-}
-
-//-----------------------------------------------------------------------------
-inline Sound::Sound()
-	: m_res(NULL)
-	, m_player_obj(NULL)
-	, m_player_play(NULL)
-	, m_player_bufferqueue(NULL)
-	, m_player_volume(NULL)
-	, m_processed_buffers(0)
-	, m_data(NULL)
-	, m_size(0)
-	, m_sample_rate(0)
-	, m_channels(0)
-	, m_bits(0)
-	, m_created(false)
-	, m_playing(false)
-	, m_looping(false)
-	, m_streaming(false)
-	, m_positional(false)
-{
-}
-
-//-----------------------------------------------------------------------------
-inline void Sound::create(SLEngineItf engine, SLObjectItf out_mix_obj, SoundResource* resource)
-{
-	CE_ASSERT_NOT_NULL(resource);
-
-	m_engine = engine;
-	m_out_mix_obj = out_mix_obj;
-
-	m_res = resource;
-
-	// Configures buffer queue
-	SLDataLocator_AndroidSimpleBufferQueue buffer_queue = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2};
-
-	// Configures audio format
-	SLDataFormat_PCM format_pcm;
-	format_pcm.formatType = SL_DATAFORMAT_PCM;
-
-	// Sets channels
-	switch (m_res->channels())
-	{
-	case 1:
-		format_pcm.numChannels = 1;
-		format_pcm.channelMask = SL_SPEAKER_FRONT_CENTER;
-		break;
-	case 2:
-	default:
-		format_pcm.numChannels = 2;
-		format_pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
-		break;
-	}
-
-	// Sets sample rate
-	switch (m_res->sample_rate())
-	{
-	case 8000:
-		format_pcm.samplesPerSec = SL_SAMPLINGRATE_8;
-		break;
-	case 11025:
-		format_pcm.samplesPerSec = SL_SAMPLINGRATE_11_025;
-		break;
-	case 16000:
-		format_pcm.samplesPerSec = SL_SAMPLINGRATE_16;
-		break;
-	case 22050:
-		format_pcm.samplesPerSec = SL_SAMPLINGRATE_22_05;
-		break;
-	case 24000:
-		format_pcm.samplesPerSec = SL_SAMPLINGRATE_24;
-		break;
-	case 32000:
-		format_pcm.samplesPerSec = SL_SAMPLINGRATE_32;
-		break;
-	case 44100:
-		format_pcm.samplesPerSec = SL_SAMPLINGRATE_44_1;
-		break;
-	case 48000:
-		format_pcm.samplesPerSec = SL_SAMPLINGRATE_48;
-		break;
-	case 64000:
-		format_pcm.samplesPerSec = SL_SAMPLINGRATE_64;
-		break;
-	case 88200:
-		format_pcm.samplesPerSec = SL_SAMPLINGRATE_88_2;
-		break;
-	case 96000:
-		format_pcm.samplesPerSec = SL_SAMPLINGRATE_96;
-		break;
-	case 192000:
-		format_pcm.samplesPerSec = SL_SAMPLINGRATE_192;
-		break;
-	}	
-	
-	format_pcm.samplesPerSec = SL_SAMPLINGRATE_44_1;
-	format_pcm.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16;
-	format_pcm.containerSize = SL_PCMSAMPLEFORMAT_FIXED_16;
-	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};
-
-	SLresult result = (*m_engine)->CreateAudioPlayer(m_engine, &m_player_obj, &audio_source, &audio_sink, 3, ids, reqs);
-	check_sles_errors(result);
-
-	result = (*m_player_obj)->Realize(m_player_obj, SL_BOOLEAN_FALSE);
-	check_sles_errors(result);
-
-	// Gets interfaces
-	result = (*m_player_obj)->GetInterface(m_player_obj, SL_IID_PLAY, &m_player_play);
-	check_sles_errors(result);
-
-	result = (*m_player_obj)->GetInterface(m_player_obj, SL_IID_BUFFERQUEUE, &m_player_bufferqueue);
-	check_sles_errors(result);
-
-	result = (*m_player_obj)->GetInterface(m_player_obj, SL_IID_VOLUME, &m_player_volume);
-	check_sles_errors(result);
-
-	(*m_player_bufferqueue)->RegisterCallback(m_player_bufferqueue, Sound::buffer_callback, this);
-
-	// Manage simple sound or stream
-	m_streaming = m_res->sound_type() == SoundType::OGG;
-
-	if (m_streaming)
-	{
-		m_decoder.init((char*)m_res->data(), m_res->size());
-
-		m_decoder.stream();
-		(*m_player_bufferqueue)->Enqueue(m_player_bufferqueue, m_decoder.data(), m_decoder.size());
-	}
-	else
-	{
-		(*m_player_bufferqueue)->Enqueue(m_player_bufferqueue, m_res->data(), m_res->size());
-	}
-
-	m_created = true;
-}
-
-//-----------------------------------------------------------------------------
-inline void Sound::update()
-{
-	// See SLESRenderer.cpp, row 160
-}
-
-//-----------------------------------------------------------------------------
-inline void Sound::destroy()
-{
-	if (m_player_obj)
-	{
-		if (m_streaming)
-		{
-			m_decoder.shutdown();
-		}
-
-		SLuint32 state;
-		(*m_player_obj)->GetState(m_player_obj, &state);
-
-		if (state == SL_OBJECT_STATE_REALIZED)
-		{
-			(*m_player_bufferqueue)->Clear(m_player_bufferqueue);
-			(*m_player_obj)->AbortAsyncOperation(m_player_obj);
-			(*m_player_obj)->Destroy(m_player_obj);
-
-			m_player_obj = NULL;
-			m_player_play = NULL;
-			m_player_bufferqueue = NULL;
-			m_player_volume = NULL;
-		}
-
-		m_created = false;
-		m_playing = false;
-		m_looping = false;
-		m_streaming = false;
-	}
-}
-
-//-----------------------------------------------------------------------------
-inline void Sound::play()
-{
-	SLresult result = (*m_player_play)->SetPlayState(m_player_play, SL_PLAYSTATE_PLAYING);
-	check_sles_errors(result);
-
-	m_playing = true;
-}
-
-//-----------------------------------------------------------------------------
-inline void Sound::pause()
-{
-	SLresult result = (*m_player_play)->SetPlayState(m_player_play, SL_PLAYSTATE_PAUSED);
-	check_sles_errors(result);
-
-	m_playing = false;
-}
-
-//-----------------------------------------------------------------------------
-inline void Sound::unpause()
-{
-	m_decoder.stream();
-	(*m_player_bufferqueue)->Enqueue(m_player_bufferqueue, m_decoder.data(), m_decoder.size());
-	play();
-}
-
-//-----------------------------------------------------------------------------
-inline void Sound::loop(bool loop)
-{
-	m_looping = loop;
-}
-
-//-----------------------------------------------------------------------------
-bool Sound::is_created() const
-{
-	return m_created;
-}
-
-//-----------------------------------------------------------------------------
-inline bool Sound::is_playing() const
-{
-	return m_playing;
-}
-
-} // namespace crown

+ 5 - 10
engine/lua/LuaWorld.cpp

@@ -81,9 +81,9 @@ CE_EXPORT int world_play_sound(lua_State* L)
 	const char* name = stack.get_string(2);
 
 	const bool loop = stack.num_args() > 2 ? stack.get_bool(3) : false;
-	const float volume = stack.num_args() > 3 ? stack.get_float(4) : 1.0f; // test value
+	const float volume = stack.num_args() > 3 ? stack.get_float(4) : 1.0f;
 	const Vector3& pos = stack.num_args() > 4 ? stack.get_vector3(5) : Vector3::ZERO;
-	const float range = stack.num_args() > 5 ? stack.get_float(6) : 1000.0f; // test value
+	const float range = stack.num_args() > 5 ? stack.get_float(6) : 1000.0f;
 
 	SoundInstanceId id = world->play_sound(name, loop, volume, pos, range);
 
@@ -118,18 +118,13 @@ CE_EXPORT int world_link_sound(lua_State* L)
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int world_set_listener(lua_State* L)
+CE_EXPORT int world_set_listener_pose(lua_State* L)
 {
 	LuaStack stack(L);
 
 	World* world = stack.get_world(1);
 
-	const Vector3& pos = stack.get_vector3(2);
-	const Vector3& vel = stack.get_vector3(3);
-	const Vector3& or_up = stack.get_vector3(4);
-	const Vector3& or_at = stack.get_vector3(5);
-
-	world->set_listener(pos, vel, or_up, or_at);
+	world->set_listener_pose(stack.get_matrix4x4(2));
 	return 0;
 }
 
@@ -232,7 +227,7 @@ void load_world(LuaEnvironment& env)
 	env.load_module_function("World", "play_sound",			world_play_sound);
 	env.load_module_function("World", "stop_sound", 		world_stop_sound);
 	env.load_module_function("World", "link_sound",			world_link_sound);
-	env.load_module_function("World", "set_listener", 		world_set_listener);
+	env.load_module_function("World", "set_listener_pose", 	world_set_listener_pose);
 	env.load_module_function("World", "set_sound_position", world_set_sound_position);
 	env.load_module_function("World", "set_sound_range", 	world_set_sound_range);
 	env.load_module_function("World", "set_sound_volume", 	world_set_sound_volume);

+ 2 - 3
engine/os/android/AndroidDevice.cpp

@@ -30,7 +30,6 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "Log.h"
 #include "OsEventQueue.h"
 #include "Renderer.h"
-#include "SoundRenderer.h"
 #include "Touch.h"
 
 namespace crown
@@ -202,13 +201,13 @@ extern "C" JNIEXPORT void JNICALL Java_crown_android_CrownLib_shutdownRenderer(J
 //-----------------------------------------------------------------------------
 extern "C" JNIEXPORT void JNICALL Java_crown_android_CrownLib_pauseSoundRenderer(JNIEnv* /*env*/, jobject /*obj*/)
 {
-	device()->sound_renderer()->pause();
+	//device()->sound_renderer()->pause();
 }
 
 //-----------------------------------------------------------------------------
 extern "C" JNIEXPORT void JNICALL Java_crown_android_CrownLib_unpauseSoundRenderer(JNIEnv* /*env*/, jobject /*obj*/)
 {
-	device()->sound_renderer()->unpause();
+	//device()->sound_renderer()->unpause();
 }
 
 //-----------------------------------------------------------------------------

+ 0 - 1
engine/resource/SoundResource.h

@@ -32,7 +32,6 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "Allocator.h"
 #include "File.h"
 #include "Device.h"
-#include "SoundRenderer.h"
 
 namespace crown
 {

+ 17 - 14
engine/world/World.cpp

@@ -29,8 +29,6 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "Allocator.h"
 #include "Device.h"
 #include "ResourceManager.h"
-#include "SoundRenderer.h"
-#include "SoundResource.h"
 
 namespace crown
 {
@@ -41,6 +39,7 @@ World::World()
 	, m_camera_pool(default_allocator(), MAX_CAMERAS, sizeof(Camera), CE_ALIGNOF(Camera))
 {
 	m_id.id = INVALID_ID;
+	m_sound_world = SoundWorld::create(default_allocator());
 }
 
 //-----------------------------------------------------------------------------
@@ -51,6 +50,8 @@ World::~World()
 	{
 		CE_DELETE(m_unit_pool, m_units[i]);
 	}
+
+	SoundWorld::destroy(default_allocator(), m_sound_world);
 }
 
 //-----------------------------------------------------------------------------
@@ -154,6 +155,8 @@ void World::update(float dt)
 	m_physics_world.update(dt);
 
 	m_scenegraph_manager.update();
+
+	m_sound_world->update();
 }
 
 //-----------------------------------------------------------------------------
@@ -185,43 +188,43 @@ void World::destroy_camera(CameraId id)
 }
 
 //-----------------------------------------------------------------------------
-SoundId World::play_sound(const char* name, const bool loop, const float volume, const Vector3& pos, const float range)
-{
-}
-
-//-----------------------------------------------------------------------------
-SoundId World::play_sound(SoundResource* sr, bool loop, float volume, const Vector3& pos, float range)
+SoundInstanceId World::play_sound(const char* name, const bool loop, const float volume, const Vector3& pos, const float range)
 {
+	m_sound_world->play(name, loop, volume);
 }
 
 //-----------------------------------------------------------------------------
-void World::stop_sound(SoundId id)
+void World::stop_sound(SoundInstanceId id)
 {
+	m_sound_world->stop(id);
 }
 
 //-----------------------------------------------------------------------------
-void World::link_sound(SoundId id, Unit* unit, int32_t node)
+void World::link_sound(SoundInstanceId id, Unit* unit, int32_t node)
 {
 }
 
 //-----------------------------------------------------------------------------
-void World::set_listener(const Vector3& pos, const Vector3& vel, const Vector3& or_up, const Vector3& or_at)
+void World::set_listener_pose(const Matrix4x4& pose)
 {
+	m_sound_world->set_listener_pose(pose);
 }
 
 //-----------------------------------------------------------------------------
-void World::set_sound_position(SoundId id, const Vector3& pos)
+void World::set_sound_position(SoundInstanceId id, const Vector3& pos)
 {
+	m_sound_world->set_sound_positions(1, &id, &pos);
 }
 
 //-----------------------------------------------------------------------------
-void World::set_sound_range(SoundId id, const float range)
+void World::set_sound_range(SoundInstanceId id, float range)
 {
 }
 
 //-----------------------------------------------------------------------------
-void World::set_sound_volume(SoundId id, const float vol)
+void World::set_sound_volume(SoundInstanceId id, float vol)
 {
+	m_sound_world->set_sound_volumes(1, &id, &vol);
 }
 
 //-----------------------------------------------------------------------------

+ 9 - 11
engine/world/World.h

@@ -35,11 +35,11 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "RenderWorld.h"
 #include "RenderWorldTypes.h"
 #include "SceneGraphManager.h"
-#include "SoundRenderer.h"
 #include "Types.h"
 #include "Unit.h"
 #include "Vector.h"
 #include "WorldTypes.h"
+#include "SoundWorld.h"
 
 namespace crown
 {
@@ -47,8 +47,6 @@ namespace crown
 #define MAX_UNITS 65000
 #define MAX_CAMERAS 16
 
-typedef Id SoundId;
-
 struct Mesh;
 struct Sprite;
 struct Actor;
@@ -84,14 +82,13 @@ public:
 	CameraId							create_camera(SceneGraph& sg, int32_t node);
 	void								destroy_camera(CameraId id);
 
-	SoundId								play_sound(const char* name, bool loop = false, float volume = 1.0f, const Vector3& pos = Vector3::ZERO, float range = 50.0f);
-	SoundId								play_sound(SoundResource* sr, bool loop, float volume, const Vector3& pos, float range);
-	void								stop_sound(SoundId sound);
-	void								link_sound(SoundId sound, Unit* unit, int32_t node);
-	void								set_listener(const Vector3& pos, const Vector3& vel, const Vector3& or_up, const Vector3& or_at);
-	void								set_sound_position(SoundId sound, const Vector3& pos);
-	void								set_sound_range(SoundId sound, const float range);
-	void								set_sound_volume(SoundId sound, const float vol);
+	SoundInstanceId						play_sound(const char* name, bool loop = false, float volume = 1.0f, const Vector3& pos = Vector3::ZERO, float range = 50.0f);
+	void								stop_sound(SoundInstanceId sound);
+	void								link_sound(SoundInstanceId sound, Unit* unit, int32_t node);
+	void								set_listener_pose(const Matrix4x4& pose);
+	void								set_sound_position(SoundInstanceId sound, const Vector3& pos);
+	void								set_sound_range(SoundInstanceId sound, float range);
+	void								set_sound_volume(SoundInstanceId sound, float vol);
 
 	GuiId								create_window_gui(const char* name);
 	GuiId								create_world_gui(const Matrix4x4 pose, const uint32_t width, const uint32_t height);
@@ -113,6 +110,7 @@ private:
 	SceneGraphManager					m_scenegraph_manager;
 	RenderWorld							m_render_world;
 	PhysicsWorld						m_physics_world;
+	SoundWorld*							m_sound_world;
 
 	WorldId								m_id;
 };