diff --git a/cmake/Modules/FindVorbis.cmake b/cmake/Modules/FindVorbis.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..e0cb2c1ac289d506ed054d6ef2f1ecb45a4be30a
--- /dev/null
+++ b/cmake/Modules/FindVorbis.cmake
@@ -0,0 +1,45 @@
+# - Find vorbis
+# Find the native vorbis includes and libraries
+#
+#  VORBIS_INCLUDE_DIR - where to find vorbis.h, etc.
+#  VORBIS_LIBRARIES   - List of libraries when using vorbis(file).
+#  VORBIS_FOUND       - True if vorbis found.
+
+if(NOT GP2XWIZ)
+    if(VORBIS_INCLUDE_DIR)
+        # Already in cache, be silent
+        set(VORBIS_FIND_QUIETLY TRUE)
+    endif(VORBIS_INCLUDE_DIR)
+    find_path(OGG_INCLUDE_DIR ogg/ogg.h)
+    find_path(VORBIS_INCLUDE_DIR vorbis/vorbisfile.h)
+    # MSVC built ogg/vorbis may be named ogg_static and vorbis_static
+    find_library(OGG_LIBRARY NAMES ogg ogg_static)
+    find_library(VORBIS_LIBRARY NAMES vorbis vorbis_static)
+    find_library(VORBISFILE_LIBRARY NAMES vorbisfile vorbisfile_static)
+    # Handle the QUIETLY and REQUIRED arguments and set VORBIS_FOUND
+    # to TRUE if all listed variables are TRUE.
+    include(FindPackageHandleStandardArgs)
+    find_package_handle_standard_args(VORBIS DEFAULT_MSG
+        OGG_INCLUDE_DIR VORBIS_INCLUDE_DIR
+        OGG_LIBRARY VORBIS_LIBRARY VORBISFILE_LIBRARY)
+else(NOT GP2XWIZ)
+    find_path(VORBIS_INCLUDE_DIR tremor/ivorbisfile.h)
+    find_library(VORBIS_LIBRARY NAMES vorbis_dec)
+    find_package_handle_standard_args(VORBIS DEFAULT_MSG
+        VORBIS_INCLUDE_DIR VORBIS_LIBRARY)
+endif(NOT GP2XWIZ)
+    
+if(VORBIS_FOUND)
+  if(NOT GP2XWIZ)
+     set(VORBIS_LIBRARIES ${VORBISFILE_LIBRARY} ${VORBIS_LIBRARY}
+           ${OGG_LIBRARY})
+  else(NOT GP2XWIZ)
+     set(VORBIS_LIBRARIES ${VORBIS_LIBRARY})
+  endif(NOT GP2XWIZ)
+else(VORBIS_FOUND)
+  set(VORBIS_LIBRARIES)
+endif(VORBIS_FOUND)
+
+mark_as_advanced(OGG_INCLUDE_DIR VORBIS_INCLUDE_DIR)
+mark_as_advanced(OGG_LIBRARY VORBIS_LIBRARY VORBISFILE_LIBRARY)
+
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index b8f0341f098166f1b18b7b49956fdf3e55feaf87..b8eb9b4e34e90b348d44cda7876c4df35287da86 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -29,6 +29,37 @@ else(GETTEXT_FOUND AND ENABLE_GETTEXT)
 	message(STATUS "GetText disabled")
 endif(GETTEXT_FOUND AND ENABLE_GETTEXT)
 
+# user visible option to enable/disable audio
+OPTION(ENABLE_AUDIO "Enable audio" ON)
+
+# this is only set to 1 if audio is enabled _and_ available
+set(USE_AUDIO 0)
+
+if(ENABLE_AUDIO)
+	# Sound libraries
+	find_package(OpenAL)
+	if (OPENAL_FOUND)
+		find_package(Vorbis)
+		if (VORBIS_FOUND)
+			set(USE_AUDIO 1)
+			set(audio_SRCS sound.cpp sound_openal.cpp)
+			set(AUDIO_INCLUDE_DIRS
+				${OPENAL_INCLUDE_DIR}
+				${VORBIS_INCLUDE_DIR}
+				)
+			set(AUDIO_LIBRARIES
+				${OPENAL_LIBRARY}
+				${VORBIS_LIBRARIES}
+				)
+			message(STATUS "Sound enabled")
+		else(VORBIS_FOUND)
+			message(FATAL_ERROR "Sound enabled, but Vorbis libraries not found!")
+		endif(VORBIS_FOUND)
+	else(OPENAL_FOUND)
+		message(FATAL_ERROR "Sound enabled, but OpenAL not found!")
+	endif(OPENAL_FOUND)
+endif(ENABLE_AUDIO)
+
 if(NOT MSVC)
 	set(USE_GPROF 0 CACHE BOOL "Use -pg flag for g++")
 endif()
