As a really compelling example of the utility, being able to define our own functions, we're going to talk about digital audio. We'll give a quick crash course in sound. This is not a physics course, and we'll do the minimal amount in terms of what sound actually is. We'll say it's the perception of the vibration of molecules. We're going to work with musical tones, which are steady periodic sounds. A pure tone is a sine wave, a sinusoidal waveform. Now, in music, it's the frequency of the sine wave that makes the different note. So, 440 Hertz is concert A, and there's a 12 notes in our scale, and they're spaced logarithmically. What that means is, that so concert A is 440 frequency, 440 peaks per second. Then the 12 things or 12 notes are space logarithmically, that means their frequency is 440 times two to the i over 12, where i is the index of a note above concert A. So, B is for 440 times two to the one sixth power and so forth. By the time we get up to the 12th note, which is an octave higher, than that's for 440 times two to the 12th over 12, or it's double. So, if we double the frequency of concert A, we get 440 to 880, and we get a note that's an octave higher. Those are the waveforms of the peaks occurring more frequently. So, that's the basic idea of how we get music, we produce sinusoidal waveforms, and that vibrates molecules that we hear. All right, so what we're going to do with digital audio, is represent a wave by sampling it at regular intervals, and saving the values in an array. Just the same way as we did when we plotted a function in the previous lecture. So, this is concert A taking 5,512 samples per second, and so one-fortieth of a second is just 137 samples. In the same way, as in the previous lecture when we plotted a function, if we take more samples, we get a more accurate depiction. So this is 275 samples per second, this is I'm sorry for a 40th of a second 275. This one's 22,000 samples per second, so this 500 in a 40th of a second. This one's 44,100, and you can see there's a lot of samples but it's a pretty good representation of the wave. This is the standard that's used for digital music and CDs, for example. So, that's the one that we're going to use. Now there's a lot of points, but we have a computer, and so we can represent a lot of points, we have arrays and we have functions, and you'll see that even though there's a lot of data, it's not difficult to write programs to manipulate it and therefore process sound. So, sound is nothing more than arrays of double values, these samples, and we're going to write programs to manipulate them. So, let's take a look at how that works. So, the main thing, is our Standard Audio library, which is like our Standard Draw library and others, providing output of your program. We developed it for this course, but now it's available, from the standard download of our core software. So what we do is, the main function in this library is to play a sound wave. It's given an array of double values, and it plays the sound wave on your computer's audio output. There's a standard file format called the.wav file format, that you can also store arrays of doubles, the library converts those into the standard format. So, there's a method play, to just play a given file. There's a method to just play the sound wave that's in the array. Now, so for a second that size of that array is 44,000, so for 10 seconds, it's half million, double values. So, if you have a lot of sound, you're going to have a lot of data and these arrays are going to be big. But that's fine, you have a fast computer. You can play 1/44100th of a second. You can save to a.wav file, you can read from a.wav file, but what our library does is allow you to hear the results of your program that manipulates sound. It's an output library for sound, and just a few methods. So, let's take a look at how to use it. Again, this is the "Hello World" the simplest program can play some sound. So, we're going to use a function, that takes as argument, the pitch or the Hertz. So, it's 440 for concert A or 880 for an octave higher and a duration, so how long do you want to play that and that's in seconds. So for 1 second, it's 44100 samples. For 10 seconds is 10 times that, and so forth. So N, is the number of samples that we have to take. It's also the size of our array. So, we build an array that's of size N, well N plus one to handle the endpoints. For i from 0, through N, what we do is, we sample the sine wave. The sine wave we have to sample, you can check this math is not a big deal, we want to take whatever the Hertz is, and then multiply that by two Pi divided by 44100, and then for each integer i, that's the point that we want to get. So, i is along this scale, and that's the function that we want to sample. Return a, so that's all that does, is it takes that particular sine wave, the one that's governed by the pitch and samples at, well multiplies the duration samples 44100 times. Creates the array, that corresponds to tone, at that pitch for that duration. So that's our function that we're going to use to manipulate tones, and this is just the "Hello World" , so what we're going to do is, take the pitch from the command line, and take the duration from the command line, and then just create an array, and fill it up with the tone of that pitch and that duration, and then play it. So that's all there is to it. So let's hear what it sounds like. So, if I invoke this program with 440 for concert A in three seconds, then here's what I get. If I want to play an octave higher, I just put 880. I don't necessarily have to do something that's on the western music scale, you can put any frequency you want. That's lower. That's an octave lower, and then this is just arbitrary frequency. So, fill in array and play it, and that's sound. So now let's look at something a little more interesting. So what we're going to do is have a data-driven program, where we put a list of tones and durations, on standard input, and then we just read them in that way we play a tune. So this tune, many of you may be are familiar with, you'll hear it in a second. How does this code going to work? So, what we want to do is, we're going to control the tempo from the command line. So, we'll multiply all these relative durations, by another number that comes from the command line. Then we'll go in and read from standard in, we'll read our notes. So, the first thing is the pitch. That's what step is it above concert A. Second thing is the duration. So, we'll take the relative, that's an eighth note about one multiplied by the tempo. Then, we'll compute the frequency from the pitch. So, we number the notes zero starting at concert A up through 12 an octave higher, and we want to take two that number divided by 12. So that's would math that pound and multiply by 540 and that gives us the frequency from the formula that I gave right in the first slide. Then, we'll just play that note. So, that was in the previous slide we had the code for tone, and that's how you invoke that function from here, we play it for the given frequency in the given duration. We'll talk about this mechanism more later on, and then, play it. So, create the note, and play it. Stay in the while loop, reading the notes from standard input. Then when you're done, we have a close function that eliminates an annoying pop. So, let's see how this works. So, I go a Java PlayThatTune, I'll play it slow first. So there's really quite amount of data flying around with this program, each note involves thousands and thousands of doubles, but you can see the possibility I think. I want to play it twice as fast. So, it opens up endless possibilities and all you need is a file like that and you can play a song, and you go to the book site, there's lots of files that students have created over the years. This is just something to think about before we move on to a more complicated program. What sound does this program produce? What it does is fill an array with random values, big array, 44,100 times 11. The answer is it plays noise. Random values that's what noise is. It's playing for 11 seconds I'll stop it now. So now, let's do something more interesting. Now, one thing that we can do is make chords. If you take two waveforms and you average them, then it's like playing the notes at the same time. So, what's a wave form? A waveform is an array of double values. If we have two of them, let's say A and B, they've got to be at the same length, then we'll take a new array C and just go all the way through and just set C to the average of the values in A and B, and that's a new wave form, so if this is A and B, fluctuates more often, if you just average them you get another looking waveform, and it's like playing the notes twice. So, let's look at a more complicated library that is going to have, now we're going to have that average function, and then we're going to have a function chord that takes two pitches and a duration. Then what I will do is compute the frequency for both pitches. It'll create an array with the tone for the first one, and again, using our tone function, and another one with the tone for the second one, and then it'll average those twos and return it. So, this is just crunching the numbers, make one make another one, average the values, and that's a chord. Well, technically, it's a two note chord. So, and then we'll just have a driver that takes the two pitches from the command line and the duration, and then puts that in the new array and then plays it. So, here's A and C for five seconds. It's like playing the two notes simultaneously. We can say play a constant A and an octave higher at the same time. That's known as the harmonic, and actually, harmonics are important in music. So, what we can do is make the tune sound a little more natural, more realistic by adding harmonics. So, let's look at how that works. So, if we have constant A then we can go ahead and make an array that's got all those numbers and for the duration. But then what we can do is take double the frequency, so that's an octave higher and make that one, and we take half the frequency, that's an octave lower, and make that one, and then what we can do is average the high and the low one and we get something in between that's both harmonics, and then average that one with our main tone, and that's we get a different thing, it's not a pure sine wave, it's got the harmonics included. Most often when you listen to music you're hearing harmonics. You can do much more complicated things to get more interesting sound, but let's look at what happens when we do that. So, now our note includes the harmonics. So, if we add that to play that tune and we do the code it's just substituting in this function that plays, that does a more interesting note. Sounds like this. Not perfect, but much more realistic than our original with pure tones. You can see where to go if you're interested. You can add in other harmonics, add chords, there's many more things that you can do just with standard audio having the ability to compute with and play music. Again, there's no end to what you might do. Bottom line is that you can write programs to manipulate sound, you can provide inputs of any type that you want to add harmonics and do what you want. But let's not lose sight of the original purpose of this lecture, and that's really it's a case study of how useful functions are. This computation is organized as a bunch of functions, there's a lot of function calls. The flow of control is quite complicated, but there's no problem understanding what this is doing. Functions provide us with the flexibility and the flow of control to organize our computations in small pieces, that's modular programming and that's what functions are all about. We'll have assignments where you get to do some more interesting things with musical tones.