I know that this has been asked before on here, but i didn't understand the responses. I am making a soundboard, and when you click one of the buttons to play a sound, i would like the one that was already playing to stop. I know i need to add AudioServicesDisposeSystemSoundID(soundID);
, but where do i add it? Here is my code:
- (IBAction)beyond:(id)sender {
CFBundleRef mainBundle = CFBundleGetMainBundle();
CFURLRef soundFileURLRef;
soundFileURLRef = CFBundleCopyResourceURL(mainBundle, (CFStringRef) @"beyond" ,CFSTR ("wav") , NULL);
UInt32 soundID;
AudioServicesCreateSystemSoundID(soundFileURLRef, &soundID);
AudioServicesPlaySystemSound(soundID);
}
- (IBAction)Years:(id)sender {
CFBundleRef mainBundle = CFBundleGetMainBundle();
CFURLRef soundFileURLRef;
soundFileURLRef = CFBundleCopyResourceURL(mainBundle, (CFStringRef) @"years" ,CFSTR ("wav") , NULL);
UInt32 soundID;
AudioServicesCreateSystemSoundID(soundFileURLRef, &soundID);
AudioServicesPlaySystemSound(soundID);
}
The problem here is you defined soundID as a local variable within your method, instead of as an instance variable within your class. When you use an instance variable, you can access it later from any method in the class.
As bneely said. You need to create an instance variable (or ivar) so that multiple methods can reference the same variable. And as you already know AudioServicesDisposeSystemSoundID()
stops the currently playing SystemSoundID
. And once you declare an ivar you don't need to declare the variable in each method. So the logical conclusion would be.
@implementation ViewControllerClassNameHere{
SystemSoundID soundID;
}
- (IBAction)beyond:(id)sender {
AudioServicesDisposeSystemSoundID(soundID);
CFBundleRef mainBundle = CFBundleGetMainBundle();
CFURLRef soundFileURLRef;
soundFileURLRef = CFBundleCopyResourceURL(mainBundle, (CFStringRef) @"beyond" ,CFSTR ("wav") , NULL);
AudioServicesCreateSystemSoundID(soundFileURLRef, &soundID);
AudioServicesPlaySystemSound(soundID);
}
- (IBAction)Years:(id)sender {
AudioServicesDisposeSystemSoundID(soundID);
CFBundleRef mainBundle = CFBundleGetMainBundle();
CFURLRef soundFileURLRef;
soundFileURLRef = CFBundleCopyResourceURL(mainBundle, (CFStringRef) @"years" ,CFSTR ("wav") , NULL);
AudioServicesCreateSystemSoundID(soundFileURLRef, &soundID);
AudioServicesPlaySystemSound(soundID);
}
You also might (will definitely) want to CFRelease()
the CFURLRef
s you copy once you've created the SystemSoundID
(so you don't leak memory). In fact you might consider making your CFURLRef
s ivars so as not to constantly copy them. You also likely want to call AudioServicesDisposeSystemSoundID(soundID);
in dealloc
.
It is answered before:
Stopping sound in Xcode
But I can repeat my answer.
Summarizing, the sentence to STOP the sound file is:
AudioServicesDisposeSystemSoundID (soundFileObject);
Explanation (Important to understand):
I have a table view with 18 different sound files. When user select a row must sound the corresponding file and when select another row, it must STOP the previous sound and play other.
All this stuff it is necessary:
1) Add to your project "AudioToolbox.framework" inside "Build Phases", inside "Link Binary With Libraries"
2) In header file (in my project it calls "GenericTableView.h") add these sentences:
#include <AudioToolbox/AudioToolbox.h>
CFURLRef soundFileURLRef;
SystemSoundID soundFileObject;
@property (readwrite) CFURLRef soundFileURLRef;
@property (readonly) SystemSoundID soundFileObject;
3) In implement file (in my project it calls "GenericTableView.m") add these sentences:
@synthesize soundFileURLRef;
@synthesize soundFileObject;
And inside your "Action" implementation or in my case, in:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// -----------------------------------------------------------------------
// -----------------------------------------------------------------------
// -----------------------------------------------------------------------
//
// That is the question: a way to STOP sound file
//
// -----------------------------------------------------------------------
// Very important to STOP the sound file
AudioServicesDisposeSystemSoundID (soundFileObject);
// -----------------------------------------------------------------------
// -----------------------------------------------------------------------
// -----------------------------------------------------------------------
// In my project "rowText" is a field that save the name of the
// corresponding sound (depending on row selected)
// It can be a string, @"Alarm Clock Bell" in example
// Create the URL for the source audio file.
// URLForResource:withExtension: method is new in iOS 4.0.
NSURL *soundURL = [[NSBundle mainBundle] URLForResource:rowText withExtension:@"caf"];
// Store the URL as a CFURLRef instance
self.soundFileURLRef = (CFURLRef) [soundURL retain];
// Create a system sound object representing the sound file.
AudioServicesCreateSystemSoundID (soundFileURLRef,&soundFileObject);
AudioServicesPlaySystemSound (soundFileObject);
[soundURL release];
}
4) Finally, in the same implement file (in my project it calls "GenericTableView.m"):
- (void)dealloc {
[super dealloc];
AudioServicesDisposeSystemSoundID (soundFileObject);
//CFRelease (soundFileURLRef);
}
I must to comment "CFRelease (soundFileURLRef)" because the App ends unexpectedly when user leaves the table view.
All this code is proportioned by Apple. In this link you can find even a sample code to test directly in your iPhone simulator.
https://developer.apple.com/library/ios/samplecode/SysSound/Introduction/Intro.html#//apple_ref/doc/uid/DTS40008018-Intro-DontLinkElementID_2