From aafe817a1f84ab61196b5806dc72f39ff472f389 Mon Sep 17 00:00:00 2001 From: Christopher Snowhill Date: Fri, 7 Mar 2025 17:26:58 -0800 Subject: [PATCH] Bug Fix: Correct playback of DSD formats DSD formats were buffering incorrectly and terminating way too soon. Signed-off-by: Christopher Snowhill --- Audio/Chain/AudioChunk.m | 6 ++++-- Audio/Chain/ConverterNode.m | 2 +- Plugins/WavPack/WavPackDecoder.m | 3 ++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Audio/Chain/AudioChunk.m b/Audio/Chain/AudioChunk.m index 6bde9f93f..fc49f3b30 100644 --- a/Audio/Chain/AudioChunk.m +++ b/Audio/Chain/AudioChunk.m @@ -174,11 +174,12 @@ static const uint32_t AudioChannelConfigTable[] = { if(formatAssigned) { @autoreleasepool { const double secondsDuration = (double)(frameCount) / format.mSampleRate; + const double DSDrate = (format.mBitsPerChannel == 1) ? 8.0 : 1.0; const size_t bytesPerPacket = format.mBytesPerPacket; const size_t byteCount = bytesPerPacket * frameCount; NSData *ret = [chunkData subdataWithRange:NSMakeRange(0, byteCount)]; [chunkData replaceBytesInRange:NSMakeRange(0, byteCount) withBytes:NULL length:0]; - streamTimestamp += secondsDuration * streamTimeRatio; + streamTimestamp += secondsDuration * streamTimeRatio * DSDrate; return ret; } } @@ -211,7 +212,8 @@ static const uint32_t AudioChannelConfigTable[] = { if(formatAssigned && [chunkData length]) { const size_t bytesPerPacket = format.mBytesPerPacket; const double sampleRate = format.mSampleRate; - return (double)([chunkData length] / bytesPerPacket) / sampleRate; + const double DSDrate = (format.mBitsPerChannel == 1) ? 8.0 : 1.0; + return ((double)([chunkData length] / bytesPerPacket) / sampleRate) * DSDrate; } return 0.0; } diff --git a/Audio/Chain/ConverterNode.m b/Audio/Chain/ConverterNode.m index 94d2dabb4..e6339993c 100644 --- a/Audio/Chain/ConverterNode.m +++ b/Audio/Chain/ConverterNode.m @@ -110,7 +110,7 @@ void scale_by_volume(float *buffer, size_t count, float volume) { AudioChunk *chunk = nil; chunk = [self convert]; if(!chunk || ![chunk frameCount]) { - if([previousNode endOfStream] == YES) { + if([[previousNode buffer] isEmpty] && [previousNode endOfStream] == YES) { endOfStream = YES; break; } diff --git a/Plugins/WavPack/WavPackDecoder.m b/Plugins/WavPack/WavPackDecoder.m index afb194d7f..553d58bfb 100644 --- a/Plugins/WavPack/WavPackDecoder.m +++ b/Plugins/WavPack/WavPackDecoder.m @@ -258,7 +258,8 @@ int32_t WriteBytesProc(void *ds, void *data, int32_t bcount) { ALog(@"Unsupported sample size: %d", bitsPerSample); } - double streamTimestamp = (double)(frame) / frequency; + double DSDrate = (bitsPerSample == 1) ? 8.0 : 1.0; + double streamTimestamp = (double)(frame) / frequency * DSDrate; frame += samplesRead; [chunk setStreamTimestamp:streamTimestamp];