Play a short sound in iOS

IosAudio

Ios Problem Overview


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?

Ios Solutions


Solution 1 - Ios

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>

Solution 2 - Ios

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

Solution 3 - Ios

Swift

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).

Using AudioToolbox

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:

  • This example is adapted from How to play a short sound clip with AudioToolbox in Swift.
  • Remember to add yourAudioFileName.mp3 (or .wav, etc) to your project.
  • Remember to import AudioToolbox
  • This answer puts the code in an IBAction button tap, but it could just as easily be put in another function, of course.

Using AVAudioPlayer

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:

Solution 4 - Ios

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

Solution 5 - Ios

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.

Solution 6 - Ios

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.

Solution 7 - Ios

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

Solution 8 - Ios

Using Swift 4

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

Solution 9 - Ios

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...

Solution 10 - Ios

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]

Solution 11 - Ios

From https://stackoverflow.com/questions/10351199/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.

See nicklockwood/SoundManager

Solution 12 - Ios

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

Solution 13 - Ios

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionBesiView Question on Stackoverflow
Solution 1 - IosbbumView Answer on Stackoverflow
Solution 2 - IosHimanshu SinghView Answer on Stackoverflow
Solution 3 - IosSuragchView Answer on Stackoverflow
Solution 4 - IosArshad ParwezView Answer on Stackoverflow
Solution 5 - IosSchulze ThomasView Answer on Stackoverflow
Solution 6 - IosRob NorbackView Answer on Stackoverflow
Solution 7 - IosConorView Answer on Stackoverflow
Solution 8 - IosVictorSimplifyView Answer on Stackoverflow
Solution 9 - IosAndres CanellaView Answer on Stackoverflow
Solution 10 - IosDDPWNAGEView Answer on Stackoverflow
Solution 11 - IosBesiView Answer on Stackoverflow
Solution 12 - IoslmnbeyondView Answer on Stackoverflow
Solution 13 - Iossanjeev sharmaView Answer on Stackoverflow