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;
OutputNode *output;
BOOL muted;
double volume;
double pitch;
double tempo;
@ -77,9 +76,6 @@
- (double)volumeUp:(double)amount;
- (double)volumeDown:(double)amount;
- (void)mute;
- (void)unmute;
- (double)amountPlayed;
- (double)amountPlayedInterval;

View file

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

View file

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

View file

@ -160,30 +160,11 @@ static void *kInputNodeContext = &kInputNodeContext;
while([self shouldContinue] == YES && [self endOfStream] == NO) {
if(shouldSeek == YES) {
BufferChain *bufferChain = controller;
AudioPlayer *audioPlayer = [controller controller];
[audioPlayer mute];
AudioPlayer *audioPlayer = [bufferChain controller];
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");
// 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];
[outputNode resetBackwards];
DLog(@"Reset buffer!");
@ -199,8 +180,6 @@ static void *kInputNodeContext = &kInputNodeContext;
if(seekError) {
[controller setError:YES];
}
[audioPlayer unmute];
}
AudioChunk *chunk;
@ -214,6 +193,11 @@ static void *kInputNodeContext = &kInputNodeContext;
chunk = nil;
}
} else {
if(chunk) {
@autoreleasepool {
chunk = nil;
}
}
DLog(@"End of stream? %@", [self properties]);
endOfStream = YES;

View file

@ -66,6 +66,7 @@
- (void)setShouldReset:(BOOL)s;
- (BOOL)shouldReset;
- (void)resetBackwards;
- (void)setPreviousNode:(id _Nullable)p;
- (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
- (BOOL)paused {
return NO;
@ -556,4 +570,23 @@
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

View file

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

View file

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

View file

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

View file

@ -203,6 +203,7 @@ current_device_listener(AudioObjectID inObjectID, UInt32 inNumberAddresses, cons
started = NO;
restarted = NO;
lastClippedSampleRate = 0.0;
inputRemain = 0;
[outputLock unlock];
}
@ -618,12 +619,6 @@ current_device_listener(AudioObjectID inObjectID, UInt32 inNumberAddresses, cons
@autoreleasepool {
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;
while(!inputRemain) {
inputRemain = [_self renderAndConvert];
@ -746,17 +741,6 @@ current_device_listener(AudioObjectID inObjectID, UInt32 inNumberAddresses, cons
volume = v * 0.01f;
}
- (void)mute {
if(!muted) {
muted = YES;
inputRemain = 0;
}
}
- (void)unmute {
muted = NO;
}
- (double)latency {
return 0.0;
}