How to record and play sound in Swift

In this tutorial, we are going to see the required steps to record and play sound in Swift Programming language using AVAudioRecorder and AVAudioPlayer

Download source code from github (SoundController.swift)

User Interface

The user interface for this demo is simple with two buttons, one for recording and another for playing sound.

201504121626.jpg

Create corresponding IBAction and IBOutlets from the two button in the View Controller.

@IBOutlet weak var recordButton: UIButton!

@IBOutlet weak var playButton: UIButton!

@IBAction func recordSound(sender: UIButton)

@IBAction func playSound(sender: UIButton)

Dual Purpose Buttons

The Record button will be used to record and stop recording. Similarly the Play button will used to Play and Stop the audio.

Class level var and let declaration

  var soundRecorder: AVAudioRecorder!

var soundPlayer:AVAudioPlayer!

  

let fileName = “demo.caf”

Declare two class level variable for holding an instance of AVAudioRecorder and AvAudioPlayer. Also create constant for holding the file name.

Create Sound file path

For this demo, the sound file will be created under the Cache directory using the name defined in the constant. Add these two function to your class

  func getCacheDirectory() -> String {

  

let paths = NSSearchPathForDirectoriesInDomains(.CachesDirectory,.UserDomainMask, true) as [String]

  

return paths[0]

}

  

func getFileURL() -> NSURL {

  

let path = getCacheDirectory().stringByAppendingPathComponent(fileName)

let filePath = NSURL(fileURLWithPath: path)

  

return filePath!

}

The getCacheDirectory retrieves the caches directory and getFileURL appends the file name with the cache directory.

Setup Recorder

Create a new function that prepares the recorder and this function will be called during the viewDidLoad operation

func setupRecorder() {

  

//set the settings for recorder

  

var recordSettings = [

AVFormatIDKey: kAudioFormatAppleLossless,

AVEncoderAudioQualityKey : AVAudioQuality.Max.rawValue,

AVEncoderBitRateKey : 320000,

AVNumberOfChannelsKey: 2,

AVSampleRateKey : 44100.0

]

  

var error: NSError?

  

soundRecorder = AVAudioRecorder(URL: getFileURL(), settings: recordSettings, error: &error)

  

if let err = error {

println(“AVAudioRecorder error: \(err.localizedDescription))

} else {

soundRecorder.delegate = self

soundRecorder.prepareToRecord()

}

}

To create an AVAudioRecorder instance, you need to pass three parameters,

URL– Specifies the path and name of the file where the sound will be recorded.

settings – Configure AVRecorder settings

error – Capture error while creating AVRecorder instance.

If there is no error while creating Audio Recorder, the delegate it set to the View Controller and recorder is prepared for recording. Make sure the View Controller conforms to AVAudioRecorderDelegate

class SoundController: UIViewController, AVAudioRecorderDelegate {

Prepare Player

Add the following function that prepares the AVAudiPlayer to play the recorded sound

func preparePlayer() {

var error: NSError?

  

soundPlayer = AVAudioPlayer(contentsOfURL: getFileURL(), error: &error)

  

if let err = error {

println(“AVAudioPlayer error: \(err.localizedDescription))

} else {

soundPlayer.delegate = self

soundPlayer.prepareToPlay()

soundPlayer.volume = 1.0

}

}

AVAudioPlayer instance is created by passing sound file that needs to be played along with pointer to capture errors while creating AVAudioPlayer instance. Make sure the View Controller conforms to AVAudioPlayerDelegate. Then call the prepareToPlay function on the AVAudioPlayer instance.

Implement IBActions function to record and play sound

Add the following implementation to the IBAction functions which records and plays sound.

@IBAction func recordSound(sender: UIButton) {

if (sender.titleLabel?.text == “Record”){

soundRecorder.record()

sender.setTitle(“Stop”, forState: .Normal)

playButton.enabled = false

} else {

soundRecorder.stop()

sender.setTitle(“Record”, forState: .Normal)

}

}

  

@IBAction func playSound(sender: UIButton) {

if (sender.titleLabel?.text == “Play”){

recordButton.enabled = false

sender.setTitle(“Stop”, forState: .Normal)

preparePlayer()

soundPlayer.play()

} else {

soundPlayer.stop()

sender.setTitle(“Play”, forState: .Normal)

}

}

When the Record button is tapped, the name of the button is changed to Stop and starts recording the sound. Similarly when the title is Stop, the recording the stopped and play button is enabled. The same is done when the user taps the play button.

class SoundController: UIViewController, AVAudioRecorderDelegate, AVAudioPlayerDelegate {

Implement AVAudioRecorderDelegate methods

  func audioRecorderDidFinishRecording(recorder: AVAudioRecorder!, successfully flag: Bool) {

playButton.enabled = true

recordButton.setTitle(“Record”, forState: .Normal)

}

  

func audioRecorderEncodeErrorDidOccur(recorder: AVAudioRecorder!, error: NSError!) {

println(“Error while recording audio \(error.localizedDescription))

}

Implement AVAudioPlayerDelegate methods

  func audioPlayerDidFinishPlaying(player: AVAudioPlayer!, successfully flag: Bool) {

recordButton.enabled = true

playButton.setTitle(“Play”, forState: .Normal)

}

  

func audioPlayerDecodeErrorDidOccur(player: AVAudioPlayer!, error: NSError!) {

println(“Error while playing audio \(error.localizedDescription))

}

Now you are good to go and try this demo. You can download the source code for recording and playing audio in swift from github.


Comments

10 responses to “How to record and play sound in Swift”

  1. Joaquin Aguilar Avatar
    Joaquin Aguilar

    Thank you so much for this tutorial. It’s very helfull to an absolute beginner like me. However, I an looking to program an even simpler app. I need it to have two buttons. One that records and another one that plays back without saving to a file. I want to press record; not pause or save but rather, press the play button and have the app play back the reasent recording. Press record again; have the previous recording purged and so on. Record – play, record – play and so on and on.
    I think this is a stripped down version of your demo app, but, being a total novice, I don’t know what parts of your code need to be stripped or modified. Can you help please?

    1. Hi Joaquin,
      That is exactly what the code does. Record -> saves to cache / Play -> reads from cache.
      Hit Record again -> overwrites cache / Play -> reads from new cache.
      So good news, no stripping needed! Just try it!
      Cheers

  2. Hi love this website! can you convert the program to swift 2 as its throwing up errors i don’t understand

    1. The project has been updated for Swift 2.0, Could you please try now. – https://github.com/rshankras/SwiftDemo

  3. Hey Ravi, thank you for posting up your tutorial, I love how it has the bare bones so I can see exactly what we’re working on. However, I seem to be having some problems with this line of code:
    soundRecorder = AVAudioRecorder(URL: getFileURL(), settings: recordSettings as [NSObject : AnyObject], error: &error)

    “Xcode is telling me that “cannot capture “getfileurl” before it is declared”

    I was wondering if you had any suggestion in order to move forward?

    Thanks!

    1. Thanks. I have made some changes for Swift 2.0 (Xcode 7.0), could you please take the latest from gitHub (https://github.com/rshankras/SwiftDemo). The problematic line is now changed to

      soundRecorder = try AVAudioRecorder(URL: getFileURL(), settings: recordSettings)

  4. Hi rshankar,
    your project only works on simulator, don’t work on devices. I have tested this examples and didn’t work. I think the problem is in the cache path. Do you have a solution ?

  5. jyothireddy Avatar
    jyothireddy

    Thank you ver Much providing this tutorial

  6. Why don’t hear music after recording while headphone is plugged in? What is the solution to record audio in headphone plugged in and out?

  7. Suyog Ghinmine Avatar
    Suyog Ghinmine

    The post is really in depth and step by step unlike a lot of other ones I have read so far. I just hope you write a new one for Swift 5. This program doesn’t run anymore on the latest Xcode 10 and Swift 5

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.