How To Play Sounds – AVAudioPlayer Tutorial (For 2019)

In this AVAudioPlayer tutorial, we’re going to go through an example of playing a sound file that you’ve added to your Xcode project.

You’ll see that it’s actually a really simple task to accomplish!

Adding the framework to your project

The first thing we’ll need to do is to add the AVFoundation framework to the project.

In the General tab of your Xcode project properties, the frameworks and libraries section is all the way at the bottom. If you click the “+” icon, you’ll get a dialog and you can search for the AVFoundation Framework to add it.

Adding the sound file to your project

For this demo, we’re going to need a sample mp3 or wav sound file. You can find a short clip on the net or download the source code for this demo to use the sample MP3 that I used.

When you have a sound file, simply drag it into your Xcode project and it’ll add the file as a resource to your project. (Make sure to select [] Copy if needed)

Importing the framework

In the class that you want to play a sound, you’re going to have to import the AVFoundation classes. At the top of the ViewController.swift file, import the framework like this:

import AVFoundation

Creating and initializing the AVAudioPlayer object

In my demo, I’m going to play a sound in the ViewController class so I’m going to create an instance variable in ViewController.swift to hold the AVAudioPlayer object:

var audioPlayer = AVAudioPlayer()

Then in the viewDidLoad method, I’m going to create a new AVAudioPlayer object and initialize it with the path to the sound file like this:

Observe that we are using Bundle to find our way inside the app to go find the file named “drum” which is of type “mp3“.
After this we initialize the player inside a Do Catch block because we need to be safe and be prepared in case one day, the app isn’t able to load or find the audio file. It’s better to display or print an error rather than having the user experience a crash. This is all it takes for a user to delete your app.

Playing the sound

Whereever you want to play the sound, simply call the play method of the AVAudioPlayer object!

audioPlayer.play()

To make things more interesting, I decided to add a button to the Storyboard.

I changed the text property to “Drum!” and centered the button vertically and horizontally to not have to worry about any device’s size.

Finally, the button can be linked to a @IBAction in our ViewController.swift file.

Inside the @IBAction function, you can add the .play() method and run your project. The drum should be playing well after each tap of the button. If it doesn’t work, make sure you didn’t make a typo in the file name or extension. At the end, your code should look like the following:


_________________________________________________________________________

The AVAudioPlayer class has other properties to control playback (such as the number of times to loop) as well as properties that give you information about the sound file (such as the duration).

Check out the Apple class reference document for more information!

24 Comments

  1. Thank you so much, this is great. It works on a simulator, but when I try to run the code it on my iPhone, it doesn’t work. Do you know what I should change? Should I have stored my audio somewhere different or added on something to the code? This is the line where the code breaks:

    try audioPlayer = AVAudioPlayer(contentsOf: URL (fileURLWithPath: dogSound!))

    Reply
  2. Hey Cris a quick question about audio files. What if we want to allow to users for upload own audio file with may be clicking button or selector like picker ? How can we solve this ?

    Reply
  3. Hi chris!

    I have done the same thing as you explained but i am unable to get sound when my app is in background. When the app is in foreground i get the ring sound but not in case when the app is in background from the beginning. I have been able to get it working on the simulator but its not working on my device and yes i have checked my sounds its set to full.

    Waiting for your response
    Thanls

    Reply
  4. Thank you
    Chris,
    I face the issue about audio is playing but audio sound doesn’t come out , only sound come out when I connect earphones . I can’t figure out about this . Would you please help.

    Reply
  5. Hi Chris,
    Thank you for your awesome site!so much great info, and I’m learning a lot!

    I have a question. How can I make the response time of the drum when I tap it a faster response? When I tap quickly the drum sound misses one of my taps. Does this have anything to do with “enabling rate”? I modified my drum sound wave file which made it a little but not perfect. Would you happen to know a solution.

    Best
    Gil

    Reply
    • Hi Gil! It’s possible that the sounds will be much more responsive if you ran the app on a physical device instead of the simulator.

      Reply
  6. Thank You Chris,

    Similar to one of the other comments. The program I’m working on is for my troops and friends. The lessons are broken down into section, I’m trying to give each section it’s own table view.
    My ambition is the user clicks on the lesson of the day and the audio plays.
    They could then use a tool bar to pause the lesson, in order to open up other programs for reference material.
    I’ve seen a lot of similar to what you noted above but only one closer to what I’m trying to pull off.

    Thank You,
    Mohamed

    Reply
  7. Hi Chris:

    Thank you for all your tutorials, they are great!! I am getting an error message which I can’t figure out… “Thread 1: EXC_BAD_ACCESS (code=1, address=0x48)”

    Here is my code: the error is appearing on the line “audioPlayer.play()”. HELP! 🙂
    —-

    import UIKit
    import AVFoundation

    class ViewController: UIViewController {

    var audioPlayer = AVAudioPlayer()

    override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view.

    let sound = Bundle.main.path(forResource: “HelloWomanVoice”, ofType:”mp3″)

    do{
    audioPlayer = try AVAudioPlayer(contentsOf: URL(fileURLWithPath: sound!))

    }
    catch {
    print (error)
    }

    }

    @IBAction func Category1Click(_ sender: Any) {

    audioPlayer.play()

    }

    }

    Reply
    • I had a similar problem. I found that changing:
      var audioPlayer = AVAudioPlayer()
      to:
      var audioPlayer: AVAudioPlayer!
      got rid of the crash.
      I don’t yet understand why that is, so an explanation as to how this change eliminated this problem, or why this might not work would be helpful.

      Reply
  8. Thanks Chris! I am working on an educational foreign language app, and this tutorial worked like a charm!!!
    I also made sure to make a note in the code and give you credit, as I used and adapted your tutorial.

    Reply
  9. Hi Christ
    I was failed in writing a function to replace the contents in viewDidLoad that supplies a global sound-name.
    If I can make that function to provide the soundName separately then I can play
    other sounds by using this function before calling [_audioPlayer play]
    At moment, I have to copy the whole code to change to
    other sounds when it finishes playing
    Would you please help.

    Reply
  10. Hello! i added this:

    – (void)viewDidLoad
    {
    [super viewDidLoad];

    // Construct URL to sound file
    NSString *path = [NSString stringWithFormat:@”%@/drum01.mp3″, [[NSBundle mainBundle] resourcePath]];
    NSURL *soundUrl = [NSURL fileURLWithPath:path];

    // Create audio player object and initialize with URL to sound
    _audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:soundUrl error:nil];
    }

    2 times but i changed the _audioplayer to another name. But then they said an error saying that redefinition of “path” and “soundUrl”!
    What should i do to fix the redefinition of this error?

    Reply
  11. Thanks Chris, this is awesome! I have multiple buttons that play sounds on my main view. How would I make it so these sounds don’t overlap if I touch multiple buttons?

    Reply
    • You add the AVAudioPlayerDelegate protocol, then make a global BOOL isPlayingAudio and use the correct methods in that delegate to update the boolean before playing the next file. Or you can globally initialize the _audioPlayer and tell the _audioPlayer to stop before playing the next one by doing the following: [_audioPlayer stop]; //change file path here// then [_audioPlayer play];

      Take note: AVAudioPlayer INTERRUPTION NOTIFICATIONS ARE DEPRECATED – Use AVAudioSession instead.

      Reply

Leave a Reply to mohamed benabdallah Cancel reply

Share
Tweet
Pin
Share
Buffer