How to stop playing sound in Xode with AudioToolbox framework? [duplicate] - iphone

Pretty simple, I'm using one button that generates a random number and then with a switch/case, it animates an image and plays a sound. My problem is that when you press the button again, the sound that was playing before doesn't stop and the sound overlaps.
Here's the code:
- (IBAction) pushme: (id) sender{
int random = (arc4random()%10);
switch (random) {
case 0: {
[ANIMATION NUMBER 0]
NSString *path = [NSString stringWithFormat:#"%#%#",[[NSBundle mainBundle] resourcePath],#"/sound0.wav"];
SystemSoundID soundID;
NSURL *filePath = [NSURL fileURLWithPath:path isDirectory:NO];
AudioServicesCreateSystemSoundID((CFURLRef)filePath, &soundID);
AudioServicesPlaySystemSound(soundID);
}
break;
case 1: {
[ANIMATION NUMBER 1]
NSString *path = [NSString stringWithFormat:#"%#%#",[[NSBundle mainBundle] resourcePath],#"/sound1.wav"];
SystemSoundID soundID;
NSURL *filePath = [NSURL fileURLWithPath:path isDirectory:NO];
AudioServicesCreateSystemSoundID((CFURLRef)filePath, &soundID);
AudioServicesPlaySystemSound(soundID);
} break; //Lots more cases after this one
I know that this is not the best way to do it, declaring the same variable over and over.
but is there a way to stop it before it plays another one?

I just dicovered the answer to my own question.
What I did was
Declare SoundSystemID soundID; in the header.
Add this line before the random number gets generated: AudioServicesDisposeSystemSoundID(soundID);
Remember that if you are going to play the sound again, you will need to load the resource again after disposing of it.
Thank you guys, anyway.

Related

How do I get sound to play in an animation I created in xcode?

I managed to create this application that includes an animation in it. But I want to make it stand out and more fun by adding a .wav file that I downloaded from the web. I want the sound to play for the duration of the animation. Only started coding a month ago so any help would be deeply appreciated
You could use the AVAudioPlayer
just create a method and connect it to your button or animation
-(void) playLoopingMusicInApplication {
AVAudioPlayer *audioPlayer;
// set the pathForResource: to the name of the sound file, and ofType: to AAC preferrably.
NSString *soundFilePath = [[NSBundle mainBundle] pathForResource:#"fileName" ofType:#"WAV"];
NSURL *soundFileURL = [NSURL fileURLWithPath:soundFilePath];
player = [[AVAudioPlayer alloc] initWithContentsOfURL:soundFileURL error:nil];
player.delegate = self;
//infinite
player.numberOfLoops = -1;
[player play];
//[player release];
}
PS - You will need to get the AVFoundation framework, and the AudioToolbox framework in your project
hope this helps!

Playing sound effect with no latency in Objective-C

I want to play some simple sound effects when people press certain buttons in my app and I've tried several things, but I always get a latency that makes the sound seem out of sync.
I've followed the tutorials here, so I've tried the build in Audio Services, but that had a latency and I've tried the AVAudioPlayer, but that had a latency as well, even though I used "prepareToPlay".
Do I really have to install a big and messy library like Finch to get a simple sound effect with no latency in my simple app?
Hope you can clarify things for me!
UPDATE
Code for Audio Services:
NSURL *soundURL = [[NSBundle mainBundle] URLForResource:#"PlopsX4"
withExtension:#"aif"];
AudioServicesCreateSystemSoundID((CFURLRef)soundURL, &sound1);
AudioServicesPlaySystemSound(sound1);
Code for AVAudioPlayer in viewDidLoad:
NSURL *soundURL = [[NSBundle mainBundle] URLForResource:#"PlopsX4"
withExtension:#"aif"];
self.avSound = [[AVAudioPlayer alloc]
initWithContentsOfURL:soundURL error:nil];
[self.avSound prepareToPlay]
Code for AVAudioPlayer in method where I want to play the file:
[self.avSound play];
The way I got this to work (and I think I got the idea from another post on SO) was to create an empty 1 second .wav file and "play" it at initialization. After that, there was no delay when I called the other sound effects.
Something like this in my sound player object
SystemSoundID blID;
SystemSoundID cID;
+(void)doInit
{
if (spinitialized){
AudioServicesPlaySystemSound (blID);
return;
}
NSString *str = [[NSBundle mainBundle] pathForResource:#"ding.wav" ofType:#""];
NSURL *uref = [NSURL fileURLWithPath:str];
OSStatus error = AudioServicesCreateSystemSoundID ((CFURLRef)uref, &cID);
if (error) NSLog(#"SoundPlayer doInit Error is %ld",error);
str = [[NSBundle mainBundle] pathForResource:#"blank.wav" ofType:#""];
uref = [NSURL fileURLWithPath:str];
error = AudioServicesCreateSystemSoundID ((CFURLRef)uref, &blID);
if (error) NSLog(#"SoundPlayer doInit Error is %ld",error);
AudioServicesPlaySystemSound (blID);
spinitialized = YES;
}
Then I could just play the "ding" without any delay using:
AudioServicesPlaySystemSound (cid);
SOLUTION
I ended up doing something similar as Mike above. I ended up playing the sound with the sound volume down in viewDidLoad:
NSURL *soundURL = [[NSBundle mainBundle] URLForResource:#"PlopsX4"
withExtension:#"aif"];
self.plops = [[AVAudioPlayer alloc] initWithContentsOfURL:soundURL error:nil];
[self.plops setVolume:0.0];
[self.plops play];
And then in the function where I play it I do:
[self.plops setVolume:1.0];
[self.plops play];
One thing I found that seems to help is, upon entry to the screen where the sound MIGHT be played, to play a fraction of a second of a sound. This seems to "prime" the sound mechanism -- allocating internal objects, paging in stuff, etc.
(I observe that this is similar to Mike M's approach.)

playing a sound in iOS smoothly

I have an object moving around the screen and once it reaches the edges it it changes direction and plays a sound this all works fine except that when it plays the sound I freezes for about half a second is there any way of making this run smoothly with the sound and object movement?
-(void)viewDidLoader
{
NSString *path1 = [[NSBundle mainBundle] pathForResource:#"ballbounce" ofType:#"mp3"];
ballbounce = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path1] error: NULL];
[ballbounce prepareToPlay];
}
-(void) ballcollition
{
[self ballplaysound]
enemy.center = CGPointMake(enemy.center.x+pos.x,enemy.center.y+pos.y);
if (enemy.center.x > 328 || enemy.center.x < 0)
{
pos.x = -pos.x;
}
}
-(void)ballplaysound
{
if (enemy.center.x > 328 || enemy.center.x < 0 ||enemy.center.y < 0||enemy.center.y < 300)
[ballbounce play];
}
use the System Sound for sound that plays smoothly.
Original NON-ARC answer:
#import <AudioToolbox/AudioToolbox.h>
- (IBAction)soundButton:(id)sender {
NSString *soundPath = [[NSBundle mainBundle] pathForResource:#"alert" ofType:#"wav"];
SystemSoundID soundID;
AudioServicesCreateSystemSoundID((CFURLRef)[NSURL fileURLWithPath: soundPath], &soundID);
AudioServicesPlaySystemSound (soundID);
[soundPath release];
}
Updated for ARC, and turned into a utility function:
- (void)soundPlay:(NSString*)waveName {
// wavName = #"alert" without any file extension (not alert.wav)
NSString *soundPath = [[NSBundle mainBundle] pathForResource:waveName ofType: #"wav"];
SystemSoundID soundID;
AudioServicesCreateSystemSoundID((__bridge CFURLRef)[NSURL fileURLWithPath: soundPath], &soundID);
AudioServicesPlaySystemSound (soundID);
}
Use AudioServicesPlaySystemSound(): https://developer.apple.com/library/ios/#documentation/AudioToolbox/Reference/SystemSoundServicesReference/Reference/reference.html
You can gain sound "smoothness" with AVPlayer by simply converting your mp3 to caf format as explained here.
1) Create AVAudioPLayer and cache it in your apps initialization code and never call it again
also call prepare as well.
2) so the method you included should only have to call play;
3) If you still get a skip use
[ballbounce performSelectorOnMainThread:#selector(play) withObject:nil];
Since you didnt include all the code and you are clearly doing drawing - putting the play method
on the queue could let the drawing code finish without interruption.
Doing this correctly might fix you. Using AudioSystemSound is much lower overhead but you should follow the same principles of preparing any often used sounds in your app initialization and not spawning them at the exact time you need them to avoid performance issues.

How to play a sound in objective C iphone coding

I have an app I am working on and It uses some of the hardware sensors to provide data on screen, there is a Label that updates with the number. I want a sound to play whenever the number is above 100 or something. For example, say it was reading numbers then all of the sudden it finds a good spot (or whatever), then I would like a sound to play or a light to light up. I am an absolute beginner and it would be nice if the answer would be easy for a absolute beginner to understand.
I am using the system AudioToolbox.framework for playing sounds in my simple game. I added this static function to common MyGame class:
+ (SystemSoundID) createSoundID: (NSString*)name
{
NSString *path = [NSString stringWithFormat: #"%#/%#",
[[NSBundle mainBundle] resourcePath], name];
NSURL* filePath = [NSURL fileURLWithPath: path isDirectory: NO];
SystemSoundID soundID;
AudioServicesCreateSystemSoundID((__bridge CFURLRef)filePath, &soundID);
return soundID;
}
I added the "Morse.aiff" file to project Resources and initialized it in (any) class initialization with the following:
self.mySound = [MyGame createSoundID: #"Morse.aiff"];
And then I played sound with this call:
AudioServicesPlaySystemSound(mySound);
Also, don't forget to import AudioServices.h file.
This audio toolbox can play also different sound formats.
h
#import <AVFoundation/AVFoundation.h>
#interface CMAVSound : NSObject {
AVAudioPlayer *audioPlayer;
}
- (id)initWithPath:(NSString*)fileNameWithExctension;
- (void)play;
#end
m
#import "CMAVSound.h"
#implementation CMAVSound
-(void)dealloc {
[audioPlayer release];
}
- (id)initWithPath:(NSString*)fileNameWithExctension {
if ((self = [super init])) {
NSURL *url = [NSURL fileURLWithPath:[NSString stringWithFormat:#"%#/%#", [[NSBundle mainBundle] resourcePath], fileNameWithExctension]];
NSError *error;
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];
if (audioPlayer == nil) {
NSLog(#"%#", [error description]);
}
}
return self;
}
- (void)play {
[audioPlayer play];
}
#end
Check out the documentation for the AVAudioPlayer class. It allows you to play sounds clips. If you have troubles implementing that, show us some code.
If the sounds gonna up to 5 seconds and no stereo output is needed I would recommend you to do that with system sounds. It is easy and better solution then any other.
Apple sample code is provided under name SysSound
EDIT1
Or maybe tutorial could help you more
http://howtomakeiphoneapps.com/2009/08/how-to-play-a-short-sound-in-iphone-code/
Take a look at following links;
http://blog.guvenergokce.com/avaudioplayer-on-iphone-simulator/57/
http://mobileorchard.com/easy-audio-playback-with-avaudioplayer/
Here you can find list of AudioServicesPlaySystemSound
http://iphonedevwiki.net/index.php/AudioServices

playing a sound, waiting it to finish playing and continue (iphone)

i'm new with the iphone and objective c, so far, I have been able to code some small examples.
i would like to play a sound and, continue with rest of the code when the sample finishes playing, i.e:
printf("hello");
playASound["file.wav"];
printf("world");
actually i'm getting: print hello, play the file and print world at the same time
but
what i want is: print hello, play the file, print world...
so, the question is how do i get it?
thanks
btw. here is the playASound code:
-(void) playASound: (NSString *) file {
//Get the filename of the sound file:
NSString *path = [NSString stringWithFormat:#"%#/%#",
[[NSBundle mainBundle] resourcePath],
file];
SystemSoundID soundID;
//Get a URL for the sound file
NSURL *filePath = [NSURL fileURLWithPath:path isDirectory:NO];
AudioServicesCreateSystemSoundID((CFURLRef)filePath, &soundID);
//play the file
AudioServicesPlaySystemSound(soundID);
}
From the documentation:
Discussion This function plays a short
sound (30 seconds or less in
duration). Because sound might play
for several seconds, this function is
executed asynchronously. To know when
a sound has finished playing, call the
AudioServicesAddSystemSoundCompletion
function to register a callback
function.
So you'll need to break up your function into two pieces: a function that calls PlayASound and prints "Hello", and a function that is called by the system when the sound is finished playing and prints "World".
// Change PlayASound to return the SystemSoundID it created
-(SystemSoundID) playASound: (NSString *) file {
//Get the filename of the sound file:
NSString *path = [NSString stringWithFormat:#"%#/%#",
[[NSBundle mainBundle] resourcePath],
file];
SystemSoundID soundID;
//Get a URL for the sound file
NSURL *filePath = [NSURL fileURLWithPath:path isDirectory:NO];
AudioServicesCreateSystemSoundID((CFURLRef)filePath, &soundID);
//play the file
AudioServicesPlaySystemSound(soundID);
return soundID;
}
-(void)startSound
{
printf("Hello");
SystemSoundID id = [self playASound:#"file.wav"];
AudioServicesAddSystemSoundCompletion (
id,
NULL,
NULL,
endSound,
NULL
);
}
void endSound (
SystemSoundID ssID,
void *clientData
)
{
printf("world\n");
}
See also docs for AudioServicesAddSystemSoundCompletion and AudioServicesSystemSoundCompletionProc.