浏览代码

first try of SoundRenderer, improve ALRenderer

mikymod 12 年之前
父节点
当前提交
c6d72d54b4
共有 3 个文件被更改,包括 220 次插入284 次删除
  1. 43 67
      engine/audio/SoundRenderer.h
  2. 79 155
      engine/audio/al/ALRenderer.cpp
  3. 98 62
      engine/audio/al/ALRenderer.h

+ 43 - 67
engine/audio/SoundRenderer.h

@@ -29,17 +29,16 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "IdTable.h"
 #include "Allocator.h"
 
-#define	MAX_SOUND_SOURCES 64
-#define	MAX_SOUND_BUFFERS 128
+#define	MAX_SOUNDS 64
 
 namespace crown
 {
 //-----------------------------------------------------------------------------
-typedef 	Id 		SoundBufferId;
-typedef 	Id 		SoundSourceId;
+typedef 	Id 		SoundId;
 
 //-----------------------------------------------------------------------------
 class SoundRendererBackend;
+class SoundResource;
 class Vec3;
 
 //-----------------------------------------------------------------------------
@@ -54,107 +53,86 @@ public:
 
 	void					shutdown();
 
-	/// Returns number of buffers actually in use
-	uint32_t				num_buffers();
+	void					frame();
 
-	/// Returns number of sources actually in use
-	uint32_t				num_sources();
+	/// Returns number of sounds actually in use
+	uint32_t				num_sounds();
 
 	/// Sets listener parameters. @a position affects audibility of sounds, 
 	/// @a velocity affects doppler shift and @a orientation affects how a sound could be heard
 	void					set_listener(const Vec3& pos, const Vec3& vel, const Vec3& or_up, const Vec3& or_at) const;
 
-	/// Creates buffer's @a data, with a specific @a size, which contains sound raw data.
-	/// More parameters must be specified, such as @a sample_rate, that is the number of sample per unit of time 
-	/// taken from a continuous signal to make a discrete signal, @a channels which specifies if sound is mono or stereo and @a bits
-	/// which specifies the magnitude of samples information.
-	/// N.B: stereo sound cannot be attenuated
-	SoundBufferId			create_buffer(const void* data, const uint32_t size, const uint32_t sample_rate, const uint32_t channels, const uint32_t bits);
-
-	void					update_buffer(SoundBufferId id, const void* data, const uint32_t size);
-	/// Destroys buffer
-	void					destroy_buffer(SoundBufferId id);
-
-	/// Binds buffer @a bid to source @a sid
-	void					bind_buffer_to_source(SoundBufferId bid, SoundSourceId sid);
-
-	/// Unbind the first buffer from @a id
-	void					unbind_buffer_from_source(SoundSourceId id);
-
-	/// Creates a source of sound 
-	SoundSourceId			create_source();
-
-	/// Updates buffer @a bid of source @a sid with new @a data of size @a size
-	/// Updates only happens when there is a free buffer;
-	bool 					update_source(SoundSourceId sid, SoundBufferId bid, const void* data, const size_t size);
+	/// Creates a sound of sound 
+	SoundId					create_sound(SoundResource* resource);
 
 	/// Destroys a sound, specified by @a id, previously created
-	void					destroy_source(SoundSourceId id);
+	void					destroy_sound(SoundId id);
 
-	/// Plays a sound, specified by source @a sid and a buffer @a bid
-	void					play_source(SoundSourceId id, bool loop);
+	/// Plays a sound, specified by sound @a sid and a buffer @a bid
+	void					play_sound(SoundId id);
 
 	/// Pauses a sound, specified by @a id
-	void					pause_source(SoundSourceId id);
+	void					pause_sound(SoundId id);
 
-	///	Sets source's @a min_distance. From @a min_distance to @a max_distance, sound
+	///	Sets sound's @a min_distance. From @a min_distance to @a max_distance, sound
 	/// scales from full volume to silence
-	void					set_source_min_distance(SoundSourceId id,  const float min_distance);
+	void					set_sound_min_distance(SoundId id, const float min_distance);
 
-	///	Sets source's @a max_distance. From @a min_distance to @a max_distance, sound
+	///	Sets sound's @a max_distance. From @a min_distance to @a max_distance, sound
 	/// scales from full volume to silence
-	void					set_source_max_distance(SoundSourceId id,  const float max_distance);
+	void					set_sound_max_distance(SoundId id, const float max_distance);
 
-	/// Sets source's @a position. It affects sound audibility
-	void					set_source_position(SoundSourceId id, const Vec3& pos);
+	/// Sets sound's @a position. It affects sound audibility
+	void					set_sound_position(SoundId id, const Vec3& pos);
 
-	/// Sets source's @a velocity. It affects doppler shift
-	void					set_source_velocity(SoundSourceId id, const Vec3& vel);
+	/// Sets sound's @a velocity. It affects doppler shift
+	void					set_sound_velocity(SoundId id, const Vec3& vel);
 
-	/// Sets source's @a direction. It affects how a sound could be heard
-	void					set_source_direction(SoundSourceId id, const Vec3& dir);
+	/// Sets sound's @a direction. It affects how a sound could be heard
+	void					set_sound_direction(SoundId id, const Vec3& dir);
 
-	/// Sets source's @a pitch.
-	void					set_source_pitch(SoundSourceId id, const float pitch);
+	/// Sets sound's @a pitch.
+	void					set_sound_pitch(SoundId id, const float pitch);
 
-	/// Sets source's @a gain, that is measure sound's amplification
-	void					set_source_gain(SoundSourceId id, const float gain);
+	/// Sets sound's @a gain, that is measure sound's amplification
+	void					set_sound_gain(SoundId id, const float gain);
 
-	/// Sets source's @a rolloff factor. Greater it is, greater sound's attenuation is
-	void					set_source_rolloff(SoundSourceId id, const float rolloff);
+	/// Sets sound's @a rolloff factor. Greater it is, greater sound's attenuation is
+	void					set_sound_rolloff(SoundId id, const float rolloff);
 
 	/// Returns minimum distance of @a id
-	float					source_min_distance(SoundSourceId id) const;
+	float					sound_min_distance(SoundId id) const;
 
 	/// Returns maximum distance of @a id
-	float					source_max_distance(SoundSourceId id) const;
+	float					sound_max_distance(SoundId id) const;
 	
 	/// Returns position of @a id
-	Vec3					source_position(SoundSourceId id) const;
+	Vec3					sound_position(SoundId id) const;
 
 	/// Returns velocity of @a id
-	Vec3					source_velocity(SoundSourceId id) const;
+	Vec3					sound_velocity(SoundId id) const;
 
 	/// Returns direction of @a id
-	Vec3					source_direction(SoundSourceId id) const;
+	Vec3					sound_direction(SoundId id) const;
 
 	/// Returns pitch of @a id
-	float					source_pitch(SoundSourceId id) const;
+	float					sound_pitch(SoundId id) const;
 
 	/// Returns gain of @a id
-	float					source_gain(SoundSourceId id) const;
+	float					sound_gain(SoundId id) const;
 
 	/// Returns rolloff factor of @a id
-	float					source_rolloff(SoundSourceId id) const;
+	/// Rolloff: perceived volume decreases at a fixed rate as a sound sound moves away from the listener
+	float					sound_rolloff(SoundId id) const;
 
 	/// Returns number of queued buffers of @a id
-	int32_t					source_queued_buffers(SoundSourceId id) const;
+	int32_t					sound_queued_buffers(SoundId id) const;
 
 	/// Returns number of processed buffers of @a id
-	int32_t					source_processed_buffers(SoundSourceId id) const;
+	int32_t					sound_processed_buffers(SoundId id) const;
 
-	/// Is source @a id playing?
-	bool					source_playing(SoundSourceId id);
+	/// Is sound @a id playing?
+	bool					sound_playing(SoundId id);
 
 private:
 
@@ -162,11 +140,9 @@ private:
 
 	SoundRendererBackend*	m_backend;
 
-	IdTable<MAX_SOUND_BUFFERS>		m_buffers_id_table;
-	IdTable<MAX_SOUND_SOURCES>		m_sources_id_table;
+	IdTable<MAX_SOUNDS>		m_sounds_id_table;
 
-	uint32_t				m_num_buffers;
-	uint32_t				m_num_sources;
+	uint32_t				m_num_sounds;
 };
 
 } // namespace crown

