Welcome reader to the final part of the Record and Play Audio tutorial.
Tutorial Revision Notes
|
I refer to the Simulator and your real device as “your device”. If you have a “real device”, you should use it to test code presented in this post. If not, then use the Simulator.
The Player View is shown when the app user tap the Recordings View’s table view cell. You’ll add code in the PlayerViewController.swift class file to enable the app user to perform these tasks:
- Play the selected sound file
- Pause the sound file that’s playing
- Stop playback of the sound file
You will create an object called, audioPlayer from the AVAudioPlayer class. You will use the object’s functions to perform above tasks.
The Navigation Bar Button
When the app user tap the navigation bar button, the app will segue him back to the Recordings View.
The NSTimer Class
An instance of the NSTimer class will animate the ticker that’s displayed on the playedTime label. The label is located between the Play/Pause button and the Stop button.
The View’s Labels
While the invisible audio player plays a sound file, the app display on a label the the selected sound file’s name. On another playedTime label, the app display the animated ticker. In other words, the label display remaining time of the sound file that’s playing.
The Play/Pause Button
This button display a play and pause icon. When the button is tapped, the app pause or play the selected sound file.
The Stop Button
This button display an icon of a solid blue square. When tapped, it stop playback of the sound file.
The Audio Player View Controller Code
You are ready to add code in the PlayerViewController.swift class file. Start by using the Source Control menu to create a new branch from the “branch-two” branch. Give the new branch the name “branch-three”
Now, modify the top portion of the file to look like this:
The first thing you did is imported the AVFoundation module in the class file. Next, you conformed the PlayerViewController class to the AVAudioPlayerDelegate protocol. Finally, you declared a global object variable called audioPlayer. The AVAudioPlayer class was used as its type. In other words, you created an invisible audioPlayer object from the AVAudioPlayer class.
Now, modify the remain code in the PlayerViewController class file to look like this:
override func viewDidLoad() { super.viewDidLoad() trackTitle.text = selectedAudioFileName let fileManager = NSFileManager.defaultManager() let urls = fileManager.URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask) let documentsDirectoryURL: NSURL = urls.first! fileURL = documentsDirectoryURL.URLByAppendingPathComponent(selectedAudioFileName) do { audioPlayer = try AVAudioPlayer(contentsOfURL: fileURL) audioPlayer.prepareToPlay() audioPlayer.delegate = self /*** DEBUG STATEMENT ***/ print("The audioPlayer is initialized with this URL:\n\(fileURL)") } catch let error as NSError { print("AUDIO PLAYER ERROR\n\(error.localizedDescription)") } } override func viewWillDisappear(animated: Bool) { if audioPlayer.playing { audioPlayer.stop() // Stop the sound that's playing } } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } @IBAction func playPauseButtonTapped(sender: AnyObject) { if audioPlayer.playing { audioPlayer.pause() } else { audioPlayer.play() timer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: "updatePlayedTime", userInfo: nil, repeats: true) } } @IBAction func stopButtonTapped(sender: AnyObject) { audioPlayer.currentTime = 0 audioPlayer.stop() } func updatePlayedTime() { let currentTime = Int(audioPlayer.currentTime) let minutes = currentTime/60 let seconds = currentTime - minutes * 60 playedTime.text = NSString(format: "%02d:%02d", minutes, seconds) as String } func audioPlayerDidFinishPlaying(player: AVAudioPlayer, successfully flag: Bool) { let msg = "Your recording was saved as, \(selectedAudioFileName)" let alert = UIAlertController(title: "Audio Diary", message: msg, preferredStyle: .Alert) alert.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil)) self.presentViewController(alert, animated: true, completion: nil) } func audioPlayerDecodeErrorDidOccur(player: AVAudioPlayer, error: NSError?) { let alert = UIAlertController(title: "Audio Diary", message: "Decoding Error: \(error?.localizedDescription)", preferredStyle: .Alert) alert.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil)) self.presentViewController(alert, animated: true, completion: nil) } }
Test The Player View Controller Code
Now, run the app on your device and test the code you entered in the PlayerViewController.swift file. You’ll have to click a cell in the Recordings table view to access the Player View.
Next, use the Player View’s Play/Pause button to play or pause the selected sound file. Use the Stop button (blue square) to stop playback of a the sound file. Notice how the playTime label’s counter increments as the sound file is playing. It it is reset to 0:00 when the sound file finish playing and when you tap the Stop button.
How The Player View Controller Code Works
It is time to go over how the PlayerViewController.swift file’s code. Let us start the with viewDidLoad() function’s code.
The viewDidLoad Function Code
Code in the viewDidLoad() function:
- Assign the selected audio file’s name to the trackTitle label.
- Get the full path to the selected audio file as a URL.
- Initialize the invisible audioPlayer object with the selected audio file.
- Prepare the audioPlayer object to play the selected audio file.
- Make the audioPlayer a delegate of the PlayerViewController class.
- The first print statement is only for debugging purpose. It print the audio fileURL in the console
- The second print statement is required. It print in the console, the error message the audioPlayer object return.
Remember, the audio file name was passed to the PlayerViewController class via code you entered in the AudioRecorderViewController.swift file’s prepareForSegue() function.
The viewWillDisappear Function Code
Now, when you tap the Player View’s navigation bar button, the viewWillDisappear() function is fired before you’re transported back to the Recordings View. Code you you entered in the function check to see if the audioPlayer is playing the selected audio file. If it is; the statement in the if block stop the audio sound file. Now, code you entered in the viewWillDisappear() function is very important. It prevent the app from playing multiple sound files at simultaneously. Test this by doing the following:
- Comment out the ViewDidDisappear() function’s code and run the app on your device.
- Select an audio file from the Recordings View and tap the Play/Pause button.
- Tap the Player View’s navigation bar’s button to return to the Recordings View and select another audio file and tap the Play/Pause button to play that sound file.
The app plays both audio files simultaneously. Before proceeding, uncomment the viewWillDisappear() function’s code.
The Play/Pause Button Code
When you tap the Play/Pause button, the playPauseButtonTapped() function is fired. Code you entered in the function pause or play the selected audio file.
The Stop Button Code
When you click the Stop button, the stopButtonTapped() function is fired. Code you entered in the function does set the currentTime variable to 0, and stop playback of the selected audio file.
The updatePlayedTime Function Code
This function pretty much update the playedTime label’s text property by displaying a minutes and seconds ticker. This is done while an audio player is playing. By the way, the updatePlayedTime() function is called in the playPauseButtonTapped() function.
The AVAudioPlayerDelegate Protocol Functions
The final set of code you entered in the PlayerViewController.swift file implemented two delegate functions of the AVAudioPlayerDelegate protocol.
audioPlayerDidFinishPlaying() – This function is fired when the audioPlayer finish playing the sound file. You entered code in the function to inform the user that the sound file finished playing; via an alert view.
audioPlayerDecodeErrorDidOccur() – This function is called when an audio player encounters a decoding error during playback of the selected audio file. The alert view code display the decoding error.
The End!
That’s it, you’ve reach the end of the three-part tutorial, Record and Play Audio. Use the Source Control menu to commit changes to the git repository. Here’s the final version of the AudioDiary project.
Comments are welcomed! 🙂