Add a readAll method to the sound decoder, for potentially more efficient reading

This commit is contained in:
Chris Robinson 2012-03-20 17:57:28 -07:00
parent deb473b9ae
commit 26a441f29a
7 changed files with 54 additions and 15 deletions

View file

@ -353,6 +353,18 @@ size_t FFmpeg_Decoder::read(char *buffer, size_t bytes)
return mStreams.front()->readAVAudioData(buffer, bytes); return mStreams.front()->readAVAudioData(buffer, bytes);
} }
void FFmpeg_Decoder::readAll(std::vector<char> &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() void FFmpeg_Decoder::rewind()
{ {
av_seek_frame(mFormatCtx, -1, 0, 0); av_seek_frame(mFormatCtx, -1, 0, 0);

View file

@ -39,6 +39,7 @@ namespace MWSound
virtual void getInfo(int *samplerate, ChannelConfig *chans, SampleType *type); virtual void getInfo(int *samplerate, ChannelConfig *chans, SampleType *type);
virtual size_t read(char *buffer, size_t bytes); virtual size_t read(char *buffer, size_t bytes);
virtual void readAll(std::vector<char> &output);
virtual void rewind(); virtual void rewind();
FFmpeg_Decoder(); FFmpeg_Decoder();

View file

@ -83,17 +83,16 @@ void MpgSnd_Decoder::open(const std::string &fname)
close(); close();
mDataStream = mResourceMgr.openResource(fname); mDataStream = mResourceMgr.openResource(fname);
SF_INFO info;
SF_VIRTUAL_IO streamIO = { SF_VIRTUAL_IO streamIO = {
ogresf_get_filelen, ogresf_seek, ogresf_get_filelen, ogresf_seek,
ogresf_read, ogresf_write, ogresf_tell 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(mSndFile)
{ {
if(info.channels == 1) if(mSndInfo.channels == 1)
mChanConfig = ChannelConfig_Mono; mChanConfig = ChannelConfig_Mono;
else if(info.channels == 2) else if(mSndInfo.channels == 2)
mChanConfig = ChannelConfig_Stereo; mChanConfig = ChannelConfig_Stereo;
else else
{ {
@ -101,7 +100,7 @@ void MpgSnd_Decoder::open(const std::string &fname)
mSndFile = NULL; mSndFile = NULL;
fail("Unsupported channel count in "+fname); fail("Unsupported channel count in "+fname);
} }
mSampleRate = info.samplerate; mSampleRate = mSndInfo.samplerate;
return; return;
} }
mDataStream->seek(0); mDataStream->seek(0);
@ -184,6 +183,19 @@ size_t MpgSnd_Decoder::read(char *buffer, size_t bytes)
return got; return got;
} }
void MpgSnd_Decoder::readAll(std::vector<char> &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() void MpgSnd_Decoder::rewind()
{ {
if(!mSndFile && !mMpgFile) if(!mSndFile && !mMpgFile)

View file

@ -15,6 +15,7 @@ namespace MWSound
{ {
class MpgSnd_Decoder : public Sound_Decoder class MpgSnd_Decoder : public Sound_Decoder
{ {
SF_INFO mSndInfo;
SNDFILE *mSndFile; SNDFILE *mSndFile;
mpg123_handle *mMpgFile; mpg123_handle *mMpgFile;
@ -36,6 +37,7 @@ namespace MWSound
virtual void getInfo(int *samplerate, ChannelConfig *chans, SampleType *type); virtual void getInfo(int *samplerate, ChannelConfig *chans, SampleType *type);
virtual size_t read(char *buffer, size_t bytes); virtual size_t read(char *buffer, size_t bytes);
virtual void readAll(std::vector<char> &output);
virtual void rewind(); virtual void rewind();
MpgSnd_Decoder(); MpgSnd_Decoder();

View file

@ -442,30 +442,25 @@ ALuint OpenAL_Output::getBuffer(const std::string &fname)
} }
throwALerror(); throwALerror();
int srate; std::vector<char> data;
ChannelConfig chans; ChannelConfig chans;
SampleType type; SampleType type;
ALenum format; ALenum format;
int srate;
DecoderPtr decoder = mManager.getDecoder(); DecoderPtr decoder = mManager.getDecoder();
decoder->open(fname); decoder->open(fname);
decoder->getInfo(&srate, &chans, &type); decoder->getInfo(&srate, &chans, &type);
format = getALFormat(chans, type); format = getALFormat(chans, type);
std::vector<char> data(32768); decoder->readAll(data);
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->close(); decoder->close();
alGenBuffers(1, &buf); alGenBuffers(1, &buf);
throwALerror(); throwALerror();
alBufferData(buf, format, &data[0], total, srate); alBufferData(buf, format, data.data(), data.size(), srate);
mBufferCache[fname] = buf; mBufferCache[fname] = buf;
mBufferRefs[buf] = 1; mBufferRefs[buf] = 1;

View file

@ -32,6 +32,7 @@ namespace MWSound
virtual void 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 size_t read(char *buffer, size_t bytes) = 0;
virtual void readAll(std::vector<char> &output);
virtual void rewind() = 0; virtual void rewind() = 0;
Sound_Decoder() : mResourceMgr(Ogre::ResourceGroupManager::getSingleton()) Sound_Decoder() : mResourceMgr(Ogre::ResourceGroupManager::getSingleton())

View file

@ -449,6 +449,22 @@ namespace MWSound
updateRegionSound(duration); updateRegionSound(duration);
} }
// Default readAll implementation, for decoders that can't do anything
// better
void Sound_Decoder::readAll(std::vector<char> &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) const char *getSampleTypeName(SampleType type)
{ {