+ 79 - 155
engine/audio/al/ALRenderer.cpp

@@ -26,8 +26,8 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 #include "SoundRenderer.h"
 #include "ALRenderer.h"
+#include "SoundResource.h"
 #include "StringUtils.h"
-
 #include "Log.h"
 
 namespace crown
@@ -102,8 +102,7 @@ private:
 	ALCdevice*				m_device;
 	ALCcontext*				m_context;
 
-	SoundBuffer 			m_buffers[MAX_SOUND_BUFFERS];
-	SoundSource 			m_sources[MAX_SOUND_SOURCES];
+	Sound 		 			m_sounds[MAX_SOUNDS];
 
 private:
 
@@ -115,8 +114,7 @@ private:
 //-----------------------------------------------------------------------------
 SoundRenderer::SoundRenderer(Allocator& allocator) : 
 	m_allocator(allocator),
-	m_num_buffers(0),
-	m_num_sources(0)
+	m_num_sounds(0)
 {
 	m_backend = CE_NEW(m_allocator, SoundRendererBackend);
 }
@@ -143,15 +141,21 @@ void SoundRenderer::shutdown()
 }
 
 //-----------------------------------------------------------------------------
-uint32_t SoundRenderer::num_buffers()
+void SoundRenderer::frame()
 {
-	return m_num_buffers;
+	for (uint32_t i = 0; i < m_num_sounds; i++)
+	{
+		if (m_backend->m_sounds[i].m_playing)
+		{
+			m_backend->m_sounds[i].update();
+		}
+	}
 }
 
 //-----------------------------------------------------------------------------
