mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-02 03:15:35 +00:00
Add a readAll method to the sound decoder, for potentially more efficient reading
This commit is contained in:
parent
deb473b9ae
commit
26a441f29a
7 changed files with 54 additions and 15 deletions
|
@ -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<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()
|
||||
{
|
||||
av_seek_frame(mFormatCtx, -1, 0, 0);
|
||||
|
|
|
@ -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<char> &output);
|
||||
virtual void rewind();
|
||||
|
||||
FFmpeg_Decoder();
|
||||
|
|
|
@ -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<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()
|
||||
{
|
||||
if(!mSndFile && !mMpgFile)
|
||||
|
|
|
@ -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<char> &output);
|
||||
virtual void rewind();
|
||||
|
||||
MpgSnd_Decoder();
|
||||
|
|
|
@ -442,30 +442,25 @@ ALuint OpenAL_Output::getBuffer(const std::string &fname)
|
|||
}
|
||||
throwALerror();
|
||||
|
||||
int srate;
|
||||
std::vector<char> 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<char> 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;
|
||||
|
||||
|
|
|
@ -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<char> &output);
|
||||
virtual void rewind() = 0;
|
||||
|
||||
Sound_Decoder() : mResourceMgr(Ogre::ResourceGroupManager::getSingleton())
|
||||
|
|
|
@ -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<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)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue