mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-12 07:34:50 +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)
|
size_t SndFileDecoder::read(char *buffer, size_t bytes)
|
||||||
{
|
{
|
||||||
int framesize = 2 * SndInfo.channels;
|
short *out = (short*)buffer;
|
||||||
return sf_readf_short(SndFile, (short*)buffer, bytes/framesize) * framesize;
|
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()
|
std::vector<char> SndFileDecoder::readAll()
|
||||||
|
|
Loading…
Reference in a new issue