-uint32_t SoundRenderer::num_sources()
+uint32_t SoundRenderer::num_sounds()
 {
-	return m_num_sources;
+	return m_num_sounds;
 }
 
 //-----------------------------------------------------------------------------
@@ -161,259 +165,179 @@ void SoundRenderer::set_listener(const Vec3& pos, const Vec3& vel, const Vec3& o
 }
 
 //-----------------------------------------------------------------------------
-SoundBufferId SoundRenderer::create_buffer(const void* data, const uint32_t size, const uint32_t sample_rate, const uint32_t channels, const uint32_t bits)
+SoundId SoundRenderer::create_sound(SoundResource* resource)
 {
-	SoundBufferId id = m_buffers_id_table.create();
+	SoundId id = m_sounds_id_table.create();
 
-	m_backend->m_buffers[id.index].create(data, size, sample_rate, channels, bits);
+	m_backend->m_sounds[id.index].create(resource);
 
-	m_num_buffers++;
+	m_num_sounds++;
 
 	return id;
 }
 
 //-----------------------------------------------------------------------------
-void SoundRenderer::update_buffer(SoundBufferId id, const void* data, const uint32_t size)
-{
-	CE_ASSERT(m_buffers_id_table.has(id), "SoundBuffer does not exists");
-
-	m_backend->m_buffers[id.index].update(data, size);
-}
-
-//-----------------------------------------------------------------------------
-void SoundRenderer::destroy_buffer(SoundBufferId id)
-{
-	CE_ASSERT(m_buffers_id_table.has(id), "SoundBuffer does not exists");
-
-	m_backend->m_buffers[id.index].destroy();
-
-	m_buffers_id_table.destroy(id);
-
-	m_num_buffers--;
-}
-
-//-----------------------------------------------------------------------------
-void SoundRenderer::bind_buffer_to_source(SoundBufferId bid, SoundSourceId sid)
-{
-	CE_ASSERT(m_buffers_id_table.has(bid), "SoundBuffer does not exists");
-	CE_ASSERT(m_sources_id_table.has(sid), "SoundSource does not exists");
-
-	SoundSource& source = m_backend->m_sources[sid.index];
-	SoundBuffer& buffer = m_backend->m_buffers[bid.index];
-
-	source.bind_buffer(buffer.m_id);
-}
-
-//-----------------------------------------------------------------------------
-void SoundRenderer::unbind_buffer_from_source(SoundSourceId id)
-{
-	CE_ASSERT(m_sources_id_table.has(id), "SoundSource does not exists");
-
-	SoundSource& source = m_backend->m_sources[id.index];
-
-	source.unbind_buffer();
-}
-
-//-----------------------------------------------------------------------------
-SoundSourceId SoundRenderer::create_source()
-{
-	SoundSourceId id = m_sources_id_table.create();
-
-	m_backend->m_sources[id.index].create();
-
-	m_num_sources++;
-
-	return id;
-}
-
-//-----------------------------------------------------------------------------
-bool SoundRenderer::update_source(SoundSourceId sid, SoundBufferId bid, const void* data, const size_t size)
-{
-	CE_ASSERT(m_sources_id_table.has(sid), "SoundSource does not exists");
-	CE_ASSERT(m_buffers_id_table.has(bid), "SoundBuffer does not exists");
-
-	CE_ASSERT_NOT_NULL(data);
-
-	bool ready = false;
-
-	int32_t processed = m_backend->m_sources[sid.index].processed_buffers();
-
-	while (processed--)
-	{
-		uint32_t buffer = m_backend->m_sources[sid.index].unbind_buffer();
-
-		update_buffer(bid, data, size);
-
-		m_backend->m_sources[sid.index].bind_buffer(buffer);
-
-		ready = true;
-	}
-
-	return ready;
-}
-
-//-----------------------------------------------------------------------------
-void SoundRenderer::destroy_source(SoundSourceId id)
+void SoundRenderer::destroy_sound(SoundId id)
 {
-	CE_ASSERT(m_sources_id_table.has(id), "SoundSource does not exists");
+	CE_ASSERT(m_sounds_id_table.has(id), "Sound does not exists");
 
-	m_backend->m_sources[id.index].destroy();
+	m_backend->m_sounds[id.index].destroy();
 
-	m_sources_id_table.destroy(id);
+	m_sounds_id_table.destroy(id);
 
-	m_num_sources--;
+	m_num_sounds--;
 }
 
 //-----------------------------------------------------------------------------
-void SoundRenderer::play_source(SoundSourceId id, bool loop)
+void SoundRenderer::play_sound(SoundId id)
 {
-	CE_ASSERT(m_sources_id_table.has(id), "SoundSource does not exists");
+	CE_ASSERT(m_sounds_id_table.has(id), "Sound does not exists");
 
-	m_backend->m_sources[id.index].play(loop);
+	m_backend->m_sounds[id.index].play();
 }
 
 //-----------------------------------------------------------------------------
-void SoundRenderer::pause_source(SoundSourceId id)
+void SoundRenderer::pause_sound(SoundId id)
 {
-	CE_ASSERT(m_sources_id_table.has(id), "SoundSource does not exists");
+	CE_ASSERT(m_sounds_id_table.has(id), "Sound does not exists");
 
-	m_backend->m_sources[id.index].pause();
+	m_backend->m_sounds[id.index].pause();
 }
 
 //-----------------------------------------------------------------------------
-void SoundRenderer::set_source_min_distance(SoundSourceId id, const float min_distance)
+void SoundRenderer::set_sound_min_distance(SoundId id, const float min_distance)
 {
-	CE_ASSERT(m_sources_id_table.has(id), "SoundSource does not exists");
+	CE_ASSERT(m_sounds_id_table.has(id), "Sound does not exists");
 
-	m_backend->m_sources[id.index].set_min_distance(min_distance);
+	m_backend->m_sounds[id.index].set_min_distance(min_distance);
 }
 
 //-----------------------------------------------------------------------------
-void SoundRenderer::set_source_max_distance(SoundSourceId id, const float max_distance)
+void SoundRenderer::set_sound_max_distance(SoundId id, const float max_distance)
 {
-	CE_ASSERT(m_sources_id_table.has(id), "SoundSource does not exists");
+	CE_ASSERT(m_sounds_id_table.has(id), "Sound does not exists");
 
-	m_backend->m_sources[id.index].set_max_distance(max_distance);
+	m_backend->m_sounds[id.index].set_max_distance(max_distance);
 }
 
 //-----------------------------------------------------------------------------
-void SoundRenderer::set_source_position(SoundSourceId id, const Vec3& pos)
+void SoundRenderer::set_sound_position(SoundId id, const Vec3& pos)
 {
-	CE_ASSERT(m_sources_id_table.has(id), "SoundSource does not exists");
+	CE_ASSERT(m_sounds_id_table.has(id), "Sound does not exists");
 
-	m_backend->m_sources[id.index].set_position(pos);
+	m_backend->m_sounds[id.index].set_position(pos);
 }
 
 //-----------------------------------------------------------------------------
-void SoundRenderer::set_source_velocity(SoundSourceId id, const Vec3& vel)
+void SoundRenderer::set_sound_velocity(SoundId id, const Vec3& vel)
 {
-	CE_ASSERT(m_sources_id_table.has(id), "SoundSource does not exists");
+	CE_ASSERT(m_sounds_id_table.has(id), "Sound does not exists");
 
-	m_backend->m_sources[id.index].set_velocity(vel);
+	m_backend->m_sounds[id.index].set_velocity(vel);
 }
 
 //-----------------------------------------------------------------------------
-void SoundRenderer::set_source_direction(SoundSourceId id, const Vec3& dir)
+void SoundRenderer::set_sound_direction(SoundId id, const Vec3& dir)
 {
-	CE_ASSERT(m_sources_id_table.has(id), "SoundSource does not exists");
+	CE_ASSERT(m_sounds_id_table.has(id), "Sound does not exists");
 
-	m_backend->m_sources[id.index].set_direction(dir);
+	m_backend->m_sounds[id.index].set_direction(dir);
 }
 
 //-----------------------------------------------------------------------------
-void SoundRenderer::set_source_pitch(SoundSourceId id, const float pitch)
+void SoundRenderer::set_sound_pitch(SoundId id, const float pitch)
 {
-	CE_ASSERT(m_sources_id_table.has(id), "SoundSource does not exists");
+	CE_ASSERT(m_sounds_id_table.has(id), "Sound does not exists");
 
-	m_backend->m_sources[id.index].set_pitch(pitch);
+	m_backend->m_sounds[id.index].set_pitch(pitch);
 }
 
 //-----------------------------------------------------------------------------
-void SoundRenderer::set_source_gain(SoundSourceId id, const float gain)
+void SoundRenderer::set_sound_gain(SoundId id, const float gain)
 {
-	CE_ASSERT(m_sources_id_table.has(id), "SoundSource does not exists");
+	CE_ASSERT(m_sounds_id_table.has(id), "Sound does not exists");
 
-	m_backend->m_sources[id.index].set_gain(gain);
+	m_backend->m_sounds[id.index].set_gain(gain);
 }
 
 //-----------------------------------------------------------------------------
-void SoundRenderer::set_source_rolloff(SoundSourceId id, const float rolloff)
+void SoundRenderer::set_sound_rolloff(SoundId id, const float rolloff)
 {
-	CE_ASSERT(m_sources_id_table.has(id), "SoundSource does not exists");
+	CE_ASSERT(m_sounds_id_table.has(id), "Sound does not exists");
 
-	m_backend->m_sources[id.index].set_rolloff(rolloff);
+	m_backend->m_sounds[id.index].set_rolloff(rolloff);
 }
 
 //-----------------------------------------------------------------------------
-float SoundRenderer::source_min_distance(SoundSourceId id) const
+float SoundRenderer::sound_min_distance(SoundId id) const
 {
-	CE_ASSERT(m_sources_id_table.has(id), "SoundSource does not exists");
+	CE_ASSERT(m_sounds_id_table.has(id), "Sound does not exists");
 
-	return m_backend->m_sources[id.index].min_distance();
+	return m_backend->m_sounds[id.index].min_distance();
 }
 
 //-----------------------------------------------------------------------------
-float SoundRenderer::source_max_distance(SoundSourceId id) const
+float SoundRenderer::sound_max_distance(SoundId id) const
 {
-	CE_ASSERT(m_sources_id_table.has(id), "SoundSource does not exists");
+	CE_ASSERT(m_sounds_id_table.has(id), "Sound does not exists");
 
-	return m_backend->m_sources[id.index].max_distance();
+	return m_backend->m_sounds[id.index].max_distance();
 }
 
 //-----------------------------------------------------------------------------
-Vec3 SoundRenderer::source_position(SoundSourceId id) const
+Vec3 SoundRenderer::sound_position(SoundId id) const
 {
-	CE_ASSERT(m_sources_id_table.has(id), "SoundSource does not exists");
+	CE_ASSERT(m_sounds_id_table.has(id), "Sound does not exists");
 
-	return m_backend->m_sources[id.index].position();
+	return m_backend->m_sounds[id.index].position();
 }
 
 //-----------------------------------------------------------------------------
-Vec3 SoundRenderer::source_velocity(SoundSourceId id) const
+Vec3 SoundRenderer::sound_velocity(SoundId id) const
 {
-	CE_ASSERT(m_sources_id_table.has(id), "SoundSource does not exists");
+	CE_ASSERT(m_sounds_id_table.has(id), "Sound does not exists");
 
-	return m_backend->m_sources[id.index].velocity();
+	return m_backend->m_sounds[id.index].velocity();
 }
 
 //-----------------------------------------------------------------------------
-Vec3 SoundRenderer::source_direction(SoundSourceId id) const
+Vec3 SoundRenderer::sound_direction(SoundId id) const
 {
-	CE_ASSERT(m_sources_id_table.has(id), "SoundSource does not exists");
+	CE_ASSERT(m_sounds_id_table.has(id), "Sound does not exists");
 
-	return m_backend->m_sources[id.index].direction();
+	return m_backend->m_sounds[id.index].direction();
 }
 
 //-----------------------------------------------------------------------------
-float SoundRenderer::source_pitch(SoundSourceId id) const
+float SoundRenderer::sound_pitch(SoundId id) const
 {
-	CE_ASSERT(m_sources_id_table.has(id), "SoundSource does not exists");
+	CE_ASSERT(m_sounds_id_table.has(id), "Sound does not exists");
 
-	return m_backend->m_sources[id.index].pitch();
+	return m_backend->m_sounds[id.index].pitch();
 }
 
 //-----------------------------------------------------------------------------
-float SoundRenderer::source_gain(SoundSourceId id) const
+float SoundRenderer::sound_gain(SoundId id) const
 {
-	CE_ASSERT(m_sources_id_table.has(id), "SoundSource does not exists");
+	CE_ASSERT(m_sounds_id_table.has(id), "Sound does not exists");
 
-	return m_backend->m_sources[id.index].gain();
+	return m_backend->m_sounds[id.index].gain();
 }
 
 //-----------------------------------------------------------------------------
-float SoundRenderer::source_rolloff(SoundSourceId id) const
+float SoundRenderer::sound_rolloff(SoundId id) const
 {
-	CE_ASSERT(m_sources_id_table.has(id), "SoundSource does not exists");
+	CE_ASSERT(m_sounds_id_table.has(id), "Sound does not exists");
 
-	return m_backend->m_sources[id.index].rolloff();
+	return m_backend->m_sounds[id.index].rolloff();
 }
 
 //-----------------------------------------------------------------------------
-bool SoundRenderer::source_playing(SoundSourceId id)
+bool SoundRenderer::sound_playing(SoundId id)
 {
-	CE_ASSERT(m_sources_id_table.has(id), "SoundSource does not exists");
+	CE_ASSERT(m_sounds_id_table.has(id), "Sound does not exists");
 
-	return m_backend->m_sources[id.index].is_playing();
+	return m_backend->m_sounds[id.index].is_playing();
 }
 
 } // namespace crown

+ 98 - 62
engine/audio/al/ALRenderer.h

@@ -29,6 +29,8 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include <AL/al.h>
 #include <AL/alc.h>
 
+#include "SoundResource.h"
+#include "OggDecoder.h"
 #include "Vec3.h"
 #include "Log.h"
 
@@ -60,22 +62,36 @@ static const char* al_error_to_string(ALenum error)
 #endif
 
 //-----------------------------------------------------------------------------
-struct SoundBuffer
+struct Sound
 {
+	//-----------------------------------------------------------------------------
+	Sound() : 
+		m_res(NULL), 
+		m_id(-1),	
+		m_looping(false)
+	{
+	}
 
-	/// Creates AL buffer of dimension @a size containing @a data.
-	/// More parameters must be specified, such as @a sample_rate, that is the number of sample per unit of time 
-	/// taken from a continuous signal to make a discrete signal, @a channels which specifies if sound is mono or stereo and @a bits
-	/// which specifies the magnitude of samples information.
-	void create(const void* data, const size_t size, const uint32_t sample_rate, const uint32_t channels, const uint32_t bits)
+	//-----------------------------------------------------------------------------
+	void create(SoundResource* resource)
 	{
-		AL_CHECK(alGenBuffers(1, &m_id));
+		CE_ASSERT_NOT_NULL(resource);
 
-		m_sample_rate = sample_rate;
+		// Stores resource pointer
+		m_res = resource;
+
+		// Generates AL source
+		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));
+
+		// Generates AL buffer
+		AL_CHECK(alGenBuffers(3, m_buffer));
 		
-		bool stereo = (channels > 1);
+		bool stereo = (m_res->channels() > 1);
 
-		switch(bits)
+		switch(m_res->bits_ps())
 		{
 			case 8:
 			{
@@ -99,81 +115,91 @@ struct SoundBuffer
 			}
 		}
 
-		AL_CHECK(alBufferData(m_id, m_format, data, size, m_sample_rate));
-	}
+		// Streams resource if is ogg 
+		if (m_res->sound_type() == ST_OGG)
+		{
+			m_streaming = true;
+			m_decoder.init((char*)m_res->data(), m_res->size());
+			m_decoder.stream();
+			AL_CHECK(alBufferData(m_buffer[0], m_format, m_decoder.data(), m_decoder.size(), m_res->sample_rate()));
+			m_decoder.stream();
+			AL_CHECK(alBufferData(m_buffer[1], m_format, m_decoder.data(), m_decoder.size(), m_res->sample_rate()));			
+			m_decoder.stream();
+			AL_CHECK(alBufferData(m_buffer[2], m_format, m_decoder.data(), m_decoder.size(), m_res->sample_rate()));
+
+			AL_CHECK(alSourceQueueBuffers(m_id, 3, m_buffer));
+		}
+		else
+		{
+			AL_CHECK(alBufferData(m_buffer[0], m_format, m_res->data(), m_res->size(), m_res->sample_rate()));
 
-	/// Updates AL buffer with new @a data and new @a size.
-	/// Buffer id, format and sample rate remain the same
-	void update(const void* data, const uint32_t size)
-	{
-		AL_CHECK(alBufferData(m_id, m_format, data, size, m_sample_rate));
+			AL_CHECK(alSourceQueueBuffers(m_id, 1, &m_buffer[0]));
+		}
 	}
 
-	/// Destroys AL buffer
-	void destroy()
+	//-----------------------------------------------------------------------------
+	void update()
 	{
-		AL_CHECK(alDeleteBuffers(1, &m_id));
-	}
+		if (m_playing)
+		{
+			if (m_streaming)
+			{
+				uint32_t processed = processed_buffers();
 
-public:
+				while (processed--)
+				{
+					ALuint buffer;
 
-	ALuint 		m_id;
-	ALenum 		m_format;
-	ALuint 		m_sample_rate;
-};
+					AL_CHECK(alSourceUnqueueBuffers(m_id, 1, &buffer));
 
-//-----------------------------------------------------------------------------
-struct SoundSource
-{
-	/// Creates AL source
-	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));
+					if (m_decoder.stream())
+					{
+						AL_CHECK(alBufferData(buffer, m_format, m_decoder.data(), m_decoder.size(), m_res->sample_rate()));
+					}
+
+					AL_CHECK(alSourceQueueBuffers(m_id, 1, &buffer));
+				}
+			}
+		}
 	}
 
-	/// Binds AL buffer at the end of source's buffer queue;
-	void bind_buffer(ALuint buffers)
+	//-----------------------------------------------------------------------------
+	void destroy()
 	{
-		AL_CHECK(alSourceQueueBuffers(m_id, 1, &buffers));
+		AL_CHECK(alDeleteSources(1, &m_id));
+
+		AL_CHECK(alDeleteBuffers(3, m_buffer));
 	}
 
-	/// Unbinds first AL buffer in queue
-	ALuint unbind_buffer()
+	//-----------------------------------------------------------------------------
+	void play()
 	{
-        ALuint buffer;
-
-		AL_CHECK(alSourceUnqueueBuffers(m_id, 1, &buffer));
+		AL_CHECK(alSourcePlay(m_id));
 
-		return buffer;
+		m_playing = true;
 	}
 
-	/// Destroyes AL source
-	void destroy()
+	//-----------------------------------------------------------------------------
+	void pause()
 	{
-		AL_CHECK(alDeleteSources(1, &m_id));
+		AL_CHECK(alSourcePause(m_id));
+
+		m_playing = false;
 	}
 
-	/// Plays AL source
-	void play(bool loop)
+	//-----------------------------------------------------------------------------
+	void set_mode(bool loop)
 	{
 		if (loop)
 		{
 			AL_CHECK(alSourcef(m_id, AL_LOOPING, AL_TRUE));
 		}
-
-		AL_CHECK(alSourcePlay(m_id));
-	}
-
-	/// Pauses AL source
-	void pause()
-	{
-		if (is_playing())
+		else
 		{
-			AL_CHECK(alSourcePause(m_id));
+			AL_CHECK(alSourcef(m_id, AL_LOOPING, AL_FALSE));
 		}
+
+		m_looping = loop;
 	}
 
 	//-----------------------------------------------------------------------------
@@ -228,6 +254,7 @@ struct SoundSource
 	float min_distance() const
 	{
 		ALfloat min_distance;
+
 		alGetSourcef(m_id, AL_REFERENCE_DISTANCE, &min_distance);
 
 		return min_distance;
@@ -237,6 +264,7 @@ struct SoundSource
 	float max_distance() const
 	{
 		ALfloat max_distance;
+
 		alGetSourcef(m_id, AL_MAX_DISTANCE, &max_distance);
 
 		return max_distance;
@@ -324,7 +352,6 @@ struct SoundSource
 	int32_t queued_buffers()
 	{
 		int32_t queued;
-
 		alGetSourcei(m_id, AL_BUFFERS_QUEUED, &queued);
 
 		return queued;
@@ -334,7 +361,6 @@ struct SoundSource
 	int32_t processed_buffers()
 	{
 		int32_t processed;
-
 		alGetSourcei(m_id, AL_BUFFERS_PROCESSED, &processed);
 
 		return processed;
@@ -342,7 +368,17 @@ struct SoundSource
 
 public:
 
-	ALuint		m_id;
+	SoundResource*	m_res;
+
+	ALuint			m_id;
+	ALuint			m_buffer[3];
+	ALuint 			m_format;
+
+	bool			m_playing;
+	bool			m_looping;
+	bool			m_streaming;
+
+	OggDecoder		m_decoder;
 };
 
 } // namespace crown