I can turn off my audio player by using:
- (IBAction)sndOnOff:(id)sender {
if (_sndBtn.selected == NO) {
[_sndBtn setSelected:YES];
[audioPlayer stop];
}
else{
[_sndBtn setSelected:NO];
[audioPlayer play];
}
But how do I turn off a System Sound that I've created?
NSURL *soundURL1 = [[NSBundle mainBundle] URLForResource:#"selectSound"
withExtension:#"wav"];
AudioServicesCreateSystemSoundID((__bridge CFURLRef)soundURL1, &sound2);
There is a reason that we don't get fine control over system sound - because it is supposed to be short (in iOS < 30 seconds) and complete. Imagine, how many times do we experience a system sound cut-off in any OS?
But you could do this:
AudioServicesDisposeSystemSoundID (sound2);
to stop it. But this means you would need to create the sound again by using:
AudioServicesCreateSystemSoundID((__bridge CFURLRef)soundURL1, &sound2);
And to play it again:
AudioServicesPlaySystemSound(sound2);
You could of course instead to play your "system sound" on AVPlayer and stop it like you do a song, but that would mean it "shouldn't be" a system sound in the first place. Hope this helps.
Just do this...
AudioServicesDisposeSystemSoundID (sound2);
I cannot think of any negative consequences.
Related
Sorry for the weird title but AVAudioPlayer acts a bit weird when it comes to playing a sound again, right before the sound that it's playing ends.
I can play an mp3 file when the player is not playing, when the player finished playing and when the player is playing.
I cannot play an mp3 when the song that is currently playing is about to end. This is my code, I documented the important bits.
-(void) play:(int)p{
if([players[p] isPlaying]){
NSLog(#"is playing");
[players[p] setCurrentTime:0.025f]; //when it's playing, set it to the start of the
//file so it starts playing again. Usually works
if(![players[p] isPlaying]){
NSLog(#"is not playing"); //although I just told the player to play again
//it sometimes returns that it in fact does NOT play
//so it's playing in the first if condition but
//not playing in the second if condition
[players[p] prepareToPlay];
[players[p] play]; //from here I try to resurrect the player numerous times
//but everything fails, I have to call the function again to make it work
[players[p] setCurrentTime:0.025f];
if([players[p] isPlaying]){
NSLog(#"playing"); //never gets called; although I tell it to play so many times
//it just won't do
}else {
NSLog(#"NOTplaying");
[players[p] play];
}
} else {
NSLog(#"is still playing");
}
} else {
NSLog(#"not playing at all");
[players[p] play]; } //if not playing, play. Always works
}
I think this might have something to do with how the AVAudioPlayer releases the file or that it's playing but is not playing anyumore in the millisecond after that. (playing during the first if condition but stopped right after that).
The window in which this occurs can easily be reproduced with with a 5sec audio file. Just wait till it's about to end and then click "play" and the method gets executed but nothing's playing. The method works in every other case (not playing and playing but not going to finish playing).
I load a video into my Sprite Kit SKVideoNode, but how do I stop and restart the playback or go to a specific time in the video? All I see are play and pause methods.
// AVPlayer
NSURL *fileURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"HowToPlay" ofType:#"mp4"]];
_avPlayer = [AVPlayer playerWithURL:fileURL];
// SKVideoNode
_videoNode = [SKVideoNode videoNodeWithAVPlayer:_avPlayer];
[_videoNode play];
This turned out to work for me.
Restart:
[_videoNode removeFromParent];
_videoNode = [SKVideoNode videoNodeWithVideoFileNamed:#"video.mp4"];
_videoNode.position = ...
_videoNode.size = ...
[self addChild:_videoNode];
[_videoNode play];
Pause:
[_videoNode pause];
_videoNode.paused = YES;
Play:
[_videoNode play];
_videoNode.paused = NO;
All you can do with a SKVideoNode is documented here. play and pause are the only supported playback methods.
There is no stop because its equivalent to pause in this context - what should "stop" do, render a black texture? If the SKVideoNode should be removed on "stop" then just send it the removeFromParent message, that'll "stop" it.
Rewind is unnecessary because you can simply run the play method again or create a new SKVideoNode.
I assume jumping to a specific timeframe isn't supported because this can't be instant, so again there's the problem of what the node should display in the time until the video playback position was moved to the specified timestamp?
If you keep a reference to the AVPlayer object used to initialize the video node then you can control playback with its methods
My application has the ability to call. Sound used to call AVAudioPlayer. The problem is that after a call to my application, if the music played in the background (for example, in the application "Music"), it does not restore music to play.
Tried some of the methods in this forum, but unfortunately nothing has helped. Help please, how can I solve this problem? Sorry for my english.
I solved this problem for myself. I check the music is playing or not, if yes then stop the music and put the flag.
thirdPartyPlayer = [MPMusicPlayerController iPodMusicPlayer];
[thirdPartyPlayer stop];
if (thirdPartyPlayer.playbackState == MPMusicPlaybackStateInterrupted || thirdPartyPlayer.playbackState == MPMusicPlaybackStatePlaying)
{
isThirdPartyPlayerPlay = true;
}
Then when the call ends, I restore play back music, if there is a flag.
if (isThirdPartyPlayerPlay)
{
[thirdPartyPlayer play];
isThirdPartyPlayerPlay = NO;
}
I'm working on an IOS game, and the background music clip is 7 seconds long, so when the scene changes from one scene to the next, I want it to stop instantly, but it continues and finishes the 7 second loop then stops.
This is the code:
[self runAction:[SKAction repeatActionForever:[SKAction playSoundFileNamed:#"sound 1.m4a" waitForCompletion:YES]]];
if (_dead == YES) {
[self removeAllActions];
}
where _dead is when the player dies, and the new scene is triggered.
How can I get the music to stop that instant, as opposed to finishing its loop?
Instead of using SKAction to play your background sound file, I would suggest using AVFoundation which allows you to simply issue a stop command.
Update
I can't think of any food tutorials that focus primarily on the sound side. Most deal with video and sound. Try google with something like 'AVFoundation tutorial'.
To use AVFoundation you can do this for your purposes...
Add the AVFoundation.framework to your project.
In your .h file add the delegate <AVAudioPlayerDelegate>
In your .m file #import <AVFoundation/AVFoundation.h>
Create a property AVAudioPlayer *_backgroundMusicPlayer;
Create this method:
- (void)playBackgroundMusic:(NSString *)filename {
NSError *error;
NSURL *backgroundMusicURL = [[NSBundle mainBundle] URLForResource:filename withExtension:nil];
_backgroundMusicPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:backgroundMusicURL error:&error];
_backgroundMusicPlayer.numberOfLoops = -1;
_backgroundMusicPlayer.volume = 0.2;
_backgroundMusicPlayer.delegate = self;
[_backgroundMusicPlayer prepareToPlay];
[_backgroundMusicPlayer play];
}
To start playing [self playBackgroundMusic:[NSString stringWithFormat:#"bgMusic.mp3"]];
To stop playing [_backgroundMusicPlayer stop];
That should do the trick. I suggest you read up on the AVAudioPlayer Class Reference so you understand its properties. For example, numberOfLoops set to -1 will loop the sound indefinitely until you call the stop method. Another issue to keep in mind is the audio file sound format. AVFoundation is somewhat picky about what sound files it will play. I always stick to mp3.
Fuzzygoat also makes an excellent point. I have not tried his approach in regards to sound so I do not know if it will solve your issue. It is similar to what you already have but with a slight change.
To start the sound:
SKAction *mySound = [SKAction repeatActionForever:[SKAction playSoundFileNamed:#"astroKitty 1.m4a" waitForCompletion:YES]];
[self runAction:mySound withKey:#"boogieDown"];
To stop the sound:
[self removeActionForKey:#"boogieDown"];
I have a piano application. It's working fine, with a little error. If I play several keys at the same time very fast, the sounds disappears for a couple of seconds, and receive the following message in the console
AudioQueueStart posting message to kill mediaserverd
Here is the relevant code:
-(IBAction)playNoteFromKeyTouch:(id) sender{
[NSThread detachNewThreadSelector:#selector(playNote:) toTarget:self withObject:[NSString stringWithFormat:#"Piano.mf.%#",[sender currentTitle]]];
}
-(void)playNote:(NSString *) note{
NSError *err;
NSString *path = [[NSBundle mainBundle] pathForResource:note ofType:#"aiff"];
AVAudioPlayer *p = [[AVAudioPlayer alloc ] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:&err];
p.delegate = self;
if (err) {
NSLog(#"%#", err);
}else{
[p prepareToPlay];
[p play];
}
}
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
{
[player release];
}
I have tested with Instruments and I don't have any memory leak. If somebody could have an idea to avoid this error it would be appreciated.
I suffer from a similar issue.
I spent ages trying to solve the issue, and I think my particular issue takes place when:
I'm in an AudioCategory that doesn't allow sound to play while the mute switch is on.
I start to play a sound (I actually don't do this in the app, but this is how I can reproduce reliably).
With the sound still playing, I switch to another AudioCategory that doesn't allow sound to play while the mute switch is on.
From this point onwards, I get 'posting message to kill mediaserverd' from what looks like various points in calls in the AudioSession API. The app hangs, the device hangs, and I struggle to get the device back to a normal running state.
According to this message it's the device's mute switch.
It turns out that having the iPad muted via the device's physical switch was
causing the problem with my app. As long as the button is not
switched on the problem does not occur.
Sheesh. How to programmatically override?
I "solved" the issue using SoundBankPlayer instead of AVAudioPlayer. SoundBanker info.