Bug Fixes: Fix monotonically increasing timestamps

Fixes timestamps in several cases where they were being processed
incorrectly, which was causing some chunked audio files to mis-report
timestamps into the past or the future, which caused the seekbar to jump
around in an unpredictable way.

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This commit is contained in:
Christopher Snowhill 2025-02-13 03:26:59 -08:00
parent 96a79d3ff2
commit c48a52cda3
5 changed files with 12 additions and 8 deletions

View file

@ -173,12 +173,12 @@ static const uint32_t AudioChannelConfigTable[] = {
- (NSData *)removeSamples:(size_t)frameCount { - (NSData *)removeSamples:(size_t)frameCount {
if(formatAssigned) { if(formatAssigned) {
@autoreleasepool { @autoreleasepool {
const double framesDuration = (double)(frameCount) / format.mSampleRate; const double secondsDuration = (double)(frameCount) / format.mSampleRate;
const size_t bytesPerPacket = format.mBytesPerPacket; const size_t bytesPerPacket = format.mBytesPerPacket;
const size_t byteCount = bytesPerPacket * frameCount; const size_t byteCount = bytesPerPacket * frameCount;
NSData *ret = [chunkData subdataWithRange:NSMakeRange(0, byteCount)]; NSData *ret = [chunkData subdataWithRange:NSMakeRange(0, byteCount)];
[chunkData replaceBytesInRange:NSMakeRange(0, byteCount) withBytes:NULL length:0]; [chunkData replaceBytesInRange:NSMakeRange(0, byteCount) withBytes:NULL length:0];
streamTimestamp += framesDuration * streamTimeRatio; streamTimestamp += secondsDuration * streamTimeRatio;
return ret; return ret;
} }
} }

View file

@ -495,12 +495,13 @@ static void convert_be_to_le(uint8_t *buffer, size_t bitsPerSample, size_t bytes
inRemover = NO; inRemover = NO;
return chunk; return chunk;
} }
double streamTimestamp = [chunk streamTimestamp];
NSData *removedData = [chunk removeSamples:maxFrameCount]; NSData *removedData = [chunk removeSamples:maxFrameCount];
AudioChunk *ret = [[AudioChunk alloc] init]; AudioChunk *ret = [[AudioChunk alloc] init];
[ret setFormat:[chunk format]]; [ret setFormat:[chunk format]];
[ret setChannelConfig:[chunk channelConfig]]; [ret setChannelConfig:[chunk channelConfig]];
[ret setLossless:[chunk lossless]]; [ret setLossless:[chunk lossless]];
[ret setStreamTimestamp:[chunk streamTimestamp]]; [ret setStreamTimestamp:streamTimestamp];
[ret setStreamTimeRatio:[chunk streamTimeRatio]]; [ret setStreamTimeRatio:[chunk streamTimeRatio]];
[ret assignData:removedData]; [ret assignData:removedData];
listDuration -= [ret duration]; listDuration -= [ret duration];
@ -535,12 +536,13 @@ static void convert_be_to_le(uint8_t *buffer, size_t bitsPerSample, size_t bytes
inRemover = NO; inRemover = NO;
return [self convertChunk:chunk]; return [self convertChunk:chunk];
} }
double streamTimestamp = [chunk streamTimestamp];
NSData *removedData = [chunk removeSamples:maxFrameCount]; NSData *removedData = [chunk removeSamples:maxFrameCount];
AudioChunk *ret = [[AudioChunk alloc] init]; AudioChunk *ret = [[AudioChunk alloc] init];
[ret setFormat:[chunk format]]; [ret setFormat:[chunk format]];
[ret setChannelConfig:[chunk channelConfig]]; [ret setChannelConfig:[chunk channelConfig]];
[ret setLossless:[chunk lossless]]; [ret setLossless:[chunk lossless]];
[ret setStreamTimestamp:[chunk streamTimestamp]]; [ret setStreamTimestamp:streamTimestamp];
[ret setStreamTimeRatio:[chunk streamTimeRatio]]; [ret setStreamTimeRatio:[chunk streamTimeRatio]];
[ret assignData:removedData]; [ret assignData:removedData];
listDuration -= [ret duration]; listDuration -= [ret duration];

View file

@ -137,7 +137,10 @@ void scale_by_volume(float *buffer, size_t count, float volume) {
if(inpOffset == inpSize) { if(inpOffset == inpSize) {
streamTimestamp = 0.0; streamTimestamp = 0.0;
streamTimeRatio = 1.0; streamTimeRatio = 1.0;
[self peekTimestamp:&streamTimestamp timeRatio:&streamTimeRatio]; if(![self peekTimestamp:&streamTimestamp timeRatio:&streamTimeRatio]) {
convertEntered = NO;
return nil;
}
} }
while(inpOffset == inpSize) { while(inpOffset == inpSize) {

View file

@ -63,7 +63,7 @@
double delta = seconds - amountPlayed; double delta = seconds - amountPlayed;
if(delta > 0.0 && delta < 5.0) { if(delta > 0.0 && delta < 5.0) {
[self incrementAmountPlayed:delta]; [self incrementAmountPlayed:delta];
} else { } else if(delta) {
amountPlayed = seconds; amountPlayed = seconds;
} }
} }

View file

@ -67,6 +67,7 @@ static void *kOutputCoreAudioContext = &kOutputCoreAudioContext;
if(!chunkRemain) { if(!chunkRemain) {
chunk = [outputController readChunk:amountToRead]; chunk = [outputController readChunk:amountToRead];
streamTimestamp = [chunk streamTimestamp];
} else { } else {
chunk = chunkRemain; chunk = chunkRemain;
chunkRemain = nil; chunkRemain = nil;
@ -77,8 +78,6 @@ static void *kOutputCoreAudioContext = &kOutputCoreAudioContext;
config = [chunk channelConfig]; config = [chunk channelConfig];
double chunkDuration = 0; double chunkDuration = 0;
streamTimestamp = [chunk streamTimestamp] + [chunk durationRatioed];
if(frameCount) { if(frameCount) {
chunkDuration = [chunk duration]; chunkDuration = [chunk duration];