mirror of
https://github.com/minetest/minetest.git
synced 2024-11-27 01:53:45 +01:00
celeron55's sound system initial framework
This commit is contained in:
parent
9dd78a8a45
commit
c301e3c82a
45
cmake/Modules/FindVorbis.cmake
Normal file
45
cmake/Modules/FindVorbis.cmake
Normal file
@ -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)
|
||||||
|
|
@ -29,6 +29,37 @@ else(GETTEXT_FOUND AND ENABLE_GETTEXT)
|
|||||||
message(STATUS "GetText disabled")
|
message(STATUS "GetText disabled")
|
||||||
endif(GETTEXT_FOUND AND ENABLE_GETTEXT)
|
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)
|
if(NOT MSVC)
|
||||||
set(USE_GPROF 0 CACHE BOOL "Use -pg flag for g++")
|
set(USE_GPROF 0 CACHE BOOL "Use -pg flag for g++")
|
||||||
endif()
|
endif()
|
||||||
@ -159,6 +190,7 @@ endif()
|
|||||||
# Client sources
|
# Client sources
|
||||||
set(minetest_SRCS
|
set(minetest_SRCS
|
||||||
${common_SRCS}
|
${common_SRCS}
|
||||||
|
${audio_SRCS}
|
||||||
sky.cpp
|
sky.cpp
|
||||||
clientmap.cpp
|
clientmap.cpp
|
||||||
content_cso.cpp
|
content_cso.cpp
|
||||||
@ -202,6 +234,7 @@ include_directories(
|
|||||||
${CMAKE_BUILD_TYPE}
|
${CMAKE_BUILD_TYPE}
|
||||||
${PNG_INCLUDE_DIR}
|
${PNG_INCLUDE_DIR}
|
||||||
${GETTEXT_INCLUDE_DIR}
|
${GETTEXT_INCLUDE_DIR}
|
||||||
|
${AUDIO_INLCUDE_DIR}
|
||||||
${JTHREAD_INCLUDE_DIR}
|
${JTHREAD_INCLUDE_DIR}
|
||||||
${SQLITE3_INCLUDE_DIR}
|
${SQLITE3_INCLUDE_DIR}
|
||||||
${LUA_INCLUDE_DIR}
|
${LUA_INCLUDE_DIR}
|
||||||
@ -221,6 +254,7 @@ if(BUILD_CLIENT)
|
|||||||
${PNG_LIBRARIES}
|
${PNG_LIBRARIES}
|
||||||
${X11_LIBRARIES}
|
${X11_LIBRARIES}
|
||||||
${GETTEXT_LIBRARY}
|
${GETTEXT_LIBRARY}
|
||||||
|
${AUDIO_LIBRARIES}
|
||||||
${JTHREAD_LIBRARY}
|
${JTHREAD_LIBRARY}
|
||||||
${SQLITE3_LIBRARY}
|
${SQLITE3_LIBRARY}
|
||||||
${LUA_LIBRARY}
|
${LUA_LIBRARY}
|
||||||
|
@ -38,6 +38,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "sha1.h"
|
#include "sha1.h"
|
||||||
#include "base64.h"
|
#include "base64.h"
|
||||||
#include "clientmap.h"
|
#include "clientmap.h"
|
||||||
|
#include "sound.h"
|
||||||
|
|
||||||
static std::string getTextureCacheDir()
|
static std::string getTextureCacheDir()
|
||||||
{
|
{
|
||||||
@ -2323,4 +2324,8 @@ u16 Client::allocateUnknownNodeId(const std::string &name)
|
|||||||
assert(0);
|
assert(0);
|
||||||
return CONTENT_IGNORE;
|
return CONTENT_IGNORE;
|
||||||
}
|
}
|
||||||
|
ISoundManager* Client::getSoundManager()
|
||||||
|
{
|
||||||
|
return &dummySoundManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -306,6 +306,7 @@ public:
|
|||||||
virtual ICraftDefManager* getCraftDefManager();
|
virtual ICraftDefManager* getCraftDefManager();
|
||||||
virtual ITextureSource* getTextureSource();
|
virtual ITextureSource* getTextureSource();
|
||||||
virtual u16 allocateUnknownNodeId(const std::string &name);
|
virtual u16 allocateUnknownNodeId(const std::string &name);
|
||||||
|
virtual ISoundManager* getSoundManager();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -55,6 +55,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "quicktune_shortcutter.h"
|
#include "quicktune_shortcutter.h"
|
||||||
#include "clientmap.h"
|
#include "clientmap.h"
|
||||||
#include "sky.h"
|
#include "sky.h"
|
||||||
|
#include "sound.h"
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -27,6 +27,7 @@ class IItemDefManager;
|
|||||||
class INodeDefManager;
|
class INodeDefManager;
|
||||||
class ICraftDefManager;
|
class ICraftDefManager;
|
||||||
class ITextureSource;
|
class ITextureSource;
|
||||||
|
class ISoundManager;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
An interface for fetching game-global definitions like tool and
|
An interface for fetching game-global definitions like tool and
|
||||||
@ -46,6 +47,8 @@ public:
|
|||||||
// pointers in other threads than main thread will make things explode.
|
// pointers in other threads than main thread will make things explode.
|
||||||
virtual ITextureSource* getTextureSource()=0;
|
virtual ITextureSource* getTextureSource()=0;
|
||||||
|
|
||||||
|
virtual ISoundManager* getSoundManager()=0;
|
||||||
|
|
||||||
// Used for keeping track of names/ids of unknown nodes
|
// Used for keeping track of names/ids of unknown nodes
|
||||||
virtual u16 allocateUnknownNodeId(const std::string &name)=0;
|
virtual u16 allocateUnknownNodeId(const std::string &name)=0;
|
||||||
|
|
||||||
@ -54,6 +57,7 @@ public:
|
|||||||
INodeDefManager* ndef(){return getNodeDefManager();}
|
INodeDefManager* ndef(){return getNodeDefManager();}
|
||||||
ICraftDefManager* cdef(){return getCraftDefManager();}
|
ICraftDefManager* cdef(){return getCraftDefManager();}
|
||||||
ITextureSource* tsrc(){return getTextureSource();}
|
ITextureSource* tsrc(){return getTextureSource();}
|
||||||
|
ISoundManager* sound(){return getSoundManager();}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -49,6 +49,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "base64.h"
|
#include "base64.h"
|
||||||
#include "tool.h"
|
#include "tool.h"
|
||||||
#include "utility_string.h"
|
#include "utility_string.h"
|
||||||
|
#include "sound.h" // dummySoundManager
|
||||||
|
|
||||||
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
|
#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);
|
return m_nodedef->allocateDummy(name);
|
||||||
}
|
}
|
||||||
|
ISoundManager* Server::getSoundManager()
|
||||||
|
{
|
||||||
|
return &dummySoundManager;
|
||||||
|
}
|
||||||
|
|
||||||
IWritableItemDefManager* Server::getWritableItemDefManager()
|
IWritableItemDefManager* Server::getWritableItemDefManager()
|
||||||
{
|
{
|
||||||
|
@ -513,6 +513,7 @@ public:
|
|||||||
virtual ICraftDefManager* getCraftDefManager();
|
virtual ICraftDefManager* getCraftDefManager();
|
||||||
virtual ITextureSource* getTextureSource();
|
virtual ITextureSource* getTextureSource();
|
||||||
virtual u16 allocateUnknownNodeId(const std::string &name);
|
virtual u16 allocateUnknownNodeId(const std::string &name);
|
||||||
|
virtual ISoundManager* getSoundManager();
|
||||||
|
|
||||||
IWritableItemDefManager* getWritableItemDefManager();
|
IWritableItemDefManager* getWritableItemDefManager();
|
||||||
IWritableNodeDefManager* getWritableNodeDefManager();
|
IWritableNodeDefManager* getWritableNodeDefManager();
|
||||||
|
25
src/sound.cpp
Normal file
25
src/sound.cpp
Normal file
@ -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;
|
||||||
|
|
||||||
|
|
77
src/sound.h
Normal file
77
src/sound.h
Normal file
@ -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
|
||||||
|
|
322
src/sound_openal.cpp
Normal file
322
src/sound_openal.cpp
Normal file
@ -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();
|
||||||
|
};
|
||||||
|
|
28
src/sound_openal.h
Normal file
28
src/sound_openal.h
Normal file
@ -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
|
||||||
|
|
Loading…
Reference in New Issue
Block a user