I guess I could use AVAudioPlayer
to play a sound, however, what I need is to just play a short sound and I don't need any loops or fine-grained control over the volume etc.
Is there an easy way to do this?
I guess I could use AVAudioPlayer
to play a sound, however, what I need is to just play a short sound and I don't need any loops or fine-grained control over the volume etc.
Is there an easy way to do this?
Every single one of the other answers leaks memory (unless ARC is enabled for one of the answers)... oddly, the answer originally marked as correct has a call to retainCount
for no apparent reason.
If you alloc/init
something, it needs to be released (unless you are using ARC).
If you call AudioServicesCreateSystemSoundID()
you have to dispose of the resulting sound.
See the Audio UI Sounds example.
Basically:
@interface MyClass:UI*ViewController // fixed
{
SystemSoundID mySound;
}
@implementation MyClass
- (void) viewDidLoad {
[super viewDidLoad];
AudioServicesCreateSystemSoundID(.... URL ...., &mySound);
}
- (void) playMySoundLikeRightNowReally {
AudioServicesPlaySystemSound(mySound);
}
- (void) dealloc {
AudioServicesDisposeSystemSoundID(mySound);
[super dealloc]; // only in manual retain/release, delete for ARC
}
@end
For completeness:
add AudioToolbox.framework
#import <AudioToolbox/AudioToolbox.h>
aif
file but I don't hear any sound in the simulator... –
Kuchen caf
files, could it be that this does not work in the Simulator? Are there better file types to use? –
Kuchen AudioServicesCreateSystemSoundID((__bridge CFURLRef)mySoundNSURL, &_mySound);
–
Gusty [super viewDidLoad]
on a subclass of NSObject
. ;) –
Microvolt For short sound clips (less than 30 secs), there's a SystemSounds library which is really nice.
Pros: You don't need to manage volume settings separately. The sound is played in a separate thread and loading and playing of audio clip is v fast. In short, you treat this clip as another system sound.
Cons: You can't provide a separate audio control setting. It's tied to the settings of the system sounds. You can't play more than 30 seconds. You probably can't apply any sound filters to enhance audio effect.
There are certainly more pros and cons, but these are some I could think of, off the top of my head.
use this import: <AudioToolbox/AudioToolbox.h>
Add the AudioToolbox Framework
then call the below method like [self playSound], wherever you want to play the clip.
-(void) playSound {
NSString *soundPath = [[NSBundle mainBundle] pathForResource:@"changeTrack" ofType:@"aif"];
SystemSoundID soundID;
AudioServicesCreateSystemSoundID((CFURLRef)[NSURL fileURLWithPath: soundPath], &soundID);
AudioServicesPlaySystemSound (soundID);
[soundPath release];
}
retainCount
(and the commented [soundPath release]
) indicates a bit of a misconception of the memory management.... –
Clapp aif
file but I don't hear any sound in the simulator... –
Kuchen The other answers here use Objective-C so I am providing a Swift version here. Swift uses Automatic Reference Counting (ARC), so I am not aware of any memory leak issues with this answer (as warned about in the accepted answer).
You can use the AudioToolbox
framework to play short sounds when you do not need much control over how they are played.
Here is how you would set it up:
import UIKit
import AudioToolbox
class PlaySoundViewController: UIViewController {
var soundURL: NSURL?
var soundID: SystemSoundID = 0
@IBAction func playSoundButtonTapped(sender: AnyObject) {
let filePath = NSBundle.mainBundle().pathForResource("yourAudioFileName", ofType: "mp3")
soundURL = NSURL(fileURLWithPath: filePath!)
if let url = soundURL {
AudioServicesCreateSystemSoundID(url, &soundID)
AudioServicesPlaySystemSound(soundID)
}
}
}
Notes:
yourAudioFileName.mp3
(or .wav
, etc) to your project.import AudioToolbox
By importing the AVFoundation
framework, you can use AVAudioPlayer
. It works for both short audio clips and long songs. You also have more control over the playback than you did with the AudioToolbox method.
Here is how you would set it up:
import UIKit
import AVFoundation
class PlaySoundViewController: UIViewController {
var mySound: AVAudioPlayer?
// a button that plays a sound
@IBAction func playSoundButtonTapped(sender: AnyObject) {
mySound?.play() // ignored if nil
}
override func viewDidLoad() {
super.viewDidLoad()
// initialize the sound
if let sound = self.setupAudioPlayerWithFile("yourAudioFileName", type: "mp3") {
self.mySound = sound
}
}
func setupAudioPlayerWithFile(file: NSString, type: NSString) -> AVAudioPlayer? {
let path = NSBundle.mainBundle().pathForResource(file as String, ofType: type as String)
let url = NSURL.fileURLWithPath(path!)
var audioPlayer: AVAudioPlayer?
do {
try audioPlayer = AVAudioPlayer(contentsOfURL: url)
} catch {
print("Player not available")
}
return audioPlayer
}
}
Notes:
import AVFoundtation
and to add yourAudioFileName.mp3
to your project.AudioServicesPlaySystemSound
is that if the user has the mute button on then the sounds will not be played. That makes sense in some respects, but depending on your application the user may still expect to hear a sound. –
Haleyhalf Recently, I used this code to play short mp3 audio which worked fine:-
Declare this below the @implementation
NSString *path;
NSURL *url;
//where you are about to add sound
path =[[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"quotes_%d",soundTags] ofType:@"mp3"];
url = [NSURL fileURLWithPath:path];
player = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:NULL];
[player setVolume:1.0];
[player play];
//just add AVFoundation framework
[player setVolume:1.0];
should come after creating the player. –
Truly I used this code to play a short aiff-sound on iOS
#import <AudioToolbox/AudioServices.h>
SystemSoundID completeSound;
NSURL *audioPath = [[NSBundle mainBundle] URLForResource:@"downloadCompleted" withExtension:@"aiff"];
AudioServicesCreateSystemSoundID((CFURLRef)audioPath, &completeSound);
AudioServicesPlaySystemSound (completeSound);
Hope this helps.
m4a
to aif
using iTunes and now I don't hear any sound in the simulator, can you tell me what approach you have used for the conversion? –
Kuchen SIMPLE CLEAN SWIFT 3 VERSION
I like more control over my sounds so I'm using AVFoundation.
import AVFoundation
class TodayViewController: UIViewController {
var clink: AVAudioPlayer?
var shatter: AVAudioPlayer?
override func viewDidLoad() {
super.viewDidLoad()
// initialize the sound
shatter = setupAudioPlayer(withFile: "shatter", type: "wav")
clink = setupAudioPlayer(withFile: "clink", type: "wav")
}
func setupAudioPlayer(withFile file: String, type: String) -> AVAudioPlayer? {
let path = Bundle.main.path(forResource: file, ofType: type)
let url = NSURL.fileURL(withPath: path!)
return try? AVAudioPlayer(contentsOf: url)
}
func onClick() {
clink?.play()
}
}
Make sure you sound file is added to your project and you import AVFoundation.
My answer is Bill's answer, but I use it without the class init or dealloc, loading the sound only when needed and releasing the sound directly after it's played:
- (void)playSound:(NSURL *)url
SystemSoundID ssID = 0;
AudioServicesCreateSystemSoundID((CFURLRef)url, &ssID);
AudioServicesAddSystemSoundCompletion(ssID, NULL, NULL, (AudioServicesSystemSoundCompletionProc)MyAudioServicesSystemSoundCompletionProc, NULL);
AudioServicesPlaySystemSound(ssID);
}
void MyAudioServicesSystemSoundCompletionProc (SystemSoundID ssID, void *clientData) {
AudioServicesDisposeSystemSoundID(ssID);
}
import AudioToolbox
func playSoundEasy(note : String) {
var soundURL: NSURL?
var soundID: SystemSoundID = 0
let filePath = Bundle.main.path(forResource: note, ofType: "wav")
soundURL = NSURL(fileURLWithPath: filePath!)
if let url = soundURL {
AudioServicesCreateSystemSoundID(url, &soundID)
AudioServicesPlaySystemSound(soundID)
}
}
Heres a quick clean method you can copy in and use in your app:
-(BOOL) playSoundFXnamed: (NSString*) vSFXName Loop: (BOOL) vLoop
{
NSError *error;
NSBundle* bundle = [NSBundle mainBundle];
NSString* bundleDirectory = (NSString*)[bundle bundlePath];
NSURL *url = [NSURL fileURLWithPath:[bundleDirectory stringByAppendingPathComponent:vSFXName]];
AVAudioPlayer *audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];
if(vLoop)
audioPlayer.numberOfLoops = -1;
else
audioPlayer.numberOfLoops = 0;
BOOL success = YES;
if (audioPlayer == nil)
{
success = NO;
}
else
{
success = [audioPlayer play];
}
return success;
}
Then to use just:
[self playSoundFXnamed:@"someAudio.mp3" Loop: NO];
If you're gonna loop then you need to take your AVAudioPlayer *audioPlayer
out into your class to be able to stop the sound.. Which you dont if you just want a short sound.
Use ARC... and I never did do anything with the NSError, so use it if ya like...
A lot of answers are confusing, and some are using the AudioToolbox
framework, different from the AVAudioFoundation
framework... here's what I did. In the .h
file, I put this code in:
@property (nonatomic, retain) AVAudioPlayer *player;
This code declares an audio player named "player." In the .m
file, under your @implementation
declaration, add @synthesize player
. This synthesizes that player
property.
In whatever function you want, tie your sound in to the player by adding this line of code, where yourSound
is the name of the sound file, and aif
is your file extension:
player = [[AVAudioPlayer alloc] initWithContentsOfURL:[[NSBundle mainBundle] URLForResource:@"yourSound" withExtension:@"aif"] error:nil]
I know the Apple Documentation says to declare a string and a NSURL, but if you combine it into one line, then you won't have to dispose of it afterwards. Also, since this is a property in your ViewController.m
file, then you won't have to keep setting that player
object to tie in with your sound.
Other answers also included using a SystemSoundID
, but that also imposes restrictions like, "the file can't be over 30 seconds long," "it has to be in a specific format," and the works. With that, it can play several sounds at a time (in case you're developing a soundboard), and it's easier to create the sounds.
To actually play your sound, insert this line (and yes, it's really this easy):
[player play]
If you use ARC, you can't manually dispose of the player, as the system will do it for you. If you're new to developing and you're using the latest version of Xcode, then you have ARC enabled. If, for some strange reason, you don't, then the code for disposing of the resources being used by player
is:
[player release]
From Sound does only work on Device but not in Simulator
Nick created a library which can be used for playing sounds in iOS and Mac Apps.
Please refer to Simple iOS audio playback
- (void)playSound
{
SystemSoundID soundId;
// NSURL *soundURL = [[NSBundle mainBundle] URLForResource:@"sample"
// withExtension:@"caf"];
// AudioServicesCreateSystemSoundID((__bridge CFURLRef)soundURL, &soundId);
NSString *path = [[NSBundle mainBundle] pathForResource:@"sample" ofType:@"mp3"];
AudioServicesCreateSystemSoundID((__bridge CFURLRef)[NSURL fileURLWithPath:path], &soundId);
AudioServicesAddSystemSoundCompletion(soundId,
NULL,
NULL,
systemAudioCallback,
NULL);
AudioServicesPlaySystemSound(soundId);
//AudioServicesPlayAlertSound(soundId);
}
- (void) systemAudioCallback(SystemSoundID soundId, void *clientData)
{
AudioServicesRemoveSystemSoundCompletion(soundId);
AudioServicesDisposeSystemSoundID(soundId);
}
Check out systemsound to play short audio file
include audiotoolbox framework
and create
systemsoundid object
NSString *soundPath = [[NSBundle mainBundle] pathForResource:file ofType:@"aiff"];
AudioServicesCreateSystemSoundID((CFURLRef)[NSURL fileURLWithPath: soundPath], &soundID);
AudioServicesPlaySystemSound (soundID);
© 2022 - 2024 — McMap. All rights reserved.