The AVPlayer / AVAudioMix effect freezes at the beginning

I am trying to implement a fading effect based on AVPlayer + AVAudioMix + AVAudioMixInputParameters. This basically works, except that when you first play the sound after starting the application, there is a click at the beginning. Subsequent games work fine, but the first glitch is pretty stable and reproducible.

The My Game button is enabled only after the AVPlayerItem status set to ready, so it is impossible to start the playback method until the player is ready. In fact, it does not matter how long I wait after downloading the audio file and building all the objects.

This happens on OS X, I have not tested it on iOS (yet).

Please note that for this test you need a sound file starting with a sound, not a sound. Here is my stripped-down code without the GUI part ( testFadeIn is the entry point):

 static AVPlayer* player; static void* PlayerItemStatusObserverContext = &PlayerItemStatusObserverContext; - (void)testFadeIn { AVURLAsset* asset = [AVURLAsset.alloc initWithURL:[NSURL fileURLWithPath:@"Helicopter.m4a"] options:@{AVURLAssetPreferPreciseDurationAndTimingKey: @YES}]; AVPlayerItem* item = [AVPlayerItem playerItemWithAsset:asset]; player = [AVPlayer playerWithPlayerItem:item]; [item addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew context:PlayerItemStatusObserverContext]; } - (void)observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object change:(NSDictionary*)change context:(void*)context { if (context == PlayerItemStatusObserverContext) { AVPlayerStatus status = (AVPlayerStatus)[[change objectForKey:NSKeyValueChangeNewKey] integerValue]; if (status == AVPlayerStatusReadyToPlay) { [self applyFadeIn]; [self performSelector:@selector(play:) withObject:nil afterDelay:1.0]; } } } - (void)applyFadeIn { assert(player.currentItem.tracks.firstObject); AVMutableAudioMixInputParameters* fadeIn = [AVMutableAudioMixInputParameters audioMixInputParametersWithTrack:player.currentItem.tracks.firstObject]; [fadeIn setVolume:0 atTime:kCMTimeZero]; [fadeIn setVolume:1 atTime:CMTimeMake(2, 1)]; NSMutableArray* paramsArray = [NSMutableArray new]; [paramsArray addObject:fadeIn]; AVMutableAudioMix* audioMix = [AVMutableAudioMix audioMix]; audioMix.inputParameters = paramsArray; player.currentItem.audioMix = audioMix; } - (void)play:(id)unused { [player play]; } 

Click! What is wrong with that?

Edit

The obvious workaround I'm currently using is: when the player reports ready, I do a short playback of 100 ms using volume = 0, then restore the current time and volume, and only then I tell the main application that the player is ready. Thus, there are no clicks. Interestingly, anything less than 100 ms still gives a click.

This seems like a problem with something that AVFoundation caches after the first play. These are not tracks, as they are available when I set the attenuation in the parameters or the search status.

+6
source share

All Articles