I have this code:
int ran = 1 + arc4random() % 18;
NSString *soundFileIs=[NSString stringWithFormat:#"ton%i.mp3",ran];
NSString *paths = [[NSBundle mainBundle] resourcePath];
NSString *audioFile = [paths stringByAppendingPathComponent:soundFileIs];
NSData *cdata =[NSData dataWithContentsOfFile:audioFile];
audioPlayer = [[AVAudioPlayer alloc] initWithData:cdata error:nil];
audioPlayer.delegate = self;
[audioPlayer play];
When I shake device, it plays random my 18 sounds. How can I make to stop previously playing sound, and play next sound? Everything works great, just I hear 1st sound when I shake for first time, when I shake 2nd time, i hear 1st and 2nd sound playing if my 1st sound didn't stop play. Thank you.
Before playing anything, check to see if it's already playing and call stop. Your code will then be:
int ran = 1 + arc4random() % 18;
NSString *soundFileIs=[NSString stringWithFormat:#"ton%i.mp3",ran];
NSString *paths = [[NSBundle mainBundle] resourcePath];
NSString *audioFile = [paths stringByAppendingPathComponent:soundFileIs];
NSData *cdata =[NSData dataWithContentsOfFile:audioFile];
if (audioPlayer.playing)
[audioPlayer stop];
audioPlayer = [[AVAudioPlayer alloc] initWithData:cdata error:nil];
audioPlayer.delegate = self;
[audioPlayer play];
when you shake that time call
[audioPlayer stop];
first check audioplayer is playing a sound or not if not then don't call stop methord if playing then 1st call stop methord
call
if([audioPlayer playing])
[audioPlayer stop];
method on shaking the device to stop the current song.
then use this delegate method to play the next song.
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
Related
My previous code was
- (void) playaudio: (id) sender
{
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"Theme"
ofType:#"mp3"];
NSURL *fileURL = [[NSURL alloc] initFileURLWithPath:filePath];
self.audioPlayer = [[AVAudioPlayer alloc]
initWithContentsOfURL:fileURL error:nil];
self.audioPlayer.currentTime = 0;
[self.audioPlayer play];
}
- (void)pause: (id)sender
{
[audioPlayer pause];
}
- (void)stop: (id)sender
{
[audioPlayer stop];
}
In the above code pause button was acting as stop button rather than pause where it was supposed to resume the audio file.
Now i have added simple statements to my code it is working to some extent but still not upto my expectations.
What happening now is when you play audio file and click on pause button nothing happens but when you click on the stop button it stops playing audio file and then when you press the pause button it resumes the audio file from where it was stopped by pressing stop button. Why is that when you press stop buttons only then pause button functions but not before that. I don't get this why?
Any ideas why this is happening
- (void)pause: (id)sender
{
[audioPlayer pause];
[audioPlayer prepareToPlay];
[audioPlayer play];
}
- (void) stop: (id) sender
{
[audioPlayer stop];
}
If anyone have any ideas that why this is happening. Will appreciate help.
Thanks in advance.
You shouldn't be recreating the audio file every time you play it. Here is how you could do this:
- (void) playaudio: (id) sender
{
if(self.audioPlayer == nil) {
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"Theme"
ofType:#"mp3"];
NSURL *fileURL = [[NSURL alloc] initFileURLWithPath:filePath];
self.audioPlayer = [[AVAudioPlayer alloc]
initWithContentsOfURL:fileURL error:nil];
self.audioPlayer.currentTime = 0; //this could be outside the if if you want it to start over when they hit play
}
[self.audioPlayer play];
}
- (void)pause: (id)sender
{
if([audioPlayer isPlaying]){
[audioPlayer pause];
} else {
[audioPlayer play];
}
}
- (void)stop: (id)sender
{
[audioPlayer stop];
}
I'm trying to create a sort of audio playlist using AVAudioPlayer. So I've used the following code:
.h
<AVAudioPlayerDelegate>
{
AVAudioPlayer *audioPlayer;
}
#property (nonatomic, retain) AVAudioPlayer *audioPlayer;
.m
#synthesize audioPlayer;
- (void)viewDidLoad
{
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
audioPlayer.numberOfLoops = 0;
audioPlayer.delegate = self;
[audioPlayer play];
}
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
{
if (flag)
{
[player release];
currentSong = currentSong + 1;
NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:[songs objectAtIndex:currentSong] ofType:#"mp3"]];
artist.text = [artists objectAtIndex:currentSong];
song.text = [songs objectAtIndex:currentSong];
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
audioPlayer.delegate = self;
audioPlayer.numberOfLoops = 0;
[audioPlayer initWithContentsOfURL:url error:nil];
[audioPlayer play];
}
}
This works for two songs, but after this there isn't any audio. Any idea why this is?
Thanks,
Denis
In this line you are initing an audio player:
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
Then you are initing it again in this line (unneeded duplication, and probably an additional retain):
[audioPlayer initWithContentsOfURL:url error:nil];
Then the next time the loop comes around, even though you release it using the line
[player release];
…there is a problem as it is still in memory, tying up a hardware codec or wasting resources. Try removing the second initWithContents… line as it is unnecessary.
1.Just maintain an array.
2.Once you create an instance of audioPlayer - add to the array and call play and release the instance of audioPlayer(since it will get retained once you added to array).
3.In audioPlayerDidFinishPlaying remove the audioPlayer from that array.
So you can play multiple files at a time
I have 6 sounds on one view.
However I want it so that I can play more than one at once, So you tap sound 1 (sound 1 is playing) then sound 2 plays. while sound 1 is still playing.
But at the moment I press sound 1 (sound 1 plays), press sound 2 (sound 2 plays, but sound 1 stops)
Here is the code for the audio part.
- (IBAction)oneSound:(id)sender; {
NSString *path = [[NSBundle mainBundle] pathForResource:#"1" ofType:#"wav"];
if (theAudio) [theAudio release];
theAudio = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
theAudio.delegate = self;
[theAudio play];
volumeTimer = [NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:#selector(updateVolume) userInfo:nil repeats:YES];
}
- (IBAction)twoSound:(id)sender; {
NSString *path = [[NSBundle mainBundle] pathForResource:#"2" ofType:#"wav"];
if (theAudio) [theAudio release];
theAudio = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
theAudio.delegate = self;
[theAudio play];
volumeTimer = [NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:#selector(updateVolume) userInfo:nil repeats:YES];
}
There is some important code missing, but it looks as if theAudio is a global you are using to manage the playing of your sounds. Since you destroy it whenever a sound is played whatever is currently playing will stop in preparation for the next sound.
There are several ways to fix this, one being that each sound gets its own unique AVAudioPlayer instance.
don't release the player just because it exists. release when finished playing
You should implement this in the app delegate or a property of the app delegate so that the delegate reference remains valid if you pop the view.
You should not need to do this for each voice. Each voice will initial the player with a different filename or URL. You gain this by making sure that you will release when finished playing. The other thing to take care of is releasing players if the player doesn't finish because of an interruption.
#pragma mark -
#pragma mark Audio methods
-(void)playNote:(NSInteger)noteNumber {
NSString *soundFilePath =
[[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:#"%i", noteNumber ]
ofType: #"caf"];
NSURL *fileURL = [[NSURL alloc] initFileURLWithPath: soundFilePath];
AVAudioPlayer *playerToPrepare = [[AVAudioPlayer alloc] initWithContentsOfURL:fileURL
error:nil];
[fileURL release];
[playerToPrepare prepareToPlay];
[playerToPrepare setDelegate: self];
[playerToPrepare play];
}
#pragma mark -
#pragma mark AVAudioPlayer delegate methods
- (void) audioPlayerDidFinishPlaying: (AVAudioPlayer *) playerThatFinished
successfully: (BOOL) completed {
if (completed) {
[playerThatFinished release];
}
}
You can declare and use:
AVAudioPlayer *theAudio1; // for file 1.wav
AVAudioPlayer *theAudio2; // for file 2.wav
...
AVAudioPlayer *theAudio6; // etc.
instead of releasing and reusing just one AVAudioPlayer.
In my project i am trying to play when my image is moving from one side to another side of half of horizontal screen .
i am trying like this
sample code
- (void)accelerometer:(UIAccelerometer *)acel
didAccelerate:(UIAcceleration *)acceleration {
if (imageView.center.x + translation.x > 160 - ballRadius) {
NSString *path = [[NSBundle mainBundle] pathForResource:#"warning" ofType:#"m4r"];
NSURL *file = [[NSURL alloc] initFileURLWithPath:path];
AVAudioPlayer *p =[[AVAudioPlayer alloc]
initWithContentsOfURL:file error:nil];
[file release];
self.player = p;
[p release];
[player prepareToPlay];
[player setDelegate:self];
[self.player play];
}
}
but my app is crashing when i am trying like this
can any one please help me
regards
Where is your app crashing? Did you use the Debugger to determine where?
How many times per second is this accelerometer being called? If you are trying to start the same sound that many times, it may be too much for the AVPlayer.
I'm calling playSoundFromBundle from the code below to play sounds (aif files). I have a sound that does a single click and then a fading sound. Both sounds are in the same file. Sometimes I get two clicks and then the fade. Meaning, click, click...fade. A single click isn't what should play. I'm guessing the sound starts (click sound), gets interrupted and then restarts (full sound...click/fade) because of other processing that may be going on. It seems random when it will occur. I put the sound on its own thread to try and avoid the double clicking. Is there anything else I can do to ensure the sound plays correctly?
- (void) playSoundFromBundleThreaded:(NSArray*)arr{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSString *fileName = (NSString*)[arr objectAtIndex:0];
NSString *fileExt = (NSString*)[arr objectAtIndex:1];
NSError *err;
AVAudioPlayer *newPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath: [[NSBundle mainBundle] pathForResource: fileName ofType: fileExt inDirectory:#"/"]] error: &err];
self.audioPlayer = newPlayer;
self.audioPlayer.numberOfLoops = 0;
self.audioPlayer.volume = .5;
if (self.audioPlayer == nil)
{
NSLog(#"Problem initializing Sound - %#", [err description]);
}
else
{
[self.audioPlayer play];
}
[newPlayer release];
[pool release];
}
- (void) playSoundFromBundle:(NSString*)fileName fileExtension:(NSString*)fileExt{
NSArray *arr = [NSArray arrayWithObjects:fileName, fileExt, nil];
[NSThread detachNewThreadSelector: #selector(playSoundFromBundleThreaded:) toTarget:self withObject:arr];
}
No idea if this would work, but check out the Audio Session stuff. It's intended to manage things like whether the playing of other sounds (such as by the music player) will interrupt audio from your application.