From d11e2ef1ac9905a02c2ddbeb6179052f52242507 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 2 Oct 2022 08:02:28 -0700 Subject: [PATCH] Always output 16-bit samples from SmackerDecoder --- src/common/cutscenes/movieplayer.cpp | 69 ++++++------------- .../libsmackerdec/include/SmackerDecoder.h | 1 - .../libsmackerdec/src/SmackerDecoder.cpp | 33 +++++---- 3 files changed, 38 insertions(+), 65 deletions(-) diff --git a/src/common/cutscenes/movieplayer.cpp b/src/common/cutscenes/movieplayer.cpp index 718416008..d2283fb28 100644 --- a/src/common/cutscenes/movieplayer.cpp +++ b/src/common/cutscenes/movieplayer.cpp @@ -611,7 +611,6 @@ struct AudioData { SmackerAudioInfo inf; - std::vector samples; int nWrite = 0; int nRead = 0; }; @@ -625,7 +624,7 @@ class SmkPlayer : public MoviePlayer uint8_t palette[768]; AnimTextures animtex; TArray pFrame; - TArray audioBuffer; + TArray audioBuffer; int nFrames; bool fullscreenScale; uint64_t nFrameNs; @@ -672,10 +671,13 @@ public: if (avail >= skip) { audiooffset += skip / framesize; - adata.nRead += skip / 2; - if (adata.nRead >= adata.nWrite) - adata.nRead = adata.nWrite = 0; - avail -= skip; + if (avail > skip) + { + adata.nRead += skip / 2; + avail -= skip; + } + else + adata.nRead = adata.nWrite = avail = 0; break; } @@ -685,12 +687,11 @@ public: skip -= avail; 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 (adata.inf.bitsPerSample == 8) copy8bitSamples(read); - else copy16bitSamples(read); - avail += read; + adata.nWrite = read / 2; + avail = read; } } else if(delay < 0.0) @@ -700,18 +701,17 @@ public: 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 (adata.inf.bitsPerSample == 8) copy8bitSamples(read); - else copy16bitSamples(read); - avail += read; + adata.nWrite = read / 2; + avail = read; } // Offset the measured audio position to account for the duplicated samples. audiooffset -= dup/framesize; - char *src = (char*)&adata.samples[adata.nRead]; + char *src = (char*)&audioBuffer[adata.nRead]; char *dst = (char*)buff; for(int i=0;i < dup;++i) @@ -726,7 +726,7 @@ public: { 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 (wrote == 0) @@ -734,14 +734,13 @@ public: break; } - if (adata.inf.bitsPerSample == 8) copy8bitSamples(read); - else copy16bitSamples(read); - avail += read; + adata.nWrite = read / 2; + avail = read; } 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; if(adata.nRead == adata.nWrite) adata.nRead = adata.nWrite = 0; @@ -756,33 +755,6 @@ public: static bool StreamCallbackC(SoundStream* stream, void* buff, int len, void* userdata) { return static_cast(userdata)->StreamCallback(stream, buff, len); } - void copy8bitSamples(unsigned count) - { - for (unsigned i = 0; i < count;) - { - unsigned todo = std::min(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(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& ans, int flags_) : animSnd(std::move(ans)) { @@ -807,8 +779,7 @@ public: adata.inf = Smacker_GetAudioTrackDetails(hSMK, 0); if (adata.inf.idealBufferSize > 0) { - audioBuffer.Resize(adata.inf.idealBufferSize); - adata.samples.resize(adata.inf.idealBufferSize); + audioBuffer.Resize(adata.inf.idealBufferSize / 2); hassound = true; } } diff --git a/src/common/thirdparty/libsmackerdec/include/SmackerDecoder.h b/src/common/thirdparty/libsmackerdec/include/SmackerDecoder.h index 42cc6fc76..e9a8b1e27 100644 --- a/src/common/thirdparty/libsmackerdec/include/SmackerDecoder.h +++ b/src/common/thirdparty/libsmackerdec/include/SmackerDecoder.h @@ -64,7 +64,6 @@ struct SmackerAudioInfo { uint32_t sampleRate; uint8_t nChannels; - uint8_t bitsPerSample; uint32_t idealBufferSize; }; diff --git a/src/common/thirdparty/libsmackerdec/src/SmackerDecoder.cpp b/src/common/thirdparty/libsmackerdec/src/SmackerDecoder.cpp index cc14a85ca..57eb4bd15 100644 --- a/src/common/thirdparty/libsmackerdec/src/SmackerDecoder.cpp +++ b/src/common/thirdparty/libsmackerdec/src/SmackerDecoder.cpp @@ -449,13 +449,18 @@ bool SmackerDecoder::Open(const char *fileName) { if (frameFlag & 1) { - // skip size - file.Skip(4); - + uint32_t size = 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].buffer = new uint8_t[unpackedSize]; + + // skip size + file.Skip(size - 8); } frameFlag >>= 1; } @@ -725,6 +730,7 @@ void SmackerDecoder::GetNextFrame() } SmackerPacket pkt = std::move(framePacketData.front()); framePacketData.pop_front(); + flock.unlock(); uint32_t frameSize = pkt.size; 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}; int16_t *samples = reinterpret_cast(track.buffer); - int8_t *samples8 = reinterpret_cast(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); unpackedSize = bits.GetBits(32); + if (unpackedSize <= 4) { + Printf("SmackerDecoder::DecodeAudio() - Packet is too small\n"); + return -1; + } if (!bits.GetBit()) { // no sound data @@ -1101,7 +1103,7 @@ int SmackerDecoder::DecodeAudio(const uint8_t *dataPtr, uint32_t size, SmackerAu for (i = stereo; i >= 0; i--) pred[i] = bits.GetBits(8); for (i = 0; i <= stereo; i++) - *samples8++ = pred[i]; + *samples++ = (pred[i]-128) << 8; for (; i < unpackedSize; i++) { if (i & stereo){ if (VLC_GetSize(vlc[1])) @@ -1109,16 +1111,17 @@ int SmackerDecoder::DecodeAudio(const uint8_t *dataPtr, uint32_t size, SmackerAu else res = 0; pred[1] += (int8_t)h[1].values[res]; - *samples8++ = pred[1]; + *samples++ = (pred[1]-128) << 8; } else { if (VLC_GetSize(vlc[0])) res = VLC_GetCodeBits(bits, vlc[0]); else res = 0; pred[0] += (int8_t)h[0].values[res]; - *samples8++ = pred[0]; + *samples++ = (pred[0]-128) << 8; } } + unpackedSize *= 2; } track.bytesReadThisFrame = unpackedSize; @@ -1201,7 +1204,6 @@ SmackerAudioInfo SmackerDecoder::GetAudioTrackDetails(uint32_t trackIndex) info.sampleRate = track->sampleRate; info.nChannels = track->nChannels; - info.bitsPerSample = track->bitsPerSample; // audio buffer size in bytes 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()); track->packetData.pop_front(); + flock.unlock(); track->bytesReadThisFrame = 0;