Stop a sound Before PLaying another

2019-09-22 05:53发布

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);
   }

3条回答
姐就是有狂的资本
2楼-- · 2019-09-22 06:49

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.

查看更多
仙女界的扛把子
3楼-- · 2019-09-22 06:59

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 CFURLRefs you copy once you've created the SystemSoundID(so you don't leak memory). In fact you might consider making your CFURLRefs ivars so as not to constantly copy them. You also likely want to call AudioServicesDisposeSystemSoundID(soundID); in dealloc.

查看更多
霸刀☆藐视天下
4楼-- · 2019-09-22 06:59

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

查看更多
登录 后发表回答