Let's walk through the play sounds view controller plus audio
class extension to understand exactly what this code is doing.
Open the play sounds view controller plus audio swift file and
navigate to the top.
The first thing you see here is a struct of alert messages.
This is just a convenient way to have the alert messages in a single place.
If you have strings or other static items that you want to use throughout
your app, this is a good practice to follow.
Below that, you see the playing state enum,
which will be used by the configure UI function to set the button states
depending if we're playing or not playing any audio.
Next up is the set up audio function, which is where we try to
load the audio recording file passed in from the record sounds view controller.
If loading the audio file fails, we present an alert message to the user.
By the way, did you notice these MARK statements here in the comments?
These are to make it easier for you to jump around in your code.
When you pull down the function listing in the editor toolbar,
you can see the section headers in bold.
It makes it easier for you to jump to the relevant section.
The play sound function is the main function in this extension.
As the name suggests, it carries out playing back the audio.
This function has something you have not seen before, that is,
optional parameters.
See the question mark here, after rates float type?
It indicates that rate is an optional parameter and
if you don't pass it in it'll be set to nil.
The same is true for pitch.
The first part of the function is to grab the AVAudioEngine and
create an AVAudioPlayerNode.
Next, we check if the rate or
the pitch parameters were passed in, since there're optional.
The way we do this check may look a little weird at first
as we're doing a value binding inside an if statement.
See the line here, if let pitch = pitch.
You really should read it as,
if the pitch variable is not nil, then execute this pitch statement.
If pitch is nil, we'll skip over this code.
Likewise, if rate is nil, we'll skip over this code too.
The concept of value binding is covered in UI fundamentals in the next lesson.
Next, we create an echo and reverb notes, but we will only use them if
either the echo or reverb parameters were passed in and set to true.
We can either have an echo and reverb, just echo, just reverb, or neither.
Lastly we tell audio player to stop playing any current audio, and
schedule our recorded audio for playback.
This ensures that the recorded audio is in memory, and ready to be played.
This part here that looks like another function,
is actually a trailing closure.
The schedule file function takes in a completion closure
that it runs when the audio file is ready to start playing.
This code here sets a timer to fire when the audio is done playing that
resets the button to the not playing state.
Now that everything is set up, we try to start the audio engine and
the audio node playback.
At this point, the audio would be playing.
Connect audio nodes is just a helper function to connect a set of audio nodes
together in the audio engine.
As with most helper functions,
this just cuts down on the duplication of code in the play sound function.
The stop audio function is in charge of stopping the audio.
Remember that timer we set back in the play sound function?
We don't want it to fire as we're stopping the sound here.
So the first if statement invalidates or cancels that timer.
The next few lines stop the audio player node and the audio engine, itself.
Next, we come to the UI functions, which are really just in charge of enabling
and disabling in the six playback buttons and the stop button.
These are helper functions and they help us by avoiding duplication of code.
We just have one place to enable or
disable the buttons, depending on if we are playing or not playing audio.
You can see that configureUI itself uses another helper function
to toggle the playback buttons.
If you pass in false, they all get disabled and
if you pass in true, they will all be enabled.
Last step is the showAlert function which simply displays an alert
to the user using UIAlertController if something goes wrong.
That it.
I've taken you through the black box class extension that allows
all the audio to be played back with changes to pitch, rate, with echo, and
even revert.
Remember that there's no harm in playing around with this code.
You should feel free to experiment and changing the settings and more.