Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Audio glitch when playing two AVPlayer audio files simultaneously

I have an iOS app that plays a background soundtrack with one AVPlayer and plays other sound clips "on top" with a second AVPlayer. (The sound clips are streamed from the Internet, hence the requirement for AVPlayer.) The problem is that when the second AVPlayer starts playing, it causes the background AVPlayer to stop for a fraction of a second, similar to what's described in this comment:

Play multiple Audio Files with AVPlayer


I am preparing the audio clips with this method:

- (void)prepareAudio:(NSURL *)assetURL {

asset = [AVURLAsset URLAssetWithURL:assetURL options:nil];
playerItem = [AVPlayerItem playerItemWithAsset:asset];
[player replaceCurrentItemWithPlayerItem:playerItem];


[playerItem addObserver:self forKeyPath:@"playbackBufferEmpty" options:NSKeyValueObservingOptionNew context:nil];
[playerItem addObserver:self forKeyPath:@"playbackLikelyToKeepUp" options:NSKeyValueObservingOptionNew context:nil];


[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(playerItemDidReachEnd:)
                                             name:AVPlayerItemDidPlayToEndTimeNotification
                                           object:[player currentItem]];

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(playerItemFailedToReachEnd:)
                                             name:AVPlayerItemFailedToPlayToEndTimeNotification
                                           object:[player currentItem]];
 }

...and then invoking [player play]; when I want to hear each sound.


Is there something I need to do when I set up the audio session or each instance of the AVPlayer, so that the sounds blend without the glitch?

like image 886
bruce1337 Avatar asked Jun 25 '12 05:06

bruce1337


2 Answers

This is probably as a result of the software encoder kicking in. You'll see a pretty big spike in memory as the software encoder attempts to play the second sound clip. Take a look at the apple docs section "iOS Hardware and Software Audio Codecs" http://developer.apple.com/library/ios/#DOCUMENTATION/AudioVideo/Conceptual/MultimediaPG/UsingAudio/UsingAudio.html

"When using hardware-assisted decoding, the device can play only a single instance of one of the supported formats at a time."

Also... "To play multiple sounds with best performance, or to efficiently play sounds while the iPod is playing in the background, use linear PCM (uncompressed) or IMA4 (compressed) audio."

If you have no choice in the media codecs you can provide, take a look at the AudioUnit framework to get a more seamless mixing. In particular the "Audio Mixer (MixerHost)" at http://developer.apple.com/library/ios/#samplecode/MixerHost/Introduction/Intro.html#//apple_ref/doc/uid/DTS40010210

like image 122
Eoin Avatar answered Oct 20 '22 17:10

Eoin


I finally figured out what the problem is. I'm writing an application where I'm adjusting the volume using the AVMutableAudioMixInputParameters class, and I'm attempting to normalize audio using this class by moving the volume up or down on a per-sample basis.

While this approach works when there are only a few volume ramps, it appears that the application of the ramps happens on the same thread that buffers the audio, so when I use too many (>~1000) of them, this eventually eats up the CPU that should be busy buffering audio, and then you have a g-g-g-glitch in the audio.

My solution was to refactor my volume normalization algorithm to use fewer volume ramps to achieve the same thing. Once I was able to get each set of volume ramps/song down to approximately 500 or so, I no longer had the issue, and the audio glitch went away.

like image 26
David Morton Avatar answered Oct 20 '22 19:10

David Morton