mirror of
https://github.com/ZDoom/qzdoom.git
synced 2025-02-09 01:01:05 +00:00
Always output 16-bit samples from SmackerDecoder
This commit is contained in:
parent
3b6723e6f2
commit
d11e2ef1ac
3 changed files with 38 additions and 65 deletions
|
@ -611,7 +611,6 @@ struct AudioData
|
||||||
{
|
{
|
||||||
SmackerAudioInfo inf;
|
SmackerAudioInfo inf;
|
||||||
|
|
||||||
std::vector<uint16_t> samples;
|
|
||||||
int nWrite = 0;
|
int nWrite = 0;
|
||||||
int nRead = 0;
|
int nRead = 0;
|
||||||
};
|
};
|
||||||
|
@ -625,7 +624,7 @@ class SmkPlayer : public MoviePlayer
|
||||||
uint8_t palette[768];
|
uint8_t palette[768];
|
||||||
AnimTextures animtex;
|
AnimTextures animtex;
|
||||||
TArray<uint8_t> pFrame;
|
TArray<uint8_t> pFrame;
|
||||||
TArray<uint8_t> audioBuffer;
|
TArray<int16_t> audioBuffer;
|
||||||
int nFrames;
|
int nFrames;
|
||||||
bool fullscreenScale;
|
bool fullscreenScale;
|
||||||
uint64_t nFrameNs;
|
uint64_t nFrameNs;
|
||||||
|
@ -672,10 +671,13 @@ public:
|
||||||
if (avail >= skip)
|
if (avail >= skip)
|
||||||
{
|
{
|
||||||
audiooffset += skip / framesize;
|
audiooffset += skip / framesize;
|
||||||
adata.nRead += skip / 2;
|
if (avail > skip)
|
||||||
if (adata.nRead >= adata.nWrite)
|
{
|
||||||
adata.nRead = adata.nWrite = 0;
|
adata.nRead += skip / 2;
|
||||||
avail -= skip;
|
avail -= skip;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
adata.nRead = adata.nWrite = avail = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -685,12 +687,11 @@ public:
|
||||||
skip -= avail;
|
skip -= avail;
|
||||||
avail = 0;
|
avail = 0;
|
||||||
|
|
||||||
auto read = Smacker_GetAudioData(hSMK, 0, (int16_t*)audioBuffer.Data());
|
auto read = Smacker_GetAudioData(hSMK, 0, audioBuffer.Data());
|
||||||
if (read == 0) break;
|
if (read == 0) break;
|
||||||
|
|
||||||
if (adata.inf.bitsPerSample == 8) copy8bitSamples(read);
|
adata.nWrite = read / 2;
|
||||||
else copy16bitSamples(read);
|
avail = read;
|
||||||
avail += read;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(delay < 0.0)
|
else if(delay < 0.0)
|
||||||
|
@ -700,18 +701,17 @@ public:
|
||||||
|
|
||||||
if(avail == 0)
|
if(avail == 0)
|
||||||
{
|
{
|
||||||
auto read = Smacker_GetAudioData(hSMK, 0, (int16_t*)audioBuffer.Data());
|
auto read = Smacker_GetAudioData(hSMK, 0, audioBuffer.Data());
|
||||||
if (read == 0) return false;
|
if (read == 0) return false;
|
||||||
|
|
||||||
if (adata.inf.bitsPerSample == 8) copy8bitSamples(read);
|
adata.nWrite = read / 2;
|
||||||
else copy16bitSamples(read);
|
avail = read;
|
||||||
avail += read;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Offset the measured audio position to account for the duplicated samples.
|
// Offset the measured audio position to account for the duplicated samples.
|
||||||
audiooffset -= dup/framesize;
|
audiooffset -= dup/framesize;
|
||||||
|
|
||||||
char *src = (char*)&adata.samples[adata.nRead];
|
char *src = (char*)&audioBuffer[adata.nRead];
|
||||||
char *dst = (char*)buff;
|
char *dst = (char*)buff;
|
||||||
|
|
||||||
for(int i=0;i < dup;++i)
|
for(int i=0;i < dup;++i)
|
||||||
|
@ -726,7 +726,7 @@ public:
|
||||||
{
|
{
|
||||||
if (avail == 0)
|
if (avail == 0)
|
||||||
{
|
{
|
||||||
auto read = Smacker_GetAudioData(hSMK, 0, (int16_t*)audioBuffer.Data());
|
auto read = Smacker_GetAudioData(hSMK, 0, audioBuffer.Data());
|
||||||
if (read == 0)
|
if (read == 0)
|
||||||
{
|
{
|
||||||
if (wrote == 0)
|
if (wrote == 0)
|
||||||
|
@ -734,14 +734,13 @@ public:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (adata.inf.bitsPerSample == 8) copy8bitSamples(read);
|
adata.nWrite = read / 2;
|
||||||
else copy16bitSamples(read);
|
avail = read;
|
||||||
avail += read;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int todo = std::min(len-wrote, avail);
|
int todo = std::min(len-wrote, avail);
|
||||||
|
|
||||||
memcpy((char*)buff+wrote, &adata.samples[adata.nRead], todo);
|
memcpy((char*)buff+wrote, &audioBuffer[adata.nRead], todo);
|
||||||
adata.nRead += todo / 2;
|
adata.nRead += todo / 2;
|
||||||
if(adata.nRead == adata.nWrite)
|
if(adata.nRead == adata.nWrite)
|
||||||
adata.nRead = adata.nWrite = 0;
|
adata.nRead = adata.nWrite = 0;
|
||||||
|
@ -756,33 +755,6 @@ public:
|
||||||
static bool StreamCallbackC(SoundStream* stream, void* buff, int len, void* userdata)
|
static bool StreamCallbackC(SoundStream* stream, void* buff, int len, void* userdata)
|
||||||
{ return static_cast<SmkPlayer*>(userdata)->StreamCallback(stream, buff, len); }
|
{ return static_cast<SmkPlayer*>(userdata)->StreamCallback(stream, buff, len); }
|
||||||
|
|
||||||
void copy8bitSamples(unsigned count)
|
|
||||||
{
|
|
||||||
for (unsigned i = 0; i < count;)
|
|
||||||
{
|
|
||||||
unsigned todo = std::min<unsigned>(count-i, std::size(adata.samples)-adata.nWrite);
|
|
||||||
for (unsigned j = 0;j < todo;++j)
|
|
||||||
adata.samples[adata.nWrite+j] = (audioBuffer[i+j] - 128) << 8;
|
|
||||||
adata.nWrite += todo;
|
|
||||||
if (adata.nWrite >= (int)std::size(adata.samples)) adata.nWrite = 0;
|
|
||||||
i += todo;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void copy16bitSamples(unsigned count)
|
|
||||||
{
|
|
||||||
auto ptr = (uint16_t*)audioBuffer.Data();
|
|
||||||
count /= 2;
|
|
||||||
for (unsigned i = 0; i < count;)
|
|
||||||
{
|
|
||||||
unsigned todo = std::min<unsigned>(count-i, std::size(adata.samples)-adata.nWrite);
|
|
||||||
memcpy(&adata.samples[adata.nWrite], ptr, todo*2);
|
|
||||||
adata.nWrite += todo;
|
|
||||||
if (adata.nWrite >= (int)std::size(adata.samples)) adata.nWrite = 0;
|
|
||||||
i += todo;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
SmkPlayer(const char *fn, TArray<int>& ans, int flags_) : animSnd(std::move(ans))
|
SmkPlayer(const char *fn, TArray<int>& ans, int flags_) : animSnd(std::move(ans))
|
||||||
{
|
{
|
||||||
|
@ -807,8 +779,7 @@ public:
|
||||||
adata.inf = Smacker_GetAudioTrackDetails(hSMK, 0);
|
adata.inf = Smacker_GetAudioTrackDetails(hSMK, 0);
|
||||||
if (adata.inf.idealBufferSize > 0)
|
if (adata.inf.idealBufferSize > 0)
|
||||||
{
|
{
|
||||||
audioBuffer.Resize(adata.inf.idealBufferSize);
|
audioBuffer.Resize(adata.inf.idealBufferSize / 2);
|
||||||
adata.samples.resize(adata.inf.idealBufferSize);
|
|
||||||
hassound = true;
|
hassound = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,7 +64,6 @@ struct SmackerAudioInfo
|
||||||
{
|
{
|
||||||
uint32_t sampleRate;
|
uint32_t sampleRate;
|
||||||
uint8_t nChannels;
|
uint8_t nChannels;
|
||||||
uint8_t bitsPerSample;
|
|
||||||
|
|
||||||
uint32_t idealBufferSize;
|
uint32_t idealBufferSize;
|
||||||
};
|
};
|
||||||
|
|
|
@ -449,13 +449,18 @@ bool SmackerDecoder::Open(const char *fileName)
|
||||||
{
|
{
|
||||||
if (frameFlag & 1)
|
if (frameFlag & 1)
|
||||||
{
|
{
|
||||||
// skip size
|
uint32_t size = file.ReadUint32LE();
|
||||||
file.Skip(4);
|
|
||||||
|
|
||||||
uint32_t unpackedSize = file.ReadUint32LE();
|
uint32_t unpackedSize = file.ReadUint32LE();
|
||||||
|
|
||||||
|
// If the track isn't 16-bit, double the buffer size for converting 8-bit to 16-bit.
|
||||||
|
if (!(audioTracks[i].flags & SMK_AUD_16BITS))
|
||||||
|
unpackedSize *= 2;
|
||||||
|
|
||||||
audioTracks[i].bufferSize = unpackedSize;
|
audioTracks[i].bufferSize = unpackedSize;
|
||||||
audioTracks[i].buffer = new uint8_t[unpackedSize];
|
audioTracks[i].buffer = new uint8_t[unpackedSize];
|
||||||
|
|
||||||
|
// skip size
|
||||||
|
file.Skip(size - 8);
|
||||||
}
|
}
|
||||||
frameFlag >>= 1;
|
frameFlag >>= 1;
|
||||||
}
|
}
|
||||||
|
@ -725,6 +730,7 @@ void SmackerDecoder::GetNextFrame()
|
||||||
}
|
}
|
||||||
SmackerPacket pkt = std::move(framePacketData.front());
|
SmackerPacket pkt = std::move(framePacketData.front());
|
||||||
framePacketData.pop_front();
|
framePacketData.pop_front();
|
||||||
|
flock.unlock();
|
||||||
|
|
||||||
uint32_t frameSize = pkt.size;
|
uint32_t frameSize = pkt.size;
|
||||||
uint8_t frameFlag = frameFlags[currentFrame];
|
uint8_t frameFlag = frameFlags[currentFrame];
|
||||||
|
@ -1017,18 +1023,14 @@ int SmackerDecoder::DecodeAudio(const uint8_t *dataPtr, uint32_t size, SmackerAu
|
||||||
int pred[2] = {0, 0};
|
int pred[2] = {0, 0};
|
||||||
|
|
||||||
int16_t *samples = reinterpret_cast<int16_t*>(track.buffer);
|
int16_t *samples = reinterpret_cast<int16_t*>(track.buffer);
|
||||||
int8_t *samples8 = reinterpret_cast<int8_t*>(track.buffer);
|
|
||||||
|
|
||||||
int buf_size = track.bufferSize;
|
|
||||||
|
|
||||||
if (buf_size <= 4) {
|
|
||||||
Printf("SmackerDecoder::DecodeAudio() - Packet is too small\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
SmackerCommon::BitReader bits(dataPtr, size);
|
SmackerCommon::BitReader bits(dataPtr, size);
|
||||||
|
|
||||||
unpackedSize = bits.GetBits(32);
|
unpackedSize = bits.GetBits(32);
|
||||||
|
if (unpackedSize <= 4) {
|
||||||
|
Printf("SmackerDecoder::DecodeAudio() - Packet is too small\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (!bits.GetBit()) {
|
if (!bits.GetBit()) {
|
||||||
// no sound data
|
// no sound data
|
||||||
|
@ -1101,7 +1103,7 @@ int SmackerDecoder::DecodeAudio(const uint8_t *dataPtr, uint32_t size, SmackerAu
|
||||||
for (i = stereo; i >= 0; i--)
|
for (i = stereo; i >= 0; i--)
|
||||||
pred[i] = bits.GetBits(8);
|
pred[i] = bits.GetBits(8);
|
||||||
for (i = 0; i <= stereo; i++)
|
for (i = 0; i <= stereo; i++)
|
||||||
*samples8++ = pred[i];
|
*samples++ = (pred[i]-128) << 8;
|
||||||
for (; i < unpackedSize; i++) {
|
for (; i < unpackedSize; i++) {
|
||||||
if (i & stereo){
|
if (i & stereo){
|
||||||
if (VLC_GetSize(vlc[1]))
|
if (VLC_GetSize(vlc[1]))
|
||||||
|
@ -1109,16 +1111,17 @@ int SmackerDecoder::DecodeAudio(const uint8_t *dataPtr, uint32_t size, SmackerAu
|
||||||
else
|
else
|
||||||
res = 0;
|
res = 0;
|
||||||
pred[1] += (int8_t)h[1].values[res];
|
pred[1] += (int8_t)h[1].values[res];
|
||||||
*samples8++ = pred[1];
|
*samples++ = (pred[1]-128) << 8;
|
||||||
} else {
|
} else {
|
||||||
if (VLC_GetSize(vlc[0]))
|
if (VLC_GetSize(vlc[0]))
|
||||||
res = VLC_GetCodeBits(bits, vlc[0]);
|
res = VLC_GetCodeBits(bits, vlc[0]);
|
||||||
else
|
else
|
||||||
res = 0;
|
res = 0;
|
||||||
pred[0] += (int8_t)h[0].values[res];
|
pred[0] += (int8_t)h[0].values[res];
|
||||||
*samples8++ = pred[0];
|
*samples++ = (pred[0]-128) << 8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
unpackedSize *= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
track.bytesReadThisFrame = unpackedSize;
|
track.bytesReadThisFrame = unpackedSize;
|
||||||
|
@ -1201,7 +1204,6 @@ SmackerAudioInfo SmackerDecoder::GetAudioTrackDetails(uint32_t trackIndex)
|
||||||
|
|
||||||
info.sampleRate = track->sampleRate;
|
info.sampleRate = track->sampleRate;
|
||||||
info.nChannels = track->nChannels;
|
info.nChannels = track->nChannels;
|
||||||
info.bitsPerSample = track->bitsPerSample;
|
|
||||||
|
|
||||||
// audio buffer size in bytes
|
// audio buffer size in bytes
|
||||||
info.idealBufferSize = track->bufferSize;
|
info.idealBufferSize = track->bufferSize;
|
||||||
|
@ -1228,6 +1230,7 @@ uint32_t SmackerDecoder::GetAudioData(uint32_t trackIndex, int16_t *audioBuffer)
|
||||||
}
|
}
|
||||||
SmackerPacket pkt = std::move(track->packetData.front());
|
SmackerPacket pkt = std::move(track->packetData.front());
|
||||||
track->packetData.pop_front();
|
track->packetData.pop_front();
|
||||||
|
flock.unlock();
|
||||||
|
|
||||||
track->bytesReadThisFrame = 0;
|
track->bytesReadThisFrame = 0;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue