playing audio when apps running - ios

I've been trying lately to get my app to play a sound from when it open to when its closed and I'm have difficulty. I have some code on playing a sound when I press a button and it's fine I'm just wondering if there is any tweaks I could do to make it play on its own and from the start or is there a way I could say press play and make the sound loop why I'm playing the game.
.h
#import <AudioToolbox/AudioToolbox.h>
- (IBAction)t1:(id)sender;
.m
- (IBAction)t1:(id)sender {
CFBundleRef mainbundle = CFBundleGetMainBundle();
CFURLRef soundFileUrlRef;
soundFileUrlRef = CFBundleCopyResourceURL(mainbundle, (CFStringRef) #"t1", CFSTR ("wav"), NULL);
UInt32 soundID;
AudioServicesCreateSystemSoundID(soundFileUrlRef, &soundID);
AudioServicesPlaySystemSound(soundID);
}

how about trying AVAudioPlayer and turning on the continuous playback by setting number of loops to -1:
myPlayer.numberOfLoops = -1
[myPlayer prepareToPlay];
[myPlayer play];
//when application did enter background or something
[myPlayer stop];
http://developer.apple.com/library/ios/#DOCUMENTATION/AVFoundation/Reference/AVAudioPlayerClassReference/Reference/Reference.html
Also make sure your Audio Sessions are set properly for background playback:
http://developer.apple.com/library/ios/#DOCUMENTATION/Audio/Conceptual/AudioSessionProgrammingGuide/Basics/Basics.html#//apple_ref/doc/uid/TP40007875-CH2-SW2

Related

Music Not Playing - XCode

I have this code to play sounds:
CFBundleRef mainBundle = CFBundleGetMainBundle();
CFURLRef soundFileURLRef;
soundFileURLRef = CFBundleCopyResourceURL(mainBundle, (CFStringRef) #"audio2", CFSTR ("mp3"), NULL);
UInt32 soundID;
AudioServicesCreateSystemSoundID(soundFileURLRef, &soundID);
AudioServicesPlaySystemSound(soundID);
It works fine for an audio file that I have that is about 1 second long. It does not, however, work for one of my files that is about 4 minutes long. How can I fix this? They're both mp3 files and placed in the same directory.
According to the apple's doc, AudioServicesPlaySystemSound has a limits as below:
Sound files that you play using this function must be:
- No longer than 30 seconds in duration
You can use AVAudioPlayer instead.

Sound not playing when iPhone is in silent mode

I am making an app that needs to play sounds even if the iPhone is in silent mode, but with the code I have now (look at bottom of this post) it wont't play sounds if the iPhone is in silent mode.
I am using the following code:
Viewcontroller.h:
#interface SoundViewController : UIViewController <UICollectionViewDataSource, UIApplicationDelegate, AVAudioPlayerDelegate, ADBannerViewDelegate, UIActionSheetDelegate> {
SystemSoundID SoundID;
NSString *listPath;
}
ViewController.m:
CFBundleRef mainBundle = CFBundleGetMainBundle();
CFURLRef soundFileURLRef;
soundFileURLRef = CFBundleCopyResourceURL(mainBundle, (__bridge CFStringRef) [mainArray objectAtIndex:indexPath.row], CFSTR("wav"), NULL);
UInt32 soundID;
AudioServicesCreateSystemSoundID(soundFileURLRef, &soundID);
AudioServicesPlaySystemSound(soundID);
The way you are triggering sounds using AudioServicesPlaySystemSound will ALWAYS obey the ringer/silent switch.
To play sound when the device is set to silent you need to use another way such as AVAudioPlayer class.

Creating AVAudioPlayer object much before playing the dynamic audio

Whenever i play an audio file like below, it is taking few seconds to start playing the audio. I have seen from some forums and understand that, AVAudioPlayer will take few seconds to start playing if we allocate the object there itself. I am thinking to allocate this object much earlier (may be Appdelegate itself), before when i want to play, so that when i want to play it, it will play immediately.
NSURL *audioPathURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:audioName ofType:#"wav"]];
audioP = [[AVAudioPlayer alloc]initWithContentsOfURL:audioPathURL error:NULL];
[appDelegate.audioP play];
but, i am passing audio url dynamically at run time, so i would like to know how can i allocate the object earlier and then be able to pass dynamic audio url path later?
Please note, my question is different from this question Slow start for AVAudioPlayer the first time a sound is played
In the existing question, they are telling about one audio file and play it when required. But, i am having many different audio file and url path is generated randomly and at run time to play, so i do not know what the actual url path to set and play. So, the answer mentioned here->Slow start for AVAudioPlayer the first time a sound is played
won't help for my question.
I can't use prepareToPlay, because audio path url is set at run time and not just one audio is being used for all the times to play, there will more than 20 audio file randomly chosen and set to play one at a time. So, i need the right answer for it, it is not a duplicate question.
Thank you!
For a single file here the solution:
in your file.h
#import <AVFoundation/AVFoundation.h>
#interface AudioPlayer : UIViewController <AVAudioPlayerDelegate> {
}
To use with button add - (IBAction)Sound:(id)sender; in your file.h
Now in your file.m
//this is a action but you can use inside a void to start auto
#implementation AudioPlayer {
SystemSoundID soundID;
}
- (IBAction)Sound:(id)sender {
AudioServicesDisposeSystemSoundID(soundID);
CFBundleRef mainBundle = CFBundleGetMainBundle();
CFURLRef soundFileURLRef;
//you can use here extension .mp3 / .wav / .aif / .ogg / .caf / and more
soundFileURLRef = CFBundleCopyResourceURL(mainBundle, (CFStringRef) #"sound" ,CFSTR ("mp3") , NULL);
AudioServicesCreateSystemSoundID(soundFileURLRef, &soundID);
AudioServicesPlaySystemSound(soundID);
}
If you want use your code to play audio from URL you can use this:
#import <AVFoundation/AVFoundation.h>
#import <MediaPlayer/MediaPlayer.h>
#interface AudioPlayer : UIViewController <AVAudioPlayerDelegate> {
AVPlayer *mySound;
}
#property (strong, nonatomic) AVPlayer *mySound;
#end
And file.m
- (IBAction)playPause:(id)sender {
if (mySound.rate == 0){
NSURL *url = [NSURL URLWithString:#"http://link.mp3"];
mySound = [[AVPlayer alloc] initWithURL:url];
[mySound setAllowsExternalPlayback:YES];
[mySound setUsesExternalPlaybackWhileExternalScreenIsActive: YES];
[mySound play];
} else {
[mySound pause];
}
}
Hope this can help you!
One thing you can do to reduce the latency of the first load+play is to "spin up" the underlying audio system before you need it by loading and playing a dummy file. For example, in application:didFinishLaunchingWithOptions: add some code like this:
// this won't effect the problem you're seeing, but it's good practice to explicitly
// set your app's audio session category
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
NSURL *audioURL = [[NSBundle mainBundle] URLForResource:#"dummy.wav" withExtension:nil];
AVAudioPlayer *dplayer = [[AVAudioPlayer alloc] initWithContentsOfURL:audioURL error:nil];
// we don't want to hear it (alternatively, the audiofile you use for this purpose can be silence.)
dplayer.volume = 0.f;
[dplayer prepareToPlay];
[dplayer play];
[dplayer stop];
Once this code completes, subsequent instantiations and playback of AVAudioPlayer instances should have pretty low latency (certainly well under 1 second)

Configure TableViewCell to play audio

I have an app that currently plays a 5 sec sound when a button is pressed within a view controller. I am trying to change this set up to where if I have a tableview, a specific cell is touched and the sound plays. I do not want an action where you select the cell and it pushes to another window to play the sound. I simply want the sound to play on touch of the cell.
Currently for my button set up I had the following to play the sound in my view controller:
In the SoundLibViewController.h
// Identifying UIButton associated with sound file
-(IBAction)CarHorn:(id)sender;
#end
In the SoundLibViewController.m
-(IBAction)CarHorn:(id)sender {
CFBundleRef mainBundle = CFBundleGetMainBundle();
CFURLRef soundFileURLRef;
soundFileURLRef = CFBundleCopyResourceURL(mainBundle, (CFStringRef) #"CarHorn", CFSTR ("wav"), NULL);
UInt32 soundID;
AudioServicesCreateSystemSoundID(soundFileURLRef, &soundID);
AudioServicesPlaySystemSound(soundID);
}
Unfortunately I can not find any help online to point me in the direction to change my code into incorporate a tableviewcell.
To give an example of what I'm looking to do: You go into your iPhone/iPad and under settings you select "Sounds". Then you choose "Ringtone", which takes you to a list of sounds. If you press the cell related to the sound it plays. THAT is what I want to do.
You need something like this in your UITableViewDelegate
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString * soundName = [self.soundNames objectAtIndex: indexPath.row]; // Assuming you have an array of sound names
CFBundleRef mainBundle = CFBundleGetMainBundle();
CFURLRef soundFileURLRef;
soundFileURLRef = CFBundleCopyResourceURL(mainBundle, (CFStringRef)soundName, CFSTR ("wav"), NULL);
UInt32 soundID;
AudioServicesCreateSystemSoundID(soundFileURLRef, &soundID);
AudioServicesPlaySystemSound(soundID);
}

How to loop audio on a specific View Controller

-(void)viewDidAppear:(BOOL)animated
{
CFBundleRef mainBundle = CFBundleGetMainBundle();
CFURLRef soundFileURLRef;
soundFileURLRef = CFBundleCopyResourceURL(mainBundle, (CFStringRef) #"Intro",
CFSTR ("wav"), NULL);
UInt32 soundID;
AudioServicesCreateSystemSoundID (soundFileURLRef, &soundID);
AudioServicesPlaySystemSound (soundID);
}
I'm a beginner with this. I'm trying to play a wav file in the background of the view controller. I originally made a 30 second wav file, it wouldn't play, I reduced the length of the audio file to 10 seconds and it plays fine on the view controller. My question is, how to loop this audio file and/or play a longer audio file. Also, will the audio stop when I leave the view controller.
I am using xCode 4.3
I am running the app on a iPhone4 & 4s (iOS 5.1)
Thanks in advance...
Apple Documentation states
http://developer.apple.com/library/ios/#documentation/AudioToolbox/Reference/SystemSoundServicesReference/Reference/reference.html
You can use System Sound Services to play short (30 seconds or shorter) sounds. The interface does not provide level, positioning, looping, or timing control, and does not support simultaneous playback: You can play only one sound at a time. You can use System Sound Services to provide audible alerts. On some iOS devices, alerts can include vibration.
So no loop is available when using system sounds.
You can check out this tutorial
http://mobileorchard.com/easy-audio-playback-with-avaudioplayer/
- (void)viewDidLoad {
[super viewDidLoad];
NSURL *url = [NSURL fileURLWithPath:[NSString stringWithFormat:#"%#/audiofile.mp3", [[NSBundle mainBundle] resourcePath]]];
NSError *error;
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];
audioPlayer.numberOfLoops = -1;
if (audioPlayer == nil)
NSLog([error description]);
else
[audioPlayer play];
}
It states that if you set the numberOfLoops property to a negative number causes the audioPlayer to loop indefinitely
And dont forget to add the AVFoundation framework to your project

Resources