diff --git a/Audio/AudioPlayer.h b/Audio/AudioPlayer.h index db22efcc8..20c41024a 100644 --- a/Audio/AudioPlayer.h +++ b/Audio/AudioPlayer.h @@ -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; diff --git a/Audio/AudioPlayer.m b/Audio/AudioPlayer.m index 20a1e3fe4..dd2d8c521 100644 --- a/Audio/AudioPlayer.m +++ b/Audio/AudioPlayer.m @@ -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]; diff --git a/Audio/Chain/BufferChain.m b/Audio/Chain/BufferChain.m index 3097332b8..9aab848c3 100644 --- a/Audio/Chain/BufferChain.m +++ b/Audio/Chain/BufferChain.m @@ -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 diff --git a/Audio/Chain/InputNode.h b/Audio/Chain/InputNode.h index e7f68afb6..d5cb999d4 100644 --- a/Audio/Chain/InputNode.h +++ b/Audio/Chain/InputNode.h @@ -29,8 +29,6 @@ BOOL shouldSeek; long seekFrame; - double lastVolume; - BOOL observersAdded; Semaphore *exitAtTheEndOfTheStream; @@ -53,6 +51,4 @@ - (id_Nonnull)decoder; -- (void)setLastVolume:(double)v; - @end diff --git a/Audio/Chain/InputNode.m b/Audio/Chain/InputNode.m index 2f91ed71f..769eeae8e 100644 --- a/Audio/Chain/InputNode.m +++ b/Audio/Chain/InputNode.m @@ -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 diff --git a/Audio/Chain/OutputNode.h b/Audio/Chain/OutputNode.h index 7c6a38877..a2a603667 100644 --- a/Audio/Chain/OutputNode.h +++ b/Audio/Chain/OutputNode.h @@ -62,6 +62,9 @@ - (double)volume; - (void)setVolume:(double)v; +- (void)mute; +- (void)unmute; + - (void)setShouldContinue:(BOOL)s; - (void)setShouldPlayOutBuffer:(BOOL)s; diff --git a/Audio/Chain/OutputNode.m b/Audio/Chain/OutputNode.m index d8e85b779..1fa0fac8c 100644 --- a/Audio/Chain/OutputNode.m +++ b/Audio/Chain/OutputNode.m @@ -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]; } diff --git a/Audio/Output/OutputCoreAudio.h b/Audio/Output/OutputCoreAudio.h index c832fa9cc..2a833532f 100644 --- a/Audio/Output/OutputCoreAudio.h +++ b/Audio/Output/OutputCoreAudio.h @@ -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; diff --git a/Audio/Output/OutputCoreAudio.m b/Audio/Output/OutputCoreAudio.m index 0be277f59..80a30c4fc 100644 --- a/Audio/Output/OutputCoreAudio.m +++ b/Audio/Output/OutputCoreAudio.m @@ -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; }