iPhone: How to play a sound at a particular time? - iphone

I have written the following code:
-(void)runTimer
{
myTicker=[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:#selector(showActivity) userInfo:nil repeats:YES];
myTicker = [NSTimer scheduledTimerWithTimeInterval:60.00 target:self selector:#selector(vibrate) userInfo:nil repeats:YES];
}
-(void)showActivity
{
NSDateFormatter *formatter =
[[[NSDateFormatter alloc] init] autorelease];
NSDate *date = [NSDate date];
[formatter setTimeStyle:NSDateFormatterMediumStyle];
[timerLabel setText:[formatter stringFromDate:date]];
}
-(void) vibrate{
AudioServicesPlaySystemSound (kSystemSoundID_Vibrate);
}
I want to play an audio file instead of vibrating the iPhone. Is that possible?

Tangential to the main question but the method called by the timer selector should be of the form...
-(void) aribtaryMethodName:(NSTimer *) theTimer;
...or it may not be called properly. It's selector should look like this:
myTicker=[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:#selector(aribtaryMethodName:) userInfo:nil repeats:YES];

Check Apple's sample project BubbleLevel. You want the SoundEffect.h and SoundEffect.m into your project and then just call:
mySound = [[SoundEffect alloc]
initWithContentsOfFile:[mainBundle pathForResource:#"mySound"
ofType:#"aif"]];
[mySound play];
Warning: I was able to play only AIF sounds converted via iTunes. Anything else failed, including CAF files. In short: import your whatever sound into iTunes (drag'n'drop), change export to AIF format and then export the file.

Yes. Assume you have a .caf file, you can play it with
SystemSoundID sound_id;
AudioServicesCreateSystemSoundID(NSURL_of_your_caf_file, &sound_id);
...
AudioServicesPlaySystemSound(sound_id);
To play music you may want to use AVAudioPlayer instead.

Sure. See AVAudioPlayer class.

-(IBAction)slider1Changed:(id)sender
{
[timer invalidate];
float sliderValue=slider1.value;
int totalSecond=(int)sliderValue;
time=totalSecond;
int sec= totalSecond %60;
int min= (totalSecond -sec)/60;
sliderValue=(float)totalSecond;
runTime.text=[NSString stringWithFormat:#"%d:%.2d",min,sec];
[slider1 setValue:sliderValue];
timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(timerChanged) userInfo:nil repeats:YES];
// to play the audio from particular time duration
[player setCurrentTime:totalSecond];
}
-(void)timerChanged
{
int totalSecond=[player duration];
float slider1Time=(float)time;
if (time <= totalSecond) {
int sec= time %60;
int min= (time -sec)/60;
runTime.text=[NSString stringWithFormat:#"%d:%.2d",min,sec];
[slider1 setValue:slider1Time];
}
else
{
[player stop];
[timer invalidate];
}
time +=1;
}

Related

Why are the following considered memory leaks?

I was just wondering if anyone could explain to me why the following lines are showing as having memory leaks within Instruments:
self.videoEngine = [[VideoEngine alloc] initWithCallbackName:#"IntroFinished"];
self.videoEngine = [[VideoEngine alloc] initWithCallbackName:#"MainMovieFinished"];
self.timerMap = [NSTimer scheduledTimerWithTimeInterval:fps target:self selector:#selector(updateAnimationTimer) userInfo:nil repeats:YES];
NSString *locationName2 = [[NSString alloc] initWithString:[locationName substringFromIndex:test]];
Is there an issue with not using a pre-set NSString when initialising? In the examples of self.videoEngine and self.timerMap they both have (nonatomic, retain) properties and are synthesised before use.
If your not using Arc (Which with the retain mentioned, i presume your not) then that will be your memory leak.
When you assign the VideoEngine property it is doing another retain on your object. You need to add autorelease to then end of you alloc statements.
self.videoEngine = [[[VideoEngine alloc] initWithCallbackName:#"IntroFinished"] autorelease];
self.videoEngine = [[[VideoEngine alloc] initWithCallbackName:#"MainMovieFinished"] autorelease];
self.timerMap = [NSTimer scheduledTimerWithTimeInterval:fps target:self selector:#selector(updateAnimationTimer) userInfo:nil repeats:YES];
NSString *locationName2 = [[NSString alloc] initWithString:[locationName substringFromIndex:test]];

iOS Stop Audio Playback At Certain Time (AVAudioPlayer End Time)

I'm wanting to play just part of an audio file. This audio file contains 232 spoken words, I have a dictionary that contains the start time of each word. So I have the start and stop times I just can't find a way to stop at a given time or play the file for a certain duration. Any advice and/or sample code to help me would be much appreciated, thanks Jason.
So I've found a solution, there's a problem with how I get endTime but I sure I can fix it.
//Prepare to play
[audioPlayer prepareToPlay];
//Get current time from the array using selected word
audioPlayer.currentTime = [[wordsDict objectForKey:selectedWord] floatValue];
//Find end time - this is a little messy for now
int currentIndex = 0;
int count = 0;
for (NSString* item in wordsKeys) {
if ([item isEqualToString: selectedWord]) {
currentIndex = count+1;
}
count++;
}
//Store found end time
endTime = [[wordsDict objectForKey:[wordsKeys objectAtIndex:currentIndex]] floatValue];
//Start Timer
NSTimer * myAudioTimer = [NSTimer scheduledTimerWithTimeInterval:0.1
target:self
selector:#selector(checkCurrentTime)
userInfo:nil
repeats:YES]
//Now play audio
[audioPlayer play];
//Stop at endTime
- (void) checkCurrentTime {
if(audioPlayer.playing && audioPlayer.currentTime >= endTime)
[audioPlayer stop];
}
This should do what you want. you don't need a repeating timer that's thrashing the player.
NSString *myAudioFileInBundle = #"words.mp3";
NSTimeInterval wordStartsAt = 1.8;
NSTimeInterval wordEndsAt = 6.5;
NSString *filePath = [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:myAudioFileInBundle];
NSURL *myFileURL = [NSURL fileURLWithPath:filePath];
AVAudioPlayer *myPlayer = [[AVAudioPlayer alloc]initWithContentsOfURL:myFileURL error:nil];
if (myPlayer)
{
[myPlayer setCurrentTime:wordStartsAt];
[myPlayer prepareToPlay];
[myPlayer play];
[NSTimer scheduledTimerWithTimeInterval:wordEndsAt-wordStartsAt target:myPlayer.autorelease selector:#selector(stop) userInfo:nil repeats:NO];
}
Try using AVPlayer instead and make use of
addBoundaryTimeObserverForTimes:queue:usingBlock:
What it does: Requests invocation of a block when specified times are traversed during normal playback.
https://developer.apple.com/library/prerelease/ios/documentation/AVFoundation/Reference/AVPlayer_Class/index.html#//apple_ref/occ/instm/AVPlayer/addBoundaryTimeObserverForTimes:queue:usingBlock:
The AVAudioPlayer gives you some neat properties to work with:
currentTime: during playback you can rely on this property.
playAtTime : starts playing from a pre-defined time.
But first of all I would write some helpers for that:
#interface Word {
double startTime;
double endTime;
}
#property double startTime;
#property double endTime;
#end
This is just a class to simply working with the following method.
- (void)playWord:(Word *)aWord {
self.avPlayer.playAtTime = aWord.startTime;
[avPlayer prepareToPlay];
[avPlayer play];
while (avPlayer.playing) {
/*
This while loop could be dangerous as it could go on for a long time.
But because we're just evaluating words, it won't be as much power draining
*/
if(avPlayer.currentTime >= aWord.endTime;
[avPlayer stop];
}
}
I would suggest you to use an array or any other mechanism to automatically switch to the next word. Maybe your could also add a Previous and Next button for handling user input.
Please let me know if that worked for you.
HTH

Get the time to "run" in iOS

I've read a guide about how to make a clock, in iOS. And that works like it should and all that, but i want to go further and get the clock to update each minut. So it's no longer "static", so if you open the application 12:16 am, and let it run it should automatically update each minut(12:17 am, 12:18am etc.).
This is the code the guide provided me with,
NSDateFormatter *datoVar = [[NSDateFormatter alloc] init];
[datoVar setDateFormat:#"hh:mm"];
LabelKlokken.text = [datoVar stringFromDate:[NSDate date]];
I've tried and tried to look through google and stackoverflow, but just can't find anything.
Thanks in advance, Oluf Nielsen.
EDITED : My code now looks like this
-(void)clock
{
NSDateFormatter *datoVar = [[NSDateFormatter alloc] init];
[datoVar setDateFormat:#"hh:mm"];
LabelKlokken.text = [datoVar stringFromDate:[NSDate date]];
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self clock];
tid = nil;
tid = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(clock) userInfo:NULL repeats:YES];
}
You can schedule an NSTimer to check for time every 60 seconds.
dateTimer = [NSTimer scheduledTimerWithTimeInterval:60 target:self selector:#selector(updateTime) userInfo:nil repeats:YES];
put your code in updateTime method. Better yet, check it every second, because it could happen that you switch time in 59th second of each minute thus being 59 seconds behind...
Remember to invalidate the timer once you want to quit updating so your app doesn't crash when you switch views or something.
[dateTimer invalidate];
dateTimer = nil;

How do I present an alarm to a user, even when my application is inactive?

I want to make an app which will let you set an alarm inside my iPhone app, then have it be activated even though my app is not running.
How would I implement this?
You want to use UILocalNotification. A couple things to note before you dive in:
It's only available on iOS4 and up.
NSDate is a pain in the ass, and it's the only option for scheduling
With that said, you can begin:
UILocalNotification *notif = [[UILocalNotification alloc] init];
notif.alertBody = #"This is a Local Notification";
NSDate *date = [NSDate date];
notif.fireDate = [date addTimeInterval:600];// fire the notification in ten minutes
[[UIApplication sharedApplication] scheduleLocalNotification:notif];
[notif release];
If you need any more help, just comment :)
try this:
in .h
int *currentTime;
in .m
-(void)startTimer {
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(updateCurrentTime) userInfo:nil repeats:YES];
}
-(void)updateCurrentTime {
currentTime ++;
if (currentTime == userDefinedTime) {
// Time is up
}
}

Iphone NSTimer Issue

Hi I am new to objective c. I am trying to make an app for iphone. I have a button on my view, and the click on which the function playSound is called. This is working properly. It does plays the sound that i want it to.
Now the problem is with the timer. I want the timer to start on the click on the same button, and the timer value will be displayed in a label. I am not very clear with the NSTimer itself either yet. I guess i am doing something wrong here. Can anyone help me with this.
-(IBAction)playSound { //:(int)reps
NSString *path = [[NSBundle mainBundle] pathForResource:#"chicken" ofType:#"wav"];
NSURL *fileURL = [[NSURL alloc] initFileURLWithPath: path];
AVAudioPlayer* theAudio = [[AVAudioPlayer alloc] initWithContentsOfURL:fileURL error:nil];
theAudio.delegate = self;
[theAudio play];
[self startTimer];
}
- (void)startTimer {
timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(targetMethod) userInfo:nil repeats:YES];
labelA.text = [NSString stringWithFormat:#"%d", timer];
}
Using the code above, when i click on the button, it plays the sound, and then my app closes.
Thanks
Zeeshan
This line:
labelA.text = [NSString stringWithFormat:#"%d", timer];
makes absolutely no sense. The timer will call the method you specify as the selector in scheduledTimerWithTimeInterval:target:selector:userInfo:repeats: when it fires so you have to implement that method and update your label there. The first line of startTimer is almost correct, but the selector must include a colon (because it denotes a method that takes one parameter):
- (void)startTimer {
timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(timerFired:) userInfo:nil repeats:YES];
}
Note that I named the selector timerFired: so we have to implement that method. If you want the timer to increment a counter, you will have to do that in this method, too:
- (void)timerFired:(NSTimer *)timer {
static int timerCounter = 0;
timerCounter++;
labelA.text = [NSString stringWithFormat:#"%d", timerCounter];
}
Don't forget to invalidate the timer later when you no longer need it.