diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/common/resources/resourcemanager.cpp | 16 | ||||
-rw-r--r-- | src/common/resources/resourcemanager.h | 3 | ||||
-rw-r--r-- | src/common/resources/sndfile.cpp | 130 | ||||
-rw-r--r-- | src/common/resources/sndfile.h | 54 | ||||
-rw-r--r-- | src/sound/oalsound/alsound.h | 67 | ||||
-rw-r--r-- | src/sound/oalsound/buffer.cpp | 33 | ||||
-rw-r--r-- | src/sound/sound.cpp | 10 |
8 files changed, 253 insertions, 61 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 114793d..db53398 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -77,6 +77,7 @@ common/stringutils.cpp common/resources/resourcemanager.cpp common/resources/resourcestreambuffer.cpp common/resources/inputstream.cpp +common/resources/sndfile.cpp graphics/core/color.cpp graphics/engine/camera.cpp graphics/engine/cloud.cpp diff --git a/src/common/resources/resourcemanager.cpp b/src/common/resources/resourcemanager.cpp index ccef2a3..b01424b 100644 --- a/src/common/resources/resourcemanager.cpp +++ b/src/common/resources/resourcemanager.cpp @@ -124,7 +124,13 @@ SDL_RWops* CResourceManager::GetSDLFileHandler(const std::string &filename) } -int CResourceManager::SDLClose(SDL_RWops* context) +CSNDFile* CResourceManager::GetSNDFileHandler(const std::string &filename) +{ + return new CSNDFile(filename); +} + + +int CResourceManager::SDLClose(SDL_RWops *context) { if (CheckSDLContext(context)) { @@ -138,7 +144,7 @@ int CResourceManager::SDLClose(SDL_RWops* context) } -int CResourceManager::SDLRead(SDL_RWops* context, void* ptr, int size, int maxnum) +int CResourceManager::SDLRead(SDL_RWops *context, void *ptr, int size, int maxnum) { if (CheckSDLContext(context)) { @@ -152,13 +158,13 @@ int CResourceManager::SDLRead(SDL_RWops* context, void* ptr, int size, int maxnu } -int CResourceManager::SDLWrite(SDL_RWops* context, const void* ptr, int size, int num) +int CResourceManager::SDLWrite(SDL_RWops *context, const void *ptr, int size, int num) { return 0; } -int CResourceManager::SDLSeek(SDL_RWops* context, int offset, int whence) +int CResourceManager::SDLSeek(SDL_RWops *context, int offset, int whence) { if (CheckSDLContext(context)) { @@ -188,7 +194,7 @@ int CResourceManager::SDLSeek(SDL_RWops* context, int offset, int whence) } -bool CResourceManager::CheckSDLContext(SDL_RWops* context) +bool CResourceManager::CheckSDLContext(SDL_RWops *context) { if (context->type != 0xc010b04f) { diff --git a/src/common/resources/resourcemanager.h b/src/common/resources/resourcemanager.h index ba11d73..fec71da 100644 --- a/src/common/resources/resourcemanager.h +++ b/src/common/resources/resourcemanager.h @@ -19,6 +19,8 @@ #include <string> #include <SDL.h> +#include "common/resources/sndfile.h" + class CResourceManager { public: @@ -30,6 +32,7 @@ public: static bool SetSaveLocation(const std::string &location); static std::string GetLanguageLocation(); static SDL_RWops* GetSDLFileHandler(const std::string &filename); + static CSNDFile* GetSNDFileHandler(const std::string &filename); private: static int SDLSeek(SDL_RWops *context, int offset, int whence); diff --git a/src/common/resources/sndfile.cpp b/src/common/resources/sndfile.cpp new file mode 100644 index 0000000..9e8e729 --- /dev/null +++ b/src/common/resources/sndfile.cpp @@ -0,0 +1,130 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2014 Polish Portal of Colobot (PPC) +// * +// * 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 3 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. If not, see http://www.gnu.org/licenses/. + +#include "common/resources/sndfile.h" + +#include <cstring> + + +CSNDFile::CSNDFile(const std::string& filename) +{ + memset(&m_file_info, 0, sizeof(SF_INFO)); + + if (PHYSFS_isInit()) + { + m_file = PHYSFS_openRead(filename.c_str()); + } + else + { + m_last_error = "Resource system not started!"; + } + + if (m_file) + { + m_snd_file = sf_open_virtual(&snd_callbacks, SFM_READ, &m_file_info, m_file); + if (!m_snd_file) + { + m_last_error = "Could not load file"; + } + } + else + { + m_last_error = std::string(PHYSFS_getLastError()); + } +} + + +CSNDFile::~CSNDFile() +{ + if (m_file) + { + PHYSFS_close(m_file); + } + + if (m_snd_file) + { + sf_close(m_snd_file); + } +} + + +bool CSNDFile::IsOpen() +{ + return m_snd_file; +} + + +SF_INFO &CSNDFile::GetFileInfo() +{ + return m_file_info; +} + + +std::string& CSNDFile::GetLastError() +{ + return m_last_error; +} + + +sf_count_t CSNDFile::Read(short int *ptr, sf_count_t items) +{ + return sf_read_short(m_snd_file, ptr, items); +} + + +sf_count_t CSNDFile::SNDLength(void *data) +{ + return PHYSFS_fileLength(static_cast<PHYSFS_File *>(data)); +} + + +sf_count_t CSNDFile::SNDRead(void *ptr, sf_count_t count, void *data) +{ + return PHYSFS_read(static_cast<PHYSFS_File *>(data), ptr, 1, count); +} + + +sf_count_t CSNDFile::SNDSeek(sf_count_t offset, int whence, void *data) +{ + PHYSFS_File *file = static_cast<PHYSFS_File *>(data); + + switch(whence) + { + case SEEK_CUR: + PHYSFS_seek(file, PHYSFS_tell(file) + offset); + break; + case SEEK_SET: + PHYSFS_seek(file, offset); + break; + case SEEK_END: + PHYSFS_seek(file, PHYSFS_fileLength(file) + offset); + break; + } + + return PHYSFS_tell(file); +} + + +sf_count_t CSNDFile::SNDTell(void *data) +{ + return PHYSFS_tell(static_cast<PHYSFS_File *>(data)); +} + + +sf_count_t CSNDFile::SNDWrite(const void *ptr, sf_count_t count, void *data) +{ + return PHYSFS_write(static_cast<PHYSFS_File *>(data), ptr, 1, count); +} diff --git a/src/common/resources/sndfile.h b/src/common/resources/sndfile.h new file mode 100644 index 0000000..5ea6ccc --- /dev/null +++ b/src/common/resources/sndfile.h @@ -0,0 +1,54 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2014 Polish Portal of Colobot (PPC) +// * +// * 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 3 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. If not, see http://www.gnu.org/licenses/. + +#pragma once + +#include <string> +#include <physfs.h> +#include <sndfile.h> + + +class CSNDFile +{ +public: + CSNDFile(const std::string &filename); + virtual ~CSNDFile(); + + SF_INFO &GetFileInfo(); + bool IsOpen(); + std::string &GetLastError(); + sf_count_t Read(short int *ptr, sf_count_t items); + +private: + static sf_count_t SNDLength(void *data); + static sf_count_t SNDSeek(sf_count_t offset, int whence, void *data); + static sf_count_t SNDRead(void *ptr, sf_count_t count, void *data); + static sf_count_t SNDWrite(const void *ptr, sf_count_t count, void *data); + static sf_count_t SNDTell(void *data); + + SF_INFO m_file_info; + SNDFILE *m_snd_file; + PHYSFS_File *m_file; + std::string m_last_error; + + SF_VIRTUAL_IO snd_callbacks = { + SNDLength, + SNDSeek, + SNDRead, + SNDWrite, + SNDTell + }; +}; diff --git a/src/sound/oalsound/alsound.h b/src/sound/oalsound/alsound.h index bb9bf28..1249f14 100644 --- a/src/sound/oalsound/alsound.h +++ b/src/sound/oalsound/alsound.h @@ -48,45 +48,44 @@ public: ALSound(); ~ALSound(); - bool Create(); - bool Cache(Sound, const std::string &); - bool CacheMusic(const std::string &); - - bool GetEnable(); - - void SetAudioVolume(int volume); - int GetAudioVolume(); - void SetMusicVolume(int volume); - int GetMusicVolume(); - - void SetListener(const Math::Vector &eye, const 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, const 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, const 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, float fadeTime=2.0f); - bool PlayMusic(const std::string &filename, bool bRepeat, float fadeTime=2.0f); - bool RestartMusic(); - void SuspendMusic(); - void StopMusic(float fadeTime=2.0f); - bool IsPlayingMusic(); - bool PlayPauseMusic(const std::string &filename, bool repeat); - void StopPauseMusic(); - - bool CheckChannel(int &channel); + bool Create() override; + bool Cache(Sound, const std::string &) override; + bool CacheMusic(const std::string &) override; + + bool GetEnable() override; + + void SetAudioVolume(int volume) override; + int GetAudioVolume() override; + void SetMusicVolume(int volume) override; + int GetMusicVolume() override; + + void SetListener(const Math::Vector &eye, const Math::Vector &lookat) override; + void FrameMove(float rTime) override; + + int Play(Sound sound, float amplitude=1.0f, float frequency=1.0f, bool bLoop = false) override; + int Play(Sound sound, const Math::Vector &pos, float amplitude=1.0f, float frequency=1.0f, bool bLoop = false) override; + bool FlushEnvelope(int channel) override; + bool AddEnvelope(int channel, float amplitude, float frequency, float time, SoundNext oper) override; + bool Position(int channel, const Math::Vector &pos) override; + bool Frequency(int channel, float frequency) override; + bool Stop(int channel) override; + bool StopAll() override; + bool MuteAll(bool bMute) override; + + bool PlayMusic(int rank, bool bRepeat, float fadeTime=2.0f) override; + bool PlayMusic(const std::string &filename, bool bRepeat, float fadeTime=2.0f) override; + bool RestartMusic() override; + void SuspendMusic() override; + void StopMusic(float fadeTime=2.0f) override; + bool IsPlayingMusic() override; + bool PlayPauseMusic(const std::string &filename, bool repeat) override; + void StopPauseMusic() override; private: void CleanUp(); int GetPriority(Sound); bool SearchFreeBuffer(Sound sound, int &channel, bool &bAlreadyLoaded); + bool CheckChannel(int &channel); bool m_enabled; float m_audioVolume; diff --git a/src/sound/oalsound/buffer.cpp b/src/sound/oalsound/buffer.cpp index b27029c..d9441ad 100644 --- a/src/sound/oalsound/buffer.cpp +++ b/src/sound/oalsound/buffer.cpp @@ -17,7 +17,10 @@ #include "sound/oalsound/buffer.h" -#include <cstring> +#include <memory> + +#include "common/resources/resourcemanager.h" + Buffer::Buffer() { @@ -42,19 +45,17 @@ 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); + std::unique_ptr<CSNDFile> file = std::unique_ptr<CSNDFile>(CResourceManager::GetSNDFileHandler(filename)); - 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); + GetLogger()->Trace(" channels %d\n", file->GetFileInfo().channels); + GetLogger()->Trace(" format %d\n", file->GetFileInfo().format); + GetLogger()->Trace(" frames %d\n", file->GetFileInfo().frames); + GetLogger()->Trace(" samplerate %d\n", file->GetFileInfo().samplerate); + GetLogger()->Trace(" sections %d\n", file->GetFileInfo().sections); - if (!file) + if (!file->IsOpen()) { - GetLogger()->Warn("Could not load file. Reason: %s\n", sf_strerror(file)); + GetLogger()->Warn("Could not load file. Reason: %s\n", file->GetLastError().c_str()); m_loaded = false; return false; } @@ -64,23 +65,21 @@ bool Buffer::LoadFromFile(std::string filename, Sound sound) { GetLogger()->Warn("Could not create audio buffer\n"); m_loaded = false; - sf_close(file); return false; } // read chunks of 4096 samples std::vector<uint16_t> data; std::array<int16_t, 4096> buffer; - data.reserve(fileInfo.frames); + data.reserve(file->GetFileInfo().frames); size_t read = 0; - while ((read = sf_read_short(file, buffer.data(), buffer.size())) != 0) + while ((read = file->Read(buffer.data(), buffer.size())) != 0) { data.insert(data.end(), buffer.begin(), buffer.begin() + read); } - sf_close(file); - 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; + alBufferData(m_buffer, file->GetFileInfo().channels == 1 ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16, &data.front(), data.size() * sizeof(uint16_t), file->GetFileInfo().samplerate); + m_duration = static_cast<float>(file->GetFileInfo().frames) / file->GetFileInfo().samplerate; m_loaded = true; return true; } diff --git a/src/sound/sound.cpp b/src/sound/sound.cpp index 9cae1fd..9c9f483 100644 --- a/src/sound/sound.cpp +++ b/src/sound/sound.cpp @@ -46,7 +46,7 @@ void CSoundInterface::CacheAll() for ( int i = 1; i < SOUND_MAX; i++ ) { std::stringstream filename; - filename << "sound" << std::setfill('0') << std::setw(3) << i << ".wav"; + filename << "sounds/sound" << std::setfill('0') << std::setw(3) << i << ".wav"; if ( !Cache(static_cast<Sound>(i), filename.str()) ) GetLogger()->Warn("Unable to load audio: %s\n", filename.str().c_str()); } @@ -54,10 +54,10 @@ void CSoundInterface::CacheAll() void CSoundInterface::AddMusicFiles() { - CacheMusic("Intro1.ogg"); - CacheMusic("Intro2.ogg"); - CacheMusic("music010.ogg"); - CacheMusic("music011.ogg"); + CacheMusic("music/Intro1.ogg"); + CacheMusic("music/Intro2.ogg"); + CacheMusic("music/music010.ogg"); + CacheMusic("music/music011.ogg"); } bool CSoundInterface::Cache(Sound bSound, const std::string &bFile) |