diff --git a/apps/openmw/mwsound/ffmpeg_decoder.cpp b/apps/openmw/mwsound/ffmpeg_decoder.cpp index b8ad80926..55ccad43d 100644 --- a/apps/openmw/mwsound/ffmpeg_decoder.cpp +++ b/apps/openmw/mwsound/ffmpeg_decoder.cpp @@ -353,6 +353,18 @@ size_t FFmpeg_Decoder::read(char *buffer, size_t bytes) return mStreams.front()->readAVAudioData(buffer, bytes); } +void FFmpeg_Decoder::readAll(std::vector &output) +{ + if(mStreams.empty()) + fail("No audio streams"); + MyStream *stream = mStreams.front(); + char *inbuf; + size_t got; + + while((inbuf=(char*)stream->getAVAudioData(&got)) != NULL && got > 0) + output.insert(output.end(), inbuf, inbuf+got); +} + void FFmpeg_Decoder::rewind() { av_seek_frame(mFormatCtx, -1, 0, 0); diff --git a/apps/openmw/mwsound/ffmpeg_decoder.hpp b/apps/openmw/mwsound/ffmpeg_decoder.hpp index 9211bcc0d..ae71c0052 100644 --- a/apps/openmw/mwsound/ffmpeg_decoder.hpp +++ b/apps/openmw/mwsound/ffmpeg_decoder.hpp @@ -39,6 +39,7 @@ namespace MWSound virtual void getInfo(int *samplerate, ChannelConfig *chans, SampleType *type); virtual size_t read(char *buffer, size_t bytes); + virtual void readAll(std::vector &output); virtual void rewind(); FFmpeg_Decoder(); diff --git a/apps/openmw/mwsound/mpgsnd_decoder.cpp b/apps/openmw/mwsound/mpgsnd_decoder.cpp index f9bef9774..f576833a8 100644 --- a/apps/openmw/mwsound/mpgsnd_decoder.cpp +++ b/apps/openmw/mwsound/mpgsnd_decoder.cpp @@ -83,17 +83,16 @@ void MpgSnd_Decoder::open(const std::string &fname) close(); mDataStream = mResourceMgr.openResource(fname); - SF_INFO info; SF_VIRTUAL_IO streamIO = { ogresf_get_filelen, ogresf_seek, ogresf_read, ogresf_write, ogresf_tell }; - mSndFile = sf_open_virtual(&streamIO, SFM_READ, &info, this); + mSndFile = sf_open_virtual(&streamIO, SFM_READ, &mSndInfo, this); if(mSndFile) { - if(info.channels == 1) + if(mSndInfo.channels == 1) mChanConfig = ChannelConfig_Mono; - else if(info.channels == 2) + else if(mSndInfo.channels == 2) mChanConfig = ChannelConfig_Stereo; else { @@ -101,7 +100,7 @@ void MpgSnd_Decoder::open(const std::string &fname) mSndFile = NULL; fail("Unsupported channel count in "+fname); } - mSampleRate = info.samplerate; + mSampleRate = mSndInfo.samplerate; return; } mDataStream->seek(0); @@ -184,6 +183,19 @@ size_t MpgSnd_Decoder::read(char *buffer, size_t bytes) return got; } +void MpgSnd_Decoder::readAll(std::vector &output) +{ + if(mSndFile && mSndInfo.frames > 0) + { + size_t pos = output.size(); + output.resize(pos + mSndInfo.frames*mSndInfo.channels*2); + sf_readf_short(mSndFile, (short*)(output.data()+pos), mSndInfo.frames); + return; + } + // Fallback in case we don't know the total already + Sound_Decoder::readAll(output); +} + void MpgSnd_Decoder::rewind() { if(!mSndFile && !mMpgFile) diff --git a/apps/openmw/mwsound/mpgsnd_decoder.hpp b/apps/openmw/mwsound/mpgsnd_decoder.hpp index 35c753ec8..1d9e9d5e2 100644 --- a/apps/openmw/mwsound/mpgsnd_decoder.hpp +++ b/apps/openmw/mwsound/mpgsnd_decoder.hpp @@ -15,6 +15,7 @@ namespace MWSound { class MpgSnd_Decoder : public Sound_Decoder { + SF_INFO mSndInfo; SNDFILE *mSndFile; mpg123_handle *mMpgFile; @@ -36,6 +37,7 @@ namespace MWSound virtual void getInfo(int *samplerate, ChannelConfig *chans, SampleType *type); virtual size_t read(char *buffer, size_t bytes); + virtual void readAll(std::vector &output); virtual void rewind(); MpgSnd_Decoder(); diff --git a/apps/openmw/mwsound/openal_output.cpp b/apps/openmw/mwsound/openal_output.cpp index 7768119b6..1efb70db4 100644 --- a/apps/openmw/mwsound/openal_output.cpp +++ b/apps/openmw/mwsound/openal_output.cpp @@ -442,30 +442,25 @@ ALuint OpenAL_Output::getBuffer(const std::string &fname) } throwALerror(); - int srate; + std::vector data; ChannelConfig chans; SampleType type; ALenum format; + int srate; DecoderPtr decoder = mManager.getDecoder(); decoder->open(fname); + decoder->getInfo(&srate, &chans, &type); format = getALFormat(chans, type); - std::vector data(32768); - size_t got, total = 0; - while((got=decoder->read(&data[total], data.size()-total)) > 0) - { - total += got; - data.resize(total*2); - } - data.resize(total); + decoder->readAll(data); decoder->close(); alGenBuffers(1, &buf); throwALerror(); - alBufferData(buf, format, &data[0], total, srate); + alBufferData(buf, format, data.data(), data.size(), srate); mBufferCache[fname] = buf; mBufferRefs[buf] = 1; diff --git a/apps/openmw/mwsound/sound_decoder.hpp b/apps/openmw/mwsound/sound_decoder.hpp index 858cc6353..e076c7b56 100644 --- a/apps/openmw/mwsound/sound_decoder.hpp +++ b/apps/openmw/mwsound/sound_decoder.hpp @@ -32,6 +32,7 @@ namespace MWSound 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); virtual void rewind() = 0; Sound_Decoder() : mResourceMgr(Ogre::ResourceGroupManager::getSingleton()) diff --git a/apps/openmw/mwsound/soundmanager.cpp b/apps/openmw/mwsound/soundmanager.cpp index ec5ab310b..ded94aee3 100644 --- a/apps/openmw/mwsound/soundmanager.cpp +++ b/apps/openmw/mwsound/soundmanager.cpp @@ -449,6 +449,22 @@ namespace MWSound updateRegionSound(duration); } + // Default readAll implementation, for decoders that can't do anything + // better + void Sound_Decoder::readAll(std::vector &output) + { + size_t total = output.size(); + size_t got; + + output.resize(total+32768); + while((got=read(&output[total], output.size()-total)) > 0) + { + total += got; + output.resize(total*2); + } + output.resize(total); + } + const char *getSampleTypeName(SampleType type) {