From 58f35e44ae17a8d4c55b1b19696245666d3697d3 Mon Sep 17 00:00:00 2001 From: erihel Date: Mon, 14 Jan 2013 22:55:16 +0100 Subject: * Removed alut * Using libsndfile to load sounds and music * Added support for playing music files --- src/CMakeLists.txt | 8 ++- src/app/app.cpp | 11 +++- src/sound/oalsound/alsound.cpp | 123 ++++++++++++++++++++++++++++------------- src/sound/oalsound/alsound.h | 8 ++- src/sound/oalsound/buffer.cpp | 41 ++++++++++---- src/sound/oalsound/buffer.h | 5 +- src/sound/oalsound/channel.cpp | 35 +++++++++--- src/sound/oalsound/channel.h | 10 ++-- src/sound/sound.h | 15 +++++ src/ui/maindialog.cpp | 4 +- 10 files changed, 186 insertions(+), 74 deletions(-) (limited to 'src') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a90b735..69164dd 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -30,12 +30,14 @@ if (${OPENAL_SOUND}) if (${MXE}) set(OPTIONAL_LIBS ${CMAKE_FIND_ROOT_PATH}/lib/libOpenAL32.a - ${CMAKE_FIND_ROOT_PATH}/lib/libalut.a + ) + elseif (${PLATFORM_WINDOWS}) + set(OPTIONAL_LIBS + OpenAL32 ) else() set(OPTIONAL_LIBS openal - alut ) endif() endif() @@ -200,6 +202,7 @@ ${GLEW_LIBRARY} ${Boost_LIBRARIES} ${OPTIONAL_LIBS} ${PLATFORM_LIBS} +${LIBSNDFILE_LIBRARY} ) # Local @@ -207,6 +210,7 @@ include_directories( . .. ${CMAKE_CURRENT_BINARY_DIR} +${LIBSNDFILE_INCLUDE_DIR} ) # System diff --git a/src/app/app.cpp b/src/app/app.cpp index 4a69655..9886b24 100644 --- a/src/app/app.cpp +++ b/src/app/app.cpp @@ -321,10 +321,17 @@ bool CApplication::Create() #endif m_sound->Create(true); - if (GetProfile().GetLocalProfileString("Resources", "Sound", path)) + if (GetProfile().GetLocalProfileString("Resources", "Sound", path)) { m_sound->CacheAll(path); - else + } else { m_sound->CacheAll(GetDataSubdirPath(DIR_SOUND)); + } + + if (GetProfile().GetLocalProfileString("Resources", "Music", path)) { + m_sound->AddMusicFiles(path); + } else { + m_sound->AddMusicFiles(GetDataSubdirPath(DIR_MUSIC)); + } } std::string standardInfoMessage = diff --git a/src/sound/oalsound/alsound.cpp b/src/sound/oalsound/alsound.cpp index 80e8fe6..0228498 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 = new Channel(); 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,20 @@ 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); + + GetLogger()->Info("Done.\n"); mEnabled = true; return true; } @@ -119,28 +132,26 @@ void ALSound::SetAudioVolume(int volume) 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 + alListenerf(AL_GAIN, MIN(static_cast(volume) / MAXVOLUME, 1.0f)); + mMusicVolume = MIN(static_cast(volume) / MAXVOLUME, 1.0f); } int ALSound::GetMusicVolume() { - // TODO stub! Add music support if ( !mEnabled ) - return 0; + return 0.0f; - return 0; + return mMusicVolume * MAXVOLUME; } @@ -242,8 +253,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 @@ -307,9 +317,9 @@ int ALSound::Play(Sound sound, Math::Vector pos, float amplitude, float frequenc 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); @@ -445,36 +455,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 + + // 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 +501,67 @@ 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(mCurrentMusic->GetSoundType()) != rank) { + mCurrentMusic->FreeBuffer(); + + if (mMusic.find(rank) == mMusic.end()) { + GetLogger()->Info("Requested music %d was not found.\n", rank); + return false; + } + + Buffer *buffer = new Buffer(); + buffer->LoadFromFile(mMusic.at(rank), static_cast(rank)); + mCurrentMusic->SetBuffer(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..4651e04 100644 --- a/src/sound/oalsound/alsound.h +++ b/src/sound/oalsound/alsound.h @@ -22,7 +22,7 @@ #include #include -#include +#include #include "common/iman.h" #include "common/logger.h" @@ -87,8 +87,10 @@ class ALSound : public CSoundInterface bool m3D; bool mMute; float mAudioVolume; - ALCdevice* audioDevice; - ALCcontext* audioContext; + float mMusicVolume; + ALCdevice* mDevice; + ALCcontext* mContext; std::map mSounds; std::map mChannels; + 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(size) * 8 / channels / bits / static_cast(freq); + // read chunks of 4096 samples + std::vector data; + std::array 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(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 +#include +#include -#include +#include +#include #include "sound/sound.h" #include "common/logger.h" diff --git a/src/sound/oalsound/channel.cpp b/src/sound/oalsound/channel.cpp index 4069313..83420ea 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()) @@ -223,8 +226,8 @@ bool Channel::SetBuffer(Buffer *buffer) { 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 +240,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()) { @@ -263,7 +282,7 @@ bool Channel::IsLoaded() { bool Channel::Stop() { if (!mReady || mBuffer == nullptr) - return false; + return false; alSourceStop(mSource); if (alCheck()) { @@ -277,7 +296,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 +311,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 +322,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 mOper; bool mReady; - bool mLoop; + bool mLoop; }; diff --git a/src/sound/sound.h b/src/sound/sound.h index c9ac349..d152f76 100644 --- a/src/sound/sound.h +++ b/src/sound/sound.h @@ -22,6 +22,7 @@ #pragma once +#include #include "math/vector.h" @@ -32,6 +33,7 @@ #include #include #include +#include /*! @@ -177,6 +179,16 @@ class CSoundInterface } }; + /** Function called to add all music files to list */ + inline void AddMusicFiles(std::string path) { + for ( int i = 1; i <= 12; i++ ) { + std::stringstream filename; + filename << path << "/music" << std::setfill('0') << std::setw(3) << i << ".ogg"; + if (boost::filesystem::exists(filename.str())) + mMusic[i] = filename.str(); + } + }; + /** Function called to cache sound effect file. * This function is called by plugin interface for each file. * \param bSound - id of a file, will be used to identify sound files @@ -328,5 +340,8 @@ class CSoundInterface * \return return true if music is playing */ inline virtual bool IsPlayingMusic() {return true;}; + + protected: + std::map mMusic; }; diff --git a/src/ui/maindialog.cpp b/src/ui/maindialog.cpp index bbba825..d19166e 100644 --- a/src/ui/maindialog.cpp +++ b/src/ui/maindialog.cpp @@ -5458,10 +5458,8 @@ void CMainDialog::ChangeSetupButtons() ps = static_cast(pw->SearchControl(EVENT_INTERFACE_VOLMUSIC)); if ( ps != 0 ) { - /* - TODO: midi volume value = ps->GetVisibleValue(); - m_sound->SetMidiVolume((int)value);*/ + m_sound->SetMusicVolume(static_cast(value)); } } -- cgit v1.2.3-1-g7c22