Placeholder Image

字幕列表 影片播放

  • Hello.

  • Welcome to part three of my coat yourself.

  • Some synthesizers.

  • Siri's the music you could hear playing in the background.

  • It's the marble machine I went to go synthesized by the sound synthesizer that many Not only is is a wonderful melody, but it highlights the three things we're gonna talk about.

  • This video first is looking at a frequency modulation, which is very important for giving a real texture to the sound.

  • This is ever so subtly changing frequency.

  • No, lost its play for the second part will be looking at voices and instruments.

  • Can we come up with a nice data structure that wraps up everything we've done so far?

  • So the oscillators on the envelopes to represent a particularly on finally, at long last will be looking at polyphony for Paul, if only depending on this is the ability to play multiple notes at the same time.

  • Let's get stuff.

  • I'm starting with the code that we used at the end of the last video, and if you remember, this code really just contains a simple oscillator on an envelope on.

  • All of the good stuff happens in this make noise function here.

  • Let's have a listen so far, Very nice so we can hear the envelope.

  • Then we can hear a sawtooth wave way.

  • Theo, we're going to be looking at frequency modulation.

  • First.

  • It can be quite complicated.

  • There is a significant amount of maths behind the theory of frequency modulation.

  • I'm not going to go into the full derivation of the formula.

  • It's not really the scope of this video, but we'll take one that's ready made, and I'll try and explain bits of it.

  • The purpose of frequency modulation, though, is to add a little bit of vibrato to the sound, and this can have a lot of depth and character and texture to the tones that we can hear.

  • Whereas I would usually talk through the theory and then write the code, I'm going to do it the other way around this time so we can listen to the effect first.

  • That might make explaining the maths a little simpler, so I'm going to make some modifications to oscillator function.

  • For now, I'm just going to hard code in the frequency modulation code.

  • The code here will take a low frequency.

  • One hurts wave to modulate the note that I'm playing and what we should hear is a siren like sound way.

  • Do.

  • And if I choose a different note, the overall pitch of the siren is a different frequency.

  • If I increase the frequency of our base signal here, you could say it's twice as quick now e.

  • Now it's less harsh.

  • That's because I've reduced the amplitude.

  • Sirens are typically considered an instrument, so let's try and make it sound a little nicer.

  • Effective frequency modulation is very subtle.

  • So I want the amplitude to be quite low and I'm going to change the frequency to about five.

  • Let's have a listen so you can definitely hear that fight.

  • Barato effect.

  • It's quite nice here.

  • I have to sign waves.

  • The blue one at the top will be unnoticed.

  • This is typically a high frequency.

  • You could say I can change the frequency on the slide ahead on DTH e sound wave At the bottom is our low frequency.

  • This is Ah in frequency modulation parlance.

  • The top one is called our carrier frequency on dth e bottom one is our message appear I've entered the formula for frequency modulation.

  • Let's enable it to see what the way form looks like and we can see when the two way forms are modulated.

  • We see a clustering off low frequencies, followed by high frequencies and low frequencies and high frequencies.

  • And so if I very gently changed the low frequency, we can see the clusters get tighter and tighter.

  • And if I change the higher frequency, which will be the note we can see, that's also changes the output wave form.

  • We can change the effect that the low frequency has on the fight high frequency by altering its amplitude on that, I call this a fudge factor, but this is actually quite a complex phenomenon in the frequency modulation equation.

  • So if I reduce the amplitude, we can see we've just left with the original note on.

  • As I increase this value, we see that the frequency modulation becomes more prominent and he could do interesting things with this.

  • In fact, if I turn it right up, we start getting very interesting way forms.

  • Indeed.

  • Now don't discount the straightaway.

  • They might actually sound fantastic.

  • Let's go back to our very first oscillator equation on what's considered the low frequency oscillator part first so we would have low frequency oscillators amplitude sign off the frequency that we want Times t.

  • Now, if you remember from our earlier videos, when you want to mix frequencies together, you add them.

  • So we also need the frequency of our note times t on.

  • We add them together, and that gives us our overall frequency, which then we can pass into another sign equation to give us output results.

  • Keen mathematicians out there may have spotted something a bit odd about left in the use of tea.

  • I don't want this to be a video about mathematics.

  • And if you're really interested, there are many resources online that talk about how frequency modulation is really a combination off triggered a metric identities on calculus.

  • Suffice to say, the equation will end with the end is a bit of a body approximation.

  • What is good enough for the purposes of this video?

  • I'm now going to modify our oscillator function so it always uses a low frequency oscillator.

  • So I've included here the frequency on DTH e amplitude, but I'm giving them default values in case we don't want to use it on.

  • I'm going to create a base frequency so we can use this frequency and the other types of oscillators.

  • This was our amplitude.

  • And so a sine wave simply becomes the sign.

  • The frequency now the only one that's tricky to modify.

  • Here is the digital approximation to a sore wave because it doesn't use D frequency, and it works in real time and doesn't use angular velocity.

  • That said, the translation from Hertz In real time too angular velocity is trivial.

  • I'll leave.

  • That is an exercise for you.

  • And I prefer the analog cell too late anyway.

  • So his original Slater function We'll just play it and make sure it still looks nice.

  • Very smooth sine waves.

  • But now we've got some additional arguments we can pass in s so the first thing is our frequency.

  • So let's set that to five hertz, and we'll set our amplitude to be quite small, maybe too small.

  • Let's try that.

  • Just for kicks.

  • Hope.

  • Let's see what the square wave sounds like.

  • I like that Now that we've got envelopes oscillators, low frequency oscillators and frequency modulation, we can have a crack it trying to create realistic sounding instruments.

  • I'm going to try and make a harmonica type sound like you heard at the start of this video in the audio track by Winter Gun.

  • I know a harmonica is a reed instrument, and it's a breathe the reed instrument.

  • So for Reed, you typically want square waves on for breathing sounds.

  • You want noise, Remember, for noise oscillators.

  • It doesn't matter what the frequency is going to be.

  • I was going to put zero de time passed that in on dth.

  • E type is oscillator of noise.

  • Let's have a listen.

  • Well, that doesn't sound anything like a harmonica.

  • Silly.

  • May.

  • There we go, going to add in just a load of noise and a DC offset intothe.

  • It's better.

  • I've added another note.

  • It's actually playing a triad of notes.

  • Now it does almost sound like a harmonica.

  • If we listen ever so carefully, just about here, the low frequency oscillator working there.

  • Let's just duplicate all of this for the moment on comment.

  • At this, it's so we can store this setting for later.

  • So we know that this is our harmonica, and now let's make a glockenspiel a bell type sound, So I'm going to.

  • Instead of using square ways I'm going to sign.

  • Waves were to keep the low frequency oscillator just the same on I'm going to use thesis and and third harmonics off the original frequency two on three.

  • We don't want any noise of the ballots.

  • Very crisp and clean instrument.

  • Let's have a listen.

  • Mmm.

  • We'll just change these square waves to sine waves.

  • Well, that doesn't sound anything like about.

  • You can see it's been hit, Miss this instrument creation.

  • The problem we have here is our envelope is completely unsuitable for that of a bell.

  • We want a very short attack time, and we want a definite decay.

  • Time on Belle's can't sustain.

  • So we have no sustained amplitude on their release over a fixed time.

  • Let's have a listen.

  • Oh, it's not quite high enough frequency yet testable all of these.

  • Oh, uh, it's a bit more about like, as you could see, it takes quite a bit of time to find an instrument, and I'm not very good at it.

  • So when I find one that actually sounds like an instrument, I want to recall those settings.

  • I think it's time we create a data structure that represents an instrument.

  • Were voice I'm going to create a base structure simply called instrument, an instrument is defined by two things.

  • First of all, it's overall volume level and secondly, the envelope by including a virtual function for the actual synthesis part off the instrument structure.

  • We can override this with based classes or based structures.

  • In this case, I will make that pill, and of course, it returns a double.

  • We can no encapsulate the whole definition instrument in a base class, which inherits from instrument.

  • So at the moment we're working with the bell.

  • Let's keep up L.

  • And the first thing the bell should do is define what its envelope looks like.

  • So we'll do some cutting paste and now will override the sound function for the actual synthesis on.

  • Let's couldn't paste the the output.

  • We'll just tidy this up a little bit.

  • And all this function needs to do is return the output at the time that has been given.

  • Now that we're working with instruments, we need to modify our program slightly.

  • So I'm creating a pointer here to the engine, which is the base class average mint, so it can point to, of course, anything that inherits from the instrument based class.

  • Let's change our make noise function.

  • All we need to do now is called the sound function Off.

  • The voice that we're using on the next change to make is to create the voice.

  • So we have our voice initially, it's no pointer, but we're going to turn this into the bell sound we've just defined.

  • And of course, we must also notify the voices envelope that we've started a note here on that We've released a note here when the key is pressed and released.

  • Have a listen.

  • Uh 00 no.

  • A proper harmonica as well.

  • So I've typed up now the harmonica.

  • And to use it all I need to do is declare the voice as being a harmonica.

  • Listen thing Very good.

  • Now that we've encapsulated instrument, the only thing left for us Synthesizer is prolific, playing more than one notes at the same time.

  • I play a note now.

  • Sounds fine, but if I play two notes at the same time, it completely falls a cart.

  • I think we've outgrown the code here now, so I'm going to refine everything we've done so far.

  • Try, make a bit more readable, bit more usable if you guys want to use this code by making it more modular, we should be able to get a lift me up and running right.

  • I've tidied up the code a little bit on.

  • The first thing I've done is change the basic type from double to F type.

  • It's still double for the most part, but it also allows us to use introduce another kinds of hard work on.

  • I've created a name, space, cold synth, and what you'll see in this name space is pretty much exactly what we've got already in our program, we got a W function for doing angular velocity.

  • This is a basic notes structure.

  • Instead of storing the frequency, I'm storing the idea of the key on the keyboard on I keep track of the times.

  • When it was switched on enough, I also stole something called the Channel Andi.

  • This is effectively the voice.

  • You see.

  • The oscillator hasn't changed at all, and I've included a function called Scale, which takes the note I D on translates it to a frequency, and this may look silly, but it's exactly the same as we had before.

  • I've refined the envelope structure a little bit it has exactly the same variables and operates in exactly the same way as before.

  • But there were a few glitches, for example, releasing the key whilst it was still in the sack face.

  • All of these books have benign doubt, but the principles are exactly the same as the 1st 2 videos.

  • It's just tidy a code.

  • The only thing that's changed now about our instruments structure is the sound function takes the note instead of the frequency on.

  • We use this scale to work out what the frequency should be.

  • As you can see, the envelope uses the note on Andi.

  • Note Off on.

  • We can pass back a Boolean here, when the amplitude goes below zero, will make a fairly crass assumption that that means the notice finished.

  • Of course, not all instruments will have finished, but we'll assume if it's making no sound, then it's not going to make any further South is our harmonica.

  • As before, I'll come back to the make noise function in a minute, but we'll see that the main is pretty much the same as it was in the 1st 2 videos.

  • I've got the get a stinky state to get the keys that are being pressed and that's it.

  • Let's have a listen.

  • Who?

  • Multiple notes being played at the same time.

  • So how do we handle polyphony?

  • There are two ways.

  • One is we could have an oscillator for every note on the keyboard that's constantly out putting something, even if it's zero.

  • Well, this is very, very inefficient to do.

  • We approached that I'm taking Is that any notes that is active?

  • It is that putting it sound has its own oscillator.

  • So we're going to store all of the notes that are currently being pressed in Vector.

  • I'll make noise functional, illiterate through this factor and generate the frequencies and mix them together when a notice finished being played.

  • It is not output anymore sound anymore, not necessarily when the key has been released, but when the synthesis output zero amplitude will remove that note from the vector.

  • So this here is my vector off notes, and I'm going to be using to implement.

  • I'm just going to stick with the harmonica for this one, so we'll stick to a single channel, and now we look at the make noise function.

  • Make noise is still the same as before.

  • All it does is amplitude and output, but we need to handle a vector inside it.

  • So I'm using some modern See here we're going to iterated through the vector of notes on.

  • We want to play the correct instrument, depending on what channel that note is using, and we'll mix the output.

  • Simply mix them by adding them together.

  • If the notice finished, then we want to set the notes activity flag to false.

  • This will signal that it should be removed later on.

  • In fact, it is removed from the vector.

  • Using this lovely bit of code here, which is a lambda function, you'll have noticed that the start of this function I'm using, um, you tex this is to protect the vector of notes because the sound machine, the background, the OLC noisemaker, that H file starts its own threat toe handle.

  • The sound synthesis on that third is not synchronized with the main thread, which handles the keyboard input.

  • So let's have a look at how we're handling the keys as before we use get a stinky state to determine which keys are being pressed.

  • I then used the find a function here on the vector I searched the vector of notes to see does a key that has been pressed already exists in our vector.

  • If no key has been found as in as in no note has been found that's attributed.

  • That key could also interpret that as being the key simply hasn't been pressed.

  • Then we want to add it to the vector.

  • So we create a new note.

  • So here's the key has been pressed.

  • State will create a new note.

  • So we sent the I d toe what the key input is.

  • We set the time that the note was started to.

  • Now we've chosen harmonica, which was Channel one, and we say the note is active and we had the note then to the vector.

  • If the notes already exists in the vector on, the key has been pressed.

  • It's just being held down so we don't need to do anything.

  • And finally, if the key has been released and the note exists in the vector, we don't want to remove the note from the vector because we now need to let it do its release phase.

  • So we set it's time off to now on.

  • We know that the make noise function will do the automatic removal from the vector later on.

  • That's all for politically tried to optimize.

  • The amount of computing results is attributed to generating the sound, and it's quite nice, because now I don't have to be as precise when impressing the keys allows for much more fluid play.

  • I think the coded yourself, since incisor is now in an almost finished, it's certainly usable by yourselves to generate all sorts of interesting sense.

  • The next video will be about sequencing the sand's ultimate on interfacing to things like the middIe Protocol, another instrument.

  • All of this Oscar.

  • This project is available to get to see the links below.

  • And also on the one hand, you've enjoyed this Cody video.

  • Please check out some of my coded all