From f952800d49167e96a4ec8604736ef660428ed68b Mon Sep 17 00:00:00 2001 From: Mathnerd314 Date: Thu, 18 Sep 2008 23:59:57 +0000 Subject: [PATCH] Change sound handling to use exceptions. No more empty.wav is needed, and all sound errors are now non-fatal. SVN-Revision: 5777 --- src/audio/sound_file.cpp | 77 ++++++++++++++++++++++++++++----------------- src/audio/sound_manager.cpp | 17 +++++----- 2 files changed, 59 insertions(+), 35 deletions(-) diff --git a/src/audio/sound_file.cpp b/src/audio/sound_file.cpp index 2af95ca78..a3613e942 100644 --- a/src/audio/sound_file.cpp +++ b/src/audio/sound_file.cpp @@ -36,6 +36,31 @@ #include "lisp/lisp.hpp" #include "file_system.hpp" +class SoundError : public std::exception +{ +public: + SoundError(const std::string& message) throw(); + virtual ~SoundError() throw(); + + const char* what() const throw(); +private: + std::string message; +}; + +SoundError::SoundError(const std::string& message) throw() +{ + this->message = message; +} + +SoundError::~SoundError() throw() +{} + +const char* +SoundError::what() const throw() +{ + return message.c_str(); +} + class WavSoundFile : public SoundFile { public: @@ -55,7 +80,7 @@ static inline uint32_t read32LE(PHYSFS_file* file) { uint32_t result; if(PHYSFS_readULE32(file, &result) == 0) - throw std::runtime_error("file too short"); + throw SoundError("file too short"); return result; } @@ -64,7 +89,7 @@ static inline uint16_t read16LE(PHYSFS_file* file) { uint16_t result; if(PHYSFS_readULE16(file, &result) == 0) - throw std::runtime_error("file too short"); + throw SoundError("file too short"); return result; } @@ -75,19 +100,19 @@ WavSoundFile::WavSoundFile(PHYSFS_file* file) char magic[4]; if(PHYSFS_read(file, magic, sizeof(magic), 1) != 1) - throw std::runtime_error("Couldn't read file magic (not a wave file)"); + throw SoundError("Couldn't read file magic (not a wave file)"); if(strncmp(magic, "RIFF", 4) != 0) { log_debug << "MAGIC: " << magic << std::endl; - throw std::runtime_error("file is not a RIFF wav file"); + throw SoundError("file is not a RIFF wav file"); } uint32_t wavelen = read32LE(file); (void) wavelen; if(PHYSFS_read(file, magic, sizeof(magic), 1) != 1) - throw std::runtime_error("Couldn't read chunk header (not a wav file?)"); + throw SoundError("Couldn't read chunk header (not a wav file?)"); if(strncmp(magic, "WAVE", 4) != 0) - throw std::runtime_error("file is not a valid RIFF/WAVE file"); + throw SoundError("file is not a valid RIFF/WAVE file"); char chunkmagic[4]; uint32_t chunklen; @@ -95,7 +120,7 @@ WavSoundFile::WavSoundFile(PHYSFS_file* file) // search audio data format chunk do { if(PHYSFS_read(file, chunkmagic, sizeof(chunkmagic), 1) != 1) - throw std::runtime_error("EOF while searching format chunk"); + throw SoundError("EOF while searching format chunk"); chunklen = read32LE(file); if(strncmp(chunkmagic, "fmt ", 4) == 0) @@ -105,19 +130,19 @@ WavSoundFile::WavSoundFile(PHYSFS_file* file) || strncmp(chunkmagic, "LIST", 4) == 0) { // skip chunk if(PHYSFS_seek(file, PHYSFS_tell(file) + chunklen) == 0) - throw std::runtime_error("EOF while searching fmt chunk"); + throw SoundError("EOF while searching fmt chunk"); } else { - throw std::runtime_error("complex WAVE files not supported"); + throw SoundError("complex WAVE files not supported"); } } while(true); if(chunklen < 16) - throw std::runtime_error("Format chunk too short"); + throw SoundError("Format chunk too short"); // parse format uint16_t encoding = read16LE(file); if(encoding != 1) - throw std::runtime_error("only PCM encoding supported"); + throw SoundError("only PCM encoding supported"); channels = read16LE(file); rate = read32LE(file); uint32_t byterate = read32LE(file); @@ -128,13 +153,13 @@ WavSoundFile::WavSoundFile(PHYSFS_file* file) if(chunklen > 16) { if(PHYSFS_seek(file, PHYSFS_tell(file) + (chunklen-16)) == 0) - throw std::runtime_error("EOF while reading rest of format chunk"); + throw SoundError("EOF while reading rest of format chunk"); } // set file offset to DATA chunk data do { if(PHYSFS_read(file, chunkmagic, sizeof(chunkmagic), 1) != 1) - throw std::runtime_error("EOF while searching data chunk"); + throw SoundError("EOF while searching data chunk"); chunklen = read32LE(file); if(strncmp(chunkmagic, "data", 4) == 0) @@ -142,7 +167,7 @@ WavSoundFile::WavSoundFile(PHYSFS_file* file) // skip chunk if(PHYSFS_seek(file, PHYSFS_tell(file) + chunklen) == 0) - throw std::runtime_error("EOF while searching fmt chunk"); + throw SoundError("EOF while searching fmt chunk"); } while(true); datastart = PHYSFS_tell(file); @@ -158,7 +183,7 @@ void WavSoundFile::reset() { if(PHYSFS_seek(file, datastart) == 0) - throw std::runtime_error("Couldn't seek to data start"); + throw SoundError("Couldn't seek to data start"); } size_t @@ -171,7 +196,7 @@ WavSoundFile::read(void* buffer, size_t buffer_size) size_t readsize = std::min(static_cast (end - cur), buffer_size); if(PHYSFS_read(file, buffer, readsize, 1) != 1) - throw std::runtime_error("read error while reading samples"); + throw SoundError("read error while reading samples"); #ifdef WORDS_BIGENDIAN if (bits_per_sample != 16) @@ -362,7 +387,7 @@ SoundFile* load_music_file(const std::string& filename) const lisp::Lisp* root = parser.parse(filename); const lisp::Lisp* music = root->get_lisp("supertux-music"); if(music == NULL) - throw std::runtime_error("file is not a supertux-music file."); + throw SoundError("file is not a supertux-music file."); std::string raw_music_file; float loop_begin = 0; @@ -373,7 +398,7 @@ SoundFile* load_music_file(const std::string& filename) music->get("loop-at", loop_at); if(loop_begin < 0) { - throw std::runtime_error("can't loop from negative value"); + throw SoundError("can't loop from negative value"); } std::string basedir = FileSystem::dirname(filename); @@ -383,7 +408,7 @@ SoundFile* load_music_file(const std::string& filename) if(!file) { std::stringstream msg; msg << "Couldn't open '" << raw_music_file << "': " << PHYSFS_getLastError(); - throw std::runtime_error(msg.str()); + throw SoundError(msg.str()); } return new OggSoundFile(file, loop_begin, loop_at); @@ -398,29 +423,25 @@ SoundFile* load_sound_file(const std::string& filename) PHYSFS_file* file = PHYSFS_openRead(filename.c_str()); if(!file) { - log_warning << "Couldn't open '" << filename << "': " << PHYSFS_getLastError() << ", using dummy sound file." << std::endl; - file = PHYSFS_openRead("sounds/empty.wav"); - if (!file) { std::stringstream msg; - msg << "Couldn't open dummy sound file '" << filename << "': " << PHYSFS_getLastError(); - throw std::runtime_error(msg.str()); - } + msg << "Couldn't open '" << filename << "': " << PHYSFS_getLastError() << ", using dummy sound file."; + throw SoundError(msg.str()); } try { char magic[4]; if(PHYSFS_read(file, magic, sizeof(magic), 1) != 1) - throw std::runtime_error("Couldn't read magic, file too short"); + throw SoundError("Couldn't read magic, file too short"); PHYSFS_seek(file, 0); if(strncmp(magic, "RIFF", 4) == 0) return new WavSoundFile(file); else if(strncmp(magic, "OggS", 4) == 0) return new OggSoundFile(file, 0, -1); else - throw std::runtime_error("Unknown file format"); + throw SoundError("Unknown file format"); } catch(std::exception& e) { std::stringstream msg; msg << "Couldn't read '" << filename << "': " << e.what(); - throw std::runtime_error(msg.str()); + throw SoundError(msg.str()); } } diff --git a/src/audio/sound_manager.cpp b/src/audio/sound_manager.cpp index b8429036a..9d9779854 100644 --- a/src/audio/sound_manager.cpp +++ b/src/audio/sound_manager.cpp @@ -180,14 +180,17 @@ SoundManager::preload(const std::string& filename) // already loaded? if(i != buffers.end()) return; + try { + std::auto_ptr file (load_sound_file(filename)); + // only keep small files + if(file->size >= 100000) + return; - std::auto_ptr file (load_sound_file(filename)); - // only keep small files - if(file->size >= 100000) - return; - - ALuint buffer = load_file_into_buffer(file.get()); - buffers.insert(std::make_pair(filename, buffer)); + ALuint buffer = load_file_into_buffer(file.get()); + buffers.insert(std::make_pair(filename, buffer)); + } catch(std::exception& e) { + log_warning << "Error while preloading sound file: " << e.what() << std::endl; + } } void -- 2.11.0