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:
parent
96a79d3ff2
commit
c48a52cda3
5 changed files with 12 additions and 8 deletions
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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];
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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];
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue