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.
Related
I'm using the systemMusicPlayer to play songs inside an app.
If a user pushes noiseButton on the Now Playing view, it will pause the systemMusicPlayer song audio file for 10 seconds to play the noiseButton audio file, and then pick back up on the systemMusicPlayer song audio file.
I'm able to get the systemMusicPlayer song audio file to pause and then pick back up after 10 seconds, but I am not able to get the noiseButton to play its sound in the 10 seconds.
I know the noiseButton audio file works
I'm NSLogging before and after the method that plays the noiseButton file
I'm not sure what I'm missing?
Here is my code:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
musicPlayer = [MPMusicPlayerController systemMusicPlayer];
[self registerMediaPlayerNotifications];
// Construct URL to sound file
NSString *path = [NSString stringWithFormat:#"%#/background-music-aac.caf", [[NSBundle mainBundle] resourcePath]];
NSURL *soundUrl = [NSURL fileURLWithPath:path];
// Create audio player object and initialize with URL to sound
_audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:soundUrl error:nil];
}
- (void)willPlayClip {
[NSTimer scheduledTimerWithTimeInterval:10.0
target:self
selector:#selector(willPlayMusicInTenSeconds:)
userInfo:nil
repeats:NO];
}
- (void)willPlayMusicInTenSeconds:(NSTimer *)timer {
NSLog(#"Get ready to Play noise sound");
[_audioPlayer play];
NSLog(#"Play noise sound");
[musicPlayer play];
NSLog(#"Start playing again");
}
And the code inside the noiseButton for when it gets pressed:
if ([musicPlayer playbackState] == MPMusicPlaybackStatePlaying) {
[musicPlayer pause];
NSLog(#"Paused!");
[self willPlayClip];
} else {
NSLog(#"Already paused");
}
What AudioSession category are you setting? If you're not, refer to this documentation:
Audio Session Categories
I believe that you should get the desired behaviour if you set your session to AVAudioSessionCategoryAmbient:
The category for an app in which sound playback is nonprimary—that is, your app can be used successfully with the sound turned off.
This category is also appropriate for “play along” style apps, such as a virtual piano that a user plays while the Music app is playing. When you use this category, audio from other apps mixes with your audio. Your audio is silenced by screen locking and by the Silent switch (called the Ring/Silent switch on iPhone).
Give that a try if you're not already.
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'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.
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);
}
I am using AVAudioPlayer to make an MP3 player. I have multiple MP3 sounds and would like to play these sounds one by one. Following is the logic of my app:
///// For playing 1st sound
mp3Player = [[AVAudioPlayer alloc] initWithContentsOfURL:url1 error:nil];
[mp3Player prepareToPlay];
[mp3Player play];
///// For playing 2nd sound
mp3Player = nil;
mp3Player = [[AVAudioPlayer alloc] initWithContentsOfURL:url2 error:nil];
[mp3Player prepareToPlay];
[mp3Player play];
///// For playing 3rd sound
mp3Player = nil;
mp3Player = [[AVAudioPlayer alloc] initWithContentsOfURL:url3 error:nil];
[mp3Player prepareToPlay];
[mp3Player play];
etc...
Just would like to know: I nil out the player and alloc AVAudioPlayer before playing the next sound. Is there any performance (speed) or memory (leak) concern in this logic? (I am using ARC). If so, is there any way to alloc AVAudioPlayer just ONE time, and to accept diffrent URLs pointing to those sounds? Thanks a lot in advance.
I think below link may help you:
How to play multiple audio files in sequence by loop in AVAudioPlayer?
In which audioPlayerDidFinishPlaying is used to play next song after one finishes.