Bug Fix: Attempt to make seeking more performant

Seeking should clear the buffers completely now, and will be nearly
instant, depending on how fast the input can decode.

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This commit is contained in:
Christopher Snowhill 2025-02-25 18:12:17 -08:00
parent 53291b570d
commit 4ed4ea906b
10 changed files with 42 additions and 83 deletions

View file

@ -25,7 +25,6 @@
BufferChain *bufferChain; BufferChain *bufferChain;
OutputNode *output; OutputNode *output;
BOOL muted;
double volume; double volume;
double pitch; double pitch;
double tempo; double tempo;
@ -77,9 +76,6 @@
- (double)volumeUp:(double)amount; - (double)volumeUp:(double)amount;
- (double)volumeDown:(double)amount; - (double)volumeDown:(double)amount;
- (void)mute;
- (void)unmute;
- (double)amountPlayed; - (double)amountPlayed;
- (double)amountPlayedInterval; - (double)amountPlayedInterval;

View file

@ -78,9 +78,6 @@
output = [[OutputNode alloc] initWithController:self previous:nil]; output = [[OutputNode alloc] initWithController:self previous:nil];
} }
[output setup]; [output setup];
if(muted) {
[output mute];
}
@synchronized(chainQueue) { @synchronized(chainQueue) {
for(id anObject in chainQueue) { for(id anObject in chainQueue) {
[anObject setShouldContinue:NO]; [anObject setShouldContinue:NO];
@ -179,10 +176,6 @@
[output resume]; [output resume];
[self setPlaybackStatus:CogStatusPlaying waitUntilDone:YES]; [self setPlaybackStatus:CogStatusPlaying waitUntilDone:YES];
if(muted) {
[self unmute];
}
} }
- (void)seekToTimeBG:(NSNumber *)time { - (void)seekToTimeBG:(NSNumber *)time {
@ -190,7 +183,6 @@
} }
- (void)seekToTime:(double)time { - (void)seekToTime:(double)time {
[self mute];
if(endOfInputReached) { if(endOfInputReached) {
// This is a dirty hack in case the playback has finished with the track // This is a dirty hack in case the playback has finished with the track
// that the user thinks they're seeking into // that the user thinks they're seeking into
@ -225,20 +217,6 @@
return volume; return volume;
} }
- (void)mute {
if(!muted) {
[output mute];
muted = YES;
}
}
- (void)unmute {
if(muted) {
[output unmute];
muted = NO;
}
}
// This is called by the delegate DURING a requestNextStream request. // This is called by the delegate DURING a requestNextStream request.
- (void)setNextStream:(NSURL *)url { - (void)setNextStream:(NSURL *)url {
[self setNextStream:url withUserInfo:nil withRGInfo:nil]; [self setNextStream:url withUserInfo:nil withRGInfo:nil];

View file

@ -230,7 +230,6 @@
AudioPlayer * audioPlayer = controller; AudioPlayer * audioPlayer = controller;
OutputNode *outputNode = [audioPlayer output]; OutputNode *outputNode = [audioPlayer output];
[audioPlayer mute];
[inputNode seek:frame]; [inputNode seek:frame];
} }

View file

@ -160,30 +160,11 @@ static void *kInputNodeContext = &kInputNodeContext;
while([self shouldContinue] == YES && [self endOfStream] == NO) { while([self shouldContinue] == YES && [self endOfStream] == NO) {
if(shouldSeek == YES) { if(shouldSeek == YES) {
BufferChain *bufferChain = controller; BufferChain *bufferChain = controller;
AudioPlayer *audioPlayer = [controller controller]; AudioPlayer *audioPlayer = [bufferChain controller];
[audioPlayer mute];
OutputNode *outputNode = [audioPlayer output]; OutputNode *outputNode = [audioPlayer output];
[outputNode resetBuffer];
ConverterNode *converter = [bufferChain converter];
DSPRubberbandNode *rubberband = [bufferChain rubberband];
DSPFSurroundNode *fsurround = [bufferChain fsurround];
DSPEqualizerNode *equalizer = [bufferChain equalizer];
DSPHRTFNode *hrtf = [bufferChain hrtf];
DSPDownmixNode *downmix = [bufferChain downmix];
VisualizationNode *visualization = [bufferChain visualization];
DLog(@"SEEKING! Resetting Buffer"); DLog(@"SEEKING! Resetting Buffer");
[outputNode resetBackwards];
// This resets the converter's buffer
[self resetBuffer];
[converter resetBuffer];
[converter inputFormatDidChange:[bufferChain inputFormat] inputConfig:[bufferChain inputConfig]];
[rubberband resetBuffer];
[fsurround resetBuffer];
[equalizer resetBuffer];
[hrtf resetBuffer];
[downmix resetBuffer];
[visualization resetBuffer];
DLog(@"Reset buffer!"); DLog(@"Reset buffer!");
@ -199,8 +180,6 @@ static void *kInputNodeContext = &kInputNodeContext;
if(seekError) { if(seekError) {
[controller setError:YES]; [controller setError:YES];
} }
[audioPlayer unmute];
} }
AudioChunk *chunk; AudioChunk *chunk;
@ -214,6 +193,11 @@ static void *kInputNodeContext = &kInputNodeContext;
chunk = nil; chunk = nil;
} }
} else { } else {
if(chunk) {
@autoreleasepool {
chunk = nil;
}
}
DLog(@"End of stream? %@", [self properties]); DLog(@"End of stream? %@", [self properties]);
endOfStream = YES; endOfStream = YES;

View file

@ -66,6 +66,7 @@
- (void)setShouldReset:(BOOL)s; - (void)setShouldReset:(BOOL)s;
- (BOOL)shouldReset; - (BOOL)shouldReset;
- (void)resetBackwards;
- (void)setPreviousNode:(id _Nullable)p; - (void)setPreviousNode:(id _Nullable)p;
- (id _Nullable)previousNode; - (id _Nullable)previousNode;

View file

@ -523,6 +523,20 @@
} }
} }
- (void)lockedResetBuffer {
@autoreleasepool {
[buffer reset];
}
}
- (void)unlockedResetBuffer {
@autoreleasepool {
[accessLock lock];
[buffer reset];
[accessLock unlock];
}
}
// Implementations should override // Implementations should override
- (BOOL)paused { - (BOOL)paused {
return NO; return NO;
@ -556,4 +570,23 @@
return 0.0; return 0.0;
} }
// Reset everything in the chain
- (void)resetBackwards {
[accessLock lock];
if(buffer) {
[self lockedResetBuffer];
[writeSemaphore signal];
[readSemaphore signal];
}
Node *node = previousNode;
while(node) {
[node unlockedResetBuffer];
[node setShouldReset:YES];
[[node writeSemaphore] signal];
[[node readSemaphore] signal];
node = [node previousNode];
}
[accessLock unlock];
}
@end @end

