I am implementing some audiobooks for iPhone. I used AVFoundation. Something like this:
NSString *path = [[NSBundle mainBundle] pathForResource:#"intro" ofType:#"mp3"];
player=[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
I have a problem. When the screen goes dark (single audio files can be very long) the audio stops playing.
I solved this problem with this string of code
- (void)applicationDidFinishLaunching:(UIApplication *)application {
// something else here...
[[UIApplication sharedApplication] setIdleTimerDisabled:YES];
}
This does not allow the iPhone to "sleep". However you can guess how this is foolish: your battery level goes down in minutes and this is not possible by audiobooks lasting more than 20 hours, for example...
So, do you know a way to prevent that when the screen sleeps the AVAudioPlayer does not stop playing?
Thanks...
Fabio
Set your audio session to kAudioSessionCategory_MediaPlayback to playback while the screen is locked.
Could I suggest that once you start playing the audio file that you tell the user to press the power button (not home button) which will lock the phone. It will not close you app but it will power off the screen with you application running in the background. Currently several apps do this.
Related
I'm using AVAudioPlayer to play a little shot sound when a user clicks a button. The sounds lasts about 3 seconds and I want that, if a user hit a button multiple times, the shot should sound multiple times. If the user clicks twice in 2 seconds, then the second sound should overlap the first shot.
My problem is that the shot only sounds every 3 seconds (if the user clicks rapidly) instead of every hit of the button.
Inside ViewDidLoad
NSString *path = [[NSBundle mainBundle] pathForResource:#"shot" ofType:#"caf"];
urlShotCaf = [NSURL fileURLWithPath:path];
player = [[AVAudioPlayer alloc] initWithContentsOfURL:urlShotCaf error:nil] ;
[player prepareToPlay];
And when a person clicks the shot button
- (IBAction)tap:(id)sender {
clicks++;
[player play];
}
Can I do this with AVAudioPlayer? Should I use another framework?
As stated in reference here:
Play multiple sounds simultaneously, one sound per audio player, with precise synchronization
I guess you need a AVAudioPlayer for every sound you want to play simultaneously. Otherwise you could use any simple library like CocosDenshion that is really simple, easy to embed and powerful (it resides on OpenAL).
Just do
[SimpleAudioEngine sharedEngine] playEffect:#"yoursound.wav"];
and you are done.
Please try this. It works for me.
- (IBAction) tap:(id)sender {
if ([player isPlaying]) {
[player stop];
[player setCurrentTime:0.0];
}
[player play];
}
If high level frameworks fail, then you can dip down to AUSampler - an AudioUnit sample player (typically used for playback of sampled instruments, drum sounds, and so on). This should have very fast response times and support multiple active notes. Configure the sample's playback as one-shot. When the button is pressed, simulate a note on event. You could also map different samples (audio recordings) to different notes and velocity ranges.
i've created a drum app. As of now, the app's kinda satisfying but not great.
The problem is a strange delay or "lag" that sometimes happens when i press my sound buttons. When i spam a button it begins to freeze, when unfreezed again, it plays the same sound stacked on itself about 4 times :(
What am i doing wrong?
Are my samples bad?
Should i use an imageView and touchesBegan to simulate the buttons?
This is the code that i use to play a sound when a button is pushed:
- (IBAction) HHC {
NSString *path = [[NSBundle mainBundle] pathForResource:#"HHClosed"ofType:#"wav"];
SystemSoundID soundID;
AudioServicesCreateSystemSoundID((CFURLRef) [NSURL fileURLWithPath:path], &soundID);
AudioServicesPlaySystemSound (soundID);
}
Please give me some good advice :)
Thanks in advance
-DD
Try doing this and see if it makes your performance better.
In your .h file declare this:
SystemSoundID soundID;
In your .m file in the -viewDidLoad method add this code:
-(void) viewDidLoad {
NSString *path = [[NSBundle mainBundle] pathForResource:#"HHClosed"ofType:#"wav"];
AudioServicesCreateSystemSoundID((CFURLRef) [NSURL fileURLWithPath:path], &soundID);
}
And in the method you showed just keep this one line of code:
- (IBAction) HHC {
AudioServicesPlaySystemSound (soundID);
}
Let me know if that makes the freezing going away. If it doesn't try Core Audio
Every time you hit the button you are loading the sound file from the filesystem, bringing it into memory, and then playing it.
This is very inefficient. Your audio samples should already be loaded in memory at launch, so they don't need to be read in from the filesystem. Also, AudioServicesPlaySystemSound isn't really designed for this kind of usage - its main purpose is playing back short alert sounds (ie, a system alert). If you need low-latency audio playback you should be looking at the Core Audio framework instead.
For low latency sound appropriate for a drum app, you will want to use the RemoteIO Audio Unit API, which is not simple. You will need to know how to handle, buffer and mix PCM sound samples. Start by reading a book on digital audio technology.
I am trying to use iPhone OS 4.0's multitasking capability. I tried to play audio in the background with no luck. I added UIBackgroundModes property in info.plist and mentioned requires audio to play in background. Also I added the code for playing the audio.
`
NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"someday" ofType:#"mp3"]];
AVAudioPlayer *audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
[audioPlayer play];
`. The audio starts playing once i click on button in the app. But when I shut the app it stops. How can I make it play in the background?
Thanks,
Tony
It sounds like you didn't set up your Audio Session correctly. From http://developer.apple.com/iphone/library/documentation/AudioVideo/Conceptual/MultimediaPG/UsingAudio/UsingAudio.html :
For example, when using the default audio session, audio in your application stops when the Auto-Lock period times out and the screen locks. If you want to ensure that playback continues with the screen locked, include the following lines in your application’s initialization code:
NSError *setCategoryErr = nil;
NSError *activationErr = nil;
[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayback error:&setCategoryErr];
[[AVAudioSession sharedInstance] setActive:YES error:&activationErr];
The AVAudioSessionCategoryPlayback category ensures that playback continues when the screen locks.
Activating the audio session puts the specified category into effect.
HI,
I think this video helps u in solving ur problem...
IN WWDC videos they have clearly explained how u can enable the back ground audio...
http://developer.apple.com/videos/wwdc/2010/
to view or download these videos u need to have a apple account...
and in that see Session 109-Adopting multitasking on iPhone OS, Part2...
Hope this will help u..
~Raviraja
i put a movie when my application will lunch . just like gameloft games .
so when application has lunched , movie plays fine but before the move plays .. my FirstViewController xib file show first then moview start to play ! why ?
here is my code :
- (void)applicationDidFinishLaunching:(UIApplication *)application {
NSBundle *bundle = [NSBundle mainBundle];
NSString *moviePath = [bundle pathForResource:#"movie" ofType:#"m4v"];
NSURL *movieURL = [[NSURL fileURLWithPath:moviePath] retain];
MPMoviePlayerController *IntroMovie = [[MPMoviePlayerController alloc] initWithContentURL:movieURL];
IntroMovie.movieControlMode = MPMovieControlModeHidden;
[IntroMovie play];
}
Your question is a little unclear, but what I think you are asking is why your movie is not playing when the application launches before the user sees the controls and items in your XIB file. If this is correct, then this is the normal behavior as typically the application will launch and only then call the function you have (applicationDidFinishLaunching). There is no guarantee that you will get that function called before the controls have loaded and are viewable on the screen all the time.
It is bad form to start you application with a movie, but if you want to then you have to deal with the fact that there will potentially be a default image or even your controls that you put in your XIB file.
One way to start with a movie, is that you must hide or delete everything in the XIB file so the screen will appear blank when the application loads. Then, when you application calls the applicationDidFinishLaunching function the user will not have seen your application and the first thing they will see is the movie. When the movie is finished playing, you will need to have a notification listener instruct your application to show the controls for your application or switch to another XIB file that has the app controls within it.
I hope this helps.
When I use my app (on the device), the actual volume works OK for a while, but after a few days it seems to get 'stuck' at a low level.
Adjusting the volume rocker has no effect - and it shows 'Ringer' text. I've noticed that other people's apps are similarly affected if they show the 'Ringer' text when adjusting the volume. But apps which don't show 'Ringer' text are not affected by this.
How would I remove the 'Ringer' text and get my app to respond properly to different volumes?
I found some code on Apple's forums which fixes it. You have to use the AVFoundation.framework and put a bit of code into your app delegate. And put an audio file called 'blank.aif' into your project. Basically, it's a hack which prepares a file to play, but then never plays it. This fools the system into thinking that sound is being played all the time, which allows the user to use the main volume control.
#import <AVFoundation/AVFoundation.h>
//...
-(void)applicationDidFinishLaunching:(UIApplication *)application {
//volume control hack
NSString *soundFilePath = [[NSBundle mainBundle] pathForResource:#"blanksound" ofType:#"aif"];
NSURL *fileURL = [[NSURL alloc] initFileURLWithPath:soundFilePath];
AVAudioPlayer *volumeHack = [[[AVAudioPlayer alloc] initWithContentsOfURL:fileURL error:nil]retain];
[fileURL release];
[volumeHack prepareToPlay];
// other applicationDidFinishLaunching stuff
}