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! 🙂
14 Responses
iam using php as server sided programing language
and swift for client
in my project i wish to record and upload audio file to the server
i am using XAMPP server.
recording part is working good
but i dont know how to upload audio file to the server
You can use an FTP client app (http://www.macupdate.com/app/mac/24467/forklift). Is that what you mean? That would work.
Mam how to upload audio file to php server ? i am using swift 1.3 and xcode 6.3.2
Could you be more specific?
i want to make an app. and i use your Is-Headphone-Plugged-In. it is very good example. Now i am recording my voice with music playing in the background.(like karaoke). my question is how can i hear my voice from headphone? i dont hear my voice from headphone when recording
will you help me 🙁
nuryarisi@gmail.com send me please.
Here is the link to the final version of the AudioDiary project. It was updated using Xcode 6.4 and Swift 2. Please let me know if this help or not.
AudioDiary Xcode project
ohhh you are perfect… 🙂 its work. Can I ask you one more thing ? i am using “https://github.com/gilesvangruisen/Swift-YouTube-Player …” for play youtube videos but in webview ios play red icon shows always..
Is the sample code I can play YouTube videos and playerparameters can easily change ?.
nuryarisi, you are right and I have absolutely no idea why the AudioDiary app isn’t working on a real device. If I figure out the reason, I will let you know.
applady its working now. thank you very much. it is my fault..:) now everything is ok. thank you.
What was it, because it crashes for me too, but not in simulator
DocumentsDirPath:
/var/mobile/Containers/Data/Application/54EC2810-A61D-4E99-85F0-E425997B4AF4/Documents
fatal error: unexpectedly found nil while unwrapping an Optional value
i have get error…playerviewcontroller.swift slider.maximumValue = Float(audioPlayer!.duration) please send me full source code.