diff options
Diffstat (limited to 'src/sound/oalsound')
-rw-r--r-- | src/sound/oalsound/alsound.cpp | 164 | ||||
-rw-r--r-- | src/sound/oalsound/alsound.h | 9 | ||||
-rw-r--r-- | src/sound/oalsound/buffer.cpp | 41 | ||||
-rw-r--r-- | src/sound/oalsound/buffer.h | 5 | ||||
-rw-r--r-- | src/sound/oalsound/channel.cpp | 42 | ||||
-rw-r--r-- | src/sound/oalsound/channel.h | 10 |
6 files changed, 191 insertions, 80 deletions
diff --git a/src/sound/oalsound/alsound.cpp b/src/sound/oalsound/alsound.cpp index 80e8fe6..2e44eef 100644 --- a/src/sound/oalsound/alsound.cpp +++ b/src/sound/oalsound/alsound.cpp @@ -27,7 +27,9 @@ ALSound::ALSound() mEnabled = false; m3D = false; mAudioVolume = 1.0f; + mMusicVolume = 1.0f; mMute = false; + mCurrentMusic = nullptr; auto pointer = CInstanceManager::GetInstancePointer(); if (pointer != nullptr) CInstanceManager::GetInstancePointer()->AddInstance(CLASS_SOUND, this); @@ -48,17 +50,21 @@ void ALSound::CleanUp() if (mEnabled) { GetLogger()->Info("Unloading files and closing device...\n"); StopAll(); - - for (auto channel : mChannels) { - delete channel.second; - } + + for (auto channel : mChannels) { + delete channel.second; + } for (auto item : mSounds) { delete item.second; - } + } mEnabled = false; - alutExit(); + + mCurrentMusic->FreeBuffer(); + delete mCurrentMusic; + alcDestroyContext(mContext); + alcCloseDevice(mDevice); } } @@ -71,13 +77,21 @@ bool ALSound::Create(bool b3D) return true; GetLogger()->Info("Opening audio device...\n"); - if (!alutInit(NULL, NULL)) { - ALenum error = alutGetError(); - GetLogger()->Error("Could not open audio device! Reason: %s\n", alutGetErrorString(error)); + mDevice = alcOpenDevice(NULL); + if (!mDevice) { + GetLogger()->Error("Could not open audio device!\n"); return false; } - GetLogger()->Info("Done.\n"); + mContext = alcCreateContext(mDevice, NULL); + if (!mContext) { + GetLogger()->Error("Could not create audio context!\n"); + return false; + } + alcMakeContextCurrent(mContext); + + mCurrentMusic = new Channel(); + GetLogger()->Info("Done.\n"); mEnabled = true; return true; } @@ -112,35 +126,35 @@ bool ALSound::GetEnable() void ALSound::SetAudioVolume(int volume) { - alListenerf(AL_GAIN, MIN(static_cast<float>(volume) / MAXVOLUME, 1.0f)); mAudioVolume = MIN(static_cast<float>(volume) / MAXVOLUME, 1.0f); + alListenerf(AL_GAIN, mAudioVolume); } int ALSound::GetAudioVolume() { - float volume; if ( !mEnabled ) return 0; - alGetListenerf(AL_GAIN, &volume); - return volume * MAXVOLUME; + return mAudioVolume * MAXVOLUME; } void ALSound::SetMusicVolume(int volume) { - // TODO stub! Add music support + mMusicVolume = MIN(static_cast<float>(volume) / MAXVOLUME, 1.0f); + if (mCurrentMusic) { + mCurrentMusic->SetVolume(mMusicVolume); + } } int ALSound::GetMusicVolume() { - // TODO stub! Add music support if ( !mEnabled ) - return 0; + return 0.0f; - return 0; + return mMusicVolume * MAXVOLUME; } @@ -242,8 +256,7 @@ bool ALSound::SearchFreeBuffer(Sound sound, int &channel, bool &bAlreadyLoaded) auto it = mChannels.end(); it--; int i = (*it).first; - while (++i) - { + while (++i) { if (mChannels.find(i) == mChannels.end()) { Channel *chn = new Channel(); // check if channel is ready to play music, if not destroy it and seek free one @@ -300,29 +313,28 @@ int ALSound::Play(Sound sound, Math::Vector pos, float amplitude, float frequenc } int channel; - bool bAlreadyLoaded; + bool bAlreadyLoaded = false; if (!SearchFreeBuffer(sound, channel, bAlreadyLoaded)) return -1; - - bAlreadyLoaded = false; + if (!bAlreadyLoaded) { if (!mChannels[channel]->SetBuffer(mSounds[sound])) { - mChannels[channel]->SetBuffer(nullptr); - return -1; - } + mChannels[channel]->SetBuffer(nullptr); + return -1; + } } - Position(channel, pos); // setting initial values - mChannels[channel]->SetStartAmplitude(amplitude); + mChannels[channel]->SetStartAmplitude(amplitude * mAudioVolume); mChannels[channel]->SetStartFrequency(frequency); mChannels[channel]->SetChangeFrequency(1.0f); mChannels[channel]->ResetOper(); - mChannels[channel]->SetFrequency(frequency * mChannels[channel]->GetFrequency()); - mChannels[channel]->SetVolume(amplitude); + mChannels[channel]->SetFrequency(frequency); + mChannels[channel]->SetVolume(amplitude * mAudioVolume); mChannels[channel]->SetLoop(bLoop); mChannels[channel]->Play(); + return channel; } @@ -445,36 +457,36 @@ void ALSound::FrameMove(float delta) for (auto it : mChannels) { if (!it.second->IsPlaying()) { continue; - } + } if (!it.second->HasEnvelope()) continue; - + SoundOper &oper = it.second->GetEnvelope(); - oper.currentTime += delta; + oper.currentTime += delta; progress = oper.currentTime / oper.totalTime; progress = MIN(progress, 1.0f); - + // setting volume volume = progress * (oper.finalAmplitude - it.second->GetStartAmplitude()); - it.second->SetVolume(volume + it.second->GetStartAmplitude()); - - // setting frequency + it.second->SetVolume((volume + it.second->GetStartAmplitude()) * mAudioVolume); + + // 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) { - oper.currentTime = 0.0f; + oper.currentTime = 0.0f; it.second->Play(); } else { - it.second->SetStartAmplitude(oper.finalAmplitude); - it.second->SetStartFrequency(oper.finalFrequency); + it.second->SetStartAmplitude(oper.finalAmplitude); + it.second->SetStartFrequency(oper.finalFrequency); if (oper.nextOper == SOPER_STOP) { - it.second->Stop(); + it.second->Stop(); } - - it.second->PopEnvelope(); + + it.second->PopEnvelope(); } } } @@ -491,32 +503,86 @@ void ALSound::SetListener(Math::Vector eye, Math::Vector lookat) bool ALSound::PlayMusic(int rank, bool bRepeat) { - // TODO stub! Add music support + if (!mEnabled) { + 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); + 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); + 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); + mCurrentMusic->SetLoop(bRepeat); + mCurrentMusic->Play(); + return true; } bool ALSound::RestartMusic() { - // TODO stub! Add music support + if (!mEnabled || !mCurrentMusic) { + return false; + } + + mCurrentMusic->Stop(); + mCurrentMusic->Play(); return true; } void ALSound::StopMusic() { - // TODO stub! Add music support + if (!mEnabled || !mCurrentMusic) { + return; + } + SuspendMusic(); } bool ALSound::IsPlayingMusic() { - // TODO stub! Add music support - return true; + if (!mEnabled || !mCurrentMusic) { + return false; + } + + return mCurrentMusic->IsPlaying(); } void ALSound::SuspendMusic() { - // TODO stub! Add music support + if (!mEnabled || !mCurrentMusic) { + return; + } + + mCurrentMusic->Stop(); } diff --git a/src/sound/oalsound/alsound.h b/src/sound/oalsound/alsound.h index 7aeec90..530aa5e 100644 --- a/src/sound/oalsound/alsound.h +++ b/src/sound/oalsound/alsound.h @@ -22,7 +22,7 @@ #include <map> #include <string> -#include <AL/alut.h> +#include <AL/al.h> #include "common/iman.h" #include "common/logger.h" @@ -87,8 +87,11 @@ class ALSound : public CSoundInterface bool m3D; bool mMute; float mAudioVolume; - ALCdevice* audioDevice; - ALCcontext* audioContext; + float mMusicVolume; + ALCdevice* mDevice; + ALCcontext* mContext; std::map<Sound, Buffer*> mSounds; std::map<int, Channel*> mChannels; + std::deque<Buffer*> mMusicCache; + Channel *mCurrentMusic; }; diff --git a/src/sound/oalsound/buffer.cpp b/src/sound/oalsound/buffer.cpp index 27da848..d76b24a 100644 --- a/src/sound/oalsound/buffer.cpp +++ b/src/sound/oalsound/buffer.cpp @@ -35,26 +35,43 @@ Buffer::~Buffer() { bool Buffer::LoadFromFile(std::string filename, Sound sound) { mSound = sound; - GetLogger()->Debug("Loading audio file: %s\n", filename.c_str()); - mBuffer = alutCreateBufferFromFile(filename.c_str()); - ALenum error = alutGetError(); - if (error) { - GetLogger()->Warn("Failed to load file. Reason: %s\n", alutGetErrorString(error)); + SF_INFO fileInfo; + SNDFILE *file = sf_open(filename.c_str(), SFM_READ, &fileInfo); + + GetLogger()->Trace(" channels %d\n", fileInfo.channels); + GetLogger()->Trace(" format %d\n", fileInfo.format); + GetLogger()->Trace(" frames %d\n", fileInfo.frames); + GetLogger()->Trace(" samplerate %d\n", fileInfo.samplerate); + GetLogger()->Trace(" sections %d\n", fileInfo.sections); + + if (!file) { + GetLogger()->Warn("Could not load file. Reason: %s\n", sf_strerror(file)); mLoaded = false; return false; } - ALint size, bits, channels, freq; - - alGetBufferi(mBuffer, AL_SIZE, &size); - alGetBufferi(mBuffer, AL_BITS, &bits); - alGetBufferi(mBuffer, AL_CHANNELS, &channels); - alGetBufferi(mBuffer, AL_FREQUENCY, &freq); + alGenBuffers(1, &mBuffer); + if (!mBuffer) { + GetLogger()->Warn("Could not create audio buffer\n"); + mLoaded = false; + sf_close(file); + return false; + } - mDuration = static_cast<ALfloat>(size) * 8 / channels / bits / static_cast<ALfloat>(freq); + // read chunks of 4096 samples + std::vector<uint16_t> data; + 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) { + data.insert(data.end(), buffer.begin(), buffer.begin() + read); + } + 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; return true; } diff --git a/src/sound/oalsound/buffer.h b/src/sound/oalsound/buffer.h index 8c4a2d3..7286deb 100644 --- a/src/sound/oalsound/buffer.h +++ b/src/sound/oalsound/buffer.h @@ -19,8 +19,11 @@ #pragma once #include <string> +#include <vector> +#include <array> -#include <AL/alut.h> +#include <AL/al.h> +#include <sndfile.h> #include "sound/sound.h" #include "common/logger.h" diff --git a/src/sound/oalsound/channel.cpp b/src/sound/oalsound/channel.cpp index 4069313..2b9af9b 100644 --- a/src/sound/oalsound/channel.cpp +++ b/src/sound/oalsound/channel.cpp @@ -34,12 +34,15 @@ Channel::Channel() { mBuffer = nullptr; mLoop = false; mInitFrequency = 0.0f; + mStartAmplitude = 0.0f; + mStartFrequency = 0.0f; + mChangeFrequency = 0.0f; } Channel::~Channel() { if (mReady) { - alSourceStop(mSource); + alSourceStop(mSource); alSourcei(mSource, AL_BUFFER, 0); alDeleteSources(1, &mSource); if (alCheck()) @@ -51,7 +54,7 @@ Channel::~Channel() { bool Channel::Play() { if (!mReady || mBuffer == nullptr) return false; - + alSourcei(mSource, AL_LOOPING, static_cast<ALint>(mLoop)); alSourcePlay(mSource); if (alCheck()) @@ -220,11 +223,12 @@ Sound Channel::GetSoundType() { bool Channel::SetBuffer(Buffer *buffer) { if (!mReady) return false; - + + Stop(); mBuffer = buffer; if (buffer == nullptr) { - alSourcei(mSource, AL_BUFFER, 0); - return true; + alSourcei(mSource, AL_BUFFER, 0); + return true; } alSourcei(mSource, AL_BUFFER, buffer->GetBuffer()); @@ -237,10 +241,26 @@ bool Channel::SetBuffer(Buffer *buffer) { } +bool Channel::FreeBuffer() { + if (!mReady) + return false; + + if (!mBuffer) { + return false; + } + + alSourceStop(mSource); + alSourcei(mSource, AL_BUFFER, 0); + delete mBuffer; + mBuffer = nullptr; + return true; +} + + bool Channel::IsPlaying() { ALint status; if (!mReady || mBuffer == nullptr) - return false; + return false; alGetSourcei(mSource, AL_SOURCE_STATE, &status); if (alCheck()) { @@ -257,13 +277,13 @@ bool Channel::IsReady() { } bool Channel::IsLoaded() { - return mBuffer == nullptr; + return mBuffer != nullptr; } bool Channel::Stop() { if (!mReady || mBuffer == nullptr) - return false; + return false; alSourceStop(mSource); if (alCheck()) { @@ -277,7 +297,7 @@ bool Channel::Stop() { float Channel::GetCurrentTime() { if (!mReady || mBuffer == nullptr) - return 0.0f; + return 0.0f; ALfloat current; alGetSourcef(mSource, AL_SEC_OFFSET, ¤t); @@ -292,7 +312,7 @@ float Channel::GetCurrentTime() void Channel::SetCurrentTime(float current) { if (!mReady || mBuffer == nullptr) - return; + return; alSourcef(mSource, AL_SEC_OFFSET, current); if (alCheck()) @@ -303,7 +323,7 @@ void Channel::SetCurrentTime(float current) float Channel::GetDuration() { if (!mReady || mBuffer == nullptr) - return 0.0f; + return 0.0f; return mBuffer->GetDuration(); } diff --git a/src/sound/oalsound/channel.h b/src/sound/oalsound/channel.h index 70307ef..8965306 100644 --- a/src/sound/oalsound/channel.h +++ b/src/sound/oalsound/channel.h @@ -52,7 +52,7 @@ class Channel bool SetFrequency(float); float GetFrequency(); - bool AdjustFrequency(float); + bool AdjustFrequency(float); float GetCurrentTime(); void SetCurrentTime(float); @@ -62,9 +62,11 @@ class Channel float GetVolume(); bool IsPlaying(); bool IsReady(); - bool IsLoaded(); + bool IsLoaded(); bool SetBuffer(Buffer *); + bool FreeBuffer(); + bool HasEnvelope(); SoundOper& GetEnvelope(); void PopEnvelope(); @@ -84,7 +86,7 @@ class Channel void AddOper(SoundOper); void ResetOper(); Sound GetSoundType(); - void SetLoop(bool); + void SetLoop(bool); private: Buffer *mBuffer; @@ -97,5 +99,5 @@ class Channel float mInitFrequency; std::deque<SoundOper> mOper; bool mReady; - bool mLoop; + bool mLoop; }; |