Play with Audio in Swift 3.0

Audio recording and playing is not a tough task in iOS but it takes time to understand and implement. There is a framework called AVFoundation which will help you to record sound.

Steps To Record Sound:

1.  Import Framework AVFoundation: 

To record and play audio first you need to import a framework AVFoundation. This framework will provide you classes and properties to record sound. To import this framework in your code open your project. Write the given line on the top of you class:

import AVFoundation

2. Create and set record session:

For that you need to define two instance variable as given below:

var audioPlayer: AVAudioPlayer?
var recordSetting = Dictionary() as [String: Any]

Now time to initialize the settings for recording:

recordSetting[AVFormatIDKey] = NSNumber(value: kAudioFormatMPEG4AAC)
recordSetting[AVSampleRateKey] = 44100.0
recordSetting[AVNumberOfChannelsKey] = 1

let docDir = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
let fileURL = docDir.appendingPathComponent("Audio").appendingPathExtension("m4a")
do {
    audioRecorder = try AVAudioRecorder(url: fileURL, settings: recordSetting)
} catch {
    print(error)
}
self.audioRecorder?.delegate = self
self.audioRecorder?.isMeteringEnabled = true
self.audioRecorder?.prepareToRecord()

Here  AVFormatIDKey is a format identifier. Here you define the format of recorded audio.
>  AVSampleRateKey is a 
sample rate, in hertz, expressed as an NSNumber floating point value.
>  isMeteringEnabled  is a Boolean value that indicates whether audio-level metering is enabled. By default, audio level metering is off for an audio recorder.
>  prepareToRecord()  method creates an audio file and prepare the system for recording. It creates an audio file at the location specified by url in init(url: setting: ) method. If a file already exists at the given location, it overwrites it.

3. Start Recording:

To start recording now you just need to get the AVAudioSession ‘s shared instance and call a single method record(). But make sure you have initialize all the settings of recording.

let audioSession = AVAudioSession.sharedInstance()
try? audioSession.setActive(true)
try? audioSession.setCategory(AVAudioSessionCategoryPlayAndRecord, with: AVAudioSessionCategoryOptions.defaultToSpeaker)
            
// Start recording 
self.audioRecorder?.record()

> First start a session of AVAudioSession with shared instance.
setActive(bool:) activates or deactivates your app session. If another audio session has higher priority than your audio session will fail.
func setCategory(_ category: with option:) used to set the audio category and mode which define how the application intend to use audio.
Now, to start recording, call record()  method. It will start recording.

4.  AVAudioRecorderDelegate:

Here are basically four delegate methods:

  • audioRecorderEncodeErrorDidOccur(_ recorder: AVAudioRecorder, error: Error?)
    This method will report you when any error occurred while encoding.

  • audioRecorderBeginInterruption(_ recorder: AVAudioRecorder)
    This method will give you callback when recording is interrupted.

  • audioRecorderEndInterruption(_ recorder: AVAudioRecorder, withOptions flags: Int) 
    This method is called when the interruption has ended.

  • audioRecorderDidFinishRecording(_ recorder: AVAudioRecorder, successfully flag: Bool)
    This method is called when the recording is finished or stoped. 

5.  Stop or Pause Recording:

You can call the given method to stop recording

func stopRecording() {
     audioRecorder?.stop()
     let session = AVAudioSession.sharedInstance()
     try? session.setActive(false)
}

Here you can call stop() to stop recording and pause() to pause recording. It you pause recording you can resume it by calling record() method.

Play with Audio:

Here are some task related to play audio:

  1. Play an audio
  2. Pause an audio
  3. Stop

1. Play an audio:

To play audio there are two easy steps:

  1. Create object of AVAudioPlayer with file path
  2. Call play() on that object
let docDir = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
let fileURL = docDir.appendingPathComponent("Audio").appendingPathExtension("mp3")
let audioPlayer = try? AVAudioPlayer(contentsOf: fileURL!)

// Play audio
audioPlayer?.play()