View file

@ -62,9 +62,6 @@
- (double)volume; - (double)volume;
- (void)setVolume:(double)v; - (void)setVolume:(double)v;
- (void)mute;
- (void)unmute;
- (void)setShouldContinue:(BOOL)s; - (void)setShouldContinue:(BOOL)s;
- (void)setShouldPlayOutBuffer:(BOOL)s; - (void)setShouldPlayOutBuffer:(BOOL)s;

View file

@ -50,14 +50,6 @@
[output resume]; [output resume];
} }
- (void)mute {
[output mute];
}
- (void)unmute {
[output unmute];
}
- (void)incrementAmountPlayed:(double)seconds { - (void)incrementAmountPlayed:(double)seconds {
amountPlayed += seconds; amountPlayed += seconds;
amountPlayedInterval += seconds; amountPlayedInterval += seconds;
@ -189,7 +181,6 @@
} }
} }
if(formatChanged) { if(formatChanged) {
[audioPlayer mute];
InputNode *inputNode = [bufferChain inputNode]; InputNode *inputNode = [bufferChain inputNode];
if(converter) { if(converter) {
[converter setOutputFormat:format]; [converter setOutputFormat:format];

View file

@ -105,7 +105,6 @@ using std::atomic_long;
float tempBuffer[512 * 32]; float tempBuffer[512 * 32];
float inputBuffer[4096 * 32]; // 4096 samples times maximum supported channel count float inputBuffer[4096 * 32]; // 4096 samples times maximum supported channel count
BOOL muted;
#ifdef OUTPUT_LOG #ifdef OUTPUT_LOG
FILE *_logFile; FILE *_logFile;
#endif #endif
@ -126,9 +125,6 @@ using std::atomic_long;
- (double)volume; - (double)volume;
- (void)setVolume:(double)v; - (void)setVolume:(double)v;
- (void)mute;
- (void)unmute;
- (void)setShouldPlayOutBuffer:(BOOL)enabled; - (void)setShouldPlayOutBuffer:(BOOL)enabled;
- (void)sustainHDCD; - (void)sustainHDCD;

View file

@ -203,6 +203,7 @@ current_device_listener(AudioObjectID inObjectID, UInt32 inNumberAddresses, cons
started = NO; started = NO;
restarted = NO; restarted = NO;
lastClippedSampleRate = 0.0; lastClippedSampleRate = 0.0;
inputRemain = 0;
[outputLock unlock]; [outputLock unlock];
} }
@ -618,12 +619,6 @@ current_device_listener(AudioObjectID inObjectID, UInt32 inNumberAddresses, cons
@autoreleasepool { @autoreleasepool {
while(renderedSamples < frameCount) { while(renderedSamples < frameCount) {
if(_self->muted) {
inputData->mBuffers[0].mDataByteSize = frameCount * format->mBytesPerPacket;
inputData->mBuffers[0].mNumberChannels = channels;
bzero(inputData->mBuffers[0].mData, inputData->mBuffers[0].mDataByteSize);
return 0;
}
int inputRemain = _self->inputRemain; int inputRemain = _self->inputRemain;
while(!inputRemain) { while(!inputRemain) {
inputRemain = [_self renderAndConvert]; inputRemain = [_self renderAndConvert];
@ -746,17 +741,6 @@ current_device_listener(AudioObjectID inObjectID, UInt32 inNumberAddresses, cons
volume = v * 0.01f; volume = v * 0.01f;
} }
- (void)mute {
if(!muted) {
muted = YES;
inputRemain = 0;
}
}
- (void)unmute {
muted = NO;
}
- (double)latency { - (double)latency {
return 0.0; return 0.0;
} }