(whistle toots) - Hello, welcome to a coding
challenge, Fourier series. So what I am going to
program in JavaScript using the p5.js library is exactly this. This is what's known as a Fourier series. It is a series of wave patterns
that when summed up together approximate some other function (sighs). What does that even mean? So first of all, I'm going
to show you some resources, the things that got me
thinking about this topic and wanting to make this coding challenge. And you probably should, if you want, stop this video and go look
at these other resources, and then you could come
back, if you wanted, or maybe you're just off
doing something else. So pretty recently, Smarter Every Day came out with a video called, What is a Fourier Series?
Explained by drawing circles. This video reminded me of a amazing video that I had watched at some point in the past (laughs), I guess like almost a year ago, called, what is the Fourier Transform?
A visual introduction. You probably, if you've done
any coding and programming, you've probably heard these terms before, FFT, fast Fourier transform. It's usually referenced in the
context of analyzing sound. And so Smarter Every Day's video was a collaboration
worked with a Turkish researcher on this website here. I'm not going to attempt to pronounce it, or I will, bilimneguzellan.net. I encourage you to check out
and read this whole article, but this is a visualization, again, of exactly what I want to do. A series of wave patterns visualized
as a path along a circle, periodic functions summed together to approximate a square wave. And if we can make this
happen in JavaScript, then there, in theory, is no reason why
we couldn't then figure out how to draw any given path as a series of Fourier transforms. And there's a sort of a
well-known GIF or video of this like crazy set of
circles drawing Homer Simpson. So I'm hoping to get there. But this video, I just want
to, by the end of this video, have exactly this pattern in JavaScript. Okay. So I also want to reference this website,
betterexplained.com, which has a nice article,
An Interactive Guide To The Fourier Transform. And this, I think, is a really
excellent explanation. So again (laughs), going to
get started coding in a second, but you're just going to have to humor me to let me kind of talk
about this a little bit more just to get my feet under me here. So the idea of a Fourier
transform, so a sound wave, right? We have this idea of a sine wave. You've probably seen me draw sine waves on the board or in code
in countless videos, usually drawn something like this. A sine wave has a frequency, (laughs) which is how often does it repeat. Like if this is the sort of x-axis, like this is one whole cycle, right? And I could think of that
as like the time it takes for this dot to go all
the way around the circle. So frequency is like how many cycles of the
wave per unit of time, like per second or per frame. There's also amplitude. Amplitude is the height
(laughs) of the sine wave, how much distance between the
very top and the very bottom. And so a sound can be
represented as a sine wave. So but you probably have seen like, oh, I've got this recording
device soundy thingy and what it's doing is
it's like (vocalizing), this is like the sound. This is the wave, this
is the representation of the sound that I'm
listening to right now. Well, you can create,
this kind of wave pattern is typically actually the sum
of multiple wave patterns. So in other words, if this
is like the musical note a, and then this is like the
musical note something else, and we're to add these two waves together, can you still see what I'm drawing? You know, I might get something
that looks like this, right? And I've done this, I think I had like an additive wave video in
the Nature of Code series about this kind of idea. The idea of the Fourier
transform is can we go, right, I could have these two waves. I could add them together
and get this pattern. Could I go in reverse? If I'm listening to a sound like this, could I pull out all of the waves, the sounds, the frequencies,
that make up that? That's like pitch detection. Or if I wanted to then filter out a very high-pitched sound,
if I could take the sound, break it apart, take away one
of the high-pitched sound, add it back together, I would get this. So this is akin to, I
love this metaphor here in the Better Explained, of
unsmoothie-ing a smoothie. So I'm (laughs), I like to
make smoothies, actually. Little-known fact. I always like, anyway, so
but could you like, right? Let's say I take some
mango, and some kale, and some blueberries, and
some like almond milk, and I mix them all together,
and I give it to my children, and I say, I made you
this beautiful smoothie. Can you guess what's inside of it? This is actually a game
we actually play at home, I've just realized, like,
ooh, this is perfect. Well, if I could do a Fourier transform, I could take the mixed
smoothie and filter out, go in reverse, and find
out all the ingredients. That's the idea. So that's the idea of
the Fourier transform. That's conceptually what it is. Now what I want to do in this
video is I'm not going to worry about figuring any of this out (laughs). I'm just, now I understand what it is, what it can be used for. I have this goal eventually of having it, of using a Fourier series
to draw any arbitrary path. But one way to get started with that is exactly what's demonstrated
here on this website, which is, what waves do
you need to add up together to end up with a square wave? And you can see here, this is actually a really
nice visualization, is as you have more and more iterations of the Fourier series, how
it converges even closer and closer to the square wave. I could also just go here to
Wikipedia and find this again. So this is the clue. So there's this idea in a Fourier series of
Fourier coefficients, and some kind of like iterative thing, of like n, and n plus one, and n plus two. And we can actually see a
nice clue to that in here. This is actually a very, this is one of the
simplest Fourier series. What is the series? One, three, five, seven. Can you guess the next number? (bell dings) Nine, right? And what's after that? 11. So if I can just implement this, each one of these circles
and have them rotate around like this at that period or frequency, with that amplitude, we're
going to get somewhere. So let's (laughs), I've talked
about this for way too long. Let's try to actually code this now. So the first thing that I want to do, I'm just going to start, I'm
going to start like kind of even not thinking about the Fourier series. And I'm just going to make
up a variable called angle. You could really think of that as time. It might be more appropriate
for me to call this time, 'cause time is moving forward, that's a sort of crucial idea. And I'm just going to say, time equals, every time through draw,
if you haven't worked with p5 before, draw is a function that loops over and over
again, over and over again. So time is moving forward. Then what I want to also
do is I just want to like draw a circle somewhere (laughs). So I'm going to translate to like 200 pixels over and 200 pixels down. I'm going to have this idea of a radius, like the radius of a
circle that I want to draw is maybe going to be 50 pixels. And then I'm going to
say ellipse at zero zero, with that radius times two,
because the ellipse function expects a diameter, radius is half that. I'm going to make this white, so
I'm going to say a stroke 250, oops (laughs), stroke 255. Somebody told me how to get
rid off that auto-complete, and I still haven't done it, and a noFill. So when I go back the to
browser and refresh it, I've got a nice circle there. Eh, let's make it a little bigger. All right. So now what I want to do
is, how can I have that dot traveling around the circle? Let me have the dot
traveling around the circle. So the way that I would
do that is I would use a polar to Cartesian
coordinate transformation. And I'll certainly have a video that talks about how to do that. But what I'm talking about
here is if this is the radius, and this is the angle, which
is really in my program the time, how far over in
x, and how far over in y, how far up in y, can be
calculated based on trigonometry? So the radius times cosine of the angle, or angle is the x value, the radius times the sine
of the angle is the y value. So I'm going to do that here (laughs). I'm going to say, let x equal
radius times cosine (snorts), cosine of time. And let y equal radius
times sine of (laughs), sine of time, I should probably
pause and turn that off. And then, but let me
get through this first, point x (laughs), I'm
definitely going to pause and turn this off, point x, y, I'm going to say stroke 255, stroke, actually, let's
make this a circle also. So we're going to say like ellipse x, y, we're just going to make it
smaller, like eight pixels. And let's also say fill 2225. My god, this is making me crazy. And here we go. Look at that. There's that circle moving, right? That circle is moving, and
maybe it makes sense to also draw a line (laughs)
from zero, zero to x, y. And now I've got this, and I want it to move a little bit faster,
and honestly I'd like it to go the other direction (laughs). I'm not sure, I should actually check. What is it doing, if I
want to like recreate exactly what's here, yeah, yeah, it's moving the other direction. So I've got the beginnings of this. Now I haven't worried
about the number four here and the fact that I've got
the angle divided by pi, but we'll get there. (bell dings) I'm back, I fixed this auto-complete thing that was bothering me
in Visual Studio Code. I'll put something in the description about how I did that (laughs). But I also wanted to mention, in the chat, thank you to Amar who mentioned, who wrote, you are using Fourier series and Fourier transform interchangeably, but they are not the same thing. So thank you so much for that comment. I will post some links, also,
in the video's description for more reading about this. But in short, the Fourier
series is for periodic signals, which is what I'm doing exactly right now to create this square
wave, which is periodic, versus the Fourier transform
which is for aperiodic signals. Another way of thinking
about that is to represent any general non-periodic function. So hopefully as I get
further down this road I will come back to this. And also in the chat,
Smarter Every Day writes, Fourier transform is for
swapping between frequency domain and time domain, which is
an also really nice way of putting it. Okay. But what I am doing in
this video is implementing the Fourier series, the periodic series that add up together to the
square wave pattern, okay. So here we go. So I have success step one. I have my circle passing around. And you know what, I think that I probably
should not put this, I'm going to have this not go
the correct direction (laughs). I'm going to have it
go, 'cause I don't know if the negative number's
going to mess things up there. Okay. All right, next step. Next thing that I need to do, and if we go back to
this particular video is, how can I take this circle
that's moving around and then draw the resulting wave pattern? And this is actually kind
of a much simpler problem than you might think, because
basically what I want to do, this is moving in two dimensions. X is oscillating back and forth, y is oscillating back and forth, and both those oscillating
at the same frequency, with the same amplitude,
in the same phase, the starting together, is moving along the path of the circle. So I just need to take the y value and sort of graph that along the x-axis. So the way that I'm going to do that is I'm going to add an array to my code. I'll call it wave. And it's going to be an empty array. It has nothing in it. And what I'm going to do here is every time I calculate a new y value, I'm going to say wave push y. So I'm just going to save
that particular y value. So now all I need to do is say, oh, you know, for let x, you
know, I'm not going to use x, i equals zero, you know, i
is less than wave.length, i++. Let's draw a point at i,wave index i, right? So all I'm doing here is
saying, let's just draw all of those height values, those y values, from kind of x equals zero to as many as them as I get. So if I do this, you're
going to see, look at that. There's that wave pattern going. All of those points
are moving up and down, and you could see how
the height of that wave is the same as the thing passing around. Okay. But this doesn't look so
great, so what I want to do is, I want to instead use beginShape
and endShape, this will, and then say vertex. So this will actually
like tie it all together. And I think if I say, no, it's actually, I'm going to leave the fill in there for a second,
'cause it's kind of cool. So that's actually like
trying to fill in the shape, which is sort of a nice pattern. But I'm going to just say noFill. I'm going to do this, refresh the page, and then also, you
know, why not translate, just to translate this a little
bit over, like 200 pixels. And we can see this. And then I guess I could also draw, sorry, I want to draw a line. Yes, I want to draw, sorry, I
got confused what I was doing. I want the end of the line
to connect to where that is. Oh, of course. Okay. So what I want to do is draw a line, so I need that first, I
need this first value. So I have x minus 200,y to i,wave index zero. And actually it's not i, it's zero. So this is just, this I
know is the very first point in this loop, and since
I translated it over, I've got to like back up with my x value. This is very awkward. ♪ I will refactor this later, you know ♪ ♪ I will refactor this later ♪ Oh, no, no, no. I don't want it to connect to here. ♪ You know I will ♪ What am I doing wrong? ♪ This later ♪ Why is what I'm doing different? Oh, this is, oh, I'm doing it backwards. Ah, I know what I'm doing. Ah, I'm doing it backwards. I actually don't want to, I'm appending to the end of the array, so
every new value I'm appending to the end, I want to
add it to the beginning, so instead of using push, there we go. Instead of using push, I want to use unshift. So unshift is a JavaScript function, it's a weird name for it,
but push just adds this thing to the end of the array, and I want to add it to the beginning. Well that was a mistake (laughs). There we go. This is what I'm looking for. There we go, okay. (bell dings) So now I have the line
(laughs) connected there. Now the one thing that's a
little bit of an issue here is that I'm just like adding
points, and adding points, and adding points, and adding points, and never getting rid of any points. So I also should probably, at some point I should say
something like, if wave.length is greater than like, I'm just going to make
up some number right now. I could do a calculation
of how many points I need 'til the end of the canvas, but just to move more quickly
here I'm going to say wave.pop. So that would just like, if
its getting more than 500 it's going to like delete
the last one off the end. And now we should be able to say like, should be able to look at wave.length. It's 152. So clearly I only need like, I don't need more than 250 (laughs). All right, we are at this spot. Now comes the exciting part. I mean this was hopefully
all somewhat exciting, but to me, how do I suddenly go from, I have one circle with a point around it, to another circle that's
kind of like there with another point around it, to another circle that's like there, with another point around it? How am I going to add up these circles and continue this path of x y along them with all of these points
rotating and spinning? And guess what? I've actually done this before. I'm just remembering now. I have a video on the fractal spirograph. Let's see if this comes up. Yeah, the fractal spirograph. I actually did this already
in the fractal spirograph which was this way of doing exactly this to create a fractal pattern. I should go back and revisit this. But so we'll see how
this compares to that. So let me go back to the code here. And so what I want to do, so first of all, before I do this, I think I need to think a bit more formally about these functions. So before, I was just saying
radius, cosine of time. Radius, sine of time. But these functions actually map to these values on Wikipedia here. So if theta is my time, basically, what I'm saying is that I want to, and the value multiplied by that is four divided by, sorry
(laughs), theta is my time, and four divided by pi is basically my radius, in a way here. Hmm, kind of conflating some
things, but I can start to use this particular series to understand the ratio of the radii and the frequencies between these different
oscillating circles. Okay. So let's say, what if
I, what I do is I say, four divided by pi, times cosine of, what was it again, one times time. So I'm going to do this. I'm going to just change the y here. And then what I'm going to do is I'm also then going to say, radius times that. And also I missed something. Four divided by what? One times, this is confusing,
'cause there's a one here. One times angle, one times pi. So I'm going to say,
that's one times time, one times time, and this is one times pi, and this is one times pi. So the number that I need to change for each circle is that one. So let's just see what
this actually yields. And I'm going to go back to here. t's sort of, it's the same thing, but now the fact that that radius is 100, it's like everything is way too big. This is going to get calculated here. ♪ I will refactor this later ♪ Let's put this in here. And then let's make this back, just 'cause I don't really need, let's make this back to here. Okay. And four time, divide, oh, oh,
this should be one times pi. Aah, why is it doing that to me? I don't want that, I want
these divided by each other. Visual Studio Code is too
smart for my own good. There we go. There we go. That's what I wanted. That's why it was giving
me something crazy. Anyway, okay. Radius is not defined. Now I need to draw the circle next. This is when things are going awry. And let me put this here. There we go. And now there we go (laughs). Of course now it's the, of course, I had the division in the wrong place. I have this tiny little wave (laughs). So let's go back and make that about 25, which I think would be now basically, oh, it's divided by pi, aah! This is going remarkably well (laughs). Here we go, okay. I'm happy with where I am now (sighs). Okay, so now I have that first circle. The reason why I am doing this, the reason why I'm putting this, making all this work,
'cause I want this to be n. I actually want this to be a
number that changes, right? First, first it's one. Then it's three, then it's
five, then it's seven. That's not too hard to figure out, right? And what I want is to start
x with, and y, both at zero, and just add this stuff together. So x+=, y plus equal. So I want you, and then what I
want to do is I want to loop n. So n is going to go from one,
I'm going to say zero, actually, n, 'cause I'm, you got to count starting with zero, n
is less than two, n++. And then, and this really by
the way, I should call this i, because what I'm really
saying is, what n is. How do I do one, three? And this is pretty easy. I multiply it by two and add one. N equals i times two, plus one, right? When i is zero, I get one. When i is one, I get three. When i is two, I get five. So now if we add these together, and I'm just doing two right now. And speaking of which, I should move this all the way down to here. And I'm going to take
this out for a second. And then I've got to go
back here, and there we go. Okay, so something is wrong. I kind of got things close. Like look at this interesting, weird, crazy pattern that I've got. Okay, so the line should
not be going from, so I should be actually keeping track of previous x is x, and previous y is y. So I don't, I'm going to like
take out the wave for a second, 'cause I'm going to have to
change what I'm doing here. And then I'm going to just
say, previous x equals x. Oh, no. And then previous x equals x, previous y equals y, And then the line is going from those. Like that's not always
going from zero, zero, it's going from the previous x, y. So now that's right. The other circle also needs to have its center be at previous x, previous y. And there we go. So now I have this. I have this circle spinning
around this circle, spinning around this circle (laughs). There's only two circles. But, in theory, if I
change this to like five, there we go. Now we're gettin' somewhere. And actually, it would be sort of fun, I really think that I should think about how I'm drawing
this a little bit better. So, for example, I think
I want these circles to be much lighter, so let
me give them a little alpha, and then the points should also be, I think the points are
almost like less relevant. I almost don't want to draw these points. Let's just, 'cause I have the lines now, so let's see what happens
if I take this out. And I do this. Oops. But I want the line to be full brightness. There we go. So this is what I'm looking to draw. So there we go. So I now have this particular
series with every circle next to, rotating around every other circle. And I am using the values from
the particular Fourier series for a square wave. Okay (sighs). So now, and I feel like
this should be bigger, it's so small. Let's go back to having this be 100,
and let's actually not, let's just see how this looks. And let's, we can also, I'm being like neurotically silly about, let's move it over a little bit. Okay. Oh, I don't want it to
go off the screen though, so let's leave it there. Split the difference, 75. Okay. And then (laughs), I'm going to
have to go back a little bit. This is very silly, what I'm doing. Okay, there. Aah (laughs)! I have a problem. 150. There we go. Okay, so I know this
is hard for you to see. Let me zoom in on it,
so this is what we got. So now guess what? We're basically done, right? Before, I just had to put the wave back. Let's see what happens if
I just put that wave back. Like what happens? I put it back. Now what's going on? Like, I'm getting some crazy thing here. I don't even know what's going on. Oh, I'm pushing all the values. I just want to push the last value. Actually, this is going to be
a much easier fix, I think. I just want to push the last
value after the loop is over. And there, we can see there we go. But I don't know why
this isn't shifted over. Did I lose that somewhere? I need to do this. This I actually going to be,
oh, this was actually fine. And there we go (laughs). (bell dings) We are done. I should add one more thing to this because this is going
to become relevant later in my mind's eye of how I'm
going to do more videos on this. So right now I am visualizing
the resulting wave pattern. Also, I got to do a few more things. Will you please bear with me? You know, this video's already
about 70,000 hours long. But let's at least add one slider. I'm going to use the, and so
I'm going to have a slider that gives me values between one and 10. And I'm going to start it at one. And what I'm going to do is I'm
going to take a slider.value. So basically I'm going to have n control the amount of iterations of the Fourier series itself. So now you could see there's just one so I can use this slider
to add two, three, four, five, six, and this is 10. And I could, this is fun that I can actually do this in real time. So now you, the viewers
of this video (laughs), will have so many more
creative and interesting ideas about how to make this prettier, how to create more
interactivity, there're so many, but this is just an inkling, right? Every system that you build with code has a bunch of variables and parameters. There's no reason why you
couldn't make those interactive. You couldn't even, we could
make the number of iterations match to a sine wave itself,
like (mimics explosion), what would happen there? That would be crazy. But now you could see up to 10. We can see how it's converging. And I, you know, I don't know
how far I want to push this. Let's push it a little. Let's try. (drums rolling) Let's put it at 100. That's zero, all the way up to 100. Performance-wise, it's fine. It's happy to do 100. There we go, look at this. Look at that square wave! Oh, that is like (laughs) the nicest square wave I've ever seen. This is making me so happy. I cannot explain to you. I feel like this is a thing
that's been in my head for years, but I never actually
like sat down to program it. 'Course I am standing right
now, but close enough. Thank you for watching this
coding challenge visualization of the Fourier series
for making a square wave. Check this video's description for a link to the Coding Train web
page with this challenger and the code for it, and then
if you make your own variation of this, please share it with me. You could contribute it right there. So what are some things you might do? Number one is, why don't you
try doing this sawtooth wave? Could you take the code that
I wrote and make it do this? That would be a nice exercise to try. What other kinds of
interactivity can you add to this in terms of changing the colors, changing the different parameters,
changing the view of it? What happens if you do this in 3-D? Like, right? Could you have some kind
of points oscillating over three dimensions in a sphere, and then map that to something? That would be cool. So I look forward to seeing
what kind of things you create. Ask your questions and
all of that nonsense. But it's not nonsense, it is,
I mean, whatever (laughs). Goodbye! (whistle toots) See you next time. (sprightly music)