Skip to content

Commit

Permalink
Bug Fix: Attempt to make seeking more performant
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
kode54 committed Feb 26, 2025
1 parent 375b019 commit 9f6134a
Show file tree
Hide file tree
Showing 10 changed files with 43 additions and 84 deletions.
4 changes: 0 additions & 4 deletions Audio/AudioPlayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
BufferChain *bufferChain;
OutputNode *output;

BOOL muted;
double volume;
double pitch;
double tempo;
Expand Down Expand Up @@ -77,9 +76,6 @@
- (double)volumeUp:(double)amount;
- (double)volumeDown:(double)amount;

- (void)mute;
- (void)unmute;

- (double)amountPlayed;
- (double)amountPlayedInterval;

Expand Down
22 changes: 0 additions & 22 deletions Audio/AudioPlayer.m
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,6 @@ - (void)play:(NSURL *)url withUserInfo:(id)userInfo withRGInfo:(NSDictionary *)r
output = [[OutputNode alloc] initWithController:self previous:nil];
}
[output setup];
if(muted) {
[output mute];
}
@synchronized(chainQueue) {
for(id anObject in chainQueue) {
[anObject setShouldContinue:NO];
Expand Down Expand Up @@ -179,18 +176,13 @@ - (void)resume {
[output resume];

[self setPlaybackStatus:CogStatusPlaying waitUntilDone:YES];

if(muted) {
[self unmute];
}
}

- (void)seekToTimeBG:(NSNumber *)time {
[self seekToTime:[time doubleValue]];
}

- (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
Expand Down Expand Up @@ -225,20 +217,6 @@ - (double)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.
- (void)setNextStream:(NSURL *)url {
[self setNextStream:url withUserInfo:nil withRGInfo:nil];
Expand Down
1 change: 0 additions & 1 deletion Audio/Chain/BufferChain.m
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,6 @@ - (void)seek:(double)time {
AudioPlayer * audioPlayer = controller;
OutputNode *outputNode = [audioPlayer output];

[audioPlayer mute];
[inputNode seek:frame];
}

Expand Down
32 changes: 8 additions & 24 deletions Audio/Chain/InputNode.m
Original file line number Diff line number Diff line change
Expand Up @@ -160,30 +160,11 @@ - (void)process {
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];
DLog(@"SEEKING! Resetting Buffer");
[outputNode resetBackwards];

DLog(@"Reset buffer!");

Expand All @@ -199,8 +180,6 @@ - (void)process {
if(seekError) {
[controller setError:YES];
}

[audioPlayer unmute];
}

AudioChunk *chunk;
Expand All @@ -214,6 +193,11 @@ - (void)process {
chunk = nil;
}
} else {
if(chunk) {
@autoreleasepool {
chunk = nil;
}
}
DLog(@"End of stream? %@", [self properties]);

endOfStream = YES;
Expand Down
1 change: 1 addition & 0 deletions Audio/Chain/Node.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@

- (void)setShouldReset:(BOOL)s;
- (BOOL)shouldReset;
- (void)resetBackwards;

- (void)setPreviousNode:(id _Nullable)p;
- (id _Nullable)previousNode;
Expand Down
33 changes: 33 additions & 0 deletions Audio/Chain/Node.m
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,20 @@ - (void)resetBuffer {
}
}

- (void)lockedResetBuffer {
@autoreleasepool {
[buffer reset];
}
}

- (void)unlockedResetBuffer {
@autoreleasepool {
[accessLock lock];
[buffer reset];
[accessLock unlock];
}
}

// Implementations should override
- (BOOL)paused {
return NO;
Expand Down Expand Up @@ -556,4 +570,23 @@ - (double)secondsBuffered {
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
3 changes: 0 additions & 3 deletions Audio/Chain/OutputNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,6 @@
- (double)volume;
- (void)setVolume:(double)v;

- (void)mute;
- (void)unmute;

- (void)setShouldContinue:(BOOL)s;

- (void)setShouldPlayOutBuffer:(BOOL)s;
Expand Down
9 changes: 0 additions & 9 deletions Audio/Chain/OutputNode.m
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,6 @@ - (void)resume {
[output resume];
}

- (void)mute {
[output mute];
}

- (void)unmute {
[output unmute];
}

- (void)incrementAmountPlayed:(double)seconds {
amountPlayed += seconds;
amountPlayedInterval += seconds;
Expand Down Expand Up @@ -189,7 +181,6 @@ - (void)setFormat:(AudioStreamBasicDescription *)f channelConfig:(uint32_t)chann
}
}
if(formatChanged) {
[audioPlayer mute];
InputNode *inputNode = [bufferChain inputNode];
if(converter) {
[converter setOutputFormat:format];
Expand Down
4 changes: 0 additions & 4 deletions Audio/Output/OutputCoreAudio.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -126,9 +125,6 @@ using std::atomic_long;
- (double)volume;
- (void)setVolume:(double)v;

- (void)mute;
- (void)unmute;

- (void)setShouldPlayOutBuffer:(BOOL)enabled;

- (void)sustainHDCD;
Expand Down
18 changes: 1 addition & 17 deletions Audio/Output/OutputCoreAudio.m
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ - (void)threadEntry:(id)arg {
started = NO;
restarted = NO;
lastClippedSampleRate = 0.0;
inputRemain = 0;
[outputLock unlock];
}

Expand Down Expand Up @@ -618,12 +619,6 @@ - (void)audioOutputBlock {

@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];
Expand Down Expand Up @@ -746,17 +741,6 @@ - (void)setVolume:(double)v {
volume = v * 0.01f;
}

- (void)mute {
if(!muted) {
muted = YES;
inputRemain = 0;
}
}

- (void)unmute {
muted = NO;
}

- (double)latency {
return 0.0;
}
Expand Down

0 comments on commit 9f6134a

Please sign in to comment.