I have an app that plays background music using MPMusicPlayerController and foreground sounds using AVAudioPlayer. I want to control the relative volume so that MPMusicPlayerController is much lower, but setting the volumne changes the overall system volume as if using the buttons on the side of the phone. Is there way to lower the volumne of MPMusicPlayerController without lowering the system volume?
MPMusicPlayerController *musicPlayer = [MPMusicPlayerController applicationMusicPlayer];
musicPlayer.volume = 0.1; // at this point the overall system volune has been set to 0.1
[musicPlayer setQueueWithItemCollection:collection];
[musicPlayer play];
AVAudioPlayer *player = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&err];
[player prepareToPlay];
[player setVolume: 1.0]; // I want this to be twice as loud as MPMusicPlayerController
[player play];
You need to learn how to "duck" the MPMusicPLayer. Try calling the method below before and after you play the AVAudioPlayer.
Basically, [self setAudioSessionWithDucking:YES] before and [self setAudioSessionWithDucking:NO] after.
- (void)setAudioSessionWithDucking:(BOOL)isDucking
{
AudioSessionSetActive(NO);
UInt32 overrideCategoryDefaultToSpeaker = 1;
AudioSessionSetProperty (kAudioSessionProperty_OverrideCategoryDefaultToSpeaker, sizeof (overrideCategoryDefaultToSpeaker), &overrideCategoryDefaultToSpeaker);
UInt32 overrideCategoryMixWithOthers = 1;
AudioSessionSetProperty (kAudioSessionProperty_OverrideCategoryMixWithOthers, sizeof (overrideCategoryMixWithOthers), &overrideCategoryMixWithOthers);
UInt32 value = isDucking;
AudioSessionSetProperty(kAudioSessionProperty_OtherMixableAudioShouldDuck, sizeof(value), &value);
AudioSessionSetActive(YES);
}
Related
I have an app that plays various musical sounds using AVAudioPlayer. It lets people select a song from their library and plays it with MPMusicPlayerController. It used to work that they could jam with it, but now when MPMusicPlayerController is playing it doesn't play the sound using AVAudioPlayer. It even doesn't play the sound once MPMusicPlayerController has stopped. I've tested it on 13.4.1 and 13.6. What changed to make it stop working and what can I do to fix it?
It plays the sound like this:
AVAudioPlayer *player = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&err];
[player prepareToPlay];
[player setVolume: 1.0];
[player play];
For the music, it gets a MPMediaItemCollection using MPMediaPickerController, then plays it like this:
- (void) playMusic: (MPMediaItemCollection *) collection {
[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryAmbient error: nil];
if (musicPlayer == nil) {
musicPlayer = [MPMusicPlayerController applicationMusicPlayer];
[musicPlayer setShuffleMode: MPMusicShuffleModeOff];
[musicPlayer setRepeatMode: MPMusicRepeatModeNone];
}
[musicPlayer setQueueWithItemCollection:collection];
[musicPlayer play];
}
Feeling stupid. The phones were set to silent mode. For some reason, it can play the sounds or the music on silent, but it can't play them both together.
I have an AVAudioPlayer playing a song through the speaker. I made the audio play through the speaker like this.
[[AVAudioSession sharedInstance] overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker error:nil];
Now I have an AVAudioPlayer which I set up like this.
player = [[AVAudioPlayer alloc] initWithContentsOfURL:currentSong.songLocation error:nil];
and I play it like this
[player prepareToPlay];
[player play];
Everything is fine until I change the audio player like this, where I first update currentSong to a new object and init from that
player = [[AVAudioPlayer alloc] initWithContentsOfURL:currentSong.songLocation error:nil];
[player setVolume:1.0f];
[player prepareToPlay];
[player play];
Now the output is quiet, still on the speaker but quiet. If I change the audio output back to AVAudioSessionPortOverrideNone and the back to AVAudioSessionPortOverrideSpeaker, the sound is loud again, but switching the AVAudioPlayer sends me back to "quiet".
I'm interested in how I can manage background music in my Sprite Kit game to achieve fade in/out.
I noticed that Sprite Kit has a built-in sound player, but it seems to be more useful for very short effects, like "on hit" sounds:
[self runAction:[SKAction playSoundFileNamed:#"music.mp3" waitForCompletion:NO]];
It does not seem like there's a way to stop this sound.
I'm using Kobold Kit, and it comes with OALSimpleAudio library that can play sounds:
[[OALSimpleAudio sharedInstance] preloadEffect:#"die.wav"];
[[OALSimpleAudio sharedInstance] playEffect:#"die.wav"];
[[OALSimpleAudio sharedInstance]preloadBg:#"battle.mp3"];
[[OALSimpleAudio sharedInstance] playBg:#"battle.mp3" loop:YES];
There's a bgVolume property in OALSimpleAudio, but no real fade.
Should try to write my own fade in/out code of if there's something out there I can use to control volume over time of a generic music player, like OALSimpleAudio.
You can also just use the build in AVAudioPlayer or of course adapt the function to your player:
//play background sound
NSError *error;
NSURL * backgroundMusicURL = [[NSBundle mainBundle] URLForResource:#"SpaceLife" withExtension:#"mp3"];
self.backgroundMusicPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:backgroundMusicURL error:&error];
self.backgroundMusicPlayer.numberOfLoops = -1;
[self.backgroundMusicPlayer prepareToPlay];
[self.backgroundMusicPlayer play];
And then you add the function from this post:
- (void)doVolumeFade
{
if (self.backgroundMusicPlayer.volume > 0.1) {
self.backgroundMusicPlayer.volume = self.player.volume - 0.1;
[self performSelector:#selector(doVolumeFade) withObject:nil afterDelay:0.1];
} else {
// Stop and get the sound ready for playing again
[self.backgroundMusicPlayer stop];
self.backgroundMusicPlayer.currentTime = 0;
[self.backgroundMusicPlayer prepareToPlay];
self.backgroundMusicPlayer.volume = 1.0;
}
}
ObjectAL has an AVAudioPlayer wrapper built in for music playback. It's called OALAudioTrack.
OALAudioTrack has a method fadeTo:duration:target:selector: that you can use to do fading. You already have an instance of OALAudioTrack available to you as the simple audio interface's backgroundTrack property:
[[OALSimpleAudio sharedInstance].backgroundTrack fadeTo:.. duration:.. ..];
I've set my phone to muted state by switching vibrate/sound hardware button. In whole application some background music is playing unless the device is in muted state. So in this case, my music is playing but muted. Now in some point I want to present video (which is without sound but this shouldn't matter), however the video in MPMoviePlayerController turns music from AVAudioPlayer on even though the device is is 'muted' state. The AVAudioPlayer continues to play loudly even when i quit MPMoviePlayerController.
Some code samples, but i doubt it will help:
// movie without sound
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategorySoloAmbient error:nil];
NSURL *movieURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"myVideo" ofType:#"mp4"]];
_moviePlayerController = [[MPMoviePlayerController alloc] initWithContentURL:movieURL];
[_scrollView addSubview:_moviePlayerController.view];
[_moviePlayerController prepareToPlay];
[_moviePlayerController play];
// music
_audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];
[_audioPlayer prepareToPlay];
[_audioPlayer play];
To fix this, I had to rewrite the code but instead of using MPMoviePlayerController I've used AVPlayer. Everything works like a charm now.
So I'm trying to play a sound file at a different rate in iOS 5.1.1, and am having absolutely no luck. So far I have tried setting the rate of the AVAudioPlayer:
player = [[AVAudioPlayer alloc] initWithContentsOfURL:referenceURL error:&error];
player.enableRate = YES;
player.rate = 1.5;
player.numberOfLoops = 0;
player.delegate = self;
[player prepareToPlay];
[player play];
with no luck at all, the sound plays but just ignores the rate I give it. I have also tried AVPlayer:
avPlayer = [[AVPlayer alloc] initWithURL:referenceURL];
avPlayer.rate = 0.5;
[avPlayer play];
Again, it plays but just ignores the rate I set. I have tried a number of different audio files but for the sake of this thread I selected Rooster-mono.wav from this catalogue: http://sig.sapp.org/sounds/wave/
Has anybody had any success with changing the playback rate on iOS 5.1.1? Or does anybody know what I am missing here?
I am doing this to change the pitch slightly of some of my samples, I realise I could do this by using RemoteIO or something similar but that seems total overkill for what I am trying to achieve (a simple playback rate adjustment).
here is some code that i know works, just re-tested in an app i've been working on. as you mention, using setEnableRate: and setRate: will only work with iOS 5.0 and above. so i use respondsToSelector: to test on the device whether or not the device will accept the request:
_noticeAudio = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"Rooster-mono" ofType:#"wav"]]
error:nil];;
if ([_noticeAudio respondsToSelector:#selector(setEnableRate:)])
_noticeAudio.enableRate = YES;
if ([_noticeAudio respondsToSelector:#selector(setRate:)])
_noticeAudio.rate = 2.0;
running on an iOS 5 device, it performs the double-rate successfully. running on iOS 4.3, it plays it at normal speed.
so, the only way you'll get the proper rate is if your device has iOS 5 on it.
Modify the code to:
avPlayer = [[AVPlayer alloc] initWithURL:referenceURL];
[avPlayer play]; //call play first
avPlayer.rate = 0.5; //then set rate
This is how you do it.
rate value is between 0.1f - 2.0f
player = [[AVAudioPlayer alloc]
initWithContentsOfURL:[NSURL fileURLWithPath:path]
error:&err];
player.volume = 0.4f;
player.enableRate=YES;
[player prepareToPlay];
[player setNumberOfLoops:0];
player.rate=2.0f;
[player play];
Swift 2.0
let player = AVPlayer(URL: url)
player.play()
player.rate = 0.9