system sound on iphone not playing - ios

I want to play a system sound but I don't hear anything:
- (void) play_system_sound
{
NSLog(#"Play system sound");
SystemSoundID soundID;
NSString *path = [[NSBundle bundleWithIdentifier:#"com.apple.UIKit"] pathForResource:#"Tock" ofType:#"aiff"];
NSLog(#"path = %#", path );
AudioServicesCreateSystemSoundID((__bridge CFURLRef)[NSURL fileURLWithPath:path], &soundID);
AudioServicesPlaySystemSound(soundID);
AudioServicesDisposeSystemSoundID(soundID);
NSLog(#"Play system sound DONE");
}
I don't hear anything. What am I doing wrong?

After AudioServicesPlaySystemSound(soundID) ,don't call AudioServicesDisposeSystemSoundID(soundID) immediately.
Try this :
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *path = [[NSBundle bundleWithIdentifier:#"com.apple.UIKit"] pathForResource:#"Tock" ofType:#"aiff"];
AudioServicesCreateSystemSoundID((__bridge CFURLRef)[NSURL fileURLWithPath:path], &soundID);
}
-(void)dealloc
{
AudioServicesDisposeSystemSoundID(soundID);
}
- (void)play_system_sound
{
AudioServicesPlaySystemSound(soundID);
}

I don't know if you have solved the problem, but for me, on iOS 7, sometimes the (__bridge CFURLRef) casting won't work, in which case, if you print out the result of (__bridge CFURLRef)[NSURL fileURLWithPath:path], it will be 0x0. This leads to failure of AudioServicesCreateSystemSoundID(). The return value of the function is type of OSStatus. If it fails, the function will return -50, which means one or more parameters are invalid. (If it executes successfully, it returns 0.)
I solved this by using the C style function getting the path of the file:
CFBundleRef mainBundle = CFBundleGetMainBundle ();
CFURLRef soundFileUrl;
soundFileUrl = CFBundleCopyResourceURL(mainBundle, CFSTR("fileName"), CFSTR("wav"), NULL);
AudioServicesCreateSystemSoundID(soundFileUrl, &soundID);

Related

Adding a sound effect to a jump

I want to add a sound effect to a jump action when my character jumps. It sounds simple to do but i just cannot do it, this is what I've tried so far..
In my header file for my character I have:
SystemSoundID jump;
- (void)playSound:(NSString *)jump1 :(NSString *) mp3;
In my implementation file I have:
- (void)playSound :(NSString *)jump1 :(NSString *) mp3{
SystemSoundID audioEffect;
NSString *path = [[NSBundle mainBundle] pathForResource : jump1 ofType :mp3];
if ([[NSFileManager defaultManager] fileExistsAtPath : path]) {
NSURL *pathURL = [NSURL fileURLWithPath: path];
AudioServicesCreateSystemSoundID((__bridge CFURLRef) pathURL, &audioEffect);
AudioServicesPlaySystemSound(audioEffect);
}
else {
NSLog(#"error , file not found aye: %#", path);
}
}
Also inside the function jump I have:
[self playSound:#"jump" :#"mp3"];
Please excuse my inexperience I just had a go at it as it would be a great feature for my game, if someone could tell me what I am doing wrong or a different and better way to do it that works that would be great thanks!
Add this method in a class and whenever you want to play the sound just call this method using [self playSound], jump.mp3 should be in your bundle, and remember one thing more don't forget to add AudioToolbox framework.
-(void) playSound {
NSString *soundPath = [[NSBundle mainBundle] pathForResource:#"jump" ofType:#"mp3"];
SystemSoundID soundID;
AudioServicesCreateSystemSoundID((__bridge CFURLRef)[NSURL fileURLWithPath: soundPath], &soundID);
AudioServicesPlaySystemSound (soundID);
}

How to use AudioServicesRemoveSystemSoundCompletion Callback

I am trying to play two different files in a queue. One is an intro track and another is a main track.
My Method to setup music playback
-(void)musicPlayBack:(CFStringRef )soundName{
CFBundleRef mainBundle = CFBundleGetMainBundle();
CFURLRef soundFileURLRef;
soundFileURLRef = CFBundleCopyResourceURL(mainBundle
, (CFStringRef) soundName, CFSTR ("mp3"), NULL);
SystemSoundID soundID;
AudioServicesCreateSystemSoundID(soundFileURLRef, &soundID);
AudioServicesAddSystemSoundCompletion(soundID, NULL, NULL, FinishedSoundPlayback, NULL);
AudioServicesPlaySystemSound(soundID);
}
-(void)playIntro:(NSString *)introTrackName{
NSArray *introTracks = [NSArray arrayWithObjects:#"heybaby",#"dumbson",#"heybadass",
#"heydarling",#"heyhoney",#"madam",#"sir", nil];
[self musicPlayBack:(__bridge CFStringRef)([introTracks objectAtIndex:2])];
}
-(void)playNotification:(NSString *)notificationTrackName{
[self musicPlayBack:(__bridge CFStringRef)(notificationTrackName)];
}
-(void)notifyWithSound:(int)batteryCase{
NSArray *mainSoundTracks = [NSArray arrayWithObjects:#"ten",#"twenty",#"twentyfive",#"thirty",
#"fourty",#"fifty",#"sixty",#"seventy",#"seventyfive",
#"eigthy",#"ninty",#"hundred",nil];
[self playIntro:#"someRandomIntro"];
while (introFinished==NO) {
if (introFinished==YES) {
break;
}
}
[self playNotification:[mainSoundTracks objectAtIndex:batteryCase]];
}
This is what i have before #implementation
BOOL introFinished = NO;
static void FinishedSoundPlayback(SystemSoundID mySSID, void* data){
introFinished = YES;
AudioServicesRemoveSystemSoundCompletion (mySSID);
NSLog(#"completion Callback");
}
The problem is FinishedSoundPlayback never gets called.
You registered the system sound under the name "soundId" and you expect callback for "mySSID". This suppose to be the same name. BTW I do not recommend this API for playing music because of its limitation.

Looping Audio with AudioToolbox.framework

I have would like to play audio on the startup of my app, but, first of all, the audio doesn't play! No matter how i code it. And secondly I would love to loop it if i can.
#implementation ViewController
-(void)awakeFromNib
{
SystemSoundID soundID;
NSString *soundFile1 = [[NSBundle mainBundle] pathForResource:#"ScaryMusic" ofType:#"mp3"];
AudioServicesCreateSystemSoundID((__bridge CFURLRef) [NSURL fileURLWithPath:soundFile1], &soundID);
AudioServicesPlaySystemSound(soundID);
NSLog(#"Sound Played");
}
Try this instead:
#import <AVFoundation/AVFoundation.h>
AVAudioPlayer *player;
NSURL *soundFileURL = [[NSBundle mainBundle] URLForResource:#"ScaryMusic" withExtension:#"mp3"];
if (soundFileURL != nil)
{
player = [[AVAudioPlayer alloc] initWithContentsOfURL:soundFileURL error:nil];
player.numberOfLoops = -1; //infinite
}
[player play];
This is better for mp3's and such. SystemSound is mostly reserved for short .wav type sounds.
If you look in the docs you'll find that mp3 is not among the formats supported by AudioToolbox

asynchronous sounds in iphone app

I use the following code to play the sounds in my app, but the problem is that it slows down the app. How can I make the sounds happen asynchronously without slowing down the actions?
SystemSoundID soundID;
NSString *soundFile = [[NSBundle mainBundle] pathForResource: _sound ofType:# "wav"];
AudioServicesCreateSystemSoundID((__bridge CFURLRef) [NSURL fileURLWithPath:soundFile], &soundID);
AudioServicesPlaySystemSound(soundID);
Do the AudioServicesCreateSystemSoundID during app initialization, or at some other point ahead of time when the user can expect/accept a little lag. It can be performed in the background, but the sound can't be played until it's finished.
AudioServicesPlaySystemSound is asynchronous already.
In other words, to demonstrate how do the init early, appDidFinishLaunching is the earliest opportunity. Make your sounds available to other parts of the app with a public property...
// AppDelegate.h, add this inside the #interface
#property (strong, nonatomic) NSArray *sounds;
// AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSMutableArray *tempSounds = [NSMutableArray array];
SystemSoundID soundID0;
// you need to initialize _sound0, _sound1, etc. as your resource names
NSString *soundFile0 = [[NSBundle mainBundle] pathForResource: _sound0 ofType:# "wav"];
AudioServicesCreateSystemSoundID((__bridge CFURLRef) [NSURL fileURLWithPath:soundFile0], &soundID0);
[tempSounds addObject:[NSNumber numberWithInt:soundID0]];
SystemSoundID soundID1;
NSString *soundFile1 = [[NSBundle mainBundle] pathForResource: _sound1 ofType:# "wav"];
AudioServicesCreateSystemSoundID((__bridge CFURLRef) [NSURL fileURLWithPath:soundFile1], &soundID1);
// SystemSoundID is an int type, so we wrap it in an NSNumber to keep in the array
[tempSounds addObject:[NSNumber numberWithInt:soundID1]];
self.sounds = [NSArray arrayWithArray:tempSounds];
// do anything else you do for app init here
return YES;
}
Then in SomeViewController.m ...
#import "AppDelegate.h"
// when you want to play a sound (the first one at index 0 in this e.g.)
NSArray *sounds = ((AppDelegate *)[[UIApplication sharedApplication] delegate]).sounds;
AudioServicesPlaySystemSound([sounds[0] intValue]);

sound not playing on real device

I'm trying to play a sound in the iPad using this code:
-(void)playSound:(NSString *)filename {
SystemSoundID soundID;
NSString *path = [[NSBundle mainBundle] pathForResource:filename ofType:#"wav"];
if (path) {
UInt32 sessionCategory = kAudioSessionCategory_AmbientSound;
AudioSessionSetProperty (
kAudioSessionProperty_AudioCategory,
sizeof (sessionCategory),
&sessionCategory
);
AudioServicesCreateSystemSoundID((CFURLRef)[NSURL fileURLWithPath:path],&soundID);
AudioServicesPlaySystemSound (soundID);
}
}
Sound is playing right in the simulator but it doesn't work on the real device (no, it's not muted :-) )
Check the file extension for case sensitivity, is it "WAV" or "Wav"... instead of "wav"
Or check your filename for the same reason.
That could solve your problem.

Resources