Move audio player 5 second fast-rewind & fast-forward - iphone

I know this is a duplicate question but I didn't find out the exact answer. I am working with AVAudioPlayer. Now I have two buttons forward & rewind. When the user will tap the forward button the audio will move 5 second forward & when the user will tap the rewind button the audio will move 5 second rewind. How can i do this exactly? Thanks in advance for any help.

Put below methods for forward and rewind player time
- (IBAction)btnForwardClicked:(id)sender
{
int currentTime = [player currentTime];
[player setCurrentTime:currentTime+5];
}
- (IBAction)btnBackwardClicked:(id)sender
{
int currentTime = [player currentTime];
[player setCurrentTime:currentTime-5];
}
here player is avaudio player's object
AVAudioPlayer *player;

- (IBAction)btnForwardClicked:(id)sender
{
NSTimeInterval *time = [player currentTime];
time+=SKIP_TIME;
//for reverse time-=SKIP_TIME
//SKIP_TIME is time which is jumped i-e 5 seconds
[player setCurrentTime:time];
}

Related

AVPlayer buffering, pausing notification, and poster frame

I have some questions related to AVPlayer which are:
When we pause the AVPlayer through [player pause] does the AVPlayer keep buffering the video from the network or does it just stop? I couldn't get any info related to this in apple's documentation. Also, is it possible to force the AVPlayer to keep buffering while in pause, so that if we have the paused video is in waiting for the first video to be ended then we wouldn't find any gap in between the videos?
On pausing the AVPlayer can we have any event on [player pause].
Can we show still image on AVPlayer for some seconds?
Thanks
1) AVPlayer will buffer the video in several cases, none cleary documented. I'd say you can expect buffering when you init the video, and when you replace the current item.
You can observe currentItem.loadedTimeRanges to know what's going on. That property will tell you which video time ranges has been loaded.
Also, there is a few other currentItem properties that may help you: playbackLikelyToKeepUp, playbackBufferFull and playbackBufferEmpty.
Achieving a perfect gapless playback is not easy.
/* player is an instance of AVPlayer */
[player addObserver:self
forKeyPath:#"currentItem.loadedTimeRanges"
options:NSKeyValueObservingOptionNew
context:kTimeRangesKVO];
In observeValueForKeyPath:ofObject:change:context::
if (kTimeRangesKVO == context) {
NSArray *timeRanges = (NSArray *)[change objectForKey:NSKeyValueChangeNewKey];
if (timeRanges && [timeRanges count]) {
CMTimeRange timerange = [[timeRanges objectAtIndex:0] CMTimeRangeValue];
NSLog(#" . . . %.5f -> %.5f", CMTimeGetSeconds(timerange.start), CMTimeGetSeconds(CMTimeAdd(timerange.start, timerange.duration)));
}
}
2) Just keep an eye on player.rate.
[player addObserver:self
forKeyPath:#"rate"
options:NSKeyValueObservingOptionNew
context:kRateDidChangeKVO];
Then in your observeValueForKeyPath:ofObject:change:context::
if (kRateDidChangeKVO == context) {
NSLog(#"Player playback rate changed: %.5f", player.rate);
if (player.rate == 0.0) {
NSLog(#" . . . PAUSED (or just started)");
}
}
3) You can build a movie of a given length using a still image but it's easier to use a regular UIImageView on top of the player. Hide/show it when needed.
Sample project: feel free to play with the code I wrote to support my answer.

How to perform operations when playing sound in iPhone?

I play a MP3 in my iPhone app using AVAudioPlayer; i need to perform some operations at certain times (say 30th seconds, 1 minute); is there a way to invoke callback functions based on mp3 playing time?
I believe the best solution is to start an NSTimer as you start the AVAudioPlayer playing. You could set the timer to fire every half second or so. Then each time your timer fires, look at the currentTime property on your audio player.
In order to do something at certain intervals, I'd suggest you kept an instance variable for the playback time from last time your timer callback was called. Then if you had passed the critical point between last callback and this, do your action.
So, in pseudocode, the timer callback:
Get the currentTime of your AVAudioPlayer
Check to see if currentTime is greater than criticalPoint
If yes, check to see if lastCurrentTime is less than criticalPoint
If yes to that too, do your action.
Set lastCurrentTime to currentTime
If you're able to use AVPlayer instead of AVAudioPlayer, you can set boundary or periodic time observers:
// File URL or URL of a media library item
AVPlayer *player = [[AVPlayer alloc] initWithURL:url];
CMTime time = CMTimeMakeWithSeconds(30.0, 600);
NSArray *times = [NSArray arrayWithObject:[NSValue valueWithCMTime:time]];
id playerObserver = [player addBoundaryTimeObserverForTimes:times queue:NULL usingBlock:^{
NSLog(#"Playback time is 30 seconds");
}];
[player play];
// remove the observer when you're done with the player:
[player removeTimeObserver:playerObserver];
AVPlayer documentation:
http://developer.apple.com/library/ios/#documentation/AVFoundation/Reference/AVPlayer_Class/Reference/Reference.html
I found this link describing a property property which seems to indicate you can get the current playback time.
If the sound is playing, currentTime is the offset of the current
playback position, measured in seconds from the start of the sound. If
the sound is not playing, currentTime is the offset of where playing
starts upon calling the play method, measured in seconds from the
start of the sound.
By setting this property you can seek to a specific point in a sound
file or implement audio fast-forward and rewind functions.
To check the time and perform your action you can simply query it:
if (avAudioPlayerObject.currentTime == 30.0) //You may need a more broad check. Double may not be able to exactly represent 30.0s
{
//Do Something
}
with multithreading your goal is simple, just do like this :
1 : in your main thread create a variable for storing time passed
2 : create new thread like "checkthread" that check each 30-20 sec(as you need)
3 : if the time passed is what you want do the callback
Yes Sure you can ...it's tricky i hope it works for you but it works for me ..
1- you play your mp3 file.
2- [self performSelector:#selector(Operation:) withObject:Object afterDelay:30];
then the function
-(void)Operation:(id)sender;
called; so you fired function after 30 second of mp3 file .. you can make many of function based on time you want..
3- there is other solution using timers
[NSTimer scheduledTimerWithTimeInterval:0 target:self selector:#selector(CheckTime:) userInfo:nil repeats:YES];
it will fire function called Check Time
-(void)CheckTime:(id)sender{
if (avAudioPlayerObject.currentTime == 30.0)
{
//Do Something
//Fire and function call such
[self performSelector:#selector(Operation:) withObject:Object]
}
}
then you can change time interval you want and repeats is for you to control repeat this action every 5 seconds or not..
Hope that helpful..
Thanks
i think ,you want to play different sound-files after 30sec then use this code :
1) all sound-files put in Array and then retrieve from document directory
2)then try this:
-(IBAction)play_sound
{
BackgroundPlayer=[[AVAudioPlayer alloc]initWithContentsOfURL:[NSURL fileURLWithPath:[[NSBundle mainBundle]pathForResource:[Arr_tone_selected objectAtIndex:j]ofType:#"mp3"]]error:NULL];
BackgroundPlayer.delegate=self;
[BackgroundPlayer play];
}
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
{
[BackgroundPlayer stop];
j++;
[self performSelector:#selector(play_sound) withObject:Object afterDelay:30];
}

Should I stop current AVPlayer instance when playing music from another URL?

I just created AVPlayer and it plays music well. I have two questions
How to play another music from another URL (should I stop current player?)
How to show current time of the song in UISlider (actually is it a method that called when the song is playing?)
Use -[AVPlayer replaceCurrentItemWithPlayerItem] to replace the current playing item reusing the player instance. You can create an item with an URL or with an asset.
In order to know when a given item finishes playing use the notification AVPlayerItemDidPlayToEndTimeNotification.
Use -[AVPlayer addPeriodicTimeObserverForInterval] to perform some action periodically while the player is playing. See this example:
[self.player addPeriodicTimeObserverForInterval:CMTimeMakeWithSeconds(0.1, 100)
queue:nil
usingBlock:^(CMTime time) {
<# your code will be called each 1/10th second #>
}];
1) If you used - (id)initWithURL:(NSURL *)URL then you should stop player with pause, dealloc it and create new instance.
AVPlayer *player = [AVPlayer alloc] initWithURL:[NSURL URLWithString:#"http:/someurl.com"]];
[player play];
[player pause];
[player release];
player = [AVPlayer alloc] initWithURL:[NSURL URLWithString:#"http:/someurl2.com"]];
[player pause];
[player release];
If you used playerWithURL, then just call the same line again.
2). The easiest is the get duration of the current item https://stackoverflow.com/a/3999238/619434 and then update the UISlider with that value. You can use NSTimer to periodically check the duration.
self.player.currentItem.asset.duration

iPhone: AVAudioPlayer not always playing audio on device

I have 2 views in my app, that are identical, they just load in a different array of sound files to use with their respective AVAudioPlayer.
However, ON THE DEVICE ONLY, on my second view, the sound seems to only play once after initialization, then it doesn't play until I initialize the player again.
This is my play button code:
- (IBAction)play:(id)sender {
if (((int)buttonCount % 2) == 0) {
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
self.audioPlayer.currentTime = 0;
self.audioPlayer.volume = volumeSlider.value;
[self.audioPlayer play];
[playButton setTitle:#"Stop..." forState:UIControlStateNormal];
buttonCount++;
[self fadePickerAnimation:NO];
NSLog(#"Should play");
}
else {
[self initializeSoundAfterStop:YES];
NSLog(#"Shouldn't play");
}
NSLog(#"buttoncount %i",buttonCount);
NSLog(#"What is the playing state? %i", self.audioPlayer.playing);
}
and the function it calls under the else clause:
- (void)initializeSoundAfterStop:(BOOL)addToButtonCount {
//Initialize audioPlayer once completely stopped
[self.audioPlayer stop];
[self.audioPlayer prepareToPlay];
[playButton setTitle:#"Chime!" forState:UIControlStateNormal];
if (addToButtonCount == YES) {
buttonCount++;
}}
The NSLogs in the above code output this as I continuously press the play button:
Should play
buttoncount 1
What is the playing state? 1
Shouldn't play
buttoncount 2
What is the playing state? 0
Should play
buttoncount 3
What is the playing state? 0
Shouldn't play
buttoncount 4
What is the playing state? 0
Should play
buttoncount 5
What is the playing state? 0
Shouldn't play
buttoncount 6
What is the playing state? 0
So as you can see, it gets stuck in a non-playing mode for some reason.
This method is used in exactly the same fashion in my first view, and it works without any problem. And it all works fine on the simulator, just not on my iPhone 4. Cannot figure this out. The play method of audioPlayer gets called when I setup a breakpoint, so I dunno!
Thanks!
Couldn't find out why this was happening, however, I fixed it by simply adding in my AVAdioPlayer initializer function at the top of the play IBAction.
Might not be the most graceful solution, but it works.
Just beware of memory allocation if you decide to do this.

AVAudioPlayer resetting currently playing sound and playing it from beginning

I'm having an issue using AVAudioPlayer where I want to reset a player if it's currently playing and have it play again.
I try the following with no luck:
The sound plays once but then the second time i select the button it stops the sound, the third time starts the sound up again.
//Stop the player and restart it
if (player.playing) {
NSLog(#"Reset sound: %#", selectedSound);
[player stop];
[player play];
} else {
NSLog(#"playSound: %#", selectedSound);
[player play];
}
I've also tried using player.currentTime = 0 which indicates that would reset the player, that didn't work, I also tried resetting currentTime = 0 and then calling play that didn't work.
//Stop the player and restart it
if (player.playing) {
NSLog(#"Reset sound: %#", selectedSound);
player.currentTime = 0;
[player play];
} else {
NSLog(#"playSound: %#", selectedSound);
[player play];
}
For your situation I would try the following
//Pause the player and restart it
if (player.playing) {
NSLog(#"Reset sound: %#", selectedSound);
[player pause];
}
player.currentTime = 0;
[player play];
If you are going to immediately play the sound again, I would suggest pause instead of stop. Calling stop "Stops playback and undoes the setup needed for playback."
As indicated, if you want the sound to play again, you should avoid disabling the AVAudioPlayer instance with a stop but rather, just issue a reset of the position where it is playing. So, don't use stop() or pause() but as Plumenator mentioned, just issue .currentTime=0. So in your case, you would simply do:
if (player.isPlaying) {
player.currentTime = 0
} else {
player.play()
}
Swift example:
player.currentTime = 0.0;