Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fade out volume of AVAudioPlayerNode programmatically

I've got an AVAudioEngine setup with a AVAudioPlayerNode that is playing some background music.

I'm trying to find a best approach to create a volume fadeout on the node over a 2 second timeframe. I'm considering using CADisplayLink in order to do this. I was wondering if somebody had experience with this scenario and could advise me on their approach?

like image 645
Danny Bravo Avatar asked Oct 07 '15 10:10

Danny Bravo


2 Answers

My approach is below. Note that I assign the timer to a member var so I can invalidate it at other points (viewWillDisappear, delloc, etc.). I was worried that it wouldn't sound smooth, but I tried it and it works fine, didn't need to use CADisplayLink.

- (void)fadeOutAudioWithDuration:(double)duration {
    double timerInterval = 0.1;
    NSNumber *volumeInterval = [NSNumber numberWithDouble:(timerInterval / duration)];
    self.fadeOutTimer = [NSTimer scheduledTimerWithTimeInterval:timerInterval target:self selector:@selector(fadeOutTimerDidFire:) userInfo:volumeInterval repeats:YES];
}

- (void)fadeOutTimerDidFire:(NSTimer *)timer {
    float volumeInterval = ((NSNumber *)timer.userInfo).floatValue;
    float currentVolume = self.audioEngine.mainMixerNode.outputVolume;
    float newValue = MAX(currentVolume - volumeInterval, 0.0f);
    self.audioEngine.mainMixerNode.outputVolume = newValue;
    if (newValue == 0.0f) {
        [timer invalidate];
    }
}
like image 124
Nigam Shah Avatar answered Sep 18 '22 01:09

Nigam Shah


You can use global gain in EQ.

for example

AVAudioUnitEQ *Volume;
Volume = [[AVAudioUnitEQ alloc] init];
[engine attachNode:Volume];
[engine connect:Volume to:engine.outputNode format:nil];

And then

Volume.globalGain = /*here your floatValue*/
like image 37
Ray Avatar answered Sep 18 '22 01:09

Ray