Checking whether the audio has ended playing in iOS - ios

I would like to check whether the audio has ended playing. If so, I need to change the button to a play button instead of a pause button. How do i do it in iOS?
My code looks like this:
-(void)playAudioFile:(BOOL)status
{
NSString *soundFilePath = [[NSBundle mainBundle] pathForResource:#"audio" ofType:#"mp3"];
NSURL *soundFileURL = [NSURL fileURLWithPath:soundFilePath];
NSError *error;
if(status)
{
if(!audioPlayer)
{
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:soundFileURL error:&error];
audioPlayer.currentTime = currentPlayTime;
audioPlayer.numberOfLoops = 0; //Infinite
audioDuration = audioPlayer.duration;
audioPlaySlider.minimumValue = 0;
audioPlaySlider.maximumValue = audioDuration;
audioPlaySlider.value = currentPlayTime;
[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:#selector(audioTimer:) userInfo:[NSDictionary dictionaryWithObject:audioPlayer forKey:#"playerObject"] repeats:YES];
}
[audioPlayer play];
if([audioPlayer rate] != 1.0 )
{
[audioPlayer play];
}
else
{
[self->audioPlayBtn setBackgroundImage:[UIImage imageNamed:#"playBtn.png"] forState:UIControlStateNormal];
}
NSLog(#"Play duration : %f",audioDuration);
}
else
{
if(audioPlayer && audioPlayer.playing)
{
[audioPlayer pause];
}
}
NSLog(#"Error for file : %#",error);
}
I tried this:
if([audioPlayer rate] != 1.0 )
{
[audioPlayer play];
}
else
{
[self->audioPlayBtn setBackgroundImage:[UIImage imageNamed:#"playBtn.png"] forState:UIControlStateNormal];
}
But not working.. Need some guidance...

Use the AVAudioPlayerDelegate's method
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
Your viewcontroller/class with the audioplayer instance must be the delegate for the audio player. The method will be called when the audio player finishes playback.
http://developer.apple.com/library/ios/#documentation/AVFoundation/Reference/AVAudioPlayerDelegateProtocolReference/Reference/Reference.html

Related

Get AVAudioPlayer delegate audioPlayerDidFinishPlaying when app was in background [duplicate]

So I have an app that plays a bunch of songs while the user can flip through a comic book. I use AVAudioPlayer and I have it set up to play the songs in a set order. So when one song finishes, the next one will play. This works flawlessly when the app is open. The problem occurs when the app is in the background. I set up the app to play in the background, and that works fine. So when the user presses the home screen the music continues to play. The problem occurs when the song ends, it is suppose to play the next song like it does when the app is open. Instead nothing happens. According to the my NSLog statements the correct methods are being called but nothing happens. Here is my code:
- (void)audioPlayerDidFinishPlaying: (AVAudioPlayer *)player successfully: (BOOL) flag {
NSLog(#"Song finished");
if ([songSelect isEqualToString: #"01icecapades"]) {
isPlay = #"yes";
songSelect = #"02sugarcube";
imageSelect = #"playbanner02";
[self performSelector:#selector(triggerSong) withObject:nil afterDelay:0];
[self performSelector:#selector(triggerBanner) withObject:nil afterDelay:0];
}
else if ([songSelect isEqualToString: #"02sugarcube"]) {
isPlay = #"yes";
songSelect = #"03bullets";
imageSelect = #"playbanner03";
[self performSelector:#selector(triggerSong) withObject:nil afterDelay:0];
[self performSelector:#selector(triggerBanner) withObject:nil afterDelay:0];
}
else if ([songSelect isEqualToString: #"03bullets"]) {
isPlay = #"yes";
songSelect = #"04satanama";
imageSelect = #"playbanner04";
[self performSelector:#selector(triggerSong) withObject:nil afterDelay:0];
[self performSelector:#selector(triggerBanner) withObject:nil afterDelay:0];
}
else if ([songSelect isEqualToString: #"04satanama"]) {
isPlay = #"yes";
songSelect = #"05uglyjoke";
imageSelect = #"playbanner05";
[self performSelector:#selector(triggerSong) withObject:nil afterDelay:0];
[self performSelector:#selector(triggerBanner) withObject:nil afterDelay:0];
}
else if ([songSelect isEqualToString: #"05uglyjoke"]) {
isPlay = #"yes";
songSelect = #"01icecapades";
imageSelect = #"playbanner01";
[self performSelector:#selector(triggerSong) withObject:nil afterDelay:0];
[self performSelector:#selector(triggerBanner) withObject:nil afterDelay:0];
}}
Above is the code that recognizes which song is playing, and sets the correct song next. Then it triggers another method that sets up the player.
- (void)triggerSong {
NSLog(#"triggerSong called");
NSString *path;
NSError *error;
// Path the audio file
path = [[NSBundle mainBundle] pathForResource:songSelect ofType:#"mp3"];
// If we can access the file...
if ([[NSFileManager defaultManager] fileExistsAtPath:path])
{
// Setup the player
player = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:&error];
//player = [initWithContentsOfURL:[NSURL fileURLWithPath:path] error:&error];
[player setDelegate: self];
// Set the volume (range is 0 to 1)
player.volume = 1.0f;
[player prepareToPlay];
[player setNumberOfLoops:0];
[player play];
NSLog(#"player play");
[error release];
player.delegate = self;
// schedules an action every second for countdown
[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:#selector(updateTimeLeft) userInfo:nil repeats:YES];
}}
Now I assuming this is not the best way to do this, but it works great when the app is in the foreground state. I've been looking through the documentation and I can't seem to find the cause of this problem. I was hoping somebody might be able to see an error to my approach. Like I said before, the two NSLogs in the triggerSong method are being called so I can't see why the AVAudioPlayer (player) is not being called.
Also I have the correct setting in my info.plist and I have this in my viewDidLoad:
//Make sure the system follows our playback status
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
[[AVAudioSession sharedInstance] setActive: YES error: nil];
Thanks for any insight. Much appreciated.
Relevant discussion
SHORT ANSWER:
You need this code in either your first view controller's init or viewDidLoad method:
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
LONG ANSWER W/ SAMPLE:
Here is my example. Like you, I began with an app that would play music in the background but could never continue playing after the first clip ended. I made a copy of the original Music.mp3 and named it Music2.mp3. My intention was to play Music2.mp3 as soon as Music.mp3 ended (audioPlayerDidFinishPlaying:). I goofed around with the background tasks for awhile until I got this working WITHOUT the background task:
-(id)init{
self = [super initWithNibName:#"MediaPlayerViewController" bundle:nil];
if(self){
//Need this to play background playlist
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
//MUSIC CLIP
//Sets up the first song...
NSString *musicPath = [[NSBundle mainBundle] pathForResource:#"Music" ofType:#"mp3"];
if(musicPath){
NSURL *musicURL = [NSURL fileURLWithPath:musicPath];
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:musicURL error:nil];
[audioPlayer setDelegate:self];
}
}
return self;
}
-(IBAction)playAudioFile:(id)sender{
if([audioPlayer isPlaying]){
//Stop playing audio and change test of button
[audioPlayer stop];
[sender setTitle:#"Play Audio File" forState:UIControlStateNormal];
}
else{
//Start playing audio and change text of button so
//user can tap to stop playback
[audioPlayer play];
[sender setTitle:#"Stop Audio File" forState:UIControlStateNormal];
}
}
-(void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag{
[audioButton setTitle:#"Play Audio File" forState:UIControlStateNormal];
[playRecordingButton setTitle:#"Play Rec File" forState:UIControlStateNormal];
//PLAY THE SECOND SONG
NSString *musicPath2 = [[NSBundle mainBundle] pathForResource:#"Music2" ofType:#"mp3"];
if(musicPath2){
NSURL *musicURL2 = [NSURL fileURLWithPath:musicPath2];
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:musicURL2 error:nil];
[audioPlayer setDelegate:self];
NSLog(#"Play it again: \n%#", musicPath2);
[audioPlayer play];
}
}
The end result is that my app is now playing Music2.mp3 on a continuous loop, even if the app is in the background.
Just to confirm what Squatch said, this is also the solution in Swift:
UIApplication.sharedApplication().beginReceivingRemoteControlEvents()
OS X exhibits the same problem using AVAudioPlayer, however UIApplication is an iOS-only construct. OS X requires using NSApplication instead, but NSApplication doesn't return until the application is terminating so we need to use threads. As a bonus, there's an assert() somewhere in the depths of NSApplication that demands the main thread.
This hybrid C++/Objective C function is one workaround for this OS X issue:
void do_the_dumb (void real_application(void)) {
std::thread thread ([real_application]() {
real_application();
[[NSApplication sharedApplication] terminate: [NSApplication sharedApplication]];
});
[[NSApplication sharedApplication] run];
thread.join();
};

How to Play AVAudio player from Starting?

I was Created AVAudio Player, its playing perfectly,Click the play button song is playing and its shows pause button,click pause button song is paused and its shows play button,but click the play button is playing from starting onwards.i want play resume song. how to control this issue. this is my code , please check once's.
-(void)playAudio
{
// [progreetimer invalidate];
// if([audioPlayer isPlaying]==YES)`enter code here`
if(self.isPlaying)
{
[self.play setBackgroundImage:[UIImage imageNamed:#"audioplayer_play.png"]
forState:UIControlStateNormal];
NSLog(#"Pausing Music");
if (self.progreetimer) {
[self.progreetimer invalidate];
progreetimer =nil;
}
[audioPlayer pause];
self.isPlaying = NO;
}
else {
// Init audio with playback capability
[self.play setBackgroundImage:[UIImage imageNamed:#"audioplayer_pause.png"] forState:UIControlStateNormal];
// NSString *urlstr = #"http://jesusredeems.in/media/Media Advt/mp3_player/Songs/viduthalaiyin geethangal_vol1/93.Ellame Koodum.mp3";
NSString *urlstr =#"http://www.abstractpath.com/files/audiosamples/sample.mp3";
urlstr = [urlstr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *url = [NSURL URLWithString:urlstr];
NSData *data = [NSData dataWithContentsOfURL:url];
audioPlayer = [[AVAudioPlayer alloc] initWithData:data error:nil];
audioPlayer.volume = 1.9f;
// [audioPlayer prepareToPlay];
SongProgressBar.maximumValue = [audioPlayer duration];
SongProgressBar.value = 0.0;
NSLog(#"Playing music");
//start a timer to update the time label display
self.progreetimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self
selector:#selector(updateTime:) userInfo:nil repeats:YES];
self.progreetimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self
selector:#selector(updateSlider) userInfo:nil repeats:YES];
[progreetimer fire];
audioPlayer.delegate=self;
[audioPlayer play];
self.isPlaying = YES;
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.SongProgressBar.minimumValue = 30;
self.SongProgressBar.maximumValue = 30;
[self.SongProgressBar setThumbImage:[UIImage imageNamed:#"thumbslider.png"]
forState:UIControlStateNormal];
// [self.SongProgressBar setThumbImage:[UIImage imageNamed:#"slider_icon.png"]
// forState:UIControlStateHighlighted];
[self.SongProgressBar setMinimumTrackImage:[UIImage imageNamed:#"slider_max.png"]
forState:UIControlStateNormal];
[self.SongProgressBar setMaximumTrackImage:[UIImage imageNamed:#"slider_icon.png"]
forState:UIControlStateNormal];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[audioPlayer pause]; // Or pause
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[audioPlayer play];
}
- (IBAction)songprogressbar:(id)sender {
// Fast skip the music when user scroll the UISlider
[audioPlayer stop];
[audioPlayer setCurrentTime:SongProgressBar.value];
[audioPlayer prepareToPlay];
[audioPlayer play];
}
- (IBAction)backword:(id)sender {
if ([self.audioPlayer isPlaying]) {
NSTimeInterval desiredTime = audioPlayer.currentTime -15.0f;
if (desiredTime < 0) {
audioPlayer.currentTime =0.0f;
} else {
audioPlayer.currentTime = desiredTime;
}
}
}
- (IBAction)play:(id)sender {
[self playAudio];
}
- (void)updateSlider {
// Update the slider about the music time
SongProgressBar.value = audioPlayer.currentTime;
}
- (void)setCurrentAudioTime:(float)value {
[self.audioPlayer setCurrentTime:value];
}
//Stops the timer when the music is finished
- (void)audioPlayerDidFinishPlaying : (AVAudioPlayer *)player successfully : (BOOL)flag {
// Music completed
if (flag) {
[progreetimer invalidate];
NSLog(#"Finished playing the song");
}
}
- (IBAction)forword:(id)sender {
if ([audioPlayer isPlaying]) {
NSTimeInterval desiredTime = audioPlayer.currentTime +15.0f;
if (desiredTime < audioPlayer.duration) {
audioPlayer.currentTime = desiredTime;
}
}
}
- (IBAction)volume:(id)sender {
audioPlayer.volume=volume.value;
}
-(NSString*)timeFormat:(float)value{
float minutes = floor(lroundf(value)/60);
float seconds = lroundf((value) - (minutes * 60));
int roundedSeconds = lroundf(seconds);
int roundedMinutes = lroundf(minutes);
NSString *time = [[NSString alloc]
initWithFormat:#"%d:%02d",
roundedMinutes, roundedSeconds];
return time;
}
- (void)updateTime:(NSTimer *)timer {
self.starttimer.text = [NSString stringWithFormat:#"%#",
[self timeFormat: ceilf(audioPlayer.currentTime)]];
self.endtimer.text = [NSString stringWithFormat:#"-%#", [self timeFormat: (audioPlayer.duration - ceilf(audioPlayer.currentTime))]];
}
You should try this. see else part of method
-(void)playAudio
{
// [progreetimer invalidate];
// if([audioPlayer isPlaying]==YES)`enter code here`
if(self.isPlaying)
{
//Code to pause audioPlayer
[audioPlayer pause];
self.isPlaying = NO;
}
else
{
if(audioPlayer.url != nil && audioPlayer.duration != 0)
{
[audioPlayer play];
}
else
{
//Code to add new audioPlayer
}
}
}
Use the following code
AVAudioPlayer *newPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL: fileURL error: nil];
[player prepareToPlay];
player.currentTime = 0;
[player play];

how to play audioplayer in ios using AVAudioplayer

I am trying to create AVAudioPlayer Programatically.I Have small issue if i play audioplayer.
I am displaying 12 audio items in UITableview.If i click first item that corresponding song will play.I should not click any pass button.i click back button and click second item.if i click second item the audio view controller will display.I click play button the song display.In first song and second song play simultaneously.This is my issue.Please help me anybody.
-(void)playOrPauseButtonPressed:(id)sender
{
if(playing==NO)
{
[playButton setBackgroundImage:[UIImage imageNamed:#"Pause.png"] forState:UIControlStateNormal];
// Here Pause.png is a image showing Pause Button.
NSError *err=nil;
AVAudioSession *audioSession=[AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryPlayback error:nil];
NSLog(#"%# %d",urlsArray,selectedIndex);
NSString *sourcePath=[urlsArray objectAtIndex:selectedIndex];
NSData *objectData=[NSData dataWithContentsOfURL:[NSURL URLWithString:sourcePath]];
audioPlayer = [[AVAudioPlayer alloc] initWithData:objectData error:&err];
audioPlayer.numberOfLoops = 0;
[audioPlayer prepareToPlay];
audioPlayer.delegate=self;
[audioPlayer play];
playing=YES;
}
else if (playing==YES)
{
[playButton setBackgroundImage:[UIImage imageNamed:#"play.png"] forState:UIControlStateNormal];
[audioPlayer pause];
playing=NO;
}
if (self.audioPlayer)
{
[self updateViewForPlayerInfo];
[self updateViewForPlayerState];
[self.audioPlayer setDelegate:self];
}
}
-(void)updateViewForPlayerInfo
{
self.songDuration.text = [NSString stringWithFormat:#"%d:%02d", (int)self.audioPlayer.duration / 60, (int)self.audioPlayer.duration % 60, nil];
NSLog(#"%f", self.audioPlayer.duration);
self.progressBar.maximumValue = self.audioPlayer.duration;
self.volumeSlider.value = self.audioPlayer.volume;
}
-(void)updateViewForPlayerState
{
[self updateCurrentTime];
if (self.updatedTimer)
{
[self.updatedTimer invalidate];
}
if (self.audioPlayer.playing)
{
self.updatedTimer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:#selector(updateCurrentTime) userInfo:self.audioPlayer repeats:YES];
}
}
-(void)updateCurrentTime
{
//NSLog(#"self.audioPlayer.currentTime = %f", self.audioPlayer.currentTime);
self.currentTime.text = [NSString stringWithFormat:#"%d:%02d", (int)self.audioPlayer.currentTime / 60, (int)self.audioPlayer.currentTime % 60, nil];
self.progressBar.value = self.audioPlayer.currentTime;
}
-(void)volumeSliderMoved:(UISlider *)sender
{
self.audioPlayer.volume=[sender value];
}
before creating a new instance of AVAudioPlayer, deallocate or nil the existing instance of player by using following lines
sourcePath=Nil;
[audioPlayer stop];
audioPlayer = Nil;
Stop the player when you go back. Maybe in ViewWillDisappear or before you create a new instance of audioplayer, you can call
if(self.audioplayer) {
[self.audioPlayer stop];
self.audioPlayer = nil;
}
Before initializing the AVAudioPlayer remove all the instances that are running before.
//YOUR STUFF
NSString *sourcePath=[urlsArray objectAtIndex:selectedIndex];
NSData *objectData=[NSData dataWithContentsOfURL:[NSURL URLWithString:sourcePath]];
for (AVAudioPlayer *a in urlsArray)
[a stop];
audioPlayer = [[AVAudioPlayer alloc] initWithData:objectData error:&err];
audioPlayer.numberOfLoops = 0;
//REST STUFF

Multiple audio files playing at once in iOS App

I have an iOS app which works like this:
First view
3 buttons that link to different views, each has its own audio file within
Imagine user opens one view, and starts to play the audio file. When they navigate around the app, the audio file still plays which is fine, Im happy with that.
However, if user then opens the second audio file and presses play, it plays on top of the first one so 2 audios are playing together.
How do I tell the code that if another play button is pressed it should stop the first audio file that is playing??
I am using AVFoundation framework to do this
Code is as follows:
NSString *stringPath = [[NSBundle mainBundle]pathForResource:#"01" ofType:#"MP3"];
NSURL *url = [NSURL fileURLWithPath:stringPath];
NSError *error;
avPlayer = [[AVAudioPlayer alloc]initWithContentsOfURL:url error:&error];
[avPlayer setNumberOfLoops:2];
[avPlayer setVolume:self.sliderVolumeOutlet.value];
[NSTimer scheduledTimerWithTimeInterval:.1 target:self selector:#selector(updateMyProgress) userInfo:nil repeats:YES];
-(void)updateMyProgress
{
float progress = [avPlayer currentTime]/[avPlayer duration];
self.myProgressView.progress = progress;
}
- (IBAction)sliderVolumeAction:(id)sender {
UISlider *mySlider = sender;
[avPlayer setVolume:mySlider.value];
}
- (IBAction)stopButton:(id)sender {
[avPlayer stop];
[avPlayer setCurrentTime:0];
}
- (IBAction)pauseButton:(id)sender {
[avPlayer pause];
}
- (IBAction)playButton:(id)sender {
[avPlayer play];
}
- (IBAction)backButtonEvent:(id)sender {
[self dismissViewControllerAnimated:YES completion:NULL];
}
You can check whether it is playing the previous track or not by if ([AVPlayer rate] != 0.0)
If it is playing then you can either add the next track into queue or just use this function to replace current track with the new one - (void)replaceCurrentItemWithPlayerItem:(AVPlayerItem *)item
Perhaps creating some sort of playSound function would be better suited for this. Something like this:
- (void)playSoundWithFileName:(NSString *)fileName andExtension:(NSString *)extension {
NSString *stringPath = [[NSBundle mainBundle]pathForResource:fileName ofType:extension];
NSURL *url = [NSURL fileURLWithPath:stringPath];
NSError *error;
if (avPlayer) {
[avPlayer stop];
avPlayer = nil;
}
avPlayer = [[AVAudioPlayer alloc]initWithContentsOfURL:url error:&error];
if (error)
NSLog(#"Error");
else {
[avPlayer setNumberOfLoops:2];
[avPlayer setVolume:self.sliderVolumeOutlet.value];
[avPlayer play];
}
}
Use:
[self playSoundWithFileName:#"01" andExtension:#"MP3"];
[NSTimer scheduledTimerWithTimeInterval:.1 target:self selector:#selector(updateMyProgress) userInfo:nil repeats:YES];
and call -(void)playSoundWithFileName whenever you want to play another sound.
Or if you were using the AVPlayer class:
- (void)playSoundWithFileName:(NSString *)fileName andExtension:(NSString *)extension {
NSString *stringPath = [[NSBundle mainBundle]pathForResource:fileName ofType:extension];
NSURL *url = [NSURL fileURLWithPath:stringPath];
AVPlayerItem *item = [AVPlayerItem playerItemWithURL:url];
if (avPlayer)
[avPlayer replaceCurrentItemWithPlayerItem:item];
else
avPlayer = [AVPlayer playerWithPlayerItem:item];
[avPlayer setVolume:self.sliderVolumeOutlet.value];
[avPlayer play];
}
Though the latter doesn't allow you set a number of loops.

AVAudioPlayer pausing issue

In my project, I have an AVAudioPlayer which plays a song. After I pause it, and hit play again, it starts over instead of playing where I paused. Why is that happening?
Also, when I press play for the first time, it loads the song about 3-4 seconds. I thought I solved it by loading it on the other thread, but it still loads too slow (at least the view doesn't freeze anymore). How can I fix that? Here's the code:
- (IBAction)play:(id)sender {
songIsCurrentlyPaused = NO;
if(songIsCurrentlyPaused==YES){
    [self.background play];
} else {
playQueue = dispatch_queue_create("volume_change", NULL);
dispatch_async(playQueue, ^{ NSString *filePath =
[[NSBundle mainBundle]pathForResource:#"some_song" ofType:#"mp3"];
NSURL *fileURL = [[NSURL alloc] initFileURLWithPath:filePath];
self.background = [[AVAudioPlayer alloc] initWithContentsOfURL:fileURL error:nil];
self.background.delegate = self;
[self.background setNumberOfLoops:1];
[self.background setVolume:0.5];
[self.background play]; });
[trackNameLabel setText:#"Currently playing :\n some_song"];
self.timer = [NSTimer scheduledTimerWithTimeInterval:0.25 target:self selector:#selector(updateProgressBar) userInfo:nil repeats:YES];
    }
}
- (IBAction)pause:(id)sender {
songIsCurrentlyPaused = YES;
[self.background pause];
[trackNameLabel setText:#"Currently playing : some_song (paused)"];
[self.progressBar setProgress:self.background.currentTime/self.background.duration animated:YES];
}
Thanks!
You're setting songIsCurrentlyPaused to NO at the beginning of play:
Try commenting it out:
- (IBAction)play:(id)sender {
//songIsCurrentlyPaused = NO;
if(songIsCurrentlyPaused==YES){
    [self.background play];
} else {
playQueue = dispatch_queue_create("volume_change", NULL);
dispatch_async(playQueue, ^{ NSString *filePath =
[[NSBundle mainBundle]pathForResource:#"some_song" ofType:#"mp3"];
NSURL *fileURL = [[NSURL alloc] initFileURLWithPath:filePath];
self.background = [[AVAudioPlayer alloc] initWithContentsOfURL:fileURL error:nil];
self.background.delegate = self;
[self.background setNumberOfLoops:1];
[self.background setVolume:0.5];
[self.background play]; });
[trackNameLabel setText:#"Currently playing :\n some_song"];
self.timer = [NSTimer scheduledTimerWithTimeInterval:0.25 target:self selector:#selector(updateProgressBar) userInfo:nil repeats:YES];
    }
}
- (IBAction)pause:(id)sender {
songIsCurrentlyPaused = YES;
[self.background pause];
[trackNameLabel setText:#"Currently playing : some_song (paused)"];
[self.progressBar setProgress:self.background.currentTime/self.background.duration animated:YES];
}
If you want to get rid of that initial pause you're gonna have to completely reorganize your player setup. Initialize it before user can hit play button and also call:
[self.background prepareToPlay];
which will preload the song. Also move songIsCurrentlyPaused = NO; to some earlier place in code.
EDIT:
To get rid of initial delay you should move your initializing code to somewhere like loadView or viweDidLoad.
//initialization code
NSString *filePath = [[NSBundle mainBundle]pathForResource:#"some_song" ofType:#"mp3"];
NSURL *fileURL = [[NSURL alloc] initFileURLWithPath:filePath];
self.background = [[AVAudioPlayer alloc] initWithContentsOfURL:fileURL error:nil];
self.background.delegate = self;
[self.background setNumberOfLoops:1];
[self.background setVolume:0.5];
[self.background prepareToPlay];
Now this may cause a lag in UI display so you might wan't to consider preloading data
in background thread.
Your IBAction methods should then be modified:
- (IBAction)play:(id)sender
{
if (songIsCurrentlyPaused==YES)
{
[self.background play];
}
else
{
playQueue = dispatch_queue_create("volume_change", NULL);
dispatch_async(playQueue, ^{
[self.background setCurrentTime: 0.0];
[self.background play];
});
[self.progressBar setProgress:0.0 animated:YES];
[trackNameLabel setText:#"Currently playing :\n some_song"];
self.timer = [NSTimer scheduledTimerWithTimeInterval:0.25 target:self selector:#selector(updateProgressBar) userInfo:nil repeats:YES];
}
songIsCurrentlyPaused = NO;
}
- (IBAction)pause:(id)sender
{
songIsCurrentlyPaused = YES;
[self.background pause];
[trackNameLabel setText:#"Currently playing : some_song (paused)"];
[self.progressBar setProgress:self.background.currentTime/self.background.duration animated:YES];
}

Resources