From aecf74e7bbeca9dae1d19444535b511f3df7f473 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 8 Dec 2017 07:00:04 -0800 Subject: [PATCH 1/3] Don't throw exceptions from the audio decoder --- apps/openmw/mwsound/ffmpeg_decoder.cpp | 190 ++++++++++++---------- apps/openmw/mwsound/ffmpeg_decoder.hpp | 18 +- apps/openmw/mwsound/movieaudiofactory.cpp | 32 ++-- apps/openmw/mwsound/openal_output.cpp | 14 +- apps/openmw/mwsound/sound_decoder.hpp | 4 +- 5 files changed, 146 insertions(+), 112 deletions(-) diff --git a/apps/openmw/mwsound/ffmpeg_decoder.cpp b/apps/openmw/mwsound/ffmpeg_decoder.cpp index 1f1834761..12ea84a42 100644 --- a/apps/openmw/mwsound/ffmpeg_decoder.cpp +++ b/apps/openmw/mwsound/ffmpeg_decoder.cpp @@ -3,7 +3,7 @@ #include #include -#include +#include #include #include @@ -11,11 +11,6 @@ namespace MWSound { -void FFmpeg_Decoder::fail(const std::string &msg) -{ - throw std::runtime_error("FFmpeg exception: "+msg); -} - int FFmpeg_Decoder::readPacket(void *user_data, uint8_t *buf, int buf_size) { try @@ -33,7 +28,8 @@ int FFmpeg_Decoder::readPacket(void *user_data, uint8_t *buf, int buf_size) int FFmpeg_Decoder::writePacket(void *, uint8_t *, int) { - throw std::runtime_error("can't write to read-only stream"); + std::cerr<< "can't write to read-only stream" <get(fname); + try + { + mDataStream = mResourceMgr->get(fname); - if((mFormatCtx=avformat_alloc_context()) == NULL) - fail("Failed to allocate context"); + if((mFormatCtx=avformat_alloc_context()) == NULL) + throw std::runtime_error("Failed to allocate context"); - mFormatCtx->pb = avio_alloc_context(NULL, 0, 0, this, readPacket, writePacket, seek); - if(!mFormatCtx->pb || avformat_open_input(&mFormatCtx, fname.c_str(), NULL, NULL) != 0) - { - // "Note that a user-supplied AVFormatContext will be freed on failure". - if (mFormatCtx) + mFormatCtx->pb = avio_alloc_context(NULL, 0, 0, this, readPacket, writePacket, seek); + if(!mFormatCtx->pb || avformat_open_input(&mFormatCtx, fname.c_str(), NULL, NULL) != 0) { - if (mFormatCtx->pb != NULL) + // "Note that a user-supplied AVFormatContext will be freed on failure". + if (mFormatCtx) { - if (mFormatCtx->pb->buffer != NULL) + if (mFormatCtx->pb != NULL) { - av_free(mFormatCtx->pb->buffer); - mFormatCtx->pb->buffer = NULL; + if (mFormatCtx->pb->buffer != NULL) + { + av_free(mFormatCtx->pb->buffer); + mFormatCtx->pb->buffer = NULL; + } + av_free(mFormatCtx->pb); + mFormatCtx->pb = NULL; } - av_free(mFormatCtx->pb); - mFormatCtx->pb = NULL; + avformat_free_context(mFormatCtx); } - avformat_free_context(mFormatCtx); + mFormatCtx = NULL; + throw std::runtime_error("Failed to allocate input stream"); } - mFormatCtx = NULL; - fail("Failed to allocate input stream"); - } - try - { if(avformat_find_stream_info(mFormatCtx, NULL) < 0) - fail("Failed to find stream info in "+fname); + throw std::runtime_error("Failed to find stream info in "+fname); for(size_t j = 0;j < mFormatCtx->nb_streams;j++) { @@ -224,23 +220,45 @@ void FFmpeg_Decoder::open(const std::string &fname) } } if(!mStream) - fail("No audio streams in "+fname); + throw std::runtime_error("No audio streams in "+fname); (*mStream)->codec->request_sample_fmt = (*mStream)->codec->sample_fmt; AVCodec *codec = avcodec_find_decoder((*mStream)->codec->codec_id); if(!codec) { - std::stringstream ss("No codec found for id "); - ss << (*mStream)->codec->codec_id; - fail(ss.str()); + std::string ss = "No codec found for id " + + std::to_string((*mStream)->codec->codec_id); + throw std::runtime_error(ss); } if(avcodec_open2((*mStream)->codec, codec, NULL) < 0) - fail("Failed to open audio codec " + std::string(codec->long_name)); + throw std::runtime_error(std::string("Failed to open audio codec ") + + codec->long_name); mFrame = av_frame_alloc(); + + if((*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_FLT || + (*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_FLTP) + mOutputSampleFormat = AV_SAMPLE_FMT_S16; // FIXME: Check for AL_EXT_FLOAT32 support + else if((*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_U8P) + mOutputSampleFormat = AV_SAMPLE_FMT_U8; + else if((*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_S16P) + mOutputSampleFormat = AV_SAMPLE_FMT_S16; + else + mOutputSampleFormat = AV_SAMPLE_FMT_S16; + + mOutputChannelLayout = (*mStream)->codec->channel_layout; + if(mOutputChannelLayout == 0) + mOutputChannelLayout = av_get_default_channel_layout((*mStream)->codec->channels); + + return true; } - catch(std::exception&) + catch(std::exception &e) + { + std::cerr<< "Could not open audio file: "<codec); @@ -248,15 +266,15 @@ void FFmpeg_Decoder::open(const std::string &fname) if (mFormatCtx->pb->buffer != NULL) { - av_free(mFormatCtx->pb->buffer); - mFormatCtx->pb->buffer = NULL; + av_free(mFormatCtx->pb->buffer); + mFormatCtx->pb->buffer = NULL; } av_free(mFormatCtx->pb); mFormatCtx->pb = NULL; avformat_close_input(&mFormatCtx); - throw; } + return false; } void FFmpeg_Decoder::close() @@ -274,18 +292,18 @@ void FFmpeg_Decoder::close() { if (mFormatCtx->pb != NULL) { - // mFormatCtx->pb->buffer must be freed by hand, - // if not, valgrind will show memleak, see: - // - // https://trac.ffmpeg.org/ticket/1357 - // - if (mFormatCtx->pb->buffer != NULL) - { - av_free(mFormatCtx->pb->buffer); - mFormatCtx->pb->buffer = NULL; - } - av_free(mFormatCtx->pb); - mFormatCtx->pb = NULL; + // mFormatCtx->pb->buffer must be freed by hand, + // if not, valgrind will show memleak, see: + // + // https://trac.ffmpeg.org/ticket/1357 + // + if (mFormatCtx->pb->buffer != NULL) + { + av_free(mFormatCtx->pb->buffer); + mFormatCtx->pb->buffer = NULL; + } + av_free(mFormatCtx->pb); + mFormatCtx->pb = NULL; } avformat_close_input(&mFormatCtx); } @@ -298,19 +316,13 @@ std::string FFmpeg_Decoder::getName() return mFormatCtx->filename; } -void FFmpeg_Decoder::getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) +bool FFmpeg_Decoder::getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) { if(!mStream) - fail("No audio stream info"); - - if((*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_FLT || (*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_FLTP) - mOutputSampleFormat = AV_SAMPLE_FMT_S16; // FIXME: Check for AL_EXT_FLOAT32 support - else if((*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_U8P) - mOutputSampleFormat = AV_SAMPLE_FMT_U8; - else if((*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_S16P) - mOutputSampleFormat = AV_SAMPLE_FMT_S16; - else - mOutputSampleFormat = AV_SAMPLE_FMT_S16; + { + std::cerr<< "No audio stream info" <codec->channel_layout; - - if(ch_layout == 0) - ch_layout = av_get_default_channel_layout((*mStream)->codec->channels); - - mOutputChannelLayout = ch_layout; - if (ch_layout == AV_CH_LAYOUT_5POINT1 || ch_layout == AV_CH_LAYOUT_7POINT1 - || ch_layout == AV_CH_LAYOUT_QUAD) // FIXME: check for AL_EXT_MCFORMATS support - mOutputChannelLayout = AV_CH_LAYOUT_STEREO; - else if (ch_layout != AV_CH_LAYOUT_MONO - && ch_layout != AV_CH_LAYOUT_STEREO) - mOutputChannelLayout = AV_CH_LAYOUT_STEREO; - if(mOutputChannelLayout == AV_CH_LAYOUT_MONO) *chans = ChannelConfig_Mono; else if(mOutputChannelLayout == AV_CH_LAYOUT_STEREO) @@ -347,13 +346,27 @@ void FFmpeg_Decoder::getInfo(int *samplerate, ChannelConfig *chans, SampleType * char str[1024]; av_get_channel_layout_string(str, sizeof(str), (*mStream)->codec->channels, (*mStream)->codec->channel_layout); - fail(std::string("Unsupported channel layout: ")+str); + std::cerr<< "Unsupported channel layout: "<codec->channels == 1) + { + mOutputChannelLayout = AV_CH_LAYOUT_MONO; + *chans = ChannelConfig_Mono; + } + else + { + mOutputChannelLayout = AV_CH_LAYOUT_STEREO; + *chans = ChannelConfig_Stereo; + } } *samplerate = (*mStream)->codec->sample_rate; + int64_t ch_layout = (*mStream)->codec->channel_layout; + if(ch_layout == 0) + ch_layout = av_get_default_channel_layout((*mStream)->codec->channels); - if(mOutputSampleFormat != (*mStream)->codec->sample_fmt - || mOutputChannelLayout != ch_layout) + if(mOutputSampleFormat != (*mStream)->codec->sample_fmt || + mOutputChannelLayout != ch_layout) { mSwr = swr_alloc_set_opts(mSwr, // SwrContext mOutputChannelLayout, // output ch layout @@ -365,24 +378,37 @@ void FFmpeg_Decoder::getInfo(int *samplerate, ChannelConfig *chans, SampleType * 0, // logging level offset NULL); // log context if(!mSwr) - fail(std::string("Couldn't allocate SwrContext")); + { + std::cerr<< "Couldn't allocate SwrContext" < &output) { if(!mStream) - fail("No audio stream"); + { + std::cerr<< "No audio stream" < &output); - virtual size_t getSampleOffset(); - - void fail(const std::string &msg); + size_t read(char *buffer, size_t bytes) override; + void readAll(std::vector &output) override; + size_t getSampleOffset() override; FFmpeg_Decoder& operator=(const FFmpeg_Decoder &rhs); FFmpeg_Decoder(const FFmpeg_Decoder &rhs); diff --git a/apps/openmw/mwsound/movieaudiofactory.cpp b/apps/openmw/mwsound/movieaudiofactory.cpp index f54ab5c06..188514f85 100644 --- a/apps/openmw/mwsound/movieaudiofactory.cpp +++ b/apps/openmw/mwsound/movieaudiofactory.cpp @@ -1,5 +1,7 @@ #include "movieaudiofactory.hpp" +#include + #include #include @@ -13,7 +15,7 @@ namespace MWSound { class MovieAudioDecoder; - class MWSoundDecoderBridge : public Sound_Decoder + class MWSoundDecoderBridge final : public Sound_Decoder { public: MWSoundDecoderBridge(MWSound::MovieAudioDecoder* decoder) @@ -25,12 +27,12 @@ namespace MWSound private: MWSound::MovieAudioDecoder* mDecoder; - virtual void open(const std::string &fname); - virtual void close(); - virtual std::string getName(); - virtual void getInfo(int *samplerate, ChannelConfig *chans, SampleType *type); - virtual size_t read(char *buffer, size_t bytes); - virtual size_t getSampleOffset(); + bool open(const std::string &fname) override; + void close() override; + std::string getName() override; + bool getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) override; + size_t read(char *buffer, size_t bytes) override; + size_t getSampleOffset() override; }; class MovieAudioDecoder : public Video::MovieAudioDecoder @@ -96,9 +98,9 @@ namespace MWSound }; - void MWSoundDecoderBridge::open(const std::string &fname) + bool MWSoundDecoderBridge::open(const std::string &fname) { - throw std::runtime_error("unimplemented"); + return false; } void MWSoundDecoderBridge::close() {} @@ -107,7 +109,7 @@ namespace MWSound return mDecoder->getStreamName(); } - void MWSoundDecoderBridge::getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) + bool MWSoundDecoderBridge::getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) { *samplerate = mDecoder->getOutputSampleRate(); @@ -124,9 +126,8 @@ namespace MWSound *chans = ChannelConfig_Quad; else { - std::stringstream error; - error << "Unsupported channel layout: " << outputChannelLayout; - throw std::runtime_error(error.str()); + std::cerr<< "Unsupported channel layout: "<getOutputSampleFormat(); @@ -140,8 +141,11 @@ namespace MWSound { char str[1024]; av_get_sample_fmt_string(str, sizeof(str), outputSampleFormat); - throw std::runtime_error(std::string("Unsupported sample format: ") + str); + std::cerr<< "Unsupported sample format: "<getInfo(&mSampleRate, &chans, &type); + if(!mDecoder->getInfo(&mSampleRate, &chans, &type)) + return false; mFormat = getALFormat(chans, type); if(!mFormat) return false; @@ -948,14 +949,18 @@ std::pair OpenAL_Output::loadSound(const std::string &fname DecoderPtr decoder = mManager.getDecoder(); // Workaround: Bethesda at some point converted some of the files to mp3, but the references were kept as .wav. if(decoder->mResourceMgr->exists(fname)) - decoder->open(fname); + { + if(!decoder->open(fname)) + return std::make_pair(nullptr, 0); + } else { std::string file = fname; std::string::size_type pos = file.rfind('.'); if(pos != std::string::npos) file = file.substr(0, pos)+".mp3"; - decoder->open(file); + if(!decoder->open(file)) + return std::make_pair(nullptr, 0); } std::vector data; @@ -964,7 +969,8 @@ std::pair OpenAL_Output::loadSound(const std::string &fname ALenum format; int srate; - decoder->getInfo(&srate, &chans, &type); + if(!decoder->getInfo(&srate, &chans, &type)) + return std::make_pair(nullptr, 0); format = getALFormat(chans, type); if(!format) return std::make_pair(nullptr, 0); diff --git a/apps/openmw/mwsound/sound_decoder.hpp b/apps/openmw/mwsound/sound_decoder.hpp index 34bae87d7..57edb1393 100644 --- a/apps/openmw/mwsound/sound_decoder.hpp +++ b/apps/openmw/mwsound/sound_decoder.hpp @@ -34,11 +34,11 @@ namespace MWSound { const VFS::Manager* mResourceMgr; - virtual void open(const std::string &fname) = 0; + virtual bool open(const std::string &fname) = 0; virtual void close() = 0; virtual std::string getName() = 0; - virtual void getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) = 0; + virtual bool getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) = 0; virtual size_t read(char *buffer, size_t bytes) = 0; virtual void readAll(std::vector &output); From 06ae61479a95fbad45ff38c4ef3f62e7988c5cbb Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 8 Dec 2017 22:10:09 -0800 Subject: [PATCH 2/3] If a sound effect fails to load, substitute silence. --- apps/openmw/mwsound/openal_output.cpp | 35 ++++++++++++++++----------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/apps/openmw/mwsound/openal_output.cpp b/apps/openmw/mwsound/openal_output.cpp index 009c019e7..89475ea48 100644 --- a/apps/openmw/mwsound/openal_output.cpp +++ b/apps/openmw/mwsound/openal_output.cpp @@ -948,35 +948,42 @@ std::pair OpenAL_Output::loadSound(const std::string &fname DecoderPtr decoder = mManager.getDecoder(); // Workaround: Bethesda at some point converted some of the files to mp3, but the references were kept as .wav. + bool succeeded; if(decoder->mResourceMgr->exists(fname)) - { - if(!decoder->open(fname)) - return std::make_pair(nullptr, 0); - } + succeeded = decoder->open(fname); else { std::string file = fname; std::string::size_type pos = file.rfind('.'); if(pos != std::string::npos) file = file.substr(0, pos)+".mp3"; - if(!decoder->open(file)) - return std::make_pair(nullptr, 0); + succeeded = decoder->open(file); } std::vector data; - ChannelConfig chans; - SampleType type; ALenum format; int srate; - if(!decoder->getInfo(&srate, &chans, &type)) - return std::make_pair(nullptr, 0); - format = getALFormat(chans, type); - if(!format) return std::make_pair(nullptr, 0); - - decoder->readAll(data); + if(succeeded) + { + ChannelConfig chans; + SampleType type; + if(decoder->getInfo(&srate, &chans, &type)) + { + format = getALFormat(chans, type); + if(format) decoder->readAll(data); + } + } decoder->close(); + if(data.empty()) + { + // If we failed to get any usable audio, substitute with silence. + format = AL_FORMAT_MONO8; + srate = 8000; + data.assign(8000, -128); + } + ALint size; ALuint buf = 0; alGenBuffers(1, &buf); From 08e947319a99021eaa3d16813c97905644a71cbf Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 9 Dec 2017 11:00:56 -0800 Subject: [PATCH 3/3] Restore exception throwing to the decoder --- apps/openmw/mwsound/ffmpeg_decoder.cpp | 48 ++++++++------------- apps/openmw/mwsound/ffmpeg_decoder.hpp | 4 +- apps/openmw/mwsound/movieaudiofactory.cpp | 21 ++++----- apps/openmw/mwsound/openal_output.cpp | 52 ++++++++++++----------- apps/openmw/mwsound/sound_decoder.hpp | 4 +- 5 files changed, 56 insertions(+), 73 deletions(-) diff --git a/apps/openmw/mwsound/ffmpeg_decoder.cpp b/apps/openmw/mwsound/ffmpeg_decoder.cpp index 12ea84a42..e2d54876f 100644 --- a/apps/openmw/mwsound/ffmpeg_decoder.cpp +++ b/apps/openmw/mwsound/ffmpeg_decoder.cpp @@ -176,16 +176,16 @@ size_t FFmpeg_Decoder::readAVAudioData(void *data, size_t length) return dec; } -bool FFmpeg_Decoder::open(const std::string &fname) +void FFmpeg_Decoder::open(const std::string &fname) { close(); - try - { - mDataStream = mResourceMgr->get(fname); + mDataStream = mResourceMgr->get(fname); - if((mFormatCtx=avformat_alloc_context()) == NULL) - throw std::runtime_error("Failed to allocate context"); + if((mFormatCtx=avformat_alloc_context()) == NULL) + throw std::runtime_error("Failed to allocate context"); + try + { mFormatCtx->pb = avio_alloc_context(NULL, 0, 0, this, readPacket, writePacket, seek); if(!mFormatCtx->pb || avformat_open_input(&mFormatCtx, fname.c_str(), NULL, NULL) != 0) { @@ -250,16 +250,8 @@ bool FFmpeg_Decoder::open(const std::string &fname) mOutputChannelLayout = (*mStream)->codec->channel_layout; if(mOutputChannelLayout == 0) mOutputChannelLayout = av_get_default_channel_layout((*mStream)->codec->channels); - - return true; - } - catch(std::exception &e) - { - std::cerr<< "Could not open audio file: "<codec); mStream = NULL; @@ -273,8 +265,8 @@ bool FFmpeg_Decoder::open(const std::string &fname) mFormatCtx->pb = NULL; avformat_close_input(&mFormatCtx); + throw; } - return false; } void FFmpeg_Decoder::close() @@ -316,13 +308,10 @@ std::string FFmpeg_Decoder::getName() return mFormatCtx->filename; } -bool FFmpeg_Decoder::getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) +void FFmpeg_Decoder::getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) { if(!mStream) - { - std::cerr<< "No audio stream info" < &output) override; diff --git a/apps/openmw/mwsound/movieaudiofactory.cpp b/apps/openmw/mwsound/movieaudiofactory.cpp index 188514f85..497562516 100644 --- a/apps/openmw/mwsound/movieaudiofactory.cpp +++ b/apps/openmw/mwsound/movieaudiofactory.cpp @@ -27,10 +27,10 @@ namespace MWSound private: MWSound::MovieAudioDecoder* mDecoder; - bool open(const std::string &fname) override; + void open(const std::string &fname) override; void close() override; std::string getName() override; - bool getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) override; + void getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) override; size_t read(char *buffer, size_t bytes) override; size_t getSampleOffset() override; }; @@ -98,9 +98,9 @@ namespace MWSound }; - bool MWSoundDecoderBridge::open(const std::string &fname) + void MWSoundDecoderBridge::open(const std::string &fname) { - return false; + throw std::runtime_error("Method not implemented"); } void MWSoundDecoderBridge::close() {} @@ -109,7 +109,7 @@ namespace MWSound return mDecoder->getStreamName(); } - bool MWSoundDecoderBridge::getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) + void MWSoundDecoderBridge::getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) { *samplerate = mDecoder->getOutputSampleRate(); @@ -125,10 +125,8 @@ namespace MWSound else if (outputChannelLayout == AV_CH_LAYOUT_QUAD) *chans = ChannelConfig_Quad; else - { - std::cerr<< "Unsupported channel layout: "<getOutputSampleFormat(); if (outputSampleFormat == AV_SAMPLE_FMT_U8) @@ -141,11 +139,8 @@ namespace MWSound { char str[1024]; av_get_sample_fmt_string(str, sizeof(str), outputSampleFormat); - std::cerr<< "Unsupported sample format: "<getInfo(&mSampleRate, &chans, &type)) + try { + mDecoder->getInfo(&mSampleRate, &chans, &type); + mFormat = getALFormat(chans, type); + } + catch(std::exception &e) { + std::cerr<< "Failed to get stream info: "< OpenAL_Output::loadSound(const std::string &fname { getALError(); - DecoderPtr decoder = mManager.getDecoder(); - // Workaround: Bethesda at some point converted some of the files to mp3, but the references were kept as .wav. - bool succeeded; - if(decoder->mResourceMgr->exists(fname)) - succeeded = decoder->open(fname); - else - { - std::string file = fname; - std::string::size_type pos = file.rfind('.'); - if(pos != std::string::npos) - file = file.substr(0, pos)+".mp3"; - succeeded = decoder->open(file); - } - std::vector data; ALenum format; int srate; - if(succeeded) - { - ChannelConfig chans; - SampleType type; - if(decoder->getInfo(&srate, &chans, &type)) + try { + DecoderPtr decoder = mManager.getDecoder(); + // Workaround: Bethesda at some point converted some of the files to mp3, but the references were kept as .wav. + if(decoder->mResourceMgr->exists(fname)) + decoder->open(fname); + else { - format = getALFormat(chans, type); - if(format) decoder->readAll(data); + std::string file = fname; + std::string::size_type pos = file.rfind('.'); + if(pos != std::string::npos) + file = file.substr(0, pos)+".mp3"; + decoder->open(file); } + + ChannelConfig chans; + SampleType type; + decoder->getInfo(&srate, &chans, &type); + format = getALFormat(chans, type); + if(format) decoder->readAll(data); + } + catch(std::exception &e) { + std::cerr<< "Failed to load audio from "<close(); if(data.empty()) { diff --git a/apps/openmw/mwsound/sound_decoder.hpp b/apps/openmw/mwsound/sound_decoder.hpp index 57edb1393..34bae87d7 100644 --- a/apps/openmw/mwsound/sound_decoder.hpp +++ b/apps/openmw/mwsound/sound_decoder.hpp @@ -34,11 +34,11 @@ namespace MWSound { const VFS::Manager* mResourceMgr; - virtual bool open(const std::string &fname) = 0; + virtual void open(const std::string &fname) = 0; virtual void close() = 0; virtual std::string getName() = 0; - virtual bool getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) = 0; + virtual void getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) = 0; virtual size_t read(char *buffer, size_t bytes) = 0; virtual void readAll(std::vector &output);