Hello Today we're going to look how to build a synthesizer from first principles.
I'm a musician.
I play the guitar, but I'm not a trained musician.
It's no word near an expert, but being a programmer and being interested in music, I thought, It's about time we have a go at trying to build a synthesizer.
This will be a software synthesizer, and I know you can get them, but I think it will be an interesting learning exercise.
I believe this will be a multi part video today.
We're only really going to look at the basics of what is a sound wave on How do we represent that on the computer system?
Going to share with you some code that I've written, which will allow you to play with these sound waves very easily.
Single single file of code you can pull into any project you like.
Those intro themes that you heard me play there were back to the future on dhe Godfather on they were replicated using my PC keyboard is it is an input on a square wave for an output.
No, that might not mean anything to you right now, but By the end of this video, you'll have a good understanding.
I should say now that this video is is really aimed at the beginner, perhaps both in sound synthesis and for programming, although I will throw in some programming tricks to make sure we got the more advanced programmers to keep them on their toes.
Let's start with the very basics.
Here is a sine wave.
You can think of a sine wave as being air moving backwards and forwards to generate sound.
In fact, if you look at your loudspeaker, you know the code, you see it bouncing backwards and forwards imagine that here is when the sweet speakers switched off, the cone pushing out, going backwards, going forwards going backwards, going forwards going backwards.
The more it goes in and out, the louder the sound will be.
And that's called amplitude, so amplitude you can also think of in terms of volume.
Loudness professionals will measure amplitude in decibels.
We're not going to touch that just yet.
We're gonna keep it very simple.
Now, the basic formula for a sine wave is amplitude time.
Sign off the frequency Times time, the same way I got on the screen here is not centered around zero.
It's actually offset 0.5 because I'm going to use This is a visualization tool and it will make things a little bit clearer.
Result to understand on frequency is how many times we see a peak within a given time interval.
So if I increase the we could see here we could see we get more peaks.
Let's take this time period here 0 to 5.
As I increase the frequency we Seymour peaks and as I decrease it, we see fewer and I can change the amplitude.
So remember amplitude was loudness.
We're going from 0 to 1.
I would just like to take this moment to point out how excellent this Tulis this is Desmond, stop calm, which is a free graphing and mathematical tool for educational purposes.
Now we'll understand frequency as being pitch, so high frequencies are high notes and lower frequencies are low notes.
And that's why I really Basie sounds, you hear throaty.
You see the speaker moving very slowly, but sometimes you can see it, but in high frequencies, he can't see it moving it all.
So we know these low frequencies are based on high frequencies are trouble.
All sound is made up of sine waves of different frequencies and amplitude.
And if we take sine waves of different frequencies and amplitude and abdomen together, we can create interesting textures on different sounding instruments.
So here's a little example of adding sine waves together.
Now the formula looks horrible And I'm afraid if you don't like maths, then probably synthesis isn't for you.
But the mass isn't too bad.
Uh, here we've got three sine wave equations with a fixed amplitude.
In this case, 0.50 point 250.1.
But we get to vary the frequency of each one of them.
Now, by adjusting the sliders we can take a frequency on, we'll add another one to it.
So if we had a very low frequency here, there we go to a high frequency and sea mounts a little bit.
That will have an interesting sound, and we can add a lower fundamental frequency to it, which is more dominant.
This has the larger amplitude.
And just by manipulating sine waves in this way, we can create all sounds.
This project is really about coding a synthesizer.
I will be sticking to the Microsoft Windows platform.
That's because I've already written some code, which interfaces with the sound hard work and that's available to download below or fromthe one loan coded dot com website to keep it simple.
I'm going to create a Win 30 to console application, and we'll call it sounds synthesizer.
I wanted to be an empty project that generates lots of stuff I'm not going to use, and we'll keep it as a consul project.
So we're not going to bother with Windows.
Gu Ys o r controls Everything will be handled just a the command prompt, and this is a nice way and to make it easy for people to learn, I like consul programs because they're limited in their access and their abilities to display information.
This focuses you to think really about what you're doing, creating an empty project that will create a source file c++, and I'm going to call that one made all of the code I'm going to include for download and in this video is written to be accessible.
It's not written to be the most optimal or intelligent way to solve the problem.
I'm learning about how to do synthesis is and producing this video, and I'm hoping that through learning myself, all the people might try and avoid some problems.
So let's begin at the very beginning.
We want some basic console activity.
I will be using Standard Library quite a bit, so I'm going to throw that in there just to keep my coat simple.
We wanted an in Maine program starts on return to Syria.
Now I mentioned before, we're going to be cheating a little bit.
I've already written a file which will access the sound hard work for us, and you just have to take my word for it.
That this file There's nothing off the present data to the sound card.
The source code is available.
Please have a look at what we're using.
This is a starting point, I think, in a future video.
Explain how this fire works.
But right now I think let's get stuck into actually generating some noise.
I've already created a file which will talk to the hard work for us.
Let's add that to the project.
But at the existing, I said it's called one lone code a noisemaker don't age.
Well, have a look at that very briefly.
But really, all it is doing is accessing the sound hard work, creating a threat in the background on presenting those with a hook to apply data to the sound card.
I will explain all of that in detail in a future video, right?
I've created a short program here, which lists all of the sound hard work available on the computer on DDE Crazy instance.
Off a class called I will See Noisemaker Cold Sound.
It's using the first device that it finds, which is usually assistance default sound device.
I'm also going to now include some additional numbers and we'll have a look at what these mean.
So I want the sample rate to be 44,100.
I want the number of channels to be one on.
I'm going to put into magic mystery numbers for now into the end.
You see that actually, our default numbers provided by this class so feel free to use it without making these modifications.
So why is noisemaker using a short here in angle brackets?
And what is the sample rate?
And what does it mean?
Well, let's have a look back at does Most powered Graf, take the original way.
Form off the on.
Bring back our existing way, for we need to represent this way form a smoothly as possible on a computer.
Can't do that.
A computer will only be able to store numbers digitally to a fixed amount of precision.
We can emulate this by applying, uh, the second function here.
Now I will go into what this function is doing just yet, but it's a nice way of visualizing what happens as we as we apply more bits to represent the numbers that represent the sine wave.
So a CZ we increase the number of bits we can see that the approximation to the sine wave becomes more and more accurate.
So with this sign wave one bits, you really only get a choice of top bottom, top bottom, top bottom because you've got one bit.
It can be on off on off if we have to.
Bits, we can see there are four states in between.
We got bottom, but about 1/3 of the way up 2/3 of the way up on the top and so on.
And as we increase the number of bits, we increase the accuracy of the representation.
So let's take eight bits commonly known.
It's one bite and so you mean so Now we've got 256 levels to represent a sine wave.
We can see we consume in quite a bit, but it's still an approximation now.
A short is 16 bits.
See, we need a lot more zooming to get thin, still an approximation.
But accuracy is now quite high.
The number of bits in this case, a 16 bit short is really used to store the accuracy of the amplitude.
The sample rates the 44,100 is really used to store the accuracy of frequency.
Now, according to Nyquist, we need a sample rate, which is double the highest frequency we want to record in our sound synthesis.
Now, human range human hearing range, that is, is about 20 hertz to 20,000 hurts, so 44,100 is a little bit more than double 20,000 hertz, which means we should be able to, in the most extreme cases, capture with some accuracy a 20,000 hertz or 20 kilohertz signal.
Now the nice thing about this piece of code is we can, of course, change our shorts to a char and it becomes an eight bit system.
Or we could change it to on INT, which becomes a 32 bit system.
For for audiophiles, only 16 bit at 44,100 is a common settle for most sound surfaces.
The number of channels here is.
Do we have a stereo system or nothing?
In this case, no, we don't.
We'll worry about that later on different video.
Right now, it's just going to assume we've got one speaker attached to the system, the eight in the 512 here used as part of latent see management on Dhe.
When we explore how the noisemaker utility works, this will become very apparent, but ultimately that we're trying to reduce the delay between hitting a key on the keyboard on hearing sound.
But if we don't give the sound hard work enough memory, which is effectively what these two numbers are defining, it gets starved of noise to make.
So it's a it's a balancing act.
We'll find ways to tune that in the future, So let's carry on writing our program.
Now we've created the hard work on.
We've set it up.
We want to create a function which allows us to play with the shape of the way for I.
Where do we put the mathematics?
So let's create a little function appear on.
We'll call it make noise, and it's important that the function takes a double type argument of de time.
The noisemaker class does everything using doubles simply because they're easy for people to understand, and they look simple on the screen.
In reality, sound hard work on the software machine does everything using interviews.
We'll worry about that some of the time, but like I said at the start of this video, let's keep this simple.
So we're going to make the noise Double D time now Double D time is tthe e time that has passed since the start of the program on We'll put in a sine wave.
So let's remember now it's sign.
Well, let's pick a frequency now.
I'm not just picking a frequency here at random.
I'm picking 440 hertz, which is on a four on a keyboard.
You can Wikipedia.
Why, that's the case.
But for now, we'll say 440 hurts on effectively.
We times that by de time.
So here we've got a frequency of 440 hurts amplitude of no 4400.5 and it's a sine wave.
There is one more thing we need to do that and that is a little numerical trick because this is a frequency of Hertz on Sign.
Doesn't really take hurt.
It takes angular velocity.
So we just need to do a conversion.
But that's simply enough.
That just becomes two times pi on.
We return all of that semi colon.
Then we returned all of that ass that give the given point of time that is supplied to us.
What should our sine wave look like now?
We need to link that function with the noise making class.
So this is simply a case off.
Using a function points the noisemaker classes constantly running in the background.
So this D time variable that goes into our make noise function will be constantly increasing.
It's up to us what maths we do.
But we need to return a value between 01 to represent where the Speaker cone should be.
Remember going back before It's the amplitude where our speaker should be relative to the time on dhe.
We've just created a simple sign wave function here.
We should be able to listen to it, and it should be the note, eh?
To make sure that the program doesn't just stop straight away, I'm going to throw in a little dirty wildly here just to keep it running.
We're still at the debugging learning stage, so countdown.
But there's one more thing we need to add on that is to our project properties.
We need to include when mm don't lip library.
And that's because the noisemaker class in the background use this motions from that library.
Let's try compiling.
Do we get a noise?
That's a sine wave playing in the background.
Sorry, it's just must your speakers, so we'll stop that now.
We can make some changes to the nature of the mathematics and listen to the differences.
So let's start by doubling the frequency so we'll take our for 40 and change it to 8 80 It's high pitched.
Take that the other way.
Thio 2 20 It's slower pace, so changing the frequency elements changes the pitch sewn waves.
A nice, but they sound a bit mellow.
I think they're a little bit dull.
Instead of sign, we can use other functions, but they need to be periodic.
Commonly used are the square and triangle wave function.
So let's have a look at how we can generate a square triangle way.
The easiest way to generate a square wave is the threshold a sine wave around its middle.
So in this case, when we go over no 0.5, we want to set the value to one.
And when we go below no 10.5, we want to set the value to zero.
Now we can see what this looks like.
So in this case, we can see as soon as the same wave crashes.
No 0.5 here in amplitude, it actually goes up to a full one.
And when it goes below no 0.5, it goes back down to zero, and it will do this irrespective of the frequency.
So as we increase the frequency, we see that the square way Bunches up and it would decrease the frequency spaces back out.
Let's modify our make noise function to turn our sine wave into a square way.
I'm going to create a temporary variable here which just captures the sine wave.
I'm going to modify it.
The out out, the output.
It's greater than zero return three else.
It's a minus.
No point thing.
We can get rid of this now.
So this will take R sine wave function here, which I should get rid of this no point to you now.
So we have a full amplitude sine wave on Dhe because we can only have a plus or a minus in a square way.
We set the amplitude explicitly, so let's have a listen.
That was much louder, So I'm going to reduce that.
Andi will probably discuss the power of a signal later on.
There we go.
And that's really cool because it sounds retro.
We Chip Juni eight bits out.
It's not surprising, because the older Games councils of Machines only had limited sound functionality, such as toppling a pin up and down.
Our program is becoming a little and Willie now as it just produces sound when it starts, and we have to terminate it to stop.
So let's add some rudimentary control, so I want it.
So when I pressed the a key, we hear the note.
When I released the a key, We don't hear the note.
I'm going to do this using a windows function.
Get a sink Qi State, which allows us to see what the state of any key is on the keyboard.
And in this case, I know that the a key could be represented using the character, eh?
Basically, I'm testing it to see is the highest bit of that key there.
If it is, then the key is pressed.
And if it isn't, then the key is released.
So if the key is pressed, we want to specify a frequency to be played.
So it's still throw appear a variable civil half a a little double the we couldn't see.
Spell that right, you can see now put pickle zero on.
We're going to use you.
That's our frequency.
So this is now a global variable.
Now we need to be careful, because Defu Quincy output is modified by this threat in the wild.
But the noise maker owns 1/3 of its own in the background, which calls the make noise function.
So just in case we're going to make this atomic if the key is pressed, Do you want our frequency output today?
440 hurts else.
It's not pressed.
We'll set the frequency output to be zero hurts.
We've now got some rudimentary control over our sounds a little less annoying.
Well, we can extend this idea to implement a full keyboard.
I've added some additional code here.
I've taken the octave base frequency.
So before we did 440 hurts.
If I have that and have it again, I get 110.
And that means I've gone down to Arctic.
So every doubling in frequency moves you up one octave.
Now, in the conventional Western scale, there are 12 notes per octave.
I can't just divide up the frequency difference by 12 because it doubles each time.
So I'm going to use the power of to here to the 12th route.
Is that divided up into our 12 notes on?
We're going to use this to modify our base frequency here with the note that we want.
So for example, let's play this a key.
That's a nice low frequency, eh?
I want to move up one semi tone.
Now when I pressed the a key, we can see it's a bit higher.
And indeed, if I move up the full 12 semi tones of inactive, it's an octave higher than the original note.
But we played before.
Let's take our basic on off switch here and turn it into a piano like keyboard, right?
I'm going to leave this little bit of magic here for a bit of a mental exercise for you, but it's not that difficult to work out what's going on.
I have effectively mapped the keyboards keyboard keys to the piano keys in the way that zed here would be a s would be a sharp X would be B c would be C F would be C sharp V would be a d g would be d sharp.
Be would be e n would be f j would be J shop.
J would be J Chef for anyway, what I'm trying to get to is it It actually models out the white and black keys on a piano on.
We've got these crazy characters in here.
They're for the comma, Andre.
The full stop keys to keep it going on basically tests.
Each of these keys, one by one on Dhe creates the frequency to output.
If no keys oppressed it all, then our frequency output becomes zero.
So let's give that a whirl.
So I'm going to press the lower A right that past middle C Effectively see see Shop day D shot, eh?
And so we have a basic square wave instrument.
Now it sounds pretty cool, I said.
Let's just change that back to sign waves For the time being, um, in this case, we'll just said the output.
I just want to reduce the volume a little better.
So we get.
It'll get very loud.
00 it's a bit scratchy.
So we didn't hear that.
The tumbler of the instruments has changed.
It's It's not a square wave anymore.
But we get lots of little pops and clicks and scratches.
And if we hold down two keys, yeah, that's really bad.
So what's what's really happening here?
Let's quickly sketch open access and see what it means for our sine wave.
So yeah, so it's plus here.
We've got our amplitude on time on if we choose a different color for a sine wave As our sine wave starts and business, it becomes a sign away for a little bit, and then we switch it off.
Well, instead of carrying on, being a nice sine wave we've actually got is a vertical stop.
Well, if we remember the start of the video, the move up and down movement of the sine wave is reflected by the in N out movement off the speaker coat.
And we're asking the speaker cone it effectively in one time period, be in two places at once.
It can't do that.
So it has to violently react.
And that is what the click and the pop is that we're here.
Likewise, our function could be at any point in time.
So we might unfortunately start r sine wave down here and carry on on the same situation applies where is we should have had a nice sine wave radiant so the speaker can accommodate that and produce the frequency.
What we actually get is a very harsh cracking apart, and this is actually a very high frequency.
But because it's so high and so violent, the speaker cone can behave in unusual ways.
So you get different sounds now you might be asking, Why did we not hear that with our square wave?
Why did we not hear clicks and pops?
Well, that's because the square wave is, believe it or not, square it relies on being nothing but a collection of clicks and pops.
That's also why we have different volume issues with square wave, too.
We're almost finished now, but before we finish this part of the video, Siri's Let's Let's play with the sound one more time.
I'm going to make it sound like a cord to make a court.
We simply add sine waves, so I'm going to take dysfunction on at another.
But I'm going to change the frequency slowly.
I'm going to cheat, and for every base frequency that we get, I'm also into offset it by another 20 hurt on DDE.
I want to make sure that our amplitude is applied to everything.
Get what does that sound like?
Well, it's an instrument.
It's not the prettiest sound I ever heard, but I know that for me, putting together this video has been a very educational experience.
I've had to learn about sine waves.
I've had to learn about synthesis, and I hope to improve my virtual synthesis instrument further and we'll see that over there.
If you found this in any way useful, please leave a comment below on.