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:
parent
53291b570d
commit
4ed4ea906b
10 changed files with 42 additions and 83 deletions
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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];
|
||||||
|
|
|
@ -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];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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];
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue