* Fixed sound pitch causing segfault

* Sound support should now compile fine with MXE
* Added cache for 3 music files to speedup loading
* Updated howto
dev-ui
erihel 2013-01-16 01:45:38 +01:00
parent 01c39c88f6
commit 9f75a29e88
8 changed files with 66 additions and 29 deletions

View File

@ -52,7 +52,7 @@ if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")
COMMAND ${CMAKE_CXX_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION) COMMAND ${CMAKE_CXX_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION)
if (GCC_VERSION VERSION_GREATER 4.7 OR GCC_VERSION VERSION_EQUAL 4.7) if (GCC_VERSION VERSION_GREATER 4.7 OR GCC_VERSION VERSION_EQUAL 4.7)
message(STATUS "Detected GCC version 4.7+") message(STATUS "Detected GCC version 4.7+")
set(CXX11_FLAGS "-std=c++11") set(CXX11_FLAGS "-std=gnu++11")
elseif (GCC_VERSION VERSION_GREATER 4.6 OR GCC_VERSION VERSION_EQUAL 4.6) elseif (GCC_VERSION VERSION_GREATER 4.6 OR GCC_VERSION VERSION_EQUAL 4.6)
message(STATUS "Detected GCC version 4.6+") message(STATUS "Detected GCC version 4.6+")
set(CXX11_FLAGS "-std=c++0x") set(CXX11_FLAGS "-std=c++0x")

View File

@ -49,6 +49,10 @@ libraries and tools.
xz xz
zlib zlib
for audio support:
openal
libsndfile
4. Now `cd' to colobot directory. To cross-compile a CMake project, you have to specify 4. Now `cd' to colobot directory. To cross-compile a CMake project, you have to specify
a CMake toolchain file. MXE has such file in MXE's directory: a CMake toolchain file. MXE has such file in MXE's directory:
usr/i686-pc-mingw32/share/cmake/mxe-conf.cmake usr/i686-pc-mingw32/share/cmake/mxe-conf.cmake

View File

@ -42,8 +42,10 @@ How to...
$ cmake . $ cmake .
$ make $ make
Note: If you experience problems with OpenGL's extensions, install GLEW library and enable Note #1: If you experience problems with OpenGL's extensions, install GLEW library and enable
it in compilation by setting USE_GLEW to 1 in CMakeLists.txt it in compilation by setting USE_GLEW to 1 in CMakeLists.txt
Note #2: For audio support you need libsndfile and openal.
1.3 Other platforms, compilers, etc. 1.3 Other platforms, compilers, etc.

View File

@ -12,6 +12,19 @@ if((${CMAKE_CROSSCOMPILING}) AND (DEFINED MSYS))
# Because find package scripts are lame # Because find package scripts are lame
set(SDLTTF_INCLUDE_DIR ${CMAKE_FIND_ROOT_PATH}/include/SDL) set(SDLTTF_INCLUDE_DIR ${CMAKE_FIND_ROOT_PATH}/include/SDL)
set(SDLIMAGE_INCLUDE_DIR ${CMAKE_FIND_ROOT_PATH}/include/SDL) set(SDLIMAGE_INCLUDE_DIR ${CMAKE_FIND_ROOT_PATH}/include/SDL)
if (${OPENAL_SOUND})
set(OPENAL_MXE_LIBS
${CMAKE_FIND_ROOT_PATH}/lib/libFLAC.a
${CMAKE_FIND_ROOT_PATH}/lib/libvorbis.a
${CMAKE_FIND_ROOT_PATH}/lib/libvorbisenc.a
${CMAKE_FIND_ROOT_PATH}/lib/libvorbisfile.a
${CMAKE_FIND_ROOT_PATH}/lib/libogg.a
${CMAKE_FIND_ROOT_PATH}/lib/libwsock32.a
)
endif()
set(MXE_CFLAGS "-DAL_LIBTYPE_STATIC")
set(MXE_LIBS set(MXE_LIBS
# For some reason, these have to be absolute paths # For some reason, these have to be absolute paths
${CMAKE_FIND_ROOT_PATH}/lib/libintl.a ${CMAKE_FIND_ROOT_PATH}/lib/libintl.a
@ -23,6 +36,7 @@ if((${CMAKE_CROSSCOMPILING}) AND (DEFINED MSYS))
${CMAKE_FIND_ROOT_PATH}/lib/libwinmm.a ${CMAKE_FIND_ROOT_PATH}/lib/libwinmm.a
${CMAKE_FIND_ROOT_PATH}/lib/libdxguid.a ${CMAKE_FIND_ROOT_PATH}/lib/libdxguid.a
${CMAKE_FIND_ROOT_PATH}/lib/libbz2.a ${CMAKE_FIND_ROOT_PATH}/lib/libbz2.a
${OPENAL_MXE_LIBS}
) )
else() else()
set(MXE 0) set(MXE 0)

View File

@ -1,5 +1,5 @@
# Compile flags as defined in global CMakeLists # Compile flags as defined in global CMakeLists
set(CMAKE_CXX_FLAGS ${COLOBOT_CXX_FLAGS}) set(CMAKE_CXX_FLAGS "${COLOBOT_CXX_FLAGS} ${MXE_CFLAGS}")
set(CMAKE_CXX_FLAGS_RELEASE ${COLOBOT_CXX_FLAGS_RELEASE}) set(CMAKE_CXX_FLAGS_RELEASE ${COLOBOT_CXX_FLAGS_RELEASE})
set(CMAKE_CXX_FLAGS_DEBUG ${COLOBOT_CXX_FLAGS_DEBUG}) set(CMAKE_CXX_FLAGS_DEBUG ${COLOBOT_CXX_FLAGS_DEBUG})
@ -27,11 +27,7 @@ endif()
set(OPTIONAL_LIBS "") set(OPTIONAL_LIBS "")
if (${OPENAL_SOUND}) if (${OPENAL_SOUND})
if (${MXE}) if (${PLATFORM_WINDOWS})
set(OPTIONAL_LIBS
${CMAKE_FIND_ROOT_PATH}/lib/libOpenAL32.a
)
elseif (${PLATFORM_WINDOWS})
set(OPTIONAL_LIBS set(OPTIONAL_LIBS
OpenAL32 OpenAL32
) )
@ -43,8 +39,6 @@ if (${OPENAL_SOUND})
endif() endif()
# Additional libraries per platform # Additional libraries per platform
set(PLATFORM_LIBS "")
if (${MXE}) # MXE requires special treatment if (${MXE}) # MXE requires special treatment
set(PLATFORM_LIBS ${MXE_LIBS}) set(PLATFORM_LIBS ${MXE_LIBS})
elseif (${PLATFORM_WINDOWS}) elseif (${PLATFORM_WINDOWS})
@ -201,8 +195,8 @@ ${PNG_LIBRARIES}
${GLEW_LIBRARY} ${GLEW_LIBRARY}
${Boost_LIBRARIES} ${Boost_LIBRARIES}
${OPTIONAL_LIBS} ${OPTIONAL_LIBS}
${PLATFORM_LIBS}
${LIBSNDFILE_LIBRARY} ${LIBSNDFILE_LIBRARY}
${PLATFORM_LIBS}
) )
# Local # Local
@ -210,7 +204,6 @@ include_directories(
. .
.. ..
${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}
${LIBSNDFILE_INCLUDE_DIR}
) )
# System # System
@ -223,6 +216,7 @@ ${PNG_INCLUDE_DIRS}
${GLEW_INCLUDE_PATH} ${GLEW_INCLUDE_PATH}
${Boost_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS}
${OPTIONAL_INCLUDE_DIRS} ${OPTIONAL_INCLUDE_DIRS}
${LIBSNDFILE_INCLUDE_DIR}
) )
link_directories(${CMAKE_CURRENT_SOURCE_DIR}/CBot) link_directories(${CMAKE_CURRENT_SOURCE_DIR}/CBot)

View File

@ -29,7 +29,7 @@ ALSound::ALSound()
mAudioVolume = 1.0f; mAudioVolume = 1.0f;
mMusicVolume = 1.0f; mMusicVolume = 1.0f;
mMute = false; mMute = false;
mCurrentMusic = new Channel(); mCurrentMusic = nullptr;
auto pointer = CInstanceManager::GetInstancePointer(); auto pointer = CInstanceManager::GetInstancePointer();
if (pointer != nullptr) if (pointer != nullptr)
CInstanceManager::GetInstancePointer()->AddInstance(CLASS_SOUND, this); CInstanceManager::GetInstancePointer()->AddInstance(CLASS_SOUND, this);
@ -90,6 +90,7 @@ bool ALSound::Create(bool b3D)
} }
alcMakeContextCurrent(mContext); alcMakeContextCurrent(mContext);
mCurrentMusic = new Channel();
GetLogger()->Info("Done.\n"); GetLogger()->Info("Done.\n");
mEnabled = true; mEnabled = true;
return true; return true;
@ -125,8 +126,8 @@ bool ALSound::GetEnable()
void ALSound::SetAudioVolume(int volume) 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); mAudioVolume = MIN(static_cast<float>(volume) / MAXVOLUME, 1.0f);
alListenerf(AL_GAIN, mAudioVolume);
} }
@ -141,8 +142,10 @@ int ALSound::GetAudioVolume()
void ALSound::SetMusicVolume(int volume) void ALSound::SetMusicVolume(int volume)
{ {
alListenerf(AL_GAIN, MIN(static_cast<float>(volume) / MAXVOLUME, 1.0f));
mMusicVolume = MIN(static_cast<float>(volume) / MAXVOLUME, 1.0f); mMusicVolume = MIN(static_cast<float>(volume) / MAXVOLUME, 1.0f);
if (mCurrentMusic) {
mCurrentMusic->SetVolume(mMusicVolume);
}
} }
@ -310,29 +313,28 @@ int ALSound::Play(Sound sound, Math::Vector pos, float amplitude, float frequenc
} }
int channel; int channel;
bool bAlreadyLoaded; bool bAlreadyLoaded = false;
if (!SearchFreeBuffer(sound, channel, bAlreadyLoaded)) if (!SearchFreeBuffer(sound, channel, bAlreadyLoaded))
return -1; return -1;
bAlreadyLoaded = false;
if (!bAlreadyLoaded) { if (!bAlreadyLoaded) {
if (!mChannels[channel]->SetBuffer(mSounds[sound])) { if (!mChannels[channel]->SetBuffer(mSounds[sound])) {
mChannels[channel]->SetBuffer(nullptr); mChannels[channel]->SetBuffer(nullptr);
return -1; return -1;
} }
} }
Position(channel, pos); Position(channel, pos);
// setting initial values // setting initial values
mChannels[channel]->SetStartAmplitude(amplitude); mChannels[channel]->SetStartAmplitude(amplitude * mAudioVolume);
mChannels[channel]->SetStartFrequency(frequency); mChannels[channel]->SetStartFrequency(frequency);
mChannels[channel]->SetChangeFrequency(1.0f); mChannels[channel]->SetChangeFrequency(1.0f);
mChannels[channel]->ResetOper(); mChannels[channel]->ResetOper();
mChannels[channel]->SetFrequency(frequency * mChannels[channel]->GetFrequency()); mChannels[channel]->SetFrequency(frequency);
mChannels[channel]->SetVolume(amplitude); mChannels[channel]->SetVolume(amplitude * mAudioVolume);
mChannels[channel]->SetLoop(bLoop); mChannels[channel]->SetLoop(bLoop);
mChannels[channel]->Play(); mChannels[channel]->Play();
return channel; return channel;
} }
@ -464,10 +466,10 @@ void ALSound::FrameMove(float delta)
oper.currentTime += delta; oper.currentTime += delta;
progress = oper.currentTime / oper.totalTime; progress = oper.currentTime / oper.totalTime;
progress = MIN(progress, 1.0f); progress = MIN(progress, 1.0f);
// setting volume // setting volume
volume = progress * (oper.finalAmplitude - it.second->GetStartAmplitude()); volume = progress * (oper.finalAmplitude - it.second->GetStartAmplitude());
it.second->SetVolume(volume + it.second->GetStartAmplitude()); it.second->SetVolume((volume + it.second->GetStartAmplitude()) * mAudioVolume);
// setting frequency // setting frequency
frequency = progress * (oper.finalFrequency - it.second->GetStartFrequency()) * it.second->GetStartFrequency() * it.second->GetChangeFrequency() * it.second->GetInitFrequency(); frequency = progress * (oper.finalFrequency - it.second->GetStartFrequency()) * it.second->GetStartFrequency() * it.second->GetChangeFrequency() * it.second->GetInitFrequency();
@ -506,7 +508,24 @@ bool ALSound::PlayMusic(int rank, bool bRepeat)
} }
if (static_cast<int>(mCurrentMusic->GetSoundType()) != rank) { if (static_cast<int>(mCurrentMusic->GetSoundType()) != rank) {
mCurrentMusic->FreeBuffer(); // 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()) { if (mMusic.find(rank) == mMusic.end()) {
GetLogger()->Info("Requested music %d was not found.\n", rank); GetLogger()->Info("Requested music %d was not found.\n", rank);
@ -514,8 +533,10 @@ bool ALSound::PlayMusic(int rank, bool bRepeat)
} }
Buffer *buffer = new Buffer(); Buffer *buffer = new Buffer();
mMusicCache.push_front(buffer);
buffer->LoadFromFile(mMusic.at(rank), static_cast<Sound>(rank)); buffer->LoadFromFile(mMusic.at(rank), static_cast<Sound>(rank));
mCurrentMusic->SetBuffer(buffer); mCurrentMusic->SetBuffer(buffer);
mMusicCache[rank] = buffer;
} }
mCurrentMusic->SetVolume(mMusicVolume); mCurrentMusic->SetVolume(mMusicVolume);

View File

@ -92,5 +92,6 @@ class ALSound : public CSoundInterface
ALCcontext* mContext; ALCcontext* mContext;
std::map<Sound, Buffer*> mSounds; std::map<Sound, Buffer*> mSounds;
std::map<int, Channel*> mChannels; std::map<int, Channel*> mChannels;
std::deque<Buffer*> mMusicCache;
Channel *mCurrentMusic; Channel *mCurrentMusic;
}; };

View File

@ -54,7 +54,7 @@ Channel::~Channel() {
bool Channel::Play() { bool Channel::Play() {
if (!mReady || mBuffer == nullptr) if (!mReady || mBuffer == nullptr)
return false; return false;
alSourcei(mSource, AL_LOOPING, static_cast<ALint>(mLoop)); alSourcei(mSource, AL_LOOPING, static_cast<ALint>(mLoop));
alSourcePlay(mSource); alSourcePlay(mSource);
if (alCheck()) if (alCheck())
@ -223,7 +223,8 @@ Sound Channel::GetSoundType() {
bool Channel::SetBuffer(Buffer *buffer) { bool Channel::SetBuffer(Buffer *buffer) {
if (!mReady) if (!mReady)
return false; return false;
Stop();
mBuffer = buffer; mBuffer = buffer;
if (buffer == nullptr) { if (buffer == nullptr) {
alSourcei(mSource, AL_BUFFER, 0); alSourcei(mSource, AL_BUFFER, 0);
@ -276,7 +277,7 @@ bool Channel::IsReady() {
} }
bool Channel::IsLoaded() { bool Channel::IsLoaded() {
return mBuffer == nullptr; return mBuffer != nullptr;
} }