Always output 16-bit samples from SmackerDecoder

This commit is contained in:
Chris Robinson 2022-10-02 08:02:28 -07:00 committed by Christoph Oelckers
parent 3b6723e6f2
commit d11e2ef1ac
3 changed files with 38 additions and 65 deletions

View file

@ -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;
} }
} }

View file

@ -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;
}; };

View file

@ -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;