From c301e3c82af4ad384f4baaa8244b3a5f26da5213 Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Fri, 23 Mar 2012 12:05:17 +0200 Subject: celeron55's sound system initial framework --- src/sound_openal.cpp | 322 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 322 insertions(+) create mode 100644 src/sound_openal.cpp (limited to 'src/sound_openal.cpp') diff --git a/src/sound_openal.cpp b/src/sound_openal.cpp new file mode 100644 index 000000000..9566f95c2 --- /dev/null +++ b/src/sound_openal.cpp @@ -0,0 +1,322 @@ +/* +Minetest-c55 +Copyright (C) 2012 celeron55, Perttu Ahola +OpenAL support based on work by: +Copyright (C) 2011 Sebastian 'Bahamada' Rühl +Copyright (C) 2011 Cyriaque 'Cisoun' Skrapits +Copyright (C) 2011 Giuseppe Bilotta + +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 + #include + #include +#elif defined(__APPLE__) + #include + #include + #include +#else + #include + #include + #include +#endif +#include +#include "log.h" +#include +#include +#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 ""; + } +} + +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 ""; + } +} + +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 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 "<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 "<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: "< > m_buffers; + std::map 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..."< >::iterator i = + m_buffers.find(name); + if(i != m_buffers.end()){ + i->second.push_back(buf); + return; + } + std::vector bufs; + bufs.push_back(buf); + return; + } + + SoundBuffer* getBuffer(const std::string &name) + { + std::map >::iterator i = + m_buffers.find(name); + if(i == m_buffers.end()) + return NULL; + std::vector &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 &filedata) + { + errorstream<<"OpenALSoundManager: Loading from filedata not" + " implemented"<