@@ -159,6 +190,7 @@ endif()
 # Client sources
 set(minetest_SRCS
 	${common_SRCS}
+	${audio_SRCS}
 	sky.cpp
 	clientmap.cpp
 	content_cso.cpp
@@ -202,6 +234,7 @@ include_directories(
 	${CMAKE_BUILD_TYPE}
 	${PNG_INCLUDE_DIR}
 	${GETTEXT_INCLUDE_DIR}
+	${AUDIO_INLCUDE_DIR}
 	${JTHREAD_INCLUDE_DIR}
 	${SQLITE3_INCLUDE_DIR}
 	${LUA_INCLUDE_DIR}
@@ -221,6 +254,7 @@ if(BUILD_CLIENT)
 		${PNG_LIBRARIES}
 		${X11_LIBRARIES}
 		${GETTEXT_LIBRARY}
+		${AUDIO_LIBRARIES}
 		${JTHREAD_LIBRARY}
 		${SQLITE3_LIBRARY}
 		${LUA_LIBRARY}
diff --git a/src/client.cpp b/src/client.cpp
index f446200a322060ef1a5d6fae8aaee64fb941a342..220fd04dda92186acc75186e3db6067f1408e1d9 100644
--- a/src/client.cpp
+++ b/src/client.cpp
@@ -38,6 +38,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "sha1.h"
 #include "base64.h"
 #include "clientmap.h"
+#include "sound.h"
 
 static std::string getTextureCacheDir()
 {
@@ -2323,4 +2324,8 @@ u16 Client::allocateUnknownNodeId(const std::string &name)
 	assert(0);
 	return CONTENT_IGNORE;
 }
+ISoundManager* Client::getSoundManager()
+{
+	return &dummySoundManager;
+}
 
diff --git a/src/client.h b/src/client.h
index 1903f3aa7b56c1bc6bf0dd9ec06ce20bf6383e6d..6063631dac7c9054fc6c82e717105a0a1bf6b8b4 100644
--- a/src/client.h
+++ b/src/client.h
@@ -306,6 +306,7 @@ class Client : public con::PeerHandler, public InventoryManager, public IGameDef
 	virtual ICraftDefManager* getCraftDefManager();
 	virtual ITextureSource* getTextureSource();
 	virtual u16 allocateUnknownNodeId(const std::string &name);
+	virtual ISoundManager* getSoundManager();
 
 private:
 	
diff --git a/src/game.cpp b/src/game.cpp
index 3e9f448d3dcef77d116947ec63538d040c0a8f51..35a0e2533498abc3c1479ca53637b58fc01cf004 100644
--- a/src/game.cpp
+++ b/src/game.cpp
@@ -55,6 +55,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "quicktune_shortcutter.h"
 #include "clientmap.h"
 #include "sky.h"
+#include "sound.h"
 #include <list>
 
 /*
diff --git a/src/gamedef.h b/src/gamedef.h
index 10ab0b0bcfb57e4ecd9cc71516366ca81302d950..91bcc0e6594bbe1cc46d1b397fe00a81b0c1804d 100644
--- a/src/gamedef.h
+++ b/src/gamedef.h
@@ -27,6 +27,7 @@ class IItemDefManager;
 class INodeDefManager;
 class ICraftDefManager;
 class ITextureSource;
+class ISoundManager;
 
 /*
 	An interface for fetching game-global definitions like tool and
@@ -46,6 +47,8 @@ class IGameDef
 	// pointers in other threads than main thread will make things explode.
 	virtual ITextureSource* getTextureSource()=0;
 	
+	virtual ISoundManager* getSoundManager()=0;
+	
 	// Used for keeping track of names/ids of unknown nodes
 	virtual u16 allocateUnknownNodeId(const std::string &name)=0;
 
@@ -54,6 +57,7 @@ class IGameDef
 	INodeDefManager* ndef(){return getNodeDefManager();}
 	ICraftDefManager* cdef(){return getCraftDefManager();}
 	ITextureSource* tsrc(){return getTextureSource();}
+	ISoundManager* sound(){return getSoundManager();}
 };
 
 #endif
diff --git a/src/server.cpp b/src/server.cpp
index 7afb22846e867622624e78d15a2fcb136fd4ba9a..d762f2688d0d80dd458512ded1938065ca494cda 100644
--- a/src/server.cpp
+++ b/src/server.cpp
@@ -49,6 +49,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "base64.h"
 #include "tool.h"
 #include "utility_string.h"
+#include "sound.h" // dummySoundManager
 
 #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
 
@@ -4270,6 +4271,10 @@ u16 Server::allocateUnknownNodeId(const std::string &name)
 {
 	return m_nodedef->allocateDummy(name);
 }
+ISoundManager* Server::getSoundManager()
+{
+	return &dummySoundManager;
+}
 
 IWritableItemDefManager* Server::getWritableItemDefManager()
 {
diff --git a/src/server.h b/src/server.h
index 328c7fb9cc12bc1d31ce33af3aaaf9fba89be650..cdedd06d89aec7c5714b01cfb2b9b3ce48f290f7 100644
--- a/src/server.h
+++ b/src/server.h
@@ -513,6 +513,7 @@ class Server : public con::PeerHandler, public MapEventReceiver,
 	virtual ICraftDefManager* getCraftDefManager();
 	virtual ITextureSource* getTextureSource();
 	virtual u16 allocateUnknownNodeId(const std::string &name);
+	virtual ISoundManager* getSoundManager();
 	
 	IWritableItemDefManager* getWritableItemDefManager();
 	IWritableNodeDefManager* getWritableNodeDefManager();
diff --git a/src/sound.cpp b/src/sound.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..fe8da73b356d604514d87b7e69e42edbc7250838
--- /dev/null
+++ b/src/sound.cpp
@@ -0,0 +1,25 @@
+/*
+Minetest-c55
+Copyright (C) 2012 celeron55, Perttu Ahola <celeron55@gmail.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "sound.h"
+
+// Global DummySoundManager singleton
+DummySoundManager dummySoundManager;
+
+
diff --git a/src/sound.h b/src/sound.h
new file mode 100644
index 0000000000000000000000000000000000000000..6b20bbd321ebcce199c8d806648bb600cf60595e
--- /dev/null
+++ b/src/sound.h
@@ -0,0 +1,77 @@
+/*
+Minetest-c55
+Copyright (C) 2012 celeron55, Perttu Ahola <celeron55@gmail.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef SOUND_HEADER
+#define SOUND_HEADER
+
+#include "irrlichttypes.h"
+#include <string>
+#include <vector>
+#include <set>
+
+class OnDemandSoundFetcher
+{
+public:
+	virtual void getSoundFilenames(const std::string &name,
+			std::set<std::string> &dst);
+};
+
+class ISoundManager
+{
+public:
+	virtual ~ISoundManager(){}
+	
+	// Multiple sounds can be loaded per name; when played, the sound
+	// should be chosen randomly from alternatives
+	// Return value determines success/failure
+	virtual bool loadSound(const std::string &name,
+			const std::string &filepath) = 0;
+	virtual bool loadSound(const std::string &name,
+			const std::vector<char> &filedata) = 0;
+
+	virtual void updateListener(v3f pos, v3f vel, v3f at, v3f up) = 0;
+	// playSound functions return -1 on failure, otherwise a handle to the
+	// sound
+	virtual int playSound(const std::string &name, int loopcount,
+			float volume) = 0;
+	virtual int playSoundAt(const std::string &name, int loopcount,
+			v3f pos, float volume) = 0;
+	virtual void stopSound(int sound) = 0;
+};
+
+class DummySoundManager: public ISoundManager
+{
+public:
+	virtual bool loadSound(const std::string &name,
+			const std::string &filepath) {return true;}
+	virtual bool loadSound(const std::string &name,
+			const std::vector<char> &filedata) {return true;}
+	void updateListener(v3f pos, v3f vel, v3f at, v3f up) {}
+	int playSound(const std::string &name, int loopcount,
+			float volume) {return 0;}
+	int playSoundAt(const std::string &name, int loopcount,
+			v3f pos, float volume) {return 0;}
+	void stopSound(int sound) {}
+};
+
+// Global DummySoundManager singleton
+extern DummySoundManager dummySoundManager;
+
+#endif
+
diff --git a/src/sound_openal.cpp b/src/sound_openal.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9566f95c2c5b2167cc5bed71974ce772a51fd8bb
--- /dev/null
+++ b/src/sound_openal.cpp
@@ -0,0 +1,322 @@
+/*
+Minetest-c55
+Copyright (C) 2012 celeron55, Perttu Ahola <celeron55@gmail.com>
+OpenAL support based on work by:
+Copyright (C) 2011 Sebastian 'Bahamada' Rühl
+Copyright (C) 2011 Cyriaque 'Cisoun' Skrapits <cysoun@gmail.com>
+Copyright (C) 2011 Giuseppe Bilotta <giuseppe.bilotta@gmail.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program; ifnot, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "sound_openal.h"
+
+#if defined(_MSC_VER)
+	#include <al.h>
+	#include <alc.h>
+	#include <alext.h>
+#elif defined(__APPLE__)
+	#include <OpenAL/al.h>
+	#include <OpenAL/alc.h>
+	#include <OpenAL/alext.h>
+#else
+	#include <AL/al.h>
+	#include <AL/alc.h>
+	#include <AL/alext.h>
+#endif
+#include <vorbis/vorbisfile.h>
+#include "log.h"
+#include <map>
+#include <vector>
+#include "utility.h" // myrand()
+
+#define BUFFER_SIZE 30000
+
+static const char *alcErrorString(ALCenum err)
+{
+	switch (err) {
+	case ALC_NO_ERROR:
+		return "no error";
+	case ALC_INVALID_DEVICE:
+		return "invalid device";
+	case ALC_INVALID_CONTEXT:
+		return "invalid context";
+	case ALC_INVALID_ENUM:
+		return "invalid enum";
+	case ALC_INVALID_VALUE:
+		return "invalid value";
+	case ALC_OUT_OF_MEMORY:
+		return "out of memory";
+	default:
+		return "<unknown OpenAL error>";
+	}
+}
+
+static const char *alErrorString(ALenum err)
+{
+	switch (err) {
+	case AL_NO_ERROR:
+		return "no error";
+	case AL_INVALID_NAME:
+		return "invalid name";
+	case AL_INVALID_ENUM:
+		return "invalid enum";
+	case AL_INVALID_VALUE:
+		return "invalid value";
+	case AL_INVALID_OPERATION:
+		return "invalid operation";
+	case AL_OUT_OF_MEMORY:
+		return "out of memory";
+	default:
+		return "<unknown OpenAL error>";
+	}
+}
+
+void f3_set(ALfloat *f3, v3f v)
+{
+	f3[0] = v.X;
+	f3[1] = v.Y;
+	f3[2] = v.Z;
+}
+
+struct SoundBuffer
+{
+	ALenum	format;
+	ALsizei	freq;
+	ALuint	bufferID;
+	std::vector<char> buffer;
+};
+
+SoundBuffer* loadOggFile(const std::string &filepath)
+{
+	int endian = 0; // 0 for Little-Endian, 1 for Big-Endian
+	int bitStream;
+	long bytes;
+	char array[BUFFER_SIZE]; // Local fixed size array
+	vorbis_info *pInfo;
+	OggVorbis_File oggFile;
+
+	// Try opening the given file
+	if(ov_fopen(filepath.c_str(), &oggFile) != 0)
+	{
+		infostream<<"Audio: Error opening "<<filepath<<" for decoding"<<std::endl;
+		return NULL;
+	}
+
+	SoundBuffer *snd = new SoundBuffer;
+
+	// Get some information about the OGG file
+	pInfo = ov_info(&oggFile, -1);
+
+	// Check the number of channels... always use 16-bit samples
+	if(pInfo->channels == 1)
+		snd->format = AL_FORMAT_MONO16;
+	else
+		snd->format = AL_FORMAT_STEREO16;
+
+	// The frequency of the sampling rate
+	snd->freq = pInfo->rate;
+
+	// Keep reading until all is read
+	do
+	{
+		// Read up to a buffer's worth of decoded sound data
+		bytes = ov_read(&oggFile, array, BUFFER_SIZE, endian, 2, 1, &bitStream);
+
+		if(bytes < 0)
+		{
+			ov_clear(&oggFile);
+			infostream<<"Audio: Error decoding "<<filepath<<std::endl;
+			return NULL;
+		}
+
+		// Append to end of buffer
+		snd->buffer.insert(snd->buffer.end(), array, array + bytes);
+	} while (bytes > 0);
+
+	alGenBuffers(1, &snd->bufferID);
+	alBufferData(snd->bufferID, snd->format,
+			&(snd->buffer[0]), snd->buffer.size(),
+			snd->freq);
+
+	ALenum error = alGetError();
+
+	if(error != AL_NO_ERROR){
+		infostream<<"Audio: OpenAL error: "<<alErrorString(error)
+				<<"preparing sound buffer"<<std::endl;
+	}
+
+	infostream<<"Audio file "<<filepath<<" loaded"<<std::endl;
+
+	// Clean up!
+	ov_clear(&oggFile);
+
+	return snd;
+}
+
+struct PlayingSound
+{
+};
+
+class OpenALSoundManager: public ISoundManager
+{
+private:
+	ALCdevice *m_device;
+	ALCcontext *m_context;
+	bool m_can_vorbis;
+	int m_next_id;
+	std::map<std::string, std::vector<SoundBuffer*> > m_buffers;
+	std::map<int, PlayingSound*> m_sounds_playing;
+public:
+	OpenALSoundManager():
+		m_device(NULL),
+		m_context(NULL),
+		m_can_vorbis(false),
+		m_next_id(1)
+	{
+		ALCenum error = ALC_NO_ERROR;
+		
+		infostream<<"Audio: Initializing..."<<std::endl;
+
+		m_device = alcOpenDevice(NULL);
+		if(!m_device){
+			infostream<<"Audio: No audio device available, audio system "
+				<<"not initialized"<<std::endl;
+			return;
+		}
+
+		if(alcIsExtensionPresent(m_device, "EXT_vorbis")){
+			infostream<<"Audio: Vorbis extension present"<<std::endl;
+			m_can_vorbis = true;
+		} else{
+			infostream<<"Audio: Vorbis extension NOT present"<<std::endl;
+			m_can_vorbis = false;
+		}
+
+		m_context = alcCreateContext(m_device, NULL);
+		if(!m_context){
+			error = alcGetError(m_device);
+			infostream<<"Audio: Unable to initialize audio context, "
+					<<"aborting audio initialization ("<<alcErrorString(error)
+					<<")"<<std::endl;
+			alcCloseDevice(m_device);
+			m_device = NULL;
+			return;
+		}
+
+		if(!alcMakeContextCurrent(m_context) ||
+				(error = alcGetError(m_device) != ALC_NO_ERROR))
+		{
+			infostream<<"Audio: Error setting audio context, aborting audio "
+					<<"initialization ("<<alcErrorString(error)<<")"<<std::endl;
+			alcDestroyContext(m_context);
+			m_context = NULL;
+			alcCloseDevice(m_device);
+			m_device = NULL;
+			return;
+		}
+
+		alDistanceModel(AL_EXPONENT_DISTANCE);
+
+		infostream<<"Audio: Initialized: OpenAL "<<alGetString(AL_VERSION)
+				<<", using "<<alcGetString(m_device, ALC_DEVICE_SPECIFIER)
+				<<std::endl;
+	}
+
+	~OpenALSoundManager()
+	{
+		infostream<<"Audio: Deinitializing..."<<std::endl;
+		// KABOOM!
+		// TODO: Clear SoundBuffers
+		alcMakeContextCurrent(NULL);
+		alcDestroyContext(m_context);
+		m_context = NULL;
+		alcCloseDevice(m_device);
+		m_device = NULL;
+		infostream<<"Audio: Deinitialized."<<std::endl;
+	}
+	
+	void addBuffer(const std::string &name, SoundBuffer *buf)
+	{
+		std::map<std::string, std::vector<SoundBuffer*> >::iterator i =
+				m_buffers.find(name);
+		if(i != m_buffers.end()){
+			i->second.push_back(buf);
+			return;
+		}
+		std::vector<SoundBuffer*> bufs;
+		bufs.push_back(buf);
+		return;
+	}
+
+	SoundBuffer* getBuffer(const std::string &name)
+	{
+		std::map<std::string, std::vector<SoundBuffer*> >::iterator i =
+				m_buffers.find(name);
+		if(i == m_buffers.end())
+			return NULL;
+		std::vector<SoundBuffer*> &bufs = i->second;
+		int j = myrand() % bufs.size();
+		return bufs[j];
+	}
+
+	void updateListener(v3f pos, v3f vel, v3f at, v3f up)
+	{
+		ALfloat f[6];
+		f3_set(f, pos);
+		alListenerfv(AL_POSITION, f);
+		f3_set(f, vel);
+		alListenerfv(AL_VELOCITY, f);
+		f3_set(f, at);
+		f3_set(f+3, up);
+		alListenerfv(AL_ORIENTATION, f);
+	}
+	
+	bool loadSound(const std::string &name,
+			const std::string &filepath)
+	{
+		SoundBuffer *buf = loadOggFile(filepath);
+		if(buf)
+			addBuffer(name, buf);
+		return false;
+	}
+	bool loadSound(const std::string &name,
+			const std::vector<char> &filedata)
+	{
+		errorstream<<"OpenALSoundManager: Loading from filedata not"
+				" implemented"<<std::endl;
+		return false;
+	}
+
+	int playSound(const std::string &name, int loopcount,
+			float volume)
+	{
+		return -1;
+	}
+	int playSoundAt(const std::string &name, int loopcount,
+			v3f pos, float volume)
+	{
+		return -1;
+	}
+	void stopSound(int sound)
+	{
+	}
+};
+
+ISoundManager *createSoundManager()
+{
+	return new OpenALSoundManager();
+};
+
diff --git a/src/sound_openal.h b/src/sound_openal.h
new file mode 100644
index 0000000000000000000000000000000000000000..de1ca3056b698bf583534260d476e6fac20a928f
--- /dev/null
+++ b/src/sound_openal.h
@@ -0,0 +1,28 @@
+/*
+Minetest-c55
+Copyright (C) 2012 celeron55, Perttu Ahola <celeron55@gmail.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef SOUND_OPENAL_HEADER
+#define SOUND_OPENAL_HEADER
+
+#include "sound.h"
+
+ISoundManager *createOpenALSoundManager();
+
+#endif
+