mirror of
https://github.com/ZDoom/qzdoom-gpl.git
synced 2024-12-12 05:02:11 +00:00
Work around a libsndfile bug related to converting float samples to shorts
Do the conversion ourselves to ensure it's properly clamped.
This commit is contained in:
parent
1a40c95f84
commit
a16f9d061c
1 changed files with 24 additions and 2 deletions
|
@ -74,8 +74,30 @@ void SndFileDecoder::getInfo(int *samplerate, ChannelConfig *chans, SampleType *
|
|||
|
||||
size_t SndFileDecoder::read(char *buffer, size_t bytes)
|
||||
{
|
||||
int framesize = 2 * SndInfo.channels;
|
||||
return sf_readf_short(SndFile, (short*)buffer, bytes/framesize) * framesize;
|
||||
short *out = (short*)buffer;
|
||||
size_t frames = bytes / SndInfo.channels / 2;
|
||||
size_t total = 0;
|
||||
|
||||
// It seems libsndfile has a bug with converting float samples from Vorbis
|
||||
// to the 16-bit shorts we use, which causes some PCM samples to overflow
|
||||
// and wrap, creating static. So instead, read the samples as floats and
|
||||
// convert to short ourselves.
|
||||
// Use a loop to convert a handful of samples at a time, avoiding a heap
|
||||
// allocation for temporary storage. 64 at a time works, though maybe it
|
||||
// could be more.
|
||||
while(total < frames)
|
||||
{
|
||||
size_t todo = std::min<size_t>(frames-total, 64/SndInfo.channels);
|
||||
float tmp[64];
|
||||
|
||||
size_t got = sf_readf_float(SndFile, tmp, todo);
|
||||
if(got < todo) frames = total + got;
|
||||
|
||||
for(size_t i = 0;i < got*SndInfo.channels;i++)
|
||||
*out++ = (short)((std::min)((std::max)(tmp[i] * 32767.f, -32768.f), 32767.f));
|
||||
total += got;
|
||||
}
|
||||
return total * SndInfo.channels * 2;
|
||||
}
|
||||
|
||||
std::vector<char> SndFileDecoder::readAll()
|
||||
|
|
Loading…
Reference in a new issue