There are three places where an audio can be found:

  1.  App bundle:  You can add an audio in app bundle or you can read it from document directory of your app.
    // Url from bundle
    let url = Bundle.main.url(forResource: "MyAudio", withExtension: "mp3")
    
    //Url from document directry
    let docDir = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true) 
    let fileURL = docDir.appendingPathComponent("Audio").appendingPathExtension("mp3")
    
    // Play audio
    let audioPlayer = try? AVAudioPlayer(contentsOf: fileURL!)
    audioPlayer?.play()
  2. Audio From Data : You can play audio from data object. This can be used when you receive an audio as Data object.
    let audioData = Data()  // your audio as Data
    audioPlayer = try AVAudioPlayer(data: data)
    audioPlayer.play()

    You can also tell the type of file. There are two initialisers for that, one for data and other for audio file.
    ->   init(contentsOf url: URL, fileTypeHint utiString: String?) throws
    ->   init(data: Data, fileTypeHint utiString: String?) throws

    Sometimes the file type can’t be determined or file is corrupted. fileTypeHint  will tells the parser what kind of data to look for. So it can be successfully parsed.

    NOTE:- In iPhone if you make your phone silent then it will mute your audio. To overcome this you just need to set category as given below:
    try? audioSession.setCategory(AVAudioSessionCategoryPlayback) 
    This will help you to play sound even if your iPhone is on silent mode.

  3. Recorded audio: Record audio can be played as given above. For that you just need to give the path and extension of that audio file.
    //Url from document directry
    let docDir = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true) 
    let fileURL = docDir.appendingPathComponent("Audio").appendingPathExtension("m4a")
    

    Now make object of AVAudioPlayer with that url and call play method.

  4. From Mobile play list: Audio file can be selected from your playlist. But the procedure is lil bit different. Here are the steps:First you need to import a framework MediaPickerthis will provide you the classes and protocols to show and pick the audio file.
    Now create an object of MPMediaPickerController and do some initial setup. Now present this view controller.

    let mediaPlayer = MPMediaPickerController(mediaTypes: .music)
    mediaPlayer.delegate = self
    mediaPlayer.allowsPickingMultipleItems = false
    mediaPlayer.modalPresentationStyle = .fullScreen
    mediaPlayer.prompt = "Select any song from the list"
    self.present(mediaPlayer, animated: true, completion: nil)

    Now conform its delegate MPMediaPlayerControllerDelegate . Here are two methods which need to be implemented:
    1.   mediaPickerDidCancel(_ mediaPicker: MPMediaPickerController)  : this method gives callback when you click on cancel button given in you media picker view controller. You can dismiss your view controller here.
    2.  mediaPicker(_ mediaPicker: MPMediaPickerController, didPickMediaItems mediaItemCollection: MPMediaItemCollection) :  This method will give you callback when you select any audio. You can select more then one audio. Now you can do anything with that file.

    func mediaPickerDidCancel(_ mediaPicker: MPMediaPickerController) {
        dismiss(animated: true, completion: nil)
    }
    
    func mediaPicker(_ mediaPicker: MPMediaPickerController, didPickMediaItems mediaItemCollection: MPMediaItemCollection) {
        let item = mediaItemCollection.items.first
        do {
            if let url = item?.assetURL {
                audioPlayer = try AVAudioPlayer(contentsOf: url)
                audioPlayer?.play()
            }
        } catch {
            print(error)
        }
    }

    NOTE:-  You can not test this on simulator. It can only be tested on device because for that you need iTunes.

2. Pause/Stop an audio:

You just need to call n single method on your audio manager object. To pause an audio call pause() and to stop an audio call stop()

Other operation which can be performed on an Audio:

There are some properties and method which help you to increase performance of your project or matches your requirement:

  • isPlaying: This property let you know if the audio is being played.
  • duration: It is an object of TimeInterval which tells you  the total duration of audio.
  • url: It returns the complete url of audio.
  • data:  It gives you the data object of played audio
  • volume: You can set the volume for your audio on the scale of 0.0 to 1.0
  • currentTime: It will tell you the current played time of audio. You can change current time of audio to rewind or forward.
  • format: This will tell you the format of audio.

That’s all you need to play with audio in Swift 3.0. Enjoy learning 🙂

Leave a Reply