Let's Build a Synth with Juce Part 5 - Creating ADSR Sliders

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey what's up everybody i'd like to welcome you to another juice tutorial and in this tutorial what we're going to do is we're actually going to start putting some sliders on our screen and control our adsr through the sliders for our synth so before we get started just want to remind you about our audio programmer community so we have now 5 000 members in our community developers of all different levels and we want you to join us if you're uh looking to get into audio programming or if you're already audio programming you can join us and help each other out and just connect with one another and you can join us on the audio programmer dot com forward slash community so let's go ahead and get started i just have my juice project open here and i'm going to just open this up in xcode now and as i was saying before what we have is if we go into our synth voice class you can see that we have this adsr that we created a couple tutorials ago and what we need to do is we actually want to start to control this with sliders so we have three main parts so we have the adsr that actually resides in our synth voice class we have our audio processor value tree state which is a list of all of our parameters and we have these four parameters attack decay sustain and release so this is located in the plug-in processor class so this is kind of our parent class for all of our data for our synthesizer and then in our editor we have the sliders that we created a few tutorials ago so we have attack uh decay sustained and release sliders so what we need to do is we need to actually get all of these kind of working together and connect all of these things up and that's what we're going to do in this tutorial so first thing that we want to do is we want to go to the synth voice class so we have this uh place where we're setting our attack decay sustain and release and prepare to play so this was just something we did last tutorial just to get something going and actually see that our adrs adsr was actually working but now we want those to be controlled by our sliders and by our audio processor value tree state so how are we going to do this so one thing that we could do is we could create a way that we could access all of these things and set and set these parameters right so what i'm going to do is i'm just going to go below prepare to play here and i'm going to create a method so let's call this so this is in our synth voice class make sure that you do that because that's the class that we're in and let's call this update adsr and then what we're going to do i'm just going to leave this blank for now and we'll uh just open our braces here just so we can actually move these things in and so i'm just going to take all of this the attack decay sustain and release and the set parameters i'm just going to cut this and i'm going to put that there in my update update adsr method i'm also just going to turn this set gain linear up just a bit so i will put this at 0.3 okay so just just so it raises the volume a little bit for us so now let's take a look at this right so we have this attack decay sustain and release parameter and we're at the moment we are just giving it some arbitrary values that we've just chosen kind of randomly and what we need to do just to walk you through what we need to do is we need to go back to our plug-in processor so i'll just open that up in another tab and we have our plug-in processor and in here we have our value trees where we have our attack decay sustain and release parameters so we need to somehow connect this to our synth voice so the way that i would do this is i would uh just actually create a method that i could call from plugin processor i always do this where i messed this up so i could call a method that would be in my process block and it would find out what the attack decay sustain and release parameters are at a particular moment and it would update those in my process block okay so that's what we're going to do so we're going to create a method that we're going to be able to call in our process block in our plugin processor so this will take a cost so i'm calling this cost because we're reading from the value we don't need to set the value of what's coming in so i'm going to say const float attack and we just need to do this for decay sustain and release so const float decay costs float release and now we just need to update the adsr with our what our new um values are going to be so we will say attack decay sustained oh i called this dk twice what's going on here sustain and release and then it sets the parameters so we should be fine there so now we just need to make sure we put this in our header file so i'll just copy this here move to the synth voice class this of course needs to be public because i need to be able to call this in my plug-in processor so i will just paste this here and now i have this update adsr great so now i can go to the plug-in processor and now i just need to call that method in this uh in in the process block right because when the attack decay or sustain or release parameter gets changed i want to change that as soon as possible and we can do that in our process block so in here i already put this uh this method where we go through our voices so this synth get them voices is referring to our synth voice class okay uh and at the moment we see that what we need to do is we need to just adjust this a little bit right so at the moment what we're doing is we're taking each voice that's in our synth and we're checking to see if it's a synthesizer voice which is the juice class right but we need what we really need to do is we need to check to see if it's a synth voice which is the class that we've created that inherits from synthesizer voice okay so for that reason what i need to do is i actually need to change this juice synthesizer voice to my own class which is a synth voice class right the reason that i need to do that is because i created a method in the synth voice class called update adsr and the update adsr method that i've created that's in a synth voice class right so that's not something that is a juice in the juice synthesizer voice class so that's the reason that i need to actually check and make sure that uh that what i'm trying to call update update adsr on is actually a synth voice pointer uh appointed to us in class okay so what i can say is if this if this is successful and if this voice is indeed a synth can be dynamically successfully dynamically cast into a synth voice class then what i could say is i could call voice and i should be able to call update adsr right so that's how i could do that so let's just go back for a second i'm just doing this for people who are getting started with c plus to show what uh what would happen if i didn't do that right so let's say that this is a juice synthesizer voice now watch what happens if i call voice and then i try to call update adsr you will see the method isn't there because it's because it's saying okay you're trying to cast to a synthesizer voice which is a juice class right there's no method in there called update adsr and for that that's the reason why it has to be the why it has to go to a my own class which is a synth voice class okay so yeah just a little bit of c plus there for you okay so next thing that we need to do is we need to so uh let me do some house cleaning here real quick before we move on so this thing where we're logging i'm just going to get rid of that so that was just something from our tutorial before also i'm going to go into the synth voice class i'm going to scroll down and i have this thing called where i was looking to see where the start sample was and just stopping the execution i'm just going to delete that as well okay so that was just something we were doing when we were debugging last tutorial so now okay so now what we need to do is we need to get all of this into here right so we need to figure out what the value of the attack parameter is in our value tray at one particular point in time so what i'm going to do is i'm going to get that value and if you've seen my previous tutorials on the audio processor value tree state you know that i could do something like this i could say auto attack equals and then we will go into our audio processor value tree state and then get raw parameter value and then we just need to get the then in there we can just put our id for the parameter that we want which would be attack decay sustain and release right so here i would just say attack okay and then then we will just do this for all of these other ones okay and there's there's another little problem here and i will show you that in a second after i type all this auto sustain get raw parameter value sustain release get raw parameter value okay so if we look at the get raw parameter value we will see that this returns a stood atomic float pointer okay so this is a pointer so what we need to do is we need to de-reference we need to find out what the value at that pointer is okay in that in that box okay and if you don't know what i mean check out the tutorials that i've done with my my son on teaching him c plus plus where we talk about how to uh how to do uh pointer basics okay so so that's why i need to do this i need to actually de-reference what this pointer is okay so that's so that should be fine now oh copy to implicitly deleted copy constructor so what this is saying is that it's making a copy of what this is and because of that i need to make this a reference to uh to this value that i'm trying to get so for that reason i need to put this ampersand so this is a reference to this and now what we need to do is now we can put these in okay i personally so so it'll it'll work fine if you just do this that's fine since this is atomic and atomics are a lot heavier than than just a regular float what i like to do is i like to have i like to do this load method just and this is just some for me or for somebody who's uh somebody who's reading through the code to just note that this is a that this is a atomic atomic float that i'm doing okay it's not just a regular uh it's not just the regular float that i'm getting there okay so that's why i'm putting that dot load that's just you could it'll work either way but i like to put it there just to let the reader know this is atomic this is a lot this is a lot um this takes a lot more power to update this so uh that's the reason that i'm doing that so now so so now what we've done is we've we have this update adsr this is calling into our uh update adsr method so all of this should be fine okay so we should be good to go i'm just going to change this wave from a sign to a saw so i will just uh i have these little notes down here by the way i have this on my github as well if you're looking for the code for this uh just check out github.com forward slash the audio programmer and you will be able to get that since this is a juice object i just need to put juice in front of this and so now that's fine so now what we've just done is we've we've attached the audio processor value tree state to our adsr which is sitting in our synth voice class so that's fine now what we need to do is we need to actually get our sliders to connect to our audio processor value tree state so here in our plugin editor we have this uh we already made the attachments right so we've sort of attached our audio processor value tree state to our slider and now what we need to do is we actually just need to put the sliders on the screen somehow okay so that's what we're going to do right now uh so what i will do is so let's just create uh let's let's make these slider styles so like let's give it a slider a linear vertical style so let's do that so i could say attack slider uh set slider style now you go through this which is juice slider slider style and then i will call this a linear vertical slider so there we go and then we need to add and make it visible so and if you've seen my previous tutorials on sliders you will see how why i'm doing all of this and also uh the default is where it takes the the box that shows the value and it sets it on the left i'm gonna i'm gonna put it below so i'm going to say attack slider set text box style and then we have juice slider text box below i'll make it read only so you can just you can just see what it is you can't actually change it and let's just give it these values of 50 and 25 so these are just some values i'm picking out a thin air so that's fine so normally you would say we're going to do the same thing for decay sustain and release slider okay so this is something that i've been doing lately just to make my my code look a lot cleaner is i will go here and i will actually create a method so let's do void tp so we're in our editor class and let's say set let's say set slider params and then in here i'm going to just i'm just going to take all of this and i'm going to just paste it in here and then i'm going to make this i'm going to make this function take a slight juice slider argument so juice slider make sure you make it a reference because we don't want to make a copy of the slider okay because it wouldn't actually affect the slider that we're trying to affect uh and so that for that reason we need to put the ampersand and it's a reference okay so and now what i need to do is i can just change this to slider i could change this to slider i could change this to slider and then what i need to do is i need to put it in my header because we got this out of line definition error so i'm just going to put it in my editor and i'll just put it here it's just a method that we've created called set slider params now what i could do is rather than having to type this for all of this four times i could just say set slider params and then here i can put attack slider set slider params k slider you know this just to me this just makes it much much easier to read than uh then when you have a million sliders that are all setting their slider styles textbox style if it's all the same they have this uh they have this little thing encoding called dry dry didn't uh don't repeat yourself so this is following the dry mantra of just write it once and then throw in your slider and it'll all it'll do the all of the heavy lifting for you there okay so that's why we're doing that so now we have that and now what we want to do is we want to go into resized and we want to actually put these on the screen so i've actually created some uh some arbitrary values here to do this so there are a bunch of ways that you could do this you could use set bounds relative you could do use a flex box there's the other one that's escaping my mind right now uh or you can just put them you can just put them statically on the screen wherever you want so that's what i'm gonna do here but i'm gonna do it in a way that i think is pretty easy to read so let's just create let's first create a couple variables here so i'm going to do this const auto and what i'm going to do is i'm going to create this box that's going to be bounds which is going to be essentially the the bounds of the the boundary of the um the whole plug-in but i'm going to shrink it a little bit so i could say bounds equals get local bounds and then what i'm going to do is i'm going to reduce that on all sides by 10. okay i'm just picking this value out of thin air so let's and then let's do uh we're going to do a padding variable so this will just be the distance between uh between our between our sliders as we go from left to right okay once again this is just something i've done through experimentation a lot of the ui setup stuff takes a lot of time and a lot of going back and forth so this is just much faster and then i'm going to create a slider width so i'll do slider width equals and what i want to do is i'm trying to i'm going to use get with because i want to get i want to get the width of this uh this this box that i'm in sorry it's going to be bounds dot get with because what i'm trying to do here is i'm trying to stay away from what they call magic numbers right because what happens is that if i if i'm using what's called magic numbers which is like a very specific number uh then if i've just changed one thing then i got to change i gotta if i change one thing with one of my sliders i've got to now change everything else so i'm trying to make this where if i need to change something in my in where my sliders are laid out i just go to one place and i can just change all of the sliders at once okay so for that reason we're going to do this get bounds or bounds dot get width divided by four i'm going to do this minus the padding okay because i'm going to account for the for the padding that uh that i've laid out that's going to space out how far the sliders are away from each other we're gonna do slider height and this will actually be the same okay and then we will do i like to do this i don't know if it's if it's something that other developers like to do but i like to do this thing like a start x which is if i'm laying something out from left to right then i'll say okay this is where i want my first slider to go it's going to go all the way on the left we're going to start at zero and then i'm going to do one for a start y so this will be start y slider start so i forgot my t here y equals and then what we're going to do is we're going to put this try to put this relatively in the middle of the screen so it'll be bells that get height divided by two minus and then we've got to pull it up a little bit from so right now we're in the middle of the screen and we're going to pull it up a bit where we say slider height divided by two okay so once again just just values that i've chosen through experimentation harmony okay so now we can set the balance so i'm going to do attack slider set bounds once again there are a million ways that you could do this you could do this with flexbox flexbox would probably be even more simple in this situation but here we are so i'm going to do slider start x so we're going to start at zero and then we got slider start y so all of our all of our sliders are going to start in the same y position and then in here i can put slider width and slider height okay and now since i'm going left to right all the slider widths and heights are going to be the same all the slider y's are going to be the same i can just take all of this and copy it and now what i could do is i could use this little handy method so you'll see what i mean here in a minute so we got set bounds and now what i could do is i could actually get the x coordinate of the attack slider this should be the case ladder sorry about that what i could do is i could get the right x coordinate of the attack slider so i could say attack slider get right see and it says returns the x-coordinate of the component's right-hand edge okay so i could do that and i'm just going to add the padding now okay so what i'm doing is i'm getting the right coordinate of the x of the attack slider i'm adding a little bit of padding and i'm saying okay that's where i want the dk slider to begin and then all of this the y the width and the height is all the same as what i had before okay now we are going to do sustain slider and what do you think we're going to do here right so we would want to get the right the right x coordinate of the decay slider right we want to get the right edge of the decay slider and then we want to add the padding once again so i could say decay slider get right plus padding once again all of this is the same and you can see that uh what'll happen is if i want to if i want to change if i if i need to change how large my sliders are i just need to change it one place i don't need to change it in three or four places anymore right so it makes it nice and extendable so we've got set bounds and then here once again we're getting the we're getting the right hand bounds the right x coordinate of the slider that's next to it we're adding a little bit of padding and then once again all of this is the same okay so yeah that seems once again if i need to change the padding if i need to change how far how far i want the box to be i can just change that using bounds and so on so that's why i'm setting up these little these little variables at the top here okay and now let's just go into our paint method let's just make this black right so we can say uh fill all and then here we can use juice colors and then black and now we should be good to go so we've connected the editor to the audio processor value tree state so we've connected all our sliders to the audio processor value tree state and we've connected those sliders to our adsr that's in our send voice and now we're opening up ableton and we're gonna try this out and see if this actually all works so here we are once again if you get confused just just try the uh try to get the um the code from the github repo sorry i lost my words for a second yeah get uh you can grab this code from my github repo github.com forward slash the audio programmer okay so i would probably make this a little bit bigger uh i mean that's something we could do down the line but this is fine for now uh the idea the idea here is that eventually we'll probably move this into its own class right so this adsr as a whole will probably be moved into its own class but we'll do that probably in the next tutorial so now we have this synth i'm going to try to play it might want to turn your headphones down just in case it's loud hopefully not okay cool so now we have we have our saw wave i'll turn it down a little bit and now uh let's see if the attack works so we hear that the attack works now we can try the release [Music] so that's cool we could try a little pluck sound here so let's try that so we can hear us a little bit it could probably be improved tweaked a little bit in the future so you hear that when i when i hold it that it kind of does the little pluck sound and then it kind of keeps going so that could probably be improved in the future but we'll do that we'll do some tweaks down the line this is just to give you a rough idea of how to do this and how to get this started so there you go it seems like it seems like all of that is working so just to review what we did there very quickly we uh we went and we created this update adsr method here where we could update our adsr within our synth voice then we went into our plug-in processor where we have the uh where we called that and we got our parameters from our audio processor value tree state and one one quick note here if you're uh if you're further ahead what you may notice is that or may observe is that hey you said that these uh these atomic float uh atomic floats they're quite heavy and they're quite quite resource intensive but we're actually updating that every process block right so every pro every time this process block calls which would be the sample rate divided by the buffer buffer size number of times in one second so that's quite a few times uh in one second every time you're calling that it would be doing all this getting getting the values and loading them that sounds pretty that sounds pretty uh resource intensive is there a way that we can only do this if we change a parameter right where there's something magical that says hey some this parameter has changed uh we uh now we want to call this and then otherwise it wouldn't call all of this and do all of this work and there is a way and we'll show you in one of the future tutorials so uh yeah so we so so then we update our adsr with our um with our values from our value tree and then in the editor we just went and we actually put the sliders on the screen and we did it using uh kind of static static positions at the moment maybe in the future we'll do it using flexbox or something else okay so uh i hope you enjoyed that tutorial if you found this helpful for you be sure to like and subscribe and we will see you next time
Info
Channel: The Audio Programmer
Views: 1,976
Rating: undefined out of 5
Keywords:
Id: PfaYCyVwB60
Channel Id: undefined
Length: 32min 6sec (1926 seconds)
Published: Sun Feb 07 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.