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;
std::vector<uint16_t> samples;
int nWrite = 0;
int nRead = 0;
};
@ -625,7 +624,7 @@ class SmkPlayer : public MoviePlayer
uint8_t palette[768];
AnimTextures animtex;
TArray<uint8_t> pFrame;
TArray<uint8_t> audioBuffer;
TArray<int16_t> audioBuffer;
int nFrames;
bool fullscreenScale;
uint64_t nFrameNs;
@ -672,10 +671,13 @@ public:
if (avail >= skip)
{
audiooffset += skip / framesize;
if (avail > skip)
{
adata.nRead += skip / 2;
if (adata.nRead >= adata.nWrite)
adata.nRead = adata.nWrite = 0;
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<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))
{
@ -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;
}
}

View file

@ -64,7 +64,6 @@ struct SmackerAudioInfo
{
uint32_t sampleRate;
uint8_t nChannels;
uint8_t bitsPerSample;
uint32_t idealBufferSize;
};

View file

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