Bug Fix: Greatly improve seeking operations
Seeking now mutes properly, and will not leave the audio muted across other operations. Audio output changes should also mute and destroy the buffers of the input chain, so that the audio resets properly. Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This commit is contained in:
parent
a7f1fd9d6c
commit
e76defbfd4
9 changed files with 68 additions and 21 deletions
|
@ -25,6 +25,7 @@
|
|||
BufferChain *bufferChain;
|
||||
OutputNode *output;
|
||||
|
||||
BOOL muted;
|
||||
double volume;
|
||||
double pitch;
|
||||
double tempo;
|
||||
|
@ -76,6 +77,9 @@
|
|||
- (double)volumeUp:(double)amount;
|
||||
- (double)volumeDown:(double)amount;
|
||||
|
||||
- (void)mute;
|
||||
- (void)unmute;
|
||||
|
||||
- (double)amountPlayed;
|
||||
- (double)amountPlayedInterval;
|
||||
|
||||
|
|
|
@ -78,7 +78,9 @@
|
|||
output = [[OutputNode alloc] initWithController:self previous:nil];
|
||||
}
|
||||
[output setup];
|
||||
[output setVolume:volume];
|
||||
if(muted) {
|
||||
[output mute];
|
||||
}
|
||||
@synchronized(chainQueue) {
|
||||
for(id anObject in chainQueue) {
|
||||
[anObject setShouldContinue:NO];
|
||||
|
@ -177,6 +179,10 @@
|
|||
[output resume];
|
||||
|
||||
[self setPlaybackStatus:CogStatusPlaying waitUntilDone:YES];
|
||||
|
||||
if(muted) {
|
||||
[self unmute];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)seekToTimeBG:(NSNumber *)time {
|
||||
|
@ -184,6 +190,7 @@
|
|||
}
|
||||
|
||||
- (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
|
||||
|
@ -218,6 +225,20 @@
|
|||
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];
|
||||
|
|
|
@ -230,7 +230,7 @@
|
|||
AudioPlayer * audioPlayer = controller;
|
||||
OutputNode *outputNode = [audioPlayer output];
|
||||
|
||||
[inputNode setLastVolume:[outputNode volume]];
|
||||
[audioPlayer mute];
|
||||
[inputNode seek:frame];
|
||||
}
|
||||
|
||||
|
@ -371,9 +371,6 @@
|
|||
[outputNode setVolume:v];
|
||||
}
|
||||
}
|
||||
if(inputNode) {
|
||||
[inputNode setLastVolume:v];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -29,8 +29,6 @@
|
|||
BOOL shouldSeek;
|
||||
long seekFrame;
|
||||
|
||||
double lastVolume;
|
||||
|
||||
BOOL observersAdded;
|
||||
|
||||
Semaphore *exitAtTheEndOfTheStream;
|
||||
|
@ -53,6 +51,4 @@
|
|||
|
||||
- (id<CogDecoder>_Nonnull)decoder;
|
||||
|
||||
- (void)setLastVolume:(double)v;
|
||||
|
||||
@end
|
||||
|
|
|
@ -29,7 +29,6 @@ static void *kInputNodeContext = &kInputNodeContext;
|
|||
if(self) {
|
||||
exitAtTheEndOfTheStream = [[Semaphore alloc] init];
|
||||
threadExited = NO;
|
||||
lastVolume = 1.0;
|
||||
}
|
||||
|
||||
return self;
|
||||
|
@ -161,7 +160,10 @@ static void *kInputNodeContext = &kInputNodeContext;
|
|||
while([self shouldContinue] == YES && [self endOfStream] == NO) {
|
||||
if(shouldSeek == YES) {
|
||||
BufferChain *bufferChain = controller;
|
||||
[bufferChain setVolume:0.0];
|
||||
AudioPlayer *audioPlayer = [controller controller];
|
||||
[audioPlayer mute];
|
||||
OutputNode *outputNode = [audioPlayer output];
|
||||
[outputNode resetBuffer];
|
||||
|
||||
ConverterNode *converter = [bufferChain converter];
|
||||
DSPRubberbandNode *rubberband = [bufferChain rubberband];
|
||||
|
@ -198,7 +200,7 @@ static void *kInputNodeContext = &kInputNodeContext;
|
|||
[controller setError:YES];
|
||||
}
|
||||
|
||||
[bufferChain setVolume:lastVolume];
|
||||
[audioPlayer unmute];
|
||||
}
|
||||
|
||||
AudioChunk *chunk;
|
||||
|
@ -251,6 +253,7 @@ static void *kInputNodeContext = &kInputNodeContext;
|
|||
seekFrame = frame;
|
||||
shouldSeek = YES;
|
||||
DLog(@"Should seek!");
|
||||
[self resetBuffer];
|
||||
[writeSemaphore signal];
|
||||
|
||||
if(endOfStream) {
|
||||
|
@ -300,8 +303,4 @@ static void *kInputNodeContext = &kInputNodeContext;
|
|||
return [buffer listDuration];
|
||||
}
|
||||
|
||||
- (void)setLastVolume:(double)v {
|
||||
lastVolume = v;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -62,6 +62,9 @@
|
|||
- (double)volume;
|
||||
- (void)setVolume:(double)v;
|
||||
|
||||
- (void)mute;
|
||||
- (void)unmute;
|
||||
|
||||
- (void)setShouldContinue:(BOOL)s;
|
||||
|
||||
- (void)setShouldPlayOutBuffer:(BOOL)s;
|
||||
|
|
|
@ -50,6 +50,14 @@
|
|||
[output resume];
|
||||
}
|
||||
|
||||
- (void)mute {
|
||||
[output mute];
|
||||
}
|
||||
|
||||
- (void)unmute {
|
||||
[output unmute];
|
||||
}
|
||||
|
||||
- (void)incrementAmountPlayed:(double)seconds {
|
||||
amountPlayed += seconds;
|
||||
amountPlayedInterval += seconds;
|
||||
|
@ -156,7 +164,8 @@
|
|||
config = channelConfig;
|
||||
// Calculate a ratio and add to double(seconds) instead, as format may change
|
||||
// double oldSampleRatio = sampleRatio;
|
||||
BufferChain *bufferChain = [controller bufferChain];
|
||||
AudioPlayer *audioPlayer = controller;
|
||||
BufferChain *bufferChain = [audioPlayer bufferChain];
|
||||
if(bufferChain) {
|
||||
ConverterNode *converter = [bufferChain converter];
|
||||
DSPDownmixNode *downmix = [bufferChain downmix];
|
||||
|
@ -180,11 +189,8 @@
|
|||
}
|
||||
}
|
||||
if(formatChanged) {
|
||||
[audioPlayer mute];
|
||||
InputNode *inputNode = [bufferChain inputNode];
|
||||
if(inputNode) {
|
||||
[inputNode setLastVolume:[output volume]];
|
||||
[output setVolume:0.0];
|
||||
}
|
||||
if(converter) {
|
||||
[converter setOutputFormat:format];
|
||||
}
|
||||
|
|
|
@ -105,6 +105,7 @@ 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
|
||||
|
@ -125,6 +126,9 @@ using std::atomic_long;
|
|||
- (double)volume;
|
||||
- (void)setVolume:(double)v;
|
||||
|
||||
- (void)mute;
|
||||
- (void)unmute;
|
||||
|
||||
- (void)setShouldPlayOutBuffer:(BOOL)enabled;
|
||||
|
||||
- (void)sustainHDCD;
|
||||
|
|
|
@ -618,6 +618,12 @@ 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];
|
||||
|
@ -740,6 +746,17 @@ 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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue