Placeholder Image

Subtitles section Play video

  • (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)

(whistle toots)

Subtitles and vocabulary

Click the word to look it up Click the word to find further inforamtion about it