forked from teamnwah/openmw-tes3coop
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);
|
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);
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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())
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue