diff options
author | Piotr Dziwinski <piotrdz@gmail.com> | 2013-06-24 21:37:15 +0200 |
---|---|---|
committer | Piotr Dziwinski <piotrdz@gmail.com> | 2013-06-24 21:37:15 +0200 |
commit | 7c2e955e1552a9c4e412ea2c936be61fc78ba010 (patch) | |
tree | ee506dfbec54f998d10c385bde3a1c3fa04e66b2 /src/sound/oalsound | |
parent | e218dcfdf2c58f8841e7ebd220527d08e870a6d5 (diff) | |
parent | b376486fd74fa02b0297ceef6d0f977b32358e5e (diff) | |
download | colobot-7c2e955e1552a9c4e412ea2c936be61fc78ba010.tar.gz colobot-7c2e955e1552a9c4e412ea2c936be61fc78ba010.tar.bz2 colobot-7c2e955e1552a9c4e412ea2c936be61fc78ba010.zip |
Colobot Gold 0.1.0-alpha
Diffstat (limited to 'src/sound/oalsound')
-rw-r--r-- | src/sound/oalsound/alsound.cpp | 517 | ||||
-rw-r--r-- | src/sound/oalsound/alsound.h | 142 | ||||
-rw-r--r-- | src/sound/oalsound/buffer.cpp | 69 | ||||
-rw-r--r-- | src/sound/oalsound/buffer.h | 48 | ||||
-rw-r--r-- | src/sound/oalsound/channel.cpp | 328 | ||||
-rw-r--r-- | src/sound/oalsound/channel.h | 142 | ||||
-rw-r--r-- | src/sound/oalsound/check.h | 1 |
7 files changed, 780 insertions, 467 deletions
diff --git a/src/sound/oalsound/alsound.cpp b/src/sound/oalsound/alsound.cpp index 8c1cb81..992b8b2 100644 --- a/src/sound/oalsound/alsound.cpp +++ b/src/sound/oalsound/alsound.cpp @@ -16,18 +16,22 @@ // * along with this program. If not, see http://www.gnu.org/licenses/. -#include "alsound.h" +#include "sound/oalsound/alsound.h" -#define MIN(a, b) (a > b ? b : a) +#include <algorithm> +#include <iomanip> + +#include <boost/filesystem.hpp> ALSound::ALSound() { - mEnabled = false; - m3D = false; - mAudioVolume = 1.0f; - mMusicVolume = 1.0f; - mMute = false; - mCurrentMusic = nullptr; + m_enabled = false; + m_3D = false; + m_audioVolume = 1.0f; + m_musicVolume = 1.0f; + m_currentMusic = nullptr; + m_eye.LoadZero(); + m_lookat.LoadZero(); } @@ -39,24 +43,36 @@ ALSound::~ALSound() void ALSound::CleanUp() { - if (mEnabled) { + if (m_enabled) + { GetLogger()->Info("Unloading files and closing device...\n"); StopAll(); + StopMusic(); - for (auto channel : mChannels) { + for (auto channel : m_channels) + { delete channel.second; } - for (auto item : mSounds) { + if (m_currentMusic) + { + delete m_currentMusic; + } + + for (auto item : m_sounds) + { delete item.second; } - mEnabled = false; + for (auto item : m_music) + { + delete item.second; + } + + m_enabled = false; - mCurrentMusic->FreeBuffer(); - delete mCurrentMusic; - alcDestroyContext(mContext); - alcCloseDevice(mDevice); + alcDestroyContext(m_context); + alcCloseDevice(m_device); } } @@ -65,41 +81,43 @@ bool ALSound::Create(bool b3D) { CleanUp(); - if (mEnabled) + if (m_enabled) return true; GetLogger()->Info("Opening audio device...\n"); - mDevice = alcOpenDevice(NULL); - if (!mDevice) { + m_device = alcOpenDevice(NULL); + if (!m_device) + { GetLogger()->Error("Could not open audio device!\n"); return false; } - mContext = alcCreateContext(mDevice, NULL); - if (!mContext) { + m_context = alcCreateContext(m_device, NULL); + if (!m_context) + { GetLogger()->Error("Could not create audio context!\n"); return false; } - alcMakeContextCurrent(mContext); + alcMakeContextCurrent(m_context); + alListenerf(AL_GAIN, m_audioVolume); + alDistanceModel(AL_LINEAR_DISTANCE_CLAMPED); - mCurrentMusic = new Channel(); + m_currentMusic = new Channel(); GetLogger()->Info("Done.\n"); - mEnabled = true; + m_enabled = true; return true; } void ALSound::SetSound3D(bool bMode) { - // TODO stub! need to be implemented - m3D = bMode; + m_3D = bMode; } bool ALSound::GetSound3D() { - // TODO stub! need to be implemented - return true; + return m_3D; } @@ -112,54 +130,70 @@ bool ALSound::GetSound3DCap() bool ALSound::GetEnable() { - return mEnabled; + return m_enabled; } void ALSound::SetAudioVolume(int volume) { - mAudioVolume = MIN(static_cast<float>(volume) / MAXVOLUME, 1.0f); - alListenerf(AL_GAIN, mAudioVolume); + m_audioVolume = static_cast<float>(volume) / MAXVOLUME; } int ALSound::GetAudioVolume() { - if ( !mEnabled ) + if ( !m_enabled ) return 0; - return mAudioVolume * MAXVOLUME; + return m_audioVolume * MAXVOLUME; } void ALSound::SetMusicVolume(int volume) { - mMusicVolume = MIN(static_cast<float>(volume) / MAXVOLUME, 1.0f); - if (mCurrentMusic) { - mCurrentMusic->SetVolume(mMusicVolume * mAudioVolume); + m_musicVolume = static_cast<float>(volume) / MAXVOLUME; + if (m_currentMusic) + { + m_currentMusic->SetVolume(m_musicVolume); } } int ALSound::GetMusicVolume() { - if ( !mEnabled ) + if ( !m_enabled ) return 0.0f; - return mMusicVolume * MAXVOLUME; + return m_musicVolume * MAXVOLUME; } bool ALSound::Cache(Sound sound, std::string filename) { Buffer *buffer = new Buffer(); - if (buffer->LoadFromFile(filename, sound)) { - mSounds[sound] = buffer; + if (buffer->LoadFromFile(filename, sound)) + { + m_sounds[sound] = buffer; return true; } return false; } +bool ALSound::CacheMusic(std::string filename) +{ + if (m_music.find(filename) == m_music.end()) + { + Buffer *buffer = new Buffer(); + std::stringstream file; + file << m_soundPath << "/" << filename; + if (buffer->LoadFromFile(file.str(), static_cast<Sound>(-1))) + { + m_music[filename] = buffer; + return true; + } + } + return false; +} int ALSound::GetPriority(Sound sound) { @@ -215,7 +249,8 @@ bool ALSound::SearchFreeBuffer(Sound sound, int &channel, bool &bAlreadyLoaded) int priority = GetPriority(sound); // Seeks a channel used which sound is stopped. - for (auto it : mChannels) { + for (auto it : m_channels) + { if (it.second->IsPlaying()) continue; if (it.second->GetSoundType() != sound) @@ -228,47 +263,55 @@ bool ALSound::SearchFreeBuffer(Sound sound, int &channel, bool &bAlreadyLoaded) } // just add a new channel if we dont have any - if (mChannels.size() == 0) { + if (m_channels.size() == 0) + { Channel *chn = new Channel(); // check if we channel ready to play music, if not report error - if (chn->IsReady()) { + if (chn->IsReady()) + { chn->SetPriority(priority); - mChannels[1] = chn; + m_channels[1] = chn; channel = 1; bAlreadyLoaded = false; return true; } delete chn; - GetLogger()->Error("Could not open channel to play sound!"); + GetLogger()->Error("Could not open channel to play sound!\n"); return false; } // Seeks a channel completely free. - if (mChannels.size() < 64) { - auto it = mChannels.end(); + if (m_channels.size() < 64) + { + auto it = m_channels.end(); it--; int i = (*it).first; - while (++i) { - if (mChannels.find(i) == mChannels.end()) { + while (++i) + { + if (m_channels.find(i) == m_channels.end()) + { Channel *chn = new Channel(); // check if channel is ready to play music, if not destroy it and seek free one - if (chn->IsReady()) { + if (chn->IsReady()) + { chn->SetPriority(priority); - mChannels[++i] = chn; + m_channels[++i] = chn; channel = i; bAlreadyLoaded = false; return true; } delete chn; - GetLogger()->Warn("Could not open additional channel to play sound!"); + GetLogger()->Warn("Could not open additional channel to play sound!\n"); } } } int lowerOrEqual = -1; - for (auto it : mChannels) { - if (it.second->GetPriority() < priority) { - GetLogger()->Debug("Sound channel with lower priority will be reused."); + for (auto it : m_channels) + { + if (it.second->GetPriority() < priority) + { + GetLogger()->Debug("Sound channel with lower priority will be reused.\n"); channel = it.first; return true; } @@ -276,9 +319,10 @@ bool ALSound::SearchFreeBuffer(Sound sound, int &channel, bool &bAlreadyLoaded) lowerOrEqual = it.first; } - if (lowerOrEqual != -1) { + if (lowerOrEqual != -1) + { channel = lowerOrEqual; - GetLogger()->Debug("Sound channel with lower or equal priority will be reused."); + GetLogger()->Debug("Sound channel with lower or equal priority will be reused.\n"); return true; } @@ -289,17 +333,18 @@ bool ALSound::SearchFreeBuffer(Sound sound, int &channel, bool &bAlreadyLoaded) int ALSound::Play(Sound sound, float amplitude, float frequency, bool bLoop) { - return Play(sound, Math::Vector(), amplitude, frequency, bLoop); + return Play(sound, m_eye, amplitude, frequency, bLoop); } int ALSound::Play(Sound sound, Math::Vector pos, float amplitude, float frequency, bool bLoop) { - if (!mEnabled) { + if (!m_enabled) + { return -1; } - - if (mSounds.find(sound) == mSounds.end()) { + if (m_sounds.find(sound) == m_sounds.end()) + { GetLogger()->Warn("Sound %d was not loaded!\n", sound); return -1; } @@ -309,23 +354,34 @@ int ALSound::Play(Sound sound, Math::Vector pos, float amplitude, float frequenc if (!SearchFreeBuffer(sound, channel, bAlreadyLoaded)) return -1; - if (!bAlreadyLoaded) { - if (!mChannels[channel]->SetBuffer(mSounds[sound])) { - mChannels[channel]->SetBuffer(nullptr); + if (!bAlreadyLoaded) + { + if (!m_channels[channel]->SetBuffer(m_sounds[sound])) + { + m_channels[channel]->SetBuffer(nullptr); return -1; } } + Position(channel, pos); + if (!m_3D) + { + ComputeVolumePan2D(channel, pos); + } + else + { + m_channels[channel]->SetVolumeAtrib(1.0f); + } // setting initial values - mChannels[channel]->SetStartAmplitude(amplitude); - mChannels[channel]->SetStartFrequency(frequency); - mChannels[channel]->SetChangeFrequency(1.0f); - mChannels[channel]->ResetOper(); - mChannels[channel]->SetFrequency(frequency); - mChannels[channel]->SetVolume(amplitude * mAudioVolume); - mChannels[channel]->SetLoop(bLoop); - mChannels[channel]->Play(); + m_channels[channel]->SetStartAmplitude(amplitude); + m_channels[channel]->SetStartFrequency(frequency); + m_channels[channel]->SetChangeFrequency(1.0f); + m_channels[channel]->ResetOper(); + m_channels[channel]->SetFrequency(frequency); + m_channels[channel]->SetVolume(powf(amplitude * m_channels[channel]->GetVolumeAtrib(), 0.2f) * m_audioVolume); + m_channels[channel]->SetLoop(bLoop); + m_channels[channel]->Play(); return channel; } @@ -333,31 +389,33 @@ int ALSound::Play(Sound sound, Math::Vector pos, float amplitude, float frequenc bool ALSound::FlushEnvelope(int channel) { - if (mChannels.find(channel) == mChannels.end()) { + if (m_channels.find(channel) == m_channels.end()) + { return false; } - mChannels[channel]->ResetOper(); + m_channels[channel]->ResetOper(); return true; } bool ALSound::AddEnvelope(int channel, float amplitude, float frequency, float time, SoundNext oper) { - if (!mEnabled) + if (!m_enabled) return false; - if (mChannels.find(channel) == mChannels.end()) { + if (m_channels.find(channel) == m_channels.end()) + { return false; } - + SoundOper op; op.finalAmplitude = amplitude; op.finalFrequency = frequency; op.totalTime = time; op.nextOper = oper; op.currentTime = 0.0f; - mChannels[channel]->AddOper(op); + m_channels[channel]->AddOper(op); return true; } @@ -365,43 +423,59 @@ bool ALSound::AddEnvelope(int channel, float amplitude, float frequency, float t bool ALSound::Position(int channel, Math::Vector pos) { - if (!mEnabled) + if (!m_enabled) return false; - if (mChannels.find(channel) == mChannels.end()) { + if (m_channels.find(channel) == m_channels.end()) + { return false; } - mChannels[channel]->SetPosition(pos); + if (m_3D) + { + m_channels[channel]->SetPan(pos); + } + else + { + ComputeVolumePan2D(channel, pos); + + if (!m_channels[channel]->HasEnvelope()) + { + float volume = m_channels[channel]->GetStartAmplitude(); + m_channels[channel]->SetVolume(powf(volume * m_channels[channel]->GetVolumeAtrib(), 0.2f) * m_audioVolume); + } + } return true; } bool ALSound::Frequency(int channel, float frequency) { - if (!mEnabled) + if (!m_enabled) return false; - if (mChannels.find(channel) == mChannels.end()) { + if (m_channels.find(channel) == m_channels.end()) + { return false; } - mChannels[channel]->SetFrequency(frequency * mChannels[channel]->GetInitFrequency()); - mChannels[channel]->SetChangeFrequency(frequency); + m_channels[channel]->SetFrequency(frequency * m_channels[channel]->GetInitFrequency()); + m_channels[channel]->SetChangeFrequency(frequency); return true; } bool ALSound::Stop(int channel) { - if (!mEnabled) + if (!m_enabled) return false; - if (mChannels.find(channel) == mChannels.end()) { + if (m_channels.find(channel) == m_channels.end()) + { return false; } - mChannels[channel]->Stop(); - mChannels[channel]->ResetOper(); + m_channels[channel]->Stop(); + m_channels[channel]->ResetOper(); return true; } @@ -409,10 +483,11 @@ bool ALSound::Stop(int channel) bool ALSound::StopAll() { - if (!mEnabled) + if (!m_enabled) return false; - for (auto channel : mChannels) { + for (auto channel : m_channels) + { channel.second->Stop(); channel.second->ResetOper(); } @@ -423,32 +498,46 @@ bool ALSound::StopAll() bool ALSound::MuteAll(bool bMute) { - if (!mEnabled) + if (!m_enabled) return false; - float volume; - mMute = bMute; - if (mMute) - volume = 0; - else - volume = mAudioVolume; - - for (auto channel : mChannels) { - channel.second->SetVolume(volume * mAudioVolume); + for (auto it : m_channels) + { + if (it.second->IsPlaying()) + { + it.second->Mute(bMute); + } } + if (bMute) + { + m_currentMusic->SetVolume(0.0f); + } + else + { + m_currentMusic->SetVolume(m_musicVolume); + } return true; } + void ALSound::FrameMove(float delta) { - if (!mEnabled) + if (!m_enabled) return; float progress; float volume, frequency; - for (auto it : mChannels) { - if (!it.second->IsPlaying()) { + for (auto it : m_channels) + { + if (!it.second->IsPlaying()) + { + continue; + } + + if (it.second->IsMuted()) + { + it.second->SetVolume(0.0f); continue; } @@ -458,25 +547,34 @@ void ALSound::FrameMove(float delta) SoundOper &oper = it.second->GetEnvelope(); oper.currentTime += delta; progress = oper.currentTime / oper.totalTime; - progress = MIN(progress, 1.0f); - + progress = std::min(progress, 1.0f); + // setting volume volume = progress * (oper.finalAmplitude - it.second->GetStartAmplitude()); - volume = (volume + it.second->GetStartAmplitude()) * mAudioVolume; - it.second->SetVolume(volume); + volume = volume + it.second->GetStartAmplitude(); + it.second->SetVolume(powf(volume * it.second->GetVolumeAtrib(), 0.2f) * m_audioVolume); // setting frequency - frequency = progress * (oper.finalFrequency - it.second->GetStartFrequency()) * it.second->GetStartFrequency() * it.second->GetChangeFrequency() * it.second->GetInitFrequency(); - it.second->AdjustFrequency(frequency); - - if (oper.totalTime <= oper.currentTime) { - if (oper.nextOper == SOPER_LOOP) { + frequency = progress; + frequency *= oper.finalFrequency - it.second->GetStartFrequency(); + frequency += it.second->GetStartFrequency(); + frequency *= it.second->GetChangeFrequency(); + frequency = (frequency * it.second->GetInitFrequency()); + it.second->SetFrequency(frequency); + + if (oper.totalTime <= oper.currentTime) + { + if (oper.nextOper == SOPER_LOOP) + { oper.currentTime = 0.0f; it.second->Play(); - } else { + } + else + { it.second->SetStartAmplitude(oper.finalAmplitude); it.second->SetStartFrequency(oper.finalFrequency); - if (oper.nextOper == SOPER_STOP) { + if (oper.nextOper == SOPER_STOP) + { it.second->Stop(); } @@ -489,94 +587,185 @@ void ALSound::FrameMove(float delta) void ALSound::SetListener(Math::Vector eye, Math::Vector lookat) { - float orientation[] = {lookat.x, lookat.y, lookat.z, 0.f, 1.f, 0.f}; - alListener3f(AL_POSITION, eye.x, eye.y, eye.z); - alListenerfv(AL_ORIENTATION, orientation); + m_eye = eye; + m_lookat = lookat; + if (m_3D) + { + float orientation[] = {lookat.x, lookat.y, lookat.z, 0.f, 1.f, 0.f}; + alListener3f(AL_POSITION, eye.x, eye.y, eye.z); + alListenerfv(AL_ORIENTATION, orientation); + } + else + { + float orientation[] = {0.0f, 0.0f, 0.0f, 0.f, 1.f, 0.f}; + alListener3f(AL_POSITION, 0.0f, 0.0f, 0.0f); + alListenerfv(AL_ORIENTATION, orientation); + + // recalculate sound position + for (auto it : m_channels) + { + if (it.second->IsPlaying()) + { + Math::Vector pos = it.second->GetPosition(); + ComputeVolumePan2D(it.first, pos); + + if (!it.second->HasEnvelope()) + { + float volume = it.second->GetStartAmplitude(); + it.second->SetVolume(powf(volume * it.second->GetVolumeAtrib(), 0.2f) * m_audioVolume); + } + } + } + } } - bool ALSound::PlayMusic(int rank, bool bRepeat) { - if (!mEnabled) { + std::stringstream filename; + filename << "music" << std::setfill('0') << std::setw(3) << rank << ".ogg"; + return PlayMusic(filename.str(), bRepeat); +} + +bool ALSound::PlayMusic(std::string filename, bool bRepeat) +{ + if (!m_enabled) + { return false; } - - if (static_cast<int>(mCurrentMusic->GetSoundType()) != rank) { - // check if we have music in cache - for (auto music : mMusicCache) { - if (static_cast<int>(music->GetSoundType()) == rank) { - GetLogger()->Debug("Music loaded from cache\n"); - mCurrentMusic->SetBuffer(music); - - mCurrentMusic->SetVolume(mMusicVolume * mAudioVolume); - mCurrentMusic->SetLoop(bRepeat); - mCurrentMusic->Play(); - return true; - } - } - - // we cache only 3 music files - if (mMusicCache.size() == 3) { - mCurrentMusic->FreeBuffer(); - mMusicCache.pop_back(); - } - if (mMusic.find(rank) == mMusic.end()) { - GetLogger()->Info("Requested music %d was not found.\n", rank); + std::stringstream file; + file << m_soundPath << "/" << filename; + + // check if we have music in cache + if (m_music.find(filename) == m_music.end()) + { + GetLogger()->Warn("Music %s was not cached!\n", filename.c_str()); + if (!boost::filesystem::exists(file.str())) + { + GetLogger()->Warn("Requested music %s was not found.\n", filename.c_str()); return false; } - Buffer *buffer = new Buffer(); - mMusicCache.push_front(buffer); - buffer->LoadFromFile(mMusic.at(rank), static_cast<Sound>(rank)); - mCurrentMusic->SetBuffer(buffer); - mMusicCache[rank] = buffer; - } - - mCurrentMusic->SetVolume(mMusicVolume * mAudioVolume); - mCurrentMusic->SetLoop(bRepeat); - mCurrentMusic->Play(); - + buffer->LoadFromFile(file.str(), static_cast<Sound>(-1)); + m_currentMusic->SetBuffer(buffer); + } + else + { + GetLogger()->Debug("Music loaded from cache\n"); + m_currentMusic->SetBuffer(m_music[filename]); + } + + m_currentMusic->SetVolume(m_musicVolume); + m_currentMusic->SetLoop(bRepeat); + m_currentMusic->Play(); + return true; } bool ALSound::RestartMusic() { - if (!mEnabled || !mCurrentMusic) { + if (!m_enabled || !m_currentMusic) + { return false; } - mCurrentMusic->Stop(); - mCurrentMusic->Play(); + m_currentMusic->Stop(); + m_currentMusic->Play(); return true; } void ALSound::StopMusic() { - if (!mEnabled || !mCurrentMusic) { + if (!m_enabled || !m_currentMusic) + { return; } - + SuspendMusic(); } bool ALSound::IsPlayingMusic() { - if (!mEnabled || !mCurrentMusic) { + if (!m_enabled || !m_currentMusic) + { return false; } - - return mCurrentMusic->IsPlaying(); + + return m_currentMusic->IsPlaying(); } void ALSound::SuspendMusic() { - if (!mEnabled || !mCurrentMusic) { + if (!m_enabled || !m_currentMusic) + { + return; + } + + m_currentMusic->Stop(); +} + + +void ALSound::ComputeVolumePan2D(int channel, Math::Vector &pos) +{ + float dist, a, g; + m_channels[channel]->SetPosition(pos); + + if (VectorsEqual(pos, m_eye)) + { + m_channels[channel]->SetVolumeAtrib(1.0f); // maximum volume + m_channels[channel]->SetPan(Math::Vector()); // at the center return; } - - mCurrentMusic->Stop(); + + dist = Distance(pos, m_eye); + if ( dist >= 110.0f ) // very far? + { + m_channels[channel]->SetVolumeAtrib(0.0f); // silence + m_channels[channel]->SetPan(Math::Vector()); // at the center + return; + } + else if ( dist <= 10.0f ) // very close? + { + m_channels[channel]->SetVolumeAtrib(1.0f); // maximum volume + m_channels[channel]->SetPan(Math::Vector()); // at the center + return; + } + m_channels[channel]->SetVolumeAtrib(1.0f - ((dist - 10.0f) / 100.0f)); + + Math::Vector one = Math::Vector(1.0f, 0.0f, 0.0f); + float angle_a = Angle(Math::Vector(m_lookat.x - m_eye.x, m_lookat.z - m_eye.z, 0.0f), one); + float angle_g = Angle(Math::Vector(pos.x - m_eye.x, pos.z - m_eye.z, 0.0f), one); + + a = fmodf(angle_a, Math::PI * 2.0f); + g = fmodf(angle_g, Math::PI * 2.0f); + + if ( a < 0.0f ) + { + a += Math::PI * 2.0f; + } + if ( g < 0.0f ) + { + g += Math::PI * 2.0f; + } + + if ( a < g ) + { + if (a + Math::PI * 2.0f - g < g - a ) + { + a += Math::PI * 2.0f; + } + } + else + { + if ( g + Math::PI * 2.0f - a < a - g ) + { + g += Math::PI * 2.0f; + } + } + + m_channels[channel]->SetPan( Math::Vector(0.0f, 0.0f, sinf(g - a)) ); } + diff --git a/src/sound/oalsound/alsound.h b/src/sound/oalsound/alsound.h index bdf06b1..ad32204 100644 --- a/src/sound/oalsound/alsound.h +++ b/src/sound/oalsound/alsound.h @@ -15,82 +15,90 @@ // * You should have received a copy of the GNU General Public License // * along with this program. If not, see http://www.gnu.org/licenses/. -// alsound.h +/** + * \file alsound.h + * \brief OpenAL implementation of sound system + */ #pragma once +#include "common/logger.h" +#include "sound/sound.h" + +#include "sound/oalsound/buffer.h" +#include "sound/oalsound/channel.h" +#include "sound/oalsound/check.h" + #include <map> #include <string> #include <AL/al.h> -#include "common/logger.h" -#include "sound/sound.h" - -#include "buffer.h" -#include "channel.h" -#include "check.h" - class ALSound : public CSoundInterface { - public: - ALSound(); - ~ALSound(); - - bool Create(bool b3D); - bool Cache(Sound, std::string); - - bool GetEnable(); - - void SetSound3D(bool bMode); - bool GetSound3D(); - bool GetSound3DCap(); - - void SetAudioVolume(int volume); - int GetAudioVolume(); - void SetMusicVolume(int volume); - int GetMusicVolume(); - - void SetListener(Math::Vector eye, Math::Vector lookat); - void FrameMove(float rTime); - - int Play(Sound sound, float amplitude=1.0f, float frequency=1.0f, bool bLoop = false); - int Play(Sound sound, Math::Vector pos, float amplitude=1.0f, float frequency=1.0f, bool bLoop = false); - bool FlushEnvelope(int channel); - bool AddEnvelope(int channel, float amplitude, float frequency, float time, SoundNext oper); - bool Position(int channel, Math::Vector pos); - bool Frequency(int channel, float frequency); - bool Stop(int channel); - bool StopAll(); - bool MuteAll(bool bMute); - - bool PlayMusic(int rank, bool bRepeat); - bool RestartMusic(); - void SuspendMusic(); - void StopMusic(); - bool IsPlayingMusic(); - - // plugin interface - std::string PluginName(); - int PluginVersion(); - void InstallPlugin(); - bool UninstallPlugin(std::string &); - - private: - void CleanUp(); - int GetPriority(Sound); - bool SearchFreeBuffer(Sound sound, int &channel, bool &bAlreadyLoaded); - - bool mEnabled; - bool m3D; - bool mMute; - float mAudioVolume; - float mMusicVolume; - ALCdevice* mDevice; - ALCcontext* mContext; - std::map<Sound, Buffer*> mSounds; - std::map<int, Channel*> mChannels; - std::deque<Buffer*> mMusicCache; - Channel *mCurrentMusic; +public: + ALSound(); + ~ALSound(); + + bool Create(bool b3D); + bool Cache(Sound, std::string); + bool CacheMusic(std::string); + + bool GetEnable(); + + void SetSound3D(bool bMode); + bool GetSound3D(); + bool GetSound3DCap(); + + void SetAudioVolume(int volume); + int GetAudioVolume(); + void SetMusicVolume(int volume); + int GetMusicVolume(); + + void SetListener(Math::Vector eye, Math::Vector lookat); + void FrameMove(float rTime); + + int Play(Sound sound, float amplitude=1.0f, float frequency=1.0f, bool bLoop = false); + int Play(Sound sound, Math::Vector pos, float amplitude=1.0f, float frequency=1.0f, bool bLoop = false); + bool FlushEnvelope(int channel); + bool AddEnvelope(int channel, float amplitude, float frequency, float time, SoundNext oper); + bool Position(int channel, Math::Vector pos); + bool Frequency(int channel, float frequency); + bool Stop(int channel); + bool StopAll(); + bool MuteAll(bool bMute); + + bool PlayMusic(int rank, bool bRepeat); + bool PlayMusic(std::string filename, bool bRepeat); + bool RestartMusic(); + void SuspendMusic(); + void StopMusic(); + bool IsPlayingMusic(); + + // plugin interface + std::string PluginName(); + int PluginVersion(); + void InstallPlugin(); + bool UninstallPlugin(std::string &); + +private: + void CleanUp(); + int GetPriority(Sound); + bool SearchFreeBuffer(Sound sound, int &channel, bool &bAlreadyLoaded); + void ComputeVolumePan2D(int channel, Math::Vector &pos); + + bool m_enabled; + bool m_3D; + float m_audioVolume; + float m_musicVolume; + ALCdevice* m_device; + ALCcontext* m_context; + std::map<Sound, Buffer*> m_sounds; + std::map<std::string, Buffer*> m_music; + std::map<int, Channel*> m_channels; + Channel *m_currentMusic; + Math::Vector m_eye; + Math::Vector m_lookat; }; + diff --git a/src/sound/oalsound/buffer.cpp b/src/sound/oalsound/buffer.cpp index edc3d74..0047f91 100644 --- a/src/sound/oalsound/buffer.cpp +++ b/src/sound/oalsound/buffer.cpp @@ -15,28 +15,35 @@ // * along with this program. If not, see http://www.gnu.org/licenses/. -#include "buffer.h" +#include "sound/oalsound/buffer.h" -Buffer::Buffer() { - mLoaded = false; - mDuration = 0.0f; +#include <cstring> + +Buffer::Buffer() +{ + m_loaded = false; + m_duration = 0.0f; } -Buffer::~Buffer() { - if (mLoaded) { - alDeleteBuffers(1, &mBuffer); +Buffer::~Buffer() +{ + if (m_loaded) + { + alDeleteBuffers(1, &m_buffer); if (alCheck()) GetLogger()->Warn("Failed to unload buffer. Code %d\n", alGetCode()); } } -bool Buffer::LoadFromFile(std::string filename, Sound sound) { - mSound = sound; +bool Buffer::LoadFromFile(std::string filename, Sound sound) +{ + m_sound = sound; GetLogger()->Debug("Loading audio file: %s\n", filename.c_str()); SF_INFO fileInfo; + memset(&fileInfo, 0, sizeof(SF_INFO)); SNDFILE *file = sf_open(filename.c_str(), SFM_READ, &fileInfo); GetLogger()->Trace(" channels %d\n", fileInfo.channels); @@ -45,16 +52,18 @@ bool Buffer::LoadFromFile(std::string filename, Sound sound) { GetLogger()->Trace(" samplerate %d\n", fileInfo.samplerate); GetLogger()->Trace(" sections %d\n", fileInfo.sections); - if (!file) { + if (!file) + { GetLogger()->Warn("Could not load file. Reason: %s\n", sf_strerror(file)); - mLoaded = false; + m_loaded = false; return false; } - alGenBuffers(1, &mBuffer); - if (!mBuffer) { + alGenBuffers(1, &m_buffer); + if (!m_buffer) + { GetLogger()->Warn("Could not create audio buffer\n"); - mLoaded = false; + m_loaded = false; sf_close(file); return false; } @@ -64,33 +73,39 @@ bool Buffer::LoadFromFile(std::string filename, Sound sound) { std::array<int16_t, 4096> buffer; data.reserve(fileInfo.frames); size_t read = 0; - while ((read = sf_read_short(file, buffer.data(), buffer.size())) != 0) { + while ((read = sf_read_short(file, buffer.data(), buffer.size())) != 0) + { data.insert(data.end(), buffer.begin(), buffer.begin() + read); } - sf_close(file); + sf_close(file); - alBufferData(mBuffer, fileInfo.channels == 1 ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16, &data.front(), data.size() * sizeof(uint16_t), fileInfo.samplerate); - mDuration = static_cast<float>(fileInfo.frames) / fileInfo.samplerate; - mLoaded = true; + alBufferData(m_buffer, fileInfo.channels == 1 ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16, &data.front(), data.size() * sizeof(uint16_t), fileInfo.samplerate); + m_duration = static_cast<float>(fileInfo.frames) / fileInfo.samplerate; + m_loaded = true; return true; } -Sound Buffer::GetSoundType() { - return mSound; +Sound Buffer::GetSoundType() +{ + return m_sound; } -ALuint Buffer::GetBuffer() { - return mBuffer; +ALuint Buffer::GetBuffer() +{ + return m_buffer; } -bool Buffer::IsLoaded() { - return mLoaded; +bool Buffer::IsLoaded() +{ + return m_loaded; } -float Buffer::GetDuration() { - return mDuration; +float Buffer::GetDuration() +{ + return m_duration; } + diff --git a/src/sound/oalsound/buffer.h b/src/sound/oalsound/buffer.h index 7286deb..d847426 100644 --- a/src/sound/oalsound/buffer.h +++ b/src/sound/oalsound/buffer.h @@ -14,10 +14,18 @@ // * You should have received a copy of the GNU General Public License // * along with this program. If not, see http://www.gnu.org/licenses/. -// buffer.h +/** + * \file buffer.h + * \brief OpenAL buffer + */ #pragma once +#include "sound/sound.h" +#include "common/logger.h" + +#include "sound/oalsound/check.h" + #include <string> #include <vector> #include <array> @@ -25,27 +33,23 @@ #include <AL/al.h> #include <sndfile.h> -#include "sound/sound.h" -#include "common/logger.h" - -#include "check.h" - class Buffer { - public: - Buffer(); - ~Buffer(); - - bool LoadFromFile(std::string, Sound); - bool IsLoaded(); - - Sound GetSoundType(); - ALuint GetBuffer(); - float GetDuration(); - - private: - ALuint mBuffer; - Sound mSound; - bool mLoaded; - float mDuration; +public: + Buffer(); + ~Buffer(); + + bool LoadFromFile(std::string, Sound); + bool IsLoaded(); + + Sound GetSoundType(); + ALuint GetBuffer(); + float GetDuration(); + +private: + ALuint m_buffer; + Sound m_sound; + bool m_loaded; + float m_duration; }; + diff --git a/src/sound/oalsound/channel.cpp b/src/sound/oalsound/channel.cpp index 19394c6..4d89df5 100644 --- a/src/sound/oalsound/channel.cpp +++ b/src/sound/oalsound/channel.cpp @@ -15,59 +15,76 @@ // * along with this program. If not, see http://www.gnu.org/licenses/. -#include "channel.h" +#include "sound/oalsound/channel.h" -#define MIN(a, b) (a > b ? b : a) - -Channel::Channel() { - alGenSources(1, &mSource); +Channel::Channel() +{ + alGenSources(1, &m_source); - if (alCheck()) { + if (alCheck()) + { GetLogger()->Warn("Failed to create sound source. Code: %d\n", alGetCode()); - mReady = false; - } else { - mReady = true; + m_ready = false; } - - mPriority = 0; - mBuffer = nullptr; - mLoop = false; - mInitFrequency = 0.0f; - mStartAmplitude = 0.0f; - mStartFrequency = 0.0f; - mChangeFrequency = 0.0f; -} - - -Channel::~Channel() { - if (mReady) { - alSourceStop(mSource); - alSourcei(mSource, AL_BUFFER, 0); - alDeleteSources(1, &mSource); + else + { + m_ready = true; + } + + m_priority = 0; + m_buffer = nullptr; + m_loop = false; + m_mute = false; + m_initFrequency = 0.0f; + m_startAmplitude = 0.0f; + m_startFrequency = 0.0f; + m_changeFrequency = 0.0f; + m_volume = 0.0f; +} + + +Channel::~Channel() +{ + if (m_ready) + { + alSourceStop(m_source); + alSourcei(m_source, AL_BUFFER, 0); + alDeleteSources(1, &m_source); if (alCheck()) GetLogger()->Warn("Failed to delete sound source. Code: %d\n", alGetCode()); } } -bool Channel::Play() { - if (!mReady || mBuffer == nullptr) +bool Channel::Play() +{ + if (!m_ready || m_buffer == nullptr) + { return false; + } - alSourcei(mSource, AL_LOOPING, static_cast<ALint>(mLoop)); - alSourcePlay(mSource); + alSourcei(m_source, AL_LOOPING, static_cast<ALint>(m_loop)); + alSourcei(m_source, AL_REFERENCE_DISTANCE, 10.0f); + alSourcei(m_source, AL_MAX_DISTANCE, 110.0f); + alSourcePlay(m_source); if (alCheck()) + { GetLogger()->Warn("Could not play audio sound source. Code: %d\n", alGetCode()); + } return true; } -bool Channel::SetPosition(Math::Vector pos) { - if (!mReady || mBuffer == nullptr) +bool Channel::SetPan(Math::Vector pos) +{ + if (!m_ready || m_buffer == nullptr) + { return false; - - alSource3f(mSource, AL_POSITION, pos.x, pos.y, pos.z); - if (alCheck()) { + } + + alSource3f(m_source, AL_POSITION, pos.x, pos.y, pos.z); + if (alCheck()) + { GetLogger()->Warn("Could not set sound position. Code: %d\n", alGetCode()); return false; } @@ -75,37 +92,46 @@ bool Channel::SetPosition(Math::Vector pos) { } -bool Channel::SetFrequency(float freq) +void Channel::SetPosition(Math::Vector pos) { - if (!mReady || mBuffer == nullptr) - return false; + m_position = pos; +} - alSourcef(mSource, AL_PITCH, freq); - if (alCheck()) { - GetLogger()->Warn("Could not set sound pitch to '%f'. Code: %d\n", freq, alGetCode()); - return false; - } - return true; + +Math::Vector Channel::GetPosition() +{ + return m_position; } -bool Channel::AdjustFrequency(float freq) +bool Channel::SetFrequency(float freq) { - if (!mReady || mBuffer == nullptr) + if (!m_ready || m_buffer == nullptr) + { return false; + } - return SetFrequency(mInitFrequency + fabs(freq)); + alSourcef(m_source, AL_PITCH, freq); + if (alCheck()) + { + GetLogger()->Warn("Could not set sound pitch to '%f'. Code: %d\n", freq, alGetCode()); + return false; + } + return true; } float Channel::GetFrequency() { ALfloat freq; - if (!mReady || mBuffer == nullptr) + if (!m_ready || m_buffer == nullptr) + { return 0; - - alGetSourcef(mSource, AL_PITCH, &freq); - if (alCheck()) { + } + + alGetSourcef(m_source, AL_PITCH, &freq); + if (alCheck()) + { GetLogger()->Warn("Could not get sound pitch. Code: %d\n", alGetCode()); return 0; } @@ -116,11 +142,14 @@ float Channel::GetFrequency() bool Channel::SetVolume(float vol) { - if (!mReady || vol < 0 || mBuffer == nullptr) + if (!m_ready || vol < 0 || m_buffer == nullptr) + { return false; - - alSourcef(mSource, AL_GAIN, MIN(powf(vol, 0.2f), 1.0f)); - if (alCheck()) { + } + + alSourcef(m_source, AL_GAIN, vol); + if (alCheck()) + { GetLogger()->Warn("Could not set sound volume to '%f'. Code: %d\n", vol, alGetCode()); return false; } @@ -131,11 +160,14 @@ bool Channel::SetVolume(float vol) float Channel::GetVolume() { ALfloat vol; - if (!mReady || mBuffer == nullptr) + if (!m_ready || m_buffer == nullptr) + { return 0; - - alGetSourcef(mSource, AL_GAIN, &vol); - if (alCheck()) { + } + + alGetSourcef(m_source, AL_GAIN, &vol); + if (alCheck()) + { GetLogger()->Warn("Could not get sound volume. Code: %d\n", alGetCode()); return 0; } @@ -144,125 +176,146 @@ float Channel::GetVolume() } +void Channel::SetVolumeAtrib(float volume) +{ + m_volume = volume; +} + + +float Channel::GetVolumeAtrib() +{ + return m_volume; +} + + + int Channel::GetPriority() { - return mPriority; + return m_priority; } void Channel::SetPriority(int pri) { - mPriority = pri; + m_priority = pri; } void Channel::SetStartAmplitude(float gain) { - mStartAmplitude = gain; - SetVolume(mStartAmplitude); + m_startAmplitude = gain; } void Channel::SetStartFrequency(float freq) { - mStartFrequency = freq; + m_startFrequency = freq; } void Channel::SetChangeFrequency(float freq) { - mChangeFrequency = freq; + m_changeFrequency = freq; } float Channel::GetStartAmplitude() { - return mStartAmplitude; + return m_startAmplitude; } float Channel::GetStartFrequency() { - return mStartFrequency; + return m_startFrequency; } float Channel::GetChangeFrequency() { - return mChangeFrequency; + return m_changeFrequency; } float Channel::GetInitFrequency() { - return mInitFrequency; + return m_initFrequency; } void Channel::AddOper(SoundOper oper) { - mOper.push_back(oper); + m_oper.push_back(oper); } void Channel::ResetOper() { - mOper.clear(); + m_oper.clear(); } -Sound Channel::GetSoundType() { - if (!mReady || mBuffer == nullptr) +Sound Channel::GetSoundType() +{ + if (!m_ready || m_buffer == nullptr) + { return SOUND_NONE; - - return mBuffer->GetSoundType(); + } + + return m_buffer->GetSoundType(); } -bool Channel::SetBuffer(Buffer *buffer) { - if (!mReady) +bool Channel::SetBuffer(Buffer *buffer) +{ + if (!m_ready) return false; - Stop(); - mBuffer = buffer; - if (buffer == nullptr) { - alSourcei(mSource, AL_BUFFER, 0); + Stop(); + m_buffer = buffer; + if (buffer == nullptr) + { + alSourcei(m_source, AL_BUFFER, 0); return true; - } - - alSourcei(mSource, AL_BUFFER, buffer->GetBuffer()); - if (alCheck()) { + } + + alSourcei(m_source, AL_BUFFER, buffer->GetBuffer()); + if (alCheck()) + { GetLogger()->Warn("Could not set sound buffer. Code: %d\n", alGetCode()); return false; } - mInitFrequency = GetFrequency(); + m_initFrequency = GetFrequency(); return true; } -bool Channel::FreeBuffer() { - if (!mReady) - return false; - - if (!mBuffer) { +bool Channel::FreeBuffer() +{ + if (!m_ready || !m_buffer) + { return false; } - alSourceStop(mSource); - alSourcei(mSource, AL_BUFFER, 0); - delete mBuffer; - mBuffer = nullptr; + alSourceStop(m_source); + alSourcei(m_source, AL_BUFFER, 0); + delete m_buffer; + m_buffer = nullptr; return true; } -bool Channel::IsPlaying() { +bool Channel::IsPlaying() +{ ALint status; - if (!mReady || mBuffer == nullptr) + if (!m_ready || m_buffer == nullptr) + { return false; - - alGetSourcei(mSource, AL_SOURCE_STATE, &status); - if (alCheck()) { + } + + alGetSourcei(m_source, AL_SOURCE_STATE, &status); + if (alCheck()) + { GetLogger()->Warn("Could not get sound status. Code: %d\n", alGetCode()); return false; } @@ -271,21 +324,27 @@ bool Channel::IsPlaying() { } -bool Channel::IsReady() { - return mReady; +bool Channel::IsReady() +{ + return m_ready; } -bool Channel::IsLoaded() { - return mBuffer != nullptr; +bool Channel::IsLoaded() +{ + return m_buffer != nullptr; } -bool Channel::Stop() { - if (!mReady || mBuffer == nullptr) +bool Channel::Stop() +{ + if (!m_ready || m_buffer == nullptr) + { return false; - - alSourceStop(mSource); - if (alCheck()) { + } + + alSourceStop(m_source); + if (alCheck()) + { GetLogger()->Warn("Could not stop sound. Code: %d\n", alGetCode()); return false; } @@ -295,12 +354,15 @@ bool Channel::Stop() { float Channel::GetCurrentTime() { - if (!mReady || mBuffer == nullptr) + if (!m_ready || m_buffer == nullptr) + { return 0.0f; - + } + ALfloat current; - alGetSourcef(mSource, AL_SEC_OFFSET, ¤t); - if (alCheck()) { + alGetSourcef(m_source, AL_SEC_OFFSET, ¤t); + if (alCheck()) + { GetLogger()->Warn("Could not get source current play time. Code: %d\n", alGetCode()); return 0.0f; } @@ -310,42 +372,62 @@ float Channel::GetCurrentTime() void Channel::SetCurrentTime(float current) { - if (!mReady || mBuffer == nullptr) + if (!m_ready || m_buffer == nullptr) + { return; - - alSourcef(mSource, AL_SEC_OFFSET, current); + } + + alSourcef(m_source, AL_SEC_OFFSET, current); if (alCheck()) + { GetLogger()->Warn("Could not get source current play time. Code: %d\n", alGetCode()); + } } float Channel::GetDuration() { - if (!mReady || mBuffer == nullptr) + if (!m_ready || m_buffer == nullptr) + { return 0.0f; - - return mBuffer->GetDuration(); + } + + return m_buffer->GetDuration(); } bool Channel::HasEnvelope() { - return mOper.size() > 0; + return m_oper.size() > 0; } SoundOper& Channel::GetEnvelope() { - return mOper.front(); + return m_oper.front(); } void Channel::PopEnvelope() { - mOper.pop_front(); + m_oper.pop_front(); } -void Channel::SetLoop(bool loop) { - mLoop = loop; +void Channel::SetLoop(bool loop) +{ + m_loop = loop; +} + + +void Channel::Mute(bool mute) +{ + m_mute = mute; } + + +bool Channel::IsMuted() +{ + return m_mute; +} + diff --git a/src/sound/oalsound/channel.h b/src/sound/oalsound/channel.h index 8965306..a04b509 100644 --- a/src/sound/oalsound/channel.h +++ b/src/sound/oalsound/channel.h @@ -14,10 +14,18 @@ // * You should have received a copy of the GNU General Public License // * along with this program. If not, see http://www.gnu.org/licenses/. -// channel.h +/** + * \file channel.h + * \brief OpenAL channel + */ #pragma once +#include "sound/sound.h" + +#include "sound/oalsound/buffer.h" +#include "sound/oalsound/check.h" + #include <string> #include <deque> #include <cassert> @@ -25,11 +33,6 @@ #include <AL/al.h> #include <AL/alc.h> -#include "sound/sound.h" - -#include "buffer.h" -#include "check.h" - struct SoundOper { float finalAmplitude; @@ -42,62 +45,73 @@ struct SoundOper class Channel { - public: - Channel(); - ~Channel(); - - bool Play(); - bool Stop(); - bool SetPosition(Math::Vector); - - bool SetFrequency(float); - float GetFrequency(); - bool AdjustFrequency(float); - - float GetCurrentTime(); - void SetCurrentTime(float); - float GetDuration(); - - bool SetVolume(float); - float GetVolume(); - bool IsPlaying(); - bool IsReady(); - bool IsLoaded(); - - bool SetBuffer(Buffer *); - bool FreeBuffer(); - - bool HasEnvelope(); - SoundOper& GetEnvelope(); - void PopEnvelope(); - - int GetPriority(); - void SetPriority(int); - - void SetStartAmplitude(float); - void SetStartFrequency(float); - void SetChangeFrequency(float); - - float GetStartAmplitude(); - float GetStartFrequency(); - float GetChangeFrequency(); - float GetInitFrequency(); - - void AddOper(SoundOper); - void ResetOper(); - Sound GetSoundType(); - void SetLoop(bool); - - private: - Buffer *mBuffer; - ALuint mSource; - - int mPriority; - float mStartAmplitude; - float mStartFrequency; - float mChangeFrequency; - float mInitFrequency; - std::deque<SoundOper> mOper; - bool mReady; - bool mLoop; +public: + Channel(); + ~Channel(); + + bool Play(); + bool Stop(); + + bool SetPan(Math::Vector); + void SetPosition(Math::Vector); + Math::Vector GetPosition(); + + bool SetFrequency(float); + float GetFrequency(); + + float GetCurrentTime(); + void SetCurrentTime(float); + float GetDuration(); + + bool SetVolume(float); + float GetVolume(); + void SetVolumeAtrib(float); + float GetVolumeAtrib(); + + bool IsPlaying(); + bool IsReady(); + bool IsLoaded(); + + bool SetBuffer(Buffer *); + bool FreeBuffer(); + + bool HasEnvelope(); + SoundOper& GetEnvelope(); + void PopEnvelope(); + + int GetPriority(); + void SetPriority(int); + + void SetStartAmplitude(float); + void SetStartFrequency(float); + void SetChangeFrequency(float); + + float GetStartAmplitude(); + float GetStartFrequency(); + float GetChangeFrequency(); + float GetInitFrequency(); + + void AddOper(SoundOper); + void ResetOper(); + Sound GetSoundType(); + void SetLoop(bool); + void Mute(bool); + bool IsMuted(); + +private: + Buffer *m_buffer; + ALuint m_source; + + int m_priority; + float m_startAmplitude; + float m_startFrequency; + float m_changeFrequency; + float m_initFrequency; + float m_volume; + std::deque<SoundOper> m_oper; + bool m_ready; + bool m_loop; + bool m_mute; + Math::Vector m_position; }; + diff --git a/src/sound/oalsound/check.h b/src/sound/oalsound/check.h index cf3e468..f677e17 100644 --- a/src/sound/oalsound/check.h +++ b/src/sound/oalsound/check.h @@ -37,3 +37,4 @@ inline ALenum alGetCode() CODE = AL_NO_ERROR; return ret